@winspan/claude-forge 8.39.0 → 8.50.6
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.
- package/.claude/CLAUDE.md +17 -0
- package/.eslintrc.js +23 -0
- package/.prettierrc +8 -0
- package/ARCHITECTURE_ISSUES.md +249 -0
- package/CLAUDE.md +265 -0
- package/CLAUDE.md.backup +488 -0
- package/DEVELOPMENT.md +310 -0
- package/dist/claudemd/claudemd-generator.d.ts +38 -3
- package/dist/claudemd/claudemd-generator.d.ts.map +1 -1
- package/dist/claudemd/claudemd-generator.js +629 -11
- package/dist/claudemd/claudemd-generator.js.map +1 -1
- package/dist/claudemd/index.d.ts +2 -2
- package/dist/claudemd/index.d.ts.map +1 -1
- package/dist/claudemd/index.js.map +1 -1
- package/dist/claudemd/resume-manager.d.ts.map +1 -1
- package/dist/claudemd/resume-manager.js +5 -2
- package/dist/claudemd/resume-manager.js.map +1 -1
- package/dist/claudemd/tech-detector.d.ts +1 -0
- package/dist/claudemd/tech-detector.d.ts.map +1 -1
- package/dist/claudemd/tech-detector.js +53 -0
- package/dist/claudemd/tech-detector.js.map +1 -1
- package/dist/cli/commands/claudemd.js +2 -2
- package/dist/cli/commands/claudemd.js.map +1 -1
- package/dist/cli/commands/daemon.d.ts +28 -0
- package/dist/cli/commands/daemon.d.ts.map +1 -1
- package/dist/cli/commands/daemon.js +200 -8
- package/dist/cli/commands/daemon.js.map +1 -1
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/init.js +3 -35
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/commands/menu.js +10 -10
- package/dist/cli/commands/menu.js.map +1 -1
- package/dist/cli/commands/skills.d.ts.map +1 -1
- package/dist/cli/commands/skills.js +8 -2
- package/dist/cli/commands/skills.js.map +1 -1
- package/dist/cli/commands/stats.d.ts.map +1 -1
- package/dist/cli/commands/stats.js +0 -17
- package/dist/cli/commands/stats.js.map +1 -1
- package/dist/cli/commands/trace.d.ts +9 -0
- package/dist/cli/commands/trace.d.ts.map +1 -0
- package/dist/cli/commands/trace.js +137 -0
- package/dist/cli/commands/trace.js.map +1 -0
- package/dist/cli/index.js +2 -4
- package/dist/cli/index.js.map +1 -1
- package/dist/core/ai/provider.d.ts +10 -2
- package/dist/core/ai/provider.d.ts.map +1 -1
- package/dist/core/ai/provider.js.map +1 -1
- package/dist/core/ai/types.d.ts +1 -19
- package/dist/core/ai/types.d.ts.map +1 -1
- package/dist/core/ai/types.js +1 -1
- package/dist/core/config.d.ts +2 -1
- package/dist/core/config.d.ts.map +1 -1
- package/dist/core/config.js +30 -6
- package/dist/core/config.js.map +1 -1
- package/dist/core/constants.d.ts +2 -2
- package/dist/core/constants.js +2 -2
- package/dist/core/constants.js.map +1 -1
- package/dist/core/queue/index.d.ts +52 -0
- package/dist/core/queue/index.d.ts.map +1 -0
- package/dist/core/queue/index.js +176 -0
- package/dist/core/queue/index.js.map +1 -0
- package/dist/core/storage/base.d.ts +33 -0
- package/dist/core/storage/base.d.ts.map +1 -0
- package/dist/core/storage/base.js +211 -0
- package/dist/core/storage/base.js.map +1 -0
- package/dist/core/storage/events.d.ts +52 -0
- package/dist/core/storage/events.d.ts.map +1 -0
- package/dist/core/storage/events.js +201 -0
- package/dist/core/storage/events.js.map +1 -0
- package/dist/core/storage/injections.d.ts +27 -0
- package/dist/core/storage/injections.d.ts.map +1 -0
- package/dist/core/storage/injections.js +51 -0
- package/dist/core/storage/injections.js.map +1 -0
- package/dist/core/storage/maintenance.d.ts +21 -0
- package/dist/core/storage/maintenance.d.ts.map +1 -0
- package/dist/core/storage/maintenance.js +52 -0
- package/dist/core/storage/maintenance.js.map +1 -0
- package/dist/core/storage/routing.d.ts +71 -0
- package/dist/core/storage/routing.d.ts.map +1 -0
- package/dist/core/storage/routing.js +141 -0
- package/dist/core/storage/routing.js.map +1 -0
- package/dist/core/storage/rows.d.ts +0 -47
- package/dist/core/storage/rows.d.ts.map +1 -1
- package/dist/core/storage/schema.sql +74 -136
- package/dist/core/storage/sessions.d.ts +34 -0
- package/dist/core/storage/sessions.d.ts.map +1 -0
- package/dist/core/storage/sessions.js +78 -0
- package/dist/core/storage/sessions.js.map +1 -0
- package/dist/core/storage/skills.d.ts +40 -0
- package/dist/core/storage/skills.d.ts.map +1 -0
- package/dist/core/storage/skills.js +107 -0
- package/dist/core/storage/skills.js.map +1 -0
- package/dist/core/storage/sqlite.d.ts +63 -265
- package/dist/core/storage/sqlite.d.ts.map +1 -1
- package/dist/core/storage/sqlite.js +102 -759
- package/dist/core/storage/sqlite.js.map +1 -1
- package/dist/core/storage/tasks.d.ts +64 -0
- package/dist/core/storage/tasks.d.ts.map +1 -0
- package/dist/core/storage/tasks.js +134 -0
- package/dist/core/storage/tasks.js.map +1 -0
- package/dist/core/storage/token-usage.d.ts +36 -0
- package/dist/core/storage/token-usage.d.ts.map +1 -0
- package/dist/core/storage/token-usage.js +59 -0
- package/dist/core/storage/token-usage.js.map +1 -0
- package/dist/core/types.d.ts +70 -4
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js +24 -1
- package/dist/core/types.js.map +1 -1
- package/dist/core/utils/format.d.ts +28 -0
- package/dist/core/utils/format.d.ts.map +1 -0
- package/dist/core/utils/format.js +68 -0
- package/dist/core/utils/format.js.map +1 -0
- package/dist/core/utils/logger.d.ts +6 -1
- package/dist/core/utils/logger.d.ts.map +1 -1
- package/dist/core/utils/logger.js +72 -2
- package/dist/core/utils/logger.js.map +1 -1
- package/dist/core/utils/session.d.ts +16 -0
- package/dist/core/utils/session.d.ts.map +1 -0
- package/dist/core/utils/session.js +25 -0
- package/dist/core/utils/session.js.map +1 -0
- package/dist/core/utils/time.d.ts +22 -0
- package/dist/core/utils/time.d.ts.map +1 -0
- package/dist/core/utils/time.js +38 -0
- package/dist/core/utils/time.js.map +1 -0
- package/dist/daemon/handlers/history-exporter.d.ts.map +1 -1
- package/dist/daemon/handlers/history-exporter.js +6 -4
- package/dist/daemon/handlers/history-exporter.js.map +1 -1
- package/dist/daemon/handlers/post-tool-use.d.ts +5 -12
- package/dist/daemon/handlers/post-tool-use.d.ts.map +1 -1
- package/dist/daemon/handlers/post-tool-use.js +21 -79
- package/dist/daemon/handlers/post-tool-use.js.map +1 -1
- package/dist/daemon/handlers/stop.d.ts +24 -12
- package/dist/daemon/handlers/stop.d.ts.map +1 -1
- package/dist/daemon/handlers/stop.js +141 -42
- package/dist/daemon/handlers/stop.js.map +1 -1
- package/dist/daemon/handlers/user-prompt.d.ts +18 -19
- package/dist/daemon/handlers/user-prompt.d.ts.map +1 -1
- package/dist/daemon/handlers/user-prompt.js +103 -227
- package/dist/daemon/handlers/user-prompt.js.map +1 -1
- package/dist/daemon/index.d.ts +6 -2
- package/dist/daemon/index.d.ts.map +1 -1
- package/dist/daemon/index.js +76 -120
- package/dist/daemon/index.js.map +1 -1
- package/dist/daemon/launchd/com.claude-forge.daemon.plist.template +47 -0
- package/dist/daemon/launchd-installer.d.ts +61 -0
- package/dist/daemon/launchd-installer.d.ts.map +1 -0
- package/dist/daemon/launchd-installer.js +182 -0
- package/dist/daemon/launchd-installer.js.map +1 -0
- package/dist/daemon/lifecycle.d.ts +11 -0
- package/dist/daemon/lifecycle.d.ts.map +1 -1
- package/dist/daemon/lifecycle.js +44 -0
- package/dist/daemon/lifecycle.js.map +1 -1
- package/dist/daemon/router.d.ts +9 -2
- package/dist/daemon/router.d.ts.map +1 -1
- package/dist/daemon/router.js +27 -3
- package/dist/daemon/router.js.map +1 -1
- package/dist/daemon/server.d.ts.map +1 -1
- package/dist/daemon/server.js +6 -5
- package/dist/daemon/server.js.map +1 -1
- package/dist/daemon/services/anti-pattern-detector.d.ts +50 -0
- package/dist/daemon/services/anti-pattern-detector.d.ts.map +1 -0
- package/dist/daemon/services/anti-pattern-detector.js +357 -0
- package/dist/daemon/services/anti-pattern-detector.js.map +1 -0
- package/dist/daemon/services/drift-detector.d.ts +64 -0
- package/dist/daemon/services/drift-detector.d.ts.map +1 -0
- package/dist/daemon/services/drift-detector.js +201 -0
- package/dist/daemon/services/drift-detector.js.map +1 -0
- package/dist/{intelligence → daemon/services}/task-segmenter.d.ts +7 -1
- package/dist/daemon/services/task-segmenter.d.ts.map +1 -0
- package/dist/{intelligence → daemon/services}/task-segmenter.js +29 -6
- package/dist/daemon/services/task-segmenter.js.map +1 -0
- package/dist/daemon/services/weekly-report.d.ts +91 -0
- package/dist/daemon/services/weekly-report.d.ts.map +1 -0
- package/dist/daemon/services/weekly-report.js +327 -0
- package/dist/daemon/services/weekly-report.js.map +1 -0
- package/dist/hooks/hook-lib.sh +81 -0
- package/dist/hooks/notification.sh +7 -3
- package/dist/hooks/post-tool-use.sh +8 -4
- package/dist/hooks/pre-tool-use.sh +7 -4
- package/dist/hooks/stop.sh +1 -1
- package/dist/hooks/user-prompt-submit.sh +8 -9
- package/dist/mcp/server.d.ts +2 -2
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +71 -11
- package/dist/mcp/server.js.map +1 -1
- package/dist/skills/invocation-guard.d.ts +20 -0
- package/dist/skills/invocation-guard.d.ts.map +1 -1
- package/dist/skills/invocation-guard.js +63 -0
- package/dist/skills/invocation-guard.js.map +1 -1
- package/dist/skills/matcher.d.ts.map +1 -1
- package/dist/skills/matcher.js +12 -3
- package/dist/skills/matcher.js.map +1 -1
- package/dist/skills/official/code-simplifier.md +16 -0
- package/dist/skills/official/find-skills.md +23 -0
- package/dist/skills/official/official-api-design.md +17 -0
- package/dist/skills/official/official-architecture-decision.md +20 -0
- package/dist/skills/official/official-bmad.md +118 -0
- package/dist/skills/official/official-db-schema-design.md +16 -0
- package/dist/skills/official/official-debug.md +17 -0
- package/dist/skills/official/official-doc-driven.md +31 -0
- package/dist/skills/official/official-harness-engineering.md +108 -0
- package/dist/skills/official/official-performance-optimization.md +30 -0
- package/dist/skills/official/official-pr-review.md +35 -0
- package/dist/skills/official/official-release-checklist.md +30 -0
- package/dist/skills/official/official-security-hardening.md +26 -0
- package/dist/skills/official/official-spec-driven-design.md +31 -0
- package/dist/skills/official/planning-with-files.md +37 -0
- package/dist/skills/official/ui-ux-pro-max.md +18 -0
- package/dist/skills/official/webapp-testing.md +12 -0
- package/dist/skills/official-skills.d.ts +8 -4
- package/dist/skills/official-skills.d.ts.map +1 -1
- package/dist/skills/official-skills.js +48 -704
- package/dist/skills/official-skills.js.map +1 -1
- package/dist/skills/registry.d.ts +5 -0
- package/dist/skills/registry.d.ts.map +1 -1
- package/dist/skills/registry.js +48 -15
- package/dist/skills/registry.js.map +1 -1
- package/dist/skills/tools/pipeline-suggest.d.ts +30 -0
- package/dist/skills/tools/pipeline-suggest.d.ts.map +1 -0
- package/dist/skills/tools/pipeline-suggest.js +178 -0
- package/dist/skills/tools/pipeline-suggest.js.map +1 -0
- package/dist/skills/tools/skill-invoke.d.ts +2 -0
- package/dist/skills/tools/skill-invoke.d.ts.map +1 -1
- package/dist/skills/tools/skill-invoke.js +5 -2
- package/dist/skills/tools/skill-invoke.js.map +1 -1
- package/dist/web/routes/ai.d.ts.map +1 -1
- package/dist/web/routes/ai.js +16 -22
- package/dist/web/routes/ai.js.map +1 -1
- package/dist/web/routes/drift.d.ts +10 -0
- package/dist/web/routes/drift.d.ts.map +1 -0
- package/dist/web/routes/drift.js +21 -0
- package/dist/web/routes/drift.js.map +1 -0
- package/dist/web/routes/error-handler.d.ts +43 -0
- package/dist/web/routes/error-handler.d.ts.map +1 -0
- package/dist/web/routes/error-handler.js +99 -0
- package/dist/web/routes/error-handler.js.map +1 -0
- package/dist/web/routes/insights.d.ts +9 -0
- package/dist/web/routes/insights.d.ts.map +1 -0
- package/dist/web/routes/insights.js +34 -0
- package/dist/web/routes/insights.js.map +1 -0
- package/dist/web/routes/patch.js +2 -2
- package/dist/web/routes/patch.js.map +1 -1
- package/dist/web/routes/reports.d.ts +10 -0
- package/dist/web/routes/reports.d.ts.map +1 -0
- package/dist/web/routes/reports.js +27 -0
- package/dist/web/routes/reports.js.map +1 -0
- package/dist/web/routes/rules.d.ts +10 -3
- package/dist/web/routes/rules.d.ts.map +1 -1
- package/dist/web/routes/rules.js +80 -95
- package/dist/web/routes/rules.js.map +1 -1
- package/dist/web/routes/sessions.d.ts +1 -2
- package/dist/web/routes/sessions.d.ts.map +1 -1
- package/dist/web/routes/sessions.js +27 -39
- package/dist/web/routes/sessions.js.map +1 -1
- package/dist/web/routes/skill-stats.d.ts.map +1 -1
- package/dist/web/routes/skill-stats.js +38 -0
- package/dist/web/routes/skill-stats.js.map +1 -1
- package/dist/web/routes/skills.d.ts.map +1 -1
- package/dist/web/routes/skills.js +34 -0
- package/dist/web/routes/skills.js.map +1 -1
- package/dist/web/routes/stats.d.ts +7 -0
- package/dist/web/routes/stats.d.ts.map +1 -0
- package/dist/web/routes/stats.js +44 -0
- package/dist/web/routes/stats.js.map +1 -0
- package/dist/web/routes/status.js +1 -1
- package/dist/web/routes/status.js.map +1 -1
- package/dist/web/routes/tasks.d.ts +4 -0
- package/dist/web/routes/tasks.d.ts.map +1 -0
- package/dist/web/routes/tasks.js +181 -0
- package/dist/web/routes/tasks.js.map +1 -0
- package/dist/web/routes/trace.d.ts +10 -0
- package/dist/web/routes/trace.d.ts.map +1 -0
- package/dist/web/routes/trace.js +123 -0
- package/dist/web/routes/trace.js.map +1 -0
- package/dist/web/routes/types.d.ts +1 -14
- package/dist/web/routes/types.d.ts.map +1 -1
- package/dist/web/routes/types.js +8 -17
- package/dist/web/routes/types.js.map +1 -1
- package/dist/web/server.d.ts +1 -9
- package/dist/web/server.d.ts.map +1 -1
- package/dist/web/server.js +28 -28
- package/dist/web/server.js.map +1 -1
- package/dist/web/static/assets/AIConfig-BQCAQE9D.js +2 -0
- package/dist/web/static/assets/AIConfig-BQCAQE9D.js.map +1 -0
- package/dist/web/static/assets/Dashboard-D7Bo6Kan.js +2 -0
- package/dist/web/static/assets/Dashboard-D7Bo6Kan.js.map +1 -0
- package/dist/web/static/assets/{Drawer-DcU3ln98.js → Drawer-BeHRQxUS.js} +2 -2
- package/dist/web/static/assets/{Drawer-DcU3ln98.js.map → Drawer-BeHRQxUS.js.map} +1 -1
- package/dist/web/static/assets/Events-K_tCY2ti.js +2 -0
- package/dist/web/static/assets/Events-K_tCY2ti.js.map +1 -0
- package/dist/web/static/assets/Reports-BJCmBnc_.js +2 -0
- package/dist/web/static/assets/Reports-BJCmBnc_.js.map +1 -0
- package/dist/web/static/assets/SearchInput-BX2KhMkw.js +2 -0
- package/dist/web/static/assets/SearchInput-BX2KhMkw.js.map +1 -0
- package/dist/web/static/assets/SessionDetail-Bkr-kC7V.js +2 -0
- package/dist/web/static/assets/SessionDetail-Bkr-kC7V.js.map +1 -0
- package/dist/web/static/assets/Sessions-Chx9OCLH.js +2 -0
- package/dist/web/static/assets/Sessions-Chx9OCLH.js.map +1 -0
- package/dist/web/static/assets/Skills-O0GT1i7m.js +2 -0
- package/dist/web/static/assets/Skills-O0GT1i7m.js.map +1 -0
- package/dist/web/static/assets/TaskDetail-5SR8zGzv.js +2 -0
- package/dist/web/static/assets/TaskDetail-5SR8zGzv.js.map +1 -0
- package/dist/web/static/assets/Tasks-DCgDqvOZ.js +2 -0
- package/dist/web/static/assets/Tasks-DCgDqvOZ.js.map +1 -0
- package/dist/web/static/assets/export-L_VBD2p1.js +4 -0
- package/dist/web/static/assets/export-L_VBD2p1.js.map +1 -0
- package/dist/web/static/assets/index-D8AKj26b.css +1 -0
- package/dist/web/static/assets/index-DxIbmNmr.js +3 -0
- package/dist/web/static/assets/index-DxIbmNmr.js.map +1 -0
- package/dist/web/static/assets/{lucide-53bR2rki.js → lucide-fJlPI3H7.js} +68 -38
- package/dist/web/static/assets/lucide-fJlPI3H7.js.map +1 -0
- package/dist/web/static/assets/time-Bxuk0M-C.js +2 -0
- package/dist/web/static/assets/time-Bxuk0M-C.js.map +1 -0
- package/dist/web/static/index.html +3 -3
- package/docs/concurrent-agents.md +129 -0
- package/docs/design/architecture-review-20260516.md +232 -0
- package/docs/design/fix-skills-data-and-set-leak-spec-20260516-1300.md +219 -0
- package/docs/design/hook-failure-queue-spec-20260516-1530.md +204 -0
- package/docs/design/refactor-phase1-spec-20260515-1600.md +543 -0
- package/docs/design/refactor-phase2-spec-20260515-1700.md +424 -0
- package/docs/design/tasks-list-filter-pagination-spec-20260518-0930.md +208 -0
- package/docs/implementation/fix-skills-data-and-set-leak-changelog-20260516-1300.md +104 -0
- package/docs/implementation/hook-failure-queue-changelog-20260516-1530.md +196 -0
- package/docs/implementation/hotfix-daemon-event-reject-20260516-1430.md +56 -0
- package/docs/implementation/refactor-phase1-changelog-20260515-1630.md +354 -0
- package/docs/implementation/refactor-phase2-changelog-20260515-1705.md +421 -0
- package/docs/implementation/tasks-list-filter-pagination-changelog-20260518-0930.md +72 -0
- package/docs/reviews/claudemd-template-sync.md +54 -0
- package/docs/reviews/tasks-filter-pagination.md +80 -0
- package/docs/ruflo-learning-strategy.md +322 -0
- package/docs/skills-deduplication-analysis.md +83 -0
- package/docs/skills-multiformat-support.md +177 -0
- package/docs/skills-third-party.md +183 -0
- package/docs/testing/tasks-filter-pagination-test-report.md +86 -0
- package/forge +321 -0
- package/package.json +28 -62
- package/playwright.config.ts +40 -0
- package/scripts/demo-v2.ts +91 -0
- package/scripts/dev-daemon.sh +232 -0
- package/scripts/dev-web.ts +109 -0
- package/scripts/e2e-mcp-link.ts +423 -0
- package/scripts/e2e-methodology-quality.ts +253 -0
- package/scripts/e2e-routing.ts +456 -0
- package/scripts/e2e-user-methodology.ts +326 -0
- package/scripts/e2e-web-workflows.ts +299 -0
- package/scripts/migrate-legacy-to-dynamic.sql +108 -0
- package/scripts/regenerate-execution-docs.ts +116 -0
- package/scripts/sync-agent-skills.ts +193 -0
- package/scripts/test-hook.sh +71 -0
- package/scripts/verify-skill-loading.ts +62 -0
- package/src/claudemd/claudemd-generator.ts +777 -0
- package/src/claudemd/convention-extractor.ts +69 -0
- package/src/claudemd/index.ts +35 -0
- package/src/claudemd/persona-manager.ts +88 -0
- package/src/claudemd/resume-manager.ts +236 -0
- package/src/claudemd/tech-detector.ts +220 -0
- package/src/cli/commands/claudemd.ts +84 -0
- package/src/cli/commands/config.ts +46 -0
- package/src/cli/commands/daemon.ts +310 -0
- package/src/cli/commands/executions.ts +114 -0
- package/src/cli/commands/init.ts +204 -0
- package/src/cli/commands/logs.ts +181 -0
- package/src/cli/commands/mcp.ts +244 -0
- package/src/cli/commands/menu.ts +356 -0
- package/src/cli/commands/skills.ts +185 -0
- package/src/cli/commands/stats.ts +74 -0
- package/src/cli/commands/status.ts +69 -0
- package/src/cli/commands/template.ts +77 -0
- package/src/cli/commands/trace.ts +164 -0
- package/src/cli/index.ts +42 -0
- package/src/cli/init/hook-manager.ts +132 -0
- package/src/core/ai/provider.ts +308 -0
- package/src/core/ai/types.ts +51 -0
- package/src/core/config.ts +124 -0
- package/src/core/constants.ts +45 -0
- package/src/core/queue/index.ts +193 -0
- package/src/core/storage/base.ts +226 -0
- package/src/core/storage/events.ts +255 -0
- package/src/core/storage/injections.ts +78 -0
- package/src/core/storage/maintenance.ts +59 -0
- package/src/core/storage/migrations/002_add_skill_tracking.sql +6 -0
- package/src/core/storage/migrations/003_add_skill_invocations.sql +23 -0
- package/src/core/storage/performance-indexes.sql +23 -0
- package/src/core/storage/routing.ts +194 -0
- package/src/core/storage/rows.ts +112 -0
- package/src/core/storage/schema.sql +214 -0
- package/src/core/storage/sessions.ts +104 -0
- package/src/core/storage/skills.ts +164 -0
- package/src/core/storage/sqlite.ts +194 -0
- package/src/core/storage/tasks.ts +170 -0
- package/src/core/storage/token-usage.ts +93 -0
- package/src/core/types.ts +154 -0
- package/src/core/utils/error-handler.ts +256 -0
- package/src/core/utils/forge-resume-block.ts +74 -0
- package/src/core/utils/format.ts +69 -0
- package/src/core/utils/logger.ts +119 -0
- package/src/core/utils/lru-cache.ts +50 -0
- package/src/core/utils/path.ts +19 -0
- package/src/core/utils/session.ts +26 -0
- package/src/core/utils/time.ts +37 -0
- package/src/core/utils/token-tracker.ts +97 -0
- package/src/daemon/event-parser.ts +35 -0
- package/src/daemon/handlers/history-exporter.ts +117 -0
- package/src/daemon/handlers/post-tool-use.ts +50 -0
- package/src/daemon/handlers/stop.ts +215 -0
- package/src/daemon/handlers/user-prompt.ts +188 -0
- package/src/daemon/index.ts +278 -0
- package/src/daemon/launchd/com.claude-forge.daemon.plist.template +47 -0
- package/src/daemon/launchd-installer.ts +260 -0
- package/src/daemon/lifecycle.ts +128 -0
- package/src/daemon/router.ts +40 -0
- package/src/daemon/server.ts +209 -0
- package/src/daemon/services/anti-pattern-detector.ts +412 -0
- package/src/daemon/services/drift-detector.ts +232 -0
- package/src/daemon/services/task-segmenter.ts +112 -0
- package/src/daemon/services/weekly-report.ts +454 -0
- package/src/hooks/hook-lib.sh +81 -0
- package/src/hooks/notification.sh +35 -0
- package/src/hooks/post-tool-use.sh +61 -0
- package/src/hooks/pre-tool-use.sh +63 -0
- package/src/hooks/stop.sh +40 -0
- package/src/hooks/user-prompt-submit.sh +69 -0
- package/src/mcp/server.ts +322 -0
- package/src/skills/index.ts +2 -0
- package/src/skills/invocation-guard.ts +177 -0
- package/src/skills/matcher.ts +148 -0
- package/src/skills/official/code-simplifier.md +16 -0
- package/src/skills/official/find-skills.md +23 -0
- package/src/skills/official/official-api-design.md +17 -0
- package/src/skills/official/official-architecture-decision.md +20 -0
- package/src/skills/official/official-bmad.md +118 -0
- package/src/skills/official/official-db-schema-design.md +16 -0
- package/src/skills/official/official-debug.md +17 -0
- package/src/skills/official/official-doc-driven.md +31 -0
- package/src/skills/official/official-harness-engineering.md +108 -0
- package/src/skills/official/official-performance-optimization.md +30 -0
- package/src/skills/official/official-pr-review.md +35 -0
- package/src/skills/official/official-release-checklist.md +30 -0
- package/src/skills/official/official-security-hardening.md +26 -0
- package/src/skills/official/official-spec-driven-design.md +31 -0
- package/src/skills/official/planning-with-files.md +37 -0
- package/src/skills/official/ui-ux-pro-max.md +18 -0
- package/src/skills/official/webapp-testing.md +12 -0
- package/src/skills/official-skills.ts +89 -0
- package/src/skills/registry.ts +355 -0
- package/src/skills/semantic-matcher.ts +231 -0
- package/src/skills/tools/pipeline-suggest.ts +226 -0
- package/src/skills/tools/skill-invoke.ts +168 -0
- package/src/skills/tools/skill-list.ts +59 -0
- package/src/templates/go.yaml +53 -0
- package/src/templates/python.yaml +59 -0
- package/src/templates/react.yaml +55 -0
- package/src/templates/template-manager.ts +170 -0
- package/src/web/auth-middleware.ts +55 -0
- package/src/web/routes/ai.ts +204 -0
- package/src/web/routes/auth.ts +22 -0
- package/src/web/routes/drift.ts +25 -0
- package/src/web/routes/error-handler.ts +120 -0
- package/src/web/routes/events.ts +47 -0
- package/src/web/routes/insights.ts +43 -0
- package/src/web/routes/patch.ts +117 -0
- package/src/web/routes/reports.ts +34 -0
- package/src/web/routes/rules.ts +101 -0
- package/src/web/routes/sessions.ts +262 -0
- package/src/web/routes/skill-stats.ts +132 -0
- package/src/web/routes/skills.ts +349 -0
- package/src/web/routes/static.ts +67 -0
- package/src/web/routes/stats.ts +60 -0
- package/src/web/routes/status.ts +30 -0
- package/src/web/routes/tasks.ts +218 -0
- package/src/web/routes/token-usage.ts +20 -0
- package/src/web/routes/trace.ts +138 -0
- package/src/web/routes/types.ts +56 -0
- package/src/web/server.ts +134 -0
- package/src/web/ssrf-guard.ts +112 -0
- package/src/web/static/index.html +3251 -0
- package/src/web/static/vendor/chart.umd.min.js +20 -0
- package/tests/e2e/dashboard.spec.ts +205 -0
- package/tests/e2e/routing-skill-e2e.test.ts +39 -0
- package/tests/helpers/mock-ai.ts +92 -0
- package/tests/helpers/mock-storage.ts +159 -0
- package/tests/integration/queue-replay.integration.test.ts +193 -0
- package/tests/integration/tasks-filter.integration.test.ts +154 -0
- package/tests/performance/database.benchmark.ts +161 -0
- package/tests/semantic-matcher.test.ts +99 -0
- package/tests/skill-matcher.test.ts +110 -0
- package/tests/unit/ai-provider-retry.test.ts +194 -0
- package/tests/unit/ai-provider-vision.test.ts +224 -0
- package/tests/unit/claudemd-generator.test.ts +68 -0
- package/tests/unit/cli-mcp.test.ts +141 -0
- package/tests/unit/handlers.test.ts +171 -0
- package/tests/unit/invocation-guard.test.ts +125 -0
- package/tests/unit/queue.test.ts +272 -0
- package/tests/unit/router.test.ts +138 -0
- package/tests/unit/security.test.ts +128 -0
- package/tests/unit/skill-invocations-workflow.test.ts +495 -0
- package/tests/unit/skill-registry.test.ts +94 -0
- package/tests/unit/skills/invocation-guard-ttl.test.ts +211 -0
- package/tests/unit/skills/official-skills-loader.test.ts +126 -0
- package/tests/unit/skills/registry-multiformat.test.ts +92 -0
- package/tests/unit/storage/sessions-aggregate.test.ts +435 -0
- package/tests/unit/storage/sqlite-refactor-harness.test.ts +314 -0
- package/tests/unit/storage.test.ts +172 -0
- package/tests/unit/token-usage.test.ts +144 -0
- package/tests/unit/type-guards.test.ts +201 -0
- package/tests/unit/utils/format.test.ts +189 -0
- package/tests/unit/utils/session.test.ts +89 -0
- package/tests/unit/utils/time.test.ts +112 -0
- package/tests/unit/web/routes-auth.test.ts +93 -0
- package/tests/unit/web/routes-events.test.ts +101 -0
- package/tests/unit/web/routes-sessions.test.ts +181 -0
- package/tests/unit/web/routes-skill-stats.test.ts +179 -0
- package/tests/unit/web/routes-stats.test.ts +92 -0
- package/tests/unit/web/routes-tasks.test.ts +351 -0
- package/tsconfig.json +22 -0
- package/vitest.config.ts +21 -0
- package/vitest.integration.config.ts +16 -0
- package/web/CLAUDE.md +20 -0
- package/web/index.html +13 -0
- package/web/package-lock.json +4854 -0
- package/web/package.json +35 -0
- package/web/postcss.config.js +6 -0
- package/web/src/App.tsx +110 -0
- package/web/src/components/CodeBlock.tsx +31 -0
- package/web/src/components/Confirm.tsx +96 -0
- package/web/src/components/Drawer.tsx +60 -0
- package/web/src/components/Layout.tsx +145 -0
- package/web/src/components/MarkdownRenderer.tsx +77 -0
- package/web/src/components/SearchInput.tsx +31 -0
- package/web/src/components/SessionDetailContent.tsx +157 -0
- package/web/src/components/Toast.tsx +92 -0
- package/web/src/index.css +19 -0
- package/web/src/main.tsx +31 -0
- package/web/src/pages/AIConfig.tsx +233 -0
- package/web/src/pages/Dashboard.tsx +572 -0
- package/web/src/pages/Events.tsx +271 -0
- package/web/src/pages/Reports.tsx +428 -0
- package/web/src/pages/SessionDetail.tsx +162 -0
- package/web/src/pages/Sessions.tsx +205 -0
- package/web/src/pages/Skills.tsx +180 -0
- package/web/src/pages/TaskDetail.tsx +511 -0
- package/web/src/pages/Tasks.tsx +150 -0
- package/web/src/utils/auth.ts +59 -0
- package/web/src/utils/export.ts +54 -0
- package/web/src/utils/time.ts +13 -0
- package/web/tailwind.config.js +11 -0
- package/web/tsconfig.json +21 -0
- package/web/tsconfig.node.json +10 -0
- package/web/vite.config.ts +76 -0
- package/winspan-claude-forge-8.43.0.tgz +0 -0
- package/dist/agents/definition.d.ts +0 -62
- package/dist/agents/definition.d.ts.map +0 -1
- package/dist/agents/definition.js +0 -27
- package/dist/agents/definition.js.map +0 -1
- package/dist/agents/distributor.d.ts +0 -23
- package/dist/agents/distributor.d.ts.map +0 -1
- package/dist/agents/distributor.js +0 -85
- package/dist/agents/distributor.js.map +0 -1
- package/dist/agents/index.d.ts +0 -5
- package/dist/agents/index.d.ts.map +0 -1
- package/dist/agents/index.js +0 -5
- package/dist/agents/index.js.map +0 -1
- package/dist/agents/methodologies/agent-builder.d.ts +0 -21
- package/dist/agents/methodologies/agent-builder.d.ts.map +0 -1
- package/dist/agents/methodologies/agent-builder.js +0 -124
- package/dist/agents/methodologies/agent-builder.js.map +0 -1
- package/dist/agents/methodologies/phases/bmad/analyze.d.ts +0 -3
- package/dist/agents/methodologies/phases/bmad/analyze.d.ts.map +0 -1
- package/dist/agents/methodologies/phases/bmad/analyze.js +0 -18
- package/dist/agents/methodologies/phases/bmad/analyze.js.map +0 -1
- package/dist/agents/methodologies/phases/bmad/design.d.ts +0 -3
- package/dist/agents/methodologies/phases/bmad/design.d.ts.map +0 -1
- package/dist/agents/methodologies/phases/bmad/design.js +0 -17
- package/dist/agents/methodologies/phases/bmad/design.js.map +0 -1
- package/dist/agents/methodologies/phases/bmad/implement.d.ts +0 -3
- package/dist/agents/methodologies/phases/bmad/implement.d.ts.map +0 -1
- package/dist/agents/methodologies/phases/bmad/implement.js +0 -16
- package/dist/agents/methodologies/phases/bmad/implement.js.map +0 -1
- package/dist/agents/methodologies/phases/bmad/index.d.ts +0 -6
- package/dist/agents/methodologies/phases/bmad/index.d.ts.map +0 -1
- package/dist/agents/methodologies/phases/bmad/index.js +0 -6
- package/dist/agents/methodologies/phases/bmad/index.js.map +0 -1
- package/dist/agents/methodologies/phases/bmad/review.d.ts +0 -3
- package/dist/agents/methodologies/phases/bmad/review.d.ts.map +0 -1
- package/dist/agents/methodologies/phases/bmad/review.js +0 -16
- package/dist/agents/methodologies/phases/bmad/review.js.map +0 -1
- package/dist/agents/methodologies/phases/bmad/test.d.ts +0 -3
- package/dist/agents/methodologies/phases/bmad/test.d.ts.map +0 -1
- package/dist/agents/methodologies/phases/bmad/test.js +0 -20
- package/dist/agents/methodologies/phases/bmad/test.js.map +0 -1
- package/dist/agents/methodologies/phases/harness/fix.d.ts +0 -3
- package/dist/agents/methodologies/phases/harness/fix.d.ts.map +0 -1
- package/dist/agents/methodologies/phases/harness/fix.js +0 -16
- package/dist/agents/methodologies/phases/harness/fix.js.map +0 -1
- package/dist/agents/methodologies/phases/harness/index.d.ts +0 -6
- package/dist/agents/methodologies/phases/harness/index.d.ts.map +0 -1
- package/dist/agents/methodologies/phases/harness/index.js +0 -6
- package/dist/agents/methodologies/phases/harness/index.js.map +0 -1
- package/dist/agents/methodologies/phases/harness/reproduce.d.ts +0 -3
- package/dist/agents/methodologies/phases/harness/reproduce.d.ts.map +0 -1
- package/dist/agents/methodologies/phases/harness/reproduce.js +0 -19
- package/dist/agents/methodologies/phases/harness/reproduce.js.map +0 -1
- package/dist/agents/methodologies/phases/harness/root-cause.d.ts +0 -3
- package/dist/agents/methodologies/phases/harness/root-cause.d.ts.map +0 -1
- package/dist/agents/methodologies/phases/harness/root-cause.js +0 -20
- package/dist/agents/methodologies/phases/harness/root-cause.js.map +0 -1
- package/dist/agents/methodologies/phases/harness/safety-net.d.ts +0 -3
- package/dist/agents/methodologies/phases/harness/safety-net.d.ts.map +0 -1
- package/dist/agents/methodologies/phases/harness/safety-net.js +0 -16
- package/dist/agents/methodologies/phases/harness/safety-net.js.map +0 -1
- package/dist/agents/methodologies/phases/harness/verify.d.ts +0 -3
- package/dist/agents/methodologies/phases/harness/verify.d.ts.map +0 -1
- package/dist/agents/methodologies/phases/harness/verify.js +0 -21
- package/dist/agents/methodologies/phases/harness/verify.js.map +0 -1
- package/dist/agents/methodologies/presets.d.ts +0 -10
- package/dist/agents/methodologies/presets.d.ts.map +0 -1
- package/dist/agents/methodologies/presets.js +0 -79
- package/dist/agents/methodologies/presets.js.map +0 -1
- package/dist/agents/methodologies/types.d.ts +0 -43
- package/dist/agents/methodologies/types.d.ts.map +0 -1
- package/dist/agents/methodologies/types.js +0 -10
- package/dist/agents/methodologies/types.js.map +0 -1
- package/dist/agents/methodologies/user-config-loader.d.ts +0 -30
- package/dist/agents/methodologies/user-config-loader.d.ts.map +0 -1
- package/dist/agents/methodologies/user-config-loader.js +0 -159
- package/dist/agents/methodologies/user-config-loader.js.map +0 -1
- package/dist/agents/official-agents.d.ts +0 -4
- package/dist/agents/official-agents.d.ts.map +0 -1
- package/dist/agents/official-agents.js +0 -559
- package/dist/agents/official-agents.js.map +0 -1
- package/dist/agents/registry.d.ts +0 -57
- package/dist/agents/registry.d.ts.map +0 -1
- package/dist/agents/registry.js +0 -271
- package/dist/agents/registry.js.map +0 -1
- package/dist/capability/index.d.ts +0 -10
- package/dist/capability/index.d.ts.map +0 -1
- package/dist/capability/index.js +0 -10
- package/dist/capability/index.js.map +0 -1
- package/dist/capability/types.d.ts +0 -10
- package/dist/capability/types.d.ts.map +0 -1
- package/dist/capability/types.js +0 -10
- package/dist/capability/types.js.map +0 -1
- package/dist/cli/commands/agents.d.ts +0 -3
- package/dist/cli/commands/agents.d.ts.map +0 -1
- package/dist/cli/commands/agents.js +0 -62
- package/dist/cli/commands/agents.js.map +0 -1
- package/dist/cli/commands/rules.d.ts +0 -8
- package/dist/cli/commands/rules.d.ts.map +0 -1
- package/dist/cli/commands/rules.js +0 -89
- package/dist/cli/commands/rules.js.map +0 -1
- package/dist/daemon/auto-disable-scheduler.d.ts +0 -53
- package/dist/daemon/auto-disable-scheduler.d.ts.map +0 -1
- package/dist/daemon/auto-disable-scheduler.js +0 -114
- package/dist/daemon/auto-disable-scheduler.js.map +0 -1
- package/dist/daemon/handlers/pre-tool-use.d.ts +0 -30
- package/dist/daemon/handlers/pre-tool-use.d.ts.map +0 -1
- package/dist/daemon/handlers/pre-tool-use.js +0 -173
- package/dist/daemon/handlers/pre-tool-use.js.map +0 -1
- package/dist/daemon/routing-observer.d.ts +0 -42
- package/dist/daemon/routing-observer.d.ts.map +0 -1
- package/dist/daemon/routing-observer.js +0 -264
- package/dist/daemon/routing-observer.js.map +0 -1
- package/dist/daemon/routing-state.d.ts +0 -63
- package/dist/daemon/routing-state.d.ts.map +0 -1
- package/dist/daemon/routing-state.js +0 -223
- package/dist/daemon/routing-state.js.map +0 -1
- package/dist/engine/agent-router.d.ts +0 -142
- package/dist/engine/agent-router.d.ts.map +0 -1
- package/dist/engine/agent-router.js +0 -276
- package/dist/engine/agent-router.js.map +0 -1
- package/dist/engine/context-builder.d.ts +0 -23
- package/dist/engine/context-builder.d.ts.map +0 -1
- package/dist/engine/context-builder.js +0 -63
- package/dist/engine/context-builder.js.map +0 -1
- package/dist/engine/conventions/basic-security.yaml +0 -109
- package/dist/engine/conventions/code-quality.yaml +0 -123
- package/dist/engine/conventions/database-safety.yaml +0 -74
- package/dist/engine/conventions/dependency-safety.yaml +0 -132
- package/dist/engine/conventions/docker-safety.yaml +0 -69
- package/dist/engine/conventions/git-safety.yaml +0 -118
- package/dist/engine/conventions/go-best-practices.yaml +0 -84
- package/dist/engine/conventions/python-best-practices.yaml +0 -96
- package/dist/engine/conventions/react-best-practices.yaml +0 -96
- package/dist/engine/conventions/routing.yaml +0 -378
- package/dist/engine/conventions/strict-security.yaml +0 -30
- package/dist/engine/conventions/ts-quality.yaml +0 -49
- package/dist/engine/dsl/compiler.d.ts +0 -34
- package/dist/engine/dsl/compiler.d.ts.map +0 -1
- package/dist/engine/dsl/compiler.js +0 -702
- package/dist/engine/dsl/compiler.js.map +0 -1
- package/dist/engine/dsl/parser.d.ts +0 -25
- package/dist/engine/dsl/parser.d.ts.map +0 -1
- package/dist/engine/dsl/parser.js +0 -208
- package/dist/engine/dsl/parser.js.map +0 -1
- package/dist/engine/dsl/runtime.d.ts +0 -46
- package/dist/engine/dsl/runtime.d.ts.map +0 -1
- package/dist/engine/dsl/runtime.js +0 -173
- package/dist/engine/dsl/runtime.js.map +0 -1
- package/dist/engine/dsl/types.d.ts +0 -139
- package/dist/engine/dsl/types.d.ts.map +0 -1
- package/dist/engine/dsl/types.js +0 -11
- package/dist/engine/dsl/types.js.map +0 -1
- package/dist/engine/evidence-store.d.ts +0 -44
- package/dist/engine/evidence-store.d.ts.map +0 -1
- package/dist/engine/evidence-store.js +0 -109
- package/dist/engine/evidence-store.js.map +0 -1
- package/dist/engine/experiment-router.d.ts +0 -102
- package/dist/engine/experiment-router.d.ts.map +0 -1
- package/dist/engine/experiment-router.js +0 -289
- package/dist/engine/experiment-router.js.map +0 -1
- package/dist/engine/recommender.d.ts +0 -52
- package/dist/engine/recommender.d.ts.map +0 -1
- package/dist/engine/recommender.js +0 -162
- package/dist/engine/recommender.js.map +0 -1
- package/dist/engine/rule-engine.d.ts +0 -33
- package/dist/engine/rule-engine.d.ts.map +0 -1
- package/dist/engine/rule-engine.js +0 -250
- package/dist/engine/rule-engine.js.map +0 -1
- package/dist/intelligence/classifier.d.ts +0 -75
- package/dist/intelligence/classifier.d.ts.map +0 -1
- package/dist/intelligence/classifier.js +0 -352
- package/dist/intelligence/classifier.js.map +0 -1
- package/dist/intelligence/context-gatherer.d.ts +0 -101
- package/dist/intelligence/context-gatherer.d.ts.map +0 -1
- package/dist/intelligence/context-gatherer.js +0 -417
- package/dist/intelligence/context-gatherer.js.map +0 -1
- package/dist/intelligence/cot-classifier.d.ts +0 -95
- package/dist/intelligence/cot-classifier.d.ts.map +0 -1
- package/dist/intelligence/cot-classifier.js +0 -391
- package/dist/intelligence/cot-classifier.js.map +0 -1
- package/dist/intelligence/distiller.d.ts +0 -22
- package/dist/intelligence/distiller.d.ts.map +0 -1
- package/dist/intelligence/distiller.js +0 -108
- package/dist/intelligence/distiller.js.map +0 -1
- package/dist/intelligence/execution-doc-builder.d.ts +0 -151
- package/dist/intelligence/execution-doc-builder.d.ts.map +0 -1
- package/dist/intelligence/execution-doc-builder.js +0 -1018
- package/dist/intelligence/execution-doc-builder.js.map +0 -1
- package/dist/intelligence/intent-types.d.ts +0 -13
- package/dist/intelligence/intent-types.d.ts.map +0 -1
- package/dist/intelligence/intent-types.js +0 -19
- package/dist/intelligence/intent-types.js.map +0 -1
- package/dist/intelligence/multimodal-parser.d.ts +0 -105
- package/dist/intelligence/multimodal-parser.d.ts.map +0 -1
- package/dist/intelligence/multimodal-parser.js +0 -425
- package/dist/intelligence/multimodal-parser.js.map +0 -1
- package/dist/intelligence/quality-gate.d.ts +0 -45
- package/dist/intelligence/quality-gate.d.ts.map +0 -1
- package/dist/intelligence/quality-gate.js +0 -193
- package/dist/intelligence/quality-gate.js.map +0 -1
- package/dist/intelligence/task-segmenter.d.ts.map +0 -1
- package/dist/intelligence/task-segmenter.js.map +0 -1
- package/dist/web/routes/agents.d.ts +0 -7
- package/dist/web/routes/agents.d.ts.map +0 -1
- package/dist/web/routes/agents.js +0 -209
- package/dist/web/routes/agents.js.map +0 -1
- package/dist/web/routes/execution-trace.d.ts +0 -21
- package/dist/web/routes/execution-trace.d.ts.map +0 -1
- package/dist/web/routes/execution-trace.js +0 -353
- package/dist/web/routes/execution-trace.js.map +0 -1
- package/dist/web/routes/experiments.d.ts +0 -15
- package/dist/web/routes/experiments.d.ts.map +0 -1
- package/dist/web/routes/experiments.js +0 -187
- package/dist/web/routes/experiments.js.map +0 -1
- package/dist/web/routes/routing.d.ts +0 -17
- package/dist/web/routes/routing.d.ts.map +0 -1
- package/dist/web/routes/routing.js +0 -592
- package/dist/web/routes/routing.js.map +0 -1
- package/dist/web/routes/workflows.d.ts +0 -19
- package/dist/web/routes/workflows.d.ts.map +0 -1
- package/dist/web/routes/workflows.js +0 -86
- package/dist/web/routes/workflows.js.map +0 -1
- package/dist/web/static/assets/AIConfig-R5wZ3ZKT.js +0 -2
- package/dist/web/static/assets/AIConfig-R5wZ3ZKT.js.map +0 -1
- package/dist/web/static/assets/Agents-Beg34V1g.js +0 -2
- package/dist/web/static/assets/Agents-Beg34V1g.js.map +0 -1
- package/dist/web/static/assets/CodeBlock--H53gk46.js +0 -2
- package/dist/web/static/assets/CodeBlock--H53gk46.js.map +0 -1
- package/dist/web/static/assets/Dashboard-Cy1xsj1J.js +0 -2
- package/dist/web/static/assets/Dashboard-Cy1xsj1J.js.map +0 -1
- package/dist/web/static/assets/Events-mFhXl4zI.js +0 -2
- package/dist/web/static/assets/Events-mFhXl4zI.js.map +0 -1
- package/dist/web/static/assets/ExecutionTrace-DG901hLR.js +0 -3
- package/dist/web/static/assets/ExecutionTrace-DG901hLR.js.map +0 -1
- package/dist/web/static/assets/MarkdownRenderer-CCIz1MOz.js +0 -2
- package/dist/web/static/assets/MarkdownRenderer-CCIz1MOz.js.map +0 -1
- package/dist/web/static/assets/Routing-B7BFLfjh.js +0 -2
- package/dist/web/static/assets/Routing-B7BFLfjh.js.map +0 -1
- package/dist/web/static/assets/SessionDetail-BT0l4RrK.js +0 -2
- package/dist/web/static/assets/SessionDetail-BT0l4RrK.js.map +0 -1
- package/dist/web/static/assets/Sessions-C6J_HQ_u.js +0 -2
- package/dist/web/static/assets/Sessions-C6J_HQ_u.js.map +0 -1
- package/dist/web/static/assets/Skills-4DQWLaTv.js +0 -2
- package/dist/web/static/assets/Skills-4DQWLaTv.js.map +0 -1
- package/dist/web/static/assets/WorkflowDetail-zhNqUkBE.js +0 -2
- package/dist/web/static/assets/WorkflowDetail-zhNqUkBE.js.map +0 -1
- package/dist/web/static/assets/Workflows-Btvi-lGw.js +0 -2
- package/dist/web/static/assets/Workflows-Btvi-lGw.js.map +0 -1
- package/dist/web/static/assets/export-BQQZLaHV.js +0 -4
- package/dist/web/static/assets/export-BQQZLaHV.js.map +0 -1
- package/dist/web/static/assets/index-Cgr9qMtq.js +0 -3
- package/dist/web/static/assets/index-Cgr9qMtq.js.map +0 -1
- package/dist/web/static/assets/index-CngWb5gC.css +0 -1
- package/dist/web/static/assets/lucide-53bR2rki.js.map +0 -1
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{j as s}from"./react-vendor-CSp-GLFF.js";import{c,L as l}from"./react-router-I-HqunH7.js";import{u as m}from"./query-C99w429o.js";import{p as o}from"./time-Bxuk0M-C.js";import{d as h}from"./vendor-CMMjVdZs.js";import{j as n,h as g,i as j,G as p,a as N}from"./lucide-fJlPI3H7.js";import{f}from"./date-fns-CZ_bHujz.js";async function v(a){const t=await fetch(`/api/sessions/${a}/detail`);if(!t.ok)throw new Error("Failed to fetch session detail");return t.json()}function C(){const{id:a}=c(),{data:t,isLoading:d,error:x}=m({queryKey:["session-detail",a],queryFn:()=>v(a),enabled:!!a});return d?s.jsx("div",{className:"bg-white rounded-lg shadow p-6",children:s.jsx("p",{className:"text-gray-600",children:"加载中..."})}):x||!t?s.jsxs("div",{children:[s.jsxs(l,{to:"/sessions",className:"inline-flex items-center text-sm text-gray-500 hover:text-gray-700 mb-4",children:[s.jsx(n,{className:"h-4 w-4 mr-1"}),"返回"]}),s.jsx("div",{className:"bg-white rounded-lg shadow p-6",children:s.jsx("p",{className:"text-red-600",children:"加载失败"})})]}):s.jsxs("div",{children:[s.jsxs(l,{to:"/sessions",className:"inline-flex items-center text-sm text-gray-500 hover:text-gray-700 mb-4",children:[s.jsx(n,{className:"h-4 w-4 mr-1"}),"返回会话列表"]}),s.jsxs("div",{className:"bg-white rounded-lg shadow p-6 mb-6",children:[s.jsx("h1",{className:"text-xl font-bold text-gray-900 mb-2",children:"会话详情"}),s.jsx("p",{className:"text-sm text-gray-500 font-mono mb-4",children:t.session.session_id}),s.jsxs("div",{className:"grid grid-cols-3 gap-4",children:[s.jsxs("div",{children:[s.jsx("div",{className:"text-xs text-gray-500",children:"事件数"}),s.jsx("div",{className:"text-lg font-semibold",children:t.session.event_count})]}),s.jsxs("div",{children:[s.jsx("div",{className:"text-xs text-gray-500",children:"任务数"}),s.jsx("div",{className:"text-lg font-semibold",children:t.tasks.length})]}),s.jsxs("div",{children:[s.jsx("div",{className:"text-xs text-gray-500",children:"开始时间"}),s.jsx("div",{className:"text-sm",children:t.session.start_time?f(o(t.session.start_time),"MM-dd HH:mm:ss"):"-"})]})]})]}),s.jsx("div",{className:"space-y-4",children:t.tasks.map(e=>s.jsxs("div",{className:"bg-white rounded-lg shadow p-6",children:[s.jsxs("div",{className:"flex items-center justify-between mb-4",children:[s.jsx("h3",{className:"text-lg font-semibold text-gray-900",children:e.title}),s.jsx("span",{className:h("px-2 py-1 text-xs font-medium rounded-full",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})]}),s.jsxs("div",{className:"grid grid-cols-3 gap-4 mb-4 text-sm",children:[s.jsxs("div",{children:[s.jsxs("div",{className:"text-xs text-gray-500 mb-1 flex items-center gap-1",children:[s.jsx(g,{className:"h-3 w-3"}),"工具使用"]}),s.jsx("div",{className:"space-y-1",children:Object.entries(e.summary.toolUsage).slice(0,5).map(([i,r])=>s.jsxs("div",{className:"flex justify-between text-xs",children:[s.jsx("span",{className:"text-gray-600",children:i}),s.jsx("span",{className:"font-mono text-gray-900",children:r})]},i))})]}),s.jsxs("div",{children:[s.jsxs("div",{className:"text-xs text-gray-500 mb-1 flex items-center gap-1",children:[s.jsx(j,{className:"h-3 w-3"}),"文件变更"]}),s.jsxs("div",{className:"text-xs text-gray-700",children:[e.summary.filesChanged.length," 个文件"]})]}),s.jsxs("div",{children:[s.jsxs("div",{className:"text-xs text-gray-500 mb-1 flex items-center gap-1",children:[s.jsx(p,{className:"h-3 w-3"}),"提交"]}),s.jsxs("div",{className:"text-xs text-gray-700",children:[e.summary.commits.length," 次"]})]})]}),e.prompts.length>0&&s.jsxs("div",{className:"border-t pt-3",children:[s.jsxs("div",{className:"text-xs text-gray-500 mb-2 flex items-center gap-1",children:[s.jsx(N,{className:"h-3 w-3"}),"用户提示"]}),s.jsx("div",{className:"space-y-2",children:e.prompts.slice(0,3).map((i,r)=>s.jsx("div",{className:"text-sm bg-gray-50 rounded p-2",children:s.jsx("p",{className:"text-gray-700 line-clamp-2",children:i.content})},r))})]})]},e.id))})]})}export{C as default};
|
|
2
|
+
//# sourceMappingURL=SessionDetail-Bkr-kC7V.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SessionDetail-Bkr-kC7V.js","sources":["../../src/pages/SessionDetail.tsx"],"sourcesContent":["import { useParams, Link } from 'react-router-dom'\nimport { useQuery } from '@tanstack/react-query'\nimport { format } from 'date-fns'\nimport { parseUTC } from '../utils/time'\nimport { ArrowLeft, MessageSquare, FileEdit, Terminal, GitCommit } from 'lucide-react'\nimport clsx from 'clsx'\n\ninterface TaskDetail {\n id: string\n title: string\n start_time: string\n end_time?: string\n status: string\n event_count: number\n prompts: Array<{ timestamp: string; content: string }>\n events: Array<any>\n injections: Array<any>\n summary: {\n toolUsage: Record<string, number>\n filesChanged: string[]\n commits: Array<{ timestamp: string; message: string }>\n }\n}\n\ninterface SessionDetail {\n session: {\n session_id: string\n first_prompt: string\n event_count: number\n start_time: string\n end_time: string\n }\n tasks: TaskDetail[]\n}\n\nasync function fetchSessionDetail(id: string): Promise<SessionDetail> {\n const res = await fetch(`/api/sessions/${id}/detail`)\n if (!res.ok) throw new Error('Failed to fetch session detail')\n return res.json()\n}\n\nexport default function SessionDetail() {\n const { id } = useParams<{ id: string }>()\n const { data, isLoading, error } = useQuery({\n queryKey: ['session-detail', id],\n queryFn: () => fetchSessionDetail(id!),\n enabled: !!id,\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=\"/sessions\" 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\">加载失败</p>\n </div>\n </div>\n )\n }\n\n return (\n <div>\n <Link to=\"/sessions\" 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 <div className=\"bg-white rounded-lg shadow p-6 mb-6\">\n <h1 className=\"text-xl font-bold text-gray-900 mb-2\">\n 会话详情\n </h1>\n <p className=\"text-sm text-gray-500 font-mono mb-4\">{data.session.session_id}</p>\n <div className=\"grid grid-cols-3 gap-4\">\n <div>\n <div className=\"text-xs text-gray-500\">事件数</div>\n <div className=\"text-lg font-semibold\">{data.session.event_count}</div>\n </div>\n <div>\n <div className=\"text-xs text-gray-500\">任务数</div>\n <div className=\"text-lg font-semibold\">{data.tasks.length}</div>\n </div>\n <div>\n <div className=\"text-xs text-gray-500\">开始时间</div>\n <div className=\"text-sm\">\n {data.session.start_time ? format(parseUTC(data.session.start_time), 'MM-dd HH:mm:ss') : '-'}\n </div>\n </div>\n </div>\n </div>\n\n <div className=\"space-y-4\">\n {data.tasks.map((task) => (\n <div key={task.id} className=\"bg-white rounded-lg shadow p-6\">\n <div className=\"flex items-center justify-between mb-4\">\n <h3 className=\"text-lg font-semibold text-gray-900\">{task.title}</h3>\n <span className={clsx(\n 'px-2 py-1 text-xs font-medium rounded-full',\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=\"grid grid-cols-3 gap-4 mb-4 text-sm\">\n <div>\n <div className=\"text-xs text-gray-500 mb-1 flex items-center gap-1\">\n <Terminal className=\"h-3 w-3\" />工具使用\n </div>\n <div className=\"space-y-1\">\n {Object.entries(task.summary.toolUsage).slice(0, 5).map(([tool, count]) => (\n <div key={tool} className=\"flex justify-between text-xs\">\n <span className=\"text-gray-600\">{tool}</span>\n <span className=\"font-mono text-gray-900\">{count}</span>\n </div>\n ))}\n </div>\n </div>\n <div>\n <div className=\"text-xs text-gray-500 mb-1 flex items-center gap-1\">\n <FileEdit className=\"h-3 w-3\" />文件变更\n </div>\n <div className=\"text-xs text-gray-700\">{task.summary.filesChanged.length} 个文件</div>\n </div>\n <div>\n <div className=\"text-xs text-gray-500 mb-1 flex items-center gap-1\">\n <GitCommit className=\"h-3 w-3\" />提交\n </div>\n <div className=\"text-xs text-gray-700\">{task.summary.commits.length} 次</div>\n </div>\n </div>\n\n {task.prompts.length > 0 && (\n <div className=\"border-t pt-3\">\n <div className=\"text-xs text-gray-500 mb-2 flex items-center gap-1\">\n <MessageSquare className=\"h-3 w-3\" />用户提示\n </div>\n <div className=\"space-y-2\">\n {task.prompts.slice(0, 3).map((p, i) => (\n <div key={i} className=\"text-sm bg-gray-50 rounded p-2\">\n <p className=\"text-gray-700 line-clamp-2\">{p.content}</p>\n </div>\n ))}\n </div>\n </div>\n )}\n </div>\n ))}\n </div>\n </div>\n )\n}\n"],"names":["fetchSessionDetail","id","res","SessionDetail","useParams","data","isLoading","error","useQuery","jsx","jsxs","Link","ArrowLeft","format","parseUTC","task","clsx","Terminal","tool","count","FileEdit","GitCommit","MessageSquare","p","i"],"mappings":"mUAmCA,eAAeA,EAAmBC,EAAoC,CACpE,MAAMC,EAAM,MAAM,MAAM,iBAAiBD,CAAE,SAAS,EACpD,GAAI,CAACC,EAAI,GAAI,MAAM,IAAI,MAAM,gCAAgC,EAC7D,OAAOA,EAAI,KAAA,CACb,CAEA,SAAwBC,GAAgB,CACtC,KAAM,CAAE,GAAAF,CAAA,EAAOG,EAAA,EACT,CAAE,KAAAC,EAAM,UAAAC,EAAW,MAAAC,CAAA,EAAUC,EAAS,CAC1C,SAAU,CAAC,iBAAkBP,CAAE,EAC/B,QAAS,IAAMD,EAAmBC,CAAG,EACrC,QAAS,CAAC,CAACA,CAAA,CACZ,EAED,OAAIK,EAEAG,EAAAA,IAAC,OAAI,UAAU,iCACb,eAAC,IAAA,CAAE,UAAU,gBAAgB,SAAA,QAAA,CAAM,CAAA,CACrC,EAIAF,GAAS,CAACF,SAET,MAAA,CACC,SAAA,CAAAK,EAAAA,KAACC,EAAA,CAAK,GAAG,YAAY,UAAU,0EAC7B,SAAA,CAAAF,EAAAA,IAACG,EAAA,CAAU,UAAU,cAAA,CAAe,EAAE,IAAA,EACxC,EACAH,EAAAA,IAAC,OAAI,UAAU,iCACb,eAAC,IAAA,CAAE,UAAU,eAAe,SAAA,MAAA,CAAI,CAAA,CAClC,CAAA,EACF,SAKD,MAAA,CACC,SAAA,CAAAC,EAAAA,KAACC,EAAA,CAAK,GAAG,YAAY,UAAU,0EAC7B,SAAA,CAAAF,EAAAA,IAACG,EAAA,CAAU,UAAU,cAAA,CAAe,EAAE,QAAA,EACxC,EAEAF,EAAAA,KAAC,MAAA,CAAI,UAAU,sCACb,SAAA,CAAAD,EAAAA,IAAC,KAAA,CAAG,UAAU,uCAAuC,SAAA,OAErD,QACC,IAAA,CAAE,UAAU,uCAAwC,SAAAJ,EAAK,QAAQ,WAAW,EAC7EK,EAAAA,KAAC,MAAA,CAAI,UAAU,yBACb,SAAA,CAAAA,OAAC,MAAA,CACC,SAAA,CAAAD,EAAAA,IAAC,MAAA,CAAI,UAAU,wBAAwB,SAAA,MAAG,QACzC,MAAA,CAAI,UAAU,wBAAyB,SAAAJ,EAAK,QAAQ,WAAA,CAAY,CAAA,EACnE,SACC,MAAA,CACC,SAAA,CAAAI,EAAAA,IAAC,MAAA,CAAI,UAAU,wBAAwB,SAAA,MAAG,QACzC,MAAA,CAAI,UAAU,wBAAyB,SAAAJ,EAAK,MAAM,MAAA,CAAO,CAAA,EAC5D,SACC,MAAA,CACC,SAAA,CAAAI,EAAAA,IAAC,MAAA,CAAI,UAAU,wBAAwB,SAAA,OAAI,EAC3CA,EAAAA,IAAC,MAAA,CAAI,UAAU,UACZ,WAAK,QAAQ,WAAaI,EAAOC,EAAST,EAAK,QAAQ,UAAU,EAAG,gBAAgB,EAAI,GAAA,CAC3F,CAAA,CAAA,CACF,CAAA,CAAA,CACF,CAAA,EACF,EAEAI,EAAAA,IAAC,MAAA,CAAI,UAAU,YACZ,SAAAJ,EAAK,MAAM,IAAKU,GACfL,EAAAA,KAAC,MAAA,CAAkB,UAAU,iCAC3B,SAAA,CAAAA,EAAAA,KAAC,MAAA,CAAI,UAAU,yCACb,SAAA,CAAAD,EAAAA,IAAC,KAAA,CAAG,UAAU,sCAAuC,SAAAM,EAAK,MAAM,EAChEN,MAAC,QAAK,UAAWO,EACf,6CACAD,EAAK,SAAW,aAAe,8BAC/BA,EAAK,SAAW,UAAY,4BAC5BA,EAAK,SAAW,aAAe,2BAAA,EAE9B,WAAK,MAAA,CACR,CAAA,EACF,EAEAL,EAAAA,KAAC,MAAA,CAAI,UAAU,sCACb,SAAA,CAAAA,OAAC,MAAA,CACC,SAAA,CAAAA,EAAAA,KAAC,MAAA,CAAI,UAAU,qDACb,SAAA,CAAAD,EAAAA,IAACQ,EAAA,CAAS,UAAU,SAAA,CAAU,EAAE,MAAA,EAClC,EACAR,EAAAA,IAAC,OAAI,UAAU,YACZ,gBAAO,QAAQM,EAAK,QAAQ,SAAS,EAAE,MAAM,EAAG,CAAC,EAAE,IAAI,CAAC,CAACG,EAAMC,CAAK,IACnET,EAAAA,KAAC,MAAA,CAAe,UAAU,+BACxB,SAAA,CAAAD,EAAAA,IAAC,OAAA,CAAK,UAAU,gBAAiB,SAAAS,EAAK,EACtCT,EAAAA,IAAC,OAAA,CAAK,UAAU,0BAA2B,SAAAU,CAAA,CAAM,CAAA,CAAA,EAFzCD,CAGV,CACD,CAAA,CACH,CAAA,EACF,SACC,MAAA,CACC,SAAA,CAAAR,EAAAA,KAAC,MAAA,CAAI,UAAU,qDACb,SAAA,CAAAD,EAAAA,IAACW,EAAA,CAAS,UAAU,SAAA,CAAU,EAAE,MAAA,EAClC,EACAV,EAAAA,KAAC,MAAA,CAAI,UAAU,wBAAyB,SAAA,CAAAK,EAAK,QAAQ,aAAa,OAAO,MAAA,CAAA,CAAI,CAAA,EAC/E,SACC,MAAA,CACC,SAAA,CAAAL,EAAAA,KAAC,MAAA,CAAI,UAAU,qDACb,SAAA,CAAAD,EAAAA,IAACY,EAAA,CAAU,UAAU,SAAA,CAAU,EAAE,IAAA,EACnC,EACAX,EAAAA,KAAC,MAAA,CAAI,UAAU,wBAAyB,SAAA,CAAAK,EAAK,QAAQ,QAAQ,OAAO,IAAA,CAAA,CAAE,CAAA,CAAA,CACxE,CAAA,EACF,EAECA,EAAK,QAAQ,OAAS,GACrBL,EAAAA,KAAC,MAAA,CAAI,UAAU,gBACb,SAAA,CAAAA,EAAAA,KAAC,MAAA,CAAI,UAAU,qDACb,SAAA,CAAAD,EAAAA,IAACa,EAAA,CAAc,UAAU,SAAA,CAAU,EAAE,MAAA,EACvC,EACAb,EAAAA,IAAC,MAAA,CAAI,UAAU,YACZ,SAAAM,EAAK,QAAQ,MAAM,EAAG,CAAC,EAAE,IAAI,CAACQ,EAAGC,IAChCf,EAAAA,IAAC,MAAA,CAAY,UAAU,iCACrB,SAAAA,EAAAA,IAAC,IAAA,CAAE,UAAU,6BAA8B,SAAAc,EAAE,OAAA,CAAQ,CAAA,EAD7CC,CAEV,CACD,CAAA,CACH,CAAA,CAAA,CACF,CAAA,GArDMT,EAAK,EAuDf,CACD,CAAA,CACH,CAAA,EACF,CAEJ"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{j as e,r as o}from"./react-vendor-CSp-GLFF.js";import{u as j}from"./query-C99w429o.js";import{p as f}from"./time-Bxuk0M-C.js";import{D as N}from"./Drawer-BeHRQxUS.js";import{d as v}from"./vendor-CMMjVdZs.js";import{f as b,a as w,z as S}from"./date-fns-CZ_bHujz.js";import{h as C,i as _,G as D,a as u,D as E,A as q,g as F}from"./lucide-fJlPI3H7.js";import{S as M}from"./SearchInput-BX2KhMkw.js";import{g as z,d as I,a as L}from"./export-L_VBD2p1.js";import{u as T}from"./index-DxIbmNmr.js";import"./react-router-I-HqunH7.js";import"./syntax-highlighter-44FakypI.js";async function $(r){const a=await fetch(`/api/sessions/${r}/detail`);if(!a.ok)throw new Error("Failed to fetch session detail");return a.json()}function k({sessionId:r}){const{data:a,isLoading:l,error:m}=j({queryKey:["session-detail",r],queryFn:()=>$(r),enabled:!!r});return l?e.jsx("div",{className:"p-6 text-gray-500",children:"加载中..."}):m||!a?e.jsx("div",{className:"p-6 text-red-600",children:"加载失败"}):e.jsxs("div",{className:"space-y-4",children:[e.jsxs("div",{children:[e.jsx("div",{className:"text-xs text-gray-500 mb-1",children:"Session ID"}),e.jsx("div",{className:"text-sm font-mono text-gray-900 break-all",children:a.session.session_id})]}),e.jsxs("div",{className:"grid grid-cols-3 gap-4 pb-4 border-b border-gray-200",children:[e.jsxs("div",{children:[e.jsx("div",{className:"text-xs text-gray-500",children:"事件数"}),e.jsx("div",{className:"text-lg font-semibold",children:a.session.event_count})]}),e.jsxs("div",{children:[e.jsx("div",{className:"text-xs text-gray-500",children:"任务数"}),e.jsx("div",{className:"text-lg font-semibold",children:a.tasks.length})]}),e.jsxs("div",{children:[e.jsx("div",{className:"text-xs text-gray-500",children:"开始时间"}),e.jsx("div",{className:"text-sm",children:a.session.start_time?b(f(a.session.start_time),"MM-dd HH:mm:ss"):"-"})]})]}),e.jsxs("div",{children:[e.jsx("h3",{className:"text-sm font-semibold text-gray-700 mb-3",children:"任务列表"}),e.jsx("div",{className:"space-y-3",children:a.tasks.map(s=>e.jsxs("div",{className:"border border-gray-200 rounded-lg p-4",children:[e.jsxs("div",{className:"flex items-center justify-between mb-3",children:[e.jsx("h4",{className:"text-sm font-semibold text-gray-900 flex-1 mr-2",children:s.title}),e.jsx("span",{className:v("px-2 py-0.5 text-xs font-medium rounded-full whitespace-nowrap",s.status==="completed"&&"bg-green-100 text-green-700",s.status==="active"&&"bg-blue-100 text-blue-700",s.status==="abandoned"&&"bg-gray-100 text-gray-600"),children:s.status})]}),e.jsxs("div",{className:"grid grid-cols-3 gap-3 mb-3 text-xs",children:[e.jsxs("div",{children:[e.jsxs("div",{className:"text-gray-500 mb-1 flex items-center gap-1",children:[e.jsx(C,{className:"h-3 w-3"}),"工具使用"]}),e.jsx("div",{className:"space-y-0.5",children:Object.entries(s.summary.toolUsage).slice(0,4).map(([i,c])=>e.jsxs("div",{className:"flex justify-between",children:[e.jsx("span",{className:"text-gray-600",children:i}),e.jsx("span",{className:"font-mono text-gray-900",children:c})]},i))})]}),e.jsxs("div",{children:[e.jsxs("div",{className:"text-gray-500 mb-1 flex items-center gap-1",children:[e.jsx(_,{className:"h-3 w-3"}),"文件变更"]}),e.jsxs("div",{className:"text-gray-700",children:[s.summary.filesChanged.length," 个"]}),s.summary.filesChanged.slice(0,3).map(i=>e.jsx("div",{className:"text-gray-500 truncate text-[10px]",title:i,children:i.split("/").pop()},i))]}),e.jsxs("div",{children:[e.jsxs("div",{className:"text-gray-500 mb-1 flex items-center gap-1",children:[e.jsx(D,{className:"h-3 w-3"}),"提交"]}),e.jsxs("div",{className:"text-gray-700",children:[s.summary.commits.length," 次"]})]})]}),s.prompts.length>0&&e.jsxs("div",{className:"border-t border-gray-100 pt-3",children:[e.jsxs("div",{className:"text-xs text-gray-500 mb-2 flex items-center gap-1",children:[e.jsx(u,{className:"h-3 w-3"}),"用户提示 (",s.prompts.length,")"]}),e.jsxs("div",{className:"space-y-1.5",children:[s.prompts.slice(0,3).map((i,c)=>e.jsx("div",{className:"text-xs bg-gray-50 rounded p-2",children:e.jsx("p",{className:"text-gray-700 line-clamp-2",children:i.content})},c)),s.prompts.length>3&&e.jsxs("div",{className:"text-xs text-gray-400",children:["还有 ",s.prompts.length-3," 条..."]})]})]})]},s.id))})]})]})}async function H(){const r=await fetch("/api/sessions?limit=200");if(!r.ok)throw new Error("Failed to fetch sessions");return r.json()}function X(){const[r,a]=o.useState(null),[l,m]=o.useState(""),[s,i]=o.useState(!1),c=T(),{data:x,isLoading:y,error:h}=j({queryKey:["sessions"],queryFn:H,refetchInterval:1e4}),n=o.useMemo(()=>{if(!x)return[];if(!l.trim())return x;const t=l.toLowerCase();return x.filter(d=>{var g;return((g=d.first_prompt)==null?void 0:g.toLowerCase().includes(t))||d.session_id.toLowerCase().includes(t)})},[x,l]),p=t=>{const d=z();t==="json"?I(`sessions-${d}.json`,n):L(`sessions-${d}.csv`,n),c.success(`已导出 ${n.length} 个会话`),i(!1)};return y?e.jsxs("div",{children:[e.jsx("h1",{className:"text-2xl font-bold text-gray-900 mb-6",children:"会话"}),e.jsx("div",{className:"bg-white rounded-lg shadow p-6",children:e.jsx("p",{className:"text-gray-600",children:"加载中..."})})]}):h?e.jsxs("div",{children:[e.jsx("h1",{className:"text-2xl font-bold text-gray-900 mb-6",children:"会话"}),e.jsx("div",{className:"bg-white rounded-lg shadow p-6",children:e.jsxs("p",{className:"text-red-600",children:["加载失败: ",h.message]})})]}):e.jsxs("div",{children:[e.jsxs("div",{className:"flex items-center justify-between mb-4 flex-wrap gap-3",children:[e.jsx("h1",{className:"text-2xl font-bold text-gray-900",children:"会话"}),e.jsxs("div",{className:"flex items-center gap-2 flex-wrap",children:[e.jsx(M,{value:l,onChange:m,placeholder:"搜索 session / 提示...",className:"w-64"}),e.jsxs("div",{className:"relative",children:[e.jsxs("button",{onClick:()=>i(t=>!t),disabled:n.length===0,className:"inline-flex items-center gap-1 px-3 py-1.5 text-sm bg-white border border-gray-300 rounded-md hover:bg-gray-50 disabled:opacity-50",children:[e.jsx(E,{className:"h-4 w-4"}),"导出"]}),s&&e.jsxs(e.Fragment,{children:[e.jsx("div",{className:"fixed inset-0 z-10",onClick:()=>i(!1)}),e.jsxs("div",{className:"absolute right-0 mt-1 bg-white border border-gray-200 rounded-md shadow-lg z-20",children:[e.jsx("button",{onClick:()=>p("json"),className:"block w-full text-left px-4 py-2 text-sm hover:bg-gray-50",children:"导出为 JSON"}),e.jsx("button",{onClick:()=>p("csv"),className:"block w-full text-left px-4 py-2 text-sm hover:bg-gray-50",children:"导出为 CSV"})]})]})]})]})]}),e.jsxs("div",{className:"text-sm text-gray-500 mb-3",children:["显示 ",n.length," 个 ",l&&"(已过滤)"]}),e.jsx("div",{className:"bg-white rounded-lg shadow overflow-hidden",children:e.jsxs("table",{className:"min-w-full divide-y divide-gray-200",children:[e.jsx("thead",{className:"bg-gray-50",children:e.jsxs("tr",{children:[e.jsx("th",{className:"px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider",children:"Session ID"}),e.jsx("th",{className:"px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider",children:"首次提示"}),e.jsx("th",{className:"px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider",children:"事件数"}),e.jsx("th",{className:"px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider",children:"时间"})]})}),e.jsxs("tbody",{className:"bg-white divide-y divide-gray-200",children:[n.map(t=>e.jsxs("tr",{className:"hover:bg-gray-50 cursor-pointer",onClick:()=>a(t.session_id),children:[e.jsx("td",{className:"px-6 py-4 whitespace-nowrap",children:e.jsxs("div",{className:"flex items-center gap-2 text-sm text-indigo-600 font-mono",children:[e.jsx(u,{className:"h-4 w-4"}),t.session_id.slice(0,12),"..."]})}),e.jsx("td",{className:"px-6 py-4",children:e.jsx("p",{className:"text-sm text-gray-900 max-w-md truncate",children:t.first_prompt||"(无提示)"})}),e.jsx("td",{className:"px-6 py-4 whitespace-nowrap",children:e.jsxs("span",{className:"inline-flex items-center gap-1 text-sm text-gray-600",children:[e.jsx(q,{className:"h-4 w-4"}),t.event_count]})}),e.jsx("td",{className:"px-6 py-4 whitespace-nowrap text-sm text-gray-500",children:e.jsxs("span",{className:"inline-flex items-center gap-1",children:[e.jsx(F,{className:"h-4 w-4"}),t.start_time?w(f(t.start_time),{addSuffix:!0,locale:S}):"-"]})})]},t.session_id)),n.length===0&&e.jsx("tr",{children:e.jsx("td",{colSpan:4,className:"px-6 py-12 text-center text-gray-500",children:l?"无匹配结果":"暂无会话记录"})})]})]})}),e.jsx(N,{open:r!==null,onClose:()=>a(null),title:"会话详情",width:"w-[800px]",children:r&&e.jsx(k,{sessionId:r})})]})}export{X as default};
|
|
2
|
+
//# sourceMappingURL=Sessions-Chx9OCLH.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Sessions-Chx9OCLH.js","sources":["../../src/components/SessionDetailContent.tsx","../../src/pages/Sessions.tsx"],"sourcesContent":["import { useQuery } from '@tanstack/react-query'\nimport { format } from 'date-fns'\nimport { parseUTC } from '../utils/time'\nimport { MessageSquare, FileEdit, Terminal, GitCommit } from 'lucide-react'\nimport clsx from 'clsx'\n\ninterface TaskDetail {\n id: string\n title: string\n start_time: string\n end_time?: string\n status: string\n event_count: number\n prompts: Array<{ timestamp: string; content: string }>\n events: Array<any>\n injections: Array<any>\n summary: {\n toolUsage: Record<string, number>\n filesChanged: string[]\n commits: Array<{ timestamp: string; message: string }>\n }\n}\n\ninterface SessionDetailData {\n session: {\n session_id: string\n first_prompt: string\n event_count: number\n start_time: string\n end_time: string\n }\n tasks: TaskDetail[]\n}\n\nasync function fetchSessionDetail(id: string): Promise<SessionDetailData> {\n const res = await fetch(`/api/sessions/${id}/detail`)\n if (!res.ok) throw new Error('Failed to fetch session detail')\n return res.json()\n}\n\ninterface Props {\n sessionId: string\n}\n\nexport default function SessionDetailContent({ sessionId }: Props) {\n const { data, isLoading, error } = useQuery({\n queryKey: ['session-detail', sessionId],\n queryFn: () => fetchSessionDetail(sessionId),\n enabled: !!sessionId,\n })\n\n if (isLoading) {\n return <div className=\"p-6 text-gray-500\">加载中...</div>\n }\n\n if (error || !data) {\n return <div className=\"p-6 text-red-600\">加载失败</div>\n }\n\n return (\n <div className=\"space-y-4\">\n <div>\n <div className=\"text-xs text-gray-500 mb-1\">Session ID</div>\n <div className=\"text-sm font-mono text-gray-900 break-all\">{data.session.session_id}</div>\n </div>\n\n <div className=\"grid grid-cols-3 gap-4 pb-4 border-b border-gray-200\">\n <div>\n <div className=\"text-xs text-gray-500\">事件数</div>\n <div className=\"text-lg font-semibold\">{data.session.event_count}</div>\n </div>\n <div>\n <div className=\"text-xs text-gray-500\">任务数</div>\n <div className=\"text-lg font-semibold\">{data.tasks.length}</div>\n </div>\n <div>\n <div className=\"text-xs text-gray-500\">开始时间</div>\n <div className=\"text-sm\">\n {data.session.start_time ? format(parseUTC(data.session.start_time), 'MM-dd HH:mm:ss') : '-'}\n </div>\n </div>\n </div>\n\n <div>\n <h3 className=\"text-sm font-semibold text-gray-700 mb-3\">任务列表</h3>\n <div className=\"space-y-3\">\n {data.tasks.map((task) => (\n <div key={task.id} className=\"border border-gray-200 rounded-lg p-4\">\n <div className=\"flex items-center justify-between mb-3\">\n <h4 className=\"text-sm font-semibold text-gray-900 flex-1 mr-2\">{task.title}</h4>\n <span className={clsx(\n 'px-2 py-0.5 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=\"grid grid-cols-3 gap-3 mb-3 text-xs\">\n <div>\n <div className=\"text-gray-500 mb-1 flex items-center gap-1\">\n <Terminal className=\"h-3 w-3\" />工具使用\n </div>\n <div className=\"space-y-0.5\">\n {Object.entries(task.summary.toolUsage).slice(0, 4).map(([tool, count]) => (\n <div key={tool} className=\"flex justify-between\">\n <span className=\"text-gray-600\">{tool}</span>\n <span className=\"font-mono text-gray-900\">{count}</span>\n </div>\n ))}\n </div>\n </div>\n <div>\n <div className=\"text-gray-500 mb-1 flex items-center gap-1\">\n <FileEdit className=\"h-3 w-3\" />文件变更\n </div>\n <div className=\"text-gray-700\">{task.summary.filesChanged.length} 个</div>\n {task.summary.filesChanged.slice(0, 3).map(f => (\n <div key={f} className=\"text-gray-500 truncate text-[10px]\" title={f}>\n {f.split('/').pop()}\n </div>\n ))}\n </div>\n <div>\n <div className=\"text-gray-500 mb-1 flex items-center gap-1\">\n <GitCommit className=\"h-3 w-3\" />提交\n </div>\n <div className=\"text-gray-700\">{task.summary.commits.length} 次</div>\n </div>\n </div>\n\n {task.prompts.length > 0 && (\n <div className=\"border-t border-gray-100 pt-3\">\n <div className=\"text-xs text-gray-500 mb-2 flex items-center gap-1\">\n <MessageSquare className=\"h-3 w-3\" />用户提示 ({task.prompts.length})\n </div>\n <div className=\"space-y-1.5\">\n {task.prompts.slice(0, 3).map((p, i) => (\n <div key={i} className=\"text-xs bg-gray-50 rounded p-2\">\n <p className=\"text-gray-700 line-clamp-2\">{p.content}</p>\n </div>\n ))}\n {task.prompts.length > 3 && (\n <div className=\"text-xs text-gray-400\">还有 {task.prompts.length - 3} 条...</div>\n )}\n </div>\n </div>\n )}\n </div>\n ))}\n </div>\n </div>\n </div>\n )\n}\n","import { useQuery } from '@tanstack/react-query'\nimport { useState, useMemo } from 'react'\nimport { formatDistanceToNow } from 'date-fns'\nimport { parseUTC } from '../utils/time'\nimport { zhCN } from 'date-fns/locale'\nimport { MessageSquare, Clock, Activity, Download } from 'lucide-react'\nimport Drawer from '../components/Drawer'\nimport SessionDetailContent from '../components/SessionDetailContent'\nimport SearchInput from '../components/SearchInput'\nimport { downloadJSON, downloadCSV, getTimestamp } from '../utils/export'\nimport { useToast } from '../components/Toast'\n\ninterface Session {\n session_id: string\n first_prompt: string\n event_count: number\n start_time: string\n end_time: string\n}\n\nasync function fetchSessions(): Promise<Session[]> {\n const res = await fetch('/api/sessions?limit=200')\n if (!res.ok) throw new Error('Failed to fetch sessions')\n return res.json()\n}\n\nexport default function Sessions() {\n const [selectedSessionId, setSelectedSessionId] = useState<string | null>(null)\n const [search, setSearch] = useState('')\n const [showExportMenu, setShowExportMenu] = useState(false)\n const toast = useToast()\n\n const { data: sessions, isLoading, error } = useQuery({\n queryKey: ['sessions'],\n queryFn: fetchSessions,\n refetchInterval: 10000,\n })\n\n const filteredSessions = useMemo(() => {\n if (!sessions) return []\n if (!search.trim()) return sessions\n const q = search.toLowerCase()\n return sessions.filter(s =>\n s.first_prompt?.toLowerCase().includes(q) ||\n s.session_id.toLowerCase().includes(q)\n )\n }, [sessions, search])\n\n const handleExport = (format: 'json' | 'csv') => {\n const ts = getTimestamp()\n if (format === 'json') {\n downloadJSON(`sessions-${ts}.json`, filteredSessions)\n } else {\n downloadCSV(`sessions-${ts}.csv`, filteredSessions)\n }\n toast.success(`已导出 ${filteredSessions.length} 个会话`)\n setShowExportMenu(false)\n }\n\n if (isLoading) {\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 return (\n <div>\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 <div className=\"flex items-center gap-2 flex-wrap\">\n <SearchInput\n value={search}\n onChange={setSearch}\n placeholder=\"搜索 session / 提示...\"\n className=\"w-64\"\n />\n <div className=\"relative\">\n <button\n onClick={() => setShowExportMenu(v => !v)}\n disabled={filteredSessions.length === 0}\n className=\"inline-flex items-center gap-1 px-3 py-1.5 text-sm bg-white border border-gray-300 rounded-md hover:bg-gray-50 disabled:opacity-50\"\n >\n <Download className=\"h-4 w-4\" />\n 导出\n </button>\n {showExportMenu && (\n <>\n <div className=\"fixed inset-0 z-10\" onClick={() => setShowExportMenu(false)} />\n <div className=\"absolute right-0 mt-1 bg-white border border-gray-200 rounded-md shadow-lg z-20\">\n <button\n onClick={() => handleExport('json')}\n className=\"block w-full text-left px-4 py-2 text-sm hover:bg-gray-50\"\n >\n 导出为 JSON\n </button>\n <button\n onClick={() => handleExport('csv')}\n className=\"block w-full text-left px-4 py-2 text-sm hover:bg-gray-50\"\n >\n 导出为 CSV\n </button>\n </div>\n </>\n )}\n </div>\n </div>\n </div>\n\n <div className=\"text-sm text-gray-500 mb-3\">\n 显示 {filteredSessions.length} 个 {search && `(已过滤)`}\n </div>\n\n <div className=\"bg-white rounded-lg shadow overflow-hidden\">\n <table className=\"min-w-full divide-y divide-gray-200\">\n <thead className=\"bg-gray-50\">\n <tr>\n <th className=\"px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider\">\n Session ID\n </th>\n <th className=\"px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider\">\n 首次提示\n </th>\n <th className=\"px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider\">\n 事件数\n </th>\n <th className=\"px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider\">\n 时间\n </th>\n </tr>\n </thead>\n <tbody className=\"bg-white divide-y divide-gray-200\">\n {filteredSessions.map((session) => (\n <tr\n key={session.session_id}\n className=\"hover:bg-gray-50 cursor-pointer\"\n onClick={() => setSelectedSessionId(session.session_id)}\n >\n <td className=\"px-6 py-4 whitespace-nowrap\">\n <div className=\"flex items-center gap-2 text-sm text-indigo-600 font-mono\">\n <MessageSquare className=\"h-4 w-4\" />\n {session.session_id.slice(0, 12)}...\n </div>\n </td>\n <td className=\"px-6 py-4\">\n <p className=\"text-sm text-gray-900 max-w-md truncate\">\n {session.first_prompt || '(无提示)'}\n </p>\n </td>\n <td className=\"px-6 py-4 whitespace-nowrap\">\n <span className=\"inline-flex items-center gap-1 text-sm text-gray-600\">\n <Activity className=\"h-4 w-4\" />\n {session.event_count}\n </span>\n </td>\n <td className=\"px-6 py-4 whitespace-nowrap text-sm text-gray-500\">\n <span className=\"inline-flex items-center gap-1\">\n <Clock className=\"h-4 w-4\" />\n {session.start_time\n ? formatDistanceToNow(parseUTC(session.start_time), {\n addSuffix: true,\n locale: zhCN,\n })\n : '-'}\n </span>\n </td>\n </tr>\n ))}\n {filteredSessions.length === 0 && (\n <tr>\n <td colSpan={4} className=\"px-6 py-12 text-center text-gray-500\">\n {search ? '无匹配结果' : '暂无会话记录'}\n </td>\n </tr>\n )}\n </tbody>\n </table>\n </div>\n\n <Drawer\n open={selectedSessionId !== null}\n onClose={() => setSelectedSessionId(null)}\n title=\"会话详情\"\n width=\"w-[800px]\"\n >\n {selectedSessionId && <SessionDetailContent sessionId={selectedSessionId} />}\n </Drawer>\n </div>\n )\n}\n"],"names":["fetchSessionDetail","id","res","SessionDetailContent","sessionId","data","isLoading","error","useQuery","jsx","jsxs","format","parseUTC","task","clsx","Terminal","tool","count","FileEdit","f","GitCommit","MessageSquare","p","i","fetchSessions","Sessions","selectedSessionId","setSelectedSessionId","useState","search","setSearch","showExportMenu","setShowExportMenu","toast","useToast","sessions","filteredSessions","useMemo","q","s","_a","handleExport","ts","getTimestamp","downloadJSON","downloadCSV","SearchInput","v","Download","Fragment","session","Activity","Clock","formatDistanceToNow","zhCN","Drawer"],"mappings":"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"}
|
|
@@ -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-BeHRQxUS.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-DxIbmNmr.js";import{a as S}from"./auth-Bnf8ZcqN.js";import{B as f,P as C,X as E,l as q}from"./lucide-fJlPI3H7.js";import"./react-router-I-HqunH7.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-O0GT1i7m.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Skills-O0GT1i7m.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 N,j as e}from"./react-vendor-CSp-GLFF.js";import{c as H,L as k}from"./react-router-I-HqunH7.js";import{u as L}from"./query-C99w429o.js";import{p as m}from"./time-Bxuk0M-C.js";import{d as o}from"./vendor-CMMjVdZs.js";import{j as I,o as q,n as B,a as R,g as S,q as W,r as f,s as y,B as A,t as D,F as G,h as E,u as O,p as z,f as K,i as Q,v as U,m as J}from"./lucide-fJlPI3H7.js";import{f as w}from"./date-fns-CZ_bHujz.js";async function V(n){const d=await fetch(`/api/tasks/${n}`);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((l,j)=>({id:`${l.timestamp}-${l.tool_name}-${j}`,timestamp:l.timestamp,tool_name:l.tool_name,hook_type:l.hook_type,input:l.input,output:l.output,is_agent_call:l.is_agent_call,agent_detail:l.agent_detail})),skillInvocations:a.skillInvocations??[],artifacts:a.artifacts??[]}}function X(n){switch(n){case"Read":return e.jsx(J,{className:"h-4 w-4 text-gray-500"});case"Edit":return e.jsx(U,{className:"h-4 w-4 text-amber-600"});case"Write":return e.jsx(Q,{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(K,{className:"h-4 w-4 text-blue-600"});case"Grep":case"Glob":return e.jsx(z,{className:"h-4 w-4 text-purple-500"});case"WebSearch":case"WebFetch":return e.jsx(O,{className:"h-4 w-4 text-cyan-600"});default:return e.jsx(E,{className:"h-4 w-4 text-gray-400"})}}function Y(n,d){const a=m(n).getTime()-m(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 ne(){const{taskId:n}=H(),[d,a]=N.useState(new Set),[l,j]=N.useState(new Set),[b,M]=N.useState(!0),{data:t,isLoading:T,error:h}=L({queryKey:["task-detail",n],queryFn:()=>V(n),enabled:!!n,refetchInterval:1e4});if(T)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(k,{to:"/tasks",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 C=s=>{a(i=>{const r=new Set(i);return r.has(s)?r.delete(s):r.add(s),r})},$=s=>{j(i=>{const r=new Set(i);return r.has(s)?r.delete(s):r.add(s),r})},P=t.end_time?`${Math.round((m(t.end_time).getTime()-m(t.start_time).getTime())/1e3)}s`:"进行中";return e.jsxs("div",{children:[e.jsxs(k,{to:"/tasks",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:t.title}),e.jsxs("span",{className:o("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(q,{className:"h-3 w-3 inline mr-1"}),t.status==="active"&&e.jsx(B,{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(m(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(m(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:P})]}),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(R,{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(m(s.timestamp),"HH:mm:ss")}),e.jsx("div",{className:"text-sm text-gray-800 whitespace-pre-wrap",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:()=>M(!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(W,{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(f,{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:()=>C(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:o("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})]}),d.has(s.id)?e.jsx(f,{className:"h-3 w-3 text-gray-400"}):e.jsx(y,{className:"h-3 w-3 text-gray-400"})]}),d.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 v,_;const r=s.is_agent_call,p=s.tool_name==="Edit"||s.tool_name==="Write",g=l.has(i),c=s.input,x=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:o("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:()=>$(i),children:[e.jsx("div",{className:"relative z-10 flex-shrink-0 w-10 flex justify-center",children:e.jsx("div",{className:o("w-8 h-8 rounded-full flex items-center justify-center",r?"bg-blue-100":"bg-white border border-gray-200"),children:X(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:o("text-sm font-medium",r?"text-blue-700":"text-gray-900"),children:s.tool_name}),((v=s.agent_detail)==null?void 0:v.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}),((_=s.agent_detail)==null?void 0:_.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:[Y(s.timestamp,t.start_time),g?e.jsx(f,{className:"h-3 w-3"}):e.jsx(y,{className:"h-3 w-3"})]})]}),!g&&p&&x&&e.jsx("p",{className:"text-xs text-green-700 font-mono mt-0.5 truncate",title:x,children:x}),!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:F=>F.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&&x&&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:x})]}),!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&&x&&e.jsxs("div",{className:"text-gray-500",children:[e.jsx("span",{className:"font-medium",children:"path: "}),e.jsx("span",{className:"font-mono",children:x})]})]})]})]},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(A,{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(D,{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(G,{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{ne as default};
|
|
2
|
+
//# sourceMappingURL=TaskDetail-5SR8zGzv.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TaskDetail-5SR8zGzv.js","sources":["../../src/pages/TaskDetail.tsx"],"sourcesContent":["import { useParams, Link } 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 {\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'\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 [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=\"/tasks\" 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=\"/tasks\" 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\">{data.title}</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\">{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":["fetchTaskDetail","taskId","res","raw","e","idx","getToolIcon","toolName","jsx","Eye","Pencil","FileEdit","Terminal","Bot","Search","Globe","getRelativeTime","eventTime","startTime","diff","parseUTC","TaskDetail","useParams","expandedInjections","setExpandedInjections","useState","expandedEvents","setExpandedEvents","showInjections","setShowInjections","data","isLoading","error","useQuery","jsxs","Link","ArrowLeft","toggleInjection","id","prev","next","toggleEvent","duration","clsx","CheckCircle2","Loader2","format","MessageSquare","up","Clock","Syringe","ChevronDown","ChevronRight","inj","event","isAgent","isFileOp","isExpanded","input","filePath","description","_a","_b","BookOpen","skill","FolderOpen","FileText"],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{r as d,j as e}from"./react-vendor-CSp-GLFF.js";import{u}from"./query-C99w429o.js";import{p as f}from"./time-Bxuk0M-C.js";import{S as g}from"./SearchInput-BX2KhMkw.js";import{d as p}from"./vendor-CMMjVdZs.js";import{b as j}from"./react-router-I-HqunH7.js";import{A as o,g as N,n as w,o as b}from"./lucide-fJlPI3H7.js";import{a as v,z as y}from"./date-fns-CZ_bHujz.js";async function C(){const a=await fetch("/api/tasks");if(!a.ok)throw new Error("Failed to fetch tasks");return a.json()}function A(){const a=j(),[t,m]=d.useState(""),{data:r,isLoading:x,error:l}=u({queryKey:["tasks"],queryFn:C,refetchInterval:1e4}),i=d.useMemo(()=>{if(!r)return[];if(!t.trim())return r;const s=t.toLowerCase();return r.filter(n=>{var c;return((c=n.title)==null?void 0:c.toLowerCase().includes(s))||n.id.toLowerCase().includes(s)})},[r,t]);if(x)return e.jsxs("div",{children:[e.jsx("h1",{className:"text-2xl font-bold text-gray-900 mb-6",children:"任务"}),e.jsx("div",{className:"bg-white rounded-lg shadow p-6",children:e.jsx("p",{className:"text-gray-600",children:"加载中..."})})]});if(l)return e.jsxs("div",{children:[e.jsx("h1",{className:"text-2xl font-bold text-gray-900 mb-6",children:"任务"}),e.jsx("div",{className:"bg-white rounded-lg shadow p-6",children:e.jsxs("p",{className:"text-red-600",children:["加载失败: ",l.message]})})]});const h=s=>{switch(s){case"completed":return e.jsx(b,{className:"h-4 w-4 text-green-600"});case"active":return e.jsx(w,{className:"h-4 w-4 text-blue-600 animate-spin"});default:return e.jsx(o,{className:"h-4 w-4 text-gray-400"})}};return e.jsxs("div",{children:[e.jsxs("div",{className:"flex items-center justify-between mb-4 flex-wrap gap-3",children:[e.jsx("h1",{className:"text-2xl font-bold text-gray-900",children:"任务"}),e.jsx(g,{value:t,onChange:m,placeholder:"搜索任务标题...",className:"w-64"})]}),e.jsxs("div",{className:"text-sm text-gray-500 mb-3",children:["显示 ",i.length," 个任务 ",t&&"(已过滤)"]}),e.jsxs("div",{className:"grid gap-4",children:[i.map(s=>e.jsxs("div",{onClick:()=>a(`/tasks/${s.id}`),className:"bg-white rounded-lg shadow hover:shadow-md transition-shadow cursor-pointer p-5",children:[e.jsxs("div",{className:"flex items-start justify-between mb-3",children:[e.jsxs("div",{className:"flex items-start gap-3 flex-1",children:[e.jsx("div",{className:"mt-0.5",children:h(s.status)}),e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsx("h3",{className:"text-base font-semibold text-gray-900 mb-1",children:s.title}),e.jsxs("p",{className:"text-xs text-gray-500 font-mono",children:[s.id.slice(0,16),"..."]})]})]}),e.jsx("span",{className:p("px-2 py-1 text-xs font-medium rounded-full whitespace-nowrap ml-3",s.status==="completed"&&"bg-green-100 text-green-700",s.status==="active"&&"bg-blue-100 text-blue-700",s.status==="abandoned"&&"bg-gray-100 text-gray-600"),children:s.status})]}),e.jsxs("div",{className:"flex items-center gap-6 text-sm text-gray-600",children:[e.jsxs("span",{className:"inline-flex items-center gap-1",children:[e.jsx(o,{className:"h-4 w-4"}),s.event_count," 个事件"]}),e.jsxs("span",{className:"inline-flex items-center gap-1",children:[e.jsx(N,{className:"h-4 w-4"}),s.start_time?v(f(s.start_time),{addSuffix:!0,locale:y}):"-"]})]})]},s.id)),i.length===0&&e.jsx("div",{className:"bg-white rounded-lg shadow p-12 text-center text-gray-500",children:t?"无匹配结果":"暂无任务记录"})]})]})}export{A as default};
|
|
2
|
+
//# sourceMappingURL=Tasks-DCgDqvOZ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Tasks-DCgDqvOZ.js","sources":["../../src/pages/Tasks.tsx"],"sourcesContent":["import { useQuery } from '@tanstack/react-query'\nimport { useState, useMemo } from 'react'\nimport { useNavigate } from 'react-router-dom'\nimport { formatDistanceToNow } from 'date-fns'\nimport { parseUTC } from '../utils/time'\nimport { zhCN } from 'date-fns/locale'\nimport { Clock, Activity, CheckCircle2, Loader2 } from 'lucide-react'\nimport SearchInput from '../components/SearchInput'\nimport clsx from 'clsx'\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}\n\nasync function fetchTasks(): Promise<Task[]> {\n const res = await fetch('/api/tasks')\n if (!res.ok) throw new Error('Failed to fetch tasks')\n return res.json()\n}\n\nexport default function Tasks() {\n const navigate = useNavigate()\n const [search, setSearch] = useState('')\n\n const { data: tasks, isLoading, error } = useQuery({\n queryKey: ['tasks'],\n queryFn: fetchTasks,\n refetchInterval: 10000,\n })\n\n const filteredTasks = useMemo(() => {\n if (!tasks) return []\n if (!search.trim()) return tasks\n const q = search.toLowerCase()\n return tasks.filter(t =>\n t.title?.toLowerCase().includes(q) ||\n t.id.toLowerCase().includes(q)\n )\n }, [tasks, search])\n\n if (isLoading) {\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 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 return (\n <div>\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={search}\n onChange={setSearch}\n placeholder=\"搜索任务标题...\"\n className=\"w-64\"\n />\n </div>\n\n <div className=\"text-sm text-gray-500 mb-3\">\n 显示 {filteredTasks.length} 个任务 {search && `(已过滤)`}\n </div>\n\n <div className=\"grid gap-4\">\n {filteredTasks.map((task) => (\n <div\n key={task.id}\n onClick={() => navigate(`/tasks/${task.id}`)}\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\">\n <div className=\"mt-0.5\">{getStatusIcon(task.status)}</div>\n <div className=\"flex-1 min-w-0\">\n <h3 className=\"text-base font-semibold text-gray-900 mb-1\">\n {task.title}\n </h3>\n <p className=\"text-xs text-gray-500 font-mono\">\n {task.id.slice(0, 16)}...\n </p>\n </div>\n </div>\n <span className={clsx(\n 'px-2 py-1 text-xs font-medium rounded-full whitespace-nowrap ml-3',\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 {filteredTasks.length === 0 && (\n <div className=\"bg-white rounded-lg shadow p-12 text-center text-gray-500\">\n {search ? '无匹配结果' : '暂无任务记录'}\n </div>\n )}\n </div>\n </div>\n )\n}\n"],"names":["fetchTasks","res","Tasks","navigate","useNavigate","search","setSearch","useState","tasks","isLoading","error","useQuery","filteredTasks","useMemo","q","t","_a","jsx","jsxs","getStatusIcon","status","CheckCircle2","Loader2","Activity","SearchInput","task","clsx","Clock","formatDistanceToNow","parseUTC","zhCN"],"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 @@
|
|
|
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-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-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-4{width:1rem}.w-5{width:1.25rem}.w-6{width:1.5rem}.w-64{width:16rem}.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-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-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-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\: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-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}}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/Dashboard-D7Bo6Kan.js","assets/react-vendor-CSp-GLFF.js","assets/query-C99w429o.js","assets/react-router-I-HqunH7.js","assets/vendor-CMMjVdZs.js","assets/lucide-fJlPI3H7.js","assets/charts-CLrM0_uM.js","assets/Sessions-Chx9OCLH.js","assets/time-Bxuk0M-C.js","assets/Drawer-BeHRQxUS.js","assets/date-fns-CZ_bHujz.js","assets/SearchInput-BX2KhMkw.js","assets/export-L_VBD2p1.js","assets/syntax-highlighter-44FakypI.js","assets/SessionDetail-Bkr-kC7V.js","assets/Events-K_tCY2ti.js","assets/Skills-O0GT1i7m.js","assets/auth-Bnf8ZcqN.js","assets/AIConfig-BQCAQE9D.js","assets/Tasks-DCgDqvOZ.js","assets/TaskDetail-5SR8zGzv.js","assets/Reports-BJCmBnc_.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-I-HqunH7.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-fJlPI3H7.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-D7Bo6Kan.js"),__vite__mapDeps([0,1,2,3,4,5,6]))),X=r.lazy(()=>m(()=>import("./Sessions-Chx9OCLH.js"),__vite__mapDeps([7,1,2,8,9,4,5,10,11,12,3,13]))),$=r.lazy(()=>m(()=>import("./SessionDetail-Bkr-kC7V.js"),__vite__mapDeps([14,1,3,4,2,8,5,10]))),K=r.lazy(()=>m(()=>import("./Events-K_tCY2ti.js"),__vite__mapDeps([15,1,2,8,4,9,5,13,11,12,10,3]))),G=r.lazy(()=>m(()=>import("./Skills-O0GT1i7m.js"),__vite__mapDeps([16,1,2,9,4,5,13,17,3]))),H=r.lazy(()=>m(()=>import("./AIConfig-BQCAQE9D.js"),__vite__mapDeps([18,1,2,17,5,3,4,13]))),J=r.lazy(()=>m(()=>import("./Tasks-DCgDqvOZ.js"),__vite__mapDeps([19,1,2,8,11,5,4,3,10]))),U=r.lazy(()=>m(()=>import("./TaskDetail-5SR8zGzv.js"),__vite__mapDeps([20,1,3,4,2,8,5,10]))),Y=r.lazy(()=>m(()=>import("./Reports-BJCmBnc_.js"),__vite__mapDeps([21,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-DxIbmNmr.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"mappings":"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","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-DxIbmNmr.js"}
|