@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,169 @@
1
+ import { describe, it, expect, vi, afterEach, beforeEach } from "vitest";
2
+ import { render, screen, cleanup, fireEvent } from "@testing-library/react";
3
+ import React from "react";
4
+
5
+ const mockCallRPC = vi.fn();
6
+ const mockHandleSubscribe = vi.fn();
7
+ const mockHandleUnsubscribe = vi.fn();
8
+ const mockClearDebug = vi.fn();
9
+ const mockSetMethod = vi.fn();
10
+
11
+ vi.mock("../../../stores/use-app-store", () => ({
12
+ useAppStore: <T,>(selector: (s: Record<string, unknown>) => T) =>
13
+ selector({
14
+ method: "system.ping",
15
+ result: { pong: true },
16
+ tickEvents: ["tick-1", "tick-2"],
17
+ tickCount: 2,
18
+ subscriptionId: null,
19
+ timerRunning: false,
20
+ setMethod: mockSetMethod,
21
+ callRPC: mockCallRPC,
22
+ handleSubscribe: mockHandleSubscribe,
23
+ handleUnsubscribe: mockHandleUnsubscribe,
24
+ clearDebug: mockClearDebug,
25
+ }),
26
+ }));
27
+
28
+ vi.mock("../../../stores/use-log-store", () => ({
29
+ useLogStore: <T,>(selector: (s: Record<string, unknown>) => T) =>
30
+ selector({ logs: ["Connected", "Error: timeout"] }),
31
+ }));
32
+
33
+ vi.mock("react-i18next", () => ({
34
+ useTranslation: () => ({ t: (k: string) => k }),
35
+ }));
36
+
37
+ const localStorageStore: Record<string, string> = {};
38
+ vi.stubGlobal("localStorage", {
39
+ getItem: (key: string) => localStorageStore[key] ?? null,
40
+ setItem: (key: string, value: string) => {
41
+ localStorageStore[key] = String(value);
42
+ },
43
+ removeItem: (key: string) => {
44
+ delete localStorageStore[key];
45
+ },
46
+ clear: () => {
47
+ Object.keys(localStorageStore).forEach((k) => delete localStorageStore[k]);
48
+ },
49
+ get length() {
50
+ return Object.keys(localStorageStore).length;
51
+ },
52
+ key: (i: number) => Object.keys(localStorageStore)[i] ?? null,
53
+ });
54
+
55
+ describe("DebugPanel", () => {
56
+ beforeEach(() => {
57
+ localStorage.clear();
58
+ });
59
+
60
+ afterEach(() => {
61
+ cleanup();
62
+ vi.clearAllMocks();
63
+ });
64
+
65
+ it("should render debug panel title", async () => {
66
+ const { DebugPanel } = await import("../DebugPanel");
67
+ render(<DebugPanel />);
68
+ expect(screen.getByText("tabs.debug")).toBeDefined();
69
+ });
70
+
71
+ it("should render RPC calls section", async () => {
72
+ const { DebugPanel } = await import("../DebugPanel");
73
+ render(<DebugPanel />);
74
+ expect(screen.getByText("debug.rpcCalls")).toBeDefined();
75
+ });
76
+
77
+ it("should call clearDebug when clear button is clicked", async () => {
78
+ const { DebugPanel } = await import("../DebugPanel");
79
+ render(<DebugPanel />);
80
+ fireEvent.click(screen.getByText("debug.clear"));
81
+ expect(mockClearDebug).toHaveBeenCalledOnce();
82
+ });
83
+
84
+ it("should collapse panel when collapse button is clicked", async () => {
85
+ const { DebugPanel } = await import("../DebugPanel");
86
+ render(<DebugPanel />);
87
+ const collapseBtn = screen.getByTitle("debug.collapsePanel");
88
+ fireEvent.click(collapseBtn);
89
+ expect(screen.getByTitle("debug.expandPanel")).toBeDefined();
90
+ expect(screen.queryByText("debug.rpcCalls")).toBeNull();
91
+ });
92
+
93
+ it("should expand panel when expand button is clicked", async () => {
94
+ const { DebugPanel } = await import("../DebugPanel");
95
+ render(<DebugPanel />);
96
+ fireEvent.click(screen.getByTitle("debug.collapsePanel"));
97
+ expect(screen.getByTitle("debug.expandPanel")).toBeDefined();
98
+ fireEvent.click(screen.getByTitle("debug.expandPanel"));
99
+ expect(screen.getByTitle("debug.collapsePanel")).toBeDefined();
100
+ expect(screen.getByText("debug.rpcCalls")).toBeDefined();
101
+ });
102
+
103
+ it("should persist collapsed state in localStorage", async () => {
104
+ const { DebugPanel } = await import("../DebugPanel");
105
+ render(<DebugPanel />);
106
+ fireEvent.click(screen.getByTitle("debug.collapsePanel"));
107
+ expect(localStorage.getItem("debug-panel-collapsed")).toBe("true");
108
+ });
109
+
110
+ it("should restore collapsed state from localStorage", async () => {
111
+ localStorage.setItem("debug-panel-collapsed", "true");
112
+ vi.resetModules();
113
+ const { DebugPanel } = await import("../DebugPanel");
114
+ render(<DebugPanel />);
115
+ expect(screen.getByTitle("debug.expandPanel")).toBeDefined();
116
+ expect(screen.queryByText("debug.rpcCalls")).toBeNull();
117
+ });
118
+
119
+ it("should render subscriptions section", async () => {
120
+ const { DebugPanel } = await import("../DebugPanel");
121
+ render(<DebugPanel />);
122
+ expect(screen.getByText("debug.subscriptions")).toBeDefined();
123
+ });
124
+
125
+ it("should render logs section", async () => {
126
+ const { DebugPanel } = await import("../DebugPanel");
127
+ render(<DebugPanel />);
128
+ expect(screen.getByText("debug.logs")).toBeDefined();
129
+ });
130
+
131
+ it("should display method select", async () => {
132
+ const { DebugPanel } = await import("../DebugPanel");
133
+ render(<DebugPanel />);
134
+ expect(screen.getByText("system.ping")).toBeDefined();
135
+ });
136
+
137
+ it("should call callRPC on call button click", async () => {
138
+ const { DebugPanel } = await import("../DebugPanel");
139
+ render(<DebugPanel />);
140
+ fireEvent.click(screen.getByText("debug.call"));
141
+ expect(mockCallRPC).toHaveBeenCalledWith("");
142
+ });
143
+
144
+ it("should display result JSON", async () => {
145
+ const { DebugPanel } = await import("../DebugPanel");
146
+ render(<DebugPanel />);
147
+ expect(screen.getByText(/pong/)).toBeDefined();
148
+ });
149
+
150
+ it("should display log entries", async () => {
151
+ const { DebugPanel } = await import("../DebugPanel");
152
+ render(<DebugPanel />);
153
+ expect(screen.getByText("Connected")).toBeDefined();
154
+ expect(screen.getByText("Error: timeout")).toBeDefined();
155
+ });
156
+
157
+ it("should show subscribe button when not subscribed", async () => {
158
+ const { DebugPanel } = await import("../DebugPanel");
159
+ render(<DebugPanel />);
160
+ expect(screen.getByText("debug.subscribe")).toBeDefined();
161
+ });
162
+
163
+ it("should display tick events", async () => {
164
+ const { DebugPanel } = await import("../DebugPanel");
165
+ render(<DebugPanel />);
166
+ expect(screen.getByText("tick-1")).toBeDefined();
167
+ expect(screen.getByText("tick-2")).toBeDefined();
168
+ });
169
+ });
@@ -2,51 +2,51 @@ import { useEffect, useCallback } from "react";
2
2
  import { useTranslation } from "react-i18next";
