@winspan/claude-forge 8.50.6 → 8.51.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CLAUDE.md +7 -7
- package/dist/claudemd/claudemd-generator.d.ts.map +1 -1
- package/dist/claudemd/claudemd-generator.js +27 -237
- package/dist/claudemd/claudemd-generator.js.map +1 -1
- package/dist/claudemd/resume-manager.js +1 -1
- package/dist/claudemd/resume-manager.js.map +1 -1
- package/dist/claudemd/templates/swarm-protocol.md +222 -0
- package/dist/cli/commands/daemon.js +6 -6
- package/dist/cli/commands/daemon.js.map +1 -1
- package/dist/cli/commands/executions.d.ts.map +1 -1
- package/dist/cli/commands/executions.js +4 -3
- package/dist/cli/commands/executions.js.map +1 -1
- package/dist/cli/commands/init.js +2 -2
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/commands/logs.js.map +1 -1
- package/dist/cli/commands/mcp.d.ts.map +1 -1
- package/dist/cli/commands/mcp.js +3 -5
- package/dist/cli/commands/mcp.js.map +1 -1
- package/dist/cli/commands/menu.d.ts.map +1 -1
- package/dist/cli/commands/menu.js +4 -3
- package/dist/cli/commands/menu.js.map +1 -1
- package/dist/cli/commands/stats.d.ts.map +1 -1
- package/dist/cli/commands/stats.js +2 -3
- package/dist/cli/commands/stats.js.map +1 -1
- package/dist/cli/commands/status.js +2 -2
- package/dist/cli/commands/status.js.map +1 -1
- package/dist/cli/commands/trace.d.ts.map +1 -1
- package/dist/cli/commands/trace.js +11 -23
- package/dist/cli/commands/trace.js.map +1 -1
- package/dist/cli/init/hook-manager.d.ts.map +1 -1
- package/dist/cli/init/hook-manager.js +2 -2
- package/dist/cli/init/hook-manager.js.map +1 -1
- package/dist/core/ai/provider.js +2 -2
- package/dist/core/ai/provider.js.map +1 -1
- package/dist/core/constants.d.ts +12 -1
- package/dist/core/constants.d.ts.map +1 -1
- package/dist/core/constants.js +15 -1
- package/dist/core/constants.js.map +1 -1
- package/dist/core/event-fields.d.ts +16 -0
- package/dist/core/event-fields.d.ts.map +1 -0
- package/dist/core/event-fields.js +19 -0
- package/dist/core/event-fields.js.map +1 -0
- package/dist/core/queue/index.d.ts.map +1 -1
- package/dist/core/queue/index.js +3 -4
- package/dist/core/queue/index.js.map +1 -1
- package/dist/core/storage/base.d.ts +36 -3
- package/dist/core/storage/base.d.ts.map +1 -1
- package/dist/core/storage/base.js +101 -58
- package/dist/core/storage/base.js.map +1 -1
- package/dist/core/storage/events.d.ts +92 -3
- package/dist/core/storage/events.d.ts.map +1 -1
- package/dist/core/storage/events.js +147 -0
- package/dist/core/storage/events.js.map +1 -1
- package/dist/core/storage/routing.d.ts +54 -1
- package/dist/core/storage/routing.d.ts.map +1 -1
- package/dist/core/storage/routing.js +99 -1
- package/dist/core/storage/routing.js.map +1 -1
- package/dist/core/storage/schema.sql +12 -2
- package/dist/core/storage/sessions.d.ts +20 -0
- package/dist/core/storage/sessions.d.ts.map +1 -1
- package/dist/core/storage/sessions.js +59 -0
- package/dist/core/storage/sessions.js.map +1 -1
- package/dist/core/storage/skills.d.ts +23 -0
- package/dist/core/storage/skills.d.ts.map +1 -1
- package/dist/core/storage/skills.js +47 -0
- package/dist/core/storage/skills.js.map +1 -1
- package/dist/core/storage/sqlite.d.ts +35 -2
- package/dist/core/storage/sqlite.d.ts.map +1 -1
- package/dist/core/storage/sqlite.js +93 -4
- package/dist/core/storage/sqlite.js.map +1 -1
- package/dist/core/storage/tasks.d.ts +49 -0
- package/dist/core/storage/tasks.d.ts.map +1 -1
- package/dist/core/storage/tasks.js +143 -1
- package/dist/core/storage/tasks.js.map +1 -1
- package/dist/core/storage/token-usage.d.ts +1 -1
- package/dist/core/storage/token-usage.d.ts.map +1 -1
- package/dist/core/storage/token-usage.js +1 -1
- package/dist/core/storage/token-usage.js.map +1 -1
- package/dist/core/types.d.ts +24 -3
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js.map +1 -1
- package/dist/core/utils/error-handler.d.ts.map +1 -1
- package/dist/core/utils/error-handler.js +3 -2
- package/dist/core/utils/error-handler.js.map +1 -1
- package/dist/core/utils/git.d.ts +10 -0
- package/dist/core/utils/git.d.ts.map +1 -0
- package/dist/core/utils/git.js +24 -0
- package/dist/core/utils/git.js.map +1 -0
- package/dist/core/utils/logger.d.ts.map +1 -1
- package/dist/core/utils/logger.js +15 -1
- package/dist/core/utils/logger.js.map +1 -1
- package/dist/core/utils/lru-cache.d.ts +1 -0
- package/dist/core/utils/lru-cache.d.ts.map +1 -1
- package/dist/core/utils/lru-cache.js +3 -0
- package/dist/core/utils/lru-cache.js.map +1 -1
- package/dist/core/utils/token-tracker.js +1 -1
- package/dist/core/utils/token-tracker.js.map +1 -1
- package/dist/daemon/event-parser.d.ts.map +1 -1
- package/dist/daemon/event-parser.js +2 -1
- package/dist/daemon/event-parser.js.map +1 -1
- package/dist/daemon/handlers/history-exporter.js.map +1 -1
- package/dist/daemon/handlers/post-tool-use.d.ts.map +1 -1
- package/dist/daemon/handlers/post-tool-use.js +7 -3
- package/dist/daemon/handlers/post-tool-use.js.map +1 -1
- package/dist/daemon/handlers/stop.d.ts +4 -0
- package/dist/daemon/handlers/stop.d.ts.map +1 -1
- package/dist/daemon/handlers/stop.js +23 -35
- package/dist/daemon/handlers/stop.js.map +1 -1
- package/dist/daemon/handlers/user-prompt.d.ts +3 -3
- package/dist/daemon/handlers/user-prompt.d.ts.map +1 -1
- package/dist/daemon/handlers/user-prompt.js +12 -22
- package/dist/daemon/handlers/user-prompt.js.map +1 -1
- package/dist/daemon/index.d.ts.map +1 -1
- package/dist/daemon/index.js +23 -9
- package/dist/daemon/index.js.map +1 -1
- package/dist/daemon/lifecycle.js +3 -4
- package/dist/daemon/lifecycle.js.map +1 -1
- package/dist/daemon/server.d.ts +6 -4
- package/dist/daemon/server.d.ts.map +1 -1
- package/dist/daemon/server.js +76 -85
- package/dist/daemon/server.js.map +1 -1
- package/dist/daemon/services/task-segmenter.js +1 -1
- package/dist/daemon/services/task-segmenter.js.map +1 -1
- package/dist/hooks/hook-lib.sh +37 -0
- package/dist/hooks/notification.sh +2 -2
- package/dist/hooks/post-tool-use.sh +2 -2
- package/dist/hooks/pre-tool-use.sh +2 -2
- package/dist/hooks/stop.sh +9 -6
- package/dist/hooks/user-prompt-submit.sh +2 -2
- package/dist/{daemon/services → web/analytics}/anti-pattern-detector.d.ts +3 -4
- package/dist/web/analytics/anti-pattern-detector.d.ts.map +1 -0
- package/dist/{daemon/services → web/analytics}/anti-pattern-detector.js +7 -46
- package/dist/{daemon/services → web/analytics}/anti-pattern-detector.js.map +1 -1
- package/dist/web/analytics/drift-detector.d.ts.map +1 -0
- package/dist/{daemon/services → web/analytics}/drift-detector.js +10 -13
- package/dist/web/analytics/drift-detector.js.map +1 -0
- package/dist/web/analytics/weekly-report.d.ts.map +1 -0
- package/dist/{daemon/services → web/analytics}/weekly-report.js +51 -50
- package/dist/web/analytics/weekly-report.js.map +1 -0
- package/dist/web/auth-middleware.d.ts.map +1 -1
- package/dist/web/auth-middleware.js +1 -2
- package/dist/web/auth-middleware.js.map +1 -1
- package/dist/web/routes/_helpers.d.ts +16 -0
- package/dist/web/routes/_helpers.d.ts.map +1 -0
- package/dist/web/routes/_helpers.js +32 -0
- package/dist/web/routes/_helpers.js.map +1 -0
- package/dist/web/routes/drift.js +1 -1
- package/dist/web/routes/drift.js.map +1 -1
- package/dist/web/routes/insights.js +1 -1
- package/dist/web/routes/insights.js.map +1 -1
- package/dist/web/routes/reports.js +1 -1
- package/dist/web/routes/reports.js.map +1 -1
- package/dist/web/routes/rules.d.ts +3 -0
- package/dist/web/routes/rules.d.ts.map +1 -1
- package/dist/web/routes/rules.js +28 -52
- package/dist/web/routes/rules.js.map +1 -1
- package/dist/web/routes/sessions.d.ts.map +1 -1
- package/dist/web/routes/sessions.js +16 -30
- package/dist/web/routes/sessions.js.map +1 -1
- package/dist/web/routes/skill-stats.d.ts +2 -0
- package/dist/web/routes/skill-stats.d.ts.map +1 -1
- package/dist/web/routes/skill-stats.js +28 -64
- 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 +5 -4
- package/dist/web/routes/skills.js.map +1 -1
- package/dist/web/routes/stats.d.ts +4 -0
- package/dist/web/routes/stats.d.ts.map +1 -1
- package/dist/web/routes/stats.js +19 -21
- package/dist/web/routes/stats.js.map +1 -1
- package/dist/web/routes/tasks.d.ts.map +1 -1
- package/dist/web/routes/tasks.js +17 -42
- package/dist/web/routes/tasks.js.map +1 -1
- package/dist/web/routes/trace.d.ts.map +1 -1
- package/dist/web/routes/trace.js +7 -17
- package/dist/web/routes/trace.js.map +1 -1
- package/dist/web/routes/types.d.ts.map +1 -1
- package/dist/web/routes/types.js +4 -3
- package/dist/web/routes/types.js.map +1 -1
- package/dist/web/static/assets/{AIConfig-BQCAQE9D.js → AIConfig-CdDWzJyO.js} +2 -2
- package/dist/web/static/assets/{AIConfig-BQCAQE9D.js.map → AIConfig-CdDWzJyO.js.map} +1 -1
- package/dist/web/static/assets/{Dashboard-D7Bo6Kan.js → Dashboard-CoEmmIDt.js} +2 -2
- package/dist/web/static/assets/{Dashboard-D7Bo6Kan.js.map → Dashboard-CoEmmIDt.js.map} +1 -1
- package/dist/web/static/assets/{Drawer-BeHRQxUS.js → Drawer-DdRTzlLB.js} +2 -2
- package/dist/web/static/assets/{Drawer-BeHRQxUS.js.map → Drawer-DdRTzlLB.js.map} +1 -1
- package/dist/web/static/assets/{Events-K_tCY2ti.js → Events-DrIq1SUS.js} +2 -2
- package/dist/web/static/assets/{Events-K_tCY2ti.js.map → Events-DrIq1SUS.js.map} +1 -1
- package/dist/web/static/assets/{Reports-BJCmBnc_.js → Reports-DFBM3MDK.js} +2 -2
- package/dist/web/static/assets/{Reports-BJCmBnc_.js.map → Reports-DFBM3MDK.js.map} +1 -1
- package/dist/web/static/assets/{SearchInput-BX2KhMkw.js → SearchInput-qCj_jAcf.js} +2 -2
- package/dist/web/static/assets/{SearchInput-BX2KhMkw.js.map → SearchInput-qCj_jAcf.js.map} +1 -1
- package/dist/web/static/assets/{SessionDetail-Bkr-kC7V.js → SessionDetail-CCzwdoT7.js} +2 -2
- package/dist/web/static/assets/{SessionDetail-Bkr-kC7V.js.map → SessionDetail-CCzwdoT7.js.map} +1 -1
- package/dist/web/static/assets/{Sessions-Chx9OCLH.js → Sessions-FfLYkAw9.js} +2 -2
- package/dist/web/static/assets/{Sessions-Chx9OCLH.js.map → Sessions-FfLYkAw9.js.map} +1 -1
- package/dist/web/static/assets/{Skills-O0GT1i7m.js → Skills-C8Gvs3Qa.js} +2 -2
- package/dist/web/static/assets/{Skills-O0GT1i7m.js.map → Skills-C8Gvs3Qa.js.map} +1 -1
- package/dist/web/static/assets/TaskDetail-BS8pYhaR.js +2 -0
- package/dist/web/static/assets/TaskDetail-BS8pYhaR.js.map +1 -0
- package/dist/web/static/assets/Tasks-CyuhizG8.js +2 -0
- package/dist/web/static/assets/Tasks-CyuhizG8.js.map +1 -0
- package/dist/web/static/assets/index-CBX47X8l.js +3 -0
- package/dist/web/static/assets/{index-DxIbmNmr.js.map → index-CBX47X8l.js.map} +1 -1
- package/dist/web/static/assets/index-DjIoMdoR.css +1 -0
- package/dist/web/static/assets/{lucide-fJlPI3H7.js → lucide-Bs_edTLa.js} +44 -39
- package/dist/web/static/assets/lucide-Bs_edTLa.js.map +1 -0
- package/dist/web/static/assets/react-router-r79dBVy4.js +20 -0
- package/dist/web/static/assets/{react-router-I-HqunH7.js.map → react-router-r79dBVy4.js.map} +1 -1
- package/dist/web/static/assets/task-title-BhOcemuR.js +2 -0
- package/dist/web/static/assets/task-title-BhOcemuR.js.map +1 -0
- package/dist/web/static/index.html +4 -4
- package/docs/design/h1-storage-aggregation-spec-20260518-1121.md +299 -0
- package/docs/design/h2-getdatabase-encapsulation-spec-20260518-1450.md +191 -0
- package/docs/design/h3-fallback-removal-spec-20260518-1245.md +76 -0
- package/docs/design/h4-index-dedup-spec-20260518-1230.md +109 -0
- package/docs/design/h6-services-migration-spec-20260518-1355.md +82 -0
- package/docs/design/l1-swarm-protocol-extract-spec-20260518-1605.md +106 -0
- package/docs/design/m10-forge-paths-spec-20260518-1320.md +121 -0
- package/docs/design/m2-m3-tool-input-spec-20260518-1425.md +131 -0
- package/docs/design/m7-routing-event-association-spec-20260518-1545.md +103 -0
- package/docs/design/project-path-gitroot-spec-20260518-1715.md +134 -0
- package/docs/design/task-active-gc-spec-20260518-1745.md +146 -0
- package/docs/implementation/h1-storage-aggregation-changelog-20260518-1121.md +82 -0
- package/docs/implementation/h2-final-changelog-20260518-1530.md +61 -0
- package/docs/implementation/h2-phase1-safety-net-changelog-20260518-1450.md +70 -0
- package/docs/implementation/h2-phase2-operations-changelog-20260518-1450.md +120 -0
- package/docs/implementation/h2-phase3-callsites-changelog-20260518-1450.md +71 -0
- package/docs/implementation/h3-fallback-removal-changelog-20260518-1245.md +71 -0
- package/docs/implementation/h4-index-dedup-changelog-20260518-1230.md +60 -0
- package/docs/implementation/h6-services-migration-changelog-20260518-1355.md +46 -0
- package/docs/implementation/h7-m9-defaults-changelog-20260518-1300.md +46 -0
- package/docs/implementation/l1-swarm-protocol-extract-changelog-20260518-1605.md +45 -0
- package/docs/implementation/l3-l4-daemon-perf-changelog-20260518-1410.md +63 -0
- package/docs/implementation/l6-l8-final-cleanup-changelog-20260518-1640.md +38 -0
- package/docs/implementation/m1-m4-m5-l7-cleanup-changelog-20260518-1310.md +58 -0
- package/docs/implementation/m10-forge-paths-changelog-20260518-1320.md +60 -0
- package/docs/implementation/m2-m3-tool-input-changelog-20260518-1425.md +43 -0
- package/docs/implementation/m6-m8-naming-shutdown-changelog-20260518-1340.md +56 -0
- package/docs/implementation/m7-routing-association-changelog-20260518-1545.md +69 -0
- package/docs/implementation/project-path-gitroot-changelog-20260518-1715.md +63 -0
- package/docs/implementation/task-active-gc-changelog-20260518-1745.md +35 -0
- package/docs/implementation/task-title-summary-changelog-20260518-1130.md +39 -0
- package/docs/implementation/tasks-detail-back-loses-filters-changelog-20260518-1100.md +22 -0
- package/docs/implementation/tasks-page-white-screen-hotfix-changelog-20260518-1015.md +56 -0
- package/docs/reviews/task-title-summary.md +92 -0
- package/docs/reviews/tasks-detail-back-loses-filters.md +58 -0
- package/docs/reviews/tasks-page-white-screen-hotfix.md +126 -0
- package/package.json +2 -2
- package/src/claudemd/claudemd-generator.ts +29 -238
- package/src/claudemd/resume-manager.ts +1 -1
- package/src/claudemd/templates/swarm-protocol.md +222 -0
- package/src/cli/commands/daemon.ts +6 -6
- package/src/cli/commands/executions.ts +4 -3
- package/src/cli/commands/init.ts +2 -2
- package/src/cli/commands/logs.ts +1 -1
- package/src/cli/commands/mcp.ts +3 -5
- package/src/cli/commands/menu.ts +4 -3
- package/src/cli/commands/stats.ts +2 -3
- package/src/cli/commands/status.ts +2 -2
- package/src/cli/commands/trace.ts +10 -26
- package/src/cli/init/hook-manager.ts +2 -2
- package/src/core/ai/provider.ts +2 -2
- package/src/core/constants.ts +18 -1
- package/src/core/event-fields.ts +32 -0
- package/src/core/queue/index.ts +3 -4
- package/src/core/storage/base.ts +132 -56
- package/src/core/storage/events.ts +183 -4
- package/src/core/storage/routing.ts +129 -1
- package/src/core/storage/schema.sql +12 -2
- package/src/core/storage/sessions.ts +64 -0
- package/src/core/storage/skills.ts +69 -0
- package/src/core/storage/sqlite.ts +103 -4
- package/src/core/storage/tasks.ts +149 -1
- package/src/core/storage/token-usage.ts +1 -1
- package/src/core/types.ts +30 -3
- package/src/core/utils/error-handler.ts +3 -2
- package/src/core/utils/git.ts +23 -0
- package/src/core/utils/logger.ts +16 -1
- package/src/core/utils/lru-cache.ts +4 -0
- package/src/core/utils/token-tracker.ts +1 -1
- package/src/daemon/event-parser.ts +4 -3
- package/src/daemon/handlers/history-exporter.ts +1 -1
- package/src/daemon/handlers/post-tool-use.ts +7 -3
- package/src/daemon/handlers/stop.ts +32 -39
- package/src/daemon/handlers/user-prompt.ts +12 -22
- package/src/daemon/index.ts +24 -10
- package/src/daemon/lifecycle.ts +3 -3
- package/src/daemon/server.ts +76 -89
- package/src/daemon/services/task-segmenter.ts +1 -1
- package/src/hooks/hook-lib.sh +37 -0
- package/src/hooks/notification.sh +2 -2
- package/src/hooks/post-tool-use.sh +2 -2
- package/src/hooks/pre-tool-use.sh +2 -2
- package/src/hooks/stop.sh +9 -6
- package/src/hooks/user-prompt-submit.sh +2 -2
- package/src/{daemon/services → web/analytics}/anti-pattern-detector.ts +9 -54
- package/src/{daemon/services → web/analytics}/drift-detector.ts +10 -23
- package/src/{daemon/services → web/analytics}/weekly-report.ts +52 -75
- package/src/web/auth-middleware.ts +1 -2
- package/src/web/routes/_helpers.ts +34 -0
- package/src/web/routes/drift.ts +1 -1
- package/src/web/routes/insights.ts +1 -1
- package/src/web/routes/reports.ts +1 -1
- package/src/web/routes/rules.ts +31 -56
- package/src/web/routes/sessions.ts +18 -30
- package/src/web/routes/skill-stats.ts +29 -69
- package/src/web/routes/skills.ts +5 -4
- package/src/web/routes/stats.ts +19 -29
- package/src/web/routes/tasks.ts +17 -42
- package/src/web/routes/trace.ts +7 -19
- package/src/web/routes/types.ts +4 -3
- package/tests/integration/claudemd-generator.test.ts +90 -0
- package/tests/integration/web-analytics.integration.test.ts +133 -0
- package/tests/integration/web-stats.integration.test.ts +135 -0
- package/tests/integration/web-trace.integration.test.ts +175 -0
- package/tests/unit/core/forge-paths.test.ts +99 -0
- package/tests/unit/daemon/post-tool-use.test.ts +121 -0
- package/tests/unit/daemon/stop-handler-behavior-summary.test.ts +202 -0
- package/tests/unit/daemon/task-segmenter-recover.test.ts +84 -0
- package/tests/unit/event-fields.test.ts +88 -0
- package/tests/unit/event-parser.test.ts +55 -0
- package/tests/unit/hooks/resolve-project-path.test.ts +122 -0
- package/tests/unit/socket-server.test.ts +183 -0
- package/tests/unit/storage/event-operations-aggregates.test.ts +342 -0
- package/tests/unit/storage/migration-idempotent.test.ts +304 -0
- package/tests/unit/storage/routing-aggregates.test.ts +276 -0
- package/tests/unit/storage/routing.test.ts +117 -0
- package/tests/unit/storage/schema-missing.test.ts +81 -0
- package/tests/unit/storage/session-operations-aggregates.test.ts +120 -0
- package/tests/unit/storage/skill-operations-counts.test.ts +106 -0
- package/tests/unit/storage/skills-aggregates.test.ts +104 -0
- package/tests/unit/storage/sqlite-refactor-harness.test.ts +3 -3
- package/tests/unit/storage/task-operations-counts.test.ts +46 -0
- package/tests/unit/storage/tasks-getById.test.ts +343 -0
- package/tests/unit/storage/tasks-stale-gc.test.ts +86 -0
- package/tests/unit/token-usage.test.ts +6 -6
- package/tests/unit/web/navigation-back-contract.test.ts +134 -0
- package/tests/unit/web/routes-rules.test.ts +182 -0
- package/tests/unit/web/routes-tasks.test.ts +34 -0
- package/tests/unit/web/task-title-contract.test.ts +210 -0
- package/tests/unit/web/tasks-component-contract.test.ts +179 -0
- package/vitest.config.ts +1 -1
- package/web/src/pages/TaskDetail.tsx +9 -5
- package/web/src/pages/Tasks.tsx +315 -50
- package/web/src/utils/navigation.ts +25 -0
- package/web/src/utils/task-title.ts +49 -0
- package/dist/daemon/services/anti-pattern-detector.d.ts.map +0 -1
- package/dist/daemon/services/drift-detector.d.ts.map +0 -1
- package/dist/daemon/services/drift-detector.js.map +0 -1
- package/dist/daemon/services/weekly-report.d.ts.map +0 -1
- package/dist/daemon/services/weekly-report.js.map +0 -1
- package/dist/web/static/assets/TaskDetail-5SR8zGzv.js +0 -2
- package/dist/web/static/assets/TaskDetail-5SR8zGzv.js.map +0 -1
- package/dist/web/static/assets/Tasks-DCgDqvOZ.js +0 -2
- package/dist/web/static/assets/Tasks-DCgDqvOZ.js.map +0 -1
- package/dist/web/static/assets/index-D8AKj26b.css +0 -1
- package/dist/web/static/assets/index-DxIbmNmr.js +0 -3
- package/dist/web/static/assets/lucide-fJlPI3H7.js.map +0 -1
- package/dist/web/static/assets/react-router-I-HqunH7.js +0 -20
- /package/dist/{daemon/services → web/analytics}/drift-detector.d.ts +0 -0
- /package/dist/{daemon/services → web/analytics}/weekly-report.d.ts +0 -0
|
@@ -7,8 +7,7 @@
|
|
|
7
7
|
import { Command } from 'commander';
|
|
8
8
|
import { SQLiteStorage } from '../../core/storage/sqlite.js';
|
|
9
9
|
import chalk from 'chalk';
|
|
10
|
-
import
|
|
11
|
-
import { homedir } from 'node:os';
|
|
10
|
+
import { FORGE_PATHS } from '../../core/constants.js';
|
|
12
11
|
|
|
13
12
|
export function createStatsCommand(): Command {
|
|
14
13
|
const cmd = new Command('stats');
|
|
@@ -18,7 +17,7 @@ export function createStatsCommand(): Command {
|
|
|
18
17
|
.option('-d, --days <days>', '统计天数', '7')
|
|
19
18
|
.option('-p, --project <path>', '项目路径')
|
|
20
19
|
.action((options: { days: string; project?: string }) => {
|
|
21
|
-
const dbPath =
|
|
20
|
+
const dbPath = FORGE_PATHS.database();
|
|
22
21
|
const storage = new SQLiteStorage(dbPath);
|
|
23
22
|
|
|
24
23
|
const days = parseInt(options.days);
|
|
@@ -2,10 +2,10 @@ import fs from 'fs';
|
|
|
2
2
|
import path from 'path';
|
|
3
3
|
import { homedir } from 'os';
|
|
4
4
|
import type { Command } from 'commander';
|
|
5
|
-
import {
|
|
5
|
+
import { FORGE_PATHS } from '../../core/constants.js';
|
|
6
6
|
import { ConfigManager } from '../../core/config.js';
|
|
7
7
|
|
|
8
|
-
const PID_FILE =
|
|
8
|
+
const PID_FILE = FORGE_PATHS.daemonPid();
|
|
9
9
|
|
|
10
10
|
function readPid(): number | null {
|
|
11
11
|
if (!fs.existsSync(PID_FILE)) return null;
|
|
@@ -11,7 +11,7 @@ import path from 'node:path';
|
|
|
11
11
|
import { homedir } from 'node:os';
|
|
12
12
|
import chalk from 'chalk';
|
|
13
13
|
import { SQLiteStorage } from '../../core/storage/sqlite.js';
|
|
14
|
-
import { FORGE_PATHS } from '../../core/constants.js';
|
|
14
|
+
import { FORGE_PATHS, DEFAULTS } from '../../core/constants.js';
|
|
15
15
|
import { ConfigManager } from '../../core/config.js';
|
|
16
16
|
|
|
17
17
|
function resolveDbPath(): string {
|
|
@@ -79,19 +79,17 @@ export function register(program: Command): void {
|
|
|
79
79
|
// 4. Query storage for session details
|
|
80
80
|
const dbPath = resolveDbPath();
|
|
81
81
|
const storage = new SQLiteStorage(dbPath);
|
|
82
|
-
const db = storage.getDatabase();
|
|
83
82
|
|
|
84
83
|
console.log(chalk.bold(`\nCommit: ${commitHash.slice(0, 7)} (${commitMessage})\n`));
|
|
85
84
|
|
|
86
85
|
for (const sessionId of sessionIds) {
|
|
87
|
-
printSessionTrace(storage,
|
|
86
|
+
printSessionTrace(storage, sessionId);
|
|
88
87
|
}
|
|
89
88
|
});
|
|
90
89
|
}
|
|
91
90
|
|
|
92
91
|
function printSessionTrace(
|
|
93
92
|
storage: SQLiteStorage,
|
|
94
|
-
db: ReturnType<SQLiteStorage['getDatabase']>,
|
|
95
93
|
sessionId: string,
|
|
96
94
|
): void {
|
|
97
95
|
// Find session
|
|
@@ -111,32 +109,18 @@ function printSessionTrace(
|
|
|
111
109
|
const durationMin = Math.round((end.getTime() - start.getTime()) / 60000);
|
|
112
110
|
const timeStr = `${formatTime(start)} - ${formatTime(end)} (${durationMin} min)`;
|
|
113
111
|
|
|
114
|
-
//
|
|
115
|
-
const eventBreakdown =
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
`).all(fullId) as Array<{ hook_type: string; cnt: number }>;
|
|
119
|
-
|
|
120
|
-
const totalEvents = eventBreakdown.reduce((sum, r) => sum + r.cnt, 0);
|
|
121
|
-
const breakdownStr = eventBreakdown.map(r => `${r.hook_type}: ${r.cnt}`).join(', ');
|
|
112
|
+
// H2 Phase 3: 改用 facade 聚合方法。
|
|
113
|
+
const eventBreakdown = storage.aggregateHookTypeBySession(fullId);
|
|
114
|
+
const totalEvents = eventBreakdown.reduce((sum, r) => sum + r.count, 0);
|
|
115
|
+
const breakdownStr = eventBreakdown.map(r => `${r.hook_type}: ${r.count}`).join(', ');
|
|
122
116
|
|
|
123
117
|
// Agent calls
|
|
124
|
-
const agentRows =
|
|
125
|
-
|
|
126
|
-
FROM events
|
|
127
|
-
WHERE session_id = ? AND tool_name IN ('Agent', 'Task') AND tool_input IS NOT NULL
|
|
128
|
-
GROUP BY agent_type
|
|
129
|
-
`).all(fullId) as Array<{ agent_type: string | null; cnt: number }>;
|
|
130
|
-
|
|
131
|
-
const totalAgents = agentRows.reduce((sum, r) => sum + r.cnt, 0);
|
|
118
|
+
const agentRows = storage.aggregateAgentTypeBySession(fullId);
|
|
119
|
+
const totalAgents = agentRows.reduce((sum, r) => sum + r.count, 0);
|
|
132
120
|
const agentNames = agentRows.filter(r => r.agent_type).map(r => r.agent_type as string);
|
|
133
121
|
|
|
134
122
|
// Skills
|
|
135
|
-
const
|
|
136
|
-
SELECT DISTINCT skill_id FROM skill_invocations WHERE session_id = ?
|
|
137
|
-
`).all(fullId) as Array<{ skill_id: string }>;
|
|
138
|
-
|
|
139
|
-
const skillNames = skillRows.map(r => r.skill_id);
|
|
123
|
+
const skillNames = storage.queryDistinctSkillIdsBySession(fullId);
|
|
140
124
|
|
|
141
125
|
// Output
|
|
142
126
|
console.log(chalk.cyan(` Session: ${fullId}`));
|
|
@@ -151,7 +135,7 @@ function printSessionTrace(
|
|
|
151
135
|
console.log(` Skills: ${skillNames.join(', ')}`);
|
|
152
136
|
}
|
|
153
137
|
|
|
154
|
-
console.log(chalk.dim(` Dashboard: http://localhost
|
|
138
|
+
console.log(chalk.dim(` Dashboard: http://localhost:${DEFAULTS.WEB_PORT}/sessions/${fullId}`));
|
|
155
139
|
console.log();
|
|
156
140
|
}
|
|
157
141
|
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import fs from 'fs';
|
|
2
2
|
import path from 'path';
|
|
3
3
|
import os from 'os';
|
|
4
|
-
import {
|
|
4
|
+
import { FORGE_PATHS } from '../../core/constants.js';
|
|
5
5
|
|
|
6
6
|
export const CLAUDE_HOME = path.join(os.homedir(), '.claude');
|
|
7
7
|
export const SETTINGS_PATH = path.join(CLAUDE_HOME, 'settings.json');
|
|
8
|
-
export const HOOKS_DIR =
|
|
8
|
+
export const HOOKS_DIR = FORGE_PATHS.hooks();
|
|
9
9
|
|
|
10
10
|
export const HOOK_SCRIPT_NAMES = [
|
|
11
11
|
'pre-tool-use.sh',
|
package/src/core/ai/provider.ts
CHANGED
|
@@ -24,8 +24,8 @@ export interface CompleteWithImageOptions extends CompleteOptions {
|
|
|
24
24
|
images: ImageInput[];
|
|
25
25
|
}
|
|
26
26
|
import { logger } from '../utils/logger.js';
|
|
27
|
+
import { DEFAULTS } from '../constants.js';
|
|
27
28
|
|
|
28
|
-
const DEFAULT_MODEL = 'claude-sonnet-4-20250514';
|
|
29
29
|
const DEFAULT_MAX_TOKENS = 4096;
|
|
30
30
|
const DEFAULT_TIMEOUT_MS = 30_000;
|
|
31
31
|
const DEFAULT_MAX_RETRIES = 2;
|
|
@@ -98,7 +98,7 @@ export class ClaudeProvider {
|
|
|
98
98
|
private totalLatencyMs = 0;
|
|
99
99
|
|
|
100
100
|
constructor(apiKey: string, model?: string, baseUrl?: string) {
|
|
101
|
-
this.model = model ||
|
|
101
|
+
this.model = model || DEFAULTS.AI_MODEL;
|
|
102
102
|
this.client = new Anthropic({
|
|
103
103
|
apiKey,
|
|
104
104
|
...(baseUrl ? { baseURL: baseUrl } : {}),
|
package/src/core/constants.ts
CHANGED
|
@@ -11,6 +11,23 @@ export const FORGE_PATHS = {
|
|
|
11
11
|
config: () => join(FORGE_HOME, 'config.yaml'),
|
|
12
12
|
database: () => join(FORGE_HOME, 'data.db'),
|
|
13
13
|
logs: () => join(FORGE_HOME, 'logs'),
|
|
14
|
+
|
|
15
|
+
// ── Daemon runtime files ────────────────────────────────
|
|
16
|
+
daemonSocket: () => join(FORGE_HOME, 'daemon.sock'),
|
|
17
|
+
daemonPid: () => join(FORGE_HOME, 'daemon.pid'),
|
|
18
|
+
daemonToken: () => join(FORGE_HOME, 'daemon.token'),
|
|
19
|
+
daemonLog: () => join(FORGE_HOME, 'daemon.log'),
|
|
20
|
+
daemonStdout: () => join(FORGE_HOME, 'daemon-stdout.log'),
|
|
21
|
+
daemonStderr: () => join(FORGE_HOME, 'daemon-stderr.log'),
|
|
22
|
+
|
|
23
|
+
// ── Subdirs ─────────────────────────────────────────────
|
|
24
|
+
hooks: () => join(FORGE_HOME, 'hooks'),
|
|
25
|
+
queue: () => join(FORGE_HOME, 'queue'),
|
|
26
|
+
queueDead: () => join(FORGE_HOME, 'queue', 'dead'),
|
|
27
|
+
|
|
28
|
+
// ── Patchable targets ───────────────────────────────────
|
|
29
|
+
routingYaml: () => join(FORGE_HOME, 'routing.yaml'),
|
|
30
|
+
backups: (kind: 'skills' | 'routing') => join(FORGE_HOME, 'backups', kind),
|
|
14
31
|
} as const;
|
|
15
32
|
|
|
16
33
|
/**
|
|
@@ -41,5 +58,5 @@ export const DEFAULTS = {
|
|
|
41
58
|
AI_MODEL: 'claude-sonnet-4-6',
|
|
42
59
|
AI_PROVIDER: 'anthropic',
|
|
43
60
|
STORAGE_MAX_SIZE_MB: 500,
|
|
44
|
-
WEB_PORT:
|
|
61
|
+
WEB_PORT: 3721,
|
|
45
62
|
} as const;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Typed getters for ForgeEvent.tool_input fields.
|
|
3
|
+
*
|
|
4
|
+
* Centralises the defensive-access pattern that previously lived as
|
|
5
|
+
* `(e.tool_input as any)?.command ?? ''` across 30+ call sites. Each
|
|
6
|
+
* getter returns `string | undefined`; callers decide their own fallback.
|
|
7
|
+
*
|
|
8
|
+
* Adding a new tool field? Extend ToolInputFields in core/types.ts first,
|
|
9
|
+
* then add a getter here if it needs a normalised access entry.
|
|
10
|
+
*/
|
|
11
|
+
import type { ForgeEvent } from './types.js';
|
|
12
|
+
|
|
13
|
+
export function getCommand(e: ForgeEvent): string | undefined {
|
|
14
|
+
const c = e.tool_input?.command;
|
|
15
|
+
return typeof c === 'string' ? c : undefined;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function getFilePath(e: ForgeEvent): string | undefined {
|
|
19
|
+
const fp = e.tool_input?.file_path ?? e.tool_input?.notebook_path;
|
|
20
|
+
return typeof fp === 'string' && fp.length > 0 ? fp : undefined;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function getUserPrompt(e: ForgeEvent): string | undefined {
|
|
24
|
+
if (typeof e.user_prompt === 'string') return e.user_prompt;
|
|
25
|
+
const fallback = e.tool_input?.user_prompt;
|
|
26
|
+
return typeof fallback === 'string' ? fallback : undefined;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function getSubagentType(e: ForgeEvent): string | undefined {
|
|
30
|
+
const s = e.tool_input?.subagent_type;
|
|
31
|
+
return typeof s === 'string' ? s : undefined;
|
|
32
|
+
}
|
package/src/core/queue/index.ts
CHANGED
|
@@ -16,16 +16,15 @@
|
|
|
16
16
|
import { mkdirSync, readdirSync, renameSync, rmSync, statSync, writeFileSync } from 'node:fs';
|
|
17
17
|
import { readFile } from 'node:fs/promises';
|
|
18
18
|
import { join } from 'node:path';
|
|
19
|
-
import { homedir } from 'node:os';
|
|
20
19
|
import { randomUUID } from 'node:crypto';
|
|
21
20
|
import type { SQLiteStorage } from '../storage/sqlite.js';
|
|
22
21
|
import type { ForgeEvent } from '../types.js';
|
|
23
22
|
import { logger } from '../utils/logger.js';
|
|
23
|
+
import { FORGE_PATHS } from '../constants.js';
|
|
24
24
|
|
|
25
25
|
// ── Constants ──────────────────────────────────────────────────────────────
|
|
26
|
-
const
|
|
27
|
-
export const
|
|
28
|
-
export const DEAD_DIR = join(FORGE_DIR, 'queue', 'dead');
|
|
26
|
+
export const QUEUE_DIR = FORGE_PATHS.queue();
|
|
27
|
+
export const DEAD_DIR = FORGE_PATHS.queueDead();
|
|
29
28
|
export const MAX_FILES = 500;
|
|
30
29
|
export const TTL_DAYS = 7;
|
|
31
30
|
|
package/src/core/storage/base.ts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* 拆分自 sqlite.ts。仅负责:
|
|
5
5
|
* - 打开数据库连接 + 配置 PRAGMA
|
|
6
|
-
* - 加载 schema.sql
|
|
6
|
+
* - 加载 schema.sql(缺失则抛错)
|
|
7
7
|
* - 增量迁移(hasColumn / addColumnIfMissing)
|
|
8
8
|
* - 一次性 sessions 回填
|
|
9
9
|
*
|
|
@@ -43,32 +43,43 @@ export class SQLiteBase {
|
|
|
43
43
|
this.db.pragma('mmap_size = 30000000000'); // 30GB memory-mapped I/O
|
|
44
44
|
this.db.pragma('page_size = 4096'); // Optimal page size for most systems
|
|
45
45
|
|
|
46
|
+
// Order matters:
|
|
47
|
+
// 1) runColumnMigrations() ALTERs missing columns on PRE-EXISTING tables.
|
|
48
|
+
// Must run BEFORE initSchema() because schema.sql contains indexes that
|
|
49
|
+
// reference new columns (e.g. idx_skill_invocations_workflow). On a
|
|
50
|
+
// legacy DB those CREATE INDEX statements would otherwise fail because
|
|
51
|
+
// CREATE TABLE IF NOT EXISTS skips the old table and never adds the column.
|
|
52
|
+
// 2) initSchema() applies schema.sql (idempotent CREATE TABLE/INDEX).
|
|
53
|
+
// 3) runIndexMigrations() patches indexes that may still be missing on
|
|
54
|
+
// legacy DBs (defensive; schema.sql already creates them on new DBs).
|
|
55
|
+
this.runColumnMigrations();
|
|
46
56
|
this.initSchema();
|
|
47
|
-
this.
|
|
57
|
+
this.runIndexMigrations();
|
|
58
|
+
this.runPostMigrations();
|
|
48
59
|
}
|
|
49
60
|
|
|
50
61
|
private initSchema(): void {
|
|
51
62
|
const thisDir = dirname(fileURLToPath(import.meta.url));
|
|
52
63
|
const schemaPath = join(thisDir, 'schema.sql');
|
|
53
64
|
|
|
54
|
-
if (existsSync(schemaPath)) {
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
65
|
+
if (!existsSync(schemaPath)) {
|
|
66
|
+
throw new Error(
|
|
67
|
+
`[SQLiteStorage] schema.sql not found at ${schemaPath}. ` +
|
|
68
|
+
`This indicates a broken build/install. Run \`npm run build\` or reinstall the package.`,
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
const schema = readFileSync(schemaPath, 'utf-8');
|
|
72
|
+
this.db.exec(schema);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
protected hasTable(name: string): boolean {
|
|
76
|
+
try {
|
|
77
|
+
const row = this.db
|
|
78
|
+
.prepare(`SELECT name FROM sqlite_master WHERE type='table' AND name = ?`)
|
|
79
|
+
.get(name);
|
|
80
|
+
return !!row;
|
|
81
|
+
} catch {
|
|
82
|
+
return false;
|
|
72
83
|
}
|
|
73
84
|
}
|
|
74
85
|
|
|
@@ -82,6 +93,10 @@ export class SQLiteBase {
|
|
|
82
93
|
}
|
|
83
94
|
|
|
84
95
|
protected addColumnIfMissing(table: string, column: string, definition: string): void {
|
|
96
|
+
// Skip silently if the table doesn't exist yet — new DBs hit this path on
|
|
97
|
+
// first boot (initSchema runs after column migrations); the column will be
|
|
98
|
+
// created by schema.sql's CREATE TABLE.
|
|
99
|
+
if (!this.hasTable(table)) return;
|
|
85
100
|
if (!this.hasColumn(table, column)) {
|
|
86
101
|
try {
|
|
87
102
|
this.db.exec(`ALTER TABLE ${table} ADD COLUMN ${column} ${definition}`);
|
|
@@ -92,10 +107,38 @@ export class SQLiteBase {
|
|
|
92
107
|
}
|
|
93
108
|
}
|
|
94
109
|
|
|
110
|
+
protected hasIndex(name: string): boolean {
|
|
111
|
+
try {
|
|
112
|
+
const row = this.db
|
|
113
|
+
.prepare(`SELECT name FROM sqlite_master WHERE type='index' AND name = ?`)
|
|
114
|
+
.get(name);
|
|
115
|
+
return !!row;
|
|
116
|
+
} catch {
|
|
117
|
+
return false;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Create an index only if it's missing. The CREATE INDEX IF NOT EXISTS already
|
|
123
|
+
* makes this safe; the hasIndex guard makes it explicit which indexes are still
|
|
124
|
+
* being patched by migrations (vs. provided by schema.sql).
|
|
125
|
+
*/
|
|
126
|
+
private createIndexIfMissing(name: string, ddl: string): void {
|
|
127
|
+
if (this.hasIndex(name)) return;
|
|
128
|
+
try {
|
|
129
|
+
this.db.exec(ddl);
|
|
130
|
+
logger.debug(`[SQLiteStorage] migration created ${name}`);
|
|
131
|
+
} catch (err) {
|
|
132
|
+
logger.warn(`[SQLiteStorage] migration: create ${name} failed: ${err}`);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
95
136
|
/**
|
|
96
|
-
*
|
|
137
|
+
* Column migrations run BEFORE initSchema() so legacy tables get missing
|
|
138
|
+
* columns (e.g. skill_invocations.workflow) before schema.sql's CREATE INDEX
|
|
139
|
+
* statements try to reference them.
|
|
97
140
|
*/
|
|
98
|
-
private
|
|
141
|
+
private runColumnMigrations(): void {
|
|
99
142
|
this.addColumnIfMissing('sessions', 'first_prompt', 'TEXT');
|
|
100
143
|
|
|
101
144
|
this.addColumnIfMissing('routing_events', 'skill_confidence', 'REAL');
|
|
@@ -105,45 +148,69 @@ export class SQLiteBase {
|
|
|
105
148
|
this.addColumnIfMissing('skill_invocations', 'phase', 'TEXT');
|
|
106
149
|
this.addColumnIfMissing('skill_invocations', 'feature_slug', 'TEXT');
|
|
107
150
|
this.addColumnIfMissing('skill_invocations', 'artifact_path', 'TEXT');
|
|
151
|
+
}
|
|
108
152
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
153
|
+
/**
|
|
154
|
+
* Index migrations run AFTER initSchema(). Each call is guarded by hasIndex
|
|
155
|
+
* so:
|
|
156
|
+
* - new DBs: schema.sql already created the index → skipped
|
|
157
|
+
* - legacy DBs: schema.sql skipped (existing index) for indexes it tries to
|
|
158
|
+
* create or covered above; remaining migration-only / pre-H1 indexes are
|
|
159
|
+
* patched here.
|
|
160
|
+
* CREATE INDEX IF NOT EXISTS is preserved as a second line of defense.
|
|
161
|
+
*/
|
|
162
|
+
private runIndexMigrations(): void {
|
|
163
|
+
this.createIndexIfMissing(
|
|
164
|
+
'idx_skill_invocations_workflow',
|
|
165
|
+
`CREATE INDEX IF NOT EXISTS idx_skill_invocations_workflow ON skill_invocations(workflow, phase)`,
|
|
166
|
+
);
|
|
167
|
+
this.createIndexIfMissing(
|
|
168
|
+
'idx_skill_invocations_feature',
|
|
169
|
+
`CREATE INDEX IF NOT EXISTS idx_skill_invocations_feature ON skill_invocations(feature_slug)`,
|
|
170
|
+
);
|
|
117
171
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
}
|
|
172
|
+
this.createIndexIfMissing(
|
|
173
|
+
'idx_sessions_start_time',
|
|
174
|
+
`CREATE INDEX IF NOT EXISTS idx_sessions_start_time ON sessions(start_time DESC)`,
|
|
175
|
+
);
|
|
123
176
|
|
|
124
|
-
// Composite indexes for high-frequency session-scoped queries
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
177
|
+
// Composite indexes for high-frequency session-scoped queries
|
|
178
|
+
this.createIndexIfMissing(
|
|
179
|
+
'idx_events_session_ts',
|
|
180
|
+
`CREATE INDEX IF NOT EXISTS idx_events_session_ts ON events(session_id, timestamp DESC)`,
|
|
181
|
+
);
|
|
182
|
+
this.createIndexIfMissing(
|
|
183
|
+
'idx_routing_events_session_ts',
|
|
184
|
+
`CREATE INDEX IF NOT EXISTS idx_routing_events_session_ts ON routing_events(session_id, ts DESC)`,
|
|
185
|
+
);
|
|
186
|
+
this.createIndexIfMissing(
|
|
187
|
+
'idx_skill_invocations_session_ts',
|
|
188
|
+
`CREATE INDEX IF NOT EXISTS idx_skill_invocations_session_ts ON skill_invocations(session_id, timestamp DESC)`,
|
|
189
|
+
);
|
|
134
190
|
|
|
135
|
-
// Phase 1 Refactor: Additional performance indexes
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
191
|
+
// Phase 1 Refactor: Additional performance indexes
|
|
192
|
+
this.createIndexIfMissing(
|
|
193
|
+
'idx_routing_events_obeyed_ts',
|
|
194
|
+
`CREATE INDEX IF NOT EXISTS idx_routing_events_obeyed_ts ON routing_events(obeyed, ts DESC)`,
|
|
195
|
+
);
|
|
196
|
+
this.createIndexIfMissing(
|
|
197
|
+
'idx_events_session_hook',
|
|
198
|
+
`CREATE INDEX IF NOT EXISTS idx_events_session_hook ON events(session_id, hook_type, timestamp DESC)`,
|
|
199
|
+
);
|
|
200
|
+
this.createIndexIfMissing(
|
|
201
|
+
'idx_injections_session_handler',
|
|
202
|
+
`CREATE INDEX IF NOT EXISTS idx_injections_session_handler ON injections(session_id, source_handler)`,
|
|
203
|
+
);
|
|
204
|
+
this.createIndexIfMissing(
|
|
205
|
+
'idx_routing_events_type_ts',
|
|
206
|
+
`CREATE INDEX IF NOT EXISTS idx_routing_events_type_ts ON routing_events(routed_to_type, ts DESC)`,
|
|
207
|
+
);
|
|
208
|
+
}
|
|
146
209
|
|
|
210
|
+
/**
|
|
211
|
+
* One-shot data migrations + deprecated table cleanup.
|
|
212
|
+
*/
|
|
213
|
+
private runPostMigrations(): void {
|
|
147
214
|
this.backfillSessionsIfNeeded();
|
|
148
215
|
|
|
149
216
|
const deprecatedTables = [
|
|
@@ -211,6 +278,15 @@ export class SQLiteBase {
|
|
|
211
278
|
}
|
|
212
279
|
}
|
|
213
280
|
|
|
281
|
+
/**
|
|
282
|
+
* @internal 仅供 *Operations 子类、migration、初始化使用。
|
|
283
|
+
*
|
|
284
|
+
* Routes / Handlers / Analytics 禁止直接调用。需要查询请走 SQLiteStorage facade
|
|
285
|
+
* 上的具名方法(query* / get* / list* / count* / aggregate*);若 facade 缺方法,
|
|
286
|
+
* 应在对应 Operations 类下沉 SQL 并补 facade 转发,而不是 db.prepare() 直写。
|
|
287
|
+
*
|
|
288
|
+
* 历史:H2 (2026-05) 已收敛 27 处越权 SQL,新增越权请走同样的下沉模式。
|
|
289
|
+
*/
|
|
214
290
|
getDatabase(): Database.Database {
|
|
215
291
|
return this.db;
|
|
216
292
|
}
|