@winspan/claude-forge 8.41.0 → 8.51.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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 +420 -12
- 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 +6 -3
- 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/claudemd/templates/swarm-protocol.md +222 -0
- 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 +204 -12
- package/dist/cli/commands/daemon.js.map +1 -1
- package/dist/cli/commands/executions.d.ts.map +1 -1
- package/dist/cli/commands/executions.js +4 -3
- package/dist/cli/commands/executions.js.map +1 -1
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/init.js +5 -37
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/commands/logs.js.map +1 -1
- package/dist/cli/commands/mcp.d.ts.map +1 -1
- package/dist/cli/commands/mcp.js +3 -5
- package/dist/cli/commands/mcp.js.map +1 -1
- package/dist/cli/commands/menu.d.ts.map +1 -1
- package/dist/cli/commands/menu.js +14 -13
- 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 +2 -20
- package/dist/cli/commands/stats.js.map +1 -1
- package/dist/cli/commands/status.js +2 -2
- package/dist/cli/commands/status.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 +125 -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/cli/init/hook-manager.d.ts.map +1 -1
- package/dist/cli/init/hook-manager.js +2 -2
- package/dist/cli/init/hook-manager.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 +2 -2
- 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 +23 -6
- package/dist/core/config.js.map +1 -1
- package/dist/core/constants.d.ts +14 -3
- package/dist/core/constants.d.ts.map +1 -1
- package/dist/core/constants.js +17 -3
- package/dist/core/constants.js.map +1 -1
- package/dist/core/event-fields.d.ts +16 -0
- package/dist/core/event-fields.d.ts.map +1 -0
- package/dist/core/event-fields.js +19 -0
- package/dist/core/event-fields.js.map +1 -0
- 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 +175 -0
- package/dist/core/queue/index.js.map +1 -0
- package/dist/core/storage/base.d.ts +66 -0
- package/dist/core/storage/base.d.ts.map +1 -0
- package/dist/core/storage/base.js +254 -0
- package/dist/core/storage/base.js.map +1 -0
- package/dist/core/storage/events.d.ts +141 -0
- package/dist/core/storage/events.d.ts.map +1 -0
- package/dist/core/storage/events.js +348 -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 +124 -0
- package/dist/core/storage/routing.d.ts.map +1 -0
- package/dist/core/storage/routing.js +239 -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 +85 -137
- package/dist/core/storage/sessions.d.ts +54 -0
- package/dist/core/storage/sessions.d.ts.map +1 -0
- package/dist/core/storage/sessions.js +137 -0
- package/dist/core/storage/sessions.js.map +1 -0
- package/dist/core/storage/skills.d.ts +63 -0
- package/dist/core/storage/skills.d.ts.map +1 -0
- package/dist/core/storage/skills.js +154 -0
- package/dist/core/storage/skills.js.map +1 -0
- package/dist/core/storage/sqlite.d.ts +97 -266
- package/dist/core/storage/sqlite.d.ts.map +1 -1
- package/dist/core/storage/sqlite.js +196 -764
- package/dist/core/storage/sqlite.js.map +1 -1
- package/dist/core/storage/tasks.d.ts +113 -0
- package/dist/core/storage/tasks.d.ts.map +1 -0
- package/dist/core/storage/tasks.js +276 -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 +83 -6
- 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/error-handler.d.ts.map +1 -1
- package/dist/core/utils/error-handler.js +3 -2
- package/dist/core/utils/error-handler.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/git.d.ts +10 -0
- package/dist/core/utils/git.d.ts.map +1 -0
- package/dist/core/utils/git.js +24 -0
- package/dist/core/utils/git.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 +87 -3
- package/dist/core/utils/logger.js.map +1 -1
- package/dist/core/utils/lru-cache.d.ts +1 -0
- package/dist/core/utils/lru-cache.d.ts.map +1 -1
- package/dist/core/utils/lru-cache.js +3 -0
- package/dist/core/utils/lru-cache.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/core/utils/token-tracker.js +1 -1
- package/dist/core/utils/token-tracker.js.map +1 -1
- package/dist/daemon/event-parser.d.ts.map +1 -1
- package/dist/daemon/event-parser.js +2 -1
- package/dist/daemon/event-parser.js.map +1 -1
- 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 +25 -79
- package/dist/daemon/handlers/post-tool-use.js.map +1 -1
- package/dist/daemon/handlers/stop.d.ts +28 -12
- package/dist/daemon/handlers/stop.d.ts.map +1 -1
- package/dist/daemon/handlers/stop.js +129 -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 +93 -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 +97 -127
- 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 +47 -4
- 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 +6 -4
- package/dist/daemon/server.d.ts.map +1 -1
- package/dist/daemon/server.js +80 -88
- package/dist/daemon/server.js.map +1 -1
- 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 +30 -7
- package/dist/daemon/services/task-segmenter.js.map +1 -0
- package/dist/hooks/hook-lib.sh +118 -0
- package/dist/hooks/notification.sh +9 -5
- package/dist/hooks/post-tool-use.sh +10 -6
- package/dist/hooks/pre-tool-use.sh +9 -6
- package/dist/hooks/stop.sh +10 -7
- package/dist/hooks/user-prompt-submit.sh +10 -11
- 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/web/analytics/anti-pattern-detector.d.ts +49 -0
- package/dist/web/analytics/anti-pattern-detector.d.ts.map +1 -0
- package/dist/web/analytics/anti-pattern-detector.js +318 -0
- package/dist/web/analytics/anti-pattern-detector.js.map +1 -0
- package/dist/web/analytics/drift-detector.d.ts +64 -0
- package/dist/web/analytics/drift-detector.d.ts.map +1 -0
- package/dist/web/analytics/drift-detector.js +198 -0
- package/dist/web/analytics/drift-detector.js.map +1 -0
- package/dist/web/analytics/weekly-report.d.ts +91 -0
- package/dist/web/analytics/weekly-report.d.ts.map +1 -0
- package/dist/web/analytics/weekly-report.js +328 -0
- package/dist/web/analytics/weekly-report.js.map +1 -0
- package/dist/web/auth-middleware.d.ts.map +1 -1
- package/dist/web/auth-middleware.js +1 -2
- package/dist/web/auth-middleware.js.map +1 -1
- package/dist/web/routes/_helpers.d.ts +16 -0
- package/dist/web/routes/_helpers.d.ts.map +1 -0
- package/dist/web/routes/_helpers.js +32 -0
- package/dist/web/routes/_helpers.js.map +1 -0
- 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 +13 -3
- package/dist/web/routes/rules.d.ts.map +1 -1
- package/dist/web/routes/rules.js +58 -97
- 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 +43 -69
- package/dist/web/routes/sessions.js.map +1 -1
- package/dist/web/routes/skill-stats.d.ts +2 -0
- package/dist/web/routes/skill-stats.d.ts.map +1 -1
- package/dist/web/routes/skill-stats.js +41 -39
- 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 +39 -4
- package/dist/web/routes/skills.js.map +1 -1
- package/dist/web/routes/stats.d.ts +11 -0
- package/dist/web/routes/stats.d.ts.map +1 -0
- package/dist/web/routes/stats.js +42 -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 +156 -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 +113 -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 +12 -20
- 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-CdDWzJyO.js +2 -0
- package/dist/web/static/assets/AIConfig-CdDWzJyO.js.map +1 -0
- package/dist/web/static/assets/Dashboard-CoEmmIDt.js +2 -0
- package/dist/web/static/assets/Dashboard-CoEmmIDt.js.map +1 -0
- package/dist/web/static/assets/{Drawer-DcU3ln98.js → Drawer-DdRTzlLB.js} +2 -2
- package/dist/web/static/assets/{Drawer-DcU3ln98.js.map → Drawer-DdRTzlLB.js.map} +1 -1
- package/dist/web/static/assets/Events-DrIq1SUS.js +2 -0
- package/dist/web/static/assets/Events-DrIq1SUS.js.map +1 -0
- package/dist/web/static/assets/Reports-DFBM3MDK.js +2 -0
- package/dist/web/static/assets/Reports-DFBM3MDK.js.map +1 -0
- package/dist/web/static/assets/SearchInput-qCj_jAcf.js +2 -0
- package/dist/web/static/assets/SearchInput-qCj_jAcf.js.map +1 -0
- package/dist/web/static/assets/SessionDetail-CCzwdoT7.js +2 -0
- package/dist/web/static/assets/SessionDetail-CCzwdoT7.js.map +1 -0
- package/dist/web/static/assets/Sessions-FfLYkAw9.js +2 -0
- package/dist/web/static/assets/Sessions-FfLYkAw9.js.map +1 -0
- package/dist/web/static/assets/Skills-C8Gvs3Qa.js +2 -0
- package/dist/web/static/assets/Skills-C8Gvs3Qa.js.map +1 -0
- package/dist/web/static/assets/TaskDetail-BS8pYhaR.js +2 -0
- package/dist/web/static/assets/TaskDetail-BS8pYhaR.js.map +1 -0
- package/dist/web/static/assets/Tasks-CyuhizG8.js +2 -0
- package/dist/web/static/assets/Tasks-CyuhizG8.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-CBX47X8l.js +3 -0
- package/dist/web/static/assets/index-CBX47X8l.js.map +1 -0
- package/dist/web/static/assets/index-DjIoMdoR.css +1 -0
- package/dist/web/static/assets/{lucide-53bR2rki.js → lucide-Bs_edTLa.js} +73 -38
- package/dist/web/static/assets/lucide-Bs_edTLa.js.map +1 -0
- package/dist/web/static/assets/react-router-r79dBVy4.js +20 -0
- package/dist/web/static/assets/{react-router-I-HqunH7.js.map → react-router-r79dBVy4.js.map} +1 -1
- package/dist/web/static/assets/task-title-BhOcemuR.js +2 -0
- package/dist/web/static/assets/task-title-BhOcemuR.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 +4 -4
- 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/h1-storage-aggregation-spec-20260518-1121.md +299 -0
- package/docs/design/h2-getdatabase-encapsulation-spec-20260518-1450.md +191 -0
- package/docs/design/h3-fallback-removal-spec-20260518-1245.md +76 -0
- package/docs/design/h4-index-dedup-spec-20260518-1230.md +109 -0
- package/docs/design/h6-services-migration-spec-20260518-1355.md +82 -0
- package/docs/design/hook-failure-queue-spec-20260516-1530.md +204 -0
- package/docs/design/l1-swarm-protocol-extract-spec-20260518-1605.md +106 -0
- package/docs/design/m10-forge-paths-spec-20260518-1320.md +121 -0
- package/docs/design/m2-m3-tool-input-spec-20260518-1425.md +131 -0
- package/docs/design/m7-routing-event-association-spec-20260518-1545.md +103 -0
- package/docs/design/project-path-gitroot-spec-20260518-1715.md +134 -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/task-active-gc-spec-20260518-1745.md +146 -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/h1-storage-aggregation-changelog-20260518-1121.md +82 -0
- package/docs/implementation/h2-final-changelog-20260518-1530.md +61 -0
- package/docs/implementation/h2-phase1-safety-net-changelog-20260518-1450.md +70 -0
- package/docs/implementation/h2-phase2-operations-changelog-20260518-1450.md +120 -0
- package/docs/implementation/h2-phase3-callsites-changelog-20260518-1450.md +71 -0
- package/docs/implementation/h3-fallback-removal-changelog-20260518-1245.md +71 -0
- package/docs/implementation/h4-index-dedup-changelog-20260518-1230.md +60 -0
- package/docs/implementation/h6-services-migration-changelog-20260518-1355.md +46 -0
- package/docs/implementation/h7-m9-defaults-changelog-20260518-1300.md +46 -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/l1-swarm-protocol-extract-changelog-20260518-1605.md +45 -0
- package/docs/implementation/l3-l4-daemon-perf-changelog-20260518-1410.md +63 -0
- package/docs/implementation/l6-l8-final-cleanup-changelog-20260518-1640.md +38 -0
- package/docs/implementation/m1-m4-m5-l7-cleanup-changelog-20260518-1310.md +58 -0
- package/docs/implementation/m10-forge-paths-changelog-20260518-1320.md +60 -0
- package/docs/implementation/m2-m3-tool-input-changelog-20260518-1425.md +43 -0
- package/docs/implementation/m6-m8-naming-shutdown-changelog-20260518-1340.md +56 -0
- package/docs/implementation/m7-routing-association-changelog-20260518-1545.md +69 -0
- package/docs/implementation/project-path-gitroot-changelog-20260518-1715.md +63 -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/task-active-gc-changelog-20260518-1745.md +35 -0
- package/docs/implementation/task-title-summary-changelog-20260518-1130.md +39 -0
- package/docs/implementation/tasks-detail-back-loses-filters-changelog-20260518-1100.md +22 -0
- package/docs/implementation/tasks-list-filter-pagination-changelog-20260518-0930.md +72 -0
- package/docs/implementation/tasks-page-white-screen-hotfix-changelog-20260518-1015.md +56 -0
- package/docs/reviews/claudemd-template-sync.md +54 -0
- package/docs/reviews/task-title-summary.md +92 -0
- package/docs/reviews/tasks-detail-back-loses-filters.md +58 -0
- package/docs/reviews/tasks-filter-pagination.md +80 -0
- package/docs/reviews/tasks-page-white-screen-hotfix.md +126 -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 +568 -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/claudemd/templates/swarm-protocol.md +222 -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 +115 -0
- package/src/cli/commands/init.ts +204 -0
- package/src/cli/commands/logs.ts +181 -0
- package/src/cli/commands/mcp.ts +242 -0
- package/src/cli/commands/menu.ts +357 -0
- package/src/cli/commands/skills.ts +185 -0
- package/src/cli/commands/stats.ts +73 -0
- package/src/cli/commands/status.ts +69 -0
- package/src/cli/commands/template.ts +77 -0
- package/src/cli/commands/trace.ts +148 -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 +62 -0
- package/src/core/event-fields.ts +32 -0
- package/src/core/queue/index.ts +192 -0
- package/src/core/storage/base.ts +302 -0
- package/src/core/storage/events.ts +434 -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 +322 -0
- package/src/core/storage/rows.ts +112 -0
- package/src/core/storage/schema.sql +224 -0
- package/src/core/storage/sessions.ts +168 -0
- package/src/core/storage/skills.ts +233 -0
- package/src/core/storage/sqlite.ts +293 -0
- package/src/core/storage/tasks.ts +318 -0
- package/src/core/storage/token-usage.ts +93 -0
- package/src/core/types.ts +181 -0
- package/src/core/utils/error-handler.ts +257 -0
- package/src/core/utils/forge-resume-block.ts +74 -0
- package/src/core/utils/format.ts +69 -0
- package/src/core/utils/git.ts +23 -0
- package/src/core/utils/logger.ts +134 -0
- package/src/core/utils/lru-cache.ts +54 -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 +36 -0
- package/src/daemon/handlers/history-exporter.ts +117 -0
- package/src/daemon/handlers/post-tool-use.ts +54 -0
- package/src/daemon/handlers/stop.ts +208 -0
- package/src/daemon/handlers/user-prompt.ts +178 -0
- package/src/daemon/index.ts +292 -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 +196 -0
- package/src/daemon/services/task-segmenter.ts +112 -0
- package/src/hooks/hook-lib.sh +118 -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 +43 -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/analytics/anti-pattern-detector.ts +367 -0
- package/src/web/analytics/drift-detector.ts +219 -0
- package/src/web/analytics/weekly-report.ts +431 -0
- package/src/web/auth-middleware.ts +54 -0
- package/src/web/routes/_helpers.ts +34 -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 +76 -0
- package/src/web/routes/sessions.ts +250 -0
- package/src/web/routes/skill-stats.ts +92 -0
- package/src/web/routes/skills.ts +350 -0
- package/src/web/routes/static.ts +67 -0
- package/src/web/routes/stats.ts +50 -0
- package/src/web/routes/status.ts +30 -0
- package/src/web/routes/tasks.ts +193 -0
- package/src/web/routes/token-usage.ts +20 -0
- package/src/web/routes/trace.ts +126 -0
- package/src/web/routes/types.ts +57 -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/claudemd-generator.test.ts +90 -0
- package/tests/integration/queue-replay.integration.test.ts +193 -0
- package/tests/integration/tasks-filter.integration.test.ts +154 -0
- package/tests/integration/web-analytics.integration.test.ts +133 -0
- package/tests/integration/web-stats.integration.test.ts +135 -0
- package/tests/integration/web-trace.integration.test.ts +175 -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/core/forge-paths.test.ts +99 -0
- package/tests/unit/daemon/post-tool-use.test.ts +121 -0
- package/tests/unit/daemon/stop-handler-behavior-summary.test.ts +202 -0
- package/tests/unit/daemon/task-segmenter-recover.test.ts +84 -0
- package/tests/unit/event-fields.test.ts +88 -0
- package/tests/unit/event-parser.test.ts +55 -0
- package/tests/unit/handlers.test.ts +171 -0
- package/tests/unit/hooks/resolve-project-path.test.ts +122 -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/socket-server.test.ts +183 -0
- package/tests/unit/storage/event-operations-aggregates.test.ts +342 -0
- package/tests/unit/storage/migration-idempotent.test.ts +304 -0
- package/tests/unit/storage/routing-aggregates.test.ts +276 -0
- package/tests/unit/storage/routing.test.ts +117 -0
- package/tests/unit/storage/schema-missing.test.ts +81 -0
- package/tests/unit/storage/session-operations-aggregates.test.ts +120 -0
- package/tests/unit/storage/sessions-aggregate.test.ts +435 -0
- package/tests/unit/storage/skill-operations-counts.test.ts +106 -0
- package/tests/unit/storage/skills-aggregates.test.ts +104 -0
- package/tests/unit/storage/sqlite-refactor-harness.test.ts +314 -0
- package/tests/unit/storage/task-operations-counts.test.ts +46 -0
- package/tests/unit/storage/tasks-getById.test.ts +343 -0
- package/tests/unit/storage/tasks-stale-gc.test.ts +86 -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/navigation-back-contract.test.ts +134 -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-rules.test.ts +182 -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 +385 -0
- package/tests/unit/web/task-title-contract.test.ts +210 -0
- package/tests/unit/web/tasks-component-contract.test.ts +179 -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 +515 -0
- package/web/src/pages/Tasks.tsx +415 -0
- package/web/src/utils/auth.ts +59 -0
- package/web/src/utils/export.ts +54 -0
- package/web/src/utils/navigation.ts +25 -0
- package/web/src/utils/task-title.ts +49 -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 -149
- 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 -19
- 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 -18
- 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 -17
- 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 -17
- 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 -21
- 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 -17
- 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 -20
- 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 -21
- 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 -17
- 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 -22
- 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 -45
- 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 -39
- package/dist/daemon/handlers/pre-tool-use.d.ts.map +0 -1
- package/dist/daemon/handlers/pre-tool-use.js +0 -166
- 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 -64
- package/dist/daemon/routing-state.d.ts.map +0 -1
- package/dist/daemon/routing-state.js +0 -240
- 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/engine/security-gates.d.ts +0 -42
- package/dist/engine/security-gates.d.ts.map +0 -1
- package/dist/engine/security-gates.js +0 -210
- package/dist/engine/security-gates.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
- package/dist/web/static/assets/react-router-I-HqunH7.js +0 -20
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ExecutionTrace-DG901hLR.js","sources":["../../src/pages/ExecutionTrace.tsx"],"sourcesContent":["import { useQuery, useQueryClient } from '@tanstack/react-query'\nimport { useState, useEffect, useMemo } from 'react'\nimport { format } from 'date-fns'\nimport { Activity, Wifi, WifiOff, Download } from 'lucide-react'\nimport clsx from 'clsx'\nimport Drawer from '../components/Drawer'\nimport CodeBlock from '../components/CodeBlock'\nimport SearchInput from '../components/SearchInput'\nimport { downloadJSON, downloadCSV, getTimestamp } from '../utils/export'\nimport { useToast } from '../components/Toast'\n\ninterface RoutingEvent {\n id: number\n session_id: string\n project_path: string\n ts: number\n prompt: string\n intent_json: string\n routed_to_type: string\n routed_to_name: string\n is_forced: number\n obeyed: number | null\n classification_ms: number\n fallback_used: number\n refusal_reason: string | null\n first_tool_name: string | null\n first_tool_ts: number | null\n completed_ts: number | null\n total_execution_ms: number | null\n completion_reason: string | null\n verdict: 'obeyed' | 'disobeyed' | 'investigation_only' | 'timeout' | 'no_action' | 'not_applicable'\n}\n\ninterface ExecutionDetail {\n routing: {\n id: number\n sessionId: string\n routeRequestId: string | null\n prompt: string\n timestamp: number\n intent: any\n routedToType: string | null\n routedToName: string | null\n obeyed: number | null\n verdict: RoutingEvent['verdict']\n classificationMs: number | null\n fallbackUsed: boolean\n refusalReason: string | null\n firstTool: string | null\n firstToolTs: number | null\n completedTs: number | null\n totalExecutionMs: number | null\n completionReason: string | null\n taskChain: any[]\n }\n events: Array<{\n event_id: string\n timestamp: string\n hook_type: string\n tool_name: string | null\n user_prompt: string | null\n tool_input: string | null\n tool_output: string | null\n }>\n injections: Array<{\n injection_type: string\n content: string\n timestamp: string\n }>\n agentCalls: Array<{\n toolEventId: number\n tool: string\n subagent: string | null\n startedTs: number\n allowed: boolean\n error: string | null\n completedTs: number | null\n completedEventId: string | null\n status: string\n }>\n skillInvocations: Array<{\n id: string\n route_request_id: string | null\n agent_id: string | null\n skill_id: string\n invocation_type: 'static' | 'dynamic' | 'slash_command'\n reason: string | null\n depth: number\n success: number\n error: string | null\n timestamp: number\n }>\n}\n\nasync function fetchRoutingEvents(filter?: string): Promise<RoutingEvent[]> {\n let url = '/api/routing/events?limit=200'\n if (filter === 'obeyed') url += '&obeyed=1'\n else if (filter === 'refused') url += '&obeyed=0'\n else if (filter === 'unknown') url += '&obeyed=null'\n const res = await fetch(url)\n if (!res.ok) throw new Error('Failed to fetch')\n return res.json()\n}\n\nconst filters = [\n { value: '', label: '全部' },\n { value: 'obeyed', label: '✓ 遵守' },\n { value: 'refused', label: '✗ 违抗' },\n { value: 'unknown', label: '? 未判定' },\n]\n\ntype Verdict = RoutingEvent['verdict']\n\nconst VERDICT_META: Record<Verdict, { label: string; className: string; title: string }> = {\n obeyed: {\n label: '✓ 遵守',\n className: 'bg-green-100 text-green-800 border border-green-200',\n title: '调用了推荐的 agent',\n },\n disobeyed: {\n label: '✗ 违抗',\n className: 'bg-red-100 text-red-800 border border-red-200',\n title: '使用了其他工具而非推荐 agent',\n },\n investigation_only: {\n label: '◎ 仅侦察',\n className: 'bg-orange-100 text-orange-800 border border-orange-200',\n title: '只做了代码调查(Read/Grep/Glob),未调用推荐 agent',\n },\n timeout: {\n label: '⏱ 超时',\n className: 'bg-gray-100 text-gray-700 border border-gray-200',\n title: '30 秒内未检测到任何工具调用',\n },\n no_action: {\n label: '— 纯对话',\n className: 'bg-gray-100 text-gray-600 border border-gray-200',\n title: '未使用任何工具(纯文字回答)',\n },\n not_applicable: {\n label: '· 未适用',\n className: 'bg-gray-50 text-gray-500 border border-gray-200',\n title: '此消息未触发 agent 推荐,不涉及遵守判定',\n },\n}\n\nfunction VerdictBadge({ verdict }: { verdict: Verdict }) {\n const meta = VERDICT_META[verdict] ?? VERDICT_META.not_applicable\n return (\n <span\n className={clsx('inline-flex items-center px-2 py-0.5 rounded text-xs whitespace-nowrap', meta.className)}\n title={meta.title}\n >\n {meta.label}\n </span>\n )\n}\n\nfunction AgentTimeline({ events, routingTimestamp }: { events: ExecutionDetail['events']; routingTimestamp: number }) {\n const [expandedNodes, setExpandedNodes] = useState<Set<string>>(new Set())\n const [collapsedInvestigation, setCollapsedInvestigation] = useState(true)\n\n const postToolUseEvents = events.filter(e => e.hook_type === 'PostToolUse' && e.tool_name)\n\n const investigationTools = new Set(['Read', 'Grep', 'Glob'])\n const investigationEvents = postToolUseEvents.filter(e => e.tool_name && investigationTools.has(e.tool_name))\n const otherEvents = postToolUseEvents.filter(e => e.tool_name && !investigationTools.has(e.tool_name))\n\n const getToolIcon = (toolName: string) => {\n if (investigationTools.has(toolName)) return '🔍'\n if (['Edit', 'Write', 'MultiEdit'].includes(toolName)) return '✏️'\n if (toolName === 'Bash') return '⚙️'\n if (['Agent', 'Task'].includes(toolName)) return '🤖'\n return '📦'\n }\n\n const toggleNode = (eventId: string) => {\n setExpandedNodes(prev => {\n const next = new Set(prev)\n if (next.has(eventId)) next.delete(eventId)\n else next.add(eventId)\n return next\n })\n }\n\n const parseToolData = (jsonStr: string | null) => {\n if (!jsonStr) return null\n try {\n return JSON.parse(jsonStr)\n } catch {\n return null\n }\n }\n\n return (\n <div className=\"space-y-3\">\n {investigationEvents.length > 0 && (\n <div className=\"border border-gray-200 rounded-lg p-3\">\n <button\n onClick={() => setCollapsedInvestigation(!collapsedInvestigation)}\n className=\"flex items-center gap-2 text-sm text-gray-700 hover:text-gray-900 w-full\"\n >\n <span>🔍 侦察 × {investigationEvents.length} 次</span>\n <span className=\"text-xs text-gray-500\">\n {collapsedInvestigation ? '(展开)' : '(收起)'}\n </span>\n </button>\n {!collapsedInvestigation && (\n <div className=\"mt-2 space-y-2 pl-4 border-l-2 border-gray-200\">\n {investigationEvents.map(e => {\n const offsetSec = ((new Date(e.timestamp).getTime() - routingTimestamp) / 1000).toFixed(1)\n const toolInput = parseToolData(e.tool_input)\n const toolOutput = parseToolData(e.tool_output)\n const isExpanded = expandedNodes.has(e.event_id)\n const hasError = toolOutput?.error\n\n return (\n <div key={e.event_id} className=\"text-xs\">\n <button\n onClick={() => toggleNode(e.event_id)}\n className=\"flex items-center gap-2 hover:bg-gray-50 p-1 rounded w-full text-left\"\n >\n <span className=\"text-gray-400 font-mono\">{offsetSec}s</span>\n <span>{getToolIcon(e.tool_name!)}</span>\n <span className=\"font-medium\">{e.tool_name}</span>\n {hasError ? (\n <span className=\"text-red-600\">✗</span>\n ) : (\n <span className=\"text-green-600\">•</span>\n )}\n </button>\n {isExpanded && (\n <div className=\"mt-1 ml-4 space-y-1\">\n {toolInput && (\n <div>\n <div className=\"text-gray-500 mb-0.5\">Input:</div>\n <CodeBlock data={toolInput} language=\"json\" maxHeight=\"150px\" />\n </div>\n )}\n {toolOutput && (\n <div>\n <div className=\"text-gray-500 mb-0.5\">Output:</div>\n <CodeBlock data={toolOutput} language=\"json\" maxHeight=\"150px\" />\n </div>\n )}\n </div>\n )}\n </div>\n )\n })}\n </div>\n )}\n </div>\n )}\n\n <div className=\"space-y-2 pl-4 border-l-2 border-indigo-200\">\n {otherEvents.map(e => {\n const offsetSec = ((new Date(e.timestamp).getTime() - routingTimestamp) / 1000).toFixed(1)\n const toolInput = parseToolData(e.tool_input)\n const toolOutput = parseToolData(e.tool_output)\n const isExpanded = expandedNodes.has(e.event_id)\n const hasError = toolOutput?.error\n\n return (\n <div key={e.event_id} className=\"text-sm\">\n <button\n onClick={() => toggleNode(e.event_id)}\n className=\"flex items-center gap-2 hover:bg-gray-50 p-2 rounded w-full text-left\"\n >\n <span className=\"text-gray-400 font-mono text-xs\">{offsetSec}s</span>\n <span>{getToolIcon(e.tool_name!)}</span>\n <span className=\"font-medium\">{e.tool_name}</span>\n {hasError ? (\n <span className=\"text-red-600\">✗</span>\n ) : (\n <span className=\"text-green-600\">•</span>\n )}\n </button>\n {isExpanded && (\n <div className=\"mt-2 ml-8 space-y-2\">\n {toolInput && (\n <div>\n <div className=\"text-xs text-gray-500 mb-1\">Input:</div>\n <CodeBlock data={toolInput} language=\"json\" maxHeight=\"200px\" />\n </div>\n )}\n {toolOutput && (\n <div>\n <div className=\"text-xs text-gray-500 mb-1\">Output:</div>\n <CodeBlock data={toolOutput} language=\"json\" maxHeight=\"200px\" />\n </div>\n )}\n </div>\n )}\n </div>\n )\n })}\n </div>\n\n {postToolUseEvents.length === 0 && (\n <div className=\"text-center text-gray-500 text-sm py-8\">\n 此次执行未产生工具调用记录\n </div>\n )}\n </div>\n )\n}\n\nfunction ArtifactCards({ events }: { events: ExecutionDetail['events'] }) {\n const [expandedCards, setExpandedCards] = useState<Set<string>>(new Set())\n\n const artifactTools = new Set(['Edit', 'Write', 'MultiEdit', 'Bash'])\n const artifactEvents = events.filter(e =>\n e.hook_type === 'PostToolUse' && e.tool_name && artifactTools.has(e.tool_name)\n )\n\n const toggleCard = (eventId: string) => {\n setExpandedCards(prev => {\n const next = new Set(prev)\n if (next.has(eventId)) next.delete(eventId)\n else next.add(eventId)\n return next\n })\n }\n\n const parseToolData = (jsonStr: string | null) => {\n if (!jsonStr) return null\n try {\n return JSON.parse(jsonStr)\n } catch {\n return null\n }\n }\n\n const countLines = (str: string | undefined) => {\n if (!str) return 0\n return str.split('\\n').length\n }\n\n return (\n <div className=\"space-y-3\">\n {artifactEvents.map(e => {\n const toolInput = parseToolData(e.tool_input)\n const toolOutput = parseToolData(e.tool_output)\n const isExpanded = expandedCards.has(e.event_id)\n\n if (e.tool_name === 'Bash') {\n const command = toolInput?.command || ''\n const stdout = toolOutput?.stdout || ''\n const stderr = toolOutput?.stderr || ''\n\n return (\n <div key={e.event_id} className=\"border border-gray-200 rounded-lg overflow-hidden\">\n <button\n onClick={() => toggleCard(e.event_id)}\n className=\"w-full px-4 py-3 bg-gray-50 hover:bg-gray-100 text-left flex items-center gap-2\"\n >\n <span>⚙️</span>\n <span className=\"font-mono text-sm flex-1 truncate\">$ {command}</span>\n <span className=\"text-xs text-gray-500\">{isExpanded ? '收起' : '展开'}</span>\n </button>\n {isExpanded && (\n <div className=\"p-4 space-y-2\">\n {stdout && (\n <div>\n <div className=\"text-xs text-gray-500 mb-1\">stdout:</div>\n <CodeBlock data={stdout} language=\"bash\" maxHeight=\"300px\" />\n </div>\n )}\n {stderr && (\n <div>\n <div className=\"text-xs text-gray-500 mb-1\">stderr:</div>\n <CodeBlock data={stderr} language=\"bash\" maxHeight=\"300px\" />\n </div>\n )}\n </div>\n )}\n </div>\n )\n }\n\n if (['Edit', 'Write', 'MultiEdit'].includes(e.tool_name!)) {\n const filePath = toolInput?.file_path || '(unknown)'\n const oldString = toolInput?.old_string || ''\n const newString = toolInput?.new_string || toolInput?.content || ''\n const isNew = e.tool_name === 'Write' || !oldString\n const addedLines = countLines(newString)\n const removedLines = countLines(oldString)\n\n return (\n <div key={e.event_id} className=\"border border-gray-200 rounded-lg overflow-hidden\">\n <button\n onClick={() => toggleCard(e.event_id)}\n className=\"w-full px-4 py-3 bg-gray-50 hover:bg-gray-100 text-left flex items-center gap-2\"\n >\n <span>📄</span>\n <span className=\"font-mono text-sm flex-1 truncate\">{filePath}</span>\n <span className=\"text-xs px-2 py-0.5 rounded bg-blue-100 text-blue-700\">\n {isNew ? '+新增' : '~修改'}\n </span>\n {!isNew && (\n <span className=\"text-xs text-gray-500\">\n +{addedLines}/-{removedLines}\n </span>\n )}\n <span className=\"text-xs text-gray-500\">{isExpanded ? '收起' : '展开'}</span>\n </button>\n {isExpanded && (\n <div className=\"p-4 space-y-2\">\n {oldString && (\n <div>\n <div className=\"text-xs text-gray-500 mb-1\">Before:</div>\n <CodeBlock data={oldString} language=\"typescript\" maxHeight=\"200px\" />\n </div>\n )}\n {newString && (\n <div>\n <div className=\"text-xs text-gray-500 mb-1\">{isNew ? 'Content:' : 'After:'}</div>\n <CodeBlock data={newString} language=\"typescript\" maxHeight=\"200px\" />\n </div>\n )}\n </div>\n )}\n </div>\n )\n }\n\n return null\n })}\n\n {artifactEvents.length === 0 && (\n <div className=\"text-center text-gray-500 text-sm py-8\">\n 此次执行未产生文件改动\n </div>\n )}\n </div>\n )\n}\n\nasync function fetchExecutionDetail(id: number): Promise<ExecutionDetail> {\n const res = await fetch(`/api/execution-trace/${id}`)\n if (!res.ok) throw new Error('Failed to fetch execution detail')\n return res.json()\n}\n\nfunction SkillInvocationCard({ invocation }: { invocation: ExecutionDetail['skillInvocations'][0] }) {\n const statusIcon = invocation.success ? '✓' : '✗'\n const statusColor = invocation.success ? 'text-green-600' : 'text-red-600'\n\n return (\n <div className=\"border border-gray-200 rounded-lg p-3\">\n <div className=\"flex items-center gap-2 text-sm\">\n <span className={statusColor}>{statusIcon}</span>\n <span className=\"font-medium\">{invocation.skill_id}</span>\n <span className=\"text-xs text-gray-500\">\n 深度 {invocation.depth} · {new Date(invocation.timestamp).toLocaleTimeString()}\n </span>\n </div>\n {invocation.agent_id && (\n <div className=\"mt-1 text-xs text-gray-500\">\n <span className=\"font-medium\">调用方 Agent:</span> {invocation.agent_id}\n </div>\n )}\n {invocation.reason && (\n <div className=\"mt-1 text-xs text-gray-600\">\n <span className=\"font-medium\">理由:</span> {invocation.reason}\n </div>\n )}\n {invocation.error && (\n <div className=\"mt-1 text-xs text-red-600\">\n <span className=\"font-medium\">错误:</span> {invocation.error}\n </div>\n )}\n </div>\n )\n}\n\nfunction SkillInvocationList({ invocations }: { invocations: ExecutionDetail['skillInvocations'] }) {\n if (!invocations || invocations.length === 0) {\n return <div className=\"text-gray-500 text-sm py-8 text-center\">此次执行未调用任何 Skill</div>\n }\n\n const staticOnes = invocations.filter(i => i.invocation_type === 'static')\n const dynamicOnes = invocations.filter(i => i.invocation_type === 'dynamic')\n const slashOnes = invocations.filter(i => i.invocation_type === 'slash_command')\n\n return (\n <div className=\"space-y-4\">\n {staticOnes.length > 0 && (\n <div>\n <h3 className=\"text-sm font-semibold text-gray-700 mb-2\">\n 静态依赖 Skill ({staticOnes.length})\n </h3>\n <div className=\"space-y-2\">\n {staticOnes.map(inv => (\n <SkillInvocationCard key={inv.id} invocation={inv} />\n ))}\n </div>\n </div>\n )}\n {dynamicOnes.length > 0 && (\n <div>\n <h3 className=\"text-sm font-semibold text-gray-700 mb-2\">\n 动态调用 Skill ({dynamicOnes.length})\n </h3>\n <div className=\"space-y-2\">\n {dynamicOnes.map(inv => (\n <SkillInvocationCard key={inv.id} invocation={inv} />\n ))}\n </div>\n </div>\n )}\n {slashOnes.length > 0 && (\n <div>\n <h3 className=\"text-sm font-semibold text-gray-700 mb-2\">\n Slash Command Skill ({slashOnes.length})\n </h3>\n <div className=\"space-y-2\">\n {slashOnes.map(inv => (\n <SkillInvocationCard key={inv.id} invocation={inv} />\n ))}\n </div>\n </div>\n )}\n </div>\n )\n}\n\nexport default function ExecutionTrace() {\n const [filter, setFilter] = useState('')\n const [search, setSearch] = useState('')\n const [selectedEvent, setSelectedEvent] = useState<RoutingEvent | null>(null)\n const [activeTab, setActiveTab] = useState<'basic' | 'timeline' | 'artifacts' | 'skills'>('basic')\n const [sseConnected, setSseConnected] = useState(false)\n const [showExportMenu, setShowExportMenu] = useState(false)\n const toast = useToast()\n const queryClient = useQueryClient()\n\n useEffect(() => {\n const eventSource = new EventSource('/api/execution-trace/stream')\n eventSource.onopen = () => setSseConnected(true)\n eventSource.onerror = () => setSseConnected(false)\n eventSource.onmessage = (e) => {\n try {\n const data = JSON.parse(e.data)\n if (data.type === 'execution-status') {\n queryClient.invalidateQueries({ queryKey: ['routing-events'] })\n }\n } catch { /* ignore */ }\n }\n return () => {\n eventSource.close()\n setSseConnected(false)\n }\n }, [queryClient])\n\n const { data: events, isLoading } = useQuery({\n queryKey: ['routing-events', filter],\n queryFn: () => fetchRoutingEvents(filter),\n refetchInterval: 10000,\n })\n\n const { data: executionDetail } = useQuery({\n queryKey: ['execution-detail', selectedEvent?.id],\n queryFn: () => fetchExecutionDetail(selectedEvent!.id),\n enabled: selectedEvent !== null,\n })\n\n const filteredEvents = useMemo(() => {\n if (!events) return []\n if (!search.trim()) return events\n const q = search.toLowerCase()\n return events.filter(e =>\n e.prompt?.toLowerCase().includes(q) ||\n e.routed_to_name?.toLowerCase().includes(q) ||\n e.first_tool_name?.toLowerCase().includes(q)\n )\n }, [events, search])\n\n const handleExport = (exportFormat: 'json' | 'csv') => {\n const ts = getTimestamp()\n if (exportFormat === 'json') {\n downloadJSON(`routing-events-${ts}.json`, filteredEvents)\n } else {\n const flat = filteredEvents.map(e => {\n let intent: { taskType?: string; complexity?: string } = {}\n try { intent = JSON.parse(e.intent_json || '{}') } catch { /* ignore */ }\n return {\n id: e.id,\n ts: e.ts ? format(e.ts, 'yyyy-MM-dd HH:mm:ss') : '',\n prompt: e.prompt,\n taskType: intent.taskType || '',\n complexity: intent.complexity || '',\n routed_to: e.routed_to_name || '',\n obeyed: e.obeyed === 1 ? 'yes' : e.obeyed === 0 ? 'no' : '',\n first_tool: e.first_tool_name || '',\n duration_ms: e.total_execution_ms || '',\n refusal_reason: e.refusal_reason || '',\n }\n })\n downloadCSV(`routing-events-${ts}.csv`, flat)\n }\n toast.success(`已导出 ${filteredEvents.length} 条追踪记录`)\n setShowExportMenu(false)\n }\n\n return (\n <div>\n <div className=\"flex items-center justify-between mb-4 flex-wrap gap-3\">\n <div>\n <h1 className=\"text-2xl font-bold text-gray-900\">执行追踪</h1>\n <div className=\"flex items-center gap-2 mt-1\">\n {sseConnected ? (\n <>\n <Wifi className=\"h-3 w-3 text-green-500\" />\n <span className=\"text-xs text-green-600\">实时流已连接</span>\n </>\n ) : (\n <>\n <WifiOff className=\"h-3 w-3 text-gray-400\" />\n <span className=\"text-xs text-gray-500\">实时流未连接</span>\n </>\n )}\n </div>\n </div>\n <div className=\"flex items-center gap-2 flex-wrap\">\n <SearchInput\n value={search}\n onChange={setSearch}\n placeholder=\"搜索 prompt / agent / tool...\"\n className=\"w-56\"\n />\n <div className=\"flex items-center gap-1\">\n {filters.map((f) => (\n <button\n key={f.value}\n onClick={() => setFilter(f.value)}\n className={clsx(\n 'px-2.5 py-1.5 text-xs rounded-md',\n filter === f.value\n ? 'bg-indigo-100 text-indigo-700'\n : 'bg-white text-gray-600 border border-gray-300 hover:bg-gray-50'\n )}\n >\n {f.label}\n </button>\n ))}\n </div>\n <div className=\"relative\">\n <button\n onClick={() => setShowExportMenu(v => !v)}\n disabled={filteredEvents.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 显示 {filteredEvents.length} 条 {search && `(已过滤)`}\n </div>\n\n <div className=\"bg-white rounded-lg shadow overflow-hidden\">\n {isLoading ? (\n <div className=\"p-6\">加载中...</div>\n ) : (\n <table className=\"min-w-full divide-y divide-gray-200\">\n <thead className=\"bg-gray-50\">\n <tr>\n <th className=\"px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase\">时间</th>\n <th className=\"px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase\">提示</th>\n <th className=\"px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase\">路由到</th>\n <th className=\"px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase\">遵守</th>\n <th className=\"px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase\">首工具</th>\n <th className=\"px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase\">耗时</th>\n </tr>\n </thead>\n <tbody className=\"bg-white divide-y divide-gray-200\">\n {filteredEvents.map((e) => {\n let intent: any = {}\n try { intent = JSON.parse(e.intent_json || '{}') } catch { /* ignore */ }\n return (\n <tr\n key={e.id}\n className=\"hover:bg-gray-50 cursor-pointer\"\n onClick={() => setSelectedEvent(e)}\n >\n <td className=\"px-4 py-2 whitespace-nowrap text-xs font-mono text-gray-500\">\n {format(e.ts, 'MM-dd HH:mm:ss')}\n </td>\n <td className=\"px-4 py-2 max-w-xs\">\n <p className=\"text-xs text-gray-700 truncate\" title={e.prompt}>{e.prompt}</p>\n <p className=\"text-xs text-gray-400 mt-0.5\">\n {intent.taskType} / {intent.complexity}\n </p>\n </td>\n <td className=\"px-4 py-2 whitespace-nowrap\">\n {e.routed_to_name ? (\n <span className=\"px-2 py-0.5 text-xs font-medium bg-indigo-100 text-indigo-700 rounded\">\n {e.routed_to_name}\n </span>\n ) : (\n <span className=\"text-xs text-gray-400\">未路由</span>\n )}\n </td>\n <td className=\"px-4 py-2 whitespace-nowrap\">\n <VerdictBadge verdict={e.verdict} />\n </td>\n <td className=\"px-4 py-2 whitespace-nowrap text-xs text-gray-700\">\n {e.first_tool_name || '-'}\n </td>\n <td className=\"px-4 py-2 whitespace-nowrap text-xs font-mono text-gray-500\">\n {e.total_execution_ms ? `${(e.total_execution_ms / 1000).toFixed(1)}s` : '-'}\n </td>\n </tr>\n )\n })}\n {filteredEvents.length === 0 && (\n <tr>\n <td colSpan={6} className=\"px-4 py-12 text-center text-gray-500\">\n <Activity className=\"h-12 w-12 text-gray-300 mx-auto mb-2\" />\n {search ? '无匹配结果' : '暂无追踪记录'}\n </td>\n </tr>\n )}\n </tbody>\n </table>\n )}\n </div>\n\n <Drawer\n open={selectedEvent !== null}\n onClose={() => {\n setSelectedEvent(null)\n setActiveTab('basic')\n }}\n title=\"Agent 执行详情\"\n >\n {selectedEvent && executionDetail && (() => {\n let intent: any = {}\n try { intent = JSON.parse(selectedEvent.intent_json || '{}') } catch { /* ignore */ }\n\n return (\n <div className=\"space-y-4\">\n <div className=\"flex gap-2 border-b border-gray-200 pb-2\">\n {(['basic', 'timeline', 'artifacts', 'skills'] as const).map(tab => (\n <button\n key={tab}\n onClick={() => setActiveTab(tab)}\n className={clsx(\n 'px-3 py-1.5 text-sm rounded-md transition-colors',\n activeTab === tab\n ? 'bg-indigo-100 text-indigo-700 font-medium'\n : 'text-gray-600 hover:bg-gray-100'\n )}\n >\n {tab === 'basic' && '基本'}\n {tab === 'timeline' && '过程'}\n {tab === 'artifacts' && '产物'}\n {tab === 'skills' && `Skill 调用 (${executionDetail?.skillInvocations?.length || 0})`}\n </button>\n ))}\n </div>\n\n {activeTab === 'basic' && (\n <div className=\"space-y-4\">\n <div>\n <div className=\"text-xs text-gray-500 mb-1\">用户提示</div>\n <div className=\"bg-purple-50 rounded p-3 text-sm text-gray-800 whitespace-pre-wrap\">\n {selectedEvent.prompt}\n </div>\n </div>\n\n <div className=\"grid grid-cols-2 gap-3\">\n <div>\n <div className=\"text-xs text-gray-500 mb-1\">路由结果</div>\n <div className=\"text-sm font-medium\">\n {selectedEvent.routed_to_name || '未路由'}\n </div>\n </div>\n <div>\n <div className=\"text-xs text-gray-500 mb-1\">遵守状态</div>\n <div><VerdictBadge verdict={selectedEvent.verdict} /></div>\n </div>\n </div>\n\n <div>\n <div className=\"text-xs text-gray-500 mb-1\">意图分类</div>\n <CodeBlock data={intent} language=\"json\" maxHeight=\"200px\" />\n </div>\n\n <div className=\"grid grid-cols-2 gap-3 text-sm\">\n <div>\n <div className=\"text-xs text-gray-500 mb-1\">首工具</div>\n <div className=\"font-mono\">{selectedEvent.first_tool_name || '-'}</div>\n </div>\n <div>\n <div className=\"text-xs text-gray-500 mb-1\">分类耗时</div>\n <div className=\"font-mono\">{selectedEvent.classification_ms}ms</div>\n </div>\n <div>\n <div className=\"text-xs text-gray-500 mb-1\">总执行时间</div>\n <div className=\"font-mono\">\n {selectedEvent.total_execution_ms\n ? `${(selectedEvent.total_execution_ms / 1000).toFixed(2)}s`\n : '-'}\n </div>\n </div>\n <div>\n <div className=\"text-xs text-gray-500 mb-1\">完成原因</div>\n <div>{selectedEvent.completion_reason || '-'}</div>\n </div>\n </div>\n\n {selectedEvent.refusal_reason && (\n <div>\n <div className=\"text-xs text-gray-500 mb-1\">违抗原因</div>\n <div className=\"bg-red-50 rounded p-3 text-sm text-red-700\">\n {selectedEvent.refusal_reason}\n </div>\n </div>\n )}\n\n <div>\n <div className=\"text-xs text-gray-500 mb-1\">Session</div>\n <div className=\"text-xs font-mono text-gray-700\">{selectedEvent.session_id}</div>\n </div>\n </div>\n )}\n\n {activeTab === 'timeline' && (\n <AgentTimeline\n events={executionDetail.events}\n routingTimestamp={selectedEvent.ts}\n />\n )}\n\n {activeTab === 'artifacts' && (\n <ArtifactCards events={executionDetail.events} />\n )}\n\n {activeTab === 'skills' && (\n <SkillInvocationList invocations={executionDetail.skillInvocations || []} />\n )}\n </div>\n )\n })()}\n </Drawer>\n </div>\n )\n}\n"],"names":["fetchRoutingEvents","filter","url","res","filters","VERDICT_META","VerdictBadge","verdict","meta","jsx","clsx","AgentTimeline","events","routingTimestamp","expandedNodes","setExpandedNodes","useState","collapsedInvestigation","setCollapsedInvestigation","postToolUseEvents","e","investigationTools","investigationEvents","otherEvents","getToolIcon","toolName","toggleNode","eventId","prev","next","parseToolData","jsonStr","jsxs","offsetSec","toolInput","toolOutput","isExpanded","hasError","CodeBlock","ArtifactCards","expandedCards","setExpandedCards","artifactTools","artifactEvents","toggleCard","countLines","str","command","stdout","stderr","filePath","oldString","newString","isNew","addedLines","removedLines","fetchExecutionDetail","id","SkillInvocationCard","invocation","statusIcon","statusColor","SkillInvocationList","invocations","staticOnes","i","dynamicOnes","slashOnes","inv","ExecutionTrace","setFilter","search","setSearch","selectedEvent","setSelectedEvent","activeTab","setActiveTab","sseConnected","setSseConnected","showExportMenu","setShowExportMenu","toast","useToast","queryClient","useQueryClient","useEffect","eventSource","isLoading","useQuery","executionDetail","filteredEvents","useMemo","q","_a","_b","_c","handleExport","exportFormat","ts","getTimestamp","downloadJSON","flat","intent","format","downloadCSV","Fragment","Wifi","WifiOff","SearchInput","f","v","Download","Activity","Drawer","tab"],"mappings":"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"}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{j as s}from"./react-vendor-CSp-GLFF.js";import{N as n,O as i}from"./vendor-CMMjVdZs.js";import{h as d,o as c}from"./syntax-highlighter-44FakypI.js";function p({content:m,className:x=""}){return s.jsx("div",{className:`prose prose-sm max-w-none ${x}`,children:s.jsx(n,{remarkPlugins:[i],components:{code({inline:e,className:t,children:r,...o}){const a=/language-(\w+)/.exec(t||""),l=a==null?void 0:a[1];return!e&&l?s.jsx(d,{style:c,language:l,PreTag:"div",customStyle:{margin:0,borderRadius:"6px",fontSize:"12px",padding:"12px"},...o,children:String(r).replace(/\n$/,"")}):s.jsx("code",{className:"bg-gray-100 text-gray-800 px-1 py-0.5 rounded text-xs font-mono",...o,children:r})},h1:({children:e})=>s.jsx("h1",{className:"text-lg font-bold text-gray-900 mt-4 mb-2",children:e}),h2:({children:e})=>s.jsx("h2",{className:"text-base font-bold text-gray-900 mt-3 mb-2",children:e}),h3:({children:e})=>s.jsx("h3",{className:"text-sm font-semibold text-gray-900 mt-2 mb-1",children:e}),p:({children:e})=>s.jsx("p",{className:"text-sm text-gray-700 my-2",children:e}),ul:({children:e})=>s.jsx("ul",{className:"list-disc list-inside text-sm text-gray-700 my-2 space-y-0.5",children:e}),ol:({children:e})=>s.jsx("ol",{className:"list-decimal list-inside text-sm text-gray-700 my-2 space-y-0.5",children:e}),li:({children:e})=>s.jsx("li",{className:"text-sm",children:e}),a:({children:e,href:t})=>s.jsx("a",{href:t,target:"_blank",rel:"noopener noreferrer",className:"text-indigo-600 hover:text-indigo-700 underline",children:e}),blockquote:({children:e})=>s.jsx("blockquote",{className:"border-l-4 border-gray-300 pl-3 italic text-gray-600 my-2",children:e}),table:({children:e})=>s.jsx("div",{className:"overflow-x-auto my-2",children:s.jsx("table",{className:"min-w-full border border-gray-200 text-sm",children:e})}),th:({children:e})=>s.jsx("th",{className:"border border-gray-200 px-2 py-1 bg-gray-50 font-semibold text-left",children:e}),td:({children:e})=>s.jsx("td",{className:"border border-gray-200 px-2 py-1",children:e})},children:m})})}export{p as M};
|
|
2
|
-
//# sourceMappingURL=MarkdownRenderer-CCIz1MOz.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"MarkdownRenderer-CCIz1MOz.js","sources":["../../src/components/MarkdownRenderer.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"],"names":["MarkdownRenderer","content","className","jsx","ReactMarkdown","remarkGfm","inline","children","props","match","lang","SyntaxHighlighter","oneLight","href"],"mappings":"2JAUA,SAAwBA,EAAiB,CAAE,QAAAC,EAAS,UAAAC,EAAY,IAAa,CAC3E,OACEC,EAAAA,IAAC,MAAA,CAAI,UAAW,6BAA6BD,CAAS,GACpD,SAAAC,EAAAA,IAACC,EAAA,CACC,cAAe,CAACC,CAAS,EACzB,WAAY,CACV,KAAK,CAAE,OAAAC,EAAQ,UAAAJ,EAAW,SAAAK,EAAU,GAAGC,GAAc,CACnD,MAAMC,EAAQ,iBAAiB,KAAKP,GAAa,EAAE,EAC7CQ,EAAOD,GAAA,YAAAA,EAAQ,GACrB,MAAI,CAACH,GAAUI,EAEXP,EAAAA,IAACQ,EAAA,CACC,MAAOC,EACP,SAAUF,EACV,OAAO,MACP,YAAa,CACX,OAAQ,EACR,aAAc,MACd,SAAU,OACV,QAAS,MAAA,EAEV,GAAGF,EAEH,SAAA,OAAOD,CAAQ,EAAE,QAAQ,MAAO,EAAE,CAAA,CAAA,EAKvCJ,EAAAA,IAAC,OAAA,CACC,UAAU,kEACT,GAAGK,EAEH,SAAAD,CAAA,CAAA,CAGP,EACA,GAAI,CAAC,CAAE,SAAAA,CAAA,IAAeJ,EAAAA,IAAC,KAAA,CAAG,UAAU,4CAA6C,SAAAI,EAAS,EAC1F,GAAI,CAAC,CAAE,SAAAA,CAAA,IAAeJ,EAAAA,IAAC,KAAA,CAAG,UAAU,8CAA+C,SAAAI,EAAS,EAC5F,GAAI,CAAC,CAAE,SAAAA,CAAA,IAAeJ,EAAAA,IAAC,KAAA,CAAG,UAAU,gDAAiD,SAAAI,EAAS,EAC9F,EAAG,CAAC,CAAE,SAAAA,CAAA,IAAeJ,EAAAA,IAAC,IAAA,CAAE,UAAU,6BAA8B,SAAAI,EAAS,EACzE,GAAI,CAAC,CAAE,SAAAA,CAAA,IAAeJ,EAAAA,IAAC,KAAA,CAAG,UAAU,+DAAgE,SAAAI,EAAS,EAC7G,GAAI,CAAC,CAAE,SAAAA,CAAA,IAAeJ,EAAAA,IAAC,KAAA,CAAG,UAAU,kEAAmE,SAAAI,EAAS,EAChH,GAAI,CAAC,CAAE,SAAAA,CAAA,IAAeJ,EAAAA,IAAC,KAAA,CAAG,UAAU,UAAW,SAAAI,EAAS,EACxD,EAAG,CAAC,CAAE,SAAAA,EAAU,KAAAM,KACdV,EAAAA,IAAC,IAAA,CAAE,KAAAU,EAAY,OAAO,SAAS,IAAI,sBAAsB,UAAU,kDAChE,SAAAN,EACH,EAEF,WAAY,CAAC,CAAE,SAAAA,CAAA,IACbJ,EAAAA,IAAC,aAAA,CAAW,UAAU,4DACnB,SAAAI,EACH,EAEF,MAAO,CAAC,CAAE,SAAAA,CAAA,IACRJ,EAAAA,IAAC,MAAA,CAAI,UAAU,uBACb,SAAAA,EAAAA,IAAC,QAAA,CAAM,UAAU,4CAA6C,SAAAI,EAAS,EACzE,EAEF,GAAI,CAAC,CAAE,SAAAA,CAAA,IAAeJ,EAAAA,IAAC,KAAA,CAAG,UAAU,sEAAuE,SAAAI,EAAS,EACpH,GAAI,CAAC,CAAE,SAAAA,KAAeJ,EAAAA,IAAC,KAAA,CAAG,UAAU,mCAAoC,SAAAI,CAAA,CAAS,CAAA,EAGlF,SAAAN,CAAA,CAAA,EAEL,CAEJ"}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{j as e}from"./react-vendor-CSp-GLFF.js";import{u as c}from"./query-C99w429o.js";import{b as m}from"./react-router-I-HqunH7.js";import{A as o,e as h,f as p,T as g}from"./lucide-53bR2rki.js";import"./vendor-CMMjVdZs.js";async function y(){const a=await fetch("/api/routing/stats?window=168");if(!a.ok)throw new Error("Failed to fetch");return a.json()}function w(){var n,i;const a=m(),{data:t,isLoading:x}=c({queryKey:["routing-stats"],queryFn:y,refetchInterval:1e4});if(x)return e.jsx("div",{className:"bg-white rounded-lg shadow p-6",children:"加载中..."});if(!t)return e.jsx("div",{className:"bg-white rounded-lg shadow p-6 text-red-600",children:"加载失败"});const d=t.obedienceRate!==null&&t.obedienceRate!==void 0?(t.obedienceRate*100).toFixed(1):"-",r=Object.entries(t.byAgent||{}).map(([s,l])=>({agent:s,...l,refusalRate:l.total>0?l.refused/l.total:null}));return e.jsxs("div",{children:[e.jsx("h1",{className:"text-2xl font-bold text-gray-900 mb-6",children:"Agent 路由"}),e.jsxs("div",{className:"grid grid-cols-1 md:grid-cols-4 gap-4 mb-6",children:[e.jsxs("div",{className:"bg-white rounded-lg shadow p-5",children:[e.jsxs("div",{className:"flex items-center justify-between mb-2",children:[e.jsx("span",{className:"text-sm text-gray-500",children:"总路由次数"}),e.jsx(o,{className:"h-4 w-4 text-gray-400"})]}),e.jsx("div",{className:"text-2xl font-bold text-gray-900",children:t.total}),e.jsx("div",{className:"text-xs text-gray-500 mt-1",children:"最近 7 天"})]}),e.jsxs("div",{className:"bg-white rounded-lg shadow p-5",children:[e.jsxs("div",{className:"flex items-center justify-between mb-2",children:[e.jsx("span",{className:"text-sm text-gray-500",children:"遵守率"}),e.jsx(h,{className:"h-4 w-4 text-green-500"})]}),e.jsxs("div",{className:"text-2xl font-bold text-gray-900",children:[d,"%"]}),e.jsxs("div",{className:"text-xs text-gray-500 mt-1",children:[t.obeyedCount," / ",t.obeyedCount+t.refusedCount]})]}),e.jsxs("div",{className:"bg-white rounded-lg shadow p-5",children:[e.jsxs("div",{className:"flex items-center justify-between mb-2",children:[e.jsx("span",{className:"text-sm text-gray-500",children:"违抗率"}),e.jsx(p,{className:"h-4 w-4 text-red-500"})]}),e.jsxs("div",{className:"text-2xl font-bold text-gray-900",children:[t.refusalRate!==null&&t.refusalRate!==void 0?(t.refusalRate*100).toFixed(1):"-","%"]}),e.jsxs("div",{className:"text-xs text-gray-500 mt-1",children:[t.refusedCount," 次"]})]}),e.jsxs("div",{className:"bg-white rounded-lg shadow p-5",children:[e.jsxs("div",{className:"flex items-center justify-between mb-2",children:[e.jsx("span",{className:"text-sm text-gray-500",children:"平均分类耗时"}),e.jsx(g,{className:"h-4 w-4 text-blue-500"})]}),e.jsx("div",{className:"text-2xl font-bold text-gray-900",children:(n=t.latency)!=null&&n.p50?`${t.latency.p50}ms`:"-"}),e.jsxs("div",{className:"text-xs text-gray-500 mt-1",children:["p95: ",(i=t.latency)!=null&&i.p95?`${t.latency.p95}ms`:"-"]})]})]}),e.jsxs("div",{className:"bg-white rounded-lg shadow overflow-hidden",children:[e.jsx("div",{className:"px-6 py-4 border-b border-gray-200",children:e.jsx("h3",{className:"text-lg font-semibold text-gray-900",children:"按 Agent 统计"})}),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",children:"Agent"}),e.jsx("th",{className:"px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase",children:"总次数"}),e.jsx("th",{className:"px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase",children:"遵守"}),e.jsx("th",{className:"px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase",children:"违抗"}),e.jsx("th",{className:"px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase",children:"未判定"}),e.jsx("th",{className:"px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase",children:"违抗率"})]})}),e.jsxs("tbody",{className:"bg-white divide-y divide-gray-200",children:[r.map(s=>e.jsxs("tr",{className:"hover:bg-gray-50 cursor-pointer",onClick:()=>a(`/execution-trace?agent=${encodeURIComponent(s.agent)}`),children:[e.jsx("td",{className:"px-6 py-3 whitespace-nowrap",children:e.jsx("span",{className:"text-sm font-medium text-indigo-600",children:s.agent})}),e.jsx("td",{className:"px-6 py-3 whitespace-nowrap text-sm text-gray-700",children:s.total}),e.jsx("td",{className:"px-6 py-3 whitespace-nowrap text-sm text-green-600",children:s.obeyed}),e.jsx("td",{className:"px-6 py-3 whitespace-nowrap text-sm text-red-600",children:s.refused}),e.jsx("td",{className:"px-6 py-3 whitespace-nowrap text-sm text-gray-400",children:s.unknown}),e.jsx("td",{className:"px-6 py-3 whitespace-nowrap text-sm text-gray-700",children:s.refusalRate!==null?`${(s.refusalRate*100).toFixed(1)}%`:"-"})]},s.agent)),r.length===0&&e.jsx("tr",{children:e.jsx("td",{colSpan:6,className:"px-6 py-12 text-center text-gray-500",children:"暂无数据"})})]})]})]})]})}export{w as default};
|
|
2
|
-
//# sourceMappingURL=Routing-B7BFLfjh.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Routing-B7BFLfjh.js","sources":["../../src/pages/Routing.tsx"],"sourcesContent":["import { useQuery } from '@tanstack/react-query'\nimport { useNavigate } from 'react-router-dom'\nimport { TrendingUp, AlertTriangle, CheckCircle, Activity } from 'lucide-react'\n\ninterface AgentStats {\n total: number\n obeyed: number\n refused: number\n unknown: number\n}\n\ninterface RoutingStats {\n windowHours: number\n total: number\n forced: number\n obeyedCount: number\n refusedCount: number\n unknownCount: number\n obedienceRate: number | null\n refusalRate: number | null\n fallbackUsedCount?: number\n latency?: { p50?: number; p95?: number; p99?: number; count?: number }\n byAgent: Record<string, AgentStats>\n}\n\nasync function fetchRoutingStats(): Promise<RoutingStats> {\n const res = await fetch('/api/routing/stats?window=168')\n if (!res.ok) throw new Error('Failed to fetch')\n return res.json()\n}\n\nexport default function Routing() {\n const navigate = useNavigate()\n const { data: stats, isLoading } = useQuery({\n queryKey: ['routing-stats'],\n queryFn: fetchRoutingStats,\n refetchInterval: 10000,\n })\n\n if (isLoading) {\n return <div className=\"bg-white rounded-lg shadow p-6\">加载中...</div>\n }\n\n if (!stats) {\n return <div className=\"bg-white rounded-lg shadow p-6 text-red-600\">加载失败</div>\n }\n\n const obediencePercent = stats.obedienceRate !== null && stats.obedienceRate !== undefined\n ? (stats.obedienceRate * 100).toFixed(1)\n : '-'\n\n // 把 byAgent 对象转成数组\n const byAgentArray = Object.entries(stats.byAgent || {}).map(([agent, s]) => ({\n agent,\n ...s,\n refusalRate: s.total > 0 ? s.refused / s.total : null,\n }))\n\n return (\n <div>\n <h1 className=\"text-2xl font-bold text-gray-900 mb-6\">Agent 路由</h1>\n\n {/* Stats cards */}\n <div className=\"grid grid-cols-1 md:grid-cols-4 gap-4 mb-6\">\n <div className=\"bg-white rounded-lg shadow p-5\">\n <div className=\"flex items-center justify-between mb-2\">\n <span className=\"text-sm text-gray-500\">总路由次数</span>\n <Activity className=\"h-4 w-4 text-gray-400\" />\n </div>\n <div className=\"text-2xl font-bold text-gray-900\">{stats.total}</div>\n <div className=\"text-xs text-gray-500 mt-1\">最近 7 天</div>\n </div>\n\n <div className=\"bg-white rounded-lg shadow p-5\">\n <div className=\"flex items-center justify-between mb-2\">\n <span className=\"text-sm text-gray-500\">遵守率</span>\n <CheckCircle className=\"h-4 w-4 text-green-500\" />\n </div>\n <div className=\"text-2xl font-bold text-gray-900\">{obediencePercent}%</div>\n <div className=\"text-xs text-gray-500 mt-1\">{stats.obeyedCount} / {stats.obeyedCount + stats.refusedCount}</div>\n </div>\n\n <div className=\"bg-white rounded-lg shadow p-5\">\n <div className=\"flex items-center justify-between mb-2\">\n <span className=\"text-sm text-gray-500\">违抗率</span>\n <AlertTriangle className=\"h-4 w-4 text-red-500\" />\n </div>\n <div className=\"text-2xl font-bold text-gray-900\">\n {stats.refusalRate !== null && stats.refusalRate !== undefined\n ? (stats.refusalRate * 100).toFixed(1)\n : '-'}%\n </div>\n <div className=\"text-xs text-gray-500 mt-1\">{stats.refusedCount} 次</div>\n </div>\n\n <div className=\"bg-white rounded-lg shadow p-5\">\n <div className=\"flex items-center justify-between mb-2\">\n <span className=\"text-sm text-gray-500\">平均分类耗时</span>\n <TrendingUp className=\"h-4 w-4 text-blue-500\" />\n </div>\n <div className=\"text-2xl font-bold text-gray-900\">\n {stats.latency?.p50 ? `${stats.latency.p50}ms` : '-'}\n </div>\n <div className=\"text-xs text-gray-500 mt-1\">\n p95: {stats.latency?.p95 ? `${stats.latency.p95}ms` : '-'}\n </div>\n </div>\n </div>\n\n {/* By Agent table */}\n <div className=\"bg-white rounded-lg shadow overflow-hidden\">\n <div className=\"px-6 py-4 border-b border-gray-200\">\n <h3 className=\"text-lg font-semibold text-gray-900\">按 Agent 统计</h3>\n </div>\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\">Agent</th>\n <th className=\"px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase\">总次数</th>\n <th className=\"px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase\">遵守</th>\n <th className=\"px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase\">违抗</th>\n <th className=\"px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase\">未判定</th>\n <th className=\"px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase\">违抗率</th>\n </tr>\n </thead>\n <tbody className=\"bg-white divide-y divide-gray-200\">\n {byAgentArray.map((row) => (\n <tr\n key={row.agent}\n className=\"hover:bg-gray-50 cursor-pointer\"\n onClick={() => navigate(`/execution-trace?agent=${encodeURIComponent(row.agent)}`)}\n >\n <td className=\"px-6 py-3 whitespace-nowrap\">\n <span className=\"text-sm font-medium text-indigo-600\">{row.agent}</span>\n </td>\n <td className=\"px-6 py-3 whitespace-nowrap text-sm text-gray-700\">{row.total}</td>\n <td className=\"px-6 py-3 whitespace-nowrap text-sm text-green-600\">{row.obeyed}</td>\n <td className=\"px-6 py-3 whitespace-nowrap text-sm text-red-600\">{row.refused}</td>\n <td className=\"px-6 py-3 whitespace-nowrap text-sm text-gray-400\">{row.unknown}</td>\n <td className=\"px-6 py-3 whitespace-nowrap text-sm text-gray-700\">\n {row.refusalRate !== null ? `${(row.refusalRate * 100).toFixed(1)}%` : '-'}\n </td>\n </tr>\n ))}\n {byAgentArray.length === 0 && (\n <tr>\n <td colSpan={6} className=\"px-6 py-12 text-center text-gray-500\">暂无数据</td>\n </tr>\n )}\n </tbody>\n </table>\n </div>\n </div>\n )\n}\n"],"names":["fetchRoutingStats","res","Routing","navigate","useNavigate","stats","isLoading","useQuery","jsx","obediencePercent","byAgentArray","agent","s","jsxs","Activity","CheckCircle","AlertTriangle","TrendingUp","_a","_b","row"],"mappings":"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"}
|
|
@@ -1,2 +0,0 @@
|
|
|
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{d as o}from"./vendor-CMMjVdZs.js";import{j as n,h,F as g,i as j,a as p}from"./lucide-53bR2rki.js";import{f as N}from"./date-fns-CZ_bHujz.js";async function f(a){const t=await fetch(`/api/sessions/${a}/detail`);if(!t.ok)throw new Error("Failed to fetch session detail");return t.json()}function L(){const{id:a}=c(),{data:t,isLoading:d,error:x}=m({queryKey:["session-detail",a],queryFn:()=>f(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?N(new Date(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:o("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(h,{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(g,{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(j,{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(p,{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{L as default};
|
|
2
|
-
//# sourceMappingURL=SessionDetail-BT0l4RrK.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"SessionDetail-BT0l4RrK.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 { 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(new Date(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","task","clsx","Terminal","tool","count","FileEdit","GitCommit","MessageSquare","p","i"],"mappings":"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"}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{j as e,r as o}from"./react-vendor-CSp-GLFF.js";import{u as j}from"./query-C99w429o.js";import{D as y}from"./Drawer-DcU3ln98.js";import{d as N}from"./vendor-CMMjVdZs.js";import{f as v,a as b,z as w}from"./date-fns-CZ_bHujz.js";import{h as S,F as C,i as _,a as f,D,A as E,g as F}from"./lucide-53bR2rki.js";import{S as q,g as M,d as z,a as I}from"./export-BQQZLaHV.js";import{u as L}from"./index-Cgr9qMtq.js";import"./react-router-I-HqunH7.js";import"./syntax-highlighter-44FakypI.js";async function T(r){const a=await fetch(`/api/sessions/${r}/detail`);if(!a.ok)throw new Error("Failed to fetch session detail");return a.json()}function $({sessionId:r}){const{data:a,isLoading:l,error:m}=j({queryKey:["session-detail",r],queryFn:()=>T(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?v(new Date(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:N("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(S,{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(C,{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(_,{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(f,{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 k(){const r=await fetch("/api/sessions?limit=200");if(!r.ok)throw new Error("Failed to fetch sessions");return r.json()}function U(){const[r,a]=o.useState(null),[l,m]=o.useState(""),[s,i]=o.useState(!1),c=L(),{data:x,isLoading:u,error:h}=j({queryKey:["sessions"],queryFn:k,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=M();t==="json"?z(`sessions-${d}.json`,n):I(`sessions-${d}.csv`,n),c.success(`已导出 ${n.length} 个会话`),i(!1)};return u?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(q,{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(D,{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(f,{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(E,{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?b(new Date(t.start_time),{addSuffix:!0,locale:w}):"-"]})})]},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(y,{open:r!==null,onClose:()=>a(null),title:"会话详情",width:"w-[800px]",children:r&&e.jsx($,{sessionId:r})})]})}export{U as default};
|
|
2
|
-
//# sourceMappingURL=Sessions-C6J_HQ_u.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Sessions-C6J_HQ_u.js","sources":["../../src/components/SessionDetailContent.tsx","../../src/pages/Sessions.tsx"],"sourcesContent":["import { useQuery } from '@tanstack/react-query'\nimport { format } from 'date-fns'\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(new Date(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 { 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(new Date(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","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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"}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{r as c,j as e}from"./react-vendor-CSp-GLFF.js";import{b as p,u,c as j}from"./query-C99w429o.js";import{D as y}from"./Drawer-DcU3ln98.js";import{M as w}from"./MarkdownRenderer-CCIz1MOz.js";import{u as b}from"./index-Cgr9qMtq.js";import{a as v}from"./auth-Bnf8ZcqN.js";import{b as g,P as N,X as k,n as S}from"./lucide-53bR2rki.js";import"./vendor-CMMjVdZs.js";import"./syntax-highlighter-44FakypI.js";import"./react-router-I-HqunH7.js";async function C(){const i=await fetch("/api/skills");if(!i.ok)throw new Error("Failed to fetch skills");const s=await i.json();return Array.isArray(s)?s:s.skills||[]}async function E(i){const s=await fetch(`/api/skills/${i}`);if(!s.ok)throw new Error("Failed to fetch");return s.json()}async function F(i,s){if(!(await v(`/api/skills/${i}`,{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({content:s})})).ok)throw new Error("Failed to save")}function R(){const i=p(),s=b(),{data:n,isLoading:f}=u({queryKey:["skills"],queryFn:C}),[r,x]=c.useState(null),[m,l]=c.useState(!1),[h,d]=c.useState(""),{data:t}=u({queryKey:["skill-detail",r],queryFn:()=>E(r),enabled:!!r});c.useEffect(()=>{t!=null&&t.content&&d(t.content),l(!1)},[t]);const o=j({mutationFn:a=>F(a.name,a.content),onSuccess:()=>{s.success("Skill 已保存"),l(!1),i.invalidateQueries({queryKey:["skill-detail",r]}),i.invalidateQueries({queryKey:["skills"]})},onError:a=>s.error(`保存失败: ${a.message}`)});return f?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:["共 ",(n==null?void 0:n.length)||0," 个 Skill"]})]}),e.jsx("div",{className:"grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4",children:n==null?void 0:n.map(a=>e.jsx("div",{className:"bg-white rounded-lg shadow p-5 hover:shadow-md transition-shadow cursor-pointer",onClick:()=>x(a.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(g,{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:a.name}),e.jsx("p",{className:"text-xs text-gray-500 mt-1 line-clamp-3",children:a.description||"(无描述)"})]})]})},a.name))}),e.jsx(y,{open:r!==null,onClose:()=>{x(null),l(!1)},title:`Skill: ${r}`,width:"w-[800px]",children:t&&e.jsxs("div",{className:"space-y-4",children:[e.jsxs("div",{className:"flex items-center gap-2 mb-2",children:[e.jsx(g,{className:"h-5 w-5 text-purple-600"}),e.jsx("h3",{className:"text-lg font-semibold text-gray-900",children:t.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:t.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:m?e.jsxs(e.Fragment,{children:[e.jsxs("button",{onClick:()=>{l(!1),d(t.content||"")},className:"inline-flex items-center gap-1 text-xs text-gray-600 hover:text-gray-700",children:[e.jsx(k,{className:"h-3 w-3"}),"取消"]}),e.jsxs("button",{onClick:()=>o.mutate({name:t.name,content:h}),disabled:o.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(S,{className:"h-3 w-3"}),o.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(N,{className:"h-3 w-3"}),"编辑"]})})]}),m?e.jsx("textarea",{value:h,onChange:a=>d(a.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(w,{content:t.content||""})}),o.isError&&e.jsxs("div",{className:"text-xs text-red-600 mt-1",children:["保存失败:",o.error.message]})]})]})})]})}export{R as default};
|
|
2
|
-
//# sourceMappingURL=Skills-4DQWLaTv.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Skills-4DQWLaTv.js","sources":["../../src/pages/Skills.tsx"],"sourcesContent":["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":["fetchSkills","res","data","fetchSkillDetail","name","saveSkill","content","authFetch","Skills","queryClient","useQueryClient","toast","useToast","skills","isLoading","useQuery","selectedSkill","setSelectedSkill","useState","editing","setEditing","editContent","setEditContent","detail","useEffect","mutation","useMutation","vars","e","jsx","jsxs","skill","BookOpen","Drawer","Fragment","X","Save","Edit2","MarkdownRenderer"],"mappings":"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"}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{j as e}from"./react-vendor-CSp-GLFF.js";import{c as j,L as u}from"./react-router-I-HqunH7.js";import{u as y}from"./query-C99w429o.js";import{d as w}from"./vendor-CMMjVdZs.js";import{G as N,q as b,d as v,r as k,j as _}from"./lucide-53bR2rki.js";import{f as n}from"./date-fns-CZ_bHujz.js";const H={bmad:["analyze","design","implement","test","review"],harness:["reproduce","safety-net","root-cause","fix","verify"]};async function S(a){const t=await fetch(`/api/workflows/${encodeURIComponent(a)}`);if(!t.ok)throw new Error(`Failed: ${t.status}`);return t.json()}function F(){const{routeRequestId:a}=j(),{data:t,isLoading:d,error:o}=y({queryKey:["workflow-detail",a],queryFn:()=>S(a),enabled:!!a,refetchInterval:5e3});if(d)return e.jsxs("div",{children:[e.jsx(c,{}),e.jsx("div",{className:"bg-white rounded-lg shadow p-6",children:e.jsx("p",{className:"text-gray-600",children:"加载中..."})})]});if(o||!t)return e.jsxs("div",{children:[e.jsx(c,{}),e.jsx("div",{className:"bg-white rounded-lg shadow p-6",children:e.jsx("p",{className:"text-red-600",children:"加载失败"})})]});const r=Array.from(new Set(t.invocations.filter(s=>s.phase!=null&&s.success).map(s=>s.phase))),l=t.workflow?H[t.workflow]??r:r,m=new Set(r),h=l.length>0?r.length/l.length*100:0,p=t.workflow==="bmad",g=t.workflow==="harness",f=p?"bg-blue-100 text-blue-800":g?"bg-orange-100 text-orange-800":"bg-gray-100 text-gray-700";return e.jsxs("div",{children:[e.jsx(c,{}),e.jsxs("div",{className:"bg-white rounded-lg shadow p-6 mb-4",children:[e.jsxs("div",{className:"flex items-center gap-3 mb-3 flex-wrap",children:[e.jsx(N,{className:"h-5 w-5 text-gray-400"}),e.jsx("h1",{className:"text-xl font-bold text-gray-900",children:"工作流详情"}),t.workflow&&e.jsx("span",{className:`px-2 py-1 rounded text-xs font-mono font-semibold ${f}`,children:t.workflow.toUpperCase()}),t.feature_slug&&e.jsx("span",{className:"text-sm text-gray-700 font-medium",children:t.feature_slug})]}),e.jsxs("p",{className:"text-xs text-gray-500 font-mono mb-4 break-all",children:["route_request_id: ",t.route_request_id]}),e.jsxs("div",{className:"grid grid-cols-2 md:grid-cols-4 gap-4 mb-4",children:[e.jsxs("div",{children:[e.jsx("div",{className:"text-xs text-gray-500",children:"调用次数"}),e.jsx("div",{className:"text-lg font-semibold",children:t.invocations.length})]}),e.jsxs("div",{children:[e.jsx("div",{className:"text-xs text-gray-500",children:"已完成 Phase"}),e.jsxs("div",{className:"text-lg font-semibold",children:[r.length," / ",l.length]})]}),e.jsxs("div",{children:[e.jsx("div",{className:"text-xs text-gray-500",children:"开始时间"}),e.jsx("div",{className:"text-sm",children:n(new Date(t.first_at),"MM-dd HH:mm:ss")})]}),e.jsxs("div",{children:[e.jsx("div",{className:"text-xs text-gray-500",children:"最后更新"}),e.jsx("div",{className:"text-sm",children:n(new Date(t.last_at),"MM-dd HH:mm:ss")})]})]}),e.jsx("div",{className:"w-full bg-gray-200 rounded-full h-2 mb-3 overflow-hidden",children:e.jsx("div",{className:"bg-green-500 h-2 rounded-full transition-all duration-300",style:{width:`${h}%`}})}),e.jsx("div",{className:"flex flex-wrap gap-x-3 gap-y-2",children:l.map((s,x)=>{const i=m.has(s);return e.jsxs("div",{className:"flex items-center gap-1.5",children:[e.jsx("span",{className:`w-6 h-6 rounded-full flex items-center justify-center text-xs font-medium ${i?"bg-green-500 text-white":"bg-gray-200 text-gray-500"}`,children:i?"✓":x+1}),e.jsx("span",{className:`text-sm ${i?"text-gray-900":"text-gray-400"}`,children:s})]},s)})})]}),e.jsxs("div",{className:"bg-white rounded-lg shadow overflow-hidden",children:[e.jsxs("div",{className:"px-6 py-4 border-b border-gray-200",children:[e.jsx("h2",{className:"text-base font-semibold text-gray-900",children:"调用流水"}),e.jsx("p",{className:"text-xs text-gray-500 mt-1",children:"按时间正序排列"})]}),e.jsx("div",{className:"overflow-x-auto",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-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider",children:"#"}),e.jsx("th",{className:"px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider",children:"Phase"}),e.jsx("th",{className:"px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider",children:"Skill"}),e.jsx("th",{className:"px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider",children:"时间"}),e.jsx("th",{className:"px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider",children:"状态"}),e.jsx("th",{className:"px-4 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:[t.invocations.map((s,x)=>e.jsxs("tr",{className:"hover:bg-gray-50",children:[e.jsx("td",{className:"px-4 py-3 text-sm text-gray-500 font-mono",children:x+1}),e.jsx("td",{className:"px-4 py-3",children:s.phase?e.jsx("span",{className:"text-sm font-mono text-gray-900",children:s.phase}):e.jsx("span",{className:"text-xs text-gray-400",children:"—"})}),e.jsxs("td",{className:"px-4 py-3",children:[e.jsx("div",{className:"text-sm font-mono text-indigo-600",children:s.skill_id}),s.reason&&e.jsx("div",{className:"text-xs text-gray-500 mt-0.5 max-w-md truncate",children:s.reason})]}),e.jsx("td",{className:"px-4 py-3 text-sm text-gray-500 whitespace-nowrap",children:n(new Date(s.timestamp),"HH:mm:ss")}),e.jsx("td",{className:"px-4 py-3",children:s.success?e.jsxs("span",{className:"inline-flex items-center gap-1 text-xs text-green-700",children:[e.jsx(b,{className:"h-3.5 w-3.5"}),"成功"]}):e.jsxs("span",{className:w("inline-flex items-center gap-1 text-xs text-red-700",s.error&&"cursor-help"),title:s.error??void 0,children:[e.jsx(v,{className:"h-3.5 w-3.5"}),"失败"]})}),e.jsx("td",{className:"px-4 py-3",children:s.artifact_path?e.jsxs("a",{href:`file://${s.artifact_path}`,className:"inline-flex items-center gap-1 text-xs text-blue-600 hover:underline max-w-xs truncate",title:s.artifact_path,children:[e.jsx(k,{className:"h-3.5 w-3.5 flex-shrink-0"}),e.jsx("span",{className:"truncate",children:s.artifact_path.split("/").pop()})]}):e.jsx("span",{className:"text-xs text-gray-400",children:"—"})})]},s.id)),t.invocations.length===0&&e.jsx("tr",{children:e.jsx("td",{colSpan:6,className:"px-4 py-12 text-center text-gray-500 text-sm",children:"暂无调用记录"})})]})]})})]})]})}function c(){return e.jsxs(u,{to:"/workflows",className:"inline-flex items-center text-sm text-gray-500 hover:text-gray-700 mb-4",children:[e.jsx(_,{className:"h-4 w-4 mr-1"}),"返回工作流列表"]})}export{F as default};
|
|
2
|
-
//# sourceMappingURL=WorkflowDetail-zhNqUkBE.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"WorkflowDetail-zhNqUkBE.js","sources":["../../src/pages/WorkflowDetail.tsx"],"sourcesContent":["import { useParams, Link } from 'react-router-dom'\nimport { useQuery } from '@tanstack/react-query'\nimport { format } from 'date-fns'\nimport { ArrowLeft, CheckCircle2, XCircle, FileText, GitBranch } from 'lucide-react'\nimport clsx from 'clsx'\n\ninterface Invocation {\n id: string\n skill_id: string\n phase: string | null\n workflow: string | null\n feature_slug: string | null\n reason: string | null\n invocation_type: 'static' | 'dynamic' | 'slash_command'\n success: boolean\n error: string | null\n timestamp: number\n artifact_path: string | null\n}\n\ninterface WorkflowDetailData {\n route_request_id: string\n workflow: string | null\n feature_slug: string | null\n session_id: string\n agent_id: string | null\n first_at: number\n last_at: number\n invocations: Invocation[]\n}\n\nconst WORKFLOW_PHASES: Record<string, string[]> = {\n bmad: ['analyze', 'design', 'implement', 'test', 'review'],\n harness: ['reproduce', 'safety-net', 'root-cause', 'fix', 'verify'],\n}\n\nasync function fetchDetail(routeRequestId: string): Promise<WorkflowDetailData> {\n const res = await fetch(`/api/workflows/${encodeURIComponent(routeRequestId)}`)\n if (!res.ok) throw new Error(`Failed: ${res.status}`)\n return res.json()\n}\n\nexport default function WorkflowDetail() {\n const { routeRequestId } = useParams<{ routeRequestId: string }>()\n const { data, isLoading, error } = useQuery({\n queryKey: ['workflow-detail', routeRequestId],\n queryFn: () => fetchDetail(routeRequestId!),\n enabled: !!routeRequestId,\n refetchInterval: 5000,\n })\n\n if (isLoading) {\n return (\n <div>\n <BackLink />\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 || !data) {\n return (\n <div>\n <BackLink />\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 const completedPhases = Array.from(\n new Set(\n data.invocations\n .filter(inv => inv.phase != null && inv.success)\n .map(inv => inv.phase as string),\n ),\n )\n const allPhases = data.workflow ? WORKFLOW_PHASES[data.workflow] ?? completedPhases : completedPhases\n const completedSet = new Set(completedPhases)\n const progress = allPhases.length > 0 ? (completedPhases.length / allPhases.length) * 100 : 0\n\n const isBmad = data.workflow === 'bmad'\n const isHarness = data.workflow === 'harness'\n const badgeClass = isBmad\n ? 'bg-blue-100 text-blue-800'\n : isHarness\n ? 'bg-orange-100 text-orange-800'\n : 'bg-gray-100 text-gray-700'\n\n return (\n <div>\n <BackLink />\n\n {/* 头部信息卡 */}\n <div className=\"bg-white rounded-lg shadow p-6 mb-4\">\n <div className=\"flex items-center gap-3 mb-3 flex-wrap\">\n <GitBranch className=\"h-5 w-5 text-gray-400\" />\n <h1 className=\"text-xl font-bold text-gray-900\">工作流详情</h1>\n {data.workflow && (\n <span className={`px-2 py-1 rounded text-xs font-mono font-semibold ${badgeClass}`}>\n {data.workflow.toUpperCase()}\n </span>\n )}\n {data.feature_slug && (\n <span className=\"text-sm text-gray-700 font-medium\">{data.feature_slug}</span>\n )}\n </div>\n <p className=\"text-xs text-gray-500 font-mono mb-4 break-all\">\n route_request_id: {data.route_request_id}\n </p>\n\n <div className=\"grid grid-cols-2 md:grid-cols-4 gap-4 mb-4\">\n <div>\n <div className=\"text-xs text-gray-500\">调用次数</div>\n <div className=\"text-lg font-semibold\">{data.invocations.length}</div>\n </div>\n <div>\n <div className=\"text-xs text-gray-500\">已完成 Phase</div>\n <div className=\"text-lg font-semibold\">\n {completedPhases.length} / {allPhases.length}\n </div>\n </div>\n <div>\n <div className=\"text-xs text-gray-500\">开始时间</div>\n <div className=\"text-sm\">{format(new Date(data.first_at), 'MM-dd HH:mm:ss')}</div>\n </div>\n <div>\n <div className=\"text-xs text-gray-500\">最后更新</div>\n <div className=\"text-sm\">{format(new Date(data.last_at), 'MM-dd HH:mm:ss')}</div>\n </div>\n </div>\n\n {/* 进度条 */}\n <div className=\"w-full bg-gray-200 rounded-full h-2 mb-3 overflow-hidden\">\n <div\n className=\"bg-green-500 h-2 rounded-full transition-all duration-300\"\n style={{ width: `${progress}%` }}\n />\n </div>\n\n {/* Phase 时间线 */}\n <div className=\"flex flex-wrap gap-x-3 gap-y-2\">\n {allPhases.map((phase, idx) => {\n const completed = completedSet.has(phase)\n return (\n <div key={phase} className=\"flex items-center gap-1.5\">\n <span\n className={`w-6 h-6 rounded-full flex items-center justify-center text-xs font-medium ${\n completed ? 'bg-green-500 text-white' : 'bg-gray-200 text-gray-500'\n }`}\n >\n {completed ? '✓' : idx + 1}\n </span>\n <span className={`text-sm ${completed ? 'text-gray-900' : 'text-gray-400'}`}>\n {phase}\n </span>\n </div>\n )\n })}\n </div>\n </div>\n\n {/* 调用流水表 */}\n <div className=\"bg-white rounded-lg shadow overflow-hidden\">\n <div className=\"px-6 py-4 border-b border-gray-200\">\n <h2 className=\"text-base font-semibold text-gray-900\">调用流水</h2>\n <p className=\"text-xs text-gray-500 mt-1\">按时间正序排列</p>\n </div>\n <div className=\"overflow-x-auto\">\n <table className=\"min-w-full divide-y divide-gray-200\">\n <thead className=\"bg-gray-50\">\n <tr>\n <th className=\"px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider\">\n #\n </th>\n <th className=\"px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider\">\n Phase\n </th>\n <th className=\"px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider\">\n Skill\n </th>\n <th className=\"px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider\">\n 时间\n </th>\n <th className=\"px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider\">\n 状态\n </th>\n <th className=\"px-4 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 {data.invocations.map((inv, idx) => (\n <tr key={inv.id} className=\"hover:bg-gray-50\">\n <td className=\"px-4 py-3 text-sm text-gray-500 font-mono\">{idx + 1}</td>\n <td className=\"px-4 py-3\">\n {inv.phase ? (\n <span className=\"text-sm font-mono text-gray-900\">{inv.phase}</span>\n ) : (\n <span className=\"text-xs text-gray-400\">—</span>\n )}\n </td>\n <td className=\"px-4 py-3\">\n <div className=\"text-sm font-mono text-indigo-600\">{inv.skill_id}</div>\n {inv.reason && (\n <div className=\"text-xs text-gray-500 mt-0.5 max-w-md truncate\">\n {inv.reason}\n </div>\n )}\n </td>\n <td className=\"px-4 py-3 text-sm text-gray-500 whitespace-nowrap\">\n {format(new Date(inv.timestamp), 'HH:mm:ss')}\n </td>\n <td className=\"px-4 py-3\">\n {inv.success ? (\n <span className=\"inline-flex items-center gap-1 text-xs text-green-700\">\n <CheckCircle2 className=\"h-3.5 w-3.5\" />\n 成功\n </span>\n ) : (\n <span\n className={clsx(\n 'inline-flex items-center gap-1 text-xs text-red-700',\n inv.error && 'cursor-help',\n )}\n title={inv.error ?? undefined}\n >\n <XCircle className=\"h-3.5 w-3.5\" />\n 失败\n </span>\n )}\n </td>\n <td className=\"px-4 py-3\">\n {inv.artifact_path ? (\n <a\n href={`file://${inv.artifact_path}`}\n className=\"inline-flex items-center gap-1 text-xs text-blue-600 hover:underline max-w-xs truncate\"\n title={inv.artifact_path}\n >\n <FileText className=\"h-3.5 w-3.5 flex-shrink-0\" />\n <span className=\"truncate\">{inv.artifact_path.split('/').pop()}</span>\n </a>\n ) : (\n <span className=\"text-xs text-gray-400\">—</span>\n )}\n </td>\n </tr>\n ))}\n {data.invocations.length === 0 && (\n <tr>\n <td colSpan={6} className=\"px-4 py-12 text-center text-gray-500 text-sm\">\n 暂无调用记录\n </td>\n </tr>\n )}\n </tbody>\n </table>\n </div>\n </div>\n </div>\n )\n}\n\nfunction BackLink() {\n return (\n <Link\n to=\"/workflows\"\n className=\"inline-flex items-center text-sm text-gray-500 hover:text-gray-700 mb-4\"\n >\n <ArrowLeft className=\"h-4 w-4 mr-1\" />\n 返回工作流列表\n </Link>\n )\n}\n"],"names":["WORKFLOW_PHASES","fetchDetail","routeRequestId","res","WorkflowDetail","useParams","data","isLoading","error","useQuery","jsx","BackLink","completedPhases","inv","allPhases","completedSet","progress","isBmad","isHarness","badgeClass","jsxs","GitBranch","format","phase","idx","completed","CheckCircle2","clsx","XCircle","FileText","Link","ArrowLeft"],"mappings":"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"}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{j as e}from"./react-vendor-CSp-GLFF.js";import{u as o}from"./query-C99w429o.js";import{L as m}from"./react-router-I-HqunH7.js";import{G as h,g}from"./lucide-53bR2rki.js";import{a as p,z as u}from"./date-fns-CZ_bHujz.js";import"./vendor-CMMjVdZs.js";const f={bmad:["analyze","design","implement","test","review"],harness:["reproduce","safety-net","root-cause","fix","verify"]};async function j(){const s=await fetch("/api/workflows");if(!s.ok)throw new Error("Failed to fetch workflows");return s.json()}function q(){const{data:s,isLoading:t,error:a}=o({queryKey:["workflows"],queryFn:j,refetchInterval:5e3});return t?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:"加载中..."})})]}):a?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:["加载失败: ",a.message]})})]}):s?e.jsxs("div",{children:[e.jsx("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("p",{className:"text-sm text-gray-500 mb-4",children:["共 ",s.total," 个 BMAD / Harness 工作流(每 5 秒自动刷新)"]}),s.items.length===0?e.jsxs("div",{className:"bg-white rounded-lg shadow p-12 text-center",children:[e.jsx(h,{className:"h-10 w-10 text-gray-300 mx-auto mb-3"}),e.jsx("p",{className:"text-gray-500 text-sm",children:"暂无工作流记录"}),e.jsx("p",{className:"text-gray-400 text-xs mt-2",children:"触发 BMAD / Harness 工作流后,进度将自动显示在这里"})]}):e.jsx("div",{className:"space-y-4",children:s.items.map(r=>e.jsx(y,{workflow:r},r.route_request_id))})]}):null}function y({workflow:s}){const t=f[s.workflow]??s.phases_completed,a=new Set(s.phases_completed),r=t.length>0?s.phases_completed.length/t.length*100:0,i=s.workflow==="bmad",c=s.workflow==="harness",d=i?"bg-blue-100 text-blue-800":c?"bg-orange-100 text-orange-800":"bg-gray-100 text-gray-700";return e.jsxs("div",{className:"border border-gray-200 rounded-lg p-4 bg-white shadow-sm hover:shadow-md transition-shadow",children:[e.jsxs("div",{className:"flex justify-between items-start mb-3",children:[e.jsxs("div",{className:"flex items-center gap-2 flex-wrap",children:[e.jsx("span",{className:`px-2 py-1 rounded text-xs font-mono font-semibold ${d}`,children:s.workflow.toUpperCase()}),s.feature_slug&&e.jsx("span",{className:"text-sm text-gray-700 font-medium",children:s.feature_slug}),e.jsxs("span",{className:"text-xs text-gray-400 font-mono",children:[s.route_request_id.slice(0,12),"..."]})]}),e.jsxs("div",{className:"flex items-center gap-1 text-xs text-gray-500",children:[e.jsx(g,{className:"h-3 w-3"}),s.last_at?p(new Date(s.last_at),{addSuffix:!0,locale:u}):"-"]})]}),e.jsx("div",{className:"w-full bg-gray-200 rounded-full h-2 mb-2 overflow-hidden",children:e.jsx("div",{className:"bg-green-500 h-2 rounded-full transition-all duration-300",style:{width:`${r}%`}})}),e.jsxs("div",{className:"text-xs text-gray-500 mb-3 flex items-center gap-3",children:[e.jsxs("span",{children:[s.phases_completed.length," / ",t.length," phases"]}),e.jsx("span",{className:"text-gray-300",children:"·"}),e.jsxs("span",{children:["调用 ",e.jsx("span",{className:"text-green-600 font-medium",children:s.success_count}),e.jsxs("span",{className:"text-gray-400",children:[" / ",s.total_invocations]})," 成功"]})]}),e.jsx("div",{className:"flex flex-wrap gap-x-3 gap-y-2 mb-3",children:t.map((n,x)=>{const l=a.has(n);return e.jsxs("div",{className:"flex items-center gap-1.5",children:[e.jsx("span",{className:`w-6 h-6 rounded-full flex items-center justify-center text-xs font-medium ${l?"bg-green-500 text-white":"bg-gray-200 text-gray-500"}`,children:l?"✓":x+1}),e.jsx("span",{className:`text-sm ${l?"text-gray-900":"text-gray-400"}`,children:n})]},n)})}),e.jsx(m,{to:`/workflows/${encodeURIComponent(s.route_request_id)}`,className:"text-blue-600 text-sm hover:underline inline-block",children:"查看详情 →"})]})}export{q as default};
|
|
2
|
-
//# sourceMappingURL=Workflows-Btvi-lGw.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Workflows-Btvi-lGw.js","sources":["../../src/pages/Workflows.tsx"],"sourcesContent":["import { useQuery } from '@tanstack/react-query'\nimport { Link } from 'react-router-dom'\nimport { GitBranch, Clock } from 'lucide-react'\nimport { formatDistanceToNow } from 'date-fns'\nimport { zhCN } from 'date-fns/locale'\n\ninterface WorkflowProgress {\n route_request_id: string\n workflow: string\n phases_completed: string[]\n feature_slug: string | null\n total_invocations: number\n success_count: number\n first_at: number\n last_at: number\n}\n\ninterface WorkflowsResponse {\n total: number\n items: WorkflowProgress[]\n}\n\n/**\n * BMAD / Harness 等内置工作流的 phase 顺序定义。用于在卡片上画完整的进度条 —\n * 已完成的 phase 标记为绿色实心圆,未完成的 phase 留灰色。\n *\n * 与后端 routing/skill 注册保持一致;如果遇到这里没有列出的 workflow(自定义工作流),\n * 渲染时退化为只展示 phases_completed 本身,不画 placeholder。\n */\nconst WORKFLOW_PHASES: Record<string, string[]> = {\n bmad: ['analyze', 'design', 'implement', 'test', 'review'],\n harness: ['reproduce', 'safety-net', 'root-cause', 'fix', 'verify'],\n}\n\nasync function fetchWorkflows(): Promise<WorkflowsResponse> {\n const res = await fetch('/api/workflows')\n if (!res.ok) throw new Error('Failed to fetch workflows')\n return res.json()\n}\n\nexport default function Workflows() {\n const { data, isLoading, error } = useQuery({\n queryKey: ['workflows'],\n queryFn: fetchWorkflows,\n refetchInterval: 5000, // 5s 轮询,便于实时观察 phase 推进\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 if (!data) return null\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>\n\n <p className=\"text-sm text-gray-500 mb-4\">\n 共 {data.total} 个 BMAD / Harness 工作流(每 5 秒自动刷新)\n </p>\n\n {data.items.length === 0 ? (\n <div className=\"bg-white rounded-lg shadow p-12 text-center\">\n <GitBranch className=\"h-10 w-10 text-gray-300 mx-auto mb-3\" />\n <p className=\"text-gray-500 text-sm\">暂无工作流记录</p>\n <p className=\"text-gray-400 text-xs mt-2\">\n 触发 BMAD / Harness 工作流后,进度将自动显示在这里\n </p>\n </div>\n ) : (\n <div className=\"space-y-4\">\n {data.items.map(wf => (\n <WorkflowCard key={wf.route_request_id} workflow={wf} />\n ))}\n </div>\n )}\n </div>\n )\n}\n\nfunction WorkflowCard({ workflow }: { workflow: WorkflowProgress }) {\n const allPhases = WORKFLOW_PHASES[workflow.workflow] ?? workflow.phases_completed\n const completedSet = new Set(workflow.phases_completed)\n const progress = allPhases.length > 0\n ? (workflow.phases_completed.length / allPhases.length) * 100\n : 0\n\n const isBmad = workflow.workflow === 'bmad'\n const isHarness = workflow.workflow === 'harness'\n const badgeClass = isBmad\n ? 'bg-blue-100 text-blue-800'\n : isHarness\n ? 'bg-orange-100 text-orange-800'\n : 'bg-gray-100 text-gray-700'\n\n return (\n <div className=\"border border-gray-200 rounded-lg p-4 bg-white shadow-sm hover:shadow-md transition-shadow\">\n <div className=\"flex justify-between items-start mb-3\">\n <div className=\"flex items-center gap-2 flex-wrap\">\n <span className={`px-2 py-1 rounded text-xs font-mono font-semibold ${badgeClass}`}>\n {workflow.workflow.toUpperCase()}\n </span>\n {workflow.feature_slug && (\n <span className=\"text-sm text-gray-700 font-medium\">{workflow.feature_slug}</span>\n )}\n <span className=\"text-xs text-gray-400 font-mono\">\n {workflow.route_request_id.slice(0, 12)}...\n </span>\n </div>\n <div className=\"flex items-center gap-1 text-xs text-gray-500\">\n <Clock className=\"h-3 w-3\" />\n {workflow.last_at\n ? formatDistanceToNow(new Date(workflow.last_at), { addSuffix: true, locale: zhCN })\n : '-'}\n </div>\n </div>\n\n {/* 进度条 */}\n <div className=\"w-full bg-gray-200 rounded-full h-2 mb-2 overflow-hidden\">\n <div\n className=\"bg-green-500 h-2 rounded-full transition-all duration-300\"\n style={{ width: `${progress}%` }}\n />\n </div>\n <div className=\"text-xs text-gray-500 mb-3 flex items-center gap-3\">\n <span>\n {workflow.phases_completed.length} / {allPhases.length} phases\n </span>\n <span className=\"text-gray-300\">·</span>\n <span>\n 调用 <span className=\"text-green-600 font-medium\">{workflow.success_count}</span>\n <span className=\"text-gray-400\"> / {workflow.total_invocations}</span> 成功\n </span>\n </div>\n\n {/* Phase 列表 */}\n <div className=\"flex flex-wrap gap-x-3 gap-y-2 mb-3\">\n {allPhases.map((phase, idx) => {\n const completed = completedSet.has(phase)\n return (\n <div key={phase} className=\"flex items-center gap-1.5\">\n <span\n className={`w-6 h-6 rounded-full flex items-center justify-center text-xs font-medium ${\n completed\n ? 'bg-green-500 text-white'\n : 'bg-gray-200 text-gray-500'\n }`}\n >\n {completed ? '✓' : idx + 1}\n </span>\n <span className={`text-sm ${completed ? 'text-gray-900' : 'text-gray-400'}`}>\n {phase}\n </span>\n </div>\n )\n })}\n </div>\n\n <Link\n to={`/workflows/${encodeURIComponent(workflow.route_request_id)}`}\n className=\"text-blue-600 text-sm hover:underline inline-block\"\n >\n 查看详情 →\n </Link>\n </div>\n )\n}\n"],"names":["WORKFLOW_PHASES","fetchWorkflows","res","Workflows","data","isLoading","error","useQuery","jsx","jsxs","GitBranch","wf","WorkflowCard","workflow","allPhases","completedSet","progress","isBmad","isHarness","badgeClass","Clock","formatDistanceToNow","zhCN","phase","idx","completed","Link"],"mappings":"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"}
|
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
import{j as r}from"./react-vendor-CSp-GLFF.js";import{S as l,X as d}from"./lucide-53bR2rki.js";function m({value:e,onChange:t,placeholder:n,className:o=""}){return r.jsxs("div",{className:`relative ${o}`,children:[r.jsx(l,{className:"absolute left-2.5 top-1/2 -translate-y-1/2 h-4 w-4 text-gray-400"}),r.jsx("input",{type:"text",value:e,onChange:s=>t(s.target.value),placeholder:n||"搜索...",className:"w-full pl-8 pr-8 py-1.5 text-sm border border-gray-300 rounded-md bg-white focus:border-indigo-500 focus:outline-none focus:ring-1 focus:ring-indigo-500"}),e&&r.jsx("button",{onClick:()=>t(""),className:"absolute right-2 top-1/2 -translate-y-1/2 text-gray-400 hover:text-gray-600",children:r.jsx(d,{className:"h-4 w-4"})})]})}function u(e,t){const n=JSON.stringify(t,null,2),o=new Blob([n],{type:"application/json"});c(e,o)}function b(e,t){if(!t||t.length===0){u(e.replace(/\.csv$/,".json"),t);return}const n=Object.keys(t[0]),o=[n.join(","),...t.map(a=>n.map(i=>p(a[i])).join(","))].join(`
|
|
2
|
-
`),s=new Blob(["\uFEFF"+o],{type:"text/csv;charset=utf-8"});c(e,s)}function p(e){if(e==null)return"";const t=typeof e=="object"?JSON.stringify(e):String(e);return t.includes(",")||t.includes('"')||t.includes(`
|
|
3
|
-
`)?`"${t.replace(/"/g,'""')}"`:t}function c(e,t){const n=URL.createObjectURL(t),o=document.createElement("a");o.href=n,o.download=e,document.body.appendChild(o),o.click(),document.body.removeChild(o),URL.revokeObjectURL(n)}function h(){const e=new Date,t=n=>String(n).padStart(2,"0");return`${e.getFullYear()}${t(e.getMonth()+1)}${t(e.getDate())}-${t(e.getHours())}${t(e.getMinutes())}${t(e.getSeconds())}`}export{m as S,b as a,u as d,h as g};
|
|
4
|
-
//# sourceMappingURL=export-BQQZLaHV.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"export-BQQZLaHV.js","sources":["../../src/components/SearchInput.tsx","../../src/utils/export.ts"],"sourcesContent":["import { Search, X } from 'lucide-react'\n\ninterface Props {\n value: string\n onChange: (value: string) => void\n placeholder?: string\n className?: string\n}\n\nexport default function SearchInput({ value, onChange, placeholder, className = '' }: Props) {\n return (\n <div className={`relative ${className}`}>\n <Search className=\"absolute left-2.5 top-1/2 -translate-y-1/2 h-4 w-4 text-gray-400\" />\n <input\n type=\"text\"\n value={value}\n onChange={(e) => onChange(e.target.value)}\n placeholder={placeholder || '搜索...'}\n className=\"w-full pl-8 pr-8 py-1.5 text-sm border border-gray-300 rounded-md bg-white focus:border-indigo-500 focus:outline-none focus:ring-1 focus:ring-indigo-500\"\n />\n {value && (\n <button\n onClick={() => onChange('')}\n className=\"absolute right-2 top-1/2 -translate-y-1/2 text-gray-400 hover:text-gray-600\"\n >\n <X className=\"h-4 w-4\" />\n </button>\n )}\n </div>\n )\n}\n","/**\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":["SearchInput","value","onChange","placeholder","className","jsxs","jsx","Search","e","X","downloadJSON","filename","data","content","blob","triggerDownload","downloadCSV","rows","headers","csv","row","h","escapeCSV","str","url","a","getTimestamp","now","pad"],"mappings":"+FASA,SAAwBA,EAAY,CAAE,MAAAC,EAAO,SAAAC,EAAU,YAAAC,EAAa,UAAAC,EAAY,IAAa,CAC3F,OACEC,EAAAA,KAAC,MAAA,CAAI,UAAW,YAAYD,CAAS,GACnC,SAAA,CAAAE,EAAAA,IAACC,EAAA,CAAO,UAAU,kEAAA,CAAmE,EACrFD,EAAAA,IAAC,QAAA,CACC,KAAK,OACL,MAAAL,EACA,SAAWO,GAAMN,EAASM,EAAE,OAAO,KAAK,EACxC,YAAaL,GAAe,QAC5B,UAAU,0JAAA,CAAA,EAEXF,GACCK,EAAAA,IAAC,SAAA,CACC,QAAS,IAAMJ,EAAS,EAAE,EAC1B,UAAU,8EAEV,SAAAI,EAAAA,IAACG,EAAA,CAAE,UAAU,SAAA,CAAU,CAAA,CAAA,CACzB,EAEJ,CAEJ,CC1BO,SAASC,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,EAAUrB,EAAwB,CACzC,GAAIA,GAAU,KAA6B,MAAO,GAClD,MAAMsB,EAAM,OAAOtB,GAAU,SAAW,KAAK,UAAUA,CAAK,EAAI,OAAOA,CAAK,EAC5E,OAAIsB,EAAI,SAAS,GAAG,GAAKA,EAAI,SAAS,GAAG,GAAKA,EAAI,SAAS;AAAA,CAAI,EACtD,IAAIA,EAAI,QAAQ,KAAM,IAAI,CAAC,IAE7BA,CACT,CAEA,SAASR,EAAgBJ,EAAkBG,EAAkB,CAC3D,MAAMU,EAAM,IAAI,gBAAgBV,CAAI,EAC9BW,EAAI,SAAS,cAAc,GAAG,EACpCA,EAAE,KAAOD,EACTC,EAAE,SAAWd,EACb,SAAS,KAAK,YAAYc,CAAC,EAC3BA,EAAE,MAAA,EACF,SAAS,KAAK,YAAYA,CAAC,EAC3B,IAAI,gBAAgBD,CAAG,CACzB,CAEO,SAASE,GAAuB,CACrC,MAAMC,MAAU,KACVC,EAAO,GAAc,OAAO,CAAC,EAAE,SAAS,EAAG,GAAG,EACpD,MAAO,GAAGD,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"}
|
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/Dashboard-Cy1xsj1J.js","assets/react-vendor-CSp-GLFF.js","assets/query-C99w429o.js","assets/react-router-I-HqunH7.js","assets/vendor-CMMjVdZs.js","assets/lucide-53bR2rki.js","assets/charts-CLrM0_uM.js","assets/Sessions-C6J_HQ_u.js","assets/Drawer-DcU3ln98.js","assets/date-fns-CZ_bHujz.js","assets/export-BQQZLaHV.js","assets/syntax-highlighter-44FakypI.js","assets/SessionDetail-BT0l4RrK.js","assets/Events-mFhXl4zI.js","assets/CodeBlock--H53gk46.js","assets/ExecutionTrace-DG901hLR.js","assets/Agents-Beg34V1g.js","assets/MarkdownRenderer-CCIz1MOz.js","assets/auth-Bnf8ZcqN.js","assets/Skills-4DQWLaTv.js","assets/Routing-B7BFLfjh.js","assets/AIConfig-R5wZ3ZKT.js","assets/Workflows-Btvi-lGw.js","assets/WorkflowDetail-zhNqUkBE.js"])))=>i.map(i=>d[i]);
|
|
2
|
-
import{r as s,j as e,e as b,d as y}from"./react-vendor-CSp-GLFF.js";import{u as v,O as w,L as N,R as _,a as c,N as C,B as k}from"./react-router-I-HqunH7.js";import{Q as E,a as T}from"./query-C99w429o.js";import{_ as x}from"./syntax-highlighter-44FakypI.js";import{d as h}from"./vendor-CMMjVdZs.js";import{X as p,M as O,L as P,a as A,A as S,T as L,G as I,B as R,b as z,N as D,C as V,I as F,c as B,d as q,e as M,f as W}from"./lucide-53bR2rki.js";(function(){const a=document.createElement("link").relList;if(a&&a.supports&&a.supports("modulepreload"))return;for(const r of document.querySelectorAll('link[rel="modulepreload"]'))o(r);new MutationObserver(r=>{for(const n of r)if(n.type==="childList")for(const t of n.addedNodes)t.tagName==="LINK"&&t.rel==="modulepreload"&&o(t)}).observe(document,{childList:!0,subtree:!0});function l(r){const n={};return r.integrity&&(n.integrity=r.integrity),r.referrerPolicy&&(n.referrerPolicy=r.referrerPolicy),r.crossOrigin==="use-credentials"?n.credentials="include":r.crossOrigin==="anonymous"?n.credentials="omit":n.credentials="same-origin",n}function o(r){if(r.ep)return;r.ep=!0;const n=l(r);fetch(r.href,n)}})();const Q=[{title:"总览",items:[{name:"仪表盘",href:"/dashboard",icon:P}]},{title:"活动",items:[{name:"会话",href:"/sessions",icon:A},{name:"事件",href:"/events",icon:S},{name:"执行追踪",href:"/execution-trace",icon:L},{name:"工作流进度",href:"/workflows",icon:I}]},{title:"配置",items:[{name:"Agent 管理",href:"/agents",icon:R},{name:"Skill 管理",href:"/skills",icon:z},{name:"Agent 路由",href:"/routing",icon:D},{name:"AI 配置",href:"/ai-config",icon:V}]}];function G(){const i=v(),[a,l]=s.useState(!1),o=r=>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(t=>{const u=t.icon,m=i.pathname===t.href||i.pathname.startsWith(t.href+"/");return e.jsxs(N,{to:t.href,onClick:r,className:h("group flex items-center px-3 py-2 text-sm font-medium rounded-md mb-0.5",m?"bg-indigo-50 text-indigo-600":"text-gray-700 hover:bg-gray-50"),children:[e.jsx(u,{className:h("mr-3 h-4 w-4",m?"text-indigo-600":"text-gray-400")}),t.name]},t.name)})]},n.title))});return e.jsxs("div",{className:"min-h-screen bg-gray-50",children:[e.jsxs("div",{className:h("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(w,{})})})]})]})}const X=s.lazy(()=>x(()=>import("./Dashboard-Cy1xsj1J.js"),__vite__mapDeps([0,1,2,3,4,5,6]))),$=s.lazy(()=>x(()=>import("./Sessions-C6J_HQ_u.js"),__vite__mapDeps([7,1,2,8,4,5,9,10,3,11]))),K=s.lazy(()=>x(()=>import("./SessionDetail-BT0l4RrK.js"),__vite__mapDeps([12,1,3,4,2,5,9]))),U=s.lazy(()=>x(()=>import("./Events-mFhXl4zI.js"),__vite__mapDeps([13,1,2,4,8,5,14,11,10,9,3]))),H=s.lazy(()=>x(()=>import("./ExecutionTrace-DG901hLR.js"),__vite__mapDeps([15,1,2,4,8,5,14,11,10,9,3]))),J=s.lazy(()=>x(()=>import("./Agents-Beg34V1g.js"),__vite__mapDeps([16,1,2,8,4,5,17,11,18,3]))),Y=s.lazy(()=>x(()=>import("./Skills-4DQWLaTv.js"),__vite__mapDeps([19,1,2,8,4,5,17,11,18,3]))),Z=s.lazy(()=>x(()=>import("./Routing-B7BFLfjh.js"),__vite__mapDeps([20,1,2,3,4,5]))),ee=s.lazy(()=>x(()=>import("./AIConfig-R5wZ3ZKT.js"),__vite__mapDeps([21,1,2,18,5,3,4,11]))),se=s.lazy(()=>x(()=>import("./Workflows-Btvi-lGw.js"),__vite__mapDeps([22,1,2,3,4,5,9]))),te=s.lazy(()=>x(()=>import("./WorkflowDetail-zhNqUkBE.js"),__vite__mapDeps([23,1,3,4,2,5,9])));function d(){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 re(){return e.jsx(_,{children:e.jsxs(c,{path:"/",element:e.jsx(G,{}),children:[e.jsx(c,{index:!0,element:e.jsx(C,{to:"/dashboard",replace:!0})}),e.jsx(c,{path:"dashboard",element:e.jsx(s.Suspense,{fallback:e.jsx(d,{}),children:e.jsx(X,{})})}),e.jsx(c,{path:"sessions",element:e.jsx(s.Suspense,{fallback:e.jsx(d,{}),children:e.jsx($,{})})}),e.jsx(c,{path:"sessions/:id",element:e.jsx(s.Suspense,{fallback:e.jsx(d,{}),children:e.jsx(K,{})})}),e.jsx(c,{path:"events",element:e.jsx(s.Suspense,{fallback:e.jsx(d,{}),children:e.jsx(U,{})})}),e.jsx(c,{path:"execution-trace",element:e.jsx(s.Suspense,{fallback:e.jsx(d,{}),children:e.jsx(H,{})})}),e.jsx(c,{path:"agents",element:e.jsx(s.Suspense,{fallback:e.jsx(d,{}),children:e.jsx(J,{})})}),e.jsx(c,{path:"skills",element:e.jsx(s.Suspense,{fallback:e.jsx(d,{}),children:e.jsx(Y,{})})}),e.jsx(c,{path:"routing",element:e.jsx(s.Suspense,{fallback:e.jsx(d,{}),children:e.jsx(Z,{})})}),e.jsx(c,{path:"ai-config",element:e.jsx(s.Suspense,{fallback:e.jsx(d,{}),children:e.jsx(ee,{})})}),e.jsx(c,{path:"workflows",element:e.jsx(s.Suspense,{fallback:e.jsx(d,{}),children:e.jsx(se,{})})}),e.jsx(c,{path:"workflows/:routeRequestId",element:e.jsx(s.Suspense,{fallback:e.jsx(d,{}),children:e.jsx(te,{})})})]})})}const g=s.createContext(null);function pe(){const i=s.useContext(g);if(!i)throw new Error("useToast must be used within ToastProvider");return i}let ne=1;function ae({children:i}){const[a,l]=s.useState([]),o=s.useCallback(t=>{l(u=>u.filter(m=>m.id!==t))},[]),r=s.useCallback((t,u)=>{const m=ne++;l(f=>[...f,{id:m,type:t,message:u}]),setTimeout(()=>o(m),4e3)},[o]),n={show:r,success:t=>r("success",t),error:t=>r("error",t),warning:t=>r("warning",t),info:t=>r("info",t)};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(t=>e.jsx(ie,{toast:t,onClose:()=>o(t.id)},t.id))})]})}function ie({toast:i,onClose:a}){const l={success:e.jsx(M,{className:"h-5 w-5 text-green-500"}),error:e.jsx(q,{className:"h-5 w-5 text-red-500"}),warning:e.jsx(B,{className:"h-5 w-5 text-yellow-500"}),info:e.jsx(F,{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:h("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 le=s.createContext(null);function oe({children:i}){var m;const[a,l]=s.useState({open:!1,options:null,resolve:null}),o=s.useCallback(f=>new Promise(j=>{l({open:!0,options:f,resolve:j})}),[]),r=f=>{a.resolve&&a.resolve(f),l({open:!1,options:null,resolve:null})},n=((m=a.options)==null?void 0:m.variant)||"danger",t={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(le.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:()=>r(!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 ${t}`,children:e.jsx(W,{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:()=>r(!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:()=>r(!0),className:`px-4 py-2 text-sm text-white rounded ${u}`,children:a.options.confirmText||"确定"})]})]})]})]})}const ce=new E({defaultOptions:{queries:{refetchOnWindowFocus:!1,retry:1}}});b.createRoot(document.getElementById("root")).render(e.jsx(y.StrictMode,{children:e.jsx(T,{client:ce,children:e.jsx(ae,{children:e.jsx(oe,{children:e.jsx(k,{children:e.jsx(re,{})})})})})}));export{pe as u};
|
|
3
|
-
//# sourceMappingURL=index-Cgr9qMtq.js.map
|