3
3
 
4
4
  interface ConfirmDialogProps {
5
- title: string;
6
- message: string;
7
- onConfirm: () => void;
8
- onCancel: () => void;
5
+ title: string;
6
+ message: string;
7
+ onConfirm: () => void;
8
+ onCancel: () => void;
9
9
  }
10
10
 
11
11
  export function ConfirmDialog({ title, message, onConfirm, onCancel }: ConfirmDialogProps) {
12
- const { t } = useTranslation();
13
- const handleKeyDown = useCallback(
14
- (e: KeyboardEvent) => {
15
- if (e.key === "Escape") onCancel();
16
- },
17
- [onCancel],
18
- );
12
+ const { t } = useTranslation();
13
+ const handleKeyDown = useCallback(
14
+ (e: KeyboardEvent) => {
15
+ if (e.key === "Escape") onCancel();
16
+ },
17
+ [onCancel]
18
+ );
19
19
 
20
- useEffect(() => {
21
- document.addEventListener("keydown", handleKeyDown);
22
- return () => document.removeEventListener("keydown", handleKeyDown);
23
- }, [handleKeyDown]);
20
+ useEffect(() => {
21
+ document.addEventListener("keydown", handleKeyDown);
22
+ return () => document.removeEventListener("keydown", handleKeyDown);
23
+ }, [handleKeyDown]);
24
24
 
25
- return (
26
- <div
27
- className="fixed inset-0 z-50 flex items-center justify-center bg-black/50"
28
- onClick={(e) => {
29
- if (e.target === e.currentTarget) onCancel();
30
- }}
31
- >
32
- <div className="bg-[var(--color-bg-secondary)] border border-[var(--color-border-secondary)] rounded-lg shadow-2xl p-4 min-w-[300px] max-w-[400px]">
33
- <h3 className="text-sm font-semibold text-[var(--color-text-primary)] mb-2">{title}</h3>
34
- <p className="text-xs text-[var(--color-text-secondary)] mb-4">{message}</p>
35
- <div className="flex justify-end gap-2">
36
- <button
37
- className="px-3 py-1.5 text-xs bg-[var(--color-bg-tertiary)] hover:bg-[var(--color-bg-hover)] rounded transition-colors text-[var(--color-text-secondary)]"
38
- onClick={onCancel}
39
- >
40
- {t("common.cancel")}
41
- </button>
42
- <button
43
- className="px-3 py-1.5 text-xs bg-red-600 hover:bg-red-700 rounded transition-colors text-white"
44
- onClick={onConfirm}
45
- >
46
- {t("common.delete")}
47
- </button>
48
- </div>
49
- </div>
50
- </div>
51
- );
25
+ return (
26
+ <div
27
+ className="fixed inset-0 z-50 flex items-center justify-center bg-black/50"
28
+ onClick={(e) => {
29
+ if (e.target === e.currentTarget) onCancel();
30
+ }}
31
+ >
32
+ <div className="bg-[var(--color-bg-secondary)] border border-[var(--color-border-secondary)] rounded-lg shadow-2xl p-4 min-w-[300px] max-w-[400px]">
33
+ <h3 className="text-sm font-semibold text-[var(--color-text-primary)] mb-2">{title}</h3>
34
+ <p className="text-xs text-[var(--color-text-secondary)] mb-4">{message}</p>
35
+ <div className="flex justify-end gap-2">
36
+ <button
37
+ className="px-3 py-1.5 text-xs bg-[var(--color-bg-tertiary)] hover:bg-[var(--color-bg-hover)] rounded transition-colors text-[var(--color-text-secondary)]"
38
+ onClick={onCancel}
39
+ >
40
+ {t("common.cancel")}
41
+ </button>
42
+ <button
43
+ className="px-3 py-1.5 text-xs bg-[var(--color-text-error)] hover:opacity-80 rounded transition-colors text-white"
44
+ onClick={onConfirm}
45
+ >
46
+ {t("common.delete")}
47
+ </button>
48
+ </div>
49
+ </div>
50
+ </div>
51
+ );
52
52
  }
