@winspan/claude-forge 8.53.2 → 8.54.3
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/DEVELOPMENT.md +290 -221
- package/README.md +50 -8
- package/dist/cli/commands/skills.d.ts.map +1 -1
- package/dist/cli/commands/skills.js +7 -3
- package/dist/cli/commands/skills.js.map +1 -1
- package/dist/cli/init/hook-manager.d.ts +1 -1
- package/dist/cli/init/hook-manager.d.ts.map +1 -1
- package/dist/cli/init/hook-manager.js +1 -0
- package/dist/cli/init/hook-manager.js.map +1 -1
- package/dist/core/storage/events.d.ts.map +1 -1
- package/dist/core/storage/events.js +0 -1
- package/dist/core/storage/events.js.map +1 -1
- package/dist/core/storage/maintenance.d.ts +25 -3
- package/dist/core/storage/maintenance.d.ts.map +1 -1
- package/dist/core/storage/maintenance.js +33 -4
- package/dist/core/storage/maintenance.js.map +1 -1
- package/dist/core/storage/routing.d.ts +4 -0
- package/dist/core/storage/routing.d.ts.map +1 -1
- package/dist/core/storage/routing.js +10 -4
- package/dist/core/storage/routing.js.map +1 -1
- package/dist/core/storage/sessions.d.ts +17 -0
- package/dist/core/storage/sessions.d.ts.map +1 -1
- package/dist/core/storage/sessions.js +64 -0
- package/dist/core/storage/sessions.js.map +1 -1
- package/dist/core/storage/skills.d.ts +4 -0
- package/dist/core/storage/skills.d.ts.map +1 -1
- package/dist/core/storage/skills.js +10 -2
- package/dist/core/storage/skills.js.map +1 -1
- package/dist/core/storage/sqlite.d.ts +5 -0
- package/dist/core/storage/sqlite.d.ts.map +1 -1
- package/dist/core/storage/sqlite.js +6 -0
- package/dist/core/storage/sqlite.js.map +1 -1
- package/dist/core/storage/tasks.d.ts.map +1 -1
- package/dist/core/storage/tasks.js +2 -0
- package/dist/core/storage/tasks.js.map +1 -1
- package/dist/core/types.d.ts +7 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/daemon/index.d.ts.map +1 -1
- package/dist/daemon/index.js +19 -4
- package/dist/daemon/index.js.map +1 -1
- package/dist/skills/registry.d.ts.map +1 -1
- package/dist/skills/registry.js +13 -2
- package/dist/skills/registry.js.map +1 -1
- package/dist/skills/semantic-matcher.d.ts +2 -2
- package/dist/skills/semantic-matcher.d.ts.map +1 -1
- package/dist/skills/semantic-matcher.js +14 -19
- package/dist/skills/semantic-matcher.js.map +1 -1
- package/dist/skills/upgrade-engine.d.ts +3 -1
- package/dist/skills/upgrade-engine.d.ts.map +1 -1
- package/dist/skills/upgrade-engine.js +25 -14
- package/dist/skills/upgrade-engine.js.map +1 -1
- package/dist/web/analytics/weekly-report.d.ts.map +1 -1
- package/dist/web/analytics/weekly-report.js +21 -29
- package/dist/web/analytics/weekly-report.js.map +1 -1
- package/dist/web/routes/patch.d.ts.map +1 -1
- package/dist/web/routes/patch.js +32 -2
- package/dist/web/routes/patch.js.map +1 -1
- package/dist/web/routes/sessions.d.ts.map +1 -1
- package/dist/web/routes/sessions.js +9 -7
- package/dist/web/routes/sessions.js.map +1 -1
- package/dist/web/routes/trace.d.ts.map +1 -1
- package/dist/web/routes/trace.js +2 -3
- package/dist/web/routes/trace.js.map +1 -1
- package/dist/web/server.d.ts.map +1 -1
- package/dist/web/server.js +3 -2
- package/dist/web/server.js.map +1 -1
- package/package.json +12 -2
- package/scripts/postinstall.cjs +21 -0
- package/.claude/CLAUDE.md +0 -17
- package/.eslintrc.js +0 -23
- package/.prettierrc +0 -8
- package/ARCHITECTURE_ISSUES.md +0 -249
- package/CLAUDE.md +0 -265
- package/CLAUDE.md.backup +0 -488
- package/docs/concurrent-agents.md +0 -129
- package/docs/design/architecture-review-20260516.md +0 -232
- package/docs/design/fix-skills-data-and-set-leak-spec-20260516-1300.md +0 -219
- package/docs/design/h1-storage-aggregation-spec-20260518-1121.md +0 -299
- package/docs/design/h2-getdatabase-encapsulation-spec-20260518-1450.md +0 -191
- package/docs/design/h3-fallback-removal-spec-20260518-1245.md +0 -76
- package/docs/design/h4-index-dedup-spec-20260518-1230.md +0 -109
- package/docs/design/h6-services-migration-spec-20260518-1355.md +0 -82
- package/docs/design/hook-failure-queue-spec-20260516-1530.md +0 -204
- package/docs/design/l1-swarm-protocol-extract-spec-20260518-1605.md +0 -106
- package/docs/design/m10-forge-paths-spec-20260518-1320.md +0 -121
- package/docs/design/m2-m3-tool-input-spec-20260518-1425.md +0 -131
- package/docs/design/m7-routing-event-association-spec-20260518-1545.md +0 -103
- package/docs/design/project-path-gitroot-spec-20260518-1715.md +0 -134
- package/docs/design/refactor-phase1-spec-20260515-1600.md +0 -543
- package/docs/design/refactor-phase2-spec-20260515-1700.md +0 -424
- package/docs/design/skill-ai-upgrade-spec-20260518-1930.md +0 -297
- package/docs/design/task-active-gc-spec-20260518-1745.md +0 -146
- package/docs/design/tasks-list-filter-pagination-spec-20260518-0930.md +0 -208
- package/docs/implementation/daemon-skill-sync-changelog-20260518-2000.md +0 -22
- package/docs/implementation/fix-skills-data-and-set-leak-changelog-20260516-1300.md +0 -104
- package/docs/implementation/h1-storage-aggregation-changelog-20260518-1121.md +0 -82
- package/docs/implementation/h2-final-changelog-20260518-1530.md +0 -61
- package/docs/implementation/h2-phase1-safety-net-changelog-20260518-1450.md +0 -70
- package/docs/implementation/h2-phase2-operations-changelog-20260518-1450.md +0 -120
- package/docs/implementation/h2-phase3-callsites-changelog-20260518-1450.md +0 -71
- package/docs/implementation/h3-fallback-removal-changelog-20260518-1245.md +0 -71
- package/docs/implementation/h4-index-dedup-changelog-20260518-1230.md +0 -60
- package/docs/implementation/h6-services-migration-changelog-20260518-1355.md +0 -46
- package/docs/implementation/h7-m9-defaults-changelog-20260518-1300.md +0 -46
- package/docs/implementation/hook-failure-queue-changelog-20260516-1530.md +0 -196
- package/docs/implementation/hotfix-daemon-event-reject-20260516-1430.md +0 -56
- package/docs/implementation/l1-swarm-protocol-extract-changelog-20260518-1605.md +0 -45
- package/docs/implementation/l3-l4-daemon-perf-changelog-20260518-1410.md +0 -63
- package/docs/implementation/l6-l8-final-cleanup-changelog-20260518-1640.md +0 -38
- package/docs/implementation/m1-m4-m5-l7-cleanup-changelog-20260518-1310.md +0 -58
- package/docs/implementation/m10-forge-paths-changelog-20260518-1320.md +0 -60
- package/docs/implementation/m2-m3-tool-input-changelog-20260518-1425.md +0 -43
- package/docs/implementation/m6-m8-naming-shutdown-changelog-20260518-1340.md +0 -56
- package/docs/implementation/m7-routing-association-changelog-20260518-1545.md +0 -69
- package/docs/implementation/project-path-gitroot-changelog-20260518-1715.md +0 -63
- package/docs/implementation/refactor-phase1-changelog-20260515-1630.md +0 -354
- package/docs/implementation/refactor-phase2-changelog-20260515-1705.md +0 -421
- package/docs/implementation/skill-ai-upgrade-changelog-20260518-1930.md +0 -49
- package/docs/implementation/task-active-gc-changelog-20260518-1745.md +0 -35
- package/docs/implementation/task-title-summary-changelog-20260518-1130.md +0 -39
- package/docs/implementation/tasks-detail-back-loses-filters-changelog-20260518-1100.md +0 -22
- package/docs/implementation/tasks-list-filter-pagination-changelog-20260518-0930.md +0 -72
- package/docs/implementation/tasks-page-white-screen-hotfix-changelog-20260518-1015.md +0 -56
- package/docs/reviews/claudemd-template-sync.md +0 -54
- package/docs/reviews/task-title-summary.md +0 -92
- package/docs/reviews/tasks-detail-back-loses-filters.md +0 -58
- package/docs/reviews/tasks-filter-pagination.md +0 -80
- package/docs/reviews/tasks-page-white-screen-hotfix.md +0 -126
- package/docs/ruflo-learning-strategy.md +0 -322
- package/docs/skills-deduplication-analysis.md +0 -83
- package/docs/skills-multiformat-support.md +0 -177
- package/docs/skills-third-party.md +0 -183
- package/docs/testing/tasks-filter-pagination-test-report.md +0 -86
- package/forge +0 -321
- package/playwright.config.ts +0 -40
- package/scripts/demo-v2.ts +0 -91
- package/scripts/dev-daemon.sh +0 -232
- package/scripts/dev-web.ts +0 -109
- package/scripts/e2e-mcp-link.ts +0 -423
- package/scripts/e2e-methodology-quality.ts +0 -253
- package/scripts/e2e-routing.ts +0 -456
- package/scripts/e2e-user-methodology.ts +0 -326
- package/scripts/e2e-web-workflows.ts +0 -299
- package/scripts/migrate-legacy-to-dynamic.sql +0 -108
- package/scripts/regenerate-execution-docs.ts +0 -116
- package/scripts/sync-agent-skills.ts +0 -193
- package/scripts/test-hook.sh +0 -71
- package/scripts/verify-skill-loading.ts +0 -62
- package/src/claudemd/claudemd-generator.ts +0 -568
- package/src/claudemd/convention-extractor.ts +0 -69
- package/src/claudemd/index.ts +0 -35
- package/src/claudemd/persona-manager.ts +0 -88
- package/src/claudemd/resume-manager.ts +0 -236
- package/src/claudemd/tech-detector.ts +0 -220
- package/src/claudemd/templates/swarm-protocol.md +0 -222
- package/src/cli/commands/claudemd.ts +0 -84
- package/src/cli/commands/config.ts +0 -46
- package/src/cli/commands/daemon.ts +0 -310
- package/src/cli/commands/executions.ts +0 -115
- package/src/cli/commands/init.ts +0 -204
- package/src/cli/commands/logs.ts +0 -181
- package/src/cli/commands/mcp.ts +0 -242
- package/src/cli/commands/menu.ts +0 -357
- package/src/cli/commands/skills.ts +0 -328
- package/src/cli/commands/stats.ts +0 -73
- package/src/cli/commands/status.ts +0 -69
- package/src/cli/commands/template.ts +0 -77
- package/src/cli/commands/trace.ts +0 -148
- package/src/cli/index.ts +0 -42
- package/src/cli/init/hook-manager.ts +0 -132
- package/src/core/ai/provider.ts +0 -308
- package/src/core/ai/types.ts +0 -51
- package/src/core/config.ts +0 -124
- package/src/core/constants.ts +0 -67
- package/src/core/event-fields.ts +0 -32
- package/src/core/queue/index.ts +0 -192
- package/src/core/storage/base.ts +0 -302
- package/src/core/storage/events.ts +0 -434
- package/src/core/storage/injections.ts +0 -78
- package/src/core/storage/maintenance.ts +0 -59
- package/src/core/storage/migrations/002_add_skill_tracking.sql +0 -6
- package/src/core/storage/migrations/003_add_skill_invocations.sql +0 -23
- package/src/core/storage/performance-indexes.sql +0 -23
- package/src/core/storage/routing.ts +0 -322
- package/src/core/storage/rows.ts +0 -112
- package/src/core/storage/schema.sql +0 -224
- package/src/core/storage/sessions.ts +0 -168
- package/src/core/storage/skills.ts +0 -233
- package/src/core/storage/sqlite.ts +0 -293
- package/src/core/storage/tasks.ts +0 -318
- package/src/core/storage/token-usage.ts +0 -93
- package/src/core/types.ts +0 -181
- package/src/core/utils/error-handler.ts +0 -257
- package/src/core/utils/forge-resume-block.ts +0 -74
- package/src/core/utils/format.ts +0 -69
- package/src/core/utils/git.ts +0 -23
- package/src/core/utils/logger.ts +0 -134
- package/src/core/utils/lru-cache.ts +0 -54
- package/src/core/utils/path.ts +0 -19
- package/src/core/utils/session.ts +0 -26
- package/src/core/utils/time.ts +0 -37
- package/src/core/utils/token-tracker.ts +0 -97
- package/src/daemon/event-parser.ts +0 -36
- package/src/daemon/handlers/history-exporter.ts +0 -117
- package/src/daemon/handlers/post-tool-use.ts +0 -54
- package/src/daemon/handlers/stop.ts +0 -208
- package/src/daemon/handlers/user-prompt.ts +0 -178
- package/src/daemon/hook-sync.ts +0 -91
- package/src/daemon/index.ts +0 -312
- package/src/daemon/launchd/com.claude-forge.daemon.plist.template +0 -47
- package/src/daemon/launchd-installer.ts +0 -260
- package/src/daemon/lifecycle.ts +0 -128
- package/src/daemon/router.ts +0 -40
- package/src/daemon/server.ts +0 -196
- package/src/daemon/services/task-segmenter.ts +0 -112
- package/src/daemon/skill-sync.ts +0 -88
- package/src/hooks/hook-lib.sh +0 -118
- package/src/hooks/notification.sh +0 -35
- package/src/hooks/post-tool-use.sh +0 -61
- package/src/hooks/pre-tool-use.sh +0 -63
- package/src/hooks/stop.sh +0 -43
- package/src/hooks/user-prompt-submit.sh +0 -69
- package/src/mcp/server.ts +0 -322
- package/src/skills/index.ts +0 -2
- package/src/skills/invocation-guard.ts +0 -177
- package/src/skills/matcher.ts +0 -148
- package/src/skills/official/code-simplifier.md +0 -52
- package/src/skills/official/find-skills.md +0 -142
- package/src/skills/official/official-api-design.md +0 -30
- package/src/skills/official/official-architecture-decision.md +0 -41
- package/src/skills/official/official-bmad.md +0 -118
- package/src/skills/official/official-db-schema-design.md +0 -34
- package/src/skills/official/official-debug.md +0 -25
- package/src/skills/official/official-doc-driven.md +0 -31
- package/src/skills/official/official-harness-engineering.md +0 -108
- package/src/skills/official/official-performance-optimization.md +0 -30
- package/src/skills/official/official-pr-review.md +0 -35
- package/src/skills/official/official-release-checklist.md +0 -30
- package/src/skills/official/official-security-hardening.md +0 -32
- package/src/skills/official/official-spec-driven-design.md +0 -31
- package/src/skills/official/planning-with-files.md +0 -241
- package/src/skills/official/ui-ux-pro-max.md +0 -105
- package/src/skills/official/webapp-testing.md +0 -96
- package/src/skills/official-skills.ts +0 -89
- package/src/skills/registry.ts +0 -355
- package/src/skills/semantic-matcher.ts +0 -234
- package/src/skills/tools/pipeline-suggest.ts +0 -226
- package/src/skills/tools/skill-invoke.ts +0 -168
- package/src/skills/tools/skill-list.ts +0 -59
- package/src/skills/upgrade-engine.ts +0 -541
- package/src/skills/upgrade-prompt.ts +0 -84
- package/src/templates/go.yaml +0 -53
- package/src/templates/python.yaml +0 -59
- package/src/templates/react.yaml +0 -55
- package/src/templates/template-manager.ts +0 -170
- package/src/web/analytics/anti-pattern-detector.ts +0 -367
- package/src/web/analytics/drift-detector.ts +0 -219
- package/src/web/analytics/weekly-report.ts +0 -431
- package/src/web/auth-middleware.ts +0 -54
- package/src/web/routes/_helpers.ts +0 -34
- package/src/web/routes/ai.ts +0 -204
- package/src/web/routes/auth.ts +0 -22
- package/src/web/routes/drift.ts +0 -25
- package/src/web/routes/error-handler.ts +0 -120
- package/src/web/routes/events.ts +0 -47
- package/src/web/routes/insights.ts +0 -43
- package/src/web/routes/patch.ts +0 -117
- package/src/web/routes/reports.ts +0 -34
- package/src/web/routes/rules.ts +0 -76
- package/src/web/routes/sessions.ts +0 -250
- package/src/web/routes/skill-stats.ts +0 -92
- package/src/web/routes/skills.ts +0 -350
- package/src/web/routes/static.ts +0 -67
- package/src/web/routes/stats.ts +0 -50
- package/src/web/routes/status.ts +0 -30
- package/src/web/routes/tasks.ts +0 -193
- package/src/web/routes/token-usage.ts +0 -20
- package/src/web/routes/trace.ts +0 -126
- package/src/web/routes/types.ts +0 -57
- package/src/web/server.ts +0 -134
- package/src/web/ssrf-guard.ts +0 -112
- package/src/web/static/index.html +0 -3251
- package/src/web/static/vendor/chart.umd.min.js +0 -20
- package/tests/e2e/dashboard.spec.ts +0 -205
- package/tests/e2e/routing-skill-e2e.test.ts +0 -39
- package/tests/helpers/mock-ai.ts +0 -92
- package/tests/helpers/mock-storage.ts +0 -159
- package/tests/integration/claudemd-generator.test.ts +0 -90
- package/tests/integration/queue-replay.integration.test.ts +0 -193
- package/tests/integration/tasks-filter.integration.test.ts +0 -154
- package/tests/integration/web-analytics.integration.test.ts +0 -133
- package/tests/integration/web-stats.integration.test.ts +0 -135
- package/tests/integration/web-trace.integration.test.ts +0 -175
- package/tests/performance/database.benchmark.ts +0 -161
- package/tests/semantic-matcher.test.ts +0 -99
- package/tests/skill-matcher.test.ts +0 -110
- package/tests/unit/ai-provider-retry.test.ts +0 -194
- package/tests/unit/ai-provider-vision.test.ts +0 -224
- package/tests/unit/claudemd-generator.test.ts +0 -68
- package/tests/unit/cli-mcp.test.ts +0 -141
- package/tests/unit/core/forge-paths.test.ts +0 -99
- package/tests/unit/daemon/hook-sync.test.ts +0 -71
- package/tests/unit/daemon/post-tool-use.test.ts +0 -121
- package/tests/unit/daemon/skill-sync.test.ts +0 -75
- package/tests/unit/daemon/stop-handler-behavior-summary.test.ts +0 -202
- package/tests/unit/daemon/task-segmenter-recover.test.ts +0 -84
- package/tests/unit/event-fields.test.ts +0 -88
- package/tests/unit/event-parser.test.ts +0 -55
- package/tests/unit/handlers.test.ts +0 -171
- package/tests/unit/hooks/resolve-project-path.test.ts +0 -122
- package/tests/unit/invocation-guard.test.ts +0 -125
- package/tests/unit/queue.test.ts +0 -272
- package/tests/unit/router.test.ts +0 -138
- package/tests/unit/security.test.ts +0 -128
- package/tests/unit/skill-invocations-workflow.test.ts +0 -495
- package/tests/unit/skill-registry.test.ts +0 -94
- package/tests/unit/skills/invocation-guard-ttl.test.ts +0 -211
- package/tests/unit/skills/official-skills-loader.test.ts +0 -126
- package/tests/unit/skills/registry-multiformat.test.ts +0 -92
- package/tests/unit/skills/upgrade-engine-parse.test.ts +0 -138
- package/tests/unit/skills/upgrade-engine.test.ts +0 -401
- package/tests/unit/skills/upgrade-prompt.test.ts +0 -89
- package/tests/unit/socket-server.test.ts +0 -183
- package/tests/unit/storage/event-operations-aggregates.test.ts +0 -342
- package/tests/unit/storage/migration-idempotent.test.ts +0 -304
- package/tests/unit/storage/routing-aggregates.test.ts +0 -276
- package/tests/unit/storage/routing.test.ts +0 -117
- package/tests/unit/storage/schema-missing.test.ts +0 -81
- package/tests/unit/storage/session-operations-aggregates.test.ts +0 -120
- package/tests/unit/storage/sessions-aggregate.test.ts +0 -435
- package/tests/unit/storage/skill-operations-counts.test.ts +0 -106
- package/tests/unit/storage/skills-aggregates.test.ts +0 -104
- package/tests/unit/storage/sqlite-refactor-harness.test.ts +0 -314
- package/tests/unit/storage/task-operations-counts.test.ts +0 -46
- package/tests/unit/storage/tasks-getById.test.ts +0 -343
- package/tests/unit/storage/tasks-stale-gc.test.ts +0 -86
- package/tests/unit/storage.test.ts +0 -172
- package/tests/unit/token-usage.test.ts +0 -144
- package/tests/unit/type-guards.test.ts +0 -201
- package/tests/unit/utils/format.test.ts +0 -189
- package/tests/unit/utils/session.test.ts +0 -89
- package/tests/unit/utils/time.test.ts +0 -112
- package/tests/unit/web/navigation-back-contract.test.ts +0 -134
- package/tests/unit/web/routes-auth.test.ts +0 -93
- package/tests/unit/web/routes-events.test.ts +0 -101
- package/tests/unit/web/routes-rules.test.ts +0 -182
- package/tests/unit/web/routes-sessions.test.ts +0 -181
- package/tests/unit/web/routes-skill-stats.test.ts +0 -179
- package/tests/unit/web/routes-stats.test.ts +0 -92
- package/tests/unit/web/routes-tasks.test.ts +0 -385
- package/tests/unit/web/task-title-contract.test.ts +0 -210
- package/tests/unit/web/tasks-component-contract.test.ts +0 -179
- package/tsconfig.json +0 -22
- package/vitest.config.ts +0 -21
- package/vitest.integration.config.ts +0 -16
- package/web/CLAUDE.md +0 -20
- package/web/index.html +0 -13
- package/web/package-lock.json +0 -4854
- package/web/package.json +0 -35
- package/web/postcss.config.js +0 -6
- package/web/src/App.tsx +0 -110
- package/web/src/components/CodeBlock.tsx +0 -31
- package/web/src/components/Confirm.tsx +0 -96
- package/web/src/components/Drawer.tsx +0 -60
- package/web/src/components/Layout.tsx +0 -145
- package/web/src/components/MarkdownRenderer.tsx +0 -77
- package/web/src/components/SearchInput.tsx +0 -31
- package/web/src/components/SessionDetailContent.tsx +0 -157
- package/web/src/components/Toast.tsx +0 -92
- package/web/src/index.css +0 -19
- package/web/src/main.tsx +0 -31
- package/web/src/pages/AIConfig.tsx +0 -233
- package/web/src/pages/Dashboard.tsx +0 -572
- package/web/src/pages/Events.tsx +0 -271
- package/web/src/pages/Reports.tsx +0 -428
- package/web/src/pages/SessionDetail.tsx +0 -162
- package/web/src/pages/Sessions.tsx +0 -205
- package/web/src/pages/Skills.tsx +0 -180
- package/web/src/pages/TaskDetail.tsx +0 -515
- package/web/src/pages/Tasks.tsx +0 -415
- package/web/src/utils/auth.ts +0 -59
- package/web/src/utils/export.ts +0 -54
- package/web/src/utils/navigation.ts +0 -25
- package/web/src/utils/task-title.ts +0 -49
- package/web/src/utils/time.ts +0 -13
- package/web/tailwind.config.js +0 -11
- package/web/tsconfig.json +0 -21
- package/web/tsconfig.node.json +0 -10
- package/web/vite.config.ts +0 -76
- package/winspan-claude-forge-8.43.0.tgz +0 -0
|
@@ -1,428 +0,0 @@
|
|
|
1
|
-
import { useQuery } from '@tanstack/react-query'
|
|
2
|
-
import { useState, type ReactNode, type ComponentType } from 'react'
|
|
3
|
-
import {
|
|
4
|
-
FileText, Download, Activity, MessageSquare, ListTodo,
|
|
5
|
-
Bot, BookOpen, Wrench, FileEdit, AlertTriangle, CheckCircle2,
|
|
6
|
-
TrendingUp, TrendingDown, Minus,
|
|
7
|
-
} from 'lucide-react'
|
|
8
|
-
import {
|
|
9
|
-
BarChart, Bar, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer,
|
|
10
|
-
} from 'recharts'
|
|
11
|
-
|
|
12
|
-
interface WeeklyReport {
|
|
13
|
-
generatedAt: string
|
|
14
|
-
week: { start: string; end: string; isoWeekNumber: number }
|
|
15
|
-
overview: {
|
|
16
|
-
totalSessions: number
|
|
17
|
-
totalEvents: number
|
|
18
|
-
totalTasks: number
|
|
19
|
-
activeProjects: string[]
|
|
20
|
-
activeDays: number
|
|
21
|
-
}
|
|
22
|
-
agentDelegation: {
|
|
23
|
-
totalPrompts: number
|
|
24
|
-
delegations: number
|
|
25
|
-
rate: string
|
|
26
|
-
weekOverWeek: string
|
|
27
|
-
topAgents: Array<{ agent: string; count: number }>
|
|
28
|
-
}
|
|
29
|
-
skills: {
|
|
30
|
-
invocations: number
|
|
31
|
-
distinct: number
|
|
32
|
-
topSkills: Array<{ skill_id: string; count: number }>
|
|
33
|
-
neverUsed: string[]
|
|
34
|
-
}
|
|
35
|
-
tools: {
|
|
36
|
-
totalCalls: number
|
|
37
|
-
topTools: Array<{ name: string; count: number }>
|
|
38
|
-
failureRate: string
|
|
39
|
-
}
|
|
40
|
-
files: {
|
|
41
|
-
topEdited: Array<{ path: string; editCount: number }>
|
|
42
|
-
totalEdits: number
|
|
43
|
-
}
|
|
44
|
-
anomalies: Array<{ type: string; description: string }>
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
const WEEK_OPTIONS: Array<{ label: string; offset: number }> = [
|
|
48
|
-
{ label: '本周', offset: 0 },
|
|
49
|
-
{ label: '上周', offset: -1 },
|
|
50
|
-
{ label: '上上周', offset: -2 },
|
|
51
|
-
]
|
|
52
|
-
|
|
53
|
-
async function fetchReport(weekOffset: number): Promise<WeeklyReport> {
|
|
54
|
-
const res = await fetch(`/api/reports/weekly?weekOffset=${weekOffset}`)
|
|
55
|
-
if (!res.ok) throw new Error('Failed to fetch weekly report')
|
|
56
|
-
return res.json()
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
export default function Reports() {
|
|
60
|
-
const [weekOffset, setWeekOffset] = useState(0)
|
|
61
|
-
const { data: report, isLoading, error } = useQuery({
|
|
62
|
-
queryKey: ['weekly-report', weekOffset],
|
|
63
|
-
queryFn: () => fetchReport(weekOffset),
|
|
64
|
-
refetchInterval: 60_000,
|
|
65
|
-
})
|
|
66
|
-
|
|
67
|
-
const handleDownload = () => {
|
|
68
|
-
const url = `/api/reports/weekly?weekOffset=${weekOffset}&format=markdown`
|
|
69
|
-
window.open(url, '_blank')
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
return (
|
|
73
|
-
<div>
|
|
74
|
-
<div className="flex items-center justify-between mb-6 flex-wrap gap-3">
|
|
75
|
-
<h1 className="flex items-center gap-2 text-2xl font-bold text-gray-900">
|
|
76
|
-
<FileText className="h-6 w-6 text-indigo-600" />
|
|
77
|
-
周报
|
|
78
|
-
</h1>
|
|
79
|
-
<div className="flex items-center gap-3">
|
|
80
|
-
<div className="inline-flex rounded-md shadow-sm">
|
|
81
|
-
{WEEK_OPTIONS.map((opt, idx) => (
|
|
82
|
-
<button
|
|
83
|
-
key={opt.offset}
|
|
84
|
-
onClick={() => setWeekOffset(opt.offset)}
|
|
85
|
-
className={[
|
|
86
|
-
'px-3 py-1.5 text-sm font-medium border',
|
|
87
|
-
idx === 0 ? 'rounded-l-md' : '',
|
|
88
|
-
idx === WEEK_OPTIONS.length - 1 ? 'rounded-r-md' : '',
|
|
89
|
-
idx > 0 ? '-ml-px' : '',
|
|
90
|
-
weekOffset === opt.offset
|
|
91
|
-
? 'bg-indigo-600 text-white border-indigo-600 z-10'
|
|
92
|
-
: 'bg-white text-gray-700 border-gray-300 hover:bg-gray-50',
|
|
93
|
-
].join(' ')}
|
|
94
|
-
>
|
|
95
|
-
{opt.label}
|
|
96
|
-
</button>
|
|
97
|
-
))}
|
|
98
|
-
</div>
|
|
99
|
-
<button
|
|
100
|
-
onClick={handleDownload}
|
|
101
|
-
className="inline-flex items-center gap-1.5 px-3 py-1.5 text-sm font-medium text-white bg-emerald-600 hover:bg-emerald-700 rounded-md shadow-sm"
|
|
102
|
-
>
|
|
103
|
-
<Download className="h-4 w-4" />
|
|
104
|
-
导出 Markdown
|
|
105
|
-
</button>
|
|
106
|
-
</div>
|
|
107
|
-
</div>
|
|
108
|
-
|
|
109
|
-
{isLoading && (
|
|
110
|
-
<div className="bg-white rounded-lg shadow p-12 text-center text-gray-500">
|
|
111
|
-
加载中...
|
|
112
|
-
</div>
|
|
113
|
-
)}
|
|
114
|
-
{error && (
|
|
115
|
-
<div className="bg-white rounded-lg shadow p-6 text-red-600">
|
|
116
|
-
加载失败: {(error as Error).message}
|
|
117
|
-
</div>
|
|
118
|
-
)}
|
|
119
|
-
|
|
120
|
-
{report && (
|
|
121
|
-
<>
|
|
122
|
-
<div className="bg-white rounded-lg shadow p-4 mb-4 flex items-center justify-between flex-wrap gap-2">
|
|
123
|
-
<div className="text-sm text-gray-600">
|
|
124
|
-
<span className="font-semibold text-gray-900">第 {report.week.isoWeekNumber} 周</span>
|
|
125
|
-
<span className="mx-2 text-gray-400">·</span>
|
|
126
|
-
{report.week.start.slice(0, 10)} ~ {report.week.end.slice(0, 10)}
|
|
127
|
-
</div>
|
|
128
|
-
<div className="text-xs text-gray-400">
|
|
129
|
-
生成于 {new Date(report.generatedAt).toLocaleString('zh-CN')}
|
|
130
|
-
</div>
|
|
131
|
-
</div>
|
|
132
|
-
|
|
133
|
-
<OverviewCard data={report.overview} />
|
|
134
|
-
<AgentCard data={report.agentDelegation} />
|
|
135
|
-
<SkillsCard data={report.skills} />
|
|
136
|
-
<ToolsCard data={report.tools} />
|
|
137
|
-
<FilesCard data={report.files} />
|
|
138
|
-
<AnomaliesCard data={report.anomalies} />
|
|
139
|
-
</>
|
|
140
|
-
)}
|
|
141
|
-
</div>
|
|
142
|
-
)
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
function SectionCard({
|
|
146
|
-
title, icon: Icon, iconColor, children,
|
|
147
|
-
}: {
|
|
148
|
-
title: string
|
|
149
|
-
icon: ComponentType<{ className?: string }>
|
|
150
|
-
iconColor?: string
|
|
151
|
-
children: ReactNode
|
|
152
|
-
}) {
|
|
153
|
-
return (
|
|
154
|
-
<div className="bg-white rounded-lg shadow p-6 mb-4">
|
|
155
|
-
<h3 className="flex items-center gap-2 text-base font-semibold text-gray-900 mb-4">
|
|
156
|
-
<Icon className={`h-4 w-4 ${iconColor ?? 'text-indigo-600'}`} />
|
|
157
|
-
{title}
|
|
158
|
-
</h3>
|
|
159
|
-
{children}
|
|
160
|
-
</div>
|
|
161
|
-
)
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
function StatNumber({ label, value }: { label: string; value: number | string }) {
|
|
165
|
-
return (
|
|
166
|
-
<div className="text-center">
|
|
167
|
-
<div className="text-2xl font-bold text-gray-900">{value}</div>
|
|
168
|
-
<div className="text-xs text-gray-500 mt-1">{label}</div>
|
|
169
|
-
</div>
|
|
170
|
-
)
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
function OverviewCard({ data }: { data: WeeklyReport['overview'] }) {
|
|
174
|
-
return (
|
|
175
|
-
<SectionCard title="概览" icon={Activity} iconColor="text-blue-600">
|
|
176
|
-
<div className="grid grid-cols-2 md:grid-cols-4 gap-4 mb-4">
|
|
177
|
-
<div className="bg-blue-50 rounded-lg p-4">
|
|
178
|
-
<div className="flex items-center gap-2 text-xs text-blue-600 mb-1">
|
|
179
|
-
<MessageSquare className="h-3 w-3" /> 会话
|
|
180
|
-
</div>
|
|
181
|
-
<div className="text-2xl font-bold text-blue-700">{data.totalSessions}</div>
|
|
182
|
-
</div>
|
|
183
|
-
<div className="bg-indigo-50 rounded-lg p-4">
|
|
184
|
-
<div className="flex items-center gap-2 text-xs text-indigo-600 mb-1">
|
|
185
|
-
<Activity className="h-3 w-3" /> 事件
|
|
186
|
-
</div>
|
|
187
|
-
<div className="text-2xl font-bold text-indigo-700">{data.totalEvents}</div>
|
|
188
|
-
</div>
|
|
189
|
-
<div className="bg-purple-50 rounded-lg p-4">
|
|
190
|
-
<div className="flex items-center gap-2 text-xs text-purple-600 mb-1">
|
|
191
|
-
<ListTodo className="h-3 w-3" /> 任务
|
|
192
|
-
</div>
|
|
193
|
-
<div className="text-2xl font-bold text-purple-700">{data.totalTasks}</div>
|
|
194
|
-
</div>
|
|
195
|
-
<div className="bg-emerald-50 rounded-lg p-4">
|
|
196
|
-
<div className="text-xs text-emerald-600 mb-1">活跃天数</div>
|
|
197
|
-
<div className="text-2xl font-bold text-emerald-700">
|
|
198
|
-
{data.activeDays} <span className="text-base font-normal">/ 7</span>
|
|
199
|
-
</div>
|
|
200
|
-
</div>
|
|
201
|
-
</div>
|
|
202
|
-
|
|
203
|
-
<div>
|
|
204
|
-
<div className="text-xs font-medium text-gray-700 mb-2">
|
|
205
|
-
活跃项目 ({data.activeProjects.length})
|
|
206
|
-
</div>
|
|
207
|
-
{data.activeProjects.length > 0 ? (
|
|
208
|
-
<div className="flex flex-wrap gap-2">
|
|
209
|
-
{data.activeProjects.map((p) => (
|
|
210
|
-
<span
|
|
211
|
-
key={p}
|
|
212
|
-
className="text-xs bg-gray-100 text-gray-700 px-2 py-1 rounded font-mono break-all"
|
|
213
|
-
title={p}
|
|
214
|
-
>
|
|
215
|
-
{p.length > 60 ? `...${p.slice(-60)}` : p}
|
|
216
|
-
</span>
|
|
217
|
-
))}
|
|
218
|
-
</div>
|
|
219
|
-
) : (
|
|
220
|
-
<div className="text-sm text-gray-400">本周无活跃项目</div>
|
|
221
|
-
)}
|
|
222
|
-
</div>
|
|
223
|
-
</SectionCard>
|
|
224
|
-
)
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
function WeekOverWeekIndicator({ weekOverWeek }: { weekOverWeek: string }) {
|
|
228
|
-
const num = parseFloat(weekOverWeek)
|
|
229
|
-
if (Number.isNaN(num) || Math.abs(num) < 0.05) {
|
|
230
|
-
return (
|
|
231
|
-
<span className="inline-flex items-center gap-1 text-xs text-gray-500">
|
|
232
|
-
<Minus className="h-3 w-3" /> {weekOverWeek}
|
|
233
|
-
</span>
|
|
234
|
-
)
|
|
235
|
-
}
|
|
236
|
-
if (num > 0) {
|
|
237
|
-
return (
|
|
238
|
-
<span className="inline-flex items-center gap-1 text-xs text-emerald-600">
|
|
239
|
-
<TrendingUp className="h-3 w-3" /> {weekOverWeek}
|
|
240
|
-
</span>
|
|
241
|
-
)
|
|
242
|
-
}
|
|
243
|
-
return (
|
|
244
|
-
<span className="inline-flex items-center gap-1 text-xs text-rose-600">
|
|
245
|
-
<TrendingDown className="h-3 w-3" /> {weekOverWeek}
|
|
246
|
-
</span>
|
|
247
|
-
)
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
function AgentCard({ data }: { data: WeeklyReport['agentDelegation'] }) {
|
|
251
|
-
const chartData = data.topAgents.map(a => ({ name: a.agent, count: a.count }))
|
|
252
|
-
return (
|
|
253
|
-
<SectionCard title="Agent 委托" icon={Bot} iconColor="text-indigo-600">
|
|
254
|
-
<div className="grid grid-cols-3 gap-4 mb-4">
|
|
255
|
-
<StatNumber label="总路由" value={data.totalPrompts} />
|
|
256
|
-
<StatNumber label="委托次数" value={data.delegations} />
|
|
257
|
-
<div className="text-center">
|
|
258
|
-
<div className="text-2xl font-bold text-indigo-700">{data.rate}</div>
|
|
259
|
-
<div className="text-xs text-gray-500 mt-1">委托率</div>
|
|
260
|
-
<div className="mt-1">
|
|
261
|
-
<WeekOverWeekIndicator weekOverWeek={data.weekOverWeek} />
|
|
262
|
-
</div>
|
|
263
|
-
</div>
|
|
264
|
-
</div>
|
|
265
|
-
|
|
266
|
-
{chartData.length > 0 ? (
|
|
267
|
-
<div>
|
|
268
|
-
<h4 className="text-sm font-medium text-gray-700 mb-2">Top 5 Agents</h4>
|
|
269
|
-
<ResponsiveContainer width="100%" height={180}>
|
|
270
|
-
<BarChart data={chartData} layout="vertical">
|
|
271
|
-
<CartesianGrid strokeDasharray="3 3" stroke="#f3f4f6" />
|
|
272
|
-
<XAxis type="number" tick={{ fontSize: 11 }} />
|
|
273
|
-
<YAxis dataKey="name" type="category" tick={{ fontSize: 11 }} width={120} />
|
|
274
|
-
<Tooltip />
|
|
275
|
-
<Bar dataKey="count" fill="#6366f1" radius={[0, 4, 4, 0]} />
|
|
276
|
-
</BarChart>
|
|
277
|
-
</ResponsiveContainer>
|
|
278
|
-
</div>
|
|
279
|
-
) : (
|
|
280
|
-
<div className="text-sm text-gray-400 text-center py-4">本周无 Agent 委托记录</div>
|
|
281
|
-
)}
|
|
282
|
-
</SectionCard>
|
|
283
|
-
)
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
function SkillsCard({ data }: { data: WeeklyReport['skills'] }) {
|
|
287
|
-
const chartData = data.topSkills.map(s => ({ name: s.skill_id, count: s.count }))
|
|
288
|
-
return (
|
|
289
|
-
<SectionCard title="Skills" icon={BookOpen} iconColor="text-emerald-600">
|
|
290
|
-
<div className="grid grid-cols-2 gap-4 mb-4">
|
|
291
|
-
<StatNumber label="调用总数" value={data.invocations} />
|
|
292
|
-
<StatNumber label="不同 Skill" value={data.distinct} />
|
|
293
|
-
</div>
|
|
294
|
-
|
|
295
|
-
{chartData.length > 0 ? (
|
|
296
|
-
<div className="mb-4">
|
|
297
|
-
<h4 className="text-sm font-medium text-gray-700 mb-2">Top 5 Skills</h4>
|
|
298
|
-
<ResponsiveContainer width="100%" height={180}>
|
|
299
|
-
<BarChart data={chartData} layout="vertical">
|
|
300
|
-
<CartesianGrid strokeDasharray="3 3" stroke="#f3f4f6" />
|
|
301
|
-
<XAxis type="number" tick={{ fontSize: 11 }} />
|
|
302
|
-
<YAxis dataKey="name" type="category" tick={{ fontSize: 10 }} width={140} />
|
|
303
|
-
<Tooltip />
|
|
304
|
-
<Bar dataKey="count" fill="#10b981" radius={[0, 4, 4, 0]} />
|
|
305
|
-
</BarChart>
|
|
306
|
-
</ResponsiveContainer>
|
|
307
|
-
</div>
|
|
308
|
-
) : (
|
|
309
|
-
<div className="text-sm text-gray-400 text-center py-4 mb-4">本周无 Skill 调用</div>
|
|
310
|
-
)}
|
|
311
|
-
|
|
312
|
-
{data.neverUsed.length > 0 && (
|
|
313
|
-
<div>
|
|
314
|
-
<h4 className="text-sm font-medium text-gray-700 mb-2">
|
|
315
|
-
从未使用的 Skill ({data.neverUsed.length})
|
|
316
|
-
</h4>
|
|
317
|
-
<div className="flex flex-wrap gap-2">
|
|
318
|
-
{data.neverUsed.map(id => (
|
|
319
|
-
<span key={id} className="text-xs bg-gray-100 text-gray-500 px-2 py-1 rounded">
|
|
320
|
-
{id}
|
|
321
|
-
</span>
|
|
322
|
-
))}
|
|
323
|
-
</div>
|
|
324
|
-
</div>
|
|
325
|
-
)}
|
|
326
|
-
</SectionCard>
|
|
327
|
-
)
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
function ToolsCard({ data }: { data: WeeklyReport['tools'] }) {
|
|
331
|
-
const chartData = data.topTools.map(t => ({ name: t.name, count: t.count }))
|
|
332
|
-
const failureNum = parseFloat(data.failureRate)
|
|
333
|
-
const failureColor = failureNum > 5 ? 'text-rose-600' : failureNum > 1 ? 'text-amber-600' : 'text-emerald-600'
|
|
334
|
-
|
|
335
|
-
return (
|
|
336
|
-
<SectionCard title="Tools" icon={Wrench} iconColor="text-amber-600">
|
|
337
|
-
<div className="grid grid-cols-2 gap-4 mb-4">
|
|
338
|
-
<StatNumber label="调用总数" value={data.totalCalls} />
|
|
339
|
-
<div className="text-center">
|
|
340
|
-
<div className={`text-2xl font-bold ${failureColor}`}>{data.failureRate}</div>
|
|
341
|
-
<div className="text-xs text-gray-500 mt-1">失败率</div>
|
|
342
|
-
</div>
|
|
343
|
-
</div>
|
|
344
|
-
|
|
345
|
-
{chartData.length > 0 ? (
|
|
346
|
-
<div>
|
|
347
|
-
<h4 className="text-sm font-medium text-gray-700 mb-2">Top 5 Tools</h4>
|
|
348
|
-
<ResponsiveContainer width="100%" height={180}>
|
|
349
|
-
<BarChart data={chartData} layout="vertical">
|
|
350
|
-
<CartesianGrid strokeDasharray="3 3" stroke="#f3f4f6" />
|
|
351
|
-
<XAxis type="number" tick={{ fontSize: 11 }} />
|
|
352
|
-
<YAxis dataKey="name" type="category" tick={{ fontSize: 11 }} width={120} />
|
|
353
|
-
<Tooltip />
|
|
354
|
-
<Bar dataKey="count" fill="#f59e0b" radius={[0, 4, 4, 0]} />
|
|
355
|
-
</BarChart>
|
|
356
|
-
</ResponsiveContainer>
|
|
357
|
-
</div>
|
|
358
|
-
) : (
|
|
359
|
-
<div className="text-sm text-gray-400 text-center py-4">本周无工具调用记录</div>
|
|
360
|
-
)}
|
|
361
|
-
</SectionCard>
|
|
362
|
-
)
|
|
363
|
-
}
|
|
364
|
-
|
|
365
|
-
function FilesCard({ data }: { data: WeeklyReport['files'] }) {
|
|
366
|
-
return (
|
|
367
|
-
<SectionCard title="文件编辑" icon={FileEdit} iconColor="text-purple-600">
|
|
368
|
-
<div className="mb-4">
|
|
369
|
-
<StatNumber label="编辑总数" value={data.totalEdits} />
|
|
370
|
-
</div>
|
|
371
|
-
|
|
372
|
-
{data.topEdited.length > 0 ? (
|
|
373
|
-
<div>
|
|
374
|
-
<h4 className="text-sm font-medium text-gray-700 mb-2">Top 5 编辑文件</h4>
|
|
375
|
-
<div className="space-y-2">
|
|
376
|
-
{data.topEdited.map((f) => (
|
|
377
|
-
<div
|
|
378
|
-
key={f.path}
|
|
379
|
-
className="flex items-center justify-between gap-3 px-3 py-2 bg-gray-50 rounded text-sm"
|
|
380
|
-
>
|
|
381
|
-
<span className="font-mono text-xs text-gray-700 break-all flex-1" title={f.path}>
|
|
382
|
-
{f.path.length > 80 ? `...${f.path.slice(-80)}` : f.path}
|
|
383
|
-
</span>
|
|
384
|
-
<span className="font-semibold text-purple-700 whitespace-nowrap">
|
|
385
|
-
{f.editCount} 次
|
|
386
|
-
</span>
|
|
387
|
-
</div>
|
|
388
|
-
))}
|
|
389
|
-
</div>
|
|
390
|
-
</div>
|
|
391
|
-
) : (
|
|
392
|
-
<div className="text-sm text-gray-400 text-center py-4">本周无文件编辑记录</div>
|
|
393
|
-
)}
|
|
394
|
-
</SectionCard>
|
|
395
|
-
)
|
|
396
|
-
}
|
|
397
|
-
|
|
398
|
-
function AnomaliesCard({ data }: { data: WeeklyReport['anomalies'] }) {
|
|
399
|
-
if (data.length === 0) {
|
|
400
|
-
return (
|
|
401
|
-
<div className="bg-emerald-50 border border-emerald-200 rounded-lg p-4 mb-4 flex items-center gap-2">
|
|
402
|
-
<CheckCircle2 className="h-5 w-5 text-emerald-600" />
|
|
403
|
-
<span className="text-sm text-emerald-700 font-medium">本周无异常</span>
|
|
404
|
-
</div>
|
|
405
|
-
)
|
|
406
|
-
}
|
|
407
|
-
return (
|
|
408
|
-
<SectionCard title="异常" icon={AlertTriangle} iconColor="text-amber-600">
|
|
409
|
-
<div className="space-y-2">
|
|
410
|
-
{data.map((item, idx) => (
|
|
411
|
-
<div
|
|
412
|
-
key={idx}
|
|
413
|
-
className="flex items-start gap-3 px-3 py-2 bg-amber-50 border border-amber-200 rounded text-sm"
|
|
414
|
-
>
|
|
415
|
-
<AlertTriangle className="h-4 w-4 text-amber-600 mt-0.5 flex-shrink-0" />
|
|
416
|
-
<div>
|
|
417
|
-
<div className="font-medium text-amber-900">{item.type}</div>
|
|
418
|
-
<div className="text-amber-700 mt-0.5">{item.description}</div>
|
|
419
|
-
</div>
|
|
420
|
-
</div>
|
|
421
|
-
))}
|
|
422
|
-
</div>
|
|
423
|
-
</SectionCard>
|
|
424
|
-
)
|
|
425
|
-
}
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
@@ -1,162 +0,0 @@
|
|
|
1
|
-
import { useParams, Link } from 'react-router-dom'
|
|
2
|
-
import { useQuery } from '@tanstack/react-query'
|
|
3
|
-
import { format } from 'date-fns'
|
|
4
|
-
import { parseUTC } from '../utils/time'
|
|
5
|
-
import { ArrowLeft, MessageSquare, FileEdit, Terminal, GitCommit } from 'lucide-react'
|
|
6
|
-
import clsx from 'clsx'
|
|
7
|
-
|
|
8
|
-
interface TaskDetail {
|
|
9
|
-
id: string
|
|
10
|
-
title: string
|
|
11
|
-
start_time: string
|
|
12
|
-
end_time?: string
|
|
13
|
-
status: string
|
|
14
|
-
event_count: number
|
|
15
|
-
prompts: Array<{ timestamp: string; content: string }>
|
|
16
|
-
events: Array<any>
|
|
17
|
-
injections: Array<any>
|
|
18
|
-
summary: {
|
|
19
|
-
toolUsage: Record<string, number>
|
|
20
|
-
filesChanged: string[]
|
|
21
|
-
commits: Array<{ timestamp: string; message: string }>
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
interface SessionDetail {
|
|
26
|
-
session: {
|
|
27
|
-
session_id: string
|
|
28
|
-
first_prompt: string
|
|
29
|
-
event_count: number
|
|
30
|
-
start_time: string
|
|
31
|
-
end_time: string
|
|
32
|
-
}
|
|
33
|
-
tasks: TaskDetail[]
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
async function fetchSessionDetail(id: string): Promise<SessionDetail> {
|
|
37
|
-
const res = await fetch(`/api/sessions/${id}/detail`)
|
|
38
|
-
if (!res.ok) throw new Error('Failed to fetch session detail')
|
|
39
|
-
return res.json()
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
export default function SessionDetail() {
|
|
43
|
-
const { id } = useParams<{ id: string }>()
|
|
44
|
-
const { data, isLoading, error } = useQuery({
|
|
45
|
-
queryKey: ['session-detail', id],
|
|
46
|
-
queryFn: () => fetchSessionDetail(id!),
|
|
47
|
-
enabled: !!id,
|
|
48
|
-
})
|
|
49
|
-
|
|
50
|
-
if (isLoading) {
|
|
51
|
-
return (
|
|
52
|
-
<div className="bg-white rounded-lg shadow p-6">
|
|
53
|
-
<p className="text-gray-600">加载中...</p>
|
|
54
|
-
</div>
|
|
55
|
-
)
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
if (error || !data) {
|
|
59
|
-
return (
|
|
60
|
-
<div>
|
|
61
|
-
<Link to="/sessions" className="inline-flex items-center text-sm text-gray-500 hover:text-gray-700 mb-4">
|
|
62
|
-
<ArrowLeft className="h-4 w-4 mr-1" />返回
|
|
63
|
-
</Link>
|
|
64
|
-
<div className="bg-white rounded-lg shadow p-6">
|
|
65
|
-
<p className="text-red-600">加载失败</p>
|
|
66
|
-
</div>
|
|
67
|
-
</div>
|
|
68
|
-
)
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
return (
|
|
72
|
-
<div>
|
|
73
|
-
<Link to="/sessions" className="inline-flex items-center text-sm text-gray-500 hover:text-gray-700 mb-4">
|
|
74
|
-
<ArrowLeft className="h-4 w-4 mr-1" />返回会话列表
|
|
75
|
-
</Link>
|
|
76
|
-
|
|
77
|
-
<div className="bg-white rounded-lg shadow p-6 mb-6">
|
|
78
|
-
<h1 className="text-xl font-bold text-gray-900 mb-2">
|
|
79
|
-
会话详情
|
|
80
|
-
</h1>
|
|
81
|
-
<p className="text-sm text-gray-500 font-mono mb-4">{data.session.session_id}</p>
|
|
82
|
-
<div className="grid grid-cols-3 gap-4">
|
|
83
|
-
<div>
|
|
84
|
-
<div className="text-xs text-gray-500">事件数</div>
|
|
85
|
-
<div className="text-lg font-semibold">{data.session.event_count}</div>
|
|
86
|
-
</div>
|
|
87
|
-
<div>
|
|
88
|
-
<div className="text-xs text-gray-500">任务数</div>
|
|
89
|
-
<div className="text-lg font-semibold">{data.tasks.length}</div>
|
|
90
|
-
</div>
|
|
91
|
-
<div>
|
|
92
|
-
<div className="text-xs text-gray-500">开始时间</div>
|
|
93
|
-
<div className="text-sm">
|
|
94
|
-
{data.session.start_time ? format(parseUTC(data.session.start_time), 'MM-dd HH:mm:ss') : '-'}
|
|
95
|
-
</div>
|
|
96
|
-
</div>
|
|
97
|
-
</div>
|
|
98
|
-
</div>
|
|
99
|
-
|
|
100
|
-
<div className="space-y-4">
|
|
101
|
-
{data.tasks.map((task) => (
|
|
102
|
-
<div key={task.id} className="bg-white rounded-lg shadow p-6">
|
|
103
|
-
<div className="flex items-center justify-between mb-4">
|
|
104
|
-
<h3 className="text-lg font-semibold text-gray-900">{task.title}</h3>
|
|
105
|
-
<span className={clsx(
|
|
106
|
-
'px-2 py-1 text-xs font-medium rounded-full',
|
|
107
|
-
task.status === 'completed' && 'bg-green-100 text-green-700',
|
|
108
|
-
task.status === 'active' && 'bg-blue-100 text-blue-700',
|
|
109
|
-
task.status === 'abandoned' && 'bg-gray-100 text-gray-600'
|
|
110
|
-
)}>
|
|
111
|
-
{task.status}
|
|
112
|
-
</span>
|
|
113
|
-
</div>
|
|
114
|
-
|
|
115
|
-
<div className="grid grid-cols-3 gap-4 mb-4 text-sm">
|
|
116
|
-
<div>
|
|
117
|
-
<div className="text-xs text-gray-500 mb-1 flex items-center gap-1">
|
|
118
|
-
<Terminal className="h-3 w-3" />工具使用
|
|
119
|
-
</div>
|
|
120
|
-
<div className="space-y-1">
|
|
121
|
-
{Object.entries(task.summary.toolUsage).slice(0, 5).map(([tool, count]) => (
|
|
122
|
-
<div key={tool} className="flex justify-between text-xs">
|
|
123
|
-
<span className="text-gray-600">{tool}</span>
|
|
124
|
-
<span className="font-mono text-gray-900">{count}</span>
|
|
125
|
-
</div>
|
|
126
|
-
))}
|
|
127
|
-
</div>
|
|
128
|
-
</div>
|
|
129
|
-
<div>
|
|
130
|
-
<div className="text-xs text-gray-500 mb-1 flex items-center gap-1">
|
|
131
|
-
<FileEdit className="h-3 w-3" />文件变更
|
|
132
|
-
</div>
|
|
133
|
-
<div className="text-xs text-gray-700">{task.summary.filesChanged.length} 个文件</div>
|
|
134
|
-
</div>
|
|
135
|
-
<div>
|
|
136
|
-
<div className="text-xs text-gray-500 mb-1 flex items-center gap-1">
|
|
137
|
-
<GitCommit className="h-3 w-3" />提交
|
|
138
|
-
</div>
|
|
139
|
-
<div className="text-xs text-gray-700">{task.summary.commits.length} 次</div>
|
|
140
|
-
</div>
|
|
141
|
-
</div>
|
|
142
|
-
|
|
143
|
-
{task.prompts.length > 0 && (
|
|
144
|
-
<div className="border-t pt-3">
|
|
145
|
-
<div className="text-xs text-gray-500 mb-2 flex items-center gap-1">
|
|
146
|
-
<MessageSquare className="h-3 w-3" />用户提示
|
|
147
|
-
</div>
|
|
148
|
-
<div className="space-y-2">
|
|
149
|
-
{task.prompts.slice(0, 3).map((p, i) => (
|
|
150
|
-
<div key={i} className="text-sm bg-gray-50 rounded p-2">
|
|
151
|
-
<p className="text-gray-700 line-clamp-2">{p.content}</p>
|
|
152
|
-
</div>
|
|
153
|
-
))}
|
|
154
|
-
</div>
|
|
155
|
-
</div>
|
|
156
|
-
)}
|
|
157
|
-
</div>
|
|
158
|
-
))}
|
|
159
|
-
</div>
|
|
160
|
-
</div>
|
|
161
|
-
)
|
|
162
|
-
}
|