@winspan/claude-forge 8.41.0 → 8.51.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (923) hide show
  1. package/.claude/CLAUDE.md +17 -0
  2. package/.eslintrc.js +23 -0
  3. package/.prettierrc +8 -0
  4. package/ARCHITECTURE_ISSUES.md +249 -0
  5. package/CLAUDE.md +265 -0
  6. package/CLAUDE.md.backup +488 -0
  7. package/DEVELOPMENT.md +310 -0
  8. package/dist/claudemd/claudemd-generator.d.ts +38 -3
  9. package/dist/claudemd/claudemd-generator.d.ts.map +1 -1
  10. package/dist/claudemd/claudemd-generator.js +420 -12
  11. package/dist/claudemd/claudemd-generator.js.map +1 -1
  12. package/dist/claudemd/index.d.ts +2 -2
  13. package/dist/claudemd/index.d.ts.map +1 -1
  14. package/dist/claudemd/index.js.map +1 -1
  15. package/dist/claudemd/resume-manager.d.ts.map +1 -1
  16. package/dist/claudemd/resume-manager.js +6 -3
  17. package/dist/claudemd/resume-manager.js.map +1 -1
  18. package/dist/claudemd/tech-detector.d.ts +1 -0
  19. package/dist/claudemd/tech-detector.d.ts.map +1 -1
  20. package/dist/claudemd/tech-detector.js +53 -0
  21. package/dist/claudemd/tech-detector.js.map +1 -1
  22. package/dist/claudemd/templates/swarm-protocol.md +222 -0
  23. package/dist/cli/commands/claudemd.js +2 -2
  24. package/dist/cli/commands/claudemd.js.map +1 -1
  25. package/dist/cli/commands/daemon.d.ts +28 -0
  26. package/dist/cli/commands/daemon.d.ts.map +1 -1
  27. package/dist/cli/commands/daemon.js +204 -12
  28. package/dist/cli/commands/daemon.js.map +1 -1
  29. package/dist/cli/commands/executions.d.ts.map +1 -1
  30. package/dist/cli/commands/executions.js +4 -3
  31. package/dist/cli/commands/executions.js.map +1 -1
  32. package/dist/cli/commands/init.d.ts.map +1 -1
  33. package/dist/cli/commands/init.js +5 -37
  34. package/dist/cli/commands/init.js.map +1 -1
  35. package/dist/cli/commands/logs.js.map +1 -1
  36. package/dist/cli/commands/mcp.d.ts.map +1 -1
  37. package/dist/cli/commands/mcp.js +3 -5
  38. package/dist/cli/commands/mcp.js.map +1 -1
  39. package/dist/cli/commands/menu.d.ts.map +1 -1
  40. package/dist/cli/commands/menu.js +14 -13
  41. package/dist/cli/commands/menu.js.map +1 -1
  42. package/dist/cli/commands/skills.d.ts.map +1 -1
  43. package/dist/cli/commands/skills.js +8 -2
  44. package/dist/cli/commands/skills.js.map +1 -1
  45. package/dist/cli/commands/stats.d.ts.map +1 -1
  46. package/dist/cli/commands/stats.js +2 -20
  47. package/dist/cli/commands/stats.js.map +1 -1
  48. package/dist/cli/commands/status.js +2 -2
  49. package/dist/cli/commands/status.js.map +1 -1
  50. package/dist/cli/commands/trace.d.ts +9 -0
  51. package/dist/cli/commands/trace.d.ts.map +1 -0
  52. package/dist/cli/commands/trace.js +125 -0
  53. package/dist/cli/commands/trace.js.map +1 -0
  54. package/dist/cli/index.js +2 -4
  55. package/dist/cli/index.js.map +1 -1
  56. package/dist/cli/init/hook-manager.d.ts.map +1 -1
  57. package/dist/cli/init/hook-manager.js +2 -2
  58. package/dist/cli/init/hook-manager.js.map +1 -1
  59. package/dist/core/ai/provider.d.ts +10 -2
  60. package/dist/core/ai/provider.d.ts.map +1 -1
  61. package/dist/core/ai/provider.js +2 -2
  62. package/dist/core/ai/provider.js.map +1 -1
  63. package/dist/core/ai/types.d.ts +1 -19
  64. package/dist/core/ai/types.d.ts.map +1 -1
  65. package/dist/core/ai/types.js +1 -1
  66. package/dist/core/config.d.ts +2 -1
  67. package/dist/core/config.d.ts.map +1 -1
  68. package/dist/core/config.js +23 -6
  69. package/dist/core/config.js.map +1 -1
  70. package/dist/core/constants.d.ts +14 -3
  71. package/dist/core/constants.d.ts.map +1 -1
  72. package/dist/core/constants.js +17 -3
  73. package/dist/core/constants.js.map +1 -1
  74. package/dist/core/event-fields.d.ts +16 -0
  75. package/dist/core/event-fields.d.ts.map +1 -0
  76. package/dist/core/event-fields.js +19 -0
  77. package/dist/core/event-fields.js.map +1 -0
  78. package/dist/core/queue/index.d.ts +52 -0
  79. package/dist/core/queue/index.d.ts.map +1 -0
  80. package/dist/core/queue/index.js +175 -0
  81. package/dist/core/queue/index.js.map +1 -0
  82. package/dist/core/storage/base.d.ts +66 -0
  83. package/dist/core/storage/base.d.ts.map +1 -0
  84. package/dist/core/storage/base.js +254 -0
  85. package/dist/core/storage/base.js.map +1 -0
  86. package/dist/core/storage/events.d.ts +141 -0
  87. package/dist/core/storage/events.d.ts.map +1 -0
  88. package/dist/core/storage/events.js +348 -0
  89. package/dist/core/storage/events.js.map +1 -0
  90. package/dist/core/storage/injections.d.ts +27 -0
  91. package/dist/core/storage/injections.d.ts.map +1 -0
  92. package/dist/core/storage/injections.js +51 -0
  93. package/dist/core/storage/injections.js.map +1 -0
  94. package/dist/core/storage/maintenance.d.ts +21 -0
  95. package/dist/core/storage/maintenance.d.ts.map +1 -0
  96. package/dist/core/storage/maintenance.js +52 -0
  97. package/dist/core/storage/maintenance.js.map +1 -0
  98. package/dist/core/storage/routing.d.ts +124 -0
  99. package/dist/core/storage/routing.d.ts.map +1 -0
  100. package/dist/core/storage/routing.js +239 -0
  101. package/dist/core/storage/routing.js.map +1 -0
  102. package/dist/core/storage/rows.d.ts +0 -47
  103. package/dist/core/storage/rows.d.ts.map +1 -1
  104. package/dist/core/storage/schema.sql +85 -137
  105. package/dist/core/storage/sessions.d.ts +54 -0
  106. package/dist/core/storage/sessions.d.ts.map +1 -0
  107. package/dist/core/storage/sessions.js +137 -0
  108. package/dist/core/storage/sessions.js.map +1 -0
  109. package/dist/core/storage/skills.d.ts +63 -0
  110. package/dist/core/storage/skills.d.ts.map +1 -0
  111. package/dist/core/storage/skills.js +154 -0
  112. package/dist/core/storage/skills.js.map +1 -0
  113. package/dist/core/storage/sqlite.d.ts +97 -266
  114. package/dist/core/storage/sqlite.d.ts.map +1 -1
  115. package/dist/core/storage/sqlite.js +196 -764
  116. package/dist/core/storage/sqlite.js.map +1 -1
  117. package/dist/core/storage/tasks.d.ts +113 -0
  118. package/dist/core/storage/tasks.d.ts.map +1 -0
  119. package/dist/core/storage/tasks.js +276 -0
  120. package/dist/core/storage/tasks.js.map +1 -0
  121. package/dist/core/storage/token-usage.d.ts +36 -0
  122. package/dist/core/storage/token-usage.d.ts.map +1 -0
  123. package/dist/core/storage/token-usage.js +59 -0
  124. package/dist/core/storage/token-usage.js.map +1 -0
  125. package/dist/core/types.d.ts +83 -6
  126. package/dist/core/types.d.ts.map +1 -1
  127. package/dist/core/types.js +24 -1
  128. package/dist/core/types.js.map +1 -1
  129. package/dist/core/utils/error-handler.d.ts.map +1 -1
  130. package/dist/core/utils/error-handler.js +3 -2
  131. package/dist/core/utils/error-handler.js.map +1 -1
  132. package/dist/core/utils/format.d.ts +28 -0
  133. package/dist/core/utils/format.d.ts.map +1 -0
  134. package/dist/core/utils/format.js +68 -0
  135. package/dist/core/utils/format.js.map +1 -0
  136. package/dist/core/utils/git.d.ts +10 -0
  137. package/dist/core/utils/git.d.ts.map +1 -0
  138. package/dist/core/utils/git.js +24 -0
  139. package/dist/core/utils/git.js.map +1 -0
  140. package/dist/core/utils/logger.d.ts +6 -1
  141. package/dist/core/utils/logger.d.ts.map +1 -1
  142. package/dist/core/utils/logger.js +87 -3
  143. package/dist/core/utils/logger.js.map +1 -1
  144. package/dist/core/utils/lru-cache.d.ts +1 -0
  145. package/dist/core/utils/lru-cache.d.ts.map +1 -1
  146. package/dist/core/utils/lru-cache.js +3 -0
  147. package/dist/core/utils/lru-cache.js.map +1 -1
  148. package/dist/core/utils/session.d.ts +16 -0
  149. package/dist/core/utils/session.d.ts.map +1 -0
  150. package/dist/core/utils/session.js +25 -0
  151. package/dist/core/utils/session.js.map +1 -0
  152. package/dist/core/utils/time.d.ts +22 -0
  153. package/dist/core/utils/time.d.ts.map +1 -0
  154. package/dist/core/utils/time.js +38 -0
  155. package/dist/core/utils/time.js.map +1 -0
  156. package/dist/core/utils/token-tracker.js +1 -1
  157. package/dist/core/utils/token-tracker.js.map +1 -1
  158. package/dist/daemon/event-parser.d.ts.map +1 -1
  159. package/dist/daemon/event-parser.js +2 -1
  160. package/dist/daemon/event-parser.js.map +1 -1
  161. package/dist/daemon/handlers/history-exporter.d.ts.map +1 -1
  162. package/dist/daemon/handlers/history-exporter.js +6 -4
  163. package/dist/daemon/handlers/history-exporter.js.map +1 -1
  164. package/dist/daemon/handlers/post-tool-use.d.ts +5 -12
  165. package/dist/daemon/handlers/post-tool-use.d.ts.map +1 -1
  166. package/dist/daemon/handlers/post-tool-use.js +25 -79
  167. package/dist/daemon/handlers/post-tool-use.js.map +1 -1
  168. package/dist/daemon/handlers/stop.d.ts +28 -12
  169. package/dist/daemon/handlers/stop.d.ts.map +1 -1
  170. package/dist/daemon/handlers/stop.js +129 -42
  171. package/dist/daemon/handlers/stop.js.map +1 -1
  172. package/dist/daemon/handlers/user-prompt.d.ts +18 -19
  173. package/dist/daemon/handlers/user-prompt.d.ts.map +1 -1
  174. package/dist/daemon/handlers/user-prompt.js +93 -227
  175. package/dist/daemon/handlers/user-prompt.js.map +1 -1
  176. package/dist/daemon/index.d.ts +6 -2
  177. package/dist/daemon/index.d.ts.map +1 -1
  178. package/dist/daemon/index.js +97 -127
  179. package/dist/daemon/index.js.map +1 -1
  180. package/dist/daemon/launchd/com.claude-forge.daemon.plist.template +47 -0
  181. package/dist/daemon/launchd-installer.d.ts +61 -0
  182. package/dist/daemon/launchd-installer.d.ts.map +1 -0
  183. package/dist/daemon/launchd-installer.js +182 -0
  184. package/dist/daemon/launchd-installer.js.map +1 -0
  185. package/dist/daemon/lifecycle.d.ts +11 -0
  186. package/dist/daemon/lifecycle.d.ts.map +1 -1
  187. package/dist/daemon/lifecycle.js +47 -4
  188. package/dist/daemon/lifecycle.js.map +1 -1
  189. package/dist/daemon/router.d.ts +9 -2
  190. package/dist/daemon/router.d.ts.map +1 -1
  191. package/dist/daemon/router.js +27 -3
  192. package/dist/daemon/router.js.map +1 -1
  193. package/dist/daemon/server.d.ts +6 -4
  194. package/dist/daemon/server.d.ts.map +1 -1
  195. package/dist/daemon/server.js +80 -88
  196. package/dist/daemon/server.js.map +1 -1
  197. package/dist/{intelligence → daemon/services}/task-segmenter.d.ts +7 -1
  198. package/dist/daemon/services/task-segmenter.d.ts.map +1 -0
  199. package/dist/{intelligence → daemon/services}/task-segmenter.js +30 -7
  200. package/dist/daemon/services/task-segmenter.js.map +1 -0
  201. package/dist/hooks/hook-lib.sh +118 -0
  202. package/dist/hooks/notification.sh +9 -5
  203. package/dist/hooks/post-tool-use.sh +10 -6
  204. package/dist/hooks/pre-tool-use.sh +9 -6
  205. package/dist/hooks/stop.sh +10 -7
  206. package/dist/hooks/user-prompt-submit.sh +10 -11
  207. package/dist/mcp/server.d.ts +2 -2
  208. package/dist/mcp/server.d.ts.map +1 -1
  209. package/dist/mcp/server.js +71 -11
  210. package/dist/mcp/server.js.map +1 -1
  211. package/dist/skills/invocation-guard.d.ts +20 -0
  212. package/dist/skills/invocation-guard.d.ts.map +1 -1
  213. package/dist/skills/invocation-guard.js +63 -0
  214. package/dist/skills/invocation-guard.js.map +1 -1
  215. package/dist/skills/matcher.d.ts.map +1 -1
  216. package/dist/skills/matcher.js +12 -3
  217. package/dist/skills/matcher.js.map +1 -1
  218. package/dist/skills/official/code-simplifier.md +16 -0
  219. package/dist/skills/official/find-skills.md +23 -0
  220. package/dist/skills/official/official-api-design.md +17 -0
  221. package/dist/skills/official/official-architecture-decision.md +20 -0
  222. package/dist/skills/official/official-bmad.md +118 -0
  223. package/dist/skills/official/official-db-schema-design.md +16 -0
  224. package/dist/skills/official/official-debug.md +17 -0
  225. package/dist/skills/official/official-doc-driven.md +31 -0
  226. package/dist/skills/official/official-harness-engineering.md +108 -0
  227. package/dist/skills/official/official-performance-optimization.md +30 -0
  228. package/dist/skills/official/official-pr-review.md +35 -0
  229. package/dist/skills/official/official-release-checklist.md +30 -0
  230. package/dist/skills/official/official-security-hardening.md +26 -0
  231. package/dist/skills/official/official-spec-driven-design.md +31 -0
  232. package/dist/skills/official/planning-with-files.md +37 -0
  233. package/dist/skills/official/ui-ux-pro-max.md +18 -0
  234. package/dist/skills/official/webapp-testing.md +12 -0
  235. package/dist/skills/official-skills.d.ts +8 -4
  236. package/dist/skills/official-skills.d.ts.map +1 -1
  237. package/dist/skills/official-skills.js +48 -704
  238. package/dist/skills/official-skills.js.map +1 -1
  239. package/dist/skills/registry.d.ts +5 -0
  240. package/dist/skills/registry.d.ts.map +1 -1
  241. package/dist/skills/registry.js +48 -15
  242. package/dist/skills/registry.js.map +1 -1
  243. package/dist/skills/tools/pipeline-suggest.d.ts +30 -0
  244. package/dist/skills/tools/pipeline-suggest.d.ts.map +1 -0
  245. package/dist/skills/tools/pipeline-suggest.js +178 -0
  246. package/dist/skills/tools/pipeline-suggest.js.map +1 -0
  247. package/dist/web/analytics/anti-pattern-detector.d.ts +49 -0
  248. package/dist/web/analytics/anti-pattern-detector.d.ts.map +1 -0
  249. package/dist/web/analytics/anti-pattern-detector.js +318 -0
  250. package/dist/web/analytics/anti-pattern-detector.js.map +1 -0
  251. package/dist/web/analytics/drift-detector.d.ts +64 -0
  252. package/dist/web/analytics/drift-detector.d.ts.map +1 -0
  253. package/dist/web/analytics/drift-detector.js +198 -0
  254. package/dist/web/analytics/drift-detector.js.map +1 -0
  255. package/dist/web/analytics/weekly-report.d.ts +91 -0
  256. package/dist/web/analytics/weekly-report.d.ts.map +1 -0
  257. package/dist/web/analytics/weekly-report.js +328 -0
  258. package/dist/web/analytics/weekly-report.js.map +1 -0
  259. package/dist/web/auth-middleware.d.ts.map +1 -1
  260. package/dist/web/auth-middleware.js +1 -2
  261. package/dist/web/auth-middleware.js.map +1 -1
  262. package/dist/web/routes/_helpers.d.ts +16 -0
  263. package/dist/web/routes/_helpers.d.ts.map +1 -0
  264. package/dist/web/routes/_helpers.js +32 -0
  265. package/dist/web/routes/_helpers.js.map +1 -0
  266. package/dist/web/routes/ai.d.ts.map +1 -1
  267. package/dist/web/routes/ai.js +16 -22
  268. package/dist/web/routes/ai.js.map +1 -1
  269. package/dist/web/routes/drift.d.ts +10 -0
  270. package/dist/web/routes/drift.d.ts.map +1 -0
  271. package/dist/web/routes/drift.js +21 -0
  272. package/dist/web/routes/drift.js.map +1 -0
  273. package/dist/web/routes/error-handler.d.ts +43 -0
  274. package/dist/web/routes/error-handler.d.ts.map +1 -0
  275. package/dist/web/routes/error-handler.js +99 -0
  276. package/dist/web/routes/error-handler.js.map +1 -0
  277. package/dist/web/routes/insights.d.ts +9 -0
  278. package/dist/web/routes/insights.d.ts.map +1 -0
  279. package/dist/web/routes/insights.js +34 -0
  280. package/dist/web/routes/insights.js.map +1 -0
  281. package/dist/web/routes/patch.js +2 -2
  282. package/dist/web/routes/patch.js.map +1 -1
  283. package/dist/web/routes/reports.d.ts +10 -0
  284. package/dist/web/routes/reports.d.ts.map +1 -0
  285. package/dist/web/routes/reports.js +27 -0
  286. package/dist/web/routes/reports.js.map +1 -0
  287. package/dist/web/routes/rules.d.ts +13 -3
  288. package/dist/web/routes/rules.d.ts.map +1 -1
  289. package/dist/web/routes/rules.js +58 -97
  290. package/dist/web/routes/rules.js.map +1 -1
  291. package/dist/web/routes/sessions.d.ts +1 -2
  292. package/dist/web/routes/sessions.d.ts.map +1 -1
  293. package/dist/web/routes/sessions.js +43 -69
  294. package/dist/web/routes/sessions.js.map +1 -1
  295. package/dist/web/routes/skill-stats.d.ts +2 -0
  296. package/dist/web/routes/skill-stats.d.ts.map +1 -1
  297. package/dist/web/routes/skill-stats.js +41 -39
  298. package/dist/web/routes/skill-stats.js.map +1 -1
  299. package/dist/web/routes/skills.d.ts.map +1 -1
  300. package/dist/web/routes/skills.js +39 -4
  301. package/dist/web/routes/skills.js.map +1 -1
  302. package/dist/web/routes/stats.d.ts +11 -0
  303. package/dist/web/routes/stats.d.ts.map +1 -0
  304. package/dist/web/routes/stats.js +42 -0
  305. package/dist/web/routes/stats.js.map +1 -0
  306. package/dist/web/routes/status.js +1 -1
  307. package/dist/web/routes/status.js.map +1 -1
  308. package/dist/web/routes/tasks.d.ts +4 -0
  309. package/dist/web/routes/tasks.d.ts.map +1 -0
  310. package/dist/web/routes/tasks.js +156 -0
  311. package/dist/web/routes/tasks.js.map +1 -0
  312. package/dist/web/routes/trace.d.ts +10 -0
  313. package/dist/web/routes/trace.d.ts.map +1 -0
  314. package/dist/web/routes/trace.js +113 -0
  315. package/dist/web/routes/trace.js.map +1 -0
  316. package/dist/web/routes/types.d.ts +1 -14
  317. package/dist/web/routes/types.d.ts.map +1 -1
  318. package/dist/web/routes/types.js +12 -20
  319. package/dist/web/routes/types.js.map +1 -1
  320. package/dist/web/server.d.ts +1 -9
  321. package/dist/web/server.d.ts.map +1 -1
  322. package/dist/web/server.js +28 -28
  323. package/dist/web/server.js.map +1 -1
  324. package/dist/web/static/assets/AIConfig-CdDWzJyO.js +2 -0
  325. package/dist/web/static/assets/AIConfig-CdDWzJyO.js.map +1 -0
  326. package/dist/web/static/assets/Dashboard-CoEmmIDt.js +2 -0
  327. package/dist/web/static/assets/Dashboard-CoEmmIDt.js.map +1 -0
  328. package/dist/web/static/assets/{Drawer-DcU3ln98.js → Drawer-DdRTzlLB.js} +2 -2
  329. package/dist/web/static/assets/{Drawer-DcU3ln98.js.map → Drawer-DdRTzlLB.js.map} +1 -1
  330. package/dist/web/static/assets/Events-DrIq1SUS.js +2 -0
  331. package/dist/web/static/assets/Events-DrIq1SUS.js.map +1 -0
  332. package/dist/web/static/assets/Reports-DFBM3MDK.js +2 -0
  333. package/dist/web/static/assets/Reports-DFBM3MDK.js.map +1 -0
  334. package/dist/web/static/assets/SearchInput-qCj_jAcf.js +2 -0
  335. package/dist/web/static/assets/SearchInput-qCj_jAcf.js.map +1 -0
  336. package/dist/web/static/assets/SessionDetail-CCzwdoT7.js +2 -0
  337. package/dist/web/static/assets/SessionDetail-CCzwdoT7.js.map +1 -0
  338. package/dist/web/static/assets/Sessions-FfLYkAw9.js +2 -0
  339. package/dist/web/static/assets/Sessions-FfLYkAw9.js.map +1 -0
  340. package/dist/web/static/assets/Skills-C8Gvs3Qa.js +2 -0
  341. package/dist/web/static/assets/Skills-C8Gvs3Qa.js.map +1 -0
  342. package/dist/web/static/assets/TaskDetail-BS8pYhaR.js +2 -0
  343. package/dist/web/static/assets/TaskDetail-BS8pYhaR.js.map +1 -0
  344. package/dist/web/static/assets/Tasks-CyuhizG8.js +2 -0
  345. package/dist/web/static/assets/Tasks-CyuhizG8.js.map +1 -0
  346. package/dist/web/static/assets/export-L_VBD2p1.js +4 -0
  347. package/dist/web/static/assets/export-L_VBD2p1.js.map +1 -0
  348. package/dist/web/static/assets/index-CBX47X8l.js +3 -0
  349. package/dist/web/static/assets/index-CBX47X8l.js.map +1 -0
  350. package/dist/web/static/assets/index-DjIoMdoR.css +1 -0
  351. package/dist/web/static/assets/{lucide-53bR2rki.js → lucide-Bs_edTLa.js} +73 -38
  352. package/dist/web/static/assets/lucide-Bs_edTLa.js.map +1 -0
  353. package/dist/web/static/assets/react-router-r79dBVy4.js +20 -0
  354. package/dist/web/static/assets/{react-router-I-HqunH7.js.map → react-router-r79dBVy4.js.map} +1 -1
  355. package/dist/web/static/assets/task-title-BhOcemuR.js +2 -0
  356. package/dist/web/static/assets/task-title-BhOcemuR.js.map +1 -0
  357. package/dist/web/static/assets/time-Bxuk0M-C.js +2 -0
  358. package/dist/web/static/assets/time-Bxuk0M-C.js.map +1 -0
  359. package/dist/web/static/index.html +4 -4
  360. package/docs/concurrent-agents.md +129 -0
  361. package/docs/design/architecture-review-20260516.md +232 -0
  362. package/docs/design/fix-skills-data-and-set-leak-spec-20260516-1300.md +219 -0
  363. package/docs/design/h1-storage-aggregation-spec-20260518-1121.md +299 -0
  364. package/docs/design/h2-getdatabase-encapsulation-spec-20260518-1450.md +191 -0
  365. package/docs/design/h3-fallback-removal-spec-20260518-1245.md +76 -0
  366. package/docs/design/h4-index-dedup-spec-20260518-1230.md +109 -0
  367. package/docs/design/h6-services-migration-spec-20260518-1355.md +82 -0
  368. package/docs/design/hook-failure-queue-spec-20260516-1530.md +204 -0
  369. package/docs/design/l1-swarm-protocol-extract-spec-20260518-1605.md +106 -0
  370. package/docs/design/m10-forge-paths-spec-20260518-1320.md +121 -0
  371. package/docs/design/m2-m3-tool-input-spec-20260518-1425.md +131 -0
  372. package/docs/design/m7-routing-event-association-spec-20260518-1545.md +103 -0
  373. package/docs/design/project-path-gitroot-spec-20260518-1715.md +134 -0
  374. package/docs/design/refactor-phase1-spec-20260515-1600.md +543 -0
  375. package/docs/design/refactor-phase2-spec-20260515-1700.md +424 -0
  376. package/docs/design/task-active-gc-spec-20260518-1745.md +146 -0
  377. package/docs/design/tasks-list-filter-pagination-spec-20260518-0930.md +208 -0
  378. package/docs/implementation/fix-skills-data-and-set-leak-changelog-20260516-1300.md +104 -0
  379. package/docs/implementation/h1-storage-aggregation-changelog-20260518-1121.md +82 -0
  380. package/docs/implementation/h2-final-changelog-20260518-1530.md +61 -0
  381. package/docs/implementation/h2-phase1-safety-net-changelog-20260518-1450.md +70 -0
  382. package/docs/implementation/h2-phase2-operations-changelog-20260518-1450.md +120 -0
  383. package/docs/implementation/h2-phase3-callsites-changelog-20260518-1450.md +71 -0
  384. package/docs/implementation/h3-fallback-removal-changelog-20260518-1245.md +71 -0
  385. package/docs/implementation/h4-index-dedup-changelog-20260518-1230.md +60 -0
  386. package/docs/implementation/h6-services-migration-changelog-20260518-1355.md +46 -0
  387. package/docs/implementation/h7-m9-defaults-changelog-20260518-1300.md +46 -0
  388. package/docs/implementation/hook-failure-queue-changelog-20260516-1530.md +196 -0
  389. package/docs/implementation/hotfix-daemon-event-reject-20260516-1430.md +56 -0
  390. package/docs/implementation/l1-swarm-protocol-extract-changelog-20260518-1605.md +45 -0
  391. package/docs/implementation/l3-l4-daemon-perf-changelog-20260518-1410.md +63 -0
  392. package/docs/implementation/l6-l8-final-cleanup-changelog-20260518-1640.md +38 -0
  393. package/docs/implementation/m1-m4-m5-l7-cleanup-changelog-20260518-1310.md +58 -0
  394. package/docs/implementation/m10-forge-paths-changelog-20260518-1320.md +60 -0
  395. package/docs/implementation/m2-m3-tool-input-changelog-20260518-1425.md +43 -0
  396. package/docs/implementation/m6-m8-naming-shutdown-changelog-20260518-1340.md +56 -0
  397. package/docs/implementation/m7-routing-association-changelog-20260518-1545.md +69 -0
  398. package/docs/implementation/project-path-gitroot-changelog-20260518-1715.md +63 -0
  399. package/docs/implementation/refactor-phase1-changelog-20260515-1630.md +354 -0
  400. package/docs/implementation/refactor-phase2-changelog-20260515-1705.md +421 -0
  401. package/docs/implementation/task-active-gc-changelog-20260518-1745.md +35 -0
  402. package/docs/implementation/task-title-summary-changelog-20260518-1130.md +39 -0
  403. package/docs/implementation/tasks-detail-back-loses-filters-changelog-20260518-1100.md +22 -0
  404. package/docs/implementation/tasks-list-filter-pagination-changelog-20260518-0930.md +72 -0
  405. package/docs/implementation/tasks-page-white-screen-hotfix-changelog-20260518-1015.md +56 -0
  406. package/docs/reviews/claudemd-template-sync.md +54 -0
  407. package/docs/reviews/task-title-summary.md +92 -0
  408. package/docs/reviews/tasks-detail-back-loses-filters.md +58 -0
  409. package/docs/reviews/tasks-filter-pagination.md +80 -0
  410. package/docs/reviews/tasks-page-white-screen-hotfix.md +126 -0
  411. package/docs/ruflo-learning-strategy.md +322 -0
  412. package/docs/skills-deduplication-analysis.md +83 -0
  413. package/docs/skills-multiformat-support.md +177 -0
  414. package/docs/skills-third-party.md +183 -0
  415. package/docs/testing/tasks-filter-pagination-test-report.md +86 -0
  416. package/forge +321 -0
  417. package/package.json +28 -62
  418. package/playwright.config.ts +40 -0
  419. package/scripts/demo-v2.ts +91 -0
  420. package/scripts/dev-daemon.sh +232 -0
  421. package/scripts/dev-web.ts +109 -0
  422. package/scripts/e2e-mcp-link.ts +423 -0
  423. package/scripts/e2e-methodology-quality.ts +253 -0
  424. package/scripts/e2e-routing.ts +456 -0
  425. package/scripts/e2e-user-methodology.ts +326 -0
  426. package/scripts/e2e-web-workflows.ts +299 -0
  427. package/scripts/migrate-legacy-to-dynamic.sql +108 -0
  428. package/scripts/regenerate-execution-docs.ts +116 -0
  429. package/scripts/sync-agent-skills.ts +193 -0
  430. package/scripts/test-hook.sh +71 -0
  431. package/scripts/verify-skill-loading.ts +62 -0
  432. package/src/claudemd/claudemd-generator.ts +568 -0
  433. package/src/claudemd/convention-extractor.ts +69 -0
  434. package/src/claudemd/index.ts +35 -0
  435. package/src/claudemd/persona-manager.ts +88 -0
  436. package/src/claudemd/resume-manager.ts +236 -0
  437. package/src/claudemd/tech-detector.ts +220 -0
  438. package/src/claudemd/templates/swarm-protocol.md +222 -0
  439. package/src/cli/commands/claudemd.ts +84 -0
  440. package/src/cli/commands/config.ts +46 -0
  441. package/src/cli/commands/daemon.ts +310 -0
  442. package/src/cli/commands/executions.ts +115 -0
  443. package/src/cli/commands/init.ts +204 -0
  444. package/src/cli/commands/logs.ts +181 -0
  445. package/src/cli/commands/mcp.ts +242 -0
  446. package/src/cli/commands/menu.ts +357 -0
  447. package/src/cli/commands/skills.ts +185 -0
  448. package/src/cli/commands/stats.ts +73 -0
  449. package/src/cli/commands/status.ts +69 -0
  450. package/src/cli/commands/template.ts +77 -0
  451. package/src/cli/commands/trace.ts +148 -0
  452. package/src/cli/index.ts +42 -0
  453. package/src/cli/init/hook-manager.ts +132 -0
  454. package/src/core/ai/provider.ts +308 -0
  455. package/src/core/ai/types.ts +51 -0
  456. package/src/core/config.ts +124 -0
  457. package/src/core/constants.ts +62 -0
  458. package/src/core/event-fields.ts +32 -0
  459. package/src/core/queue/index.ts +192 -0
  460. package/src/core/storage/base.ts +302 -0
  461. package/src/core/storage/events.ts +434 -0
  462. package/src/core/storage/injections.ts +78 -0
  463. package/src/core/storage/maintenance.ts +59 -0
  464. package/src/core/storage/migrations/002_add_skill_tracking.sql +6 -0
  465. package/src/core/storage/migrations/003_add_skill_invocations.sql +23 -0
  466. package/src/core/storage/performance-indexes.sql +23 -0
  467. package/src/core/storage/routing.ts +322 -0
  468. package/src/core/storage/rows.ts +112 -0
  469. package/src/core/storage/schema.sql +224 -0
  470. package/src/core/storage/sessions.ts +168 -0
  471. package/src/core/storage/skills.ts +233 -0
  472. package/src/core/storage/sqlite.ts +293 -0
  473. package/src/core/storage/tasks.ts +318 -0
  474. package/src/core/storage/token-usage.ts +93 -0
  475. package/src/core/types.ts +181 -0
  476. package/src/core/utils/error-handler.ts +257 -0
  477. package/src/core/utils/forge-resume-block.ts +74 -0
  478. package/src/core/utils/format.ts +69 -0
  479. package/src/core/utils/git.ts +23 -0
  480. package/src/core/utils/logger.ts +134 -0
  481. package/src/core/utils/lru-cache.ts +54 -0
  482. package/src/core/utils/path.ts +19 -0
  483. package/src/core/utils/session.ts +26 -0
  484. package/src/core/utils/time.ts +37 -0
  485. package/src/core/utils/token-tracker.ts +97 -0
  486. package/src/daemon/event-parser.ts +36 -0
  487. package/src/daemon/handlers/history-exporter.ts +117 -0
  488. package/src/daemon/handlers/post-tool-use.ts +54 -0
  489. package/src/daemon/handlers/stop.ts +208 -0
  490. package/src/daemon/handlers/user-prompt.ts +178 -0
  491. package/src/daemon/index.ts +292 -0
  492. package/src/daemon/launchd/com.claude-forge.daemon.plist.template +47 -0
  493. package/src/daemon/launchd-installer.ts +260 -0
  494. package/src/daemon/lifecycle.ts +128 -0
  495. package/src/daemon/router.ts +40 -0
  496. package/src/daemon/server.ts +196 -0
  497. package/src/daemon/services/task-segmenter.ts +112 -0
  498. package/src/hooks/hook-lib.sh +118 -0
  499. package/src/hooks/notification.sh +35 -0
  500. package/src/hooks/post-tool-use.sh +61 -0
  501. package/src/hooks/pre-tool-use.sh +63 -0
  502. package/src/hooks/stop.sh +43 -0
  503. package/src/hooks/user-prompt-submit.sh +69 -0
  504. package/src/mcp/server.ts +322 -0
  505. package/src/skills/index.ts +2 -0
  506. package/src/skills/invocation-guard.ts +177 -0
  507. package/src/skills/matcher.ts +148 -0
  508. package/src/skills/official/code-simplifier.md +16 -0
  509. package/src/skills/official/find-skills.md +23 -0
  510. package/src/skills/official/official-api-design.md +17 -0
  511. package/src/skills/official/official-architecture-decision.md +20 -0
  512. package/src/skills/official/official-bmad.md +118 -0
  513. package/src/skills/official/official-db-schema-design.md +16 -0
  514. package/src/skills/official/official-debug.md +17 -0
  515. package/src/skills/official/official-doc-driven.md +31 -0
  516. package/src/skills/official/official-harness-engineering.md +108 -0
  517. package/src/skills/official/official-performance-optimization.md +30 -0
  518. package/src/skills/official/official-pr-review.md +35 -0
  519. package/src/skills/official/official-release-checklist.md +30 -0
  520. package/src/skills/official/official-security-hardening.md +26 -0
  521. package/src/skills/official/official-spec-driven-design.md +31 -0
  522. package/src/skills/official/planning-with-files.md +37 -0
  523. package/src/skills/official/ui-ux-pro-max.md +18 -0
  524. package/src/skills/official/webapp-testing.md +12 -0
  525. package/src/skills/official-skills.ts +89 -0
  526. package/src/skills/registry.ts +355 -0
  527. package/src/skills/semantic-matcher.ts +231 -0
  528. package/src/skills/tools/pipeline-suggest.ts +226 -0
  529. package/src/skills/tools/skill-invoke.ts +168 -0
  530. package/src/skills/tools/skill-list.ts +59 -0
  531. package/src/templates/go.yaml +53 -0
  532. package/src/templates/python.yaml +59 -0
  533. package/src/templates/react.yaml +55 -0
  534. package/src/templates/template-manager.ts +170 -0
  535. package/src/web/analytics/anti-pattern-detector.ts +367 -0
  536. package/src/web/analytics/drift-detector.ts +219 -0
  537. package/src/web/analytics/weekly-report.ts +431 -0
  538. package/src/web/auth-middleware.ts +54 -0
  539. package/src/web/routes/_helpers.ts +34 -0
  540. package/src/web/routes/ai.ts +204 -0
  541. package/src/web/routes/auth.ts +22 -0
  542. package/src/web/routes/drift.ts +25 -0
  543. package/src/web/routes/error-handler.ts +120 -0
  544. package/src/web/routes/events.ts +47 -0
  545. package/src/web/routes/insights.ts +43 -0
  546. package/src/web/routes/patch.ts +117 -0
  547. package/src/web/routes/reports.ts +34 -0
  548. package/src/web/routes/rules.ts +76 -0
  549. package/src/web/routes/sessions.ts +250 -0
  550. package/src/web/routes/skill-stats.ts +92 -0
  551. package/src/web/routes/skills.ts +350 -0
  552. package/src/web/routes/static.ts +67 -0
  553. package/src/web/routes/stats.ts +50 -0
  554. package/src/web/routes/status.ts +30 -0
  555. package/src/web/routes/tasks.ts +193 -0
  556. package/src/web/routes/token-usage.ts +20 -0
  557. package/src/web/routes/trace.ts +126 -0
  558. package/src/web/routes/types.ts +57 -0
  559. package/src/web/server.ts +134 -0
  560. package/src/web/ssrf-guard.ts +112 -0
  561. package/src/web/static/index.html +3251 -0
  562. package/src/web/static/vendor/chart.umd.min.js +20 -0
  563. package/tests/e2e/dashboard.spec.ts +205 -0
  564. package/tests/e2e/routing-skill-e2e.test.ts +39 -0
  565. package/tests/helpers/mock-ai.ts +92 -0
  566. package/tests/helpers/mock-storage.ts +159 -0
  567. package/tests/integration/claudemd-generator.test.ts +90 -0
  568. package/tests/integration/queue-replay.integration.test.ts +193 -0
  569. package/tests/integration/tasks-filter.integration.test.ts +154 -0
  570. package/tests/integration/web-analytics.integration.test.ts +133 -0
  571. package/tests/integration/web-stats.integration.test.ts +135 -0
  572. package/tests/integration/web-trace.integration.test.ts +175 -0
  573. package/tests/performance/database.benchmark.ts +161 -0
  574. package/tests/semantic-matcher.test.ts +99 -0
  575. package/tests/skill-matcher.test.ts +110 -0
  576. package/tests/unit/ai-provider-retry.test.ts +194 -0
  577. package/tests/unit/ai-provider-vision.test.ts +224 -0
  578. package/tests/unit/claudemd-generator.test.ts +68 -0
  579. package/tests/unit/cli-mcp.test.ts +141 -0
  580. package/tests/unit/core/forge-paths.test.ts +99 -0
  581. package/tests/unit/daemon/post-tool-use.test.ts +121 -0
  582. package/tests/unit/daemon/stop-handler-behavior-summary.test.ts +202 -0
  583. package/tests/unit/daemon/task-segmenter-recover.test.ts +84 -0
  584. package/tests/unit/event-fields.test.ts +88 -0
  585. package/tests/unit/event-parser.test.ts +55 -0
  586. package/tests/unit/handlers.test.ts +171 -0
  587. package/tests/unit/hooks/resolve-project-path.test.ts +122 -0
  588. package/tests/unit/invocation-guard.test.ts +125 -0
  589. package/tests/unit/queue.test.ts +272 -0
  590. package/tests/unit/router.test.ts +138 -0
  591. package/tests/unit/security.test.ts +128 -0
  592. package/tests/unit/skill-invocations-workflow.test.ts +495 -0
  593. package/tests/unit/skill-registry.test.ts +94 -0
  594. package/tests/unit/skills/invocation-guard-ttl.test.ts +211 -0
  595. package/tests/unit/skills/official-skills-loader.test.ts +126 -0
  596. package/tests/unit/skills/registry-multiformat.test.ts +92 -0
  597. package/tests/unit/socket-server.test.ts +183 -0
  598. package/tests/unit/storage/event-operations-aggregates.test.ts +342 -0
  599. package/tests/unit/storage/migration-idempotent.test.ts +304 -0
  600. package/tests/unit/storage/routing-aggregates.test.ts +276 -0
  601. package/tests/unit/storage/routing.test.ts +117 -0
  602. package/tests/unit/storage/schema-missing.test.ts +81 -0
  603. package/tests/unit/storage/session-operations-aggregates.test.ts +120 -0
  604. package/tests/unit/storage/sessions-aggregate.test.ts +435 -0
  605. package/tests/unit/storage/skill-operations-counts.test.ts +106 -0
  606. package/tests/unit/storage/skills-aggregates.test.ts +104 -0
  607. package/tests/unit/storage/sqlite-refactor-harness.test.ts +314 -0
  608. package/tests/unit/storage/task-operations-counts.test.ts +46 -0
  609. package/tests/unit/storage/tasks-getById.test.ts +343 -0
  610. package/tests/unit/storage/tasks-stale-gc.test.ts +86 -0
  611. package/tests/unit/storage.test.ts +172 -0
  612. package/tests/unit/token-usage.test.ts +144 -0
  613. package/tests/unit/type-guards.test.ts +201 -0
  614. package/tests/unit/utils/format.test.ts +189 -0
  615. package/tests/unit/utils/session.test.ts +89 -0
  616. package/tests/unit/utils/time.test.ts +112 -0
  617. package/tests/unit/web/navigation-back-contract.test.ts +134 -0
  618. package/tests/unit/web/routes-auth.test.ts +93 -0
  619. package/tests/unit/web/routes-events.test.ts +101 -0
  620. package/tests/unit/web/routes-rules.test.ts +182 -0
  621. package/tests/unit/web/routes-sessions.test.ts +181 -0
  622. package/tests/unit/web/routes-skill-stats.test.ts +179 -0
  623. package/tests/unit/web/routes-stats.test.ts +92 -0
  624. package/tests/unit/web/routes-tasks.test.ts +385 -0
  625. package/tests/unit/web/task-title-contract.test.ts +210 -0
  626. package/tests/unit/web/tasks-component-contract.test.ts +179 -0
  627. package/tsconfig.json +22 -0
  628. package/vitest.config.ts +21 -0
  629. package/vitest.integration.config.ts +16 -0
  630. package/web/CLAUDE.md +20 -0
  631. package/web/index.html +13 -0
  632. package/web/package-lock.json +4854 -0
  633. package/web/package.json +35 -0
  634. package/web/postcss.config.js +6 -0
  635. package/web/src/App.tsx +110 -0
  636. package/web/src/components/CodeBlock.tsx +31 -0
  637. package/web/src/components/Confirm.tsx +96 -0
  638. package/web/src/components/Drawer.tsx +60 -0
  639. package/web/src/components/Layout.tsx +145 -0
  640. package/web/src/components/MarkdownRenderer.tsx +77 -0
  641. package/web/src/components/SearchInput.tsx +31 -0
  642. package/web/src/components/SessionDetailContent.tsx +157 -0
  643. package/web/src/components/Toast.tsx +92 -0
  644. package/web/src/index.css +19 -0
  645. package/web/src/main.tsx +31 -0
  646. package/web/src/pages/AIConfig.tsx +233 -0
  647. package/web/src/pages/Dashboard.tsx +572 -0
  648. package/web/src/pages/Events.tsx +271 -0
  649. package/web/src/pages/Reports.tsx +428 -0
  650. package/web/src/pages/SessionDetail.tsx +162 -0
  651. package/web/src/pages/Sessions.tsx +205 -0
  652. package/web/src/pages/Skills.tsx +180 -0
  653. package/web/src/pages/TaskDetail.tsx +515 -0
  654. package/web/src/pages/Tasks.tsx +415 -0
  655. package/web/src/utils/auth.ts +59 -0
  656. package/web/src/utils/export.ts +54 -0
  657. package/web/src/utils/navigation.ts +25 -0
  658. package/web/src/utils/task-title.ts +49 -0
  659. package/web/src/utils/time.ts +13 -0
  660. package/web/tailwind.config.js +11 -0
  661. package/web/tsconfig.json +21 -0
  662. package/web/tsconfig.node.json +10 -0
  663. package/web/vite.config.ts +76 -0
  664. package/winspan-claude-forge-8.43.0.tgz +0 -0
  665. package/dist/agents/definition.d.ts +0 -62
  666. package/dist/agents/definition.d.ts.map +0 -1
  667. package/dist/agents/definition.js +0 -27
  668. package/dist/agents/definition.js.map +0 -1
  669. package/dist/agents/distributor.d.ts +0 -23
  670. package/dist/agents/distributor.d.ts.map +0 -1
  671. package/dist/agents/distributor.js +0 -85
  672. package/dist/agents/distributor.js.map +0 -1
  673. package/dist/agents/index.d.ts +0 -5
  674. package/dist/agents/index.d.ts.map +0 -1
  675. package/dist/agents/index.js +0 -5
  676. package/dist/agents/index.js.map +0 -1
  677. package/dist/agents/methodologies/agent-builder.d.ts +0 -21
  678. package/dist/agents/methodologies/agent-builder.d.ts.map +0 -1
  679. package/dist/agents/methodologies/agent-builder.js +0 -149
  680. package/dist/agents/methodologies/agent-builder.js.map +0 -1
  681. package/dist/agents/methodologies/phases/bmad/analyze.d.ts +0 -3
  682. package/dist/agents/methodologies/phases/bmad/analyze.d.ts.map +0 -1
  683. package/dist/agents/methodologies/phases/bmad/analyze.js +0 -19
  684. package/dist/agents/methodologies/phases/bmad/analyze.js.map +0 -1
  685. package/dist/agents/methodologies/phases/bmad/design.d.ts +0 -3
  686. package/dist/agents/methodologies/phases/bmad/design.d.ts.map +0 -1
  687. package/dist/agents/methodologies/phases/bmad/design.js +0 -18
  688. package/dist/agents/methodologies/phases/bmad/design.js.map +0 -1
  689. package/dist/agents/methodologies/phases/bmad/implement.d.ts +0 -3
  690. package/dist/agents/methodologies/phases/bmad/implement.d.ts.map +0 -1
  691. package/dist/agents/methodologies/phases/bmad/implement.js +0 -17
  692. package/dist/agents/methodologies/phases/bmad/implement.js.map +0 -1
  693. package/dist/agents/methodologies/phases/bmad/index.d.ts +0 -6
  694. package/dist/agents/methodologies/phases/bmad/index.d.ts.map +0 -1
  695. package/dist/agents/methodologies/phases/bmad/index.js +0 -6
  696. package/dist/agents/methodologies/phases/bmad/index.js.map +0 -1
  697. package/dist/agents/methodologies/phases/bmad/review.d.ts +0 -3
  698. package/dist/agents/methodologies/phases/bmad/review.d.ts.map +0 -1
  699. package/dist/agents/methodologies/phases/bmad/review.js +0 -17
  700. package/dist/agents/methodologies/phases/bmad/review.js.map +0 -1
  701. package/dist/agents/methodologies/phases/bmad/test.d.ts +0 -3
  702. package/dist/agents/methodologies/phases/bmad/test.d.ts.map +0 -1
  703. package/dist/agents/methodologies/phases/bmad/test.js +0 -21
  704. package/dist/agents/methodologies/phases/bmad/test.js.map +0 -1
  705. package/dist/agents/methodologies/phases/harness/fix.d.ts +0 -3
  706. package/dist/agents/methodologies/phases/harness/fix.d.ts.map +0 -1
  707. package/dist/agents/methodologies/phases/harness/fix.js +0 -17
  708. package/dist/agents/methodologies/phases/harness/fix.js.map +0 -1
  709. package/dist/agents/methodologies/phases/harness/index.d.ts +0 -6
  710. package/dist/agents/methodologies/phases/harness/index.d.ts.map +0 -1
  711. package/dist/agents/methodologies/phases/harness/index.js +0 -6
  712. package/dist/agents/methodologies/phases/harness/index.js.map +0 -1
  713. package/dist/agents/methodologies/phases/harness/reproduce.d.ts +0 -3
  714. package/dist/agents/methodologies/phases/harness/reproduce.d.ts.map +0 -1
  715. package/dist/agents/methodologies/phases/harness/reproduce.js +0 -20
  716. package/dist/agents/methodologies/phases/harness/reproduce.js.map +0 -1
  717. package/dist/agents/methodologies/phases/harness/root-cause.d.ts +0 -3
  718. package/dist/agents/methodologies/phases/harness/root-cause.d.ts.map +0 -1
  719. package/dist/agents/methodologies/phases/harness/root-cause.js +0 -21
  720. package/dist/agents/methodologies/phases/harness/root-cause.js.map +0 -1
  721. package/dist/agents/methodologies/phases/harness/safety-net.d.ts +0 -3
  722. package/dist/agents/methodologies/phases/harness/safety-net.d.ts.map +0 -1
  723. package/dist/agents/methodologies/phases/harness/safety-net.js +0 -17
  724. package/dist/agents/methodologies/phases/harness/safety-net.js.map +0 -1
  725. package/dist/agents/methodologies/phases/harness/verify.d.ts +0 -3
  726. package/dist/agents/methodologies/phases/harness/verify.d.ts.map +0 -1
  727. package/dist/agents/methodologies/phases/harness/verify.js +0 -22
  728. package/dist/agents/methodologies/phases/harness/verify.js.map +0 -1
  729. package/dist/agents/methodologies/presets.d.ts +0 -10
  730. package/dist/agents/methodologies/presets.d.ts.map +0 -1
  731. package/dist/agents/methodologies/presets.js +0 -79
  732. package/dist/agents/methodologies/presets.js.map +0 -1
  733. package/dist/agents/methodologies/types.d.ts +0 -45
  734. package/dist/agents/methodologies/types.d.ts.map +0 -1
  735. package/dist/agents/methodologies/types.js +0 -10
  736. package/dist/agents/methodologies/types.js.map +0 -1
  737. package/dist/agents/methodologies/user-config-loader.d.ts +0 -30
  738. package/dist/agents/methodologies/user-config-loader.d.ts.map +0 -1
  739. package/dist/agents/methodologies/user-config-loader.js +0 -159
  740. package/dist/agents/methodologies/user-config-loader.js.map +0 -1
  741. package/dist/agents/official-agents.d.ts +0 -4
  742. package/dist/agents/official-agents.d.ts.map +0 -1
  743. package/dist/agents/official-agents.js +0 -559
  744. package/dist/agents/official-agents.js.map +0 -1
  745. package/dist/agents/registry.d.ts +0 -57
  746. package/dist/agents/registry.d.ts.map +0 -1
  747. package/dist/agents/registry.js +0 -271
  748. package/dist/agents/registry.js.map +0 -1
  749. package/dist/capability/index.d.ts +0 -10
  750. package/dist/capability/index.d.ts.map +0 -1
  751. package/dist/capability/index.js +0 -10
  752. package/dist/capability/index.js.map +0 -1
  753. package/dist/capability/types.d.ts +0 -10
  754. package/dist/capability/types.d.ts.map +0 -1
  755. package/dist/capability/types.js +0 -10
  756. package/dist/capability/types.js.map +0 -1
  757. package/dist/cli/commands/agents.d.ts +0 -3
  758. package/dist/cli/commands/agents.d.ts.map +0 -1
  759. package/dist/cli/commands/agents.js +0 -62
  760. package/dist/cli/commands/agents.js.map +0 -1
  761. package/dist/cli/commands/rules.d.ts +0 -8
  762. package/dist/cli/commands/rules.d.ts.map +0 -1
  763. package/dist/cli/commands/rules.js +0 -89
  764. package/dist/cli/commands/rules.js.map +0 -1
  765. package/dist/daemon/auto-disable-scheduler.d.ts +0 -53
  766. package/dist/daemon/auto-disable-scheduler.d.ts.map +0 -1
  767. package/dist/daemon/auto-disable-scheduler.js +0 -114
  768. package/dist/daemon/auto-disable-scheduler.js.map +0 -1
  769. package/dist/daemon/handlers/pre-tool-use.d.ts +0 -39
  770. package/dist/daemon/handlers/pre-tool-use.d.ts.map +0 -1
  771. package/dist/daemon/handlers/pre-tool-use.js +0 -166
  772. package/dist/daemon/handlers/pre-tool-use.js.map +0 -1
  773. package/dist/daemon/routing-observer.d.ts +0 -42
  774. package/dist/daemon/routing-observer.d.ts.map +0 -1
  775. package/dist/daemon/routing-observer.js +0 -264
  776. package/dist/daemon/routing-observer.js.map +0 -1
  777. package/dist/daemon/routing-state.d.ts +0 -64
  778. package/dist/daemon/routing-state.d.ts.map +0 -1
  779. package/dist/daemon/routing-state.js +0 -240
  780. package/dist/daemon/routing-state.js.map +0 -1
  781. package/dist/engine/agent-router.d.ts +0 -142
  782. package/dist/engine/agent-router.d.ts.map +0 -1
  783. package/dist/engine/agent-router.js +0 -276
  784. package/dist/engine/agent-router.js.map +0 -1
  785. package/dist/engine/context-builder.d.ts +0 -23
  786. package/dist/engine/context-builder.d.ts.map +0 -1
  787. package/dist/engine/context-builder.js +0 -63
  788. package/dist/engine/context-builder.js.map +0 -1
  789. package/dist/engine/conventions/basic-security.yaml +0 -109
  790. package/dist/engine/conventions/code-quality.yaml +0 -123
  791. package/dist/engine/conventions/database-safety.yaml +0 -74
  792. package/dist/engine/conventions/dependency-safety.yaml +0 -132
  793. package/dist/engine/conventions/docker-safety.yaml +0 -69
  794. package/dist/engine/conventions/git-safety.yaml +0 -118
  795. package/dist/engine/conventions/go-best-practices.yaml +0 -84
  796. package/dist/engine/conventions/python-best-practices.yaml +0 -96
  797. package/dist/engine/conventions/react-best-practices.yaml +0 -96
  798. package/dist/engine/conventions/routing.yaml +0 -378
  799. package/dist/engine/conventions/strict-security.yaml +0 -30
  800. package/dist/engine/conventions/ts-quality.yaml +0 -49
  801. package/dist/engine/dsl/compiler.d.ts +0 -34
  802. package/dist/engine/dsl/compiler.d.ts.map +0 -1
  803. package/dist/engine/dsl/compiler.js +0 -702
  804. package/dist/engine/dsl/compiler.js.map +0 -1
  805. package/dist/engine/dsl/parser.d.ts +0 -25
  806. package/dist/engine/dsl/parser.d.ts.map +0 -1
  807. package/dist/engine/dsl/parser.js +0 -208
  808. package/dist/engine/dsl/parser.js.map +0 -1
  809. package/dist/engine/dsl/runtime.d.ts +0 -46
  810. package/dist/engine/dsl/runtime.d.ts.map +0 -1
  811. package/dist/engine/dsl/runtime.js +0 -173
  812. package/dist/engine/dsl/runtime.js.map +0 -1
  813. package/dist/engine/dsl/types.d.ts +0 -139
  814. package/dist/engine/dsl/types.d.ts.map +0 -1
  815. package/dist/engine/dsl/types.js +0 -11
  816. package/dist/engine/dsl/types.js.map +0 -1
  817. package/dist/engine/evidence-store.d.ts +0 -44
  818. package/dist/engine/evidence-store.d.ts.map +0 -1
  819. package/dist/engine/evidence-store.js +0 -109
  820. package/dist/engine/evidence-store.js.map +0 -1
  821. package/dist/engine/experiment-router.d.ts +0 -102
  822. package/dist/engine/experiment-router.d.ts.map +0 -1
  823. package/dist/engine/experiment-router.js +0 -289
  824. package/dist/engine/experiment-router.js.map +0 -1
  825. package/dist/engine/recommender.d.ts +0 -52
  826. package/dist/engine/recommender.d.ts.map +0 -1
  827. package/dist/engine/recommender.js +0 -162
  828. package/dist/engine/recommender.js.map +0 -1
  829. package/dist/engine/rule-engine.d.ts +0 -33
  830. package/dist/engine/rule-engine.d.ts.map +0 -1
  831. package/dist/engine/rule-engine.js +0 -250
  832. package/dist/engine/rule-engine.js.map +0 -1
  833. package/dist/engine/security-gates.d.ts +0 -42
  834. package/dist/engine/security-gates.d.ts.map +0 -1
  835. package/dist/engine/security-gates.js +0 -210
  836. package/dist/engine/security-gates.js.map +0 -1
  837. package/dist/intelligence/classifier.d.ts +0 -75
  838. package/dist/intelligence/classifier.d.ts.map +0 -1
  839. package/dist/intelligence/classifier.js +0 -352
  840. package/dist/intelligence/classifier.js.map +0 -1
  841. package/dist/intelligence/context-gatherer.d.ts +0 -101
  842. package/dist/intelligence/context-gatherer.d.ts.map +0 -1
  843. package/dist/intelligence/context-gatherer.js +0 -417
  844. package/dist/intelligence/context-gatherer.js.map +0 -1
  845. package/dist/intelligence/cot-classifier.d.ts +0 -95
  846. package/dist/intelligence/cot-classifier.d.ts.map +0 -1
  847. package/dist/intelligence/cot-classifier.js +0 -391
  848. package/dist/intelligence/cot-classifier.js.map +0 -1
  849. package/dist/intelligence/distiller.d.ts +0 -22
  850. package/dist/intelligence/distiller.d.ts.map +0 -1
  851. package/dist/intelligence/distiller.js +0 -108
  852. package/dist/intelligence/distiller.js.map +0 -1
  853. package/dist/intelligence/execution-doc-builder.d.ts +0 -151
  854. package/dist/intelligence/execution-doc-builder.d.ts.map +0 -1
  855. package/dist/intelligence/execution-doc-builder.js +0 -1018
  856. package/dist/intelligence/execution-doc-builder.js.map +0 -1
  857. package/dist/intelligence/intent-types.d.ts +0 -13
  858. package/dist/intelligence/intent-types.d.ts.map +0 -1
  859. package/dist/intelligence/intent-types.js +0 -19
  860. package/dist/intelligence/intent-types.js.map +0 -1
  861. package/dist/intelligence/multimodal-parser.d.ts +0 -105
  862. package/dist/intelligence/multimodal-parser.d.ts.map +0 -1
  863. package/dist/intelligence/multimodal-parser.js +0 -425
  864. package/dist/intelligence/multimodal-parser.js.map +0 -1
  865. package/dist/intelligence/quality-gate.d.ts +0 -45
  866. package/dist/intelligence/quality-gate.d.ts.map +0 -1
  867. package/dist/intelligence/quality-gate.js +0 -193
  868. package/dist/intelligence/quality-gate.js.map +0 -1
  869. package/dist/intelligence/task-segmenter.d.ts.map +0 -1
  870. package/dist/intelligence/task-segmenter.js.map +0 -1
  871. package/dist/web/routes/agents.d.ts +0 -7
  872. package/dist/web/routes/agents.d.ts.map +0 -1
  873. package/dist/web/routes/agents.js +0 -209
  874. package/dist/web/routes/agents.js.map +0 -1
  875. package/dist/web/routes/execution-trace.d.ts +0 -21
  876. package/dist/web/routes/execution-trace.d.ts.map +0 -1
  877. package/dist/web/routes/execution-trace.js +0 -353
  878. package/dist/web/routes/execution-trace.js.map +0 -1
  879. package/dist/web/routes/experiments.d.ts +0 -15
  880. package/dist/web/routes/experiments.d.ts.map +0 -1
  881. package/dist/web/routes/experiments.js +0 -187
  882. package/dist/web/routes/experiments.js.map +0 -1
  883. package/dist/web/routes/routing.d.ts +0 -17
  884. package/dist/web/routes/routing.d.ts.map +0 -1
  885. package/dist/web/routes/routing.js +0 -592
  886. package/dist/web/routes/routing.js.map +0 -1
  887. package/dist/web/routes/workflows.d.ts +0 -19
  888. package/dist/web/routes/workflows.d.ts.map +0 -1
  889. package/dist/web/routes/workflows.js +0 -86
  890. package/dist/web/routes/workflows.js.map +0 -1
  891. package/dist/web/static/assets/AIConfig-R5wZ3ZKT.js +0 -2
  892. package/dist/web/static/assets/AIConfig-R5wZ3ZKT.js.map +0 -1
  893. package/dist/web/static/assets/Agents-Beg34V1g.js +0 -2
  894. package/dist/web/static/assets/Agents-Beg34V1g.js.map +0 -1
  895. package/dist/web/static/assets/CodeBlock--H53gk46.js +0 -2
  896. package/dist/web/static/assets/CodeBlock--H53gk46.js.map +0 -1
  897. package/dist/web/static/assets/Dashboard-Cy1xsj1J.js +0 -2
  898. package/dist/web/static/assets/Dashboard-Cy1xsj1J.js.map +0 -1
  899. package/dist/web/static/assets/Events-mFhXl4zI.js +0 -2
  900. package/dist/web/static/assets/Events-mFhXl4zI.js.map +0 -1
  901. package/dist/web/static/assets/ExecutionTrace-DG901hLR.js +0 -3
  902. package/dist/web/static/assets/ExecutionTrace-DG901hLR.js.map +0 -1
  903. package/dist/web/static/assets/MarkdownRenderer-CCIz1MOz.js +0 -2
  904. package/dist/web/static/assets/MarkdownRenderer-CCIz1MOz.js.map +0 -1
  905. package/dist/web/static/assets/Routing-B7BFLfjh.js +0 -2
  906. package/dist/web/static/assets/Routing-B7BFLfjh.js.map +0 -1
  907. package/dist/web/static/assets/SessionDetail-BT0l4RrK.js +0 -2
  908. package/dist/web/static/assets/SessionDetail-BT0l4RrK.js.map +0 -1
  909. package/dist/web/static/assets/Sessions-C6J_HQ_u.js +0 -2
  910. package/dist/web/static/assets/Sessions-C6J_HQ_u.js.map +0 -1
  911. package/dist/web/static/assets/Skills-4DQWLaTv.js +0 -2
  912. package/dist/web/static/assets/Skills-4DQWLaTv.js.map +0 -1
  913. package/dist/web/static/assets/WorkflowDetail-zhNqUkBE.js +0 -2
  914. package/dist/web/static/assets/WorkflowDetail-zhNqUkBE.js.map +0 -1
  915. package/dist/web/static/assets/Workflows-Btvi-lGw.js +0 -2
  916. package/dist/web/static/assets/Workflows-Btvi-lGw.js.map +0 -1
  917. package/dist/web/static/assets/export-BQQZLaHV.js +0 -4
  918. package/dist/web/static/assets/export-BQQZLaHV.js.map +0 -1
  919. package/dist/web/static/assets/index-Cgr9qMtq.js +0 -3
  920. package/dist/web/static/assets/index-Cgr9qMtq.js.map +0 -1
  921. package/dist/web/static/assets/index-CngWb5gC.css +0 -1
  922. package/dist/web/static/assets/lucide-53bR2rki.js.map +0 -1
  923. package/dist/web/static/assets/react-router-I-HqunH7.js +0 -20