@@ -1,82 +1,87 @@
1
1
  import { useEffect, useRef, useCallback } from "react";
2
2
 
3
3
  export interface MenuItem {
4
- label: string;
5
- icon?: React.ReactNode;
6
- onClick: () => void;
7
- danger?: boolean;
8
- divider?: boolean;
4
+ label: string;
5
+ icon?: React.ReactNode;
6
+ onClick: () => void;
7
+ danger?: boolean;
8
+ divider?: boolean;
9
9
  }
10
10
 
11
11
  interface ContextMenuProps {
12
- x: number;
13
- y: number;
14
- items: MenuItem[];
15
- onClose: () => void;
12
+ x: number;
13
+ y: number;
14
+ items: MenuItem[];
15
+ onClose: () => void;
16
16
  }
17
17
 
18
18
  export function ContextMenu({ x, y, items, onClose }: ContextMenuProps) {
19
- const ref = useRef<HTMLDivElement>(null);
19
+ const ref = useRef<HTMLDivElement>(null);
20
20
 
21
- // Adjust position to stay within viewport
22
- const adjustedX = useRef(x);
23
- const adjustedY = useRef(y);
21
+ // Adjust position to stay within viewport
22
+ const adjustedX = useRef(x);
23
+ const adjustedY = useRef(y);
24
24
 
25
- useEffect(() => {
26
- const el = ref.current;
27
- if (!el) return;
28
- const rect = el.getBoundingClientRect();
29
- const vw = window.innerWidth;
30
- const vh = window.innerHeight;
31
- if (rect.right > vw) adjustedX.current = Math.max(0, x - rect.width);
32
- if (rect.bottom > vh) adjustedY.current = Math.max(0, y - rect.height);
33
- el.style.left = `${adjustedX.current}px`;
34
- el.style.top = `${adjustedY.current}px`;
35
- }, [x, y]);
25
+ useEffect(() => {
26
+ const el = ref.current;
27
+ if (!el) return;
28
+ const rect = el.getBoundingClientRect();
29
+ const vw = window.innerWidth;
30
+ const vh = window.innerHeight;
31
+ if (rect.right > vw) adjustedX.current = Math.max(0, x - rect.width);
32
+ if (rect.bottom > vh) adjustedY.current = Math.max(0, y - rect.height);
33
+ el.style.left = `${adjustedX.current}px`;
34
+ el.style.top = `${adjustedY.current}px`;
35
+ }, [x, y]);
36
36
 
37
- const handleClickOutside = useCallback((e: MouseEvent) => {
38
- if (ref.current && !ref.current.contains(e.target as Node)) {
39
- onClose();
40
- }
41
- }, [onClose]);
37
+ const handleClickOutside = useCallback(
38
+ (e: MouseEvent) => {
39
+ if (ref.current && !ref.current.contains(e.target as Node)) {
40
+ onClose();
41
+ }
42
+ },
43
+ [onClose]
44
+ );
42
45
 
43
- useEffect(() => {
44
- document.addEventListener("mousedown", handleClickOutside);
45
- const handleKeyDown = (e: KeyboardEvent) => {
46
- if (e.key === "Escape") onClose();
47
- };
48
- document.addEventListener("keydown", handleKeyDown);
49
- return () => {
50
- document.removeEventListener("mousedown", handleClickOutside);
51
- document.removeEventListener("keydown", handleKeyDown);
52
- };
53
- }, [handleClickOutside, onClose]);
46
+ useEffect(() => {
47
+ document.addEventListener("mousedown", handleClickOutside);
48
+ const handleKeyDown = (e: KeyboardEvent) => {
49
+ if (e.key === "Escape") onClose();
50
+ };
51
+ document.addEventListener("keydown", handleKeyDown);
52
+ return () => {
53
+ document.removeEventListener("mousedown", handleClickOutside);
54
+ document.removeEventListener("keydown", handleKeyDown);
55
+ };
56
+ }, [handleClickOutside, onClose]);
54
57
 
55
- return (
56
- <div
57
- ref={ref}
58
- className="fixed z-50 min-w-[160px] bg-[var(--color-bg-secondary)] border border-[var(--color-border-secondary)] rounded-md shadow-xl py-1"
59
- style={{ left: adjustedX.current, top: adjustedY.current }}
60
- >
61
- {items.map((item, i) => (
62
- <div key={i}>
63
- {item.divider && i > 0 && <div className="border-t border-[var(--color-border-secondary)] my-1" />}
64
- <button
65
- className={`w-full text-left px-3 py-1.5 text-xs flex items-center gap-2 transition-colors ${
66
- item.danger
67
- ? "text-red-400 hover:bg-red-900/30"
68
- : "text-[var(--color-text-secondary)] hover:bg-[var(--color-bg-hover)]"
69
- }`}
70
- onClick={() => {
71
- item.onClick();
72
- onClose();
73
- }}
74
- >
75
- {item.icon && <span className="w-3.5 shrink-0">{item.icon}</span>}
76
- {item.label}
77
- </button>
78
- </div>
79
- ))}
80
- </div>
81
- );
58
+ return (
59
+ <div
60
+ ref={ref}
61
+ className="fixed z-50 min-w-[160px] bg-[var(--color-bg-secondary)] border border-[var(--color-border-secondary)] rounded-md shadow-xl py-1"
62
+ style={{ left: adjustedX.current, top: adjustedY.current }}
63
+ >
64
+ {items.map((item, i) => (
65
+ <div key={i}>
66
+ {item.divider && i > 0 && (
67
+ <div className="border-t border-[var(--color-border-secondary)] my-1" />
68
+ )}
69
+ <button
70
+ className={`w-full text-left px-3 py-1.5 text-xs flex items-center gap-2 transition-colors ${
71
+ item.danger
72
+ ? "text-[var(--color-text-error)] hover:bg-[var(--color-text-error)]/20"
73
+ : "text-[var(--color-text-secondary)] hover:bg-[var(--color-bg-hover)]"
74
+ }`}
75
+ onClick={() => {
76
+ item.onClick();
77
+ onClose();
78
+ }}
79
+ >
80
+ {item.icon && <span className="w-3.5 shrink-0">{item.icon}</span>}
81
+ {item.label}
82
+ </button>
83
+ </div>
84
+ ))}
85
+ </div>
86
+ );
82
87
  }
