@winspan/claude-forge 8.41.0 → 8.50.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/CLAUDE.md +17 -0
- package/.eslintrc.js +23 -0
- package/.prettierrc +8 -0
- package/ARCHITECTURE_ISSUES.md +249 -0
- package/CLAUDE.md +265 -0
- package/CLAUDE.md.backup +488 -0
- package/DEVELOPMENT.md +310 -0
- package/dist/claudemd/claudemd-generator.d.ts +38 -3
- package/dist/claudemd/claudemd-generator.d.ts.map +1 -1
- package/dist/claudemd/claudemd-generator.js +629 -11
- package/dist/claudemd/claudemd-generator.js.map +1 -1
- package/dist/claudemd/index.d.ts +2 -2
- package/dist/claudemd/index.d.ts.map +1 -1
- package/dist/claudemd/index.js.map +1 -1
- package/dist/claudemd/resume-manager.d.ts.map +1 -1
- package/dist/claudemd/resume-manager.js +5 -2
- package/dist/claudemd/resume-manager.js.map +1 -1
- package/dist/claudemd/tech-detector.d.ts +1 -0
- package/dist/claudemd/tech-detector.d.ts.map +1 -1
- package/dist/claudemd/tech-detector.js +53 -0
- package/dist/claudemd/tech-detector.js.map +1 -1
- package/dist/cli/commands/claudemd.js +2 -2
- package/dist/cli/commands/claudemd.js.map +1 -1
- package/dist/cli/commands/daemon.d.ts +28 -0
- package/dist/cli/commands/daemon.d.ts.map +1 -1
- package/dist/cli/commands/daemon.js +200 -8
- package/dist/cli/commands/daemon.js.map +1 -1
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/init.js +3 -35
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/commands/menu.js +10 -10
- package/dist/cli/commands/menu.js.map +1 -1
- package/dist/cli/commands/skills.d.ts.map +1 -1
- package/dist/cli/commands/skills.js +8 -2
- package/dist/cli/commands/skills.js.map +1 -1
- package/dist/cli/commands/stats.d.ts.map +1 -1
- package/dist/cli/commands/stats.js +0 -17
- package/dist/cli/commands/stats.js.map +1 -1
- package/dist/cli/commands/trace.d.ts +9 -0
- package/dist/cli/commands/trace.d.ts.map +1 -0
- package/dist/cli/commands/trace.js +137 -0
- package/dist/cli/commands/trace.js.map +1 -0
- package/dist/cli/index.js +2 -4
- package/dist/cli/index.js.map +1 -1
- package/dist/core/ai/provider.d.ts +10 -2
- package/dist/core/ai/provider.d.ts.map +1 -1
- package/dist/core/ai/provider.js.map +1 -1
- package/dist/core/ai/types.d.ts +1 -19
- package/dist/core/ai/types.d.ts.map +1 -1
- package/dist/core/ai/types.js +1 -1
- package/dist/core/config.d.ts +2 -1
- package/dist/core/config.d.ts.map +1 -1
- package/dist/core/config.js +23 -6
- package/dist/core/config.js.map +1 -1
- package/dist/core/constants.d.ts +2 -2
- package/dist/core/constants.js +2 -2
- package/dist/core/constants.js.map +1 -1
- package/dist/core/queue/index.d.ts +52 -0
- package/dist/core/queue/index.d.ts.map +1 -0
- package/dist/core/queue/index.js +176 -0
- package/dist/core/queue/index.js.map +1 -0
- package/dist/core/storage/base.d.ts +33 -0
- package/dist/core/storage/base.d.ts.map +1 -0
- package/dist/core/storage/base.js +211 -0
- package/dist/core/storage/base.js.map +1 -0
- package/dist/core/storage/events.d.ts +52 -0
- package/dist/core/storage/events.d.ts.map +1 -0
- package/dist/core/storage/events.js +201 -0
- package/dist/core/storage/events.js.map +1 -0
- package/dist/core/storage/injections.d.ts +27 -0
- package/dist/core/storage/injections.d.ts.map +1 -0
- package/dist/core/storage/injections.js +51 -0
- package/dist/core/storage/injections.js.map +1 -0
- package/dist/core/storage/maintenance.d.ts +21 -0
- package/dist/core/storage/maintenance.d.ts.map +1 -0
- package/dist/core/storage/maintenance.js +52 -0
- package/dist/core/storage/maintenance.js.map +1 -0
- package/dist/core/storage/routing.d.ts +71 -0
- package/dist/core/storage/routing.d.ts.map +1 -0
- package/dist/core/storage/routing.js +141 -0
- package/dist/core/storage/routing.js.map +1 -0
- package/dist/core/storage/rows.d.ts +0 -47
- package/dist/core/storage/rows.d.ts.map +1 -1
- package/dist/core/storage/schema.sql +74 -136
- package/dist/core/storage/sessions.d.ts +34 -0
- package/dist/core/storage/sessions.d.ts.map +1 -0
- package/dist/core/storage/sessions.js +78 -0
- package/dist/core/storage/sessions.js.map +1 -0
- package/dist/core/storage/skills.d.ts +40 -0
- package/dist/core/storage/skills.d.ts.map +1 -0
- package/dist/core/storage/skills.js +107 -0
- package/dist/core/storage/skills.js.map +1 -0
- package/dist/core/storage/sqlite.d.ts +63 -265
- package/dist/core/storage/sqlite.d.ts.map +1 -1
- package/dist/core/storage/sqlite.js +102 -759
- package/dist/core/storage/sqlite.js.map +1 -1
- package/dist/core/storage/tasks.d.ts +64 -0
- package/dist/core/storage/tasks.d.ts.map +1 -0
- package/dist/core/storage/tasks.js +134 -0
- package/dist/core/storage/tasks.js.map +1 -0
- package/dist/core/storage/token-usage.d.ts +36 -0
- package/dist/core/storage/token-usage.d.ts.map +1 -0
- package/dist/core/storage/token-usage.js +59 -0
- package/dist/core/storage/token-usage.js.map +1 -0
- package/dist/core/types.d.ts +60 -4
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js +24 -1
- package/dist/core/types.js.map +1 -1
- package/dist/core/utils/format.d.ts +28 -0
- package/dist/core/utils/format.d.ts.map +1 -0
- package/dist/core/utils/format.js +68 -0
- package/dist/core/utils/format.js.map +1 -0
- package/dist/core/utils/logger.d.ts +6 -1
- package/dist/core/utils/logger.d.ts.map +1 -1
- package/dist/core/utils/logger.js +72 -2
- package/dist/core/utils/logger.js.map +1 -1
- package/dist/core/utils/session.d.ts +16 -0
- package/dist/core/utils/session.d.ts.map +1 -0
- package/dist/core/utils/session.js +25 -0
- package/dist/core/utils/session.js.map +1 -0
- package/dist/core/utils/time.d.ts +22 -0
- package/dist/core/utils/time.d.ts.map +1 -0
- package/dist/core/utils/time.js +38 -0
- package/dist/core/utils/time.js.map +1 -0
- package/dist/daemon/handlers/history-exporter.d.ts.map +1 -1
- package/dist/daemon/handlers/history-exporter.js +6 -4
- package/dist/daemon/handlers/history-exporter.js.map +1 -1
- package/dist/daemon/handlers/post-tool-use.d.ts +5 -12
- package/dist/daemon/handlers/post-tool-use.d.ts.map +1 -1
- package/dist/daemon/handlers/post-tool-use.js +21 -79
- package/dist/daemon/handlers/post-tool-use.js.map +1 -1
- package/dist/daemon/handlers/stop.d.ts +24 -12
- package/dist/daemon/handlers/stop.d.ts.map +1 -1
- package/dist/daemon/handlers/stop.js +141 -42
- package/dist/daemon/handlers/stop.js.map +1 -1
- package/dist/daemon/handlers/user-prompt.d.ts +18 -19
- package/dist/daemon/handlers/user-prompt.d.ts.map +1 -1
- package/dist/daemon/handlers/user-prompt.js +103 -227
- package/dist/daemon/handlers/user-prompt.js.map +1 -1
- package/dist/daemon/index.d.ts +6 -2
- package/dist/daemon/index.d.ts.map +1 -1
- package/dist/daemon/index.js +76 -120
- package/dist/daemon/index.js.map +1 -1
- package/dist/daemon/launchd/com.claude-forge.daemon.plist.template +47 -0
- package/dist/daemon/launchd-installer.d.ts +61 -0
- package/dist/daemon/launchd-installer.d.ts.map +1 -0
- package/dist/daemon/launchd-installer.js +182 -0
- package/dist/daemon/launchd-installer.js.map +1 -0
- package/dist/daemon/lifecycle.d.ts +11 -0
- package/dist/daemon/lifecycle.d.ts.map +1 -1
- package/dist/daemon/lifecycle.js +44 -0
- package/dist/daemon/lifecycle.js.map +1 -1
- package/dist/daemon/router.d.ts +9 -2
- package/dist/daemon/router.d.ts.map +1 -1
- package/dist/daemon/router.js +27 -3
- package/dist/daemon/router.js.map +1 -1
- package/dist/daemon/server.d.ts.map +1 -1
- package/dist/daemon/server.js +6 -5
- package/dist/daemon/server.js.map +1 -1
- package/dist/daemon/services/anti-pattern-detector.d.ts +50 -0
- package/dist/daemon/services/anti-pattern-detector.d.ts.map +1 -0
- package/dist/daemon/services/anti-pattern-detector.js +357 -0
- package/dist/daemon/services/anti-pattern-detector.js.map +1 -0
- package/dist/daemon/services/drift-detector.d.ts +64 -0
- package/dist/daemon/services/drift-detector.d.ts.map +1 -0
- package/dist/daemon/services/drift-detector.js +201 -0
- package/dist/daemon/services/drift-detector.js.map +1 -0
- package/dist/{intelligence → daemon/services}/task-segmenter.d.ts +7 -1
- package/dist/daemon/services/task-segmenter.d.ts.map +1 -0
- package/dist/{intelligence → daemon/services}/task-segmenter.js +29 -6
- package/dist/daemon/services/task-segmenter.js.map +1 -0
- package/dist/daemon/services/weekly-report.d.ts +91 -0
- package/dist/daemon/services/weekly-report.d.ts.map +1 -0
- package/dist/daemon/services/weekly-report.js +327 -0
- package/dist/daemon/services/weekly-report.js.map +1 -0
- package/dist/hooks/hook-lib.sh +81 -0
- package/dist/hooks/notification.sh +7 -3
- package/dist/hooks/post-tool-use.sh +8 -4
- package/dist/hooks/pre-tool-use.sh +7 -4
- package/dist/hooks/stop.sh +1 -1
- package/dist/hooks/user-prompt-submit.sh +8 -9
- package/dist/mcp/server.d.ts +2 -2
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +71 -11
- package/dist/mcp/server.js.map +1 -1
- package/dist/skills/invocation-guard.d.ts +20 -0
- package/dist/skills/invocation-guard.d.ts.map +1 -1
- package/dist/skills/invocation-guard.js +63 -0
- package/dist/skills/invocation-guard.js.map +1 -1
- package/dist/skills/matcher.d.ts.map +1 -1
- package/dist/skills/matcher.js +12 -3
- package/dist/skills/matcher.js.map +1 -1
- package/dist/skills/official/code-simplifier.md +16 -0
- package/dist/skills/official/find-skills.md +23 -0
- package/dist/skills/official/official-api-design.md +17 -0
- package/dist/skills/official/official-architecture-decision.md +20 -0
- package/dist/skills/official/official-bmad.md +118 -0
- package/dist/skills/official/official-db-schema-design.md +16 -0
- package/dist/skills/official/official-debug.md +17 -0
- package/dist/skills/official/official-doc-driven.md +31 -0
- package/dist/skills/official/official-harness-engineering.md +108 -0
- package/dist/skills/official/official-performance-optimization.md +30 -0
- package/dist/skills/official/official-pr-review.md +35 -0
- package/dist/skills/official/official-release-checklist.md +30 -0
- package/dist/skills/official/official-security-hardening.md +26 -0
- package/dist/skills/official/official-spec-driven-design.md +31 -0
- package/dist/skills/official/planning-with-files.md +37 -0
- package/dist/skills/official/ui-ux-pro-max.md +18 -0
- package/dist/skills/official/webapp-testing.md +12 -0
- package/dist/skills/official-skills.d.ts +8 -4
- package/dist/skills/official-skills.d.ts.map +1 -1
- package/dist/skills/official-skills.js +48 -704
- package/dist/skills/official-skills.js.map +1 -1
- package/dist/skills/registry.d.ts +5 -0
- package/dist/skills/registry.d.ts.map +1 -1
- package/dist/skills/registry.js +48 -15
- package/dist/skills/registry.js.map +1 -1
- package/dist/skills/tools/pipeline-suggest.d.ts +30 -0
- package/dist/skills/tools/pipeline-suggest.d.ts.map +1 -0
- package/dist/skills/tools/pipeline-suggest.js +178 -0
- package/dist/skills/tools/pipeline-suggest.js.map +1 -0
- package/dist/web/routes/ai.d.ts.map +1 -1
- package/dist/web/routes/ai.js +16 -22
- package/dist/web/routes/ai.js.map +1 -1
- package/dist/web/routes/drift.d.ts +10 -0
- package/dist/web/routes/drift.d.ts.map +1 -0
- package/dist/web/routes/drift.js +21 -0
- package/dist/web/routes/drift.js.map +1 -0
- package/dist/web/routes/error-handler.d.ts +43 -0
- package/dist/web/routes/error-handler.d.ts.map +1 -0
- package/dist/web/routes/error-handler.js +99 -0
- package/dist/web/routes/error-handler.js.map +1 -0
- package/dist/web/routes/insights.d.ts +9 -0
- package/dist/web/routes/insights.d.ts.map +1 -0
- package/dist/web/routes/insights.js +34 -0
- package/dist/web/routes/insights.js.map +1 -0
- package/dist/web/routes/patch.js +2 -2
- package/dist/web/routes/patch.js.map +1 -1
- package/dist/web/routes/reports.d.ts +10 -0
- package/dist/web/routes/reports.d.ts.map +1 -0
- package/dist/web/routes/reports.js +27 -0
- package/dist/web/routes/reports.js.map +1 -0
- package/dist/web/routes/rules.d.ts +10 -3
- package/dist/web/routes/rules.d.ts.map +1 -1
- package/dist/web/routes/rules.js +80 -95
- package/dist/web/routes/rules.js.map +1 -1
- package/dist/web/routes/sessions.d.ts +1 -2
- package/dist/web/routes/sessions.d.ts.map +1 -1
- package/dist/web/routes/sessions.js +27 -39
- package/dist/web/routes/sessions.js.map +1 -1
- package/dist/web/routes/skill-stats.d.ts.map +1 -1
- package/dist/web/routes/skill-stats.js +38 -0
- package/dist/web/routes/skill-stats.js.map +1 -1
- package/dist/web/routes/skills.d.ts.map +1 -1
- package/dist/web/routes/skills.js +34 -0
- package/dist/web/routes/skills.js.map +1 -1
- package/dist/web/routes/stats.d.ts +7 -0
- package/dist/web/routes/stats.d.ts.map +1 -0
- package/dist/web/routes/stats.js +44 -0
- package/dist/web/routes/stats.js.map +1 -0
- package/dist/web/routes/status.js +1 -1
- package/dist/web/routes/status.js.map +1 -1
- package/dist/web/routes/tasks.d.ts +4 -0
- package/dist/web/routes/tasks.d.ts.map +1 -0
- package/dist/web/routes/tasks.js +181 -0
- package/dist/web/routes/tasks.js.map +1 -0
- package/dist/web/routes/trace.d.ts +10 -0
- package/dist/web/routes/trace.d.ts.map +1 -0
- package/dist/web/routes/trace.js +123 -0
- package/dist/web/routes/trace.js.map +1 -0
- package/dist/web/routes/types.d.ts +1 -14
- package/dist/web/routes/types.d.ts.map +1 -1
- package/dist/web/routes/types.js +8 -17
- package/dist/web/routes/types.js.map +1 -1
- package/dist/web/server.d.ts +1 -9
- package/dist/web/server.d.ts.map +1 -1
- package/dist/web/server.js +28 -28
- package/dist/web/server.js.map +1 -1
- package/dist/web/static/assets/AIConfig-BQCAQE9D.js +2 -0
- package/dist/web/static/assets/AIConfig-BQCAQE9D.js.map +1 -0
- package/dist/web/static/assets/Dashboard-D7Bo6Kan.js +2 -0
- package/dist/web/static/assets/Dashboard-D7Bo6Kan.js.map +1 -0
- package/dist/web/static/assets/{Drawer-DcU3ln98.js → Drawer-BeHRQxUS.js} +2 -2
- package/dist/web/static/assets/{Drawer-DcU3ln98.js.map → Drawer-BeHRQxUS.js.map} +1 -1
- package/dist/web/static/assets/Events-K_tCY2ti.js +2 -0
- package/dist/web/static/assets/Events-K_tCY2ti.js.map +1 -0
- package/dist/web/static/assets/Reports-BJCmBnc_.js +2 -0
- package/dist/web/static/assets/Reports-BJCmBnc_.js.map +1 -0
- package/dist/web/static/assets/SearchInput-BX2KhMkw.js +2 -0
- package/dist/web/static/assets/SearchInput-BX2KhMkw.js.map +1 -0
- package/dist/web/static/assets/SessionDetail-Bkr-kC7V.js +2 -0
- package/dist/web/static/assets/SessionDetail-Bkr-kC7V.js.map +1 -0
- package/dist/web/static/assets/Sessions-Chx9OCLH.js +2 -0
- package/dist/web/static/assets/Sessions-Chx9OCLH.js.map +1 -0
- package/dist/web/static/assets/Skills-O0GT1i7m.js +2 -0
- package/dist/web/static/assets/Skills-O0GT1i7m.js.map +1 -0
- package/dist/web/static/assets/TaskDetail-5SR8zGzv.js +2 -0
- package/dist/web/static/assets/TaskDetail-5SR8zGzv.js.map +1 -0
- package/dist/web/static/assets/Tasks-DCgDqvOZ.js +2 -0
- package/dist/web/static/assets/Tasks-DCgDqvOZ.js.map +1 -0
- package/dist/web/static/assets/export-L_VBD2p1.js +4 -0
- package/dist/web/static/assets/export-L_VBD2p1.js.map +1 -0
- package/dist/web/static/assets/index-D8AKj26b.css +1 -0
- package/dist/web/static/assets/index-DxIbmNmr.js +3 -0
- package/dist/web/static/assets/index-DxIbmNmr.js.map +1 -0
- package/dist/web/static/assets/{lucide-53bR2rki.js → lucide-fJlPI3H7.js} +68 -38
- package/dist/web/static/assets/lucide-fJlPI3H7.js.map +1 -0
- package/dist/web/static/assets/time-Bxuk0M-C.js +2 -0
- package/dist/web/static/assets/time-Bxuk0M-C.js.map +1 -0
- package/dist/web/static/index.html +3 -3
- package/docs/concurrent-agents.md +129 -0
- package/docs/design/architecture-review-20260516.md +232 -0
- package/docs/design/fix-skills-data-and-set-leak-spec-20260516-1300.md +219 -0
- package/docs/design/hook-failure-queue-spec-20260516-1530.md +204 -0
- package/docs/design/refactor-phase1-spec-20260515-1600.md +543 -0
- package/docs/design/refactor-phase2-spec-20260515-1700.md +424 -0
- package/docs/design/tasks-list-filter-pagination-spec-20260518-0930.md +208 -0
- package/docs/implementation/fix-skills-data-and-set-leak-changelog-20260516-1300.md +104 -0
- package/docs/implementation/hook-failure-queue-changelog-20260516-1530.md +196 -0
- package/docs/implementation/hotfix-daemon-event-reject-20260516-1430.md +56 -0
- package/docs/implementation/refactor-phase1-changelog-20260515-1630.md +354 -0
- package/docs/implementation/refactor-phase2-changelog-20260515-1705.md +421 -0
- package/docs/implementation/tasks-list-filter-pagination-changelog-20260518-0930.md +72 -0
- package/docs/reviews/claudemd-template-sync.md +54 -0
- package/docs/reviews/tasks-filter-pagination.md +80 -0
- package/docs/ruflo-learning-strategy.md +322 -0
- package/docs/skills-deduplication-analysis.md +83 -0
- package/docs/skills-multiformat-support.md +177 -0
- package/docs/skills-third-party.md +183 -0
- package/docs/testing/tasks-filter-pagination-test-report.md +86 -0
- package/forge +321 -0
- package/package.json +28 -62
- package/playwright.config.ts +40 -0
- package/scripts/demo-v2.ts +91 -0
- package/scripts/dev-daemon.sh +232 -0
- package/scripts/dev-web.ts +109 -0
- package/scripts/e2e-mcp-link.ts +423 -0
- package/scripts/e2e-methodology-quality.ts +253 -0
- package/scripts/e2e-routing.ts +456 -0
- package/scripts/e2e-user-methodology.ts +326 -0
- package/scripts/e2e-web-workflows.ts +299 -0
- package/scripts/migrate-legacy-to-dynamic.sql +108 -0
- package/scripts/regenerate-execution-docs.ts +116 -0
- package/scripts/sync-agent-skills.ts +193 -0
- package/scripts/test-hook.sh +71 -0
- package/scripts/verify-skill-loading.ts +62 -0
- package/src/claudemd/claudemd-generator.ts +777 -0
- package/src/claudemd/convention-extractor.ts +69 -0
- package/src/claudemd/index.ts +35 -0
- package/src/claudemd/persona-manager.ts +88 -0
- package/src/claudemd/resume-manager.ts +236 -0
- package/src/claudemd/tech-detector.ts +220 -0
- package/src/cli/commands/claudemd.ts +84 -0
- package/src/cli/commands/config.ts +46 -0
- package/src/cli/commands/daemon.ts +310 -0
- package/src/cli/commands/executions.ts +114 -0
- package/src/cli/commands/init.ts +204 -0
- package/src/cli/commands/logs.ts +181 -0
- package/src/cli/commands/mcp.ts +244 -0
- package/src/cli/commands/menu.ts +356 -0
- package/src/cli/commands/skills.ts +185 -0
- package/src/cli/commands/stats.ts +74 -0
- package/src/cli/commands/status.ts +69 -0
- package/src/cli/commands/template.ts +77 -0
- package/src/cli/commands/trace.ts +164 -0
- package/src/cli/index.ts +42 -0
- package/src/cli/init/hook-manager.ts +132 -0
- package/src/core/ai/provider.ts +308 -0
- package/src/core/ai/types.ts +51 -0
- package/src/core/config.ts +124 -0
- package/src/core/constants.ts +45 -0
- package/src/core/queue/index.ts +193 -0
- package/src/core/storage/base.ts +226 -0
- package/src/core/storage/events.ts +255 -0
- package/src/core/storage/injections.ts +78 -0
- package/src/core/storage/maintenance.ts +59 -0
- package/src/core/storage/migrations/002_add_skill_tracking.sql +6 -0
- package/src/core/storage/migrations/003_add_skill_invocations.sql +23 -0
- package/src/core/storage/performance-indexes.sql +23 -0
- package/src/core/storage/routing.ts +194 -0
- package/src/core/storage/rows.ts +112 -0
- package/src/core/storage/schema.sql +214 -0
- package/src/core/storage/sessions.ts +104 -0
- package/src/core/storage/skills.ts +164 -0
- package/src/core/storage/sqlite.ts +194 -0
- package/src/core/storage/tasks.ts +170 -0
- package/src/core/storage/token-usage.ts +93 -0
- package/src/core/types.ts +154 -0
- package/src/core/utils/error-handler.ts +256 -0
- package/src/core/utils/forge-resume-block.ts +74 -0
- package/src/core/utils/format.ts +69 -0
- package/src/core/utils/logger.ts +119 -0
- package/src/core/utils/lru-cache.ts +50 -0
- package/src/core/utils/path.ts +19 -0
- package/src/core/utils/session.ts +26 -0
- package/src/core/utils/time.ts +37 -0
- package/src/core/utils/token-tracker.ts +97 -0
- package/src/daemon/event-parser.ts +35 -0
- package/src/daemon/handlers/history-exporter.ts +117 -0
- package/src/daemon/handlers/post-tool-use.ts +50 -0
- package/src/daemon/handlers/stop.ts +215 -0
- package/src/daemon/handlers/user-prompt.ts +188 -0
- package/src/daemon/index.ts +278 -0
- package/src/daemon/launchd/com.claude-forge.daemon.plist.template +47 -0
- package/src/daemon/launchd-installer.ts +260 -0
- package/src/daemon/lifecycle.ts +128 -0
- package/src/daemon/router.ts +40 -0
- package/src/daemon/server.ts +209 -0
- package/src/daemon/services/anti-pattern-detector.ts +412 -0
- package/src/daemon/services/drift-detector.ts +232 -0
- package/src/daemon/services/task-segmenter.ts +112 -0
- package/src/daemon/services/weekly-report.ts +454 -0
- package/src/hooks/hook-lib.sh +81 -0
- package/src/hooks/notification.sh +35 -0
- package/src/hooks/post-tool-use.sh +61 -0
- package/src/hooks/pre-tool-use.sh +63 -0
- package/src/hooks/stop.sh +40 -0
- package/src/hooks/user-prompt-submit.sh +69 -0
- package/src/mcp/server.ts +322 -0
- package/src/skills/index.ts +2 -0
- package/src/skills/invocation-guard.ts +177 -0
- package/src/skills/matcher.ts +148 -0
- package/src/skills/official/code-simplifier.md +16 -0
- package/src/skills/official/find-skills.md +23 -0
- package/src/skills/official/official-api-design.md +17 -0
- package/src/skills/official/official-architecture-decision.md +20 -0
- package/src/skills/official/official-bmad.md +118 -0
- package/src/skills/official/official-db-schema-design.md +16 -0
- package/src/skills/official/official-debug.md +17 -0
- package/src/skills/official/official-doc-driven.md +31 -0
- package/src/skills/official/official-harness-engineering.md +108 -0
- package/src/skills/official/official-performance-optimization.md +30 -0
- package/src/skills/official/official-pr-review.md +35 -0
- package/src/skills/official/official-release-checklist.md +30 -0
- package/src/skills/official/official-security-hardening.md +26 -0
- package/src/skills/official/official-spec-driven-design.md +31 -0
- package/src/skills/official/planning-with-files.md +37 -0
- package/src/skills/official/ui-ux-pro-max.md +18 -0
- package/src/skills/official/webapp-testing.md +12 -0
- package/src/skills/official-skills.ts +89 -0
- package/src/skills/registry.ts +355 -0
- package/src/skills/semantic-matcher.ts +231 -0
- package/src/skills/tools/pipeline-suggest.ts +226 -0
- package/src/skills/tools/skill-invoke.ts +168 -0
- package/src/skills/tools/skill-list.ts +59 -0
- package/src/templates/go.yaml +53 -0
- package/src/templates/python.yaml +59 -0
- package/src/templates/react.yaml +55 -0
- package/src/templates/template-manager.ts +170 -0
- package/src/web/auth-middleware.ts +55 -0
- package/src/web/routes/ai.ts +204 -0
- package/src/web/routes/auth.ts +22 -0
- package/src/web/routes/drift.ts +25 -0
- package/src/web/routes/error-handler.ts +120 -0
- package/src/web/routes/events.ts +47 -0
- package/src/web/routes/insights.ts +43 -0
- package/src/web/routes/patch.ts +117 -0
- package/src/web/routes/reports.ts +34 -0
- package/src/web/routes/rules.ts +101 -0
- package/src/web/routes/sessions.ts +262 -0
- package/src/web/routes/skill-stats.ts +132 -0
- package/src/web/routes/skills.ts +349 -0
- package/src/web/routes/static.ts +67 -0
- package/src/web/routes/stats.ts +60 -0
- package/src/web/routes/status.ts +30 -0
- package/src/web/routes/tasks.ts +218 -0
- package/src/web/routes/token-usage.ts +20 -0
- package/src/web/routes/trace.ts +138 -0
- package/src/web/routes/types.ts +56 -0
- package/src/web/server.ts +134 -0
- package/src/web/ssrf-guard.ts +112 -0
- package/src/web/static/index.html +3251 -0
- package/src/web/static/vendor/chart.umd.min.js +20 -0
- package/tests/e2e/dashboard.spec.ts +205 -0
- package/tests/e2e/routing-skill-e2e.test.ts +39 -0
- package/tests/helpers/mock-ai.ts +92 -0
- package/tests/helpers/mock-storage.ts +159 -0
- package/tests/integration/queue-replay.integration.test.ts +193 -0
- package/tests/integration/tasks-filter.integration.test.ts +154 -0
- package/tests/performance/database.benchmark.ts +161 -0
- package/tests/semantic-matcher.test.ts +99 -0
- package/tests/skill-matcher.test.ts +110 -0
- package/tests/unit/ai-provider-retry.test.ts +194 -0
- package/tests/unit/ai-provider-vision.test.ts +224 -0
- package/tests/unit/claudemd-generator.test.ts +68 -0
- package/tests/unit/cli-mcp.test.ts +141 -0
- package/tests/unit/handlers.test.ts +171 -0
- package/tests/unit/invocation-guard.test.ts +125 -0
- package/tests/unit/queue.test.ts +272 -0
- package/tests/unit/router.test.ts +138 -0
- package/tests/unit/security.test.ts +128 -0
- package/tests/unit/skill-invocations-workflow.test.ts +495 -0
- package/tests/unit/skill-registry.test.ts +94 -0
- package/tests/unit/skills/invocation-guard-ttl.test.ts +211 -0
- package/tests/unit/skills/official-skills-loader.test.ts +126 -0
- package/tests/unit/skills/registry-multiformat.test.ts +92 -0
- package/tests/unit/storage/sessions-aggregate.test.ts +435 -0
- package/tests/unit/storage/sqlite-refactor-harness.test.ts +314 -0
- package/tests/unit/storage.test.ts +172 -0
- package/tests/unit/token-usage.test.ts +144 -0
- package/tests/unit/type-guards.test.ts +201 -0
- package/tests/unit/utils/format.test.ts +189 -0
- package/tests/unit/utils/session.test.ts +89 -0
- package/tests/unit/utils/time.test.ts +112 -0
- package/tests/unit/web/routes-auth.test.ts +93 -0
- package/tests/unit/web/routes-events.test.ts +101 -0
- package/tests/unit/web/routes-sessions.test.ts +181 -0
- package/tests/unit/web/routes-skill-stats.test.ts +179 -0
- package/tests/unit/web/routes-stats.test.ts +92 -0
- package/tests/unit/web/routes-tasks.test.ts +351 -0
- package/tsconfig.json +22 -0
- package/vitest.config.ts +21 -0
- package/vitest.integration.config.ts +16 -0
- package/web/CLAUDE.md +20 -0
- package/web/index.html +13 -0
- package/web/package-lock.json +4854 -0
- package/web/package.json +35 -0
- package/web/postcss.config.js +6 -0
- package/web/src/App.tsx +110 -0
- package/web/src/components/CodeBlock.tsx +31 -0
- package/web/src/components/Confirm.tsx +96 -0
- package/web/src/components/Drawer.tsx +60 -0
- package/web/src/components/Layout.tsx +145 -0
- package/web/src/components/MarkdownRenderer.tsx +77 -0
- package/web/src/components/SearchInput.tsx +31 -0
- package/web/src/components/SessionDetailContent.tsx +157 -0
- package/web/src/components/Toast.tsx +92 -0
- package/web/src/index.css +19 -0
- package/web/src/main.tsx +31 -0
- package/web/src/pages/AIConfig.tsx +233 -0
- package/web/src/pages/Dashboard.tsx +572 -0
- package/web/src/pages/Events.tsx +271 -0
- package/web/src/pages/Reports.tsx +428 -0
- package/web/src/pages/SessionDetail.tsx +162 -0
- package/web/src/pages/Sessions.tsx +205 -0
- package/web/src/pages/Skills.tsx +180 -0
- package/web/src/pages/TaskDetail.tsx +511 -0
- package/web/src/pages/Tasks.tsx +150 -0
- package/web/src/utils/auth.ts +59 -0
- package/web/src/utils/export.ts +54 -0
- package/web/src/utils/time.ts +13 -0
- package/web/tailwind.config.js +11 -0
- package/web/tsconfig.json +21 -0
- package/web/tsconfig.node.json +10 -0
- package/web/vite.config.ts +76 -0
- package/winspan-claude-forge-8.43.0.tgz +0 -0
- package/dist/agents/definition.d.ts +0 -62
- package/dist/agents/definition.d.ts.map +0 -1
- package/dist/agents/definition.js +0 -27
- package/dist/agents/definition.js.map +0 -1
- package/dist/agents/distributor.d.ts +0 -23
- package/dist/agents/distributor.d.ts.map +0 -1
- package/dist/agents/distributor.js +0 -85
- package/dist/agents/distributor.js.map +0 -1
- package/dist/agents/index.d.ts +0 -5
- package/dist/agents/index.d.ts.map +0 -1
- package/dist/agents/index.js +0 -5
- package/dist/agents/index.js.map +0 -1
- package/dist/agents/methodologies/agent-builder.d.ts +0 -21
- package/dist/agents/methodologies/agent-builder.d.ts.map +0 -1
- package/dist/agents/methodologies/agent-builder.js +0 -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
|
@@ -1,1018 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* ExecutionDocBuilder — 为每个路由生成 Agent/Skill 执行文档
|
|
3
|
-
*
|
|
4
|
-
* 触发时机:Stop hook 异步 tail(由 daemon 集成方调用)
|
|
5
|
-
* 输出位置:<projectPath>/.claude-forge/executions/
|
|
6
|
-
*
|
|
7
|
-
* 目录结构:
|
|
8
|
-
* <projectPath>/.claude-forge/executions/
|
|
9
|
-
* ├─ index.md 全局索引
|
|
10
|
-
* └─ by-route/
|
|
11
|
-
* └─ {route_request_id}/
|
|
12
|
-
* ├─ overview.md 路由概览 + 执行链路
|
|
13
|
-
* ├─ agent-{slug}.md Agent 执行文档
|
|
14
|
-
* └─ skill-{slug}-{seq}.md Skill 调用文档
|
|
15
|
-
*
|
|
16
|
-
* 数据流:
|
|
17
|
-
* session → routing_events (group by route_request_id)
|
|
18
|
-
* → events / v2_tool_events / skill_invocations / injections
|
|
19
|
-
* → 模板渲染 + AI 总结(可选)
|
|
20
|
-
* → 写入 md 文件
|
|
21
|
-
*/
|
|
22
|
-
import fs from 'node:fs';
|
|
23
|
-
import path from 'node:path';
|
|
24
|
-
import { logger } from '../core/utils/logger.js';
|
|
25
|
-
// ── 中文化映射(仅用于正文展示;frontmatter 仍使用英文 key 维持机器可读契约) ─────
|
|
26
|
-
/** TaskType → 中文标签(展示格式:`中文(英文)`) */
|
|
27
|
-
export const TASK_TYPE_CN = {
|
|
28
|
-
build_system: '搭建系统',
|
|
29
|
-
add_feature: '新增功能',
|
|
30
|
-
refactor: '重构代码',
|
|
31
|
-
migrate: '迁移代码',
|
|
32
|
-
fix_bug: '修复 Bug',
|
|
33
|
-
analyze_requirement: '需求分析',
|
|
34
|
-
design_architecture: '架构设计',
|
|
35
|
-
design_api: 'API 设计',
|
|
36
|
-
design_schema: 'Schema 设计',
|
|
37
|
-
write_code: '编写代码',
|
|
38
|
-
write_test: '编写测试',
|
|
39
|
-
review: '代码评审',
|
|
40
|
-
audit_security: '安全审计',
|
|
41
|
-
optimize_perf: '性能优化',
|
|
42
|
-
write_spec: '规范文档',
|
|
43
|
-
review_doc: '文档评审',
|
|
44
|
-
create_pr: '创建 PR',
|
|
45
|
-
explain: '代码解释',
|
|
46
|
-
setup_project: '项目初始化',
|
|
47
|
-
cleanup_code: '代码清理',
|
|
48
|
-
upgrade_dependency: '依赖升级',
|
|
49
|
-
improve_coverage: '提升覆盖率',
|
|
50
|
-
check_quality: '代码质量检查',
|
|
51
|
-
research: '技术调研',
|
|
52
|
-
investigate: '问题排查',
|
|
53
|
-
compare_solutions: '方案对比',
|
|
54
|
-
write_doc: '文档编写',
|
|
55
|
-
analyze_codebase: '代码库分析',
|
|
56
|
-
multi_domain: '跨领域任务',
|
|
57
|
-
other: '其他任务',
|
|
58
|
-
};
|
|
59
|
-
/** Complexity → 中文标签 */
|
|
60
|
-
export const COMPLEXITY_CN = {
|
|
61
|
-
simple: '简单',
|
|
62
|
-
moderate: '中等',
|
|
63
|
-
complex: '复杂',
|
|
64
|
-
};
|
|
65
|
-
/** ActionVerb → 中文标签(V2 字段,留作未来字段使用) */
|
|
66
|
-
export const ACTION_VERB_CN = {
|
|
67
|
-
investigate: '排查',
|
|
68
|
-
fix: '修复',
|
|
69
|
-
create: '创建',
|
|
70
|
-
modify: '修改',
|
|
71
|
-
delete: '删除',
|
|
72
|
-
verify: '验证',
|
|
73
|
-
explain: '解释',
|
|
74
|
-
setup: '配置',
|
|
75
|
-
migrate: '迁移',
|
|
76
|
-
research: '调研',
|
|
77
|
-
};
|
|
78
|
-
/** routed_to_type → 显示标签(仅做首字母大写 + 中文兜底) */
|
|
79
|
-
const ROUTED_TO_TYPE_CN = {
|
|
80
|
-
agent: 'Agent',
|
|
81
|
-
skill: 'Skill',
|
|
82
|
-
none: '未路由',
|
|
83
|
-
};
|
|
84
|
-
/**
|
|
85
|
-
* 从 `by-route/<routeId>/(overview|agent-*|skill-*).md` 返回索引的相对路径。
|
|
86
|
-
* `executions/by-route/<routeId>/x.md` → `executions/index.md` = `../../index.md`。
|
|
87
|
-
*/
|
|
88
|
-
const BACK_TO_INDEX_LINK = '> [← 返回索引](../../index.md)';
|
|
89
|
-
const DEFAULT_AI_TIMEOUT_MS = 15_000;
|
|
90
|
-
const MAX_AI_SUMMARY_CHARS = 600;
|
|
91
|
-
const MAX_TIMELINE_ROWS = 30;
|
|
92
|
-
const MAX_BASH_COMMANDS = 10;
|
|
93
|
-
const MAX_FILE_CHANGES = 30;
|
|
94
|
-
export class ExecutionDocBuilder {
|
|
95
|
-
storage;
|
|
96
|
-
ai;
|
|
97
|
-
constructor(storage, ai = null) {
|
|
98
|
-
this.storage = storage;
|
|
99
|
-
this.ai = ai;
|
|
100
|
-
}
|
|
101
|
-
/**
|
|
102
|
-
* 为指定 session 的所有路由生成执行文档。
|
|
103
|
-
* 失败时记录 warn 不抛异常,避免阻塞 hook。
|
|
104
|
-
*/
|
|
105
|
-
async build(sessionId, projectPath) {
|
|
106
|
-
try {
|
|
107
|
-
const baseDir = path.join(projectPath, '.claude-forge', 'executions');
|
|
108
|
-
const byRouteDir = path.join(baseDir, 'by-route');
|
|
109
|
-
fs.mkdirSync(byRouteDir, { recursive: true });
|
|
110
|
-
const routes = this.storage.queryRoutingEvents({
|
|
111
|
-
session_id: sessionId,
|
|
112
|
-
limit: 100,
|
|
113
|
-
});
|
|
114
|
-
if (routes.length === 0) {
|
|
115
|
-
logger.debug(`[ExecutionDoc] No routes for session ${sessionId}`);
|
|
116
|
-
return;
|
|
117
|
-
}
|
|
118
|
-
let generated = 0;
|
|
119
|
-
for (const route of routes) {
|
|
120
|
-
if (!route.route_request_id)
|
|
121
|
-
continue;
|
|
122
|
-
try {
|
|
123
|
-
await this.buildForRoute(route, byRouteDir);
|
|
124
|
-
generated++;
|
|
125
|
-
}
|
|
126
|
-
catch (err) {
|
|
127
|
-
logger.warn(`[ExecutionDoc] Failed to build route ${route.route_request_id}: ${err}`);
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
this.updateIndex(baseDir);
|
|
131
|
-
logger.info(`[ExecutionDoc] Generated ${generated} route document(s) for session ${sessionId}`);
|
|
132
|
-
}
|
|
133
|
-
catch (err) {
|
|
134
|
-
logger.warn(`[ExecutionDoc] Failed to build: ${err}`);
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
// ── Per-route orchestration ───────────────────────────────────────────
|
|
138
|
-
async buildForRoute(route, byRouteDir) {
|
|
139
|
-
const routeId = route.route_request_id;
|
|
140
|
-
const routeDir = path.join(byRouteDir, this.safeDirName(routeId));
|
|
141
|
-
fs.mkdirSync(routeDir, { recursive: true });
|
|
142
|
-
// Query associated data
|
|
143
|
-
const events = this.storage.queryEvents({
|
|
144
|
-
session_id: route.session_id,
|
|
145
|
-
limit: 1000,
|
|
146
|
-
});
|
|
147
|
-
const toolEvents = this.queryToolEventsByRoute(routeId);
|
|
148
|
-
const skillInvocations = this.safeQuerySkillInvocations(routeId);
|
|
149
|
-
// Agent document
|
|
150
|
-
if (route.routed_to_type === 'agent' && route.routed_to_name) {
|
|
151
|
-
const agentMd = await this.renderAgentExecution(route, events, toolEvents, skillInvocations);
|
|
152
|
-
const agentFile = path.join(routeDir, `agent-${this.slug(route.routed_to_name)}.md`);
|
|
153
|
-
fs.writeFileSync(agentFile, agentMd, 'utf-8');
|
|
154
|
-
}
|
|
155
|
-
// Skill documents
|
|
156
|
-
skillInvocations.forEach((inv, idx) => {
|
|
157
|
-
const skillMd = this.renderSkillExecution(inv, route);
|
|
158
|
-
const seq = String(idx + 1).padStart(2, '0');
|
|
159
|
-
const skillFile = path.join(routeDir, `skill-${this.slug(inv.skill_id)}-${seq}.md`);
|
|
160
|
-
fs.writeFileSync(skillFile, skillMd, 'utf-8');
|
|
161
|
-
});
|
|
162
|
-
// Overview
|
|
163
|
-
if (route.routed_to_name || skillInvocations.length > 0) {
|
|
164
|
-
const overviewMd = this.renderOverview(route, skillInvocations);
|
|
165
|
-
fs.writeFileSync(path.join(routeDir, 'overview.md'), overviewMd, 'utf-8');
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
// ── Queries ───────────────────────────────────────────────────────────
|
|
169
|
-
queryToolEventsByRoute(routeRequestId) {
|
|
170
|
-
try {
|
|
171
|
-
const db = this.storage.getDatabase();
|
|
172
|
-
return db
|
|
173
|
-
.prepare(`SELECT id, session_id, route_request_id, tool, args, result,
|
|
174
|
-
success, error, timestamp
|
|
175
|
-
FROM v2_tool_events
|
|
176
|
-
WHERE route_request_id = ?
|
|
177
|
-
ORDER BY timestamp ASC`)
|
|
178
|
-
.all(routeRequestId);
|
|
179
|
-
}
|
|
180
|
-
catch (err) {
|
|
181
|
-
logger.debug(`[ExecutionDoc] queryToolEvents failed: ${err}`);
|
|
182
|
-
return [];
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
safeQuerySkillInvocations(routeRequestId) {
|
|
186
|
-
try {
|
|
187
|
-
const rows = this.storage.querySkillInvocations({
|
|
188
|
-
route_request_id: routeRequestId,
|
|
189
|
-
limit: 100,
|
|
190
|
-
});
|
|
191
|
-
return [...rows].sort((a, b) => a.timestamp - b.timestamp);
|
|
192
|
-
}
|
|
193
|
-
catch (err) {
|
|
194
|
-
logger.debug(`[ExecutionDoc] querySkillInvocations failed: ${err}`);
|
|
195
|
-
return [];
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
// ── Agent execution rendering ─────────────────────────────────────────
|
|
199
|
-
async renderAgentExecution(route, events, toolEvents, skillInvocations) {
|
|
200
|
-
const agentName = route.routed_to_name ?? 'unknown';
|
|
201
|
-
const intent = this.safeJson(route.intent_json);
|
|
202
|
-
const taskType = intent?.taskType ?? 'unknown';
|
|
203
|
-
const complexity = intent?.complexity ?? 'unknown';
|
|
204
|
-
const verdict = this.verdictLabel(route);
|
|
205
|
-
const durationMs = route.total_execution_ms ?? null;
|
|
206
|
-
const shortId = this.shortRouteId(route.route_request_id);
|
|
207
|
-
const postUseEvents = events.filter(e => e.hook_type === 'PostToolUse');
|
|
208
|
-
const toolCounts = this.countTools(postUseEvents);
|
|
209
|
-
const toolCountsLine = this.formatToolCounts(toolCounts);
|
|
210
|
-
const timelineRows = this.buildTimelineRows(postUseEvents);
|
|
211
|
-
const fileChanges = this.extractFileChanges(postUseEvents);
|
|
212
|
-
const bashCommands = this.extractBashCommands(postUseEvents);
|
|
213
|
-
const startedAt = new Date(route.ts).toISOString();
|
|
214
|
-
const completedAt = route.completed_ts
|
|
215
|
-
? new Date(route.completed_ts).toISOString()
|
|
216
|
-
: '';
|
|
217
|
-
const aiSummary = await this.tryGenerateSummary({
|
|
218
|
-
agentName,
|
|
219
|
-
prompt: route.prompt,
|
|
220
|
-
toolCounts,
|
|
221
|
-
fileChanges,
|
|
222
|
-
skillInvocations,
|
|
223
|
-
events: postUseEvents,
|
|
224
|
-
});
|
|
225
|
-
const errorCount = toolEvents.filter(t => t.success === 0).length;
|
|
226
|
-
// Frontmatter 保持英文:机器读取契约(不要改成中文 key)
|
|
227
|
-
const frontmatter = [
|
|
228
|
-
'---',
|
|
229
|
-
'type: agent_execution',
|
|
230
|
-
`agent_id: ${agentName}`,
|
|
231
|
-
`route_request_id: ${route.route_request_id}`,
|
|
232
|
-
`session_id: ${route.session_id}`,
|
|
233
|
-
`started_at: ${startedAt}`,
|
|
234
|
-
`completed_at: ${completedAt}`,
|
|
235
|
-
`duration_ms: ${durationMs ?? ''}`,
|
|
236
|
-
`verdict: ${verdict.key}`,
|
|
237
|
-
`tool_call_count: ${postUseEvents.length}`,
|
|
238
|
-
'---',
|
|
239
|
-
].join('\n');
|
|
240
|
-
const promptPreview = this.truncate(route.prompt, 100);
|
|
241
|
-
const taskTypeDisplay = this.taskTypeLabel(taskType);
|
|
242
|
-
const complexityDisplay = this.complexityLabel(complexity);
|
|
243
|
-
const body = [
|
|
244
|
-
`# Agent 执行 · ${agentName}`,
|
|
245
|
-
'',
|
|
246
|
-
BACK_TO_INDEX_LINK,
|
|
247
|
-
'',
|
|
248
|
-
`> 路由追踪 · [Web 查看](http://localhost:3721/trace?id=${shortId})`,
|
|
249
|
-
'',
|
|
250
|
-
'## 一、概览',
|
|
251
|
-
'',
|
|
252
|
-
'| 项 | 值 |',
|
|
253
|
-
'|---|---|',
|
|
254
|
-
`| 用户问题 | ${this.mdEscape(promptPreview)} |`,
|
|
255
|
-
`| 路由决策 | ${taskTypeDisplay} + ${complexityDisplay} → ${agentName} |`,
|
|
256
|
-
`| 是否遵守 | ${verdict.label} |`,
|
|
257
|
-
`| 耗时 | ${this.formatDurationHuman(durationMs)} |`,
|
|
258
|
-
`| 工具调用 | ${toolCountsLine || '(无)'} |`,
|
|
259
|
-
'',
|
|
260
|
-
'## 二、时间线',
|
|
261
|
-
'',
|
|
262
|
-
timelineRows.length > 0
|
|
263
|
-
? this.renderTimelineTable(timelineRows)
|
|
264
|
-
: '_本次路由未产生 PostToolUse 事件_',
|
|
265
|
-
'',
|
|
266
|
-
'## 三、输入参数',
|
|
267
|
-
'',
|
|
268
|
-
'### 原始 Prompt',
|
|
269
|
-
'',
|
|
270
|
-
'```',
|
|
271
|
-
route.prompt,
|
|
272
|
-
'```',
|
|
273
|
-
'',
|
|
274
|
-
'## 四、子任务调用',
|
|
275
|
-
'',
|
|
276
|
-
this.renderSkillInvocationsSection(skillInvocations),
|
|
277
|
-
'',
|
|
278
|
-
'## 五、产物清单',
|
|
279
|
-
'',
|
|
280
|
-
'### 文件改动',
|
|
281
|
-
fileChanges.length > 0
|
|
282
|
-
? fileChanges
|
|
283
|
-
.slice(0, MAX_FILE_CHANGES)
|
|
284
|
-
.map(f => `- ${this.fileActionLabel(f.action)} \`${f.path}\``)
|
|
285
|
-
.join('\n')
|
|
286
|
-
: '_无文件改动_',
|
|
287
|
-
'',
|
|
288
|
-
'### Bash 命令',
|
|
289
|
-
bashCommands.length > 0
|
|
290
|
-
? ['```bash', ...bashCommands.slice(0, MAX_BASH_COMMANDS), '```'].join('\n')
|
|
291
|
-
: '_无 Bash 命令_',
|
|
292
|
-
'',
|
|
293
|
-
'## 六、执行结果总结',
|
|
294
|
-
'',
|
|
295
|
-
aiSummary,
|
|
296
|
-
'',
|
|
297
|
-
'## 七、元数据',
|
|
298
|
-
'',
|
|
299
|
-
'| 项 | 值 |',
|
|
300
|
-
'|---|---|',
|
|
301
|
-
`| 工具事件数 | ${toolEvents.length} |`,
|
|
302
|
-
`| 错误次数 | ${errorCount} |`,
|
|
303
|
-
`| Skill 调用次数 | ${skillInvocations.length} |`,
|
|
304
|
-
'',
|
|
305
|
-
].join('\n');
|
|
306
|
-
return `${frontmatter}\n\n${body}`;
|
|
307
|
-
}
|
|
308
|
-
// ── Skill execution rendering ─────────────────────────────────────────
|
|
309
|
-
renderSkillExecution(inv, route) {
|
|
310
|
-
const invokedAt = new Date(inv.timestamp).toISOString();
|
|
311
|
-
// Frontmatter 保持英文:机器读取契约
|
|
312
|
-
const frontmatter = [
|
|
313
|
-
'---',
|
|
314
|
-
'type: skill_execution',
|
|
315
|
-
`skill_id: ${inv.skill_id}`,
|
|
316
|
-
`invocation_id: ${inv.id}`,
|
|
317
|
-
`route_request_id: ${inv.route_request_id ?? ''}`,
|
|
318
|
-
`session_id: ${inv.session_id}`,
|
|
319
|
-
`agent_id: ${inv.agent_id ?? ''}`,
|
|
320
|
-
`invocation_type: ${inv.invocation_type}`,
|
|
321
|
-
`invoked_at: ${invokedAt}`,
|
|
322
|
-
`success: ${inv.success === 1}`,
|
|
323
|
-
'---',
|
|
324
|
-
].join('\n');
|
|
325
|
-
const body = [
|
|
326
|
-
`# Skill 调用 · ${inv.skill_id}`,
|
|
327
|
-
'',
|
|
328
|
-
BACK_TO_INDEX_LINK,
|
|
329
|
-
'',
|
|
330
|
-
'## 一、调用上下文',
|
|
331
|
-
'',
|
|
332
|
-
'| 项 | 值 |',
|
|
333
|
-
'|---|---|',
|
|
334
|
-
`| Skill ID | \`${inv.skill_id}\` |`,
|
|
335
|
-
`| 调用类型 | ${this.skillInvocationTypeLabel(inv.invocation_type)} |`,
|
|
336
|
-
`| 发起者 | ${inv.agent_id ? `\`${inv.agent_id}\`` : '主 Claude'} |`,
|
|
337
|
-
`| 嵌套深度 | ${inv.depth} |`,
|
|
338
|
-
`| 调用时间 | ${this.formatDateTimeHuman(invokedAt)} |`,
|
|
339
|
-
`| 执行结果 | ${inv.success === 1 ? '✅ 成功' : '❌ 失败'} |`,
|
|
340
|
-
inv.error ? `| 错误信息 | ${this.mdEscape(inv.error)} |` : '',
|
|
341
|
-
'',
|
|
342
|
-
'## 二、Skill 内容概要',
|
|
343
|
-
'',
|
|
344
|
-
inv.reason
|
|
345
|
-
? this.truncate(inv.reason, 400)
|
|
346
|
-
: '_未记录调用理由_',
|
|
347
|
-
'',
|
|
348
|
-
'## 三、关联',
|
|
349
|
-
'',
|
|
350
|
-
`- 所属路由:\`${inv.route_request_id ?? 'N/A'}\``,
|
|
351
|
-
`- 发起 Agent:${route.routed_to_name ? `\`${route.routed_to_name}\`` : '_无(直接调用)_'}`,
|
|
352
|
-
'',
|
|
353
|
-
'## 四、元数据',
|
|
354
|
-
'',
|
|
355
|
-
'| 项 | 值 |',
|
|
356
|
-
'|---|---|',
|
|
357
|
-
`| 调用 ID | \`${inv.id}\` |`,
|
|
358
|
-
`| 会话 ID | \`${inv.session_id}\` |`,
|
|
359
|
-
`| 时间戳 | ${inv.timestamp} |`,
|
|
360
|
-
'',
|
|
361
|
-
]
|
|
362
|
-
.filter(line => line !== '')
|
|
363
|
-
.join('\n');
|
|
364
|
-
return `${frontmatter}\n\n${body}`;
|
|
365
|
-
}
|
|
366
|
-
// ── Overview rendering ──────────────────────────────────────────────────
|
|
367
|
-
renderOverview(route, skillInvocations) {
|
|
368
|
-
const routeId = route.route_request_id;
|
|
369
|
-
const shortId = this.shortRouteId(routeId);
|
|
370
|
-
const intent = this.safeJson(route.intent_json);
|
|
371
|
-
const taskType = intent?.taskType ?? 'unknown';
|
|
372
|
-
const complexity = intent?.complexity ?? 'unknown';
|
|
373
|
-
const verdict = this.verdictLabel(route);
|
|
374
|
-
const startedAt = new Date(route.ts).toISOString();
|
|
375
|
-
const completedAt = route.completed_ts
|
|
376
|
-
? new Date(route.completed_ts).toISOString()
|
|
377
|
-
: '';
|
|
378
|
-
// Frontmatter 保持英文:机器读取契约
|
|
379
|
-
// prompt 字段供 index 生成器读取(避免它再去解析 body 表格)
|
|
380
|
-
const frontmatter = [
|
|
381
|
-
'---',
|
|
382
|
-
'type: route_overview',
|
|
383
|
-
`route_request_id: ${routeId}`,
|
|
384
|
-
`session_id: ${route.session_id}`,
|
|
385
|
-
`started_at: ${startedAt}`,
|
|
386
|
-
`completed_at: ${completedAt}`,
|
|
387
|
-
`routed_to: ${route.routed_to_name ?? 'none'}`,
|
|
388
|
-
`verdict: ${verdict.key}`,
|
|
389
|
-
`prompt: ${this.frontmatterValue(route.prompt)}`,
|
|
390
|
-
'---',
|
|
391
|
-
].join('\n');
|
|
392
|
-
// 执行链路树
|
|
393
|
-
const treeLines = [];
|
|
394
|
-
treeLines.push(`[Router] ${taskType} + ${complexity}`);
|
|
395
|
-
if (route.routed_to_name) {
|
|
396
|
-
treeLines.push(` └─ [Agent] ${route.routed_to_name}`);
|
|
397
|
-
skillInvocations.forEach((inv, idx) => {
|
|
398
|
-
const prefix = idx === skillInvocations.length - 1 ? ' └─' : ' ├─';
|
|
399
|
-
const status = inv.success === 1 ? 'OK' : 'FAIL';
|
|
400
|
-
treeLines.push(`${prefix} [Skill] ${inv.skill_id} (${status})`);
|
|
401
|
-
});
|
|
402
|
-
}
|
|
403
|
-
const taskTypeDisplay = this.taskTypeLabel(taskType);
|
|
404
|
-
const complexityDisplay = this.complexityLabel(complexity);
|
|
405
|
-
const routedToDisplay = this.routedToLabel(route.routed_to_type ?? null, route.routed_to_name ?? null);
|
|
406
|
-
const body = [
|
|
407
|
-
`# 路由概览 · ${shortId}`,
|
|
408
|
-
'',
|
|
409
|
-
BACK_TO_INDEX_LINK,
|
|
410
|
-
'',
|
|
411
|
-
`> [Web 查看](http://localhost:3721/trace?id=${shortId})`,
|
|
412
|
-
'',
|
|
413
|
-
'## 一、路由决策',
|
|
414
|
-
'',
|
|
415
|
-
'| 项 | 值 |',
|
|
416
|
-
'|---|---|',
|
|
417
|
-
`| 用户问题 | ${this.mdEscape(this.truncate(route.prompt, 80))} |`,
|
|
418
|
-
`| 任务类型 | ${taskTypeDisplay} |`,
|
|
419
|
-
`| 复杂度 | ${complexityDisplay} |`,
|
|
420
|
-
`| 路由目标 | ${routedToDisplay} |`,
|
|
421
|
-
`| 是否遵守 | ${verdict.label} |`,
|
|
422
|
-
`| 分类耗时 | ${this.formatDurationHuman(route.classification_ms ?? null)} |`,
|
|
423
|
-
`| 执行耗时 | ${this.formatDurationHuman(route.total_execution_ms ?? null)} |`,
|
|
424
|
-
'',
|
|
425
|
-
'## 二、执行链路',
|
|
426
|
-
'',
|
|
427
|
-
'```',
|
|
428
|
-
...treeLines,
|
|
429
|
-
'```',
|
|
430
|
-
'',
|
|
431
|
-
'## 三、产物',
|
|
432
|
-
'',
|
|
433
|
-
route.routed_to_name
|
|
434
|
-
? `- [Agent 执行文档](./agent-${this.slug(route.routed_to_name)}.md)`
|
|
435
|
-
: '_无 Agent 文档_',
|
|
436
|
-
...skillInvocations.map((inv, idx) => {
|
|
437
|
-
const seq = String(idx + 1).padStart(2, '0');
|
|
438
|
-
return `- [Skill:${inv.skill_id}](./skill-${this.slug(inv.skill_id)}-${seq}.md)`;
|
|
439
|
-
}),
|
|
440
|
-
'',
|
|
441
|
-
'## 四、相关文档',
|
|
442
|
-
'',
|
|
443
|
-
'- [全局索引](../../index.md)',
|
|
444
|
-
'',
|
|
445
|
-
].join('\n');
|
|
446
|
-
return `${frontmatter}\n\n${body}`;
|
|
447
|
-
}
|
|
448
|
-
// ── Index generation ──────────────────────────────────────────────────
|
|
449
|
-
/**
|
|
450
|
-
* 重写 index.md(人类友好视图)+ index-raw.md(原始技术视图)。
|
|
451
|
-
*
|
|
452
|
-
* 主索引为倒序:最新的执行排在最上面,列包含:
|
|
453
|
-
* - 倒序编号(# 列:最新条目数字最大,等于总数)
|
|
454
|
-
* - 时间(今天 HH:MM / 昨天 HH:MM / MM-DD HH:MM / YYYY-MM-DD HH:MM)
|
|
455
|
-
* - 任务描述(来自 overview.md frontmatter.prompt 或 body 中的 Prompt 行,截 40 字符)
|
|
456
|
-
* - 执行者(聚合 agent-*.md 文件名:单个/× N/最多列两个 +N)
|
|
457
|
-
* - 状态(基于 verdict 字段映射的中文标签)
|
|
458
|
-
* - 详情链接(相对路径)
|
|
459
|
-
*
|
|
460
|
-
* 容错策略:缺少 overview.md / frontmatter 解析失败 → 显示占位符,不中断生成。
|
|
461
|
-
*/
|
|
462
|
-
updateIndex(baseDir) {
|
|
463
|
-
const byRouteDir = path.join(baseDir, 'by-route');
|
|
464
|
-
if (!fs.existsSync(byRouteDir))
|
|
465
|
-
return;
|
|
466
|
-
const dirNames = fs
|
|
467
|
-
.readdirSync(byRouteDir, { withFileTypes: true })
|
|
468
|
-
.filter(d => d.isDirectory())
|
|
469
|
-
.map(d => d.name);
|
|
470
|
-
// 收集每条记录的元数据
|
|
471
|
-
const entries = dirNames.map(d => this.collectIndexEntry(byRouteDir, d));
|
|
472
|
-
// 按 started_at 降序(最新在前)
|
|
473
|
-
entries.sort((a, b) => b.startedAtMs - a.startedAtMs);
|
|
474
|
-
const now = Date.now();
|
|
475
|
-
const indexMd = this.renderIndexMd(entries, now);
|
|
476
|
-
fs.writeFileSync(path.join(baseDir, 'index.md'), indexMd, 'utf-8');
|
|
477
|
-
const rawIndexMd = this.renderRawIndexMd(entries, now);
|
|
478
|
-
fs.writeFileSync(path.join(baseDir, 'index-raw.md'), rawIndexMd, 'utf-8');
|
|
479
|
-
}
|
|
480
|
-
/** 从单个 routeId 目录收集索引所需的元数据 */
|
|
481
|
-
collectIndexEntry(byRouteDir, dirName) {
|
|
482
|
-
const dirPath = path.join(byRouteDir, dirName);
|
|
483
|
-
let files = [];
|
|
484
|
-
try {
|
|
485
|
-
files = fs.readdirSync(dirPath);
|
|
486
|
-
}
|
|
487
|
-
catch {
|
|
488
|
-
files = [];
|
|
489
|
-
}
|
|
490
|
-
// agent-<slug>.md → 提取 <slug> 作为执行者标识
|
|
491
|
-
const agents = files
|
|
492
|
-
.filter(f => f.startsWith('agent-') && f.endsWith('.md'))
|
|
493
|
-
.map(f => f.slice('agent-'.length, -'.md'.length));
|
|
494
|
-
let prompt = '';
|
|
495
|
-
let verdict = '';
|
|
496
|
-
let startedAtMs = this.fallbackStartedAtFromDirName(dirName);
|
|
497
|
-
let hasOverview = false;
|
|
498
|
-
const overviewPath = path.join(dirPath, 'overview.md');
|
|
499
|
-
if (fs.existsSync(overviewPath)) {
|
|
500
|
-
hasOverview = true;
|
|
501
|
-
try {
|
|
502
|
-
const content = fs.readFileSync(overviewPath, 'utf-8');
|
|
503
|
-
const fm = this.parseFrontmatter(content);
|
|
504
|
-
const startedAt = fm.started_at;
|
|
505
|
-
if (startedAt) {
|
|
506
|
-
const parsed = Date.parse(startedAt);
|
|
507
|
-
if (!Number.isNaN(parsed))
|
|
508
|
-
startedAtMs = parsed;
|
|
509
|
-
}
|
|
510
|
-
verdict = fm.verdict ?? '';
|
|
511
|
-
// 优先用 frontmatter 中的 prompt(Agent B 可能后续加入)
|
|
512
|
-
if (fm.prompt) {
|
|
513
|
-
prompt = fm.prompt;
|
|
514
|
-
}
|
|
515
|
-
else {
|
|
516
|
-
prompt = this.extractPromptFromBody(content);
|
|
517
|
-
}
|
|
518
|
-
}
|
|
519
|
-
catch (err) {
|
|
520
|
-
logger.debug(`[ExecutionDoc] parse overview failed for ${dirName}: ${err}`);
|
|
521
|
-
}
|
|
522
|
-
}
|
|
523
|
-
return { dirName, startedAtMs, prompt, verdict, agents, files, hasOverview };
|
|
524
|
-
}
|
|
525
|
-
/** 兜底:当 overview.md 缺失时,从目录名 `<uuid>:<unix_ms>` 中解析时间 */
|
|
526
|
-
fallbackStartedAtFromDirName(dirName) {
|
|
527
|
-
const parts = dirName.split(':');
|
|
528
|
-
if (parts.length >= 2) {
|
|
529
|
-
const tail = parts[parts.length - 1];
|
|
530
|
-
const ts = parseInt(tail, 10);
|
|
531
|
-
if (!Number.isNaN(ts) && ts > 0)
|
|
532
|
-
return ts;
|
|
533
|
-
}
|
|
534
|
-
return 0;
|
|
535
|
-
}
|
|
536
|
-
/** 简化版 YAML frontmatter 解析(key: value 单行格式) */
|
|
537
|
-
parseFrontmatter(content) {
|
|
538
|
-
const m = content.match(/^---\r?\n([\s\S]*?)\r?\n---/);
|
|
539
|
-
if (!m)
|
|
540
|
-
return {};
|
|
541
|
-
const result = {};
|
|
542
|
-
for (const line of m[1].split(/\r?\n/)) {
|
|
543
|
-
const idx = line.indexOf(':');
|
|
544
|
-
if (idx === -1)
|
|
545
|
-
continue;
|
|
546
|
-
const key = line.slice(0, idx).trim();
|
|
547
|
-
const value = line.slice(idx + 1).trim();
|
|
548
|
-
if (key)
|
|
549
|
-
result[key] = value;
|
|
550
|
-
}
|
|
551
|
-
return result;
|
|
552
|
-
}
|
|
553
|
-
/** 当 frontmatter 没有 prompt 时,从 body 的 "| Prompt | ... |" 行兜底提取 */
|
|
554
|
-
extractPromptFromBody(content) {
|
|
555
|
-
const body = content.replace(/^---\r?\n[\s\S]*?\r?\n---\r?\n?/, '');
|
|
556
|
-
const match = body.match(/^\|\s*Prompt\s*\|\s*([^|]*?)\s*\|/m);
|
|
557
|
-
return match ? match[1].trim() : '';
|
|
558
|
-
}
|
|
559
|
-
/** 渲染主索引(人类友好视图) */
|
|
560
|
-
renderIndexMd(entries, nowMs) {
|
|
561
|
-
const lines = [
|
|
562
|
-
'# 执行记录',
|
|
563
|
-
'',
|
|
564
|
-
`> 生成时间: ${this.formatGenerationTime(nowMs)} · 共 ${entries.length} 次任务执行`,
|
|
565
|
-
'',
|
|
566
|
-
];
|
|
567
|
-
if (entries.length === 0) {
|
|
568
|
-
lines.push('_暂无执行记录_', '');
|
|
569
|
-
return lines.join('\n');
|
|
570
|
-
}
|
|
571
|
-
lines.push('| # | 时间 | 任务描述 | 执行者 | 状态 | 详情 |', '|---|---|---|---|---|---|');
|
|
572
|
-
entries.forEach((e, idx) => {
|
|
573
|
-
const seq = entries.length - idx; // 倒序编号,最新对应总数
|
|
574
|
-
const time = this.formatIndexTime(e.startedAtMs, nowMs);
|
|
575
|
-
const desc = this.truncatePromptForIndex(e.prompt, 40);
|
|
576
|
-
const agents = this.formatAgentList(e.agents);
|
|
577
|
-
const status = this.mapVerdictToStatus(e.verdict, e.hasOverview);
|
|
578
|
-
const link = `[打开](by-route/${encodeURI(e.dirName)}/)`;
|
|
579
|
-
lines.push(`| ${seq} | ${time} | ${this.mdEscape(desc)} | ${this.mdEscape(agents)} | ${status} | ${link} |`);
|
|
580
|
-
});
|
|
581
|
-
lines.push('', '> 提示:原始技术视图(routeId + 文件列表)见 [index-raw.md](./index-raw.md)', '');
|
|
582
|
-
return lines.join('\n');
|
|
583
|
-
}
|
|
584
|
-
/** 渲染原始技术视图(保留 routeId + 文件列表,供系统/Agent 使用) */
|
|
585
|
-
renderRawIndexMd(entries, nowMs) {
|
|
586
|
-
const lines = [
|
|
587
|
-
'# Execution Documents Index (Raw)',
|
|
588
|
-
'',
|
|
589
|
-
`> 生成时间: ${new Date(nowMs).toISOString()}`,
|
|
590
|
-
'',
|
|
591
|
-
`共 ${entries.length} 个路由执行记录(按 started_at 降序)。`,
|
|
592
|
-
'',
|
|
593
|
-
'| # | Route ID | 开始时间 | 文件 |',
|
|
594
|
-
'|---|---|---|---|',
|
|
595
|
-
];
|
|
596
|
-
entries.forEach((e, idx) => {
|
|
597
|
-
const seq = entries.length - idx;
|
|
598
|
-
const fileList = e.files.map(f => `\`${f}\``).join(', ') || '(空)';
|
|
599
|
-
const startedAt = e.startedAtMs > 0 ? new Date(e.startedAtMs).toISOString() : '-';
|
|
600
|
-
lines.push(`| ${seq} | \`${e.dirName}\` | ${startedAt} | ${fileList} |`);
|
|
601
|
-
});
|
|
602
|
-
lines.push('');
|
|
603
|
-
return lines.join('\n');
|
|
604
|
-
}
|
|
605
|
-
/** 索引头部生成时间:YYYY-MM-DD HH:MM */
|
|
606
|
-
formatGenerationTime(ms) {
|
|
607
|
-
const d = new Date(ms);
|
|
608
|
-
return (`${d.getFullYear()}-${this.pad2(d.getMonth() + 1)}-${this.pad2(d.getDate())} ` +
|
|
609
|
-
`${this.pad2(d.getHours())}:${this.pad2(d.getMinutes())}`);
|
|
610
|
-
}
|
|
611
|
-
/** 列表中的时间格式:今天/昨天/本年/跨年四档 */
|
|
612
|
-
formatIndexTime(startedAtMs, nowMs) {
|
|
613
|
-
if (startedAtMs <= 0)
|
|
614
|
-
return '—';
|
|
615
|
-
const d = new Date(startedAtMs);
|
|
616
|
-
const now = new Date(nowMs);
|
|
617
|
-
const sameYMD = (a, b) => a.getFullYear() === b.getFullYear() &&
|
|
618
|
-
a.getMonth() === b.getMonth() &&
|
|
619
|
-
a.getDate() === b.getDate();
|
|
620
|
-
if (sameYMD(d, now)) {
|
|
621
|
-
return `${this.pad2(d.getHours())}:${this.pad2(d.getMinutes())}`;
|
|
622
|
-
}
|
|
623
|
-
const yesterday = new Date(now.getTime());
|
|
624
|
-
yesterday.setDate(yesterday.getDate() - 1);
|
|
625
|
-
if (sameYMD(d, yesterday)) {
|
|
626
|
-
return `昨天 ${this.pad2(d.getHours())}:${this.pad2(d.getMinutes())}`;
|
|
627
|
-
}
|
|
628
|
-
if (d.getFullYear() === now.getFullYear()) {
|
|
629
|
-
return (`${this.pad2(d.getMonth() + 1)}-${this.pad2(d.getDate())} ` +
|
|
630
|
-
`${this.pad2(d.getHours())}:${this.pad2(d.getMinutes())}`);
|
|
631
|
-
}
|
|
632
|
-
return (`${d.getFullYear()}-${this.pad2(d.getMonth() + 1)}-${this.pad2(d.getDate())} ` +
|
|
633
|
-
`${this.pad2(d.getHours())}:${this.pad2(d.getMinutes())}`);
|
|
634
|
-
}
|
|
635
|
-
pad2(n) {
|
|
636
|
-
return n.toString().padStart(2, '0');
|
|
637
|
-
}
|
|
638
|
-
/**
|
|
639
|
-
* 任务描述清洗与截断。
|
|
640
|
-
* - 剥离系统消息标签(<task-notification>, <system-reminder>, <local-command-*>)
|
|
641
|
-
* 只保留标签内的实际任务内容;如果整段都是系统消息则降级到 "[系统通知]"
|
|
642
|
-
* - 移除常见 markdown 噪声([Image #N] 等)
|
|
643
|
-
* - 多行/多空白归一为单空格
|
|
644
|
-
* - 超过 maxLen 字符(基于 JS 字符串 length,对中文 1:1)→ 尾加 "..."
|
|
645
|
-
* - 空字符串 → "—"
|
|
646
|
-
*/
|
|
647
|
-
truncatePromptForIndex(text, maxLen) {
|
|
648
|
-
if (!text)
|
|
649
|
-
return '—';
|
|
650
|
-
let cleaned = text;
|
|
651
|
-
// 1. 识别系统消息:若整段以 <task-notification> 等系统标签开头,
|
|
652
|
-
// 标记为系统通知(这些不是真实用户输入,而是后台任务完成回调等)
|
|
653
|
-
const isSystemMessage = /^\s*<(task-notification|system-reminder|local-command-stdout|local-command-stderr)\b/i.test(cleaned);
|
|
654
|
-
if (isSystemMessage) {
|
|
655
|
-
// 尝试从 <summary> 或 <result> 标签提取人类可读摘要
|
|
656
|
-
const summaryMatch = cleaned.match(/<summary>([\s\S]*?)<\/summary>/i);
|
|
657
|
-
if (summaryMatch && summaryMatch[1].trim()) {
|
|
658
|
-
cleaned = `[系统] ${summaryMatch[1].trim()}`;
|
|
659
|
-
}
|
|
660
|
-
else {
|
|
661
|
-
return '[系统通知]';
|
|
662
|
-
}
|
|
663
|
-
}
|
|
664
|
-
// 2. 剥离 XML/HTML 风格标签内容(保留文本)
|
|
665
|
-
cleaned = cleaned.replace(/<[^>]+>/g, ' ');
|
|
666
|
-
// 3. 移除图片标记和空白归一
|
|
667
|
-
cleaned = cleaned
|
|
668
|
-
.replace(/\[Image\s*#?\d+\]/gi, '')
|
|
669
|
-
.replace(/\r?\n+/g, ' ')
|
|
670
|
-
.replace(/\s+/g, ' ')
|
|
671
|
-
.trim();
|
|
672
|
-
if (!cleaned)
|
|
673
|
-
return '—';
|
|
674
|
-
if (cleaned.length <= maxLen)
|
|
675
|
-
return cleaned;
|
|
676
|
-
return cleaned.slice(0, maxLen) + '...';
|
|
677
|
-
}
|
|
678
|
-
/**
|
|
679
|
-
* 执行者列表格式化:
|
|
680
|
-
* - 0 个 → "—"
|
|
681
|
-
* - 1 个 → "name"
|
|
682
|
-
* - 多个同名(理论上文件名不会重复,但兼容) → "name × N"
|
|
683
|
-
* - 2 个不同 → "a, b"
|
|
684
|
-
* - 多于 2 个不同 → "a, b, +N"
|
|
685
|
-
*/
|
|
686
|
-
formatAgentList(agents) {
|
|
687
|
-
if (agents.length === 0)
|
|
688
|
-
return '—';
|
|
689
|
-
const counts = new Map();
|
|
690
|
-
for (const a of agents) {
|
|
691
|
-
counts.set(a, (counts.get(a) ?? 0) + 1);
|
|
692
|
-
}
|
|
693
|
-
const entries = [...counts.entries()];
|
|
694
|
-
const render = ([name, c]) => c > 1 ? `${name} × ${c}` : name;
|
|
695
|
-
if (entries.length === 1)
|
|
696
|
-
return render(entries[0]);
|
|
697
|
-
if (entries.length <= 2)
|
|
698
|
-
return entries.map(render).join(', ');
|
|
699
|
-
const head = entries.slice(0, 2).map(render).join(', ');
|
|
700
|
-
const rest = entries.length - 2;
|
|
701
|
-
return `${head}, +${rest}`;
|
|
702
|
-
}
|
|
703
|
-
/** verdict → 状态展示标签 */
|
|
704
|
-
mapVerdictToStatus(verdict, hasOverview) {
|
|
705
|
-
if (!hasOverview)
|
|
706
|
-
return '❓ 未知';
|
|
707
|
-
switch (verdict) {
|
|
708
|
-
case 'obeyed':
|
|
709
|
-
case 'not_applicable':
|
|
710
|
-
return '✅ 已完成';
|
|
711
|
-
case 'disobeyed':
|
|
712
|
-
return '⚠️ 未遵守';
|
|
713
|
-
case 'timeout':
|
|
714
|
-
return '⏱️ 超时';
|
|
715
|
-
case 'pending':
|
|
716
|
-
return '🔄 进行中';
|
|
717
|
-
default:
|
|
718
|
-
return verdict ? `❓ ${verdict}` : '❓ 未知';
|
|
719
|
-
}
|
|
720
|
-
}
|
|
721
|
-
// ── AI summary ────────────────────────────────────────────────────────
|
|
722
|
-
async tryGenerateSummary(ctx) {
|
|
723
|
-
const fallback = this.buildFallbackSummary(ctx);
|
|
724
|
-
if (!this.ai)
|
|
725
|
-
return fallback;
|
|
726
|
-
try {
|
|
727
|
-
const eventsSummary = ctx.events
|
|
728
|
-
.slice(0, 40)
|
|
729
|
-
.map(e => `${e.tool_name ?? e.hook_type}`)
|
|
730
|
-
.join(', ');
|
|
731
|
-
const prompt = [
|
|
732
|
-
'基于以下 Agent 执行数据,用中文 100 字以内总结 Agent 做了什么。',
|
|
733
|
-
'只输出总结文本,不要加标题或前缀。',
|
|
734
|
-
'',
|
|
735
|
-
`Agent: ${ctx.agentName}`,
|
|
736
|
-
`用户请求: ${this.truncate(ctx.prompt, 200)}`,
|
|
737
|
-
`工具调用: ${eventsSummary}`,
|
|
738
|
-
`文件改动: ${ctx.fileChanges.map(f => `${f.action} ${f.path}`).join(', ') || '无'}`,
|
|
739
|
-
`Skill 调用: ${ctx.skillInvocations.map(s => s.skill_id).join(', ') || '无'}`,
|
|
740
|
-
].join('\n');
|
|
741
|
-
const result = await this.ai.complete(prompt, {
|
|
742
|
-
maxTokens: 256,
|
|
743
|
-
timeoutMs: DEFAULT_AI_TIMEOUT_MS,
|
|
744
|
-
});
|
|
745
|
-
return result.slice(0, MAX_AI_SUMMARY_CHARS) || fallback;
|
|
746
|
-
}
|
|
747
|
-
catch (err) {
|
|
748
|
-
logger.debug(`[ExecutionDoc] AI summary failed, using fallback: ${err}`);
|
|
749
|
-
return fallback;
|
|
750
|
-
}
|
|
751
|
-
}
|
|
752
|
-
buildFallbackSummary(ctx) {
|
|
753
|
-
const totalCalls = ctx.events.length;
|
|
754
|
-
const fileCount = ctx.fileChanges.length;
|
|
755
|
-
return `本次 ${ctx.agentName} 执行了 ${totalCalls} 个工具调用,涉及 ${fileCount} 个文件改动。`;
|
|
756
|
-
}
|
|
757
|
-
// ── Helper: timeline ──────────────────────────────────────────────────
|
|
758
|
-
buildTimelineRows(events) {
|
|
759
|
-
return events
|
|
760
|
-
.sort((a, b) => new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime())
|
|
761
|
-
.slice(0, MAX_TIMELINE_ROWS)
|
|
762
|
-
.map(e => {
|
|
763
|
-
const time = this.formatTime(e.timestamp);
|
|
764
|
-
const action = e.tool_name ?? e.hook_type;
|
|
765
|
-
const target = this.extractTarget(e);
|
|
766
|
-
return { time, action, target };
|
|
767
|
-
});
|
|
768
|
-
}
|
|
769
|
-
renderTimelineTable(rows) {
|
|
770
|
-
const header = '| 时间 | 动作 | 对象 |\n|---|---|---|';
|
|
771
|
-
const body = rows
|
|
772
|
-
.map(r => `| ${r.time} | ${r.action} | ${this.mdEscape(r.target)} |`)
|
|
773
|
-
.join('\n');
|
|
774
|
-
return `${header}\n${body}`;
|
|
775
|
-
}
|
|
776
|
-
// ── Helper: file changes & bash ───────────────────────────────────────
|
|
777
|
-
extractFileChanges(events) {
|
|
778
|
-
const changes = [];
|
|
779
|
-
for (const e of events) {
|
|
780
|
-
if (!e.tool_name || !e.tool_input)
|
|
781
|
-
continue;
|
|
782
|
-
if (e.tool_name === 'Edit' || e.tool_name === 'Write') {
|
|
783
|
-
const filePath = e.tool_input.file_path ??
|
|
784
|
-
e.tool_input.path ??
|
|
785
|
-
'';
|
|
786
|
-
if (filePath) {
|
|
787
|
-
changes.push({ action: e.tool_name, path: filePath });
|
|
788
|
-
}
|
|
789
|
-
}
|
|
790
|
-
}
|
|
791
|
-
return changes;
|
|
792
|
-
}
|
|
793
|
-
extractBashCommands(events) {
|
|
794
|
-
const commands = [];
|
|
795
|
-
for (const e of events) {
|
|
796
|
-
if (e.tool_name !== 'Bash' || !e.tool_input)
|
|
797
|
-
continue;
|
|
798
|
-
const cmd = e.tool_input.command ?? '';
|
|
799
|
-
if (cmd)
|
|
800
|
-
commands.push(cmd);
|
|
801
|
-
}
|
|
802
|
-
return commands;
|
|
803
|
-
}
|
|
804
|
-
// ── Helper: skill invocations section ─────────────────────────────────
|
|
805
|
-
renderSkillInvocationsSection(invocations) {
|
|
806
|
-
if (invocations.length === 0)
|
|
807
|
-
return '_无子任务调用_';
|
|
808
|
-
const header = '| # | Skill ID | 类型 | 结果 | 时间 |\n|---|---|---|---|---|';
|
|
809
|
-
const rows = invocations.map((inv, idx) => {
|
|
810
|
-
const status = inv.success === 1 ? '✅ 成功' : '❌ 失败';
|
|
811
|
-
const time = this.formatTime(new Date(inv.timestamp).toISOString());
|
|
812
|
-
const typeLabel = this.skillInvocationTypeLabel(inv.invocation_type);
|
|
813
|
-
return `| ${idx + 1} | \`${inv.skill_id}\` | ${typeLabel} | ${status} | ${time} |`;
|
|
814
|
-
});
|
|
815
|
-
return `${header}\n${rows.join('\n')}`;
|
|
816
|
-
}
|
|
817
|
-
// ── Utility methods ───────────────────────────────────────────────────
|
|
818
|
-
slug(name) {
|
|
819
|
-
return name
|
|
820
|
-
.toLowerCase()
|
|
821
|
-
.replace(/[^a-z0-9-]/g, '-')
|
|
822
|
-
.replace(/-+/g, '-')
|
|
823
|
-
.slice(0, 32);
|
|
824
|
-
}
|
|
825
|
-
safeDirName(routeId) {
|
|
826
|
-
return routeId.replace(/[^a-zA-Z0-9_:-]/g, '_');
|
|
827
|
-
}
|
|
828
|
-
shortRouteId(routeId) {
|
|
829
|
-
// route_request_id format: "route:<uuid>" or just a uuid
|
|
830
|
-
const parts = routeId.split(':');
|
|
831
|
-
const uuid = parts.length > 1 ? parts[1] : parts[0];
|
|
832
|
-
return uuid.slice(0, 8);
|
|
833
|
-
}
|
|
834
|
-
verdictLabel(route) {
|
|
835
|
-
if (!route.routed_to_name)
|
|
836
|
-
return { key: 'not_applicable', label: '— 不适用' };
|
|
837
|
-
if (route.obeyed === 1)
|
|
838
|
-
return { key: 'obeyed', label: '✅ 已遵守' };
|
|
839
|
-
if (route.obeyed === 0)
|
|
840
|
-
return { key: 'disobeyed', label: '❌ 未遵守' };
|
|
841
|
-
if (route.completion_reason === 'timeout')
|
|
842
|
-
return { key: 'timeout', label: '⏱️ 超时' };
|
|
843
|
-
return { key: 'pending', label: '🔄 待判定' };
|
|
844
|
-
}
|
|
845
|
-
countTools(events) {
|
|
846
|
-
const counts = new Map();
|
|
847
|
-
for (const e of events) {
|
|
848
|
-
if (e.tool_name) {
|
|
849
|
-
counts.set(e.tool_name, (counts.get(e.tool_name) ?? 0) + 1);
|
|
850
|
-
}
|
|
851
|
-
}
|
|
852
|
-
return counts;
|
|
853
|
-
}
|
|
854
|
-
formatToolCounts(counts) {
|
|
855
|
-
if (counts.size === 0)
|
|
856
|
-
return '';
|
|
857
|
-
return [...counts.entries()]
|
|
858
|
-
.sort((a, b) => b[1] - a[1])
|
|
859
|
-
.map(([tool, count]) => `${tool}x${count}`)
|
|
860
|
-
.join(' / ');
|
|
861
|
-
}
|
|
862
|
-
formatDuration(ms) {
|
|
863
|
-
if (ms === null)
|
|
864
|
-
return '-';
|
|
865
|
-
if (ms < 1000)
|
|
866
|
-
return `${ms}ms`;
|
|
867
|
-
if (ms < 60_000)
|
|
868
|
-
return `${(ms / 1000).toFixed(1)}s`;
|
|
869
|
-
return `${(ms / 60_000).toFixed(1)}min`;
|
|
870
|
-
}
|
|
871
|
-
/**
|
|
872
|
-
* 人性化耗时:
|
|
873
|
-
* - null/<=0 → "—"
|
|
874
|
-
* - < 1s → "<1 秒"
|
|
875
|
-
* - < 60s → "X.X 秒"(一位小数,整秒去掉 .0)
|
|
876
|
-
* - < 60min → "X 分 Y 秒"(整分钟省略秒部分)
|
|
877
|
-
* - >= 60min → "X 小时 Y 分"
|
|
878
|
-
*/
|
|
879
|
-
formatDurationHuman(ms) {
|
|
880
|
-
if (ms === null || ms <= 0)
|
|
881
|
-
return '—';
|
|
882
|
-
if (ms < 1000)
|
|
883
|
-
return '<1 秒';
|
|
884
|
-
if (ms < 60_000) {
|
|
885
|
-
const secs = ms / 1000;
|
|
886
|
-
const rounded = Math.round(secs * 10) / 10;
|
|
887
|
-
const display = Number.isInteger(rounded)
|
|
888
|
-
? rounded.toFixed(0)
|
|
889
|
-
: rounded.toFixed(1);
|
|
890
|
-
return `${display} 秒`;
|
|
891
|
-
}
|
|
892
|
-
if (ms < 3_600_000) {
|
|
893
|
-
const totalSec = Math.round(ms / 1000);
|
|
894
|
-
const mins = Math.floor(totalSec / 60);
|
|
895
|
-
const secs = totalSec % 60;
|
|
896
|
-
return secs === 0 ? `${mins} 分钟` : `${mins} 分 ${secs} 秒`;
|
|
897
|
-
}
|
|
898
|
-
const totalMin = Math.round(ms / 60_000);
|
|
899
|
-
const hours = Math.floor(totalMin / 60);
|
|
900
|
-
const mins = totalMin % 60;
|
|
901
|
-
return mins === 0 ? `${hours} 小时` : `${hours} 小时 ${mins} 分`;
|
|
902
|
-
}
|
|
903
|
-
/** TaskType 显示:`中文(英文)`,未知值原样返回。 */
|
|
904
|
-
taskTypeLabel(taskType) {
|
|
905
|
-
const cn = TASK_TYPE_CN[taskType];
|
|
906
|
-
return cn ? `${cn}(${taskType})` : taskType;
|
|
907
|
-
}
|
|
908
|
-
/** Complexity 显示:`中文(英文)`,未知值原样返回。 */
|
|
909
|
-
complexityLabel(complexity) {
|
|
910
|
-
const cn = COMPLEXITY_CN[complexity];
|
|
911
|
-
return cn ? `${cn}(${complexity})` : complexity;
|
|
912
|
-
}
|
|
913
|
-
/** 路由目标:`Agent → name` / `Skill → name` / `未路由`。 */
|
|
914
|
-
routedToLabel(type, name) {
|
|
915
|
-
if (!name)
|
|
916
|
-
return ROUTED_TO_TYPE_CN.none;
|
|
917
|
-
if (type === 'agent' || type === 'skill') {
|
|
918
|
-
return `${ROUTED_TO_TYPE_CN[type]} → ${name}`;
|
|
919
|
-
}
|
|
920
|
-
return name;
|
|
921
|
-
}
|
|
922
|
-
/** 文件改动动作:英文 → 中文动词。 */
|
|
923
|
-
fileActionLabel(action) {
|
|
924
|
-
if (action === 'Edit')
|
|
925
|
-
return '修改';
|
|
926
|
-
if (action === 'Write')
|
|
927
|
-
return '写入';
|
|
928
|
-
return action;
|
|
929
|
-
}
|
|
930
|
-
/**
|
|
931
|
-
* 人性化日期时间:`YYYY-MM-DD HH:mm:ss`(本地时区)
|
|
932
|
-
* 失败时回退到原值。
|
|
933
|
-
*/
|
|
934
|
-
formatDateTimeHuman(isoOrTs) {
|
|
935
|
-
try {
|
|
936
|
-
const d = new Date(isoOrTs);
|
|
937
|
-
if (Number.isNaN(d.getTime()))
|
|
938
|
-
return isoOrTs;
|
|
939
|
-
const pad = (n) => n.toString().padStart(2, '0');
|
|
940
|
-
return (`${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())} ` +
|
|
941
|
-
`${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}`);
|
|
942
|
-
}
|
|
943
|
-
catch {
|
|
944
|
-
return isoOrTs;
|
|
945
|
-
}
|
|
946
|
-
}
|
|
947
|
-
/**
|
|
948
|
-
* YAML frontmatter 单行字符串值(无引号,依赖 parseFrontmatter 的 indexOf(':') 切分):
|
|
949
|
-
* - 去除换行 / 多余空白(避免破坏行结构)
|
|
950
|
-
* - 去除前导 `---`(避免与 frontmatter 终止符歧义)
|
|
951
|
-
* - 不加引号 —— Agent A 的 parseFrontmatter 不做反引号处理
|
|
952
|
-
*
|
|
953
|
-
* 注意:若 prompt 很长,索引层会再做截断展示。
|
|
954
|
-
*/
|
|
955
|
-
frontmatterValue(text) {
|
|
956
|
-
const sanitized = text
|
|
957
|
-
.replace(/\r?\n+/g, ' ')
|
|
958
|
-
.replace(/\s+/g, ' ')
|
|
959
|
-
.replace(/^-{3,}/, '')
|
|
960
|
-
.trim();
|
|
961
|
-
return sanitized;
|
|
962
|
-
}
|
|
963
|
-
formatTime(isoOrTs) {
|
|
964
|
-
try {
|
|
965
|
-
const d = new Date(isoOrTs);
|
|
966
|
-
return d.toTimeString().slice(0, 8); // HH:mm:ss
|
|
967
|
-
}
|
|
968
|
-
catch {
|
|
969
|
-
return isoOrTs;
|
|
970
|
-
}
|
|
971
|
-
}
|
|
972
|
-
extractTarget(event) {
|
|
973
|
-
if (!event.tool_input)
|
|
974
|
-
return '';
|
|
975
|
-
const input = event.tool_input;
|
|
976
|
-
if (typeof input.file_path === 'string')
|
|
977
|
-
return input.file_path;
|
|
978
|
-
if (typeof input.path === 'string')
|
|
979
|
-
return input.path;
|
|
980
|
-
if (typeof input.command === 'string') {
|
|
981
|
-
return this.truncate(input.command, 60);
|
|
982
|
-
}
|
|
983
|
-
if (typeof input.pattern === 'string')
|
|
984
|
-
return input.pattern;
|
|
985
|
-
return '';
|
|
986
|
-
}
|
|
987
|
-
truncate(text, maxLen) {
|
|
988
|
-
if (text.length <= maxLen)
|
|
989
|
-
return text;
|
|
990
|
-
return text.slice(0, maxLen) + '...';
|
|
991
|
-
}
|
|
992
|
-
mdEscape(text) {
|
|
993
|
-
return text.replace(/\|/g, '\\|').replace(/\n/g, ' ');
|
|
994
|
-
}
|
|
995
|
-
safeJson(json) {
|
|
996
|
-
if (!json)
|
|
997
|
-
return null;
|
|
998
|
-
try {
|
|
999
|
-
return JSON.parse(json);
|
|
1000
|
-
}
|
|
1001
|
-
catch {
|
|
1002
|
-
return null;
|
|
1003
|
-
}
|
|
1004
|
-
}
|
|
1005
|
-
skillInvocationTypeLabel(type) {
|
|
1006
|
-
switch (type) {
|
|
1007
|
-
case 'static':
|
|
1008
|
-
return '静态依赖';
|
|
1009
|
-
case 'dynamic':
|
|
1010
|
-
return '动态调用';
|
|
1011
|
-
case 'slash_command':
|
|
1012
|
-
return '命令触发';
|
|
1013
|
-
default:
|
|
1014
|
-
return type;
|
|
1015
|
-
}
|
|
1016
|
-
}
|
|
1017
|
-
}
|
|
1018
|
-
//# sourceMappingURL=execution-doc-builder.js.map
|