@@ -0,0 +1,2 @@
1
+ import{j as e,r as m}from"./react-vendor-CSp-GLFF.js";import{b as y,u,c as p}from"./query-C99w429o.js";import{D as j}from"./Drawer-DdRTzlLB.js";import{N as b,O as N}from"./vendor-CMMjVdZs.js";import{h as w,o as v}from"./syntax-highlighter-44FakypI.js";import{u as k}from"./index-CBX47X8l.js";import{a as S}from"./auth-Bnf8ZcqN.js";import{B as f,P as C,X as E,l as q}from"./lucide-Bs_edTLa.js";import"./react-router-r79dBVy4.js";function F({content:a,className:t=""}){return e.jsx("div",{className:`prose prose-sm max-w-none ${t}`,children:e.jsx(b,{remarkPlugins:[N],components:{code({inline:s,className:c,children:i,...d}){const o=/language-(\w+)/.exec(c||""),l=o==null?void 0:o[1];return!s&&l?e.jsx(w,{style:v,language:l,PreTag:"div",customStyle:{margin:0,borderRadius:"6px",fontSize:"12px",padding:"12px"},...d,children:String(i).replace(/\n$/,"")}):e.jsx("code",{className:"bg-gray-100 text-gray-800 px-1 py-0.5 rounded text-xs font-mono",...d,children:i})},h1:({children:s})=>e.jsx("h1",{className:"text-lg font-bold text-gray-900 mt-4 mb-2",children:s}),h2:({children:s})=>e.jsx("h2",{className:"text-base font-bold text-gray-900 mt-3 mb-2",children:s}),h3:({children:s})=>e.jsx("h3",{className:"text-sm font-semibold text-gray-900 mt-2 mb-1",children:s}),p:({children:s})=>e.jsx("p",{className:"text-sm text-gray-700 my-2",children:s}),ul:({children:s})=>e.jsx("ul",{className:"list-disc list-inside text-sm text-gray-700 my-2 space-y-0.5",children:s}),ol:({children:s})=>e.jsx("ol",{className:"list-decimal list-inside text-sm text-gray-700 my-2 space-y-0.5",children:s}),li:({children:s})=>e.jsx("li",{className:"text-sm",children:s}),a:({children:s,href:c})=>e.jsx("a",{href:c,target:"_blank",rel:"noopener noreferrer",className:"text-indigo-600 hover:text-indigo-700 underline",children:s}),blockquote:({children:s})=>e.jsx("blockquote",{className:"border-l-4 border-gray-300 pl-3 italic text-gray-600 my-2",children:s}),table:({children:s})=>e.jsx("div",{className:"overflow-x-auto my-2",children:e.jsx("table",{className:"min-w-full border border-gray-200 text-sm",children:s})}),th:({children:s})=>e.jsx("th",{className:"border border-gray-200 px-2 py-1 bg-gray-50 font-semibold text-left",children:s}),td:({children:s})=>e.jsx("td",{className:"border border-gray-200 px-2 py-1",children:s})},children:a})})}async function P(){const a=await fetch("/api/skills");if(!a.ok)throw new Error("Failed to fetch skills");const t=await a.json();return Array.isArray(t)?t:t.skills||[]}async function $(a){const t=await fetch(`/api/skills/${a}`);if(!t.ok)throw new Error("Failed to fetch");return t.json()}async function K(a,t){if(!(await S(`/api/skills/${a}`,{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({content:t})})).ok)throw new Error("Failed to save")}function z(){const a=y(),t=k(),{data:s,isLoading:c}=u({queryKey:["skills"],queryFn:P}),[i,d]=m.useState(null),[o,l]=m.useState(!1),[h,g]=m.useState(""),{data:r}=u({queryKey:["skill-detail",i],queryFn:()=>$(i),enabled:!!i});m.useEffect(()=>{r!=null&&r.content&&g(r.content),l(!1)},[r]);const x=p({mutationFn:n=>K(n.name,n.content),onSuccess:()=>{t.success("Skill 已保存"),l(!1),a.invalidateQueries({queryKey:["skill-detail",i]}),a.invalidateQueries({queryKey:["skills"]})},onError:n=>t.error(`保存失败: ${n.message}`)});return c?e.jsx("div",{className:"bg-white rounded-lg shadow p-6",children:"加载中..."}):e.jsxs("div",{children:[e.jsxs("div",{className:"flex items-center justify-between mb-6",children:[e.jsx("h1",{className:"text-2xl font-bold text-gray-900",children:"Skill 管理"}),e.jsxs("div",{className:"text-sm text-gray-500",children:["共 ",(s==null?void 0:s.length)||0," 个 Skill"]})]}),e.jsx("div",{className:"grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4",children:s==null?void 0:s.map(n=>e.jsx("div",{className:"bg-white rounded-lg shadow p-5 hover:shadow-md transition-shadow cursor-pointer",onClick:()=>d(n.name),children:e.jsxs("div",{className:"flex items-start gap-3",children:[e.jsx("div",{className:"w-10 h-10 rounded-lg bg-purple-100 flex items-center justify-center flex-shrink-0",children:e.jsx(f,{className:"h-5 w-5 text-purple-600"})}),e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsx("h3",{className:"font-semibold text-gray-900 truncate",children:n.name}),e.jsx("p",{className:"text-xs text-gray-500 mt-1 line-clamp-3",children:n.description||"(无描述)"})]})]})},n.name))}),e.jsx(j,{open:i!==null,onClose:()=>{d(null),l(!1)},title:`Skill: ${i}`,width:"w-[800px]",children:r&&e.jsxs("div",{className:"space-y-4",children:[e.jsxs("div",{className:"flex items-center gap-2 mb-2",children:[e.jsx(f,{className:"h-5 w-5 text-purple-600"}),e.jsx("h3",{className:"text-lg font-semibold text-gray-900",children:r.name})]}),e.jsxs("div",{children:[e.jsx("div",{className:"text-xs text-gray-500 mb-1",children:"描述"}),e.jsx("div",{className:"text-sm text-gray-800",children:r.description})]}),e.jsxs("div",{children:[e.jsxs("div",{className:"flex items-center justify-between mb-2",children:[e.jsx("div",{className:"text-xs text-gray-500",children:"完整内容 (Markdown)"}),e.jsx("div",{className:"flex items-center gap-2",children:o?e.jsxs(e.Fragment,{children:[e.jsxs("button",{onClick:()=>{l(!1),g(r.content||"")},className:"inline-flex items-center gap-1 text-xs text-gray-600 hover:text-gray-700",children:[e.jsx(E,{className:"h-3 w-3"}),"取消"]}),e.jsxs("button",{onClick:()=>x.mutate({name:r.name,content:h}),disabled:x.isPending,className:"inline-flex items-center gap-1 text-xs bg-indigo-600 text-white px-2 py-1 rounded hover:bg-indigo-700 disabled:bg-gray-400",children:[e.jsx(q,{className:"h-3 w-3"}),x.isPending?"保存中...":"保存"]})]}):e.jsxs("button",{onClick:()=>l(!0),className:"inline-flex items-center gap-1 text-xs text-indigo-600 hover:text-indigo-700",children:[e.jsx(C,{className:"h-3 w-3"}),"编辑"]})})]}),o?e.jsx("textarea",{value:h,onChange:n=>g(n.target.value),className:"w-full font-mono text-xs bg-gray-50 rounded p-3 border border-gray-300 focus:border-indigo-500 focus:outline-none",rows:20}):e.jsx("div",{className:"bg-white rounded p-3 border border-gray-200 max-h-[500px] overflow-y-auto",children:e.jsx(F,{content:r.content||""})}),x.isError&&e.jsxs("div",{className:"text-xs text-red-600 mt-1",children:["保存失败:",x.error.message]})]})]})})]})}export{z as default};
2
+ //# sourceMappingURL=Skills-C8Gvs3Qa.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Skills-C8Gvs3Qa.js","sources":["../../src/components/MarkdownRenderer.tsx","../../src/pages/Skills.tsx"],"sourcesContent":["import ReactMarkdown from 'react-markdown'\nimport remarkGfm from 'remark-gfm'\nimport { Prism as SyntaxHighlighter } from 'react-syntax-highlighter'\nimport { oneLight } from 'react-syntax-highlighter/dist/esm/styles/prism'\n\ninterface Props {\n content: string\n className?: string\n}\n\nexport default function MarkdownRenderer({ content, className = '' }: Props) {\n return (\n <div className={`prose prose-sm max-w-none ${className}`}>\n <ReactMarkdown\n remarkPlugins={[remarkGfm]}\n components={{\n code({ inline, className, children, ...props }: any) {\n const match = /language-(\\w+)/.exec(className || '')\n const lang = match?.[1]\n if (!inline && lang) {\n return (\n <SyntaxHighlighter\n style={oneLight}\n language={lang}\n PreTag=\"div\"\n customStyle={{\n margin: 0,\n borderRadius: '6px',\n fontSize: '12px',\n padding: '12px',\n }}\n {...props}\n >\n {String(children).replace(/\\n$/, '')}\n </SyntaxHighlighter>\n )\n }\n return (\n <code\n className=\"bg-gray-100 text-gray-800 px-1 py-0.5 rounded text-xs font-mono\"\n {...props}\n >\n {children}\n </code>\n )\n },\n h1: ({ children }) => <h1 className=\"text-lg font-bold text-gray-900 mt-4 mb-2\">{children}</h1>,\n h2: ({ children }) => <h2 className=\"text-base font-bold text-gray-900 mt-3 mb-2\">{children}</h2>,\n h3: ({ children }) => <h3 className=\"text-sm font-semibold text-gray-900 mt-2 mb-1\">{children}</h3>,\n p: ({ children }) => <p className=\"text-sm text-gray-700 my-2\">{children}</p>,\n ul: ({ children }) => <ul className=\"list-disc list-inside text-sm text-gray-700 my-2 space-y-0.5\">{children}</ul>,\n ol: ({ children }) => <ol className=\"list-decimal list-inside text-sm text-gray-700 my-2 space-y-0.5\">{children}</ol>,\n li: ({ children }) => <li className=\"text-sm\">{children}</li>,\n a: ({ children, href }) => (\n <a href={href} target=\"_blank\" rel=\"noopener noreferrer\" className=\"text-indigo-600 hover:text-indigo-700 underline\">\n {children}\n </a>\n ),\n blockquote: ({ children }) => (\n <blockquote className=\"border-l-4 border-gray-300 pl-3 italic text-gray-600 my-2\">\n {children}\n </blockquote>\n ),\n table: ({ children }) => (\n <div className=\"overflow-x-auto my-2\">\n <table className=\"min-w-full border border-gray-200 text-sm\">{children}</table>\n </div>\n ),\n th: ({ children }) => <th className=\"border border-gray-200 px-2 py-1 bg-gray-50 font-semibold text-left\">{children}</th>,\n td: ({ children }) => <td className=\"border border-gray-200 px-2 py-1\">{children}</td>,\n }}\n >\n {content}\n </ReactMarkdown>\n </div>\n )\n}\n","import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'\nimport { useState, useEffect } from 'react'\nimport { BookOpen, Edit2, Save, X } from 'lucide-react'\nimport Drawer from '../components/Drawer'\nimport MarkdownRenderer from '../components/MarkdownRenderer'\nimport { useToast } from '../components/Toast'\nimport { authFetch } from '../utils/auth'\n\ninterface Skill {\n name: string\n description: string\n content?: string\n}\n\ninterface SkillsResponse {\n skills?: Skill[]\n}\n\nasync function fetchSkills(): Promise<Skill[]> {\n const res = await fetch('/api/skills')\n if (!res.ok) throw new Error('Failed to fetch skills')\n const data: SkillsResponse | Skill[] = await res.json()\n if (Array.isArray(data)) return data\n return data.skills || []\n}\n\nasync function fetchSkillDetail(name: string): Promise<Skill> {\n const res = await fetch(`/api/skills/${name}`)\n if (!res.ok) throw new Error('Failed to fetch')\n return res.json()\n}\n\nasync function saveSkill(name: string, content: string): Promise<void> {\n const res = await authFetch(`/api/skills/${name}`, {\n method: 'PUT',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ content }),\n })\n if (!res.ok) throw new Error('Failed to save')\n}\n\nexport default function Skills() {\n const queryClient = useQueryClient()\n const toast = useToast()\n const { data: skills, isLoading } = useQuery({\n queryKey: ['skills'],\n queryFn: fetchSkills,\n })\n\n const [selectedSkill, setSelectedSkill] = useState<string | null>(null)\n const [editing, setEditing] = useState(false)\n const [editContent, setEditContent] = useState('')\n\n const { data: detail } = useQuery({\n queryKey: ['skill-detail', selectedSkill],\n queryFn: () => fetchSkillDetail(selectedSkill!),\n enabled: !!selectedSkill,\n })\n\n useEffect(() => {\n if (detail?.content) setEditContent(detail.content)\n setEditing(false)\n }, [detail])\n\n const mutation = useMutation({\n mutationFn: (vars: { name: string; content: string }) => saveSkill(vars.name, vars.content),\n onSuccess: () => {\n toast.success('Skill 已保存')\n setEditing(false)\n queryClient.invalidateQueries({ queryKey: ['skill-detail', selectedSkill] })\n queryClient.invalidateQueries({ queryKey: ['skills'] })\n },\n onError: (e: Error) => toast.error(`保存失败: ${e.message}`),\n })\n\n if (isLoading) {\n return <div className=\"bg-white rounded-lg shadow p-6\">加载中...</div>\n }\n\n return (\n <div>\n <div className=\"flex items-center justify-between mb-6\">\n <h1 className=\"text-2xl font-bold text-gray-900\">Skill 管理</h1>\n <div className=\"text-sm text-gray-500\">共 {skills?.length || 0} 个 Skill</div>\n </div>\n\n <div className=\"grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4\">\n {skills?.map((skill) => (\n <div\n key={skill.name}\n className=\"bg-white rounded-lg shadow p-5 hover:shadow-md transition-shadow cursor-pointer\"\n onClick={() => setSelectedSkill(skill.name)}\n >\n <div className=\"flex items-start gap-3\">\n <div className=\"w-10 h-10 rounded-lg bg-purple-100 flex items-center justify-center flex-shrink-0\">\n <BookOpen className=\"h-5 w-5 text-purple-600\" />\n </div>\n <div className=\"flex-1 min-w-0\">\n <h3 className=\"font-semibold text-gray-900 truncate\">{skill.name}</h3>\n <p className=\"text-xs text-gray-500 mt-1 line-clamp-3\">\n {skill.description || '(无描述)'}\n </p>\n </div>\n </div>\n </div>\n ))}\n </div>\n\n {/* Skill Detail Drawer */}\n <Drawer\n open={selectedSkill !== null}\n onClose={() => { setSelectedSkill(null); setEditing(false) }}\n title={`Skill: ${selectedSkill}`}\n width=\"w-[800px]\"\n >\n {detail && (\n <div className=\"space-y-4\">\n <div className=\"flex items-center gap-2 mb-2\">\n <BookOpen className=\"h-5 w-5 text-purple-600\" />\n <h3 className=\"text-lg font-semibold text-gray-900\">{detail.name}</h3>\n </div>\n\n <div>\n <div className=\"text-xs text-gray-500 mb-1\">描述</div>\n <div className=\"text-sm text-gray-800\">{detail.description}</div>\n </div>\n\n <div>\n <div className=\"flex items-center justify-between mb-2\">\n <div className=\"text-xs text-gray-500\">完整内容 (Markdown)</div>\n <div className=\"flex items-center gap-2\">\n {!editing ? (\n <button\n onClick={() => setEditing(true)}\n className=\"inline-flex items-center gap-1 text-xs text-indigo-600 hover:text-indigo-700\"\n >\n <Edit2 className=\"h-3 w-3\" />编辑\n </button>\n ) : (\n <>\n <button\n onClick={() => { setEditing(false); setEditContent(detail.content || '') }}\n className=\"inline-flex items-center gap-1 text-xs text-gray-600 hover:text-gray-700\"\n >\n <X className=\"h-3 w-3\" />取消\n </button>\n <button\n onClick={() => mutation.mutate({ name: detail.name, content: editContent })}\n disabled={mutation.isPending}\n className=\"inline-flex items-center gap-1 text-xs bg-indigo-600 text-white px-2 py-1 rounded hover:bg-indigo-700 disabled:bg-gray-400\"\n >\n <Save className=\"h-3 w-3\" />\n {mutation.isPending ? '保存中...' : '保存'}\n </button>\n </>\n )}\n </div>\n </div>\n {editing ? (\n <textarea\n value={editContent}\n onChange={(e) => setEditContent(e.target.value)}\n className=\"w-full font-mono text-xs bg-gray-50 rounded p-3 border border-gray-300 focus:border-indigo-500 focus:outline-none\"\n rows={20}\n />\n ) : (\n <div className=\"bg-white rounded p-3 border border-gray-200 max-h-[500px] overflow-y-auto\">\n <MarkdownRenderer content={detail.content || ''} />\n </div>\n )}\n {mutation.isError && (\n <div className=\"text-xs text-red-600 mt-1\">保存失败:{(mutation.error as Error).message}</div>\n )}\n </div>\n </div>\n )}\n </Drawer>\n </div>\n )\n}\n"],"names":["MarkdownRenderer","content","className","jsx","ReactMarkdown","remarkGfm","inline","children","props","match","lang","SyntaxHighlighter","oneLight","href","fetchSkills","res","data","fetchSkillDetail","name","saveSkill","authFetch","Skills","queryClient","useQueryClient","toast","useToast","skills","isLoading","useQuery","selectedSkill","setSelectedSkill","useState","editing","setEditing","editContent","setEditContent","detail","useEffect","mutation","useMutation","vars","e","jsxs","skill","BookOpen","Drawer","Fragment","X","Save","Edit2"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import{r as f,j as e}from"./react-vendor-CSp-GLFF.js";import{c as q,u as R,L as T}from"./react-router-r79dBVy4.js";import{u as W}from"./query-C99w429o.js";import{p as x}from"./time-Bxuk0M-C.js";import{d as m}from"./vendor-CMMjVdZs.js";import{n as A}from"./task-title-BhOcemuR.js";import{j as I,r as D,n as G,a as O,g as S,t as z,u as N,q as y,B as K,o as Q,F as U,h as E,v as J,s as V,f as X,i as Y,w as Z,m as ee}from"./lucide-Bs_edTLa.js";import{f as w}from"./date-fns-CZ_bHujz.js";function se(l,d="/tasks"){if(l!=null&&typeof l=="object"&&"from"in l){const a=l.from;if(typeof a=="string"&&a.length>0)return a}return d}async function te(l){const d=await fetch(`/api/tasks/${l}`);if(!d.ok)throw new Error("Failed to fetch task detail");const a=await d.json();return{...a.task,userPrompts:a.userPrompts??[],injections:a.injections??[],timeline:(a.timeline??[]).map((n,j)=>({id:`${n.timestamp}-${n.tool_name}-${j}`,timestamp:n.timestamp,tool_name:n.tool_name,hook_type:n.hook_type,input:n.input,output:n.output,is_agent_call:n.is_agent_call,agent_detail:n.agent_detail})),skillInvocations:a.skillInvocations??[],artifacts:a.artifacts??[]}}function ae(l){switch(l){case"Read":return e.jsx(ee,{className:"h-4 w-4 text-gray-500"});case"Edit":return e.jsx(Z,{className:"h-4 w-4 text-amber-600"});case"Write":return e.jsx(Y,{className:"h-4 w-4 text-green-600"});case"Bash":return e.jsx(E,{className:"h-4 w-4 text-orange-600"});case"Agent":case"Task":return e.jsx(X,{className:"h-4 w-4 text-blue-600"});case"Grep":case"Glob":return e.jsx(V,{className:"h-4 w-4 text-purple-500"});case"WebSearch":case"WebFetch":return e.jsx(J,{className:"h-4 w-4 text-cyan-600"});default:return e.jsx(E,{className:"h-4 w-4 text-gray-400"})}}function re(l,d){const a=x(l).getTime()-x(d).getTime();return a<1e3?"+0s":a<6e4?`+${Math.floor(a/1e3)}s`:a<36e5?`+${Math.floor(a/6e4)}m${Math.floor(a%6e4/1e3)}s`:`+${Math.floor(a/36e5)}h${Math.floor(a%36e5/6e4)}m`}function he(){var v;const{taskId:l}=q(),d=R(),a=se(d.state),[n,j]=f.useState(new Set),[M,C]=f.useState(new Set),[b,P]=f.useState(!0),{data:t,isLoading:$,error:h}=W({queryKey:["task-detail",l],queryFn:()=>te(l),enabled:!!l,refetchInterval:1e4});if($)return e.jsx("div",{className:"bg-white rounded-lg shadow p-6",children:e.jsx("p",{className:"text-gray-600",children:"加载中..."})});if(h||!t)return e.jsxs("div",{children:[e.jsxs(T,{to:a,className:"inline-flex items-center text-sm text-gray-500 hover:text-gray-700 mb-4",children:[e.jsx(I,{className:"h-4 w-4 mr-1"}),"返回"]}),e.jsx("div",{className:"bg-white rounded-lg shadow p-6",children:e.jsxs("p",{className:"text-red-600",children:["加载失败: ",(h==null?void 0:h.message)||"未知错误"]})})]});const F=s=>{j(i=>{const r=new Set(i);return r.has(s)?r.delete(s):r.add(s),r})},H=s=>{C(i=>{const r=new Set(i);return r.has(s)?r.delete(s):r.add(s),r})},L=t.end_time?`${Math.round((x(t.end_time).getTime()-x(t.start_time).getTime())/1e3)}s`:"进行中";return e.jsxs("div",{children:[e.jsxs(T,{to:a,className:"inline-flex items-center text-sm text-gray-500 hover:text-gray-700 mb-4",children:[e.jsx(I,{className:"h-4 w-4 mr-1"}),"返回任务列表"]}),e.jsxs("div",{className:"bg-white rounded-lg shadow p-6 mb-6",children:[e.jsxs("div",{className:"flex items-start justify-between mb-4",children:[e.jsx("h1",{className:"text-xl font-bold text-gray-900",children:A(t.title,(v=t.userPrompts[0])==null?void 0:v.content)}),e.jsxs("span",{className:m("px-2 py-1 text-xs font-medium rounded-full",t.status==="completed"&&"bg-green-100 text-green-700",t.status==="active"&&"bg-blue-100 text-blue-700",t.status==="abandoned"&&"bg-gray-100 text-gray-600"),children:[t.status==="completed"&&e.jsx(D,{className:"h-3 w-3 inline mr-1"}),t.status==="active"&&e.jsx(G,{className:"h-3 w-3 inline mr-1 animate-spin"}),t.status]})]}),e.jsxs("div",{className:"grid grid-cols-4 gap-4 text-sm",children:[e.jsxs("div",{children:[e.jsx("div",{className:"text-xs text-gray-500 mb-1",children:"开始时间"}),e.jsx("div",{className:"text-gray-900",children:w(x(t.start_time),"MM-dd HH:mm:ss")})]}),e.jsxs("div",{children:[e.jsx("div",{className:"text-xs text-gray-500 mb-1",children:"结束时间"}),e.jsx("div",{className:"text-gray-900",children:t.end_time?w(x(t.end_time),"MM-dd HH:mm:ss"):"-"})]}),e.jsxs("div",{children:[e.jsx("div",{className:"text-xs text-gray-500 mb-1",children:"持续时间"}),e.jsx("div",{className:"text-gray-900",children:L})]}),e.jsxs("div",{children:[e.jsx("div",{className:"text-xs text-gray-500 mb-1",children:"事件数"}),e.jsx("div",{className:"text-gray-900",children:t.event_count})]})]})]}),t.userPrompts.length>0&&e.jsxs("div",{className:"bg-white rounded-lg shadow p-6 mb-6",children:[e.jsxs("h2",{className:"text-base font-semibold text-gray-900 mb-4 flex items-center gap-2",children:[e.jsx(O,{className:"h-4 w-4 text-purple-500"}),"用户消息",e.jsx("span",{className:"text-xs text-gray-500 bg-gray-100 px-2 py-0.5 rounded-full",children:t.userPrompts.length})]}),e.jsx("div",{className:"space-y-3",children:t.userPrompts.map((s,i)=>e.jsxs("div",{className:"bg-purple-50 border border-purple-100 rounded-lg p-3",children:[e.jsx("div",{className:"text-xs text-gray-500 mb-1 font-mono",children:w(x(s.timestamp),"HH:mm:ss")}),e.jsx("div",{className:"text-sm text-gray-800 whitespace-pre-wrap break-all",children:s.content})]},i))})]}),t.userPrompts.length===0&&t.injections.length===0&&t.timeline.length===0&&t.skillInvocations.length===0&&t.artifacts.length===0&&e.jsxs("div",{className:"bg-white rounded-lg shadow p-12 text-center",children:[e.jsx(S,{className:"h-12 w-12 text-gray-300 mx-auto mb-3"}),e.jsx("p",{className:"text-sm text-gray-500",children:"该任务暂无可展示的执行内容"}),e.jsx("p",{className:"text-xs text-gray-400 mt-1",children:"事件可能仍在记录中,稍后刷新查看"})]}),t.injections.length>0&&e.jsxs("div",{className:"bg-white rounded-lg shadow mb-6",children:[e.jsxs("button",{onClick:()=>P(!b),className:"w-full flex items-center justify-between p-4 text-left hover:bg-gray-50 rounded-t-lg",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(z,{className:"h-4 w-4 text-gray-500"}),e.jsx("h2",{className:"text-base font-semibold text-gray-900",children:"注入内容"}),e.jsx("span",{className:"text-xs text-gray-500 bg-gray-100 px-2 py-0.5 rounded-full",children:t.injections.length})]}),b?e.jsx(N,{className:"h-4 w-4 text-gray-400"}):e.jsx(y,{className:"h-4 w-4 text-gray-400"})]}),b&&e.jsx("div",{className:"px-4 pb-4 space-y-2",children:t.injections.map(s=>e.jsxs("div",{className:"bg-gray-50 rounded-lg border border-gray-100",children:[e.jsxs("button",{onClick:()=>F(s.id),className:"w-full flex items-center justify-between p-3 text-left",children:[e.jsxs("div",{className:"flex items-center gap-2 text-sm",children:[e.jsx("span",{className:m("px-1.5 py-0.5 text-xs rounded font-mono",s.injection_type==="systemMessage"?"bg-blue-50 text-blue-700":"bg-amber-50 text-amber-700"),children:s.injection_type}),e.jsx("span",{className:"text-gray-600",children:s.source_handler})]}),n.has(s.id)?e.jsx(N,{className:"h-3 w-3 text-gray-400"}):e.jsx(y,{className:"h-3 w-3 text-gray-400"})]}),n.has(s.id)&&e.jsx("div",{className:"px-3 pb-3",children:e.jsx("pre",{className:"text-xs text-gray-700 bg-white border border-gray-200 rounded p-3 overflow-x-auto max-h-64 overflow-y-auto whitespace-pre-wrap",children:s.content})})]},s.id))})]}),t.timeline.length>0&&e.jsxs("div",{className:"bg-white rounded-lg shadow p-6 mb-6",children:[e.jsxs("h2",{className:"text-base font-semibold text-gray-900 mb-4 flex items-center gap-2",children:[e.jsx(S,{className:"h-4 w-4 text-gray-500"}),"执行时间线",e.jsx("span",{className:"text-xs text-gray-500 bg-gray-100 px-2 py-0.5 rounded-full",children:t.timeline.length})]}),e.jsxs("div",{className:"relative",children:[e.jsx("div",{className:"absolute left-[19px] top-2 bottom-2 w-px bg-gray-200"}),e.jsx("div",{className:"space-y-0",children:t.timeline.map((s,i)=>{var _,k;const r=s.is_agent_call,p=s.tool_name==="Edit"||s.tool_name==="Write",g=M.has(i),c=s.input,o=c==null?void 0:c.file_path,u=(c==null?void 0:c.description)||(c==null?void 0:c.command);return e.jsxs("div",{className:m("relative flex items-start gap-3 py-2 px-2 rounded-md cursor-pointer hover:bg-gray-50 transition-colors",r&&"bg-blue-50 hover:bg-blue-100"),onClick:()=>H(i),children:[e.jsx("div",{className:"relative z-10 flex-shrink-0 w-10 flex justify-center",children:e.jsx("div",{className:m("w-8 h-8 rounded-full flex items-center justify-center",r?"bg-blue-100":"bg-white border border-gray-200"),children:ae(s.tool_name)})}),e.jsxs("div",{className:"flex-1 min-w-0 pt-1",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:m("text-sm font-medium",r?"text-blue-700":"text-gray-900"),children:s.tool_name}),((_=s.agent_detail)==null?void 0:_.subagent_type)&&e.jsx("span",{className:"text-xs bg-blue-100 text-blue-700 px-1.5 py-0.5 rounded font-mono",children:s.agent_detail.subagent_type}),((k=s.agent_detail)==null?void 0:k.name)&&e.jsx("span",{className:"text-xs text-blue-600",children:s.agent_detail.name}),e.jsxs("span",{className:"text-xs text-gray-400 font-mono ml-auto flex items-center gap-1",children:[re(s.timestamp,t.start_time),g?e.jsx(N,{className:"h-3 w-3"}):e.jsx(y,{className:"h-3 w-3"})]})]}),!g&&p&&o&&e.jsx("p",{className:"text-xs text-green-700 font-mono mt-0.5 truncate",title:o,children:o}),!g&&!p&&u&&e.jsx("p",{className:"text-xs text-gray-500 mt-0.5 truncate",children:u}),g&&e.jsxs("div",{className:"mt-2 space-y-2 text-xs",onClick:B=>B.stopPropagation(),children:[r&&s.agent_detail&&e.jsxs("div",{className:"bg-blue-50 border border-blue-200 rounded-lg p-3 space-y-2",children:[s.agent_detail.subagent_type&&e.jsxs("div",{children:[e.jsx("span",{className:"text-blue-600 font-medium",children:"subagent_type: "}),e.jsx("span",{className:"font-mono text-blue-800",children:s.agent_detail.subagent_type})]}),s.agent_detail.name&&e.jsxs("div",{children:[e.jsx("span",{className:"text-blue-600 font-medium",children:"name: "}),e.jsx("span",{className:"font-mono text-blue-800",children:s.agent_detail.name})]}),s.agent_detail.prompt&&e.jsxs("div",{children:[e.jsx("span",{className:"text-blue-600 font-medium",children:"prompt:"}),e.jsx("pre",{className:"mt-1 p-2 bg-white rounded border border-blue-100 text-gray-800 whitespace-pre-wrap break-words max-h-60 overflow-y-auto",children:s.agent_detail.prompt})]})]}),p&&o&&e.jsxs("div",{className:"bg-green-50 border border-green-200 rounded-lg p-3",children:[e.jsx("span",{className:"text-green-700 font-medium",children:"file: "}),e.jsx("span",{className:"font-mono text-green-800",children:o})]}),!r&&u&&e.jsx("div",{className:"bg-gray-50 border border-gray-200 rounded-lg p-3",children:e.jsx("pre",{className:"text-gray-700 whitespace-pre-wrap break-words max-h-40 overflow-y-auto",children:u})}),!r&&!p&&o&&e.jsxs("div",{className:"text-gray-500",children:[e.jsx("span",{className:"font-medium",children:"path: "}),e.jsx("span",{className:"font-mono",children:o})]})]})]})]},s.id||i)})})]})]}),t.skillInvocations.length>0&&e.jsxs("div",{className:"bg-white rounded-lg shadow p-6 mb-6",children:[e.jsxs("h2",{className:"text-base font-semibold text-gray-900 mb-4 flex items-center gap-2",children:[e.jsx(K,{className:"h-4 w-4 text-purple-500"}),"Skill 调用",e.jsx("span",{className:"text-xs text-gray-500 bg-gray-100 px-2 py-0.5 rounded-full",children:t.skillInvocations.length})]}),e.jsx("div",{className:"space-y-3",children:t.skillInvocations.map(s=>e.jsxs("div",{className:"border border-purple-100 bg-purple-50 rounded-lg p-4",children:[e.jsxs("div",{className:"flex items-center gap-2 mb-2",children:[e.jsx("span",{className:"text-sm font-medium text-purple-800 font-mono",children:s.skill_id}),s.workflow&&e.jsx("span",{className:"text-xs bg-purple-100 text-purple-700 px-1.5 py-0.5 rounded",children:s.workflow}),s.phase&&e.jsxs("span",{className:"text-xs bg-purple-100 text-purple-700 px-1.5 py-0.5 rounded",children:["phase: ",s.phase]})]}),e.jsx("p",{className:"text-xs text-purple-700",children:s.reason})]},s.id))})]}),t.artifacts.length>0&&e.jsxs("div",{className:"bg-white rounded-lg shadow p-6 mb-6",children:[e.jsxs("h2",{className:"text-base font-semibold text-gray-900 mb-4 flex items-center gap-2",children:[e.jsx(Q,{className:"h-4 w-4 text-green-600"}),"产物",e.jsxs("span",{className:"text-xs text-gray-500 bg-gray-100 px-2 py-0.5 rounded-full",children:[t.artifacts.length," 个文件"]})]}),e.jsx("div",{className:"space-y-1",children:t.artifacts.map(s=>e.jsxs("div",{className:"flex items-center gap-2 py-1.5 px-3 rounded hover:bg-green-50",children:[e.jsx(U,{className:"h-4 w-4 text-green-600 flex-shrink-0"}),e.jsx("span",{className:"text-sm text-gray-800 font-mono truncate",title:s,children:s})]},s))})]})]})}export{he as default};
2
+ //# sourceMappingURL=TaskDetail-BS8pYhaR.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TaskDetail-BS8pYhaR.js","sources":["../../src/utils/navigation.ts","../../src/pages/TaskDetail.tsx"],"sourcesContent":["/**\n * Navigation helpers for react-router-based back-navigation with state preservation.\n */\n\n/**\n * Resolves the \"back\" URL from react-router navigation state.\n *\n * Usage in a detail page:\n * const location = useLocation()\n * const backTo = resolveBackTo(location.state)\n * // <Link to={backTo}>Back</Link>\n *\n * The navigation state is set by the list page when navigating forward:\n * navigate(`/tasks/${id}`, { state: { from: location.pathname + location.search } })\n *\n * @param state - location.state from react-router (typed as unknown for safety)\n * @param fallback - URL to use when state carries no valid `from` field (default: '/tasks')\n */\nexport function resolveBackTo(state: unknown, fallback = '/tasks'): string {\n if (state !== null && state !== undefined && typeof state === 'object' && 'from' in state) {\n const from = (state as { from?: unknown }).from\n if (typeof from === 'string' && from.length > 0) return from\n }\n return fallback\n}\n","import { useParams, Link, useLocation } from 'react-router-dom'\nimport { useQuery } from '@tanstack/react-query'\nimport { useState } from 'react'\nimport { format } from 'date-fns'\nimport { parseUTC } from '../utils/time'\nimport { resolveBackTo } from '../utils/navigation'\nimport {\n ArrowLeft,\n Clock,\n CheckCircle2,\n Loader2,\n ChevronDown,\n ChevronRight,\n FileText,\n Terminal,\n FileEdit,\n Bot,\n BookOpen,\n Syringe,\n FolderOpen,\n Eye,\n Pencil,\n Search,\n Globe,\n MessageSquare,\n} from 'lucide-react'\nimport clsx from 'clsx'\nimport { normalizeTaskTitle } from '../utils/task-title'\n\ninterface Injection {\n id: string\n injection_type: 'systemMessage' | 'additionalContext'\n source_handler: string\n content: string\n timestamp: string\n}\n\ninterface TimelineEvent {\n id: string\n timestamp: string\n tool_name: string\n hook_type: string\n input: unknown\n output: unknown\n is_agent_call: boolean\n agent_detail?: {\n subagent_type?: string\n name?: string\n prompt?: string\n }\n}\n\ninterface SkillInvocation {\n id: string\n skill_id: string\n reason: string\n workflow?: string\n phase?: string\n timestamp: string\n}\n\ninterface UserPrompt {\n timestamp: string\n content: string\n}\n\ninterface TaskDetailData {\n id: string\n title: string\n status: 'active' | 'completed' | 'abandoned'\n start_time: string\n end_time?: string\n event_count: number\n session_id: string\n userPrompts: UserPrompt[]\n injections: Injection[]\n timeline: TimelineEvent[]\n skillInvocations: SkillInvocation[]\n artifacts: string[]\n}\n\nasync function fetchTaskDetail(taskId: string): Promise<TaskDetailData> {\n const res = await fetch(`/api/tasks/${taskId}`)\n if (!res.ok) throw new Error('Failed to fetch task detail')\n const raw = await res.json()\n // API returns { task: {...}, injections, timeline, skillInvocations, artifacts }\n // Flatten task fields into top level for component consumption\n return {\n ...raw.task,\n userPrompts: raw.userPrompts ?? [],\n injections: raw.injections ?? [],\n timeline: (raw.timeline ?? []).map((e: any, idx: number) => ({\n id: `${e.timestamp}-${e.tool_name}-${idx}`,\n timestamp: e.timestamp,\n tool_name: e.tool_name,\n hook_type: e.hook_type,\n input: e.input,\n output: e.output,\n is_agent_call: e.is_agent_call,\n agent_detail: e.agent_detail,\n })),\n skillInvocations: raw.skillInvocations ?? [],\n artifacts: raw.artifacts ?? [],\n }\n}\n\nfunction getToolIcon(toolName: string) {\n switch (toolName) {\n case 'Read':\n return <Eye className=\"h-4 w-4 text-gray-500\" />\n case 'Edit':\n return <Pencil className=\"h-4 w-4 text-amber-600\" />\n case 'Write':\n return <FileEdit className=\"h-4 w-4 text-green-600\" />\n case 'Bash':\n return <Terminal className=\"h-4 w-4 text-orange-600\" />\n case 'Agent':\n case 'Task':\n return <Bot className=\"h-4 w-4 text-blue-600\" />\n case 'Grep':\n case 'Glob':\n return <Search className=\"h-4 w-4 text-purple-500\" />\n case 'WebSearch':\n case 'WebFetch':\n return <Globe className=\"h-4 w-4 text-cyan-600\" />\n default:\n return <Terminal className=\"h-4 w-4 text-gray-400\" />\n }\n}\n\nfunction getRelativeTime(eventTime: string, startTime: string): string {\n const diff = parseUTC(eventTime).getTime() - parseUTC(startTime).getTime()\n if (diff < 1000) return '+0s'\n if (diff < 60000) return `+${Math.floor(diff / 1000)}s`\n if (diff < 3600000) return `+${Math.floor(diff / 60000)}m${Math.floor((diff % 60000) / 1000)}s`\n return `+${Math.floor(diff / 3600000)}h${Math.floor((diff % 3600000) / 60000)}m`\n}\n\nexport default function TaskDetail() {\n const { taskId } = useParams<{ taskId: string }>()\n const location = useLocation()\n const backTo = resolveBackTo(location.state)\n const [expandedInjections, setExpandedInjections] = useState<Set<string>>(new Set())\n const [expandedEvents, setExpandedEvents] = useState<Set<number>>(new Set())\n const [showInjections, setShowInjections] = useState(true)\n\n const { data, isLoading, error } = useQuery({\n queryKey: ['task-detail', taskId],\n queryFn: () => fetchTaskDetail(taskId!),\n enabled: !!taskId,\n refetchInterval: 10000,\n })\n\n if (isLoading) {\n return (\n <div className=\"bg-white rounded-lg shadow p-6\">\n <p className=\"text-gray-600\">加载中...</p>\n </div>\n )\n }\n\n if (error || !data) {\n return (\n <div>\n <Link to={backTo} className=\"inline-flex items-center text-sm text-gray-500 hover:text-gray-700 mb-4\">\n <ArrowLeft className=\"h-4 w-4 mr-1\" />返回\n </Link>\n <div className=\"bg-white rounded-lg shadow p-6\">\n <p className=\"text-red-600\">加载失败: {(error as Error)?.message || '未知错误'}</p>\n </div>\n </div>\n )\n }\n\n const toggleInjection = (id: string) => {\n setExpandedInjections(prev => {\n const next = new Set(prev)\n if (next.has(id)) next.delete(id)\n else next.add(id)\n return next\n })\n }\n\n const toggleEvent = (idx: number) => {\n setExpandedEvents(prev => {\n const next = new Set(prev)\n if (next.has(idx)) next.delete(idx)\n else next.add(idx)\n return next\n })\n }\n\n const duration = data.end_time\n ? `${Math.round((parseUTC(data.end_time).getTime() - parseUTC(data.start_time).getTime()) / 1000)}s`\n : '进行中'\n\n return (\n <div>\n <Link to={backTo} className=\"inline-flex items-center text-sm text-gray-500 hover:text-gray-700 mb-4\">\n <ArrowLeft className=\"h-4 w-4 mr-1\" />返回任务列表\n </Link>\n\n {/* 区域 1:任务概览 */}\n <div className=\"bg-white rounded-lg shadow p-6 mb-6\">\n <div className=\"flex items-start justify-between mb-4\">\n <h1 className=\"text-xl font-bold text-gray-900\">{normalizeTaskTitle(data.title, data.userPrompts[0]?.content)}</h1>\n <span className={clsx(\n 'px-2 py-1 text-xs font-medium rounded-full',\n data.status === 'completed' && 'bg-green-100 text-green-700',\n data.status === 'active' && 'bg-blue-100 text-blue-700',\n data.status === 'abandoned' && 'bg-gray-100 text-gray-600'\n )}>\n {data.status === 'completed' && <CheckCircle2 className=\"h-3 w-3 inline mr-1\" />}\n {data.status === 'active' && <Loader2 className=\"h-3 w-3 inline mr-1 animate-spin\" />}\n {data.status}\n </span>\n </div>\n <div className=\"grid grid-cols-4 gap-4 text-sm\">\n <div>\n <div className=\"text-xs text-gray-500 mb-1\">开始时间</div>\n <div className=\"text-gray-900\">\n {format(parseUTC(data.start_time), 'MM-dd HH:mm:ss')}\n </div>\n </div>\n <div>\n <div className=\"text-xs text-gray-500 mb-1\">结束时间</div>\n <div className=\"text-gray-900\">\n {data.end_time ? format(parseUTC(data.end_time), 'MM-dd HH:mm:ss') : '-'}\n </div>\n </div>\n <div>\n <div className=\"text-xs text-gray-500 mb-1\">持续时间</div>\n <div className=\"text-gray-900\">{duration}</div>\n </div>\n <div>\n <div className=\"text-xs text-gray-500 mb-1\">事件数</div>\n <div className=\"text-gray-900\">{data.event_count}</div>\n </div>\n </div>\n </div>\n\n {/* 区域 1.5:用户消息 */}\n {data.userPrompts.length > 0 && (\n <div className=\"bg-white rounded-lg shadow p-6 mb-6\">\n <h2 className=\"text-base font-semibold text-gray-900 mb-4 flex items-center gap-2\">\n <MessageSquare className=\"h-4 w-4 text-purple-500\" />\n 用户消息\n <span className=\"text-xs text-gray-500 bg-gray-100 px-2 py-0.5 rounded-full\">\n {data.userPrompts.length}\n </span>\n </h2>\n <div className=\"space-y-3\">\n {data.userPrompts.map((up, idx) => (\n <div key={idx} className=\"bg-purple-50 border border-purple-100 rounded-lg p-3\">\n <div className=\"text-xs text-gray-500 mb-1 font-mono\">\n {format(parseUTC(up.timestamp), 'HH:mm:ss')}\n </div>\n <div className=\"text-sm text-gray-800 whitespace-pre-wrap break-all\">{up.content}</div>\n </div>\n ))}\n </div>\n </div>\n )}\n\n {/* 空状态:所有详情区块都为空时的兜底提示 */}\n {data.userPrompts.length === 0 &&\n data.injections.length === 0 &&\n data.timeline.length === 0 &&\n data.skillInvocations.length === 0 &&\n data.artifacts.length === 0 && (\n <div className=\"bg-white rounded-lg shadow p-12 text-center\">\n <Clock className=\"h-12 w-12 text-gray-300 mx-auto mb-3\" />\n <p className=\"text-sm text-gray-500\">该任务暂无可展示的执行内容</p>\n <p className=\"text-xs text-gray-400 mt-1\">事件可能仍在记录中,稍后刷新查看</p>\n </div>\n )}\n\n {/* 区域 2:注入内容 */}\n {data.injections.length > 0 && (\n <div className=\"bg-white rounded-lg shadow mb-6\">\n <button\n onClick={() => setShowInjections(!showInjections)}\n className=\"w-full flex items-center justify-between p-4 text-left hover:bg-gray-50 rounded-t-lg\"\n >\n <div className=\"flex items-center gap-2\">\n <Syringe className=\"h-4 w-4 text-gray-500\" />\n <h2 className=\"text-base font-semibold text-gray-900\">注入内容</h2>\n <span className=\"text-xs text-gray-500 bg-gray-100 px-2 py-0.5 rounded-full\">\n {data.injections.length}\n </span>\n </div>\n {showInjections ? <ChevronDown className=\"h-4 w-4 text-gray-400\" /> : <ChevronRight className=\"h-4 w-4 text-gray-400\" />}\n </button>\n {showInjections && (\n <div className=\"px-4 pb-4 space-y-2\">\n {data.injections.map((inj) => (\n <div key={inj.id} className=\"bg-gray-50 rounded-lg border border-gray-100\">\n <button\n onClick={() => toggleInjection(inj.id)}\n className=\"w-full flex items-center justify-between p-3 text-left\"\n >\n <div className=\"flex items-center gap-2 text-sm\">\n <span className={clsx(\n 'px-1.5 py-0.5 text-xs rounded font-mono',\n inj.injection_type === 'systemMessage' ? 'bg-blue-50 text-blue-700' : 'bg-amber-50 text-amber-700'\n )}>\n {inj.injection_type}\n </span>\n <span className=\"text-gray-600\">{inj.source_handler}</span>\n </div>\n {expandedInjections.has(inj.id) ? <ChevronDown className=\"h-3 w-3 text-gray-400\" /> : <ChevronRight className=\"h-3 w-3 text-gray-400\" />}\n </button>\n {expandedInjections.has(inj.id) && (\n <div className=\"px-3 pb-3\">\n <pre className=\"text-xs text-gray-700 bg-white border border-gray-200 rounded p-3 overflow-x-auto max-h-64 overflow-y-auto whitespace-pre-wrap\">\n {inj.content}\n </pre>\n </div>\n )}\n </div>\n ))}\n </div>\n )}\n </div>\n )}\n\n {/* 区域 3:执行时间线 */}\n {data.timeline.length > 0 && (\n <div className=\"bg-white rounded-lg shadow p-6 mb-6\">\n <h2 className=\"text-base font-semibold text-gray-900 mb-4 flex items-center gap-2\">\n <Clock className=\"h-4 w-4 text-gray-500\" />\n 执行时间线\n <span className=\"text-xs text-gray-500 bg-gray-100 px-2 py-0.5 rounded-full\">\n {data.timeline.length}\n </span>\n </h2>\n <div className=\"relative\">\n {/* 竖线 */}\n <div className=\"absolute left-[19px] top-2 bottom-2 w-px bg-gray-200\" />\n <div className=\"space-y-0\">\n {data.timeline.map((event, idx) => {\n const isAgent = event.is_agent_call\n const isFileOp = event.tool_name === 'Edit' || event.tool_name === 'Write'\n const isExpanded = expandedEvents.has(idx)\n const input = event.input as Record<string, unknown> | null\n const filePath = input?.file_path as string | undefined\n const description = (input?.description || input?.command) as string | undefined\n\n return (\n <div key={event.id || idx} className={clsx(\n 'relative flex items-start gap-3 py-2 px-2 rounded-md cursor-pointer hover:bg-gray-50 transition-colors',\n isAgent && 'bg-blue-50 hover:bg-blue-100',\n )}\n onClick={() => toggleEvent(idx)}\n >\n <div className=\"relative z-10 flex-shrink-0 w-10 flex justify-center\">\n <div className={clsx(\n 'w-8 h-8 rounded-full flex items-center justify-center',\n isAgent ? 'bg-blue-100' : 'bg-white border border-gray-200'\n )}>\n {getToolIcon(event.tool_name)}\n </div>\n </div>\n <div className=\"flex-1 min-w-0 pt-1\">\n <div className=\"flex items-center gap-2\">\n <span className={clsx(\n 'text-sm font-medium',\n isAgent ? 'text-blue-700' : 'text-gray-900'\n )}>\n {event.tool_name}\n </span>\n {event.agent_detail?.subagent_type && (\n <span className=\"text-xs bg-blue-100 text-blue-700 px-1.5 py-0.5 rounded font-mono\">\n {event.agent_detail.subagent_type}\n </span>\n )}\n {event.agent_detail?.name && (\n <span className=\"text-xs text-blue-600\">\n {event.agent_detail.name}\n </span>\n )}\n <span className=\"text-xs text-gray-400 font-mono ml-auto flex items-center gap-1\">\n {getRelativeTime(event.timestamp, data.start_time)}\n {isExpanded ? <ChevronDown className=\"h-3 w-3\" /> : <ChevronRight className=\"h-3 w-3\" />}\n </span>\n </div>\n {!isExpanded && isFileOp && filePath && (\n <p className=\"text-xs text-green-700 font-mono mt-0.5 truncate\" title={filePath}>\n {filePath}\n </p>\n )}\n {!isExpanded && !isFileOp && description && (\n <p className=\"text-xs text-gray-500 mt-0.5 truncate\">{description}</p>\n )}\n {/* 展开的详细内容 */}\n {isExpanded && (\n <div className=\"mt-2 space-y-2 text-xs\" onClick={e => e.stopPropagation()}>\n {/* Agent 调用详情 */}\n {isAgent && event.agent_detail && (\n <div className=\"bg-blue-50 border border-blue-200 rounded-lg p-3 space-y-2\">\n {event.agent_detail.subagent_type && (\n <div>\n <span className=\"text-blue-600 font-medium\">subagent_type: </span>\n <span className=\"font-mono text-blue-800\">{event.agent_detail.subagent_type}</span>\n </div>\n )}\n {event.agent_detail.name && (\n <div>\n <span className=\"text-blue-600 font-medium\">name: </span>\n <span className=\"font-mono text-blue-800\">{event.agent_detail.name}</span>\n </div>\n )}\n {event.agent_detail.prompt && (\n <div>\n <span className=\"text-blue-600 font-medium\">prompt:</span>\n <pre className=\"mt-1 p-2 bg-white rounded border border-blue-100 text-gray-800 whitespace-pre-wrap break-words max-h-60 overflow-y-auto\">\n {event.agent_detail.prompt}\n </pre>\n </div>\n )}\n </div>\n )}\n {/* 文件操作详情 */}\n {isFileOp && filePath && (\n <div className=\"bg-green-50 border border-green-200 rounded-lg p-3\">\n <span className=\"text-green-700 font-medium\">file: </span>\n <span className=\"font-mono text-green-800\">{filePath}</span>\n </div>\n )}\n {/* 通用工具详情 */}\n {!isAgent && description && (\n <div className=\"bg-gray-50 border border-gray-200 rounded-lg p-3\">\n <pre className=\"text-gray-700 whitespace-pre-wrap break-words max-h-40 overflow-y-auto\">\n {description}\n </pre>\n </div>\n )}\n {/* 文件路径(非文件操作工具,如 Read) */}\n {!isAgent && !isFileOp && filePath && (\n <div className=\"text-gray-500\">\n <span className=\"font-medium\">path: </span>\n <span className=\"font-mono\">{filePath}</span>\n </div>\n )}\n </div>\n )}\n </div>\n </div>\n )\n })}\n </div>\n </div>\n </div>\n )}\n\n {/* 区域 4:Skill 调用 */}\n {data.skillInvocations.length > 0 && (\n <div className=\"bg-white rounded-lg shadow p-6 mb-6\">\n <h2 className=\"text-base font-semibold text-gray-900 mb-4 flex items-center gap-2\">\n <BookOpen className=\"h-4 w-4 text-purple-500\" />\n Skill 调用\n <span className=\"text-xs text-gray-500 bg-gray-100 px-2 py-0.5 rounded-full\">\n {data.skillInvocations.length}\n </span>\n </h2>\n <div className=\"space-y-3\">\n {data.skillInvocations.map((skill) => (\n <div key={skill.id} className=\"border border-purple-100 bg-purple-50 rounded-lg p-4\">\n <div className=\"flex items-center gap-2 mb-2\">\n <span className=\"text-sm font-medium text-purple-800 font-mono\">\n {skill.skill_id}\n </span>\n {skill.workflow && (\n <span className=\"text-xs bg-purple-100 text-purple-700 px-1.5 py-0.5 rounded\">\n {skill.workflow}\n </span>\n )}\n {skill.phase && (\n <span className=\"text-xs bg-purple-100 text-purple-700 px-1.5 py-0.5 rounded\">\n phase: {skill.phase}\n </span>\n )}\n </div>\n <p className=\"text-xs text-purple-700\">{skill.reason}</p>\n </div>\n ))}\n </div>\n </div>\n )}\n\n {/* 区域 5:产物 */}\n {data.artifacts.length > 0 && (\n <div className=\"bg-white rounded-lg shadow p-6 mb-6\">\n <h2 className=\"text-base font-semibold text-gray-900 mb-4 flex items-center gap-2\">\n <FolderOpen className=\"h-4 w-4 text-green-600\" />\n 产物\n <span className=\"text-xs text-gray-500 bg-gray-100 px-2 py-0.5 rounded-full\">\n {data.artifacts.length} 个文件\n </span>\n </h2>\n <div className=\"space-y-1\">\n {data.artifacts.map((filePath) => (\n <div key={filePath} className=\"flex items-center gap-2 py-1.5 px-3 rounded hover:bg-green-50\">\n <FileText className=\"h-4 w-4 text-green-600 flex-shrink-0\" />\n <span className=\"text-sm text-gray-800 font-mono truncate\" title={filePath}>\n {filePath}\n </span>\n </div>\n ))}\n </div>\n </div>\n )}\n </div>\n )\n}\n"],"names":["resolveBackTo","state","fallback","from","fetchTaskDetail","taskId","res","raw","e","idx","getToolIcon","toolName","jsx","Eye","Pencil","FileEdit","Terminal","Bot","Search","Globe","getRelativeTime","eventTime","startTime","diff","parseUTC","TaskDetail","useParams","location","useLocation","backTo","expandedInjections","setExpandedInjections","useState","expandedEvents","setExpandedEvents","showInjections","setShowInjections","data","isLoading","error","useQuery","jsxs","Link","ArrowLeft","toggleInjection","id","prev","next","toggleEvent","duration","normalizeTaskTitle","_a","clsx","CheckCircle2","Loader2","format","MessageSquare","up","Clock","Syringe","ChevronDown","ChevronRight","inj","event","isAgent","isFileOp","isExpanded","input","filePath","description","_b","BookOpen","skill","FolderOpen","FileText"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import{r as v,j as t}from"./react-vendor-CSp-GLFF.js";import{u as D}from"./query-C99w429o.js";import{b as Z,u as B,d as Q}from"./react-router-r79dBVy4.js";import{p as V}from"./time-Bxuk0M-C.js";import{S as H}from"./SearchInput-qCj_jAcf.js";import{d as u}from"./vendor-CMMjVdZs.js";import{n as J}from"./task-title-BhOcemuR.js";import{o as W,A as F,g as X,p as Y,q as ee,n as te,r as se}from"./lucide-Bs_edTLa.js";import{a as ae,z as re}from"./date-fns-CZ_bHujz.js";const A=[20,50,100],ne=50;function oe(s){const a=Date.now();return s==="1h"?new Date(a-36e5).toISOString():s==="24h"?new Date(a-864e5).toISOString():s==="7d"?new Date(a-7*864e5).toISOString():""}async function ie(s){const a=await fetch(`/api/tasks?${s.toString()}`);if(!a.ok)throw new Error("Failed to fetch tasks");return a.json()}async function ce(){const s=await fetch("/api/tasks/projects");if(!s.ok)throw new Error("Failed to fetch projects");return s.json()}function I(s){const a=s.replace(/\\/g,"/").split("/").filter(Boolean);return a.length<=2?s:"…/"+a.slice(-2).join("/")}function be(){const s=Z(),a=B(),[i,f]=Q(),l=Math.max(1,Number(i.get("page")??"1")),d=A.includes(Number(i.get("size")??""))?Number(i.get("size")):ne,r=i.getAll("project"),o=i.get("preset")??"",z=i.get("from")??"",L=i.get("to")??"",m=i.get("search")??"",[O,b]=v.useState(!1),x=v.useCallback(e=>{f(h=>{const c=new URLSearchParams(h);for(const[p,g]of Object.entries(e))g===null||g===""?c.delete(p):Array.isArray(g)?(c.delete(p),g.forEach(K=>c.append(p,K))):c.set(p,g);return c},{replace:!0})},[f]),j=o&&o!=="custom"?oe(o):z,y=o&&o!=="custom"?"":L,S=v.useMemo(()=>{const e=new URLSearchParams;return e.set("limit",String(d)),e.set("offset",String((l-1)*d)),r.forEach(h=>e.append("project",h)),j&&e.set("from",j),y&&e.set("to",y),m&&e.set("search",m),e},[l,d,r,j,y,m]),{data:n,isLoading:w,error:C}=D({queryKey:["tasks",S.toString()],queryFn:()=>ie(S),refetchInterval:15e3,placeholderData:e=>e}),{data:P=[]}=D({queryKey:["task-projects"],queryFn:ce,staleTime:6e4}),k=(n==null?void 0:n.items)??[],N=(n==null?void 0:n.total)??0,E=(n==null?void 0:n.has_more)??!1,_=Math.ceil(N/d)||1,q=e=>{x({search:e||null,page:"1"})},M=e=>{const h=r.includes(e)?r.filter(c=>c!==e):[...r,e];x({project:h.length?h:null,page:"1"})},R=()=>x({project:null,page:"1"}),U=e=>{x({preset:e||null,from:null,to:null,page:"1"})},$=e=>{x({size:String(e),page:"1"})},T=e=>{x({page:String(Math.max(1,Math.min(e,_)))})},G=e=>{switch(e){case"completed":return t.jsx(se,{className:"h-4 w-4 text-green-600"});case"active":return t.jsx(te,{className:"h-4 w-4 text-blue-600 animate-spin"});default:return t.jsx(F,{className:"h-4 w-4 text-gray-400"})}};return w&&!n?t.jsxs("div",{children:[t.jsx("h1",{className:"text-2xl font-bold text-gray-900 mb-6",children:"任务"}),t.jsx("div",{className:"bg-white rounded-lg shadow p-6",children:t.jsx("p",{className:"text-gray-600",children:"加载中..."})})]}):C?t.jsxs("div",{children:[t.jsx("h1",{className:"text-2xl font-bold text-gray-900 mb-6",children:"任务"}),t.jsx("div",{className:"bg-white rounded-lg shadow p-6",children:t.jsxs("p",{className:"text-red-600",children:["加载失败: ",C.message]})})]}):t.jsxs("div",{children:[t.jsxs("div",{className:"flex items-center justify-between mb-4 flex-wrap gap-3",children:[t.jsx("h1",{className:"text-2xl font-bold text-gray-900",children:"任务"}),t.jsx(H,{value:m,onChange:q,placeholder:"搜索任务标题...",className:"w-64"})]}),t.jsxs("div",{className:"flex flex-wrap items-center gap-2 mb-4",children:[["1h","24h","7d"].map(e=>t.jsx("button",{onClick:()=>U(o===e?"":e),className:u("px-3 py-1.5 text-xs font-medium rounded-md border transition-colors",o===e?"bg-indigo-600 text-white border-indigo-600":"bg-white text-gray-700 border-gray-300 hover:bg-gray-50"),children:e==="1h"?"近 1 小时":e==="24h"?"近 24 小时":"近 7 天"},e)),P.length>0&&t.jsxs("div",{className:"relative",children:[t.jsxs("button",{onClick:()=>b(e=>!e),className:u("inline-flex items-center gap-1.5 px-3 py-1.5 text-xs font-medium rounded-md border transition-colors",r.length>0?"bg-indigo-50 text-indigo-700 border-indigo-300":"bg-white text-gray-700 border-gray-300 hover:bg-gray-50"),children:[t.jsx(W,{className:"h-3.5 w-3.5"}),r.length>0?`项目 (${r.length})`:"所有项目"]}),O&&t.jsxs(t.Fragment,{children:[t.jsx("div",{className:"fixed inset-0 z-10",onClick:()=>b(!1)}),t.jsxs("div",{className:"absolute left-0 mt-1 w-72 bg-white border border-gray-200 rounded-md shadow-lg z-20 max-h-64 overflow-y-auto",children:[r.length>0&&t.jsx("button",{onClick:()=>{R(),b(!1)},className:"w-full text-left px-3 py-2 text-xs text-indigo-600 hover:bg-indigo-50 border-b border-gray-100",children:"清除筛选"}),P.map(e=>t.jsxs("label",{className:"flex items-center gap-2 px-3 py-2 text-sm text-gray-700 hover:bg-gray-50 cursor-pointer",children:[t.jsx("input",{type:"checkbox",className:"rounded text-indigo-600",checked:r.includes(e),onChange:()=>M(e)}),t.jsx("span",{className:"truncate font-mono text-xs",title:e,children:I(e)})]},e))]})]})]}),(r.length>0||o||m)&&t.jsx("button",{onClick:()=>f({},{replace:!0}),className:"px-2 py-1.5 text-xs text-gray-500 hover:text-gray-700 underline",children:"清除所有筛选"})]}),t.jsxs("div",{className:"flex items-center justify-between mb-3 text-sm text-gray-500",children:[t.jsxs("span",{children:["共 ",t.jsx("span",{className:"font-semibold text-gray-900",children:N})," 条",w&&t.jsx("span",{className:"ml-2 text-xs text-indigo-500",children:"刷新中..."})]}),t.jsxs("div",{className:"flex items-center gap-2",children:[t.jsx("span",{className:"text-xs",children:"每页"}),A.map(e=>t.jsx("button",{onClick:()=>$(e),className:u("px-2 py-0.5 text-xs rounded border",d===e?"bg-indigo-600 text-white border-indigo-600":"bg-white text-gray-600 border-gray-300 hover:bg-gray-50"),children:e},e))]})]}),t.jsxs("div",{className:"grid gap-4",children:[k.map(e=>t.jsxs("div",{onClick:()=>s(`/tasks/${e.id}`,{state:{from:a.pathname+a.search}}),className:"bg-white rounded-lg shadow hover:shadow-md transition-shadow cursor-pointer p-5",children:[t.jsxs("div",{className:"flex items-start justify-between mb-3",children:[t.jsxs("div",{className:"flex items-start gap-3 flex-1 min-w-0",children:[t.jsx("div",{className:"mt-0.5 flex-shrink-0",children:G(e.status)}),t.jsxs("div",{className:"flex-1 min-w-0",children:[t.jsx("h3",{className:"text-base font-semibold text-gray-900 mb-1 truncate",children:J(e.title,e.first_prompt)}),e.project_path&&t.jsx("p",{className:"text-xs text-gray-400 font-mono truncate",title:e.project_path,children:I(e.project_path)})]})]}),t.jsx("span",{className:u("ml-3 flex-shrink-0 px-2 py-1 text-xs font-medium rounded-full whitespace-nowrap",e.status==="completed"&&"bg-green-100 text-green-700",e.status==="active"&&"bg-blue-100 text-blue-700",e.status==="abandoned"&&"bg-gray-100 text-gray-600"),children:e.status})]}),t.jsxs("div",{className:"flex items-center gap-6 text-sm text-gray-600",children:[t.jsxs("span",{className:"inline-flex items-center gap-1",children:[t.jsx(F,{className:"h-4 w-4"}),e.event_count," 个事件"]}),t.jsxs("span",{className:"inline-flex items-center gap-1",children:[t.jsx(X,{className:"h-4 w-4"}),e.start_time?ae(V(e.start_time),{addSuffix:!0,locale:re}):"-"]})]})]},e.id)),k.length===0&&!w&&t.jsx("div",{className:"bg-white rounded-lg shadow p-12 text-center text-gray-500",children:m||r.length>0||o?"无匹配结果":"暂无任务记录"})]}),N>d&&t.jsxs("div",{className:"flex items-center justify-between mt-6",children:[t.jsxs("button",{onClick:()=>T(l-1),disabled:l<=1,className:"inline-flex items-center gap-1 px-3 py-1.5 text-sm border rounded-md bg-white hover:bg-gray-50 disabled:opacity-40 disabled:cursor-not-allowed",children:[t.jsx(Y,{className:"h-4 w-4"}),"上一页"]}),t.jsxs("span",{className:"text-sm text-gray-500",children:["第 ",l," / ",_," 页",E?"":"(已到末页)"]}),t.jsxs("button",{onClick:()=>T(l+1),disabled:!E,className:"inline-flex items-center gap-1 px-3 py-1.5 text-sm border rounded-md bg-white hover:bg-gray-50 disabled:opacity-40 disabled:cursor-not-allowed",children:["下一页",t.jsx(ee,{className:"h-4 w-4"})]})]})]})}export{be as default};
2
+ //# sourceMappingURL=Tasks-CyuhizG8.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Tasks-CyuhizG8.js","sources":["../../src/pages/Tasks.tsx"],"sourcesContent":["import { useQuery } from '@tanstack/react-query'\nimport { useState, useMemo, useCallback } from 'react'\nimport { useNavigate, useSearchParams, useLocation } from 'react-router-dom'\nimport { formatDistanceToNow } from 'date-fns'\nimport { parseUTC } from '../utils/time'\nimport { zhCN } from 'date-fns/locale'\nimport {\n Clock,\n Activity,\n CheckCircle2,\n Loader2,\n ChevronLeft,\n ChevronRight,\n FolderOpen,\n} from 'lucide-react'\nimport SearchInput from '../components/SearchInput'\nimport clsx from 'clsx'\nimport { normalizeTaskTitle } from '../utils/task-title'\n\n// ── Types ────────────────────────────────────────────────────────────────────\n\ninterface Task {\n id: string\n title: string\n status: 'active' | 'completed' | 'abandoned'\n start_time: string\n end_time?: string\n event_count: number\n session_id: string\n project_path?: string\n first_prompt?: string | null\n}\n\ninterface TaskPage {\n items: Task[]\n total: number\n has_more: boolean\n}\n\n// ── Constants ─────────────────────────────────────────────────────────────────\n\nconst PAGE_SIZES = [20, 50, 100] as const\nconst DEFAULT_PAGE_SIZE = 50\n\ntype TimePreset = '1h' | '24h' | '7d' | 'custom' | ''\n\nfunction presetToFrom(preset: TimePreset): string {\n const now = Date.now()\n if (preset === '1h') return new Date(now - 3600_000).toISOString()\n if (preset === '24h') return new Date(now - 86_400_000).toISOString()\n if (preset === '7d') return new Date(now - 7 * 86_400_000).toISOString()\n return ''\n}\n\n// ── Fetch ─────────────────────────────────────────────────────────────────────\n\nasync function fetchTasks(params: URLSearchParams): Promise<TaskPage> {\n const res = await fetch(`/api/tasks?${params.toString()}`)\n if (!res.ok) throw new Error('Failed to fetch tasks')\n return res.json() as Promise<TaskPage>\n}\n\nasync function fetchProjects(): Promise<string[]> {\n const res = await fetch('/api/tasks/projects')\n if (!res.ok) throw new Error('Failed to fetch projects')\n return res.json() as Promise<string[]>\n}\n\n// ── Helpers ───────────────────────────────────────────────────────────────────\n\nfunction shortPath(p: string): string {\n const parts = p.replace(/\\\\/g, '/').split('/').filter(Boolean)\n if (parts.length <= 2) return p\n return '…/' + parts.slice(-2).join('/')\n}\n\nexport default function Tasks() {\n const navigate = useNavigate()\n const location = useLocation()\n const [searchParams, setSearchParams] = useSearchParams()\n\n // ── URL-synced state ──────────────────────────────────────────────────────\n const page = Math.max(1, Number(searchParams.get('page') ?? '1'))\n const pageSize = (PAGE_SIZES as readonly number[]).includes(Number(searchParams.get('size') ?? ''))\n ? Number(searchParams.get('size'))\n : DEFAULT_PAGE_SIZE\n const selectedProjects = searchParams.getAll('project')\n const timePreset = (searchParams.get('preset') ?? '') as TimePreset\n const fromParam = searchParams.get('from') ?? ''\n const toParam = searchParams.get('to') ?? ''\n const searchVal = searchParams.get('search') ?? ''\n\n // ── Local state for project dropdown ─────────────────────────────────────\n const [projectDropdownOpen, setProjectDropdownOpen] = useState(false)\n\n // ── Patch URL helper ──────────────────────────────────────────────────────\n const patchSearch = useCallback((patch: Record<string, string | string[] | null>) => {\n setSearchParams(prev => {\n const next = new URLSearchParams(prev)\n for (const [k, v] of Object.entries(patch)) {\n if (v === null || v === '') {\n next.delete(k)\n } else if (Array.isArray(v)) {\n next.delete(k)\n v.forEach(val => next.append(k, val))\n } else {\n next.set(k, v)\n }\n }\n return next\n }, { replace: true })\n }, [setSearchParams])\n\n // ── Compute effective from/to ─────────────────────────────────────────────\n const effectiveFrom = timePreset && timePreset !== 'custom' ? presetToFrom(timePreset) : fromParam\n const effectiveTo = timePreset && timePreset !== 'custom' ? '' : toParam\n\n // ── Build query params for /api/tasks ────────────────────────────────────\n const queryParams = useMemo(() => {\n const p = new URLSearchParams()\n p.set('limit', String(pageSize))\n p.set('offset', String((page - 1) * pageSize))\n selectedProjects.forEach(pr => p.append('project', pr))\n if (effectiveFrom) p.set('from', effectiveFrom)\n if (effectiveTo) p.set('to', effectiveTo)\n if (searchVal) p.set('search', searchVal)\n return p\n }, [page, pageSize, selectedProjects, effectiveFrom, effectiveTo, searchVal])\n\n // ── Queries ───────────────────────────────────────────────────────────────\n const { data, isLoading, error } = useQuery<TaskPage>({\n queryKey: ['tasks', queryParams.toString()],\n queryFn: () => fetchTasks(queryParams),\n refetchInterval: 15_000,\n placeholderData: prev => prev,\n })\n\n const { data: projects = [] } = useQuery<string[]>({\n queryKey: ['task-projects'],\n queryFn: fetchProjects,\n staleTime: 60_000,\n })\n\n const tasks = data?.items ?? []\n const total = data?.total ?? 0\n const hasMore = data?.has_more ?? false\n const totalPages = Math.ceil(total / pageSize) || 1\n\n // ── Event handlers ────────────────────────────────────────────────────────\n const handleSearchChange = (val: string) => {\n patchSearch({ search: val || null, page: '1' })\n }\n\n const toggleProject = (proj: string) => {\n const next = selectedProjects.includes(proj)\n ? selectedProjects.filter(p => p !== proj)\n : [...selectedProjects, proj]\n patchSearch({ project: next.length ? next : null, page: '1' })\n }\n\n const clearProjects = () => patchSearch({ project: null, page: '1' })\n\n const handlePreset = (preset: TimePreset) => {\n patchSearch({ preset: preset || null, from: null, to: null, page: '1' })\n }\n\n const handlePageSize = (size: number) => {\n patchSearch({ size: String(size), page: '1' })\n }\n\n const goPage = (p: number) => {\n patchSearch({ page: String(Math.max(1, Math.min(p, totalPages))) })\n }\n\n // ── Status icon ───────────────────────────────────────────────────────────\n const getStatusIcon = (status: string) => {\n switch (status) {\n case 'completed':\n return <CheckCircle2 className=\"h-4 w-4 text-green-600\" />\n case 'active':\n return <Loader2 className=\"h-4 w-4 text-blue-600 animate-spin\" />\n default:\n return <Activity className=\"h-4 w-4 text-gray-400\" />\n }\n }\n\n // ── Loading / error states ────────────────────────────────────────────────\n if (isLoading && !data) {\n return (\n <div>\n <h1 className=\"text-2xl font-bold text-gray-900 mb-6\">任务</h1>\n <div className=\"bg-white rounded-lg shadow p-6\">\n <p className=\"text-gray-600\">加载中...</p>\n </div>\n </div>\n )\n }\n\n if (error) {\n return (\n <div>\n <h1 className=\"text-2xl font-bold text-gray-900 mb-6\">任务</h1>\n <div className=\"bg-white rounded-lg shadow p-6\">\n <p className=\"text-red-600\">加载失败: {(error as Error).message}</p>\n </div>\n </div>\n )\n }\n\n // ── Render ────────────────────────────────────────────────────────────────\n return (\n <div>\n {/* Header */}\n <div className=\"flex items-center justify-between mb-4 flex-wrap gap-3\">\n <h1 className=\"text-2xl font-bold text-gray-900\">任务</h1>\n <SearchInput\n value={searchVal}\n onChange={handleSearchChange}\n placeholder=\"搜索任务标题...\"\n className=\"w-64\"\n />\n </div>\n\n {/* Filters bar */}\n <div className=\"flex flex-wrap items-center gap-2 mb-4\">\n {/* Time presets */}\n {(['1h', '24h', '7d'] as TimePreset[]).map(preset => (\n <button\n key={preset}\n onClick={() => handlePreset(timePreset === preset ? '' : preset)}\n className={clsx(\n 'px-3 py-1.5 text-xs font-medium rounded-md border transition-colors',\n timePreset === preset\n ? 'bg-indigo-600 text-white border-indigo-600'\n : 'bg-white text-gray-700 border-gray-300 hover:bg-gray-50'\n )}\n >\n {preset === '1h' ? '近 1 小时' : preset === '24h' ? '近 24 小时' : '近 7 天'}\n </button>\n ))}\n\n {/* Project multi-select */}\n {projects.length > 0 && (\n <div className=\"relative\">\n <button\n onClick={() => setProjectDropdownOpen(v => !v)}\n className={clsx(\n 'inline-flex items-center gap-1.5 px-3 py-1.5 text-xs font-medium rounded-md border transition-colors',\n selectedProjects.length > 0\n ? 'bg-indigo-50 text-indigo-700 border-indigo-300'\n : 'bg-white text-gray-700 border-gray-300 hover:bg-gray-50'\n )}\n >\n <FolderOpen className=\"h-3.5 w-3.5\" />\n {selectedProjects.length > 0\n ? `项目 (${selectedProjects.length})`\n : '所有项目'}\n </button>\n {projectDropdownOpen && (\n <>\n <div className=\"fixed inset-0 z-10\" onClick={() => setProjectDropdownOpen(false)} />\n <div className=\"absolute left-0 mt-1 w-72 bg-white border border-gray-200 rounded-md shadow-lg z-20 max-h-64 overflow-y-auto\">\n {selectedProjects.length > 0 && (\n <button\n onClick={() => { clearProjects(); setProjectDropdownOpen(false) }}\n className=\"w-full text-left px-3 py-2 text-xs text-indigo-600 hover:bg-indigo-50 border-b border-gray-100\"\n >\n 清除筛选\n </button>\n )}\n {projects.map(proj => (\n <label\n key={proj}\n className=\"flex items-center gap-2 px-3 py-2 text-sm text-gray-700 hover:bg-gray-50 cursor-pointer\"\n >\n <input\n type=\"checkbox\"\n className=\"rounded text-indigo-600\"\n checked={selectedProjects.includes(proj)}\n onChange={() => toggleProject(proj)}\n />\n <span className=\"truncate font-mono text-xs\" title={proj}>\n {shortPath(proj)}\n </span>\n </label>\n ))}\n </div>\n </>\n )}\n </div>\n )}\n\n {/* Active filter summary */}\n {(selectedProjects.length > 0 || timePreset || searchVal) && (\n <button\n onClick={() => setSearchParams({}, { replace: true })}\n className=\"px-2 py-1.5 text-xs text-gray-500 hover:text-gray-700 underline\"\n >\n 清除所有筛选\n </button>\n )}\n </div>\n\n {/* Result count + page-size selector */}\n <div className=\"flex items-center justify-between mb-3 text-sm text-gray-500\">\n <span>\n 共 <span className=\"font-semibold text-gray-900\">{total}</span> 条\n {isLoading && <span className=\"ml-2 text-xs text-indigo-500\">刷新中...</span>}\n </span>\n <div className=\"flex items-center gap-2\">\n <span className=\"text-xs\">每页</span>\n {PAGE_SIZES.map(size => (\n <button\n key={size}\n onClick={() => handlePageSize(size)}\n className={clsx(\n 'px-2 py-0.5 text-xs rounded border',\n pageSize === size\n ? 'bg-indigo-600 text-white border-indigo-600'\n : 'bg-white text-gray-600 border-gray-300 hover:bg-gray-50'\n )}\n >\n {size}\n </button>\n ))}\n </div>\n </div>\n\n {/* Task list */}\n <div className=\"grid gap-4\">\n {tasks.map((task) => (\n <div\n key={task.id}\n onClick={() => navigate(`/tasks/${task.id}`, { state: { from: location.pathname + location.search } })}\n className=\"bg-white rounded-lg shadow hover:shadow-md transition-shadow cursor-pointer p-5\"\n >\n <div className=\"flex items-start justify-between mb-3\">\n <div className=\"flex items-start gap-3 flex-1 min-w-0\">\n <div className=\"mt-0.5 flex-shrink-0\">{getStatusIcon(task.status)}</div>\n <div className=\"flex-1 min-w-0\">\n <h3 className=\"text-base font-semibold text-gray-900 mb-1 truncate\">\n {normalizeTaskTitle(task.title, task.first_prompt)}\n </h3>\n {task.project_path && (\n <p className=\"text-xs text-gray-400 font-mono truncate\" title={task.project_path}>\n {shortPath(task.project_path)}\n </p>\n )}\n </div>\n </div>\n <span className={clsx(\n 'ml-3 flex-shrink-0 px-2 py-1 text-xs font-medium rounded-full whitespace-nowrap',\n task.status === 'completed' && 'bg-green-100 text-green-700',\n task.status === 'active' && 'bg-blue-100 text-blue-700',\n task.status === 'abandoned' && 'bg-gray-100 text-gray-600',\n )}>\n {task.status}\n </span>\n </div>\n\n <div className=\"flex items-center gap-6 text-sm text-gray-600\">\n <span className=\"inline-flex items-center gap-1\">\n <Activity className=\"h-4 w-4\" />\n {task.event_count} 个事件\n </span>\n <span className=\"inline-flex items-center gap-1\">\n <Clock className=\"h-4 w-4\" />\n {task.start_time\n ? formatDistanceToNow(parseUTC(task.start_time), {\n addSuffix: true,\n locale: zhCN,\n })\n : '-'}\n </span>\n </div>\n </div>\n ))}\n\n {tasks.length === 0 && !isLoading && (\n <div className=\"bg-white rounded-lg shadow p-12 text-center text-gray-500\">\n {searchVal || selectedProjects.length > 0 || timePreset\n ? '无匹配结果'\n : '暂无任务记录'}\n </div>\n )}\n </div>\n\n {/* Pagination */}\n {total > pageSize && (\n <div className=\"flex items-center justify-between mt-6\">\n <button\n onClick={() => goPage(page - 1)}\n disabled={page <= 1}\n className=\"inline-flex items-center gap-1 px-3 py-1.5 text-sm border rounded-md bg-white hover:bg-gray-50 disabled:opacity-40 disabled:cursor-not-allowed\"\n >\n <ChevronLeft className=\"h-4 w-4\" />\n 上一页\n </button>\n <span className=\"text-sm text-gray-500\">\n 第 {page} / {totalPages} 页\n {hasMore ? '' : '(已到末页)'}\n </span>\n <button\n onClick={() => goPage(page + 1)}\n disabled={!hasMore}\n className=\"inline-flex items-center gap-1 px-3 py-1.5 text-sm border rounded-md bg-white hover:bg-gray-50 disabled:opacity-40 disabled:cursor-not-allowed\"\n >\n 下一页\n <ChevronRight className=\"h-4 w-4\" />\n </button>\n </div>\n )}\n </div>\n )\n}\n"],"names":["PAGE_SIZES","DEFAULT_PAGE_SIZE","presetToFrom","preset","now","fetchTasks","params","res","fetchProjects","shortPath","p","parts","Tasks","navigate","useNavigate","location","useLocation","searchParams","setSearchParams","useSearchParams","page","pageSize","selectedProjects","timePreset","fromParam","toParam","searchVal","projectDropdownOpen","setProjectDropdownOpen","useState","patchSearch","useCallback","patch","prev","next","k","v","val","effectiveFrom","effectiveTo","queryParams","useMemo","pr","data","isLoading","error","useQuery","projects","tasks","total","hasMore","totalPages","handleSearchChange","toggleProject","proj","clearProjects","handlePreset","handlePageSize","size","goPage","getStatusIcon","status","jsx","CheckCircle2","Loader2","Activity","jsxs","SearchInput","clsx","FolderOpen","Fragment","task","normalizeTaskTitle","Clock","formatDistanceToNow","parseUTC","zhCN","ChevronLeft","ChevronRight"],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ function a(n,t){const e=JSON.stringify(t,null,2),o=new Blob([e],{type:"application/json"});c(n,o)}function l(n,t){if(!t||t.length===0){a(n.replace(/\.csv$/,".json"),t);return}const e=Object.keys(t[0]),o=[e.join(","),...t.map(s=>e.map(r=>d(s[r])).join(","))].join(`
2
+ `),i=new Blob(["\uFEFF"+o],{type:"text/csv;charset=utf-8"});c(n,i)}function d(n){if(n==null)return"";const t=typeof n=="object"?JSON.stringify(n):String(n);return t.includes(",")||t.includes('"')||t.includes(`
3
+ `)?`"${t.replace(/"/g,'""')}"`:t}function c(n,t){const e=URL.createObjectURL(t),o=document.createElement("a");o.href=e,o.download=n,document.body.appendChild(o),o.click(),document.body.removeChild(o),URL.revokeObjectURL(e)}function u(){const n=new Date,t=e=>String(e).padStart(2,"0");return`${n.getFullYear()}${t(n.getMonth()+1)}${t(n.getDate())}-${t(n.getHours())}${t(n.getMinutes())}${t(n.getSeconds())}`}export{l as a,a as d,u as g};
4
+ //# sourceMappingURL=export-L_VBD2p1.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"export-L_VBD2p1.js","sources":["../../src/utils/export.ts"],"sourcesContent":["/**\n * 导出工具函数:JSON / CSV\n */\n\nexport function downloadJSON(filename: string, data: unknown): void {\n const content = JSON.stringify(data, null, 2)\n const blob = new Blob([content], { type: 'application/json' })\n triggerDownload(filename, blob)\n}\n\nexport function downloadCSV<T extends object>(filename: string, rows: T[]): void {\n if (!rows || rows.length === 0) {\n downloadJSON(filename.replace(/\\.csv$/, '.json'), rows)\n return\n }\n\n const headers = Object.keys(rows[0]) as (keyof T & string)[]\n const csv = [\n headers.join(','),\n ...rows.map(row =>\n headers.map(h => escapeCSV(row[h])).join(',')\n ),\n ].join('\\n')\n\n // 添加 BOM 让 Excel 识别 UTF-8\n const blob = new Blob(['' + csv], { type: 'text/csv;charset=utf-8' })\n triggerDownload(filename, blob)\n}\n\nfunction escapeCSV(value: unknown): string {\n if (value === null || value === undefined) return ''\n const str = typeof value === 'object' ? JSON.stringify(value) : String(value)\n if (str.includes(',') || str.includes('\"') || str.includes('\\n')) {\n return `\"${str.replace(/\"/g, '\"\"')}\"`\n }\n return str\n}\n\nfunction triggerDownload(filename: string, blob: Blob): void {\n const url = URL.createObjectURL(blob)\n const a = document.createElement('a')\n a.href = url\n a.download = filename\n document.body.appendChild(a)\n a.click()\n document.body.removeChild(a)\n URL.revokeObjectURL(url)\n}\n\nexport function getTimestamp(): string {\n const now = new Date()\n const pad = (n: number) => String(n).padStart(2, '0')\n return `${now.getFullYear()}${pad(now.getMonth() + 1)}${pad(now.getDate())}-${pad(now.getHours())}${pad(now.getMinutes())}${pad(now.getSeconds())}`\n}\n"],"names":["downloadJSON","filename","data","content","blob","triggerDownload","downloadCSV","rows","headers","csv","row","h","escapeCSV","value","str","url","a","getTimestamp","now","pad","n"],"mappings":"AAIO,SAASA,EAAaC,EAAkBC,EAAqB,CAClE,MAAMC,EAAU,KAAK,UAAUD,EAAM,KAAM,CAAC,EACtCE,EAAO,IAAI,KAAK,CAACD,CAAO,EAAG,CAAE,KAAM,mBAAoB,EAC7DE,EAAgBJ,EAAUG,CAAI,CAChC,CAEO,SAASE,EAA8BL,EAAkBM,EAAiB,CAC/E,GAAI,CAACA,GAAQA,EAAK,SAAW,EAAG,CAC9BP,EAAaC,EAAS,QAAQ,SAAU,OAAO,EAAGM,CAAI,EACtD,MACF,CAEA,MAAMC,EAAU,OAAO,KAAKD,EAAK,CAAC,CAAC,EAC7BE,EAAM,CACVD,EAAQ,KAAK,GAAG,EAChB,GAAGD,EAAK,IAAIG,GACVF,EAAQ,IAAIG,GAAKC,EAAUF,EAAIC,CAAC,CAAC,CAAC,EAAE,KAAK,GAAG,CAAA,CAC9C,EACA,KAAK;AAAA,CAAI,EAGLP,EAAO,IAAI,KAAK,CAAC,SAAMK,CAAG,EAAG,CAAE,KAAM,yBAA0B,EACrEJ,EAAgBJ,EAAUG,CAAI,CAChC,CAEA,SAASQ,EAAUC,EAAwB,CACzC,GAAIA,GAAU,KAA6B,MAAO,GAClD,MAAMC,EAAM,OAAOD,GAAU,SAAW,KAAK,UAAUA,CAAK,EAAI,OAAOA,CAAK,EAC5E,OAAIC,EAAI,SAAS,GAAG,GAAKA,EAAI,SAAS,GAAG,GAAKA,EAAI,SAAS;AAAA,CAAI,EACtD,IAAIA,EAAI,QAAQ,KAAM,IAAI,CAAC,IAE7BA,CACT,CAEA,SAAST,EAAgBJ,EAAkBG,EAAkB,CAC3D,MAAMW,EAAM,IAAI,gBAAgBX,CAAI,EAC9BY,EAAI,SAAS,cAAc,GAAG,EACpCA,EAAE,KAAOD,EACTC,EAAE,SAAWf,EACb,SAAS,KAAK,YAAYe,CAAC,EAC3BA,EAAE,MAAA,EACF,SAAS,KAAK,YAAYA,CAAC,EAC3B,IAAI,gBAAgBD,CAAG,CACzB,CAEO,SAASE,GAAuB,CACrC,MAAMC,MAAU,KACVC,EAAOC,GAAc,OAAOA,CAAC,EAAE,SAAS,EAAG,GAAG,EACpD,MAAO,GAAGF,EAAI,YAAA,CAAa,GAAGC,EAAID,EAAI,SAAA,EAAa,CAAC,CAAC,GAAGC,EAAID,EAAI,SAAS,CAAC,IAAIC,EAAID,EAAI,SAAA,CAAU,CAAC,GAAGC,EAAID,EAAI,WAAA,CAAY,CAAC,GAAGC,EAAID,EAAI,WAAA,CAAY,CAAC,EACnJ"}
@@ -0,0 +1,3 @@
1
+ const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/Dashboard-CoEmmIDt.js","assets/react-vendor-CSp-GLFF.js","assets/query-C99w429o.js","assets/react-router-r79dBVy4.js","assets/vendor-CMMjVdZs.js","assets/lucide-Bs_edTLa.js","assets/charts-CLrM0_uM.js","assets/Sessions-FfLYkAw9.js","assets/time-Bxuk0M-C.js","assets/Drawer-DdRTzlLB.js","assets/date-fns-CZ_bHujz.js","assets/SearchInput-qCj_jAcf.js","assets/export-L_VBD2p1.js","assets/syntax-highlighter-44FakypI.js","assets/SessionDetail-CCzwdoT7.js","assets/Events-DrIq1SUS.js","assets/Skills-C8Gvs3Qa.js","assets/auth-Bnf8ZcqN.js","assets/AIConfig-CdDWzJyO.js","assets/Tasks-CyuhizG8.js","assets/task-title-BhOcemuR.js","assets/TaskDetail-BS8pYhaR.js","assets/Reports-DFBM3MDK.js"])))=>i.map(i=>d[i]);
2
+ import{r,j as e,e as b,d as y}from"./react-vendor-CSp-GLFF.js";import{u as v,O as N,L as w,R as _,a as c,N as C,B as k}from"./react-router-r79dBVy4.js";import{Q as T,a as E}from"./query-C99w429o.js";import{_ as m}from"./syntax-highlighter-44FakypI.js";import{d as f}from"./vendor-CMMjVdZs.js";import{X as p,M as O,L as P,a as L,b as S,F as I,A,B as R,C as z,I as D,c as F,d as V,e as B,T as M}from"./lucide-Bs_edTLa.js";(function(){const a=document.createElement("link").relList;if(a&&a.supports&&a.supports("modulepreload"))return;for(const t of document.querySelectorAll('link[rel="modulepreload"]'))o(t);new MutationObserver(t=>{for(const n of t)if(n.type==="childList")for(const s of n.addedNodes)s.tagName==="LINK"&&s.rel==="modulepreload"&&o(s)}).observe(document,{childList:!0,subtree:!0});function l(t){const n={};return t.integrity&&(n.integrity=t.integrity),t.referrerPolicy&&(n.referrerPolicy=t.referrerPolicy),t.crossOrigin==="use-credentials"?n.credentials="include":t.crossOrigin==="anonymous"?n.credentials="omit":n.credentials="same-origin",n}function o(t){if(t.ep)return;t.ep=!0;const n=l(t);fetch(t.href,n)}})();const q=[{title:"总览",items:[{name:"仪表盘",href:"/dashboard",icon:P}]},{title:"活动",items:[{name:"会话",href:"/sessions",icon:L},{name:"任务",href:"/tasks",icon:S},{name:"周报",href:"/reports",icon:I},{name:"事件",href:"/events",icon:A}]},{title:"配置",items:[{name:"Skill 管理",href:"/skills",icon:R},{name:"AI 配置",href:"/ai-config",icon:z}]}];function Q(){const i=v(),[a,l]=r.useState(!1),o=t=>e.jsx(e.Fragment,{children:q.map(n=>e.jsxs("div",{className:"mb-4",children:[e.jsx("div",{className:"px-3 py-2 text-xs font-semibold text-gray-400 uppercase tracking-wider",children:n.title}),n.items.map(s=>{const u=s.icon,d=i.pathname===s.href||i.pathname.startsWith(s.href+"/");return e.jsxs(w,{to:s.href,onClick:t,className:f("group flex items-center px-3 py-2 text-sm font-medium rounded-md mb-0.5",d?"bg-indigo-50 text-indigo-600":"text-gray-700 hover:bg-gray-50"),children:[e.jsx(u,{className:f("mr-3 h-4 w-4",d?"text-indigo-600":"text-gray-400")}),s.name]},s.name)})]},n.title))});return e.jsxs("div",{className:"min-h-screen bg-gray-50",children:[e.jsxs("div",{className:f("fixed inset-0 z-40 lg:hidden",a?"block":"hidden"),children:[e.jsx("div",{className:"fixed inset-0 bg-gray-600 bg-opacity-75",onClick:()=>l(!1)}),e.jsxs("div",{className:"fixed inset-y-0 left-0 flex w-64 flex-col bg-white",children:[e.jsxs("div",{className:"flex items-center justify-between px-4 py-4 border-b",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("div",{className:"w-8 h-8 rounded-lg bg-gradient-to-br from-indigo-500 to-purple-600 flex items-center justify-center text-white font-bold text-sm",children:"CF"}),e.jsx("h1",{className:"text-base font-bold text-gray-900",children:"Claude Forge"})]}),e.jsx("button",{onClick:()=>l(!1),className:"text-gray-500",children:e.jsx(p,{className:"h-5 w-5"})})]}),e.jsx("nav",{className:"flex-1 overflow-y-auto px-2 py-4",children:o(()=>l(!1))})]})]}),e.jsx("div",{className:"hidden lg:fixed lg:inset-y-0 lg:flex lg:w-64 lg:flex-col",children:e.jsxs("div",{className:"flex flex-col flex-grow border-r border-gray-200 bg-white",children:[e.jsxs("div",{className:"flex items-center gap-2 px-4 py-4 border-b",children:[e.jsx("div",{className:"w-8 h-8 rounded-lg bg-gradient-to-br from-indigo-500 to-purple-600 flex items-center justify-center text-white font-bold text-sm",children:"CF"}),e.jsx("h1",{className:"text-base font-bold text-gray-900",children:"Claude Forge"})]}),e.jsx("nav",{className:"flex-1 overflow-y-auto px-2 py-4",children:o()})]})}),e.jsxs("div",{className:"lg:pl-64",children:[e.jsxs("div",{className:"sticky top-0 z-10 flex h-14 flex-shrink-0 bg-white border-b border-gray-200 lg:hidden",children:[e.jsx("button",{onClick:()=>l(!0),className:"px-4 text-gray-500 focus:outline-none",children:e.jsx(O,{className:"h-5 w-5"})}),e.jsx("div",{className:"flex flex-1 items-center px-4",children:e.jsx("h1",{className:"text-base font-semibold text-gray-900",children:"Claude Forge"})})]}),e.jsx("main",{className:"py-6",children:e.jsx("div",{className:"mx-auto max-w-7xl px-4 sm:px-6 lg:px-8",children:e.jsx(N,{})})})]})]})}const W=r.lazy(()=>m(()=>import("./Dashboard-CoEmmIDt.js"),__vite__mapDeps([0,1,2,3,4,5,6]))),X=r.lazy(()=>m(()=>import("./Sessions-FfLYkAw9.js"),__vite__mapDeps([7,1,2,8,9,4,5,10,11,12,3,13]))),$=r.lazy(()=>m(()=>import("./SessionDetail-CCzwdoT7.js"),__vite__mapDeps([14,1,3,4,2,8,5,10]))),K=r.lazy(()=>m(()=>import("./Events-DrIq1SUS.js"),__vite__mapDeps([15,1,2,8,4,9,5,13,11,12,10,3]))),G=r.lazy(()=>m(()=>import("./Skills-C8Gvs3Qa.js"),__vite__mapDeps([16,1,2,9,4,5,13,17,3]))),H=r.lazy(()=>m(()=>import("./AIConfig-CdDWzJyO.js"),__vite__mapDeps([18,1,2,17,5,3,4,13]))),J=r.lazy(()=>m(()=>import("./Tasks-CyuhizG8.js"),__vite__mapDeps([19,1,2,3,4,8,11,5,20,10]))),U=r.lazy(()=>m(()=>import("./TaskDetail-BS8pYhaR.js"),__vite__mapDeps([21,1,3,4,2,8,20,5,10]))),Y=r.lazy(()=>m(()=>import("./Reports-DFBM3MDK.js"),__vite__mapDeps([22,1,2,5,6,4])));function x(){return e.jsx("div",{className:"flex items-center justify-center h-full py-16",children:e.jsxs("div",{className:"flex items-center gap-3 text-sm text-gray-500",children:[e.jsx("div",{className:"w-4 h-4 border-2 border-gray-300 border-t-blue-500 rounded-full animate-spin"}),"加载中..."]})})}function Z(){return e.jsx(_,{children:e.jsxs(c,{path:"/",element:e.jsx(Q,{}),children:[e.jsx(c,{index:!0,element:e.jsx(C,{to:"/dashboard",replace:!0})}),e.jsx(c,{path:"dashboard",element:e.jsx(r.Suspense,{fallback:e.jsx(x,{}),children:e.jsx(W,{})})}),e.jsx(c,{path:"sessions",element:e.jsx(r.Suspense,{fallback:e.jsx(x,{}),children:e.jsx(X,{})})}),e.jsx(c,{path:"sessions/:id",element:e.jsx(r.Suspense,{fallback:e.jsx(x,{}),children:e.jsx($,{})})}),e.jsx(c,{path:"events",element:e.jsx(r.Suspense,{fallback:e.jsx(x,{}),children:e.jsx(K,{})})}),e.jsx(c,{path:"skills",element:e.jsx(r.Suspense,{fallback:e.jsx(x,{}),children:e.jsx(G,{})})}),e.jsx(c,{path:"ai-config",element:e.jsx(r.Suspense,{fallback:e.jsx(x,{}),children:e.jsx(H,{})})}),e.jsx(c,{path:"tasks",element:e.jsx(r.Suspense,{fallback:e.jsx(x,{}),children:e.jsx(J,{})})}),e.jsx(c,{path:"tasks/:taskId",element:e.jsx(r.Suspense,{fallback:e.jsx(x,{}),children:e.jsx(U,{})})}),e.jsx(c,{path:"reports",element:e.jsx(r.Suspense,{fallback:e.jsx(x,{}),children:e.jsx(Y,{})})})]})})}const g=r.createContext(null);function me(){const i=r.useContext(g);if(!i)throw new Error("useToast must be used within ToastProvider");return i}let ee=1;function se({children:i}){const[a,l]=r.useState([]),o=r.useCallback(s=>{l(u=>u.filter(d=>d.id!==s))},[]),t=r.useCallback((s,u)=>{const d=ee++;l(h=>[...h,{id:d,type:s,message:u}]),setTimeout(()=>o(d),4e3)},[o]),n={show:t,success:s=>t("success",s),error:s=>t("error",s),warning:s=>t("warning",s),info:s=>t("info",s)};return e.jsxs(g.Provider,{value:n,children:[i,e.jsx("div",{className:"fixed top-4 right-4 z-[9999] space-y-2 max-w-md",children:a.map(s=>e.jsx(te,{toast:s,onClose:()=>o(s.id)},s.id))})]})}function te({toast:i,onClose:a}){const l={success:e.jsx(B,{className:"h-5 w-5 text-green-500"}),error:e.jsx(V,{className:"h-5 w-5 text-red-500"}),warning:e.jsx(F,{className:"h-5 w-5 text-yellow-500"}),info:e.jsx(D,{className:"h-5 w-5 text-blue-500"})},o={success:"border-green-200",error:"border-red-200",warning:"border-yellow-200",info:"border-blue-200"};return e.jsxs("div",{className:f("bg-white shadow-lg rounded-lg border px-4 py-3 flex items-start gap-3 animate-in slide-in-from-right",o[i.type]),children:[l[i.type],e.jsx("div",{className:"flex-1 text-sm text-gray-800",children:i.message}),e.jsx("button",{onClick:a,className:"text-gray-400 hover:text-gray-600",children:e.jsx(p,{className:"h-4 w-4"})})]})}const re=r.createContext(null);function ne({children:i}){var d;const[a,l]=r.useState({open:!1,options:null,resolve:null}),o=r.useCallback(h=>new Promise(j=>{l({open:!0,options:h,resolve:j})}),[]),t=h=>{a.resolve&&a.resolve(h),l({open:!1,options:null,resolve:null})},n=((d=a.options)==null?void 0:d.variant)||"danger",s={danger:"text-red-600",warning:"text-yellow-600",info:"text-blue-600"}[n],u={danger:"bg-red-600 hover:bg-red-700",warning:"bg-yellow-600 hover:bg-yellow-700",info:"bg-indigo-600 hover:bg-indigo-700"}[n];return e.jsxs(re.Provider,{value:{confirm:o},children:[i,a.open&&a.options&&e.jsxs("div",{className:"fixed inset-0 z-[9999] flex items-center justify-center",children:[e.jsx("div",{className:"absolute inset-0 bg-black bg-opacity-50",onClick:()=>t(!1)}),e.jsxs("div",{className:"relative bg-white rounded-lg shadow-xl max-w-md w-full mx-4 p-6",children:[e.jsxs("div",{className:"flex items-start gap-4",children:[e.jsx("div",{className:`flex-shrink-0 ${s}`,children:e.jsx(M,{className:"h-6 w-6"})}),e.jsxs("div",{className:"flex-1",children:[e.jsx("h3",{className:"text-lg font-semibold text-gray-900 mb-2",children:a.options.title}),e.jsx("p",{className:"text-sm text-gray-600 whitespace-pre-wrap",children:a.options.message})]})]}),e.jsxs("div",{className:"flex justify-end gap-2 mt-6",children:[e.jsx("button",{onClick:()=>t(!1),className:"px-4 py-2 text-sm text-gray-700 bg-white border border-gray-300 rounded hover:bg-gray-50",children:a.options.cancelText||"取消"}),e.jsx("button",{onClick:()=>t(!0),className:`px-4 py-2 text-sm text-white rounded ${u}`,children:a.options.confirmText||"确定"})]})]})]})]})}const ae=new T({defaultOptions:{queries:{refetchOnWindowFocus:!1,retry:1}}});b.createRoot(document.getElementById("root")).render(e.jsx(y.StrictMode,{children:e.jsx(E,{client:ae,children:e.jsx(se,{children:e.jsx(ne,{children:e.jsx(k,{children:e.jsx(Z,{})})})})})}));export{me as u};
3
+ //# sourceMappingURL=index-CBX47X8l.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"mappings":";0mCA0BA,MAAMA,EAAyB,CAC7B,CACE,MAAO,KACP,MAAO,CACL,CAAE,KAAM,MAAO,KAAM,aAAc,KAAMC,CAAA,CAAgB,CAC3D,EAEF,CACE,MAAO,KACP,MAAO,CACL,CAAE,KAAM,KAAM,KAAM,YAAa,KAAMC,CAAA,EACvC,CAAE,KAAM,KAAM,KAAM,SAAU,KAAMC,CAAA,EACpC,CAAE,KAAM,KAAM,KAAM,WAAY,KAAMC,CAAA,EACtC,CAAE,KAAM,KAAM,KAAM,UAAW,KAAMC,CAAA,CAAS,CAChD,EAEF,CACE,MAAO,KACP,MAAO,CACL,CAAE,KAAM,WAAY,KAAM,UAAW,KAAMC,CAAA,EAC3C,CAAE,KAAM,QAAS,KAAM,aAAc,KAAMC,CAAA,CAAI,CACjD,CAEJ,EAEA,SAAwBC,GAAS,CAC/B,MAAMC,EAAWC,EAAA,EACX,CAACC,EAAaC,CAAc,EAAIC,WAAS,EAAK,EAE9CC,EAAaC,GACjBC,MAAAC,WAAA,CACG,SAAAjB,EAAS,IAAKkB,GACbC,OAAC,OAAwB,UAAU,OACjC,UAAAH,MAAC,OAAI,UAAU,yEACZ,SAAAE,EAAQ,MACX,EACCA,EAAQ,MAAM,IAAKE,GAAS,CAC3B,MAAMC,EAAOD,EAAK,KACZE,EAAWb,EAAS,WAAaW,EAAK,MAAQX,EAAS,SAAS,WAAWW,EAAK,KAAO,GAAG,EAChG,OACED,OAACI,EAAA,CAEC,GAAIH,EAAK,KACT,QAAAL,EACA,UAAWS,EACT,0EACAF,EACI,+BACA,kCAGN,UAAAN,MAACK,GAAK,UAAWG,EAAK,eAAgBF,EAAW,kBAAoB,eAAe,EAAG,EACtFF,EAAK,OAXDA,EAAK,KAchB,CAAC,IAvBOF,EAAQ,KAwBlB,CACD,EACH,EAGF,OACEC,OAAC,OAAI,UAAU,0BAEb,UAAAA,OAAC,OAAI,UAAWK,EAAK,+BAAgCb,EAAc,QAAU,QAAQ,EACnF,UAAAK,MAAC,OAAI,UAAU,0CAA0C,QAAS,IAAMJ,EAAe,EAAK,EAAG,EAC/FO,OAAC,OAAI,UAAU,qDACb,UAAAA,OAAC,OAAI,UAAU,uDACb,UAAAA,OAAC,OAAI,UAAU,0BACb,UAAAH,MAAC,OAAI,UAAU,mIAAmI,cAElJ,EACAA,MAAC,MAAG,UAAU,oCAAoC,wBAAY,GAChE,EACAA,MAAC,UAAO,QAAS,IAAMJ,EAAe,EAAK,EAAG,UAAU,gBACtD,SAAAI,MAACS,EAAA,CAAE,UAAU,UAAU,EACzB,GACF,EACAT,MAAC,OAAI,UAAU,mCACZ,WAAU,IAAMJ,EAAe,EAAK,CAAC,EACxC,GACF,GACF,QAGC,OAAI,UAAU,2DACb,SAAAO,OAAC,OAAI,UAAU,4DACb,UAAAA,OAAC,OAAI,UAAU,6CACb,UAAAH,MAAC,OAAI,UAAU,mIAAmI,cAElJ,EACAA,MAAC,MAAG,UAAU,oCAAoC,wBAAY,GAChE,EACAA,MAAC,OAAI,UAAU,mCAAoC,YAAU,CAAE,GACjE,EACF,EAGAG,OAAC,OAAI,UAAU,WACb,UAAAA,OAAC,OAAI,UAAU,wFACb,UAAAH,MAAC,UACC,QAAS,IAAMJ,EAAe,EAAI,EAClC,UAAU,wCAEV,SAAAI,MAACU,EAAA,CAAK,UAAU,UAAU,IAE5BV,MAAC,OAAI,UAAU,gCACb,eAAC,MAAG,UAAU,wCAAwC,wBAAY,EACpE,GACF,EACAA,MAAC,QAAK,UAAU,OACd,SAAAA,MAAC,OAAI,UAAU,yCACb,SAAAA,MAACW,EAAA,EAAO,EACV,EACF,GACF,GACF,CAEJ,CC3IA,MAAMC,EAAYC,OAAK,UAAM,OAAO,yBAAmB,mCAAC,EAClDC,EAAWD,OAAK,UAAM,OAAO,wBAAkB,iDAAC,EAChDE,EAAgBF,OAAK,UAAM,OAAO,6BAAuB,uCAAC,EAC1DG,EAASH,OAAK,UAAM,OAAO,sBAAgB,kDAAC,EAC5CI,EAASJ,OAAK,UAAM,OAAO,sBAAgB,0CAAC,EAC5CK,EAAWL,OAAK,UAAM,OAAO,wBAAkB,wCAAC,EAChDM,EAAQN,OAAK,UAAM,OAAO,qBAAe,6CAAC,EAC1CO,EAAaP,OAAK,UAAM,OAAO,0BAAoB,0CAAC,EACpDQ,EAAUR,OAAK,UAAM,OAAO,uBAAiB,kCAAC,EAEpD,SAASS,GAAe,CACtB,aACG,OAAI,UAAU,gDACb,SAAAnB,OAAC,OAAI,UAAU,gDACb,UAAAH,MAAC,OAAI,UAAU,+EAA+E,EAAE,UAElG,EACF,CAEJ,CAEA,SAAwBuB,GAAM,CAC5B,OACEvB,MAACwB,GACC,SAAArB,OAACsB,EAAA,CAAM,KAAK,IAAI,QAASzB,MAACR,EAAA,EAAO,EAC/B,UAAAQ,MAACyB,EAAA,CACC,MAAK,GACL,QAASzB,MAAC0B,EAAA,CAAS,GAAG,aAAa,QAAO,GAAC,IAE7C1B,MAACyB,EAAA,CACC,KAAK,YACL,cACGE,WAAA,CAAS,eAAWL,EAAA,EAAa,EAChC,SAAAtB,MAACY,EAAA,EAAU,EACb,IAGJZ,MAACyB,EAAA,CACC,KAAK,WACL,cACGE,WAAA,CAAS,eAAWL,EAAA,EAAa,EAChC,SAAAtB,MAACc,EAAA,EAAS,EACZ,IAGJd,MAACyB,EAAA,CACC,KAAK,eACL,cACGE,WAAA,CAAS,eAAWL,EAAA,EAAa,EAChC,SAAAtB,MAACe,EAAA,EAAc,EACjB,IAGJf,MAACyB,EAAA,CACC,KAAK,SACL,cACGE,WAAA,CAAS,eAAWL,EAAA,EAAa,EAChC,SAAAtB,MAACgB,EAAA,EAAO,EACV,IAGJhB,MAACyB,EAAA,CACC,KAAK,SACL,cACGE,WAAA,CAAS,eAAWL,EAAA,EAAa,EAChC,SAAAtB,MAACiB,EAAA,EAAO,EACV,IAGJjB,MAACyB,EAAA,CACC,KAAK,YACL,cACGE,WAAA,CAAS,eAAWL,EAAA,EAAa,EAChC,SAAAtB,MAACkB,EAAA,EAAS,EACZ,IAGJlB,MAACyB,EAAA,CACC,KAAK,QACL,cACGE,WAAA,CAAS,eAAWL,EAAA,EAAa,EAChC,SAAAtB,MAACmB,EAAA,EAAM,EACT,IAGJnB,MAACyB,EAAA,CACC,KAAK,gBACL,cACGE,WAAA,CAAS,eAAWL,EAAA,EAAa,EAChC,SAAAtB,MAACoB,EAAA,EAAW,EACd,IAGJpB,MAACyB,EAAA,CACC,KAAK,UACL,cACGE,WAAA,CAAS,eAAWL,EAAA,EAAa,EAChC,SAAAtB,MAACqB,EAAA,EAAQ,EACX,GAEJ,EACF,EACF,CAEJ,CCzFA,MAAMO,EAAeC,gBAAwC,IAAI,EAE1D,SAASC,IAAW,CACzB,MAAMC,EAAMC,aAAWJ,CAAY,EACnC,GAAI,CAACG,EAAK,MAAM,IAAI,MAAM,4CAA4C,EACtE,OAAOA,CACT,CAEA,IAAIE,GAAS,EAEN,SAASC,GAAc,CAAE,SAAAC,GAAqC,CACnE,KAAM,CAACC,EAAQC,CAAS,EAAIxC,WAAkB,EAAE,EAE1CyC,EAASC,cAAaC,GAAe,CACzCH,KAAkBI,EAAK,UAAYC,EAAE,KAAOF,CAAE,CAAC,CACjD,EAAG,EAAE,EAECG,EAAOJ,cAAY,CAACK,EAAiBC,IAAoB,CAC7D,MAAML,EAAKP,KACXI,EAAUI,GAAQ,CAAC,GAAGA,EAAM,CAAE,GAAAD,EAAI,KAAAI,EAAM,QAAAC,CAAA,CAAS,CAAC,EAClD,WAAW,IAAMP,EAAOE,CAAE,EAAG,GAAI,CACnC,EAAG,CAACF,CAAM,CAAC,EAELQ,EAA2B,CAC/B,KAAAH,EACA,QAAUI,GAAQJ,EAAK,UAAWI,CAAG,EACrC,MAAQA,GAAQJ,EAAK,QAASI,CAAG,EACjC,QAAUA,GAAQJ,EAAK,UAAWI,CAAG,EACrC,KAAOA,GAAQJ,EAAK,OAAQI,CAAG,GAGjC,OACE5C,OAACyB,EAAa,SAAb,CAAsB,MAAAkB,EACpB,UAAAX,EACDnC,MAAC,OAAI,UAAU,kDACZ,WAAO,IAAI0C,SACTM,GAAA,CAAqB,MAAON,EAAG,QAAS,IAAMJ,EAAOI,EAAE,EAAE,GAA1CA,EAAE,EAA2C,CAC9D,EACH,GACF,CAEJ,CAEA,SAASM,GAAU,CAAE,MAAAC,EAAO,QAAAC,GAAkD,CAC5E,MAAMC,EAAQ,CACZ,QAASnD,MAACoD,EAAA,CAAY,UAAU,yBAAyB,EACzD,MAAOpD,MAACqD,EAAA,CAAQ,UAAU,uBAAuB,EACjD,QAASrD,MAACsD,EAAA,CAAY,UAAU,0BAA0B,EAC1D,KAAMtD,MAACuD,EAAA,CAAK,UAAU,wBAAwB,GAE1CC,EAAe,CACnB,QAAS,mBACT,MAAO,iBACP,QAAS,oBACT,KAAM,mBAGR,OACErD,OAAC,OACC,UAAWK,EACT,uGACAgD,EAAaP,EAAM,IAAI,GAGxB,UAAAE,EAAMF,EAAM,IAAI,EACjBjD,MAAC,OAAI,UAAU,+BAAgC,WAAM,QAAQ,EAC7DA,MAAC,UAAO,QAASkD,EAAS,UAAU,oCAClC,SAAAlD,MAACS,EAAA,CAAE,UAAU,UAAU,EACzB,IAGN,CC5EA,MAAMgD,GAAiB5B,gBAA0C,IAAI,EAQ9D,SAAS6B,GAAgB,CAAE,SAAAvB,GAAqC,OACrE,KAAM,CAACwB,EAAOC,CAAQ,EAAI/D,WAIvB,CAAE,KAAM,GAAO,QAAS,KAAM,QAAS,KAAM,EAE1CgE,EAAUtB,cAAauB,GACpB,IAAI,QAASC,GAAY,CAC9BH,EAAS,CAAE,KAAM,GAAM,QAAAE,EAAS,QAAAC,EAAS,CAC3C,CAAC,EACA,EAAE,EAECC,EAAeC,GAAoB,CACnCN,EAAM,SAASA,EAAM,QAAQM,CAAM,EACvCL,EAAS,CAAE,KAAM,GAAO,QAAS,KAAM,QAAS,KAAM,CACxD,EAEMM,IAAUC,EAAAR,EAAM,UAAN,YAAAQ,EAAe,UAAW,SACpCC,EAAY,CAChB,OAAQ,eACR,QAAS,kBACT,KAAM,iBACNF,CAAO,EACHG,EAAW,CACf,OAAQ,8BACR,QAAS,oCACT,KAAM,qCACNH,CAAO,EAET,cACGT,GAAe,SAAf,CAAwB,MAAO,CAAE,QAAAI,GAC/B,UAAA1B,EACAwB,EAAM,MAAQA,EAAM,SACnBxD,OAAC,OAAI,UAAU,0DACb,UAAAH,MAAC,OACC,UAAU,0CACV,QAAS,IAAMgE,EAAY,EAAK,IAElC7D,OAAC,OAAI,UAAU,kEACb,UAAAA,OAAC,OAAI,UAAU,yBACb,UAAAH,MAAC,OAAI,UAAW,iBAAiBoE,CAAS,GACxC,SAAApE,MAACsE,EAAA,CAAc,UAAU,UAAU,EACrC,EACAnE,OAAC,OAAI,UAAU,SACb,UAAAH,MAAC,MAAG,UAAU,2CACX,SAAA2D,EAAM,QAAQ,MACjB,QACC,KAAE,UAAU,4CACV,SAAAA,EAAM,QAAQ,QACjB,GACF,GACF,EACAxD,OAAC,OAAI,UAAU,8BACb,UAAAH,MAAC,UACC,QAAS,IAAMgE,EAAY,EAAK,EAChC,UAAU,2FAET,SAAAL,EAAM,QAAQ,YAAc,OAE/B3D,MAAC,UACC,QAAS,IAAMgE,EAAY,EAAI,EAC/B,UAAW,wCAAwCK,CAAQ,GAE1D,SAAAV,EAAM,QAAQ,aAAe,MAChC,EACF,GACF,GACF,GAEJ,CAEJ,CCtFA,MAAMY,GAAc,IAAIC,EAAY,CAClC,eAAgB,CACd,QAAS,CACP,qBAAsB,GACtB,MAAO,EACT,CAEJ,CAAC,EAEDC,EAAS,WAAW,SAAS,eAAe,MAAM,CAAE,EAAE,OACpDzE,MAAC0E,EAAM,WAAN,CACC,eAACC,EAAA,CAAoB,OAAQJ,GAC3B,SAAAvE,MAACkC,GAAA,CACC,eAACwB,GAAA,CACC,SAAA1D,MAAC4E,GACC,SAAA5E,MAACuB,EAAA,EAAI,EACP,EACF,EACF,EACF,EACF,CACF","names":["sections","LayoutDashboard","MessageSquare","ListTodo","FileText","Activity","BookOpen","Cpu","Layout","location","useLocation","sidebarOpen","setSidebarOpen","useState","renderNav","onClick","jsx","Fragment","section","jsxs","item","Icon","isActive","Link","clsx","X","Menu","Outlet","Dashboard","lazy","Sessions","SessionDetail","Events","Skills","AIConfig","Tasks","TaskDetail","Reports","PageFallback","App","Routes","Route","Navigate","Suspense","ToastContext","createContext","useToast","ctx","useContext","nextId","ToastProvider","children","toasts","setToasts","remove","useCallback","id","prev","t","show","type","message","value","msg","ToastItem","toast","onClose","icons","CheckCircle","XCircle","AlertCircle","Info","borderColors","ConfirmContext","ConfirmProvider","state","setState","confirm","options","resolve","handleClose","result","variant","_a","iconColor","btnColor","AlertTriangle","queryClient","QueryClient","ReactDOM","React","QueryClientProvider","BrowserRouter"],"ignoreList":[],"sources":["../../src/components/Layout.tsx","../../src/App.tsx","../../src/components/Toast.tsx","../../src/components/Confirm.tsx","../../src/main.tsx"],"sourcesContent":["import { Outlet, Link, useLocation } from 'react-router-dom'\nimport {\n LayoutDashboard,\n MessageSquare,\n Activity,\n Menu,\n X,\n BookOpen,\n Cpu,\n ListTodo,\n FileText,\n} from 'lucide-react'\nimport { useState } from 'react'\nimport clsx from 'clsx'\n\ninterface NavItem {\n name: string\n href: string\n icon: any\n}\n\ninterface NavSection {\n title: string\n items: NavItem[]\n}\n\nconst sections: NavSection[] = [\n {\n title: '总览',\n items: [\n { name: '仪表盘', href: '/dashboard', icon: LayoutDashboard },\n ],\n },\n {\n title: '活动',\n items: [\n { name: '会话', href: '/sessions', icon: MessageSquare },\n { name: '任务', href: '/tasks', icon: ListTodo },\n { name: '周报', href: '/reports', icon: FileText },\n { name: '事件', href: '/events', icon: Activity },\n ],\n },\n {\n title: '配置',\n items: [\n { name: 'Skill 管理', href: '/skills', icon: BookOpen },\n { name: 'AI 配置', href: '/ai-config', icon: Cpu },\n ],\n },\n]\n\nexport default function Layout() {\n const location = useLocation()\n const [sidebarOpen, setSidebarOpen] = useState(false)\n\n const renderNav = (onClick?: () => void) => (\n <>\n {sections.map((section) => (\n <div key={section.title} className=\"mb-4\">\n <div className=\"px-3 py-2 text-xs font-semibold text-gray-400 uppercase tracking-wider\">\n {section.title}\n </div>\n {section.items.map((item) => {\n const Icon = item.icon\n const isActive = location.pathname === item.href || location.pathname.startsWith(item.href + '/')\n return (\n <Link\n key={item.name}\n to={item.href}\n onClick={onClick}\n className={clsx(\n 'group flex items-center px-3 py-2 text-sm font-medium rounded-md mb-0.5',\n isActive\n ? 'bg-indigo-50 text-indigo-600'\n : 'text-gray-700 hover:bg-gray-50'\n )}\n >\n <Icon className={clsx('mr-3 h-4 w-4', isActive ? 'text-indigo-600' : 'text-gray-400')} />\n {item.name}\n </Link>\n )\n })}\n </div>\n ))}\n </>\n )\n\n return (\n <div className=\"min-h-screen bg-gray-50\">\n {/* Mobile sidebar */}\n <div className={clsx('fixed inset-0 z-40 lg:hidden', sidebarOpen ? 'block' : 'hidden')}>\n <div className=\"fixed inset-0 bg-gray-600 bg-opacity-75\" onClick={() => setSidebarOpen(false)} />\n <div className=\"fixed inset-y-0 left-0 flex w-64 flex-col bg-white\">\n <div className=\"flex items-center justify-between px-4 py-4 border-b\">\n <div className=\"flex items-center gap-2\">\n <div className=\"w-8 h-8 rounded-lg bg-gradient-to-br from-indigo-500 to-purple-600 flex items-center justify-center text-white font-bold text-sm\">\n CF\n </div>\n <h1 className=\"text-base font-bold text-gray-900\">Claude Forge</h1>\n </div>\n <button onClick={() => setSidebarOpen(false)} className=\"text-gray-500\">\n <X className=\"h-5 w-5\" />\n </button>\n </div>\n <nav className=\"flex-1 overflow-y-auto px-2 py-4\">\n {renderNav(() => setSidebarOpen(false))}\n </nav>\n </div>\n </div>\n\n {/* Desktop sidebar */}\n <div className=\"hidden lg:fixed lg:inset-y-0 lg:flex lg:w-64 lg:flex-col\">\n <div className=\"flex flex-col flex-grow border-r border-gray-200 bg-white\">\n <div className=\"flex items-center gap-2 px-4 py-4 border-b\">\n <div className=\"w-8 h-8 rounded-lg bg-gradient-to-br from-indigo-500 to-purple-600 flex items-center justify-center text-white font-bold text-sm\">\n CF\n </div>\n <h1 className=\"text-base font-bold text-gray-900\">Claude Forge</h1>\n </div>\n <nav className=\"flex-1 overflow-y-auto px-2 py-4\">{renderNav()}</nav>\n </div>\n </div>\n\n {/* Main content */}\n <div className=\"lg:pl-64\">\n <div className=\"sticky top-0 z-10 flex h-14 flex-shrink-0 bg-white border-b border-gray-200 lg:hidden\">\n <button\n onClick={() => setSidebarOpen(true)}\n className=\"px-4 text-gray-500 focus:outline-none\"\n >\n <Menu className=\"h-5 w-5\" />\n </button>\n <div className=\"flex flex-1 items-center px-4\">\n <h1 className=\"text-base font-semibold text-gray-900\">Claude Forge</h1>\n </div>\n </div>\n <main className=\"py-6\">\n <div className=\"mx-auto max-w-7xl px-4 sm:px-6 lg:px-8\">\n <Outlet />\n </div>\n </main>\n </div>\n </div>\n )\n}\n","import { lazy, Suspense } from 'react'\nimport { Routes, Route, Navigate } from 'react-router-dom'\nimport Layout from './components/Layout'\n\n// 路由级代码分割:按需加载 page 组件,缩小主 bundle\nconst Dashboard = lazy(() => import('./pages/Dashboard'))\nconst Sessions = lazy(() => import('./pages/Sessions'))\nconst SessionDetail = lazy(() => import('./pages/SessionDetail'))\nconst Events = lazy(() => import('./pages/Events'))\nconst Skills = lazy(() => import('./pages/Skills'))\nconst AIConfig = lazy(() => import('./pages/AIConfig'))\nconst Tasks = lazy(() => import('./pages/Tasks'))\nconst TaskDetail = lazy(() => import('./pages/TaskDetail'))\nconst Reports = lazy(() => import('./pages/Reports'))\n\nfunction PageFallback() {\n return (\n <div className=\"flex items-center justify-center h-full py-16\">\n <div className=\"flex items-center gap-3 text-sm text-gray-500\">\n <div className=\"w-4 h-4 border-2 border-gray-300 border-t-blue-500 rounded-full animate-spin\" />\n 加载中...\n </div>\n </div>\n )\n}\n\nexport default function App() {\n return (\n <Routes>\n <Route path=\"/\" element={<Layout />}>\n <Route\n index\n element={<Navigate to=\"/dashboard\" replace />}\n />\n <Route\n path=\"dashboard\"\n element={\n <Suspense fallback={<PageFallback />}>\n <Dashboard />\n </Suspense>\n }\n />\n <Route\n path=\"sessions\"\n element={\n <Suspense fallback={<PageFallback />}>\n <Sessions />\n </Suspense>\n }\n />\n <Route\n path=\"sessions/:id\"\n element={\n <Suspense fallback={<PageFallback />}>\n <SessionDetail />\n </Suspense>\n }\n />\n <Route\n path=\"events\"\n element={\n <Suspense fallback={<PageFallback />}>\n <Events />\n </Suspense>\n }\n />\n <Route\n path=\"skills\"\n element={\n <Suspense fallback={<PageFallback />}>\n <Skills />\n </Suspense>\n }\n />\n <Route\n path=\"ai-config\"\n element={\n <Suspense fallback={<PageFallback />}>\n <AIConfig />\n </Suspense>\n }\n />\n <Route\n path=\"tasks\"\n element={\n <Suspense fallback={<PageFallback />}>\n <Tasks />\n </Suspense>\n }\n />\n <Route\n path=\"tasks/:taskId\"\n element={\n <Suspense fallback={<PageFallback />}>\n <TaskDetail />\n </Suspense>\n }\n />\n <Route\n path=\"reports\"\n element={\n <Suspense fallback={<PageFallback />}>\n <Reports />\n </Suspense>\n }\n />\n </Route>\n </Routes>\n )\n}\n","import { createContext, useContext, useState, useCallback, ReactNode } from 'react'\nimport { CheckCircle, XCircle, AlertCircle, Info, X } from 'lucide-react'\nimport clsx from 'clsx'\n\ntype ToastType = 'success' | 'error' | 'warning' | 'info'\n\ninterface Toast {\n id: number\n type: ToastType\n message: string\n}\n\ninterface ToastContextValue {\n show: (type: ToastType, message: string) => void\n success: (message: string) => void\n error: (message: string) => void\n warning: (message: string) => void\n info: (message: string) => void\n}\n\nconst ToastContext = createContext<ToastContextValue | null>(null)\n\nexport function useToast() {\n const ctx = useContext(ToastContext)\n if (!ctx) throw new Error('useToast must be used within ToastProvider')\n return ctx\n}\n\nlet nextId = 1\n\nexport function ToastProvider({ children }: { children: ReactNode }) {\n const [toasts, setToasts] = useState<Toast[]>([])\n\n const remove = useCallback((id: number) => {\n setToasts(prev => prev.filter(t => t.id !== id))\n }, [])\n\n const show = useCallback((type: ToastType, message: string) => {\n const id = nextId++\n setToasts(prev => [...prev, { id, type, message }])\n setTimeout(() => remove(id), 4000)\n }, [remove])\n\n const value: ToastContextValue = {\n show,\n success: (msg) => show('success', msg),\n error: (msg) => show('error', msg),\n warning: (msg) => show('warning', msg),\n info: (msg) => show('info', msg),\n }\n\n return (\n <ToastContext.Provider value={value}>\n {children}\n <div className=\"fixed top-4 right-4 z-[9999] space-y-2 max-w-md\">\n {toasts.map(t => (\n <ToastItem key={t.id} toast={t} onClose={() => remove(t.id)} />\n ))}\n </div>\n </ToastContext.Provider>\n )\n}\n\nfunction ToastItem({ toast, onClose }: { toast: Toast; onClose: () => void }) {\n const icons = {\n success: <CheckCircle className=\"h-5 w-5 text-green-500\" />,\n error: <XCircle className=\"h-5 w-5 text-red-500\" />,\n warning: <AlertCircle className=\"h-5 w-5 text-yellow-500\" />,\n info: <Info className=\"h-5 w-5 text-blue-500\" />,\n }\n const borderColors = {\n success: 'border-green-200',\n error: 'border-red-200',\n warning: 'border-yellow-200',\n info: 'border-blue-200',\n }\n\n return (\n <div\n className={clsx(\n 'bg-white shadow-lg rounded-lg border px-4 py-3 flex items-start gap-3 animate-in slide-in-from-right',\n borderColors[toast.type]\n )}\n >\n {icons[toast.type]}\n <div className=\"flex-1 text-sm text-gray-800\">{toast.message}</div>\n <button onClick={onClose} className=\"text-gray-400 hover:text-gray-600\">\n <X className=\"h-4 w-4\" />\n </button>\n </div>\n )\n}\n","import { createContext, useContext, useState, useCallback, ReactNode } from 'react'\nimport { AlertTriangle } from 'lucide-react'\n\ninterface ConfirmOptions {\n title: string\n message: string\n confirmText?: string\n cancelText?: string\n variant?: 'danger' | 'warning' | 'info'\n}\n\ninterface ConfirmContextValue {\n confirm: (options: ConfirmOptions) => Promise<boolean>\n}\n\nconst ConfirmContext = createContext<ConfirmContextValue | null>(null)\n\nexport function useConfirm() {\n const ctx = useContext(ConfirmContext)\n if (!ctx) throw new Error('useConfirm must be used within ConfirmProvider')\n return ctx.confirm\n}\n\nexport function ConfirmProvider({ children }: { children: ReactNode }) {\n const [state, setState] = useState<{\n open: boolean\n options: ConfirmOptions | null\n resolve: ((value: boolean) => void) | null\n }>({ open: false, options: null, resolve: null })\n\n const confirm = useCallback((options: ConfirmOptions): Promise<boolean> => {\n return new Promise((resolve) => {\n setState({ open: true, options, resolve })\n })\n }, [])\n\n const handleClose = (result: boolean) => {\n if (state.resolve) state.resolve(result)\n setState({ open: false, options: null, resolve: null })\n }\n\n const variant = state.options?.variant || 'danger'\n const iconColor = {\n danger: 'text-red-600',\n warning: 'text-yellow-600',\n info: 'text-blue-600',\n }[variant]\n const btnColor = {\n danger: 'bg-red-600 hover:bg-red-700',\n warning: 'bg-yellow-600 hover:bg-yellow-700',\n info: 'bg-indigo-600 hover:bg-indigo-700',\n }[variant]\n\n return (\n <ConfirmContext.Provider value={{ confirm }}>\n {children}\n {state.open && state.options && (\n <div className=\"fixed inset-0 z-[9999] flex items-center justify-center\">\n <div\n className=\"absolute inset-0 bg-black bg-opacity-50\"\n onClick={() => handleClose(false)}\n />\n <div className=\"relative bg-white rounded-lg shadow-xl max-w-md w-full mx-4 p-6\">\n <div className=\"flex items-start gap-4\">\n <div className={`flex-shrink-0 ${iconColor}`}>\n <AlertTriangle className=\"h-6 w-6\" />\n </div>\n <div className=\"flex-1\">\n <h3 className=\"text-lg font-semibold text-gray-900 mb-2\">\n {state.options.title}\n </h3>\n <p className=\"text-sm text-gray-600 whitespace-pre-wrap\">\n {state.options.message}\n </p>\n </div>\n </div>\n <div className=\"flex justify-end gap-2 mt-6\">\n <button\n onClick={() => handleClose(false)}\n className=\"px-4 py-2 text-sm text-gray-700 bg-white border border-gray-300 rounded hover:bg-gray-50\"\n >\n {state.options.cancelText || '取消'}\n </button>\n <button\n onClick={() => handleClose(true)}\n className={`px-4 py-2 text-sm text-white rounded ${btnColor}`}\n >\n {state.options.confirmText || '确定'}\n </button>\n </div>\n </div>\n </div>\n )}\n </ConfirmContext.Provider>\n )\n}\n","import React from 'react'\nimport ReactDOM from 'react-dom/client'\nimport { BrowserRouter } from 'react-router-dom'\nimport { QueryClient, QueryClientProvider } from '@tanstack/react-query'\nimport App from './App'\nimport { ToastProvider } from './components/Toast'\nimport { ConfirmProvider } from './components/Confirm'\nimport './index.css'\n\nconst queryClient = new QueryClient({\n defaultOptions: {\n queries: {\n refetchOnWindowFocus: false,\n retry: 1,\n },\n },\n})\n\nReactDOM.createRoot(document.getElementById('root')!).render(\n <React.StrictMode>\n <QueryClientProvider client={queryClient}>\n <ToastProvider>\n <ConfirmProvider>\n <BrowserRouter>\n <App />\n </BrowserRouter>\n </ConfirmProvider>\n </ToastProvider>\n </QueryClientProvider>\n </React.StrictMode>,\n)\n"],"file":"assets/index-CBX47X8l.js"}
@@ -0,0 +1 @@
1
+ *,:before,:after{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }*,:before,:after{box-sizing:border-box;border-width:0;border-style:solid;border-color:#e5e7eb}:before,:after{--tw-content: ""}html,:host{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji",Segoe UI Symbol,"Noto Color Emoji";font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dl,dd,h1,h2,h3,h4,h5,h6,hr,figure,p,pre{margin:0}fieldset{margin:0;padding:0}legend{padding:0}ol,ul,menu{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}button,[role=button]{cursor:pointer}:disabled{cursor:default}img,svg,video,canvas,audio,iframe,embed,object{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]:where(:not([hidden=until-found])){display:none}.pointer-events-none{pointer-events:none}.visible{visibility:visible}.invisible{visibility:hidden}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.sticky{position:sticky}.inset-0{top:0;right:0;bottom:0;left:0}.inset-y-0{top:0;bottom:0}.bottom-2{bottom:.5rem}.left-0{left:0}.left-2\.5{left:.625rem}.left-\[19px\]{left:19px}.right-0{right:0}.right-2{right:.5rem}.right-4{right:1rem}.top-0{top:0}.top-1\/2{top:50%}.top-2{top:.5rem}.top-4{top:1rem}.z-10{z-index:10}.z-20{z-index:20}.z-40{z-index:40}.z-50{z-index:50}.z-\[9999\]{z-index:9999}.mx-2{margin-left:.5rem;margin-right:.5rem}.mx-4{margin-left:1rem;margin-right:1rem}.mx-auto{margin-left:auto;margin-right:auto}.my-2{margin-top:.5rem;margin-bottom:.5rem}.-ml-px{margin-left:-1px}.mb-0\.5{margin-bottom:.125rem}.mb-1{margin-bottom:.25rem}.mb-2{margin-bottom:.5rem}.mb-3{margin-bottom:.75rem}.mb-4{margin-bottom:1rem}.mb-5{margin-bottom:1.25rem}.mb-6{margin-bottom:1.5rem}.ml-2{margin-left:.5rem}.ml-3{margin-left:.75rem}.ml-auto{margin-left:auto}.mr-1{margin-right:.25rem}.mr-2{margin-right:.5rem}.mr-3{margin-right:.75rem}.mt-0\.5{margin-top:.125rem}.mt-1{margin-top:.25rem}.mt-2{margin-top:.5rem}.mt-3{margin-top:.75rem}.mt-4{margin-top:1rem}.mt-6{margin-top:1.5rem}.line-clamp-2{overflow:hidden;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2}.line-clamp-3{overflow:hidden;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:3}.block{display:block}.\!inline{display:inline!important}.inline{display:inline}.flex{display:flex}.inline-flex{display:inline-flex}.table{display:table}.grid{display:grid}.hidden{display:none}.h-10{height:2.5rem}.h-12{height:3rem}.h-14{height:3.5rem}.h-3{height:.75rem}.h-3\.5{height:.875rem}.h-4{height:1rem}.h-5{height:1.25rem}.h-6{height:1.5rem}.h-8{height:2rem}.h-\[100px\]{height:100px}.h-\[120px\]{height:120px}.h-\[240px\]{height:240px}.h-full{height:100%}.max-h-40{max-height:10rem}.max-h-60{max-height:15rem}.max-h-64{max-height:16rem}.max-h-\[500px\]{max-height:500px}.min-h-screen{min-height:100vh}.w-10{width:2.5rem}.w-12{width:3rem}.w-3{width:.75rem}.w-3\.5{width:.875rem}.w-4{width:1rem}.w-5{width:1.25rem}.w-6{width:1.5rem}.w-64{width:16rem}.w-72{width:18rem}.w-8{width:2rem}.w-\[600px\]{width:600px}.w-\[800px\]{width:800px}.w-full{width:100%}.w-px{width:1px}.min-w-0{min-width:0px}.min-w-full{min-width:100%}.max-w-2xl{max-width:42rem}.max-w-7xl{max-width:80rem}.max-w-full{max-width:100%}.max-w-md{max-width:28rem}.max-w-none{max-width:none}.max-w-xl{max-width:36rem}.flex-1{flex:1 1 0%}.flex-shrink-0,.shrink-0{flex-shrink:0}.flex-grow{flex-grow:1}.-translate-y-1\/2{--tw-translate-y: -50%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.translate-x-0{--tw-translate-x: 0px;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.translate-x-full{--tw-translate-x: 100%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.transform{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}@keyframes spin{to{transform:rotate(360deg)}}.animate-spin{animation:spin 1s linear infinite}.cursor-pointer{cursor:pointer}.list-inside{list-style-position:inside}.list-decimal{list-style-type:decimal}.list-disc{list-style-type:disc}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-start{align-items:flex-start}.items-center{align-items:center}.justify-end{justify-content:flex-end}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-1{gap:.25rem}.gap-1\.5{gap:.375rem}.gap-2{gap:.5rem}.gap-3{gap:.75rem}.gap-4{gap:1rem}.gap-6{gap:1.5rem}.space-y-0>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(0px * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(0px * var(--tw-space-y-reverse))}.space-y-0\.5>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.125rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.125rem * var(--tw-space-y-reverse))}.space-y-1>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.25rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.25rem * var(--tw-space-y-reverse))}.space-y-1\.5>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.375rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.375rem * var(--tw-space-y-reverse))}.space-y-2>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.5rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.5rem * var(--tw-space-y-reverse))}.space-y-3>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.75rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.75rem * var(--tw-space-y-reverse))}.space-y-4>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(1rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1rem * var(--tw-space-y-reverse))}.divide-y>:not([hidden])~:not([hidden]){--tw-divide-y-reverse: 0;border-top-width:calc(1px * calc(1 - var(--tw-divide-y-reverse)));border-bottom-width:calc(1px * var(--tw-divide-y-reverse))}.divide-gray-200>:not([hidden])~:not([hidden]){--tw-divide-opacity: 1;border-color:rgb(229 231 235 / var(--tw-divide-opacity, 1))}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.whitespace-nowrap{white-space:nowrap}.whitespace-pre-wrap{white-space:pre-wrap}.break-words{overflow-wrap:break-word}.break-all{word-break:break-all}.rounded{border-radius:.25rem}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:.5rem}.rounded-md{border-radius:.375rem}.rounded-l-md{border-top-left-radius:.375rem;border-bottom-left-radius:.375rem}.rounded-r-md{border-top-right-radius:.375rem;border-bottom-right-radius:.375rem}.rounded-t-lg{border-top-left-radius:.5rem;border-top-right-radius:.5rem}.border{border-width:1px}.border-2{border-width:2px}.border-b{border-bottom-width:1px}.border-l-4{border-left-width:4px}.border-r{border-right-width:1px}.border-t{border-top-width:1px}.border-amber-200{--tw-border-opacity: 1;border-color:rgb(253 230 138 / var(--tw-border-opacity, 1))}.border-amber-500{--tw-border-opacity: 1;border-color:rgb(245 158 11 / var(--tw-border-opacity, 1))}.border-blue-100{--tw-border-opacity: 1;border-color:rgb(219 234 254 / var(--tw-border-opacity, 1))}.border-blue-200{--tw-border-opacity: 1;border-color:rgb(191 219 254 / var(--tw-border-opacity, 1))}.border-blue-400{--tw-border-opacity: 1;border-color:rgb(96 165 250 / var(--tw-border-opacity, 1))}.border-emerald-200{--tw-border-opacity: 1;border-color:rgb(167 243 208 / var(--tw-border-opacity, 1))}.border-gray-100{--tw-border-opacity: 1;border-color:rgb(243 244 246 / var(--tw-border-opacity, 1))}.border-gray-200{--tw-border-opacity: 1;border-color:rgb(229 231 235 / var(--tw-border-opacity, 1))}.border-gray-300{--tw-border-opacity: 1;border-color:rgb(209 213 219 / var(--tw-border-opacity, 1))}.border-green-200{--tw-border-opacity: 1;border-color:rgb(187 247 208 / var(--tw-border-opacity, 1))}.border-indigo-300{--tw-border-opacity: 1;border-color:rgb(165 180 252 / var(--tw-border-opacity, 1))}.border-indigo-600{--tw-border-opacity: 1;border-color:rgb(79 70 229 / var(--tw-border-opacity, 1))}.border-purple-100{--tw-border-opacity: 1;border-color:rgb(243 232 255 / var(--tw-border-opacity, 1))}.border-red-200{--tw-border-opacity: 1;border-color:rgb(254 202 202 / var(--tw-border-opacity, 1))}.border-red-500{--tw-border-opacity: 1;border-color:rgb(239 68 68 / var(--tw-border-opacity, 1))}.border-yellow-200{--tw-border-opacity: 1;border-color:rgb(254 240 138 / var(--tw-border-opacity, 1))}.border-t-blue-500{--tw-border-opacity: 1;border-top-color:rgb(59 130 246 / var(--tw-border-opacity, 1))}.bg-amber-50{--tw-bg-opacity: 1;background-color:rgb(255 251 235 / var(--tw-bg-opacity, 1))}.bg-amber-50\/30{background-color:#fffbeb4d}.bg-black{--tw-bg-opacity: 1;background-color:rgb(0 0 0 / var(--tw-bg-opacity, 1))}.bg-blue-100{--tw-bg-opacity: 1;background-color:rgb(219 234 254 / var(--tw-bg-opacity, 1))}.bg-blue-50{--tw-bg-opacity: 1;background-color:rgb(239 246 255 / var(--tw-bg-opacity, 1))}.bg-blue-50\/30{background-color:#eff6ff4d}.bg-emerald-50{--tw-bg-opacity: 1;background-color:rgb(236 253 245 / var(--tw-bg-opacity, 1))}.bg-emerald-600{--tw-bg-opacity: 1;background-color:rgb(5 150 105 / var(--tw-bg-opacity, 1))}.bg-gray-100{--tw-bg-opacity: 1;background-color:rgb(243 244 246 / var(--tw-bg-opacity, 1))}.bg-gray-200{--tw-bg-opacity: 1;background-color:rgb(229 231 235 / var(--tw-bg-opacity, 1))}.bg-gray-50{--tw-bg-opacity: 1;background-color:rgb(249 250 251 / var(--tw-bg-opacity, 1))}.bg-gray-600{--tw-bg-opacity: 1;background-color:rgb(75 85 99 / var(--tw-bg-opacity, 1))}.bg-green-100{--tw-bg-opacity: 1;background-color:rgb(220 252 231 / var(--tw-bg-opacity, 1))}.bg-green-50{--tw-bg-opacity: 1;background-color:rgb(240 253 244 / var(--tw-bg-opacity, 1))}.bg-indigo-100{--tw-bg-opacity: 1;background-color:rgb(224 231 255 / var(--tw-bg-opacity, 1))}.bg-indigo-50{--tw-bg-opacity: 1;background-color:rgb(238 242 255 / var(--tw-bg-opacity, 1))}.bg-indigo-600{--tw-bg-opacity: 1;background-color:rgb(79 70 229 / var(--tw-bg-opacity, 1))}.bg-purple-100{--tw-bg-opacity: 1;background-color:rgb(243 232 255 / var(--tw-bg-opacity, 1))}.bg-purple-50{--tw-bg-opacity: 1;background-color:rgb(250 245 255 / var(--tw-bg-opacity, 1))}.bg-red-50{--tw-bg-opacity: 1;background-color:rgb(254 242 242 / var(--tw-bg-opacity, 1))}.bg-red-50\/30{background-color:#fef2f24d}.bg-red-600{--tw-bg-opacity: 1;background-color:rgb(220 38 38 / var(--tw-bg-opacity, 1))}.bg-white{--tw-bg-opacity: 1;background-color:rgb(255 255 255 / var(--tw-bg-opacity, 1))}.bg-yellow-100{--tw-bg-opacity: 1;background-color:rgb(254 249 195 / var(--tw-bg-opacity, 1))}.bg-yellow-600{--tw-bg-opacity: 1;background-color:rgb(202 138 4 / var(--tw-bg-opacity, 1))}.bg-opacity-0{--tw-bg-opacity: 0}.bg-opacity-50{--tw-bg-opacity: .5}.bg-opacity-75{--tw-bg-opacity: .75}.bg-gradient-to-br{background-image:linear-gradient(to bottom right,var(--tw-gradient-stops))}.from-indigo-500{--tw-gradient-from: #6366f1 var(--tw-gradient-from-position);--tw-gradient-to: rgb(99 102 241 / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to)}.to-purple-600{--tw-gradient-to: #9333ea var(--tw-gradient-to-position)}.p-12{padding:3rem}.p-2{padding:.5rem}.p-3{padding:.75rem}.p-4{padding:1rem}.p-5{padding:1.25rem}.p-6{padding:1.5rem}.px-1{padding-left:.25rem;padding-right:.25rem}.px-1\.5{padding-left:.375rem;padding-right:.375rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-4{padding-left:1rem;padding-right:1rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.py-0\.5{padding-top:.125rem;padding-bottom:.125rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-1\.5{padding-top:.375rem;padding-bottom:.375rem}.py-12{padding-top:3rem;padding-bottom:3rem}.py-16{padding-top:4rem;padding-bottom:4rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.py-4{padding-top:1rem;padding-bottom:1rem}.py-6{padding-top:1.5rem;padding-bottom:1.5rem}.pb-3{padding-bottom:.75rem}.pb-4{padding-bottom:1rem}.pl-3{padding-left:.75rem}.pl-8{padding-left:2rem}.pr-10{padding-right:2.5rem}.pr-8{padding-right:2rem}.pt-1{padding-top:.25rem}.pt-3{padding-top:.75rem}.pt-4{padding-top:1rem}.text-left{text-align:left}.text-center{text-align:center}.font-mono{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.text-2xl{font-size:1.5rem;line-height:2rem}.text-\[10px\]{font-size:10px}.text-base{font-size:1rem;line-height:1.5rem}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.text-xs{font-size:.75rem;line-height:1rem}.font-bold{font-weight:700}.font-medium{font-weight:500}.font-normal{font-weight:400}.font-semibold{font-weight:600}.uppercase{text-transform:uppercase}.italic{font-style:italic}.tracking-wider{letter-spacing:.05em}.text-amber-600{--tw-text-opacity: 1;color:rgb(217 119 6 / var(--tw-text-opacity, 1))}.text-amber-700{--tw-text-opacity: 1;color:rgb(180 83 9 / var(--tw-text-opacity, 1))}.text-amber-900{--tw-text-opacity: 1;color:rgb(120 53 15 / var(--tw-text-opacity, 1))}.text-blue-500{--tw-text-opacity: 1;color:rgb(59 130 246 / var(--tw-text-opacity, 1))}.text-blue-600{--tw-text-opacity: 1;color:rgb(37 99 235 / var(--tw-text-opacity, 1))}.text-blue-700{--tw-text-opacity: 1;color:rgb(29 78 216 / var(--tw-text-opacity, 1))}.text-blue-800{--tw-text-opacity: 1;color:rgb(30 64 175 / var(--tw-text-opacity, 1))}.text-cyan-600{--tw-text-opacity: 1;color:rgb(8 145 178 / var(--tw-text-opacity, 1))}.text-emerald-600{--tw-text-opacity: 1;color:rgb(5 150 105 / var(--tw-text-opacity, 1))}.text-emerald-700{--tw-text-opacity: 1;color:rgb(4 120 87 / var(--tw-text-opacity, 1))}.text-gray-300{--tw-text-opacity: 1;color:rgb(209 213 219 / var(--tw-text-opacity, 1))}.text-gray-400{--tw-text-opacity: 1;color:rgb(156 163 175 / var(--tw-text-opacity, 1))}.text-gray-500{--tw-text-opacity: 1;color:rgb(107 114 128 / var(--tw-text-opacity, 1))}.text-gray-600{--tw-text-opacity: 1;color:rgb(75 85 99 / var(--tw-text-opacity, 1))}.text-gray-700{--tw-text-opacity: 1;color:rgb(55 65 81 / var(--tw-text-opacity, 1))}.text-gray-800{--tw-text-opacity: 1;color:rgb(31 41 55 / var(--tw-text-opacity, 1))}.text-gray-900{--tw-text-opacity: 1;color:rgb(17 24 39 / var(--tw-text-opacity, 1))}.text-green-500{--tw-text-opacity: 1;color:rgb(34 197 94 / var(--tw-text-opacity, 1))}.text-green-600{--tw-text-opacity: 1;color:rgb(22 163 74 / var(--tw-text-opacity, 1))}.text-green-700{--tw-text-opacity: 1;color:rgb(21 128 61 / var(--tw-text-opacity, 1))}.text-green-800{--tw-text-opacity: 1;color:rgb(22 101 52 / var(--tw-text-opacity, 1))}.text-indigo-500{--tw-text-opacity: 1;color:rgb(99 102 241 / var(--tw-text-opacity, 1))}.text-indigo-600{--tw-text-opacity: 1;color:rgb(79 70 229 / var(--tw-text-opacity, 1))}.text-indigo-700{--tw-text-opacity: 1;color:rgb(67 56 202 / var(--tw-text-opacity, 1))}.text-orange-600{--tw-text-opacity: 1;color:rgb(234 88 12 / var(--tw-text-opacity, 1))}.text-purple-500{--tw-text-opacity: 1;color:rgb(168 85 247 / var(--tw-text-opacity, 1))}.text-purple-600{--tw-text-opacity: 1;color:rgb(147 51 234 / var(--tw-text-opacity, 1))}.text-purple-700{--tw-text-opacity: 1;color:rgb(126 34 206 / var(--tw-text-opacity, 1))}.text-purple-800{--tw-text-opacity: 1;color:rgb(107 33 168 / var(--tw-text-opacity, 1))}.text-red-500{--tw-text-opacity: 1;color:rgb(239 68 68 / var(--tw-text-opacity, 1))}.text-red-600{--tw-text-opacity: 1;color:rgb(220 38 38 / var(--tw-text-opacity, 1))}.text-red-700{--tw-text-opacity: 1;color:rgb(185 28 28 / var(--tw-text-opacity, 1))}.text-red-800{--tw-text-opacity: 1;color:rgb(153 27 27 / var(--tw-text-opacity, 1))}.text-rose-600{--tw-text-opacity: 1;color:rgb(225 29 72 / var(--tw-text-opacity, 1))}.text-white{--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity, 1))}.text-yellow-500{--tw-text-opacity: 1;color:rgb(234 179 8 / var(--tw-text-opacity, 1))}.text-yellow-600{--tw-text-opacity: 1;color:rgb(202 138 4 / var(--tw-text-opacity, 1))}.text-yellow-700{--tw-text-opacity: 1;color:rgb(161 98 7 / var(--tw-text-opacity, 1))}.underline{text-decoration-line:underline}.shadow{--tw-shadow: 0 1px 3px 0 rgb(0 0 0 / .1), 0 1px 2px -1px rgb(0 0 0 / .1);--tw-shadow-colored: 0 1px 3px 0 var(--tw-shadow-color), 0 1px 2px -1px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-lg{--tw-shadow: 0 10px 15px -3px rgb(0 0 0 / .1), 0 4px 6px -4px rgb(0 0 0 / .1);--tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-sm{--tw-shadow: 0 1px 2px 0 rgb(0 0 0 / .05);--tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-xl{--tw-shadow: 0 20px 25px -5px rgb(0 0 0 / .1), 0 8px 10px -6px rgb(0 0 0 / .1);--tw-shadow-colored: 0 20px 25px -5px var(--tw-shadow-color), 0 8px 10px -6px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.transition-colors{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-opacity{transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-shadow{transition-property:box-shadow;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-transform{transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}:root{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,PingFang SC,sans-serif;line-height:1.5;font-weight:400;color-scheme:light;font-synthesis:none;text-rendering:optimizeLegibility;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}body{margin:0;min-height:100vh}.hover\:bg-blue-100:hover{--tw-bg-opacity: 1;background-color:rgb(219 234 254 / var(--tw-bg-opacity, 1))}.hover\:bg-emerald-700:hover{--tw-bg-opacity: 1;background-color:rgb(4 120 87 / var(--tw-bg-opacity, 1))}.hover\:bg-gray-200:hover{--tw-bg-opacity: 1;background-color:rgb(229 231 235 / var(--tw-bg-opacity, 1))}.hover\:bg-gray-50:hover{--tw-bg-opacity: 1;background-color:rgb(249 250 251 / var(--tw-bg-opacity, 1))}.hover\:bg-green-50:hover{--tw-bg-opacity: 1;background-color:rgb(240 253 244 / var(--tw-bg-opacity, 1))}.hover\:bg-indigo-50:hover{--tw-bg-opacity: 1;background-color:rgb(238 242 255 / var(--tw-bg-opacity, 1))}.hover\:bg-indigo-700:hover{--tw-bg-opacity: 1;background-color:rgb(67 56 202 / var(--tw-bg-opacity, 1))}.hover\:bg-red-700:hover{--tw-bg-opacity: 1;background-color:rgb(185 28 28 / var(--tw-bg-opacity, 1))}.hover\:bg-yellow-700:hover{--tw-bg-opacity: 1;background-color:rgb(161 98 7 / var(--tw-bg-opacity, 1))}.hover\:text-gray-600:hover{--tw-text-opacity: 1;color:rgb(75 85 99 / var(--tw-text-opacity, 1))}.hover\:text-gray-700:hover{--tw-text-opacity: 1;color:rgb(55 65 81 / var(--tw-text-opacity, 1))}.hover\:text-indigo-700:hover{--tw-text-opacity: 1;color:rgb(67 56 202 / var(--tw-text-opacity, 1))}.hover\:shadow-md:hover{--tw-shadow: 0 4px 6px -1px rgb(0 0 0 / .1), 0 2px 4px -2px rgb(0 0 0 / .1);--tw-shadow-colored: 0 4px 6px -1px var(--tw-shadow-color), 0 2px 4px -2px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.focus\:border-indigo-500:focus{--tw-border-opacity: 1;border-color:rgb(99 102 241 / var(--tw-border-opacity, 1))}.focus\:outline-none:focus{outline:2px solid transparent;outline-offset:2px}.focus\:ring-1:focus{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.focus\:ring-indigo-500:focus{--tw-ring-opacity: 1;--tw-ring-color: rgb(99 102 241 / var(--tw-ring-opacity, 1))}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:bg-gray-400:disabled{--tw-bg-opacity: 1;background-color:rgb(156 163 175 / var(--tw-bg-opacity, 1))}.disabled\:bg-gray-50:disabled{--tw-bg-opacity: 1;background-color:rgb(249 250 251 / var(--tw-bg-opacity, 1))}.disabled\:text-gray-400:disabled{--tw-text-opacity: 1;color:rgb(156 163 175 / var(--tw-text-opacity, 1))}.disabled\:opacity-40:disabled{opacity:.4}.disabled\:opacity-50:disabled{opacity:.5}@media (min-width: 640px){.sm\:px-6{padding-left:1.5rem;padding-right:1.5rem}}@media (min-width: 768px){.md\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.md\:grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}}@media (min-width: 1024px){.lg\:fixed{position:fixed}.lg\:inset-y-0{top:0;bottom:0}.lg\:col-span-2{grid-column:span 2 / span 2}.lg\:flex{display:flex}.lg\:hidden{display:none}.lg\:w-64{width:16rem}.lg\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.lg\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.lg\:grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}.lg\:flex-col{flex-direction:column}.lg\:px-8{padding-left:2rem;padding-right:2rem}.lg\:pl-64{padding-left:16rem}}