@@ -18,7 +18,7 @@ const FILTER_PRESETS: Record<SubEventType, string[]> = {
18
18
  const CATEGORY_COLORS: Record<FeedCategory, string> = {
19
19
  tech: "bg-blue-600/30 text-blue-300",
20
20
  news: "bg-amber-600/30 text-amber-300",
21
- general: "bg-green-600/30 text-green-300",
21
+ general: "bg-[var(--color-text-success)]/30 text-[var(--color-text-success)]",
22
22
  };
23
23
 
24
24
  export function FeedPanel() {
@@ -103,6 +103,7 @@ export function FeedPanel() {
103
103
  className="w-24 px-2 py-1.5 text-xs bg-[var(--color-bg-tertiary)] rounded text-[var(--color-text-primary)] border border-[var(--color-border-secondary)] focus:border-[var(--color-accent)] focus:outline-none"
104
104
  />
105
105
  <select
106
+ aria-label={t("feed.newPost")}
106
107
  value={category}
107
108
  onChange={(e) => setCategory(e.target.value as FeedCategory)}
108
109
  className="px-2 py-1.5 text-xs bg-[var(--color-bg-tertiary)] rounded text-[var(--color-text-primary)] border border-[var(--color-border-secondary)]"
@@ -141,6 +142,7 @@ export function FeedPanel() {
141
142
  </div>
142
143
  <div className="flex gap-2 items-center">
143
144
  <select
145
+ aria-label={t("feed.eventStream")}
144
146
  value={activeEventType}
145
147
  onChange={(e) => {
146
148
  setActiveEventType(e.target.value as SubEventType);
@@ -164,14 +166,14 @@ export function FeedPanel() {
164
166
  {!subscribed ? (
165
167
  <button
166
168
  onClick={handleSubscribe}
167
- className="px-3 py-1.5 text-xs bg-green-600 hover:bg-green-700 rounded transition-colors whitespace-nowrap"
169
+ className="px-3 py-1.5 text-xs bg-[var(--color-text-success)] hover:opacity-80 rounded transition-colors whitespace-nowrap"
168
170
  >
169
171
  {t("feed.subscribe")}
170
172
  </button>
171
173
  ) : (
172
174
  <button
173
175
  onClick={handleUnsubscribe}
174
- className="px-3 py-1.5 text-xs bg-red-600 hover:bg-red-700 rounded transition-colors whitespace-nowrap"
176
+ className="px-3 py-1.5 text-xs bg-[var(--color-text-error)] hover:opacity-80 rounded transition-colors whitespace-nowrap"
175
177
  >
176
178
  {t("feed.unsubscribe")}
177
179
  </button>
@@ -203,7 +205,7 @@ export function FeedPanel() {
203
205
  {t("feed.eventStream")}
204
206
  </div>
205
207
  {subscribed && (
206
- <span className="px-1.5 py-0.5 bg-green-600/30 text-green-400 rounded text-[10px] animate-pulse">
208
+ <span className="px-1.5 py-0.5 bg-[var(--color-text-success)]/30 text-[var(--color-text-success)] rounded text-[10px] animate-pulse">
207
209
  {t("feed.live")}
208
210
  </span>
209
211
  )}
@@ -225,7 +227,7 @@ export function FeedPanel() {
225
227
  {new Date(entry.timestamp).toLocaleTimeString()}
226
228
  </span>
227
229
  </div>
228
- <pre className="text-cyan-300 mt-0.5 whitespace-pre-wrap break-all">
230
+ <pre className="text-[var(--color-text-info)] mt-0.5 whitespace-pre-wrap break-all">
229
231
  {JSON.stringify(entry.payload, null, 0)}
230
232
  </pre>
231
233
  </div>
@@ -4,52 +4,71 @@ import { formatSize } from "../../utils/file-utils";
4
4
  import { VirtualizedCodeView } from "./VirtualizedCodeView";
5
5
 
6
6
  interface FilePreviewOverlayProps {
7
- preview: FilePreview;
8
- loading: boolean;
9
- onClose: () => void;
7
+ preview: FilePreview;
8
+ loading: boolean;
9
+ onClose: () => void;
10
+ scrollToLine?: number;
11
+ onScrolledToLine?: () => void;
10
12
  }
11
13
 
12
- export function FilePreviewOverlay({ preview, loading, onClose }: FilePreviewOverlayProps) {
13
- return (
14
- <div className="absolute inset-0 z-10 bg-[var(--color-bg-primary)]/95 flex flex-col overflow-hidden">
15
- <div className="flex items-center justify-between px-4 py-2 bg-[var(--color-bg-secondary)] border-b border-[var(--color-border-primary)] flex-shrink-0">
16
- <div className="flex items-center gap-2">
17
- <FileText className="w-4 h-4 text-[var(--color-text-tertiary)]" />
18
- <span className="text-sm font-medium text-[var(--color-text-secondary)]">{preview.name}</span>
19
- {preview.size > 0 && (
20
- <span className="text-xs text-[var(--color-text-placeholder)]">{formatSize(preview.size)}</span>
21
- )}
22
- {preview.totalLines != null && (
23
- <span className="text-xs text-[var(--color-text-placeholder)]">{preview.totalLines} lines</span>
24
- )}
25
- </div>
26
- <button
27
- onClick={onClose}
28
- className="text-[var(--color-text-tertiary)] hover:text-[var(--color-text-primary)] p-1 rounded hover:bg-[var(--color-bg-hover)] transition-colors"
29
- >
30
- <X className="w-4 h-4" />
31
- </button>
32
- </div>
14
+ export function FilePreviewOverlay({
15
+ preview,
16
+ loading,
17
+ onClose,
18
+ scrollToLine,
19
+ onScrolledToLine,
20
+ }: FilePreviewOverlayProps) {
21
+ return (
22
+ <div className="absolute inset-0 z-10 bg-[var(--color-bg-primary)]/95 flex flex-col overflow-hidden">
23
+ <div className="flex items-center justify-between px-4 py-2 bg-[var(--color-bg-secondary)] border-b border-[var(--color-border-primary)] flex-shrink-0">
24
+ <div className="flex items-center gap-2">
25
+ <FileText className="w-4 h-4 text-[var(--color-text-tertiary)]" />
26
+ <span className="text-sm font-medium text-[var(--color-text-secondary)]">
27
+ {preview.name}
28
+ </span>
29
+ {preview.size > 0 && (
30
+ <span className="text-xs text-[var(--color-text-placeholder)]">
31
+ {formatSize(preview.size)}
32
+ </span>
33
+ )}
34
+ {preview.totalLines != null && (
35
+ <span className="text-xs text-[var(--color-text-placeholder)]">
36
+ {preview.totalLines} lines
37
+ </span>
38
+ )}
39
+ </div>
40
+ <button
41
+ onClick={onClose}
42
+ className="text-[var(--color-text-tertiary)] hover:text-[var(--color-text-primary)] p-1 rounded hover:bg-[var(--color-bg-hover)] transition-colors"
43
+ >
44
+ <X className="w-4 h-4" />
45
+ </button>
46
+ </div>
33
47
 
34
- {/* File content — flex-col so VirtualizedCodeView's flex-1 works */}
35
- <div className="flex-1 min-h-0 flex flex-col">
36
- {loading ? (
37
- <div className="flex items-center justify-center h-full text-[var(--color-text-tertiary)] text-sm">
38
- <div className="w-5 h-5 border-2 border-[var(--color-text-accent)] border-t-transparent rounded-full animate-spin mr-2" />
39
- Loading...
40
- </div>
41
- ) : preview.isImage && preview.imageUrl ? (
42
- <div className="flex items-center justify-center h-full p-4 bg-[#1a1a2e]">
43
- <img
44
- src={preview.imageUrl}
45
- alt={preview.name}
46
- className="max-w-full max-h-full object-contain rounded"
47
- />
48
- </div>
49
- ) : preview.content ? (
50
- <VirtualizedCodeView code={preview.content} filename={preview.name} />
51
- ) : null}
52
- </div>
53
- </div>
54
- );
48
+ {/* File content — flex-col so VirtualizedCodeView's flex-1 works */}
49
+ <div className="flex-1 min-h-0 flex flex-col">
50
+ {loading ? (
51
+ <div className="flex items-center justify-center h-full text-[var(--color-text-tertiary)] text-sm">
52
+ <div className="w-5 h-5 border-2 border-[var(--color-text-accent)] border-t-transparent rounded-full animate-spin mr-2" />
53
+ Loading...
54
+ </div>
55
+ ) : preview.isImage && preview.imageUrl ? (
56
+ <div className="flex items-center justify-center h-full p-4 bg-[#1a1a2e]">
57
+ <img
58
+ src={preview.imageUrl}
59
+ alt={preview.name}
60
+ className="max-w-full max-h-full object-contain rounded"
61
+ />
62
+ </div>
63
+ ) : preview.content ? (
64
+ <VirtualizedCodeView
65
+ code={preview.content}
66
+ filename={preview.name}
67
+ scrollToLine={scrollToLine}
68
+ onScrolledToLine={onScrolledToLine}
69
+ />
70
+ ) : null}
71
+ </div>
72
+ </div>
73
+ );
55
74
  }