prjct-cli 0.11.5 → 0.12.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/CHANGELOG.md +58 -0
- package/README.md +81 -25
- package/bin/dev.js +1 -1
- package/bin/generate-views.js +209 -0
- package/bin/migrate-to-json.js +742 -0
- package/bin/prjct +5 -5
- package/bin/serve.js +226 -50
- package/core/__tests__/agentic/{memory-system.test.js → memory-system.test.ts} +12 -23
- package/core/__tests__/agentic/{plan-mode.test.js → plan-mode.test.ts} +26 -24
- package/core/__tests__/agentic/{prompt-builder.test.js → prompt-builder.test.ts} +3 -8
- package/core/__tests__/utils/{date-helper.test.js → date-helper.test.ts} +19 -30
- package/core/__tests__/utils/{output.test.js → output.test.ts} +12 -24
- package/core/agentic/agent-router.ts +137 -0
- package/core/agentic/chain-of-thought.ts +228 -0
- package/core/agentic/command-executor/command-executor.ts +384 -0
- package/core/agentic/command-executor/index.ts +16 -0
- package/core/agentic/command-executor/status-signal.ts +38 -0
- package/core/agentic/command-executor/types.ts +79 -0
- package/core/agentic/command-executor.ts +8 -0
- package/core/agentic/{context-builder.js → context-builder.ts} +92 -81
- package/core/agentic/context-filter.ts +365 -0
- package/core/agentic/ground-truth/index.ts +76 -0
- package/core/agentic/ground-truth/types.ts +33 -0
- package/core/agentic/ground-truth/utils.ts +48 -0
- package/core/agentic/ground-truth/verifiers/analyze.ts +54 -0
- package/core/agentic/ground-truth/verifiers/done.ts +75 -0
- package/core/agentic/ground-truth/verifiers/feature.ts +70 -0
- package/core/agentic/ground-truth/verifiers/index.ts +37 -0
- package/core/agentic/ground-truth/verifiers/init.ts +52 -0
- package/core/agentic/ground-truth/verifiers/now.ts +57 -0
- package/core/agentic/ground-truth/verifiers/ship.ts +85 -0
- package/core/agentic/ground-truth/verifiers/spec.ts +45 -0
- package/core/agentic/ground-truth/verifiers/sync.ts +47 -0
- package/core/agentic/ground-truth/verifiers.ts +6 -0
- package/core/agentic/ground-truth.ts +8 -0
- package/core/agentic/loop-detector/error-analysis.ts +97 -0
- package/core/agentic/loop-detector/hallucination.ts +71 -0
- package/core/agentic/loop-detector/index.ts +41 -0
- package/core/agentic/loop-detector/loop-detector.ts +222 -0
- package/core/agentic/loop-detector/types.ts +66 -0
- package/core/agentic/loop-detector.ts +8 -0
- package/core/agentic/memory-system/history.ts +53 -0
- package/core/agentic/memory-system/index.ts +192 -0
- package/core/agentic/memory-system/patterns.ts +156 -0
- package/core/agentic/memory-system/semantic-memories.ts +277 -0
- package/core/agentic/memory-system/session.ts +21 -0
- package/core/agentic/memory-system/types.ts +159 -0
- package/core/agentic/memory-system.ts +8 -0
- package/core/agentic/parallel-tools.ts +165 -0
- package/core/agentic/plan-mode/approval.ts +57 -0
- package/core/agentic/plan-mode/constants.ts +44 -0
- package/core/agentic/plan-mode/index.ts +28 -0
- package/core/agentic/plan-mode/plan-mode.ts +406 -0
- package/core/agentic/plan-mode/types.ts +193 -0
- package/core/agentic/plan-mode.ts +8 -0
- package/core/agentic/prompt-builder.ts +566 -0
- package/core/agentic/response-templates.ts +164 -0
- package/core/agentic/semantic-compression.ts +273 -0
- package/core/agentic/services.ts +206 -0
- package/core/agentic/smart-context.ts +476 -0
- package/core/agentic/{template-loader.js → template-loader.ts} +27 -16
- package/core/agentic/think-blocks.ts +202 -0
- package/core/agentic/tool-registry.ts +119 -0
- package/core/agentic/validation-rules.ts +313 -0
- package/core/agents/index.ts +28 -0
- package/core/agents/performance.ts +444 -0
- package/core/agents/types.ts +126 -0
- package/core/bus/{index.js → index.ts} +57 -61
- package/core/command-registry/categories.ts +23 -0
- package/core/command-registry/commands.ts +15 -0
- package/core/command-registry/core-commands.ts +319 -0
- package/core/command-registry/index.ts +158 -0
- package/core/command-registry/optional-commands.ts +119 -0
- package/core/command-registry/setup-commands.ts +53 -0
- package/core/command-registry/types.ts +59 -0
- package/core/command-registry.ts +9 -0
- package/core/commands/analysis.ts +298 -0
- package/core/commands/analytics.ts +288 -0
- package/core/commands/base.ts +273 -0
- package/core/commands/index.ts +211 -0
- package/core/commands/maintenance.ts +226 -0
- package/core/commands/planning.ts +311 -0
- package/core/commands/setup.ts +309 -0
- package/core/commands/shipping.ts +188 -0
- package/core/commands/types.ts +183 -0
- package/core/commands/workflow.ts +226 -0
- package/core/commands.ts +11 -0
- package/core/constants/formats.ts +187 -0
- package/core/constants/index.ts +7 -0
- package/core/{context-sync.js → context-sync.ts} +59 -26
- package/core/data/agents-manager.ts +76 -0
- package/core/data/analysis-manager.ts +83 -0
- package/core/data/base-manager.ts +156 -0
- package/core/data/ideas-manager.ts +81 -0
- package/core/data/index.ts +32 -0
- package/core/data/outcomes-manager.ts +96 -0
- package/core/data/project-manager.ts +75 -0
- package/core/data/roadmap-manager.ts +118 -0
- package/core/data/shipped-manager.ts +65 -0
- package/core/data/state-manager.ts +214 -0
- package/core/domain/{agent-generator.js → agent-generator.ts} +77 -57
- package/core/domain/{agent-loader.js → agent-loader.ts} +65 -56
- package/core/domain/{agent-matcher.js → agent-matcher.ts} +51 -24
- package/core/domain/{agent-validator.js → agent-validator.ts} +70 -37
- package/core/domain/{analyzer.js → analyzer.ts} +91 -85
- package/core/domain/{architect-session.js → architect-session.ts} +49 -34
- package/core/domain/{architecture-generator.js → architecture-generator.ts} +25 -13
- package/core/domain/{context-estimator.js → context-estimator.ts} +57 -36
- package/core/domain/{product-standards.js → product-standards.ts} +40 -26
- package/core/domain/{smart-cache.js → smart-cache.ts} +39 -30
- package/core/domain/{snapshot-manager.js → snapshot-manager.ts} +103 -100
- package/core/domain/{task-analyzer.js → task-analyzer.ts} +82 -43
- package/core/domain/task-stack/index.ts +19 -0
- package/core/domain/task-stack/parser.ts +86 -0
- package/core/domain/task-stack/storage.ts +123 -0
- package/core/domain/task-stack/task-stack.ts +340 -0
- package/core/domain/task-stack/types.ts +51 -0
- package/core/domain/task-stack.ts +8 -0
- package/core/{index.js → index.ts} +61 -18
- package/core/infrastructure/{agent-detector.js → agent-detector.ts} +55 -19
- package/core/infrastructure/agents/{claude-agent.js → claude-agent.ts} +61 -21
- package/core/infrastructure/{author-detector.js → author-detector.ts} +42 -49
- package/core/infrastructure/{capability-installer.js → capability-installer.ts} +51 -27
- package/core/infrastructure/{command-installer.js → command-installer/command-installer.ts} +43 -144
- package/core/infrastructure/command-installer/global-config.ts +106 -0
- package/core/infrastructure/command-installer/index.ts +25 -0
- package/core/infrastructure/command-installer/types.ts +41 -0
- package/core/infrastructure/command-installer.ts +8 -0
- package/core/infrastructure/{config-manager.js → config-manager.ts} +60 -80
- package/core/infrastructure/{editors-config.js → editors-config.ts} +33 -31
- package/core/infrastructure/legacy-installer-detector/cleanup.ts +216 -0
- package/core/infrastructure/legacy-installer-detector/detection.ts +95 -0
- package/core/infrastructure/legacy-installer-detector/index.ts +171 -0
- package/core/infrastructure/legacy-installer-detector/migration.ts +87 -0
- package/core/infrastructure/legacy-installer-detector/types.ts +42 -0
- package/core/infrastructure/legacy-installer-detector.ts +7 -0
- package/core/infrastructure/migrator/file-operations.ts +125 -0
- package/core/infrastructure/migrator/index.ts +288 -0
- package/core/infrastructure/migrator/project-scanner.ts +89 -0
- package/core/infrastructure/migrator/reports.ts +117 -0
- package/core/infrastructure/migrator/types.ts +124 -0
- package/core/infrastructure/migrator/validation.ts +94 -0
- package/core/infrastructure/migrator/version-migration.ts +117 -0
- package/core/infrastructure/migrator.ts +10 -0
- package/core/infrastructure/{path-manager.js → path-manager.ts} +51 -91
- package/core/infrastructure/session-manager/index.ts +23 -0
- package/core/infrastructure/session-manager/migration.ts +88 -0
- package/core/infrastructure/session-manager/session-manager.ts +307 -0
- package/core/infrastructure/session-manager/types.ts +45 -0
- package/core/infrastructure/session-manager.ts +8 -0
- package/core/infrastructure/{setup.js → setup.ts} +29 -21
- package/core/infrastructure/{update-checker.js → update-checker.ts} +40 -18
- package/core/outcomes/analyzer.ts +333 -0
- package/core/outcomes/index.ts +34 -0
- package/core/outcomes/recorder.ts +194 -0
- package/core/outcomes/types.ts +145 -0
- package/core/plugin/{hooks.js → hooks.ts} +56 -58
- package/core/plugin/{index.js → index.ts} +19 -8
- package/core/plugin/{loader.js → loader.ts} +87 -69
- package/core/plugin/{registry.js → registry.ts} +49 -45
- package/core/plugins/{webhook.js → webhook.ts} +43 -27
- package/core/schemas/agents.ts +27 -0
- package/core/schemas/analysis.ts +41 -0
- package/core/schemas/ideas.ts +83 -0
- package/core/schemas/index.ts +73 -0
- package/core/schemas/outcomes.ts +22 -0
- package/core/schemas/project.ts +26 -0
- package/core/schemas/roadmap.ts +90 -0
- package/core/schemas/shipped.ts +82 -0
- package/core/schemas/state.ts +107 -0
- package/core/session/index.ts +17 -0
- package/core/session/{metrics.js → metrics.ts} +64 -46
- package/core/session/{index.js → session-manager.ts} +51 -117
- package/core/session/types.ts +29 -0
- package/core/session/utils.ts +57 -0
- package/core/state/index.ts +25 -0
- package/core/state/manager.ts +376 -0
- package/core/state/types.ts +185 -0
- package/core/tsconfig.json +22 -0
- package/core/types/index.ts +506 -0
- package/core/utils/{animations.js → animations.ts} +74 -28
- package/core/utils/{branding.js → branding.ts} +29 -4
- package/core/utils/{date-helper.js → date-helper.ts} +31 -74
- package/core/utils/file-helper.ts +262 -0
- package/core/utils/{jsonl-helper.js → jsonl-helper.ts} +71 -107
- package/core/utils/{logger.js → logger.ts} +24 -12
- package/core/utils/{output.js → output.ts} +25 -13
- package/core/utils/{project-capabilities.js → project-capabilities.ts} +31 -18
- package/core/utils/{session-helper.js → session-helper.ts} +79 -66
- package/core/utils/{version.js → version.ts} +23 -31
- package/core/view-generator.ts +536 -0
- package/package.json +23 -17
- package/packages/shared/.turbo/turbo-build.log +14 -0
- package/packages/shared/dist/index.d.ts +8 -613
- package/packages/shared/dist/index.d.ts.map +1 -0
- package/packages/shared/dist/index.js +4110 -118
- package/packages/shared/dist/schemas.d.ts +408 -0
- package/packages/shared/dist/schemas.d.ts.map +1 -0
- package/packages/shared/dist/types.d.ts +144 -0
- package/packages/shared/dist/types.d.ts.map +1 -0
- package/packages/shared/dist/unified.d.ts +139 -0
- package/packages/shared/dist/unified.d.ts.map +1 -0
- package/packages/shared/dist/utils.d.ts +60 -0
- package/packages/shared/dist/utils.d.ts.map +1 -0
- package/packages/shared/package.json +4 -4
- package/packages/shared/src/index.ts +1 -0
- package/packages/shared/src/unified.ts +174 -0
- package/packages/web/app/api/claude/sessions/route.ts +1 -1
- package/packages/web/app/api/claude/status/route.ts +1 -1
- package/packages/web/app/api/migrate/route.ts +46 -0
- package/packages/web/app/api/projects/[id]/route.ts +1 -1
- package/packages/web/app/api/projects/[id]/stats/route.ts +30 -2
- package/packages/web/app/api/projects/[id]/status/route.ts +1 -1
- package/packages/web/app/api/projects/route.ts +1 -1
- package/packages/web/app/api/settings/route.ts +97 -0
- package/packages/web/app/api/v2/projects/[id]/unified/route.ts +57 -0
- package/packages/web/app/globals.css +38 -0
- package/packages/web/app/layout.tsx +10 -2
- package/packages/web/app/page.tsx +9 -224
- package/packages/web/app/project/[id]/page.tsx +191 -63
- package/packages/web/app/project/[id]/stats/loading.tsx +43 -0
- package/packages/web/app/project/[id]/stats/page.tsx +204 -163
- package/packages/web/app/settings/page.tsx +222 -2
- package/packages/web/components/ActivityTimeline/ActivityTimeline.constants.ts +2 -0
- package/packages/web/components/ActivityTimeline/ActivityTimeline.tsx +50 -0
- package/packages/web/components/ActivityTimeline/ActivityTimeline.types.ts +8 -0
- package/packages/web/components/ActivityTimeline/hooks/index.ts +2 -0
- package/packages/web/components/ActivityTimeline/hooks/useExpandable.ts +9 -0
- package/packages/web/components/ActivityTimeline/hooks/useGroupedEvents.ts +23 -0
- package/packages/web/components/ActivityTimeline/index.ts +2 -0
- package/packages/web/components/AgentsCard/AgentsCard.tsx +63 -0
- package/packages/web/components/AgentsCard/AgentsCard.types.ts +13 -0
- package/packages/web/components/AgentsCard/index.ts +2 -0
- package/packages/web/components/AppSidebar/AppSidebar.tsx +134 -0
- package/packages/web/components/AppSidebar/index.ts +1 -0
- package/packages/web/components/BackLink/BackLink.tsx +18 -0
- package/packages/web/components/BackLink/BackLink.types.ts +5 -0
- package/packages/web/components/BackLink/index.ts +2 -0
- package/packages/web/components/BentoCard/BentoCard.constants.ts +16 -0
- package/packages/web/components/BentoCard/BentoCard.tsx +47 -0
- package/packages/web/components/BentoCard/BentoCard.types.ts +15 -0
- package/packages/web/components/BentoCard/index.ts +2 -0
- package/packages/web/components/BentoCardSkeleton/BentoCardSkeleton.constants.ts +9 -0
- package/packages/web/components/BentoCardSkeleton/BentoCardSkeleton.tsx +18 -0
- package/packages/web/components/BentoCardSkeleton/BentoCardSkeleton.types.ts +5 -0
- package/packages/web/components/BentoCardSkeleton/index.ts +2 -0
- package/packages/web/components/{stats → BentoGrid}/BentoGrid.tsx +4 -8
- package/packages/web/components/BentoGrid/BentoGrid.types.ts +4 -0
- package/packages/web/components/BentoGrid/index.ts +2 -0
- package/packages/web/components/CommandButton/index.ts +1 -0
- package/packages/web/components/ConnectionStatus/index.ts +1 -0
- package/packages/web/components/DashboardContent/DashboardContent.tsx +254 -0
- package/packages/web/components/DashboardContent/index.ts +1 -0
- package/packages/web/components/DateGroup/DateGroup.tsx +18 -0
- package/packages/web/components/DateGroup/DateGroup.types.ts +6 -0
- package/packages/web/components/DateGroup/DateGroup.utils.ts +11 -0
- package/packages/web/components/DateGroup/index.ts +2 -0
- package/packages/web/components/{stats → EmptyState}/EmptyState.tsx +1 -10
- package/packages/web/components/EmptyState/EmptyState.types.ts +10 -0
- package/packages/web/components/EmptyState/index.ts +2 -0
- package/packages/web/components/EventRow/EventRow.constants.ts +10 -0
- package/packages/web/components/EventRow/EventRow.tsx +49 -0
- package/packages/web/components/EventRow/EventRow.types.ts +7 -0
- package/packages/web/components/EventRow/EventRow.utils.ts +49 -0
- package/packages/web/components/EventRow/index.ts +2 -0
- package/packages/web/components/ExpandButton/ExpandButton.tsx +18 -0
- package/packages/web/components/ExpandButton/ExpandButton.types.ts +6 -0
- package/packages/web/components/ExpandButton/index.ts +2 -0
- package/packages/web/components/HealthGradientBackground/HealthGradientBackground.tsx +14 -0
- package/packages/web/components/HealthGradientBackground/HealthGradientBackground.types.ts +5 -0
- package/packages/web/components/HealthGradientBackground/HealthGradientBackground.utils.ts +13 -0
- package/packages/web/components/HealthGradientBackground/index.ts +2 -0
- package/packages/web/components/HeroSection/HeroSection.tsx +55 -0
- package/packages/web/components/HeroSection/HeroSection.types.ts +14 -0
- package/packages/web/components/HeroSection/HeroSection.utils.ts +7 -0
- package/packages/web/components/HeroSection/hooks/index.ts +2 -0
- package/packages/web/components/HeroSection/hooks/useCountUp.ts +45 -0
- package/packages/web/components/HeroSection/hooks/useWeeklyActivity.ts +18 -0
- package/packages/web/components/HeroSection/index.ts +2 -0
- package/packages/web/components/{stats → IdeasCard}/IdeasCard.tsx +3 -14
- package/packages/web/components/IdeasCard/IdeasCard.types.ts +9 -0
- package/packages/web/components/IdeasCard/index.ts +2 -0
- package/packages/web/components/InsightMessage/InsightMessage.tsx +9 -0
- package/packages/web/components/InsightMessage/InsightMessage.types.ts +3 -0
- package/packages/web/components/InsightMessage/index.ts +2 -0
- package/packages/web/components/Logo/index.ts +1 -0
- package/packages/web/components/MarkdownContent/index.ts +1 -0
- package/packages/web/components/NowCard/NowCard.tsx +93 -0
- package/packages/web/components/NowCard/NowCard.types.ts +15 -0
- package/packages/web/components/NowCard/index.ts +2 -0
- package/packages/web/components/ProgressRing/ProgressRing.constants.ts +20 -0
- package/packages/web/components/{stats → ProgressRing}/ProgressRing.tsx +4 -27
- package/packages/web/components/ProgressRing/ProgressRing.types.ts +11 -0
- package/packages/web/components/ProgressRing/index.ts +2 -0
- package/packages/web/components/ProjectAvatar/index.ts +1 -0
- package/packages/web/components/Providers/index.ts +1 -0
- package/packages/web/components/QueueCard/QueueCard.tsx +72 -0
- package/packages/web/components/QueueCard/QueueCard.types.ts +11 -0
- package/packages/web/components/QueueCard/QueueCard.utils.ts +12 -0
- package/packages/web/components/QueueCard/index.ts +2 -0
- package/packages/web/components/{stats → RoadmapCard}/RoadmapCard.tsx +3 -23
- package/packages/web/components/RoadmapCard/RoadmapCard.types.ts +15 -0
- package/packages/web/components/RoadmapCard/index.ts +2 -0
- package/packages/web/components/{stats → ShipsCard}/ShipsCard.tsx +4 -22
- package/packages/web/components/ShipsCard/ShipsCard.types.ts +12 -0
- package/packages/web/components/ShipsCard/ShipsCard.utils.ts +4 -0
- package/packages/web/components/ShipsCard/index.ts +2 -0
- package/packages/web/components/{stats → SparklineChart}/SparklineChart.tsx +1 -7
- package/packages/web/components/SparklineChart/SparklineChart.types.ts +6 -0
- package/packages/web/components/SparklineChart/index.ts +2 -0
- package/packages/web/components/StreakCard/StreakCard.constants.ts +2 -0
- package/packages/web/components/{stats → StreakCard}/StreakCard.tsx +5 -11
- package/packages/web/components/StreakCard/StreakCard.types.ts +4 -0
- package/packages/web/components/StreakCard/index.ts +2 -0
- package/packages/web/components/TasksCounter/TasksCounter.tsx +14 -0
- package/packages/web/components/TasksCounter/TasksCounter.types.ts +3 -0
- package/packages/web/components/TasksCounter/index.ts +2 -0
- package/packages/web/components/TechStackBadges/index.ts +1 -0
- package/packages/web/components/{TerminalTab.tsx → TerminalTabs/TerminalTab.tsx} +11 -0
- package/packages/web/components/{TerminalTabs.tsx → TerminalTabs/TerminalTabs.tsx} +29 -28
- package/packages/web/components/TerminalTabs/index.ts +1 -0
- package/packages/web/components/VelocityBadge/VelocityBadge.tsx +27 -0
- package/packages/web/components/VelocityBadge/VelocityBadge.types.ts +3 -0
- package/packages/web/components/VelocityBadge/index.ts +2 -0
- package/packages/web/components/VelocityCard/VelocityCard.tsx +71 -0
- package/packages/web/components/VelocityCard/VelocityCard.types.ts +7 -0
- package/packages/web/components/VelocityCard/index.ts +2 -0
- package/packages/web/components/WeeklySparkline/WeeklySparkline.tsx +13 -0
- package/packages/web/components/WeeklySparkline/WeeklySparkline.types.ts +3 -0
- package/packages/web/components/WeeklySparkline/index.ts +2 -0
- package/packages/web/components/ui/input.tsx +21 -0
- package/packages/web/context/TerminalTabsContext.tsx +46 -1
- package/packages/web/hooks/useClaudeTerminal.ts +71 -21
- package/packages/web/hooks/useProjectStats.ts +55 -0
- package/packages/web/hooks/useProjects.ts +6 -6
- package/packages/web/lib/actions/projects.ts +15 -0
- package/packages/web/lib/json-loader.ts +630 -0
- package/packages/web/lib/services/index.ts +9 -0
- package/packages/web/lib/services/migration.server.ts +598 -0
- package/packages/web/lib/services/projects.server.ts +52 -0
- package/packages/web/lib/services/stats.server.ts +264 -0
- package/packages/web/lib/unified-loader.ts +396 -0
- package/packages/web/package.json +10 -7
- package/packages/web/server.ts +36 -6
- package/templates/commands/done.md +76 -32
- package/templates/commands/feature.md +121 -47
- package/templates/commands/idea.md +81 -8
- package/templates/commands/now.md +41 -17
- package/templates/commands/ship.md +64 -25
- package/templates/commands/sync.md +28 -3
- package/core/agentic/agent-router.js +0 -140
- package/core/agentic/chain-of-thought.js +0 -578
- package/core/agentic/command-executor.js +0 -417
- package/core/agentic/context-filter.js +0 -354
- package/core/agentic/ground-truth.js +0 -591
- package/core/agentic/loop-detector.js +0 -406
- package/core/agentic/memory-system.js +0 -845
- package/core/agentic/parallel-tools.js +0 -366
- package/core/agentic/plan-mode.js +0 -572
- package/core/agentic/prompt-builder.js +0 -352
- package/core/agentic/response-templates.js +0 -290
- package/core/agentic/semantic-compression.js +0 -517
- package/core/agentic/think-blocks.js +0 -657
- package/core/agentic/tool-registry.js +0 -184
- package/core/agentic/validation-rules.js +0 -380
- package/core/command-registry.js +0 -698
- package/core/commands.js +0 -2237
- package/core/domain/task-stack.js +0 -497
- package/core/infrastructure/legacy-installer-detector.js +0 -546
- package/core/infrastructure/migrator.js +0 -796
- package/core/infrastructure/session-manager.js +0 -390
- package/core/utils/file-helper.js +0 -329
- package/packages/web/app/api/projects/[id]/delete/route.ts +0 -21
- package/packages/web/app/api/stats/route.ts +0 -38
- package/packages/web/components/AppSidebar.tsx +0 -113
- package/packages/web/components/stats/ActivityTimeline.tsx +0 -201
- package/packages/web/components/stats/AgentsCard.tsx +0 -56
- package/packages/web/components/stats/BentoCard.tsx +0 -88
- package/packages/web/components/stats/HeroSection.tsx +0 -172
- package/packages/web/components/stats/NowCard.tsx +0 -71
- package/packages/web/components/stats/QueueCard.tsx +0 -58
- package/packages/web/components/stats/VelocityCard.tsx +0 -60
- package/packages/web/components/stats/index.ts +0 -17
- package/packages/web/hooks/useStats.ts +0 -28
- /package/packages/web/components/{CommandButton.tsx → CommandButton/CommandButton.tsx} +0 -0
- /package/packages/web/components/{ConnectionStatus.tsx → ConnectionStatus/ConnectionStatus.tsx} +0 -0
- /package/packages/web/components/{Logo.tsx → Logo/Logo.tsx} +0 -0
- /package/packages/web/components/{MarkdownContent.tsx → MarkdownContent/MarkdownContent.tsx} +0 -0
- /package/packages/web/components/{ProjectAvatar.tsx → ProjectAvatar/ProjectAvatar.tsx} +0 -0
- /package/packages/web/components/{providers.tsx → Providers/Providers.tsx} +0 -0
- /package/packages/web/components/{TechStackBadges.tsx → TechStackBadges/TechStackBadges.tsx} +0 -0
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* @version 1.0.0
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
import { eventBus, EventTypes } from '../bus'
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
13
|
* Hook Points - Where plugins can intercept
|
|
@@ -38,47 +38,64 @@ const HookPoints = {
|
|
|
38
38
|
TRANSFORM_COMMIT_MESSAGE: 'transform:commit.message',
|
|
39
39
|
TRANSFORM_TASK_DATA: 'transform:task.data',
|
|
40
40
|
TRANSFORM_METRICS: 'transform:metrics'
|
|
41
|
+
} as const
|
|
42
|
+
|
|
43
|
+
type HookPoint = typeof HookPoints[keyof typeof HookPoints]
|
|
44
|
+
type HookHandler = (data: unknown, context?: unknown) => unknown | Promise<unknown>
|
|
45
|
+
|
|
46
|
+
interface HookEntry {
|
|
47
|
+
handler: HookHandler
|
|
48
|
+
pluginName: string
|
|
49
|
+
priority: number
|
|
50
|
+
id: string
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
interface HookRegisterOptions {
|
|
54
|
+
pluginName?: string
|
|
55
|
+
priority?: number
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
interface PluginHookEntry {
|
|
59
|
+
hookPoint: string
|
|
60
|
+
id: string
|
|
41
61
|
}
|
|
42
62
|
|
|
43
63
|
class HookSystem {
|
|
64
|
+
private hooks: Map<string, HookEntry[]>
|
|
65
|
+
private pluginHooks: Map<string, PluginHookEntry[]>
|
|
66
|
+
|
|
44
67
|
constructor() {
|
|
45
68
|
this.hooks = new Map()
|
|
46
|
-
this.pluginHooks = new Map()
|
|
69
|
+
this.pluginHooks = new Map()
|
|
47
70
|
}
|
|
48
71
|
|
|
49
72
|
/**
|
|
50
73
|
* Register a hook handler
|
|
51
|
-
* @param {string} hookPoint - Hook point from HookPoints
|
|
52
|
-
* @param {Function} handler - Handler function
|
|
53
|
-
* @param {Object} options
|
|
54
|
-
* @param {string} options.pluginName - Name of the plugin
|
|
55
|
-
* @param {number} options.priority - Execution order (lower = first)
|
|
56
|
-
* @returns {Function} Unregister function
|
|
57
74
|
*/
|
|
58
|
-
register(hookPoint, handler, options = {}) {
|
|
75
|
+
register(hookPoint: string, handler: HookHandler, options: HookRegisterOptions = {}): () => void {
|
|
59
76
|
const { pluginName = 'anonymous', priority = 10 } = options
|
|
60
77
|
|
|
61
78
|
if (!this.hooks.has(hookPoint)) {
|
|
62
79
|
this.hooks.set(hookPoint, [])
|
|
63
80
|
}
|
|
64
81
|
|
|
65
|
-
const hookEntry = {
|
|
82
|
+
const hookEntry: HookEntry = {
|
|
66
83
|
handler,
|
|
67
84
|
pluginName,
|
|
68
85
|
priority,
|
|
69
86
|
id: `${pluginName}:${Date.now()}`
|
|
70
87
|
}
|
|
71
88
|
|
|
72
|
-
this.hooks.get(hookPoint)
|
|
89
|
+
this.hooks.get(hookPoint)!.push(hookEntry)
|
|
73
90
|
|
|
74
91
|
// Sort by priority
|
|
75
|
-
this.hooks.get(hookPoint)
|
|
92
|
+
this.hooks.get(hookPoint)!.sort((a, b) => a.priority - b.priority)
|
|
76
93
|
|
|
77
94
|
// Track by plugin
|
|
78
95
|
if (!this.pluginHooks.has(pluginName)) {
|
|
79
96
|
this.pluginHooks.set(pluginName, [])
|
|
80
97
|
}
|
|
81
|
-
this.pluginHooks.get(pluginName)
|
|
98
|
+
this.pluginHooks.get(pluginName)!.push({ hookPoint, id: hookEntry.id })
|
|
82
99
|
|
|
83
100
|
// Return unregister function
|
|
84
101
|
return () => this.unregister(hookPoint, hookEntry.id)
|
|
@@ -86,10 +103,8 @@ class HookSystem {
|
|
|
86
103
|
|
|
87
104
|
/**
|
|
88
105
|
* Unregister a hook handler
|
|
89
|
-
* @param {string} hookPoint
|
|
90
|
-
* @param {string} id
|
|
91
106
|
*/
|
|
92
|
-
unregister(hookPoint, id) {
|
|
107
|
+
unregister(hookPoint: string, id: string): void {
|
|
93
108
|
const hooks = this.hooks.get(hookPoint)
|
|
94
109
|
if (hooks) {
|
|
95
110
|
const index = hooks.findIndex(h => h.id === id)
|
|
@@ -101,9 +116,8 @@ class HookSystem {
|
|
|
101
116
|
|
|
102
117
|
/**
|
|
103
118
|
* Unregister all hooks from a plugin
|
|
104
|
-
* @param {string} pluginName
|
|
105
119
|
*/
|
|
106
|
-
unregisterPlugin(pluginName) {
|
|
120
|
+
unregisterPlugin(pluginName: string): void {
|
|
107
121
|
const pluginEntries = this.pluginHooks.get(pluginName)
|
|
108
122
|
if (pluginEntries) {
|
|
109
123
|
for (const entry of pluginEntries) {
|
|
@@ -115,11 +129,8 @@ class HookSystem {
|
|
|
115
129
|
|
|
116
130
|
/**
|
|
117
131
|
* Execute a "before" hook (can modify data)
|
|
118
|
-
* @param {string} hookPoint
|
|
119
|
-
* @param {Object} data - Data that can be modified
|
|
120
|
-
* @returns {Promise<Object>} Modified data
|
|
121
132
|
*/
|
|
122
|
-
async executeBefore(hookPoint, data) {
|
|
133
|
+
async executeBefore(hookPoint: string, data: Record<string, unknown>): Promise<Record<string, unknown>> {
|
|
123
134
|
const hooks = this.hooks.get(hookPoint) || []
|
|
124
135
|
let result = { ...data }
|
|
125
136
|
|
|
@@ -127,10 +138,10 @@ class HookSystem {
|
|
|
127
138
|
try {
|
|
128
139
|
const modified = await hook.handler(result)
|
|
129
140
|
if (modified !== undefined) {
|
|
130
|
-
result = { ...result, ...modified }
|
|
141
|
+
result = { ...result, ...(modified as Record<string, unknown>) }
|
|
131
142
|
}
|
|
132
143
|
} catch (error) {
|
|
133
|
-
console.error(`Hook error [${hook.pluginName}] at ${hookPoint}:`, error.message)
|
|
144
|
+
console.error(`Hook error [${hook.pluginName}] at ${hookPoint}:`, (error as Error).message)
|
|
134
145
|
// Continue with other hooks
|
|
135
146
|
}
|
|
136
147
|
}
|
|
@@ -140,11 +151,8 @@ class HookSystem {
|
|
|
140
151
|
|
|
141
152
|
/**
|
|
142
153
|
* Execute an "after" hook (side effects only)
|
|
143
|
-
* @param {string} hookPoint
|
|
144
|
-
* @param {Object} data - Read-only data
|
|
145
|
-
* @returns {Promise<void>}
|
|
146
154
|
*/
|
|
147
|
-
async executeAfter(hookPoint, data) {
|
|
155
|
+
async executeAfter(hookPoint: string, data: Record<string, unknown>): Promise<void> {
|
|
148
156
|
const hooks = this.hooks.get(hookPoint) || []
|
|
149
157
|
|
|
150
158
|
// Execute all hooks in parallel for after hooks
|
|
@@ -153,7 +161,7 @@ class HookSystem {
|
|
|
153
161
|
try {
|
|
154
162
|
await hook.handler(data)
|
|
155
163
|
} catch (error) {
|
|
156
|
-
console.error(`Hook error [${hook.pluginName}] at ${hookPoint}:`, error.message)
|
|
164
|
+
console.error(`Hook error [${hook.pluginName}] at ${hookPoint}:`, (error as Error).message)
|
|
157
165
|
}
|
|
158
166
|
})
|
|
159
167
|
)
|
|
@@ -167,12 +175,8 @@ class HookSystem {
|
|
|
167
175
|
|
|
168
176
|
/**
|
|
169
177
|
* Execute a "transform" hook (must return modified value)
|
|
170
|
-
* @param {string} hookPoint
|
|
171
|
-
* @param {*} value - Value to transform
|
|
172
|
-
* @param {Object} context - Additional context
|
|
173
|
-
* @returns {Promise<*>} Transformed value
|
|
174
178
|
*/
|
|
175
|
-
async executeTransform(hookPoint, value, context = {}) {
|
|
179
|
+
async executeTransform<T>(hookPoint: string, value: T, context: Record<string, unknown> = {}): Promise<T> {
|
|
176
180
|
const hooks = this.hooks.get(hookPoint) || []
|
|
177
181
|
let result = value
|
|
178
182
|
|
|
@@ -180,10 +184,10 @@ class HookSystem {
|
|
|
180
184
|
try {
|
|
181
185
|
const transformed = await hook.handler(result, context)
|
|
182
186
|
if (transformed !== undefined) {
|
|
183
|
-
result = transformed
|
|
187
|
+
result = transformed as T
|
|
184
188
|
}
|
|
185
189
|
} catch (error) {
|
|
186
|
-
console.error(`Transform hook error [${hook.pluginName}] at ${hookPoint}:`, error.message)
|
|
190
|
+
console.error(`Transform hook error [${hook.pluginName}] at ${hookPoint}:`, (error as Error).message)
|
|
187
191
|
// Keep previous value on error
|
|
188
192
|
}
|
|
189
193
|
}
|
|
@@ -193,11 +197,9 @@ class HookSystem {
|
|
|
193
197
|
|
|
194
198
|
/**
|
|
195
199
|
* Map hook point to event type
|
|
196
|
-
* @param {string} hookPoint
|
|
197
|
-
* @returns {string|null}
|
|
198
200
|
*/
|
|
199
|
-
hookToEvent(hookPoint) {
|
|
200
|
-
const mapping = {
|
|
201
|
+
hookToEvent(hookPoint: string): string | null {
|
|
202
|
+
const mapping: Record<string, string> = {
|
|
201
203
|
[HookPoints.AFTER_SESSION_START]: EventTypes.SESSION_STARTED,
|
|
202
204
|
[HookPoints.AFTER_SESSION_COMPLETE]: EventTypes.SESSION_COMPLETED,
|
|
203
205
|
[HookPoints.AFTER_TASK_CREATE]: EventTypes.TASK_CREATED,
|
|
@@ -215,10 +217,8 @@ class HookSystem {
|
|
|
215
217
|
|
|
216
218
|
/**
|
|
217
219
|
* Get all registered hooks for a point
|
|
218
|
-
* @param {string} hookPoint
|
|
219
|
-
* @returns {Object[]}
|
|
220
220
|
*/
|
|
221
|
-
getHooks(hookPoint) {
|
|
221
|
+
getHooks(hookPoint: string): Array<{ pluginName: string; priority: number }> {
|
|
222
222
|
return (this.hooks.get(hookPoint) || []).map(h => ({
|
|
223
223
|
pluginName: h.pluginName,
|
|
224
224
|
priority: h.priority
|
|
@@ -227,28 +227,24 @@ class HookSystem {
|
|
|
227
227
|
|
|
228
228
|
/**
|
|
229
229
|
* Get all hooks registered by a plugin
|
|
230
|
-
* @param {string} pluginName
|
|
231
|
-
* @returns {string[]} Hook points
|
|
232
230
|
*/
|
|
233
|
-
getPluginHooks(pluginName) {
|
|
231
|
+
getPluginHooks(pluginName: string): string[] {
|
|
234
232
|
const entries = this.pluginHooks.get(pluginName) || []
|
|
235
233
|
return entries.map(e => e.hookPoint)
|
|
236
234
|
}
|
|
237
235
|
|
|
238
236
|
/**
|
|
239
237
|
* Check if a hook point has any handlers
|
|
240
|
-
* @param {string} hookPoint
|
|
241
|
-
* @returns {boolean}
|
|
242
238
|
*/
|
|
243
|
-
hasHooks(hookPoint) {
|
|
239
|
+
hasHooks(hookPoint: string): boolean {
|
|
244
240
|
const hooks = this.hooks.get(hookPoint)
|
|
245
|
-
return hooks && hooks.length > 0
|
|
241
|
+
return hooks !== undefined && hooks.length > 0
|
|
246
242
|
}
|
|
247
243
|
|
|
248
244
|
/**
|
|
249
245
|
* Clear all hooks
|
|
250
246
|
*/
|
|
251
|
-
clear() {
|
|
247
|
+
clear(): void {
|
|
252
248
|
this.hooks.clear()
|
|
253
249
|
this.pluginHooks.clear()
|
|
254
250
|
}
|
|
@@ -262,7 +258,7 @@ const hooks = {
|
|
|
262
258
|
/**
|
|
263
259
|
* Register a before hook
|
|
264
260
|
*/
|
|
265
|
-
before: (point, handler, options) => {
|
|
261
|
+
before: (point: string, handler: HookHandler, options?: HookRegisterOptions) => {
|
|
266
262
|
const hookPoint = `before:${point}`
|
|
267
263
|
return hookSystem.register(hookPoint, handler, options)
|
|
268
264
|
},
|
|
@@ -270,7 +266,7 @@ const hooks = {
|
|
|
270
266
|
/**
|
|
271
267
|
* Register an after hook
|
|
272
268
|
*/
|
|
273
|
-
after: (point, handler, options) => {
|
|
269
|
+
after: (point: string, handler: HookHandler, options?: HookRegisterOptions) => {
|
|
274
270
|
const hookPoint = `after:${point}`
|
|
275
271
|
return hookSystem.register(hookPoint, handler, options)
|
|
276
272
|
},
|
|
@@ -278,7 +274,7 @@ const hooks = {
|
|
|
278
274
|
/**
|
|
279
275
|
* Register a transform hook
|
|
280
276
|
*/
|
|
281
|
-
transform: (point, handler, options) => {
|
|
277
|
+
transform: (point: string, handler: HookHandler, options?: HookRegisterOptions) => {
|
|
282
278
|
const hookPoint = `transform:${point}`
|
|
283
279
|
return hookSystem.register(hookPoint, handler, options)
|
|
284
280
|
},
|
|
@@ -286,28 +282,30 @@ const hooks = {
|
|
|
286
282
|
/**
|
|
287
283
|
* Execute before hooks
|
|
288
284
|
*/
|
|
289
|
-
runBefore: (point, data) => {
|
|
285
|
+
runBefore: (point: string, data: Record<string, unknown>) => {
|
|
290
286
|
return hookSystem.executeBefore(`before:${point}`, data)
|
|
291
287
|
},
|
|
292
288
|
|
|
293
289
|
/**
|
|
294
290
|
* Execute after hooks
|
|
295
291
|
*/
|
|
296
|
-
runAfter: (point, data) => {
|
|
292
|
+
runAfter: (point: string, data: Record<string, unknown>) => {
|
|
297
293
|
return hookSystem.executeAfter(`after:${point}`, data)
|
|
298
294
|
},
|
|
299
295
|
|
|
300
296
|
/**
|
|
301
297
|
* Execute transform hooks
|
|
302
298
|
*/
|
|
303
|
-
runTransform: (point, value, context) => {
|
|
299
|
+
runTransform: <T>(point: string, value: T, context?: Record<string, unknown>) => {
|
|
304
300
|
return hookSystem.executeTransform(`transform:${point}`, value, context)
|
|
305
301
|
}
|
|
306
302
|
}
|
|
307
303
|
|
|
308
|
-
|
|
304
|
+
export {
|
|
309
305
|
HookSystem,
|
|
310
306
|
HookPoints,
|
|
311
307
|
hookSystem,
|
|
312
308
|
hooks
|
|
313
309
|
}
|
|
310
|
+
|
|
311
|
+
export default { HookSystem, HookPoints, hookSystem, hooks }
|
|
@@ -6,16 +6,14 @@
|
|
|
6
6
|
* @version 1.0.0
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
import { HookSystem, HookPoints, hookSystem, hooks } from './hooks'
|
|
10
|
+
import { PluginLoader, pluginLoader } from './loader'
|
|
11
|
+
import { PluginRegistry, pluginRegistry } from './registry'
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
14
|
* Initialize the complete plugin system
|
|
15
|
-
* @param {string} projectPath
|
|
16
|
-
* @param {Object} config
|
|
17
15
|
*/
|
|
18
|
-
async function initializePlugins(projectPath, config = {}) {
|
|
16
|
+
async function initializePlugins(projectPath: string, config: Record<string, unknown> = {}): Promise<void> {
|
|
19
17
|
await pluginRegistry.initialize()
|
|
20
18
|
await pluginLoader.initialize(projectPath, config)
|
|
21
19
|
}
|
|
@@ -23,7 +21,7 @@ async function initializePlugins(projectPath, config = {}) {
|
|
|
23
21
|
/**
|
|
24
22
|
* Shutdown the plugin system
|
|
25
23
|
*/
|
|
26
|
-
async function shutdownPlugins() {
|
|
24
|
+
async function shutdownPlugins(): Promise<void> {
|
|
27
25
|
const plugins = pluginLoader.getAllPlugins()
|
|
28
26
|
|
|
29
27
|
for (const plugin of plugins) {
|
|
@@ -31,7 +29,7 @@ async function shutdownPlugins() {
|
|
|
31
29
|
}
|
|
32
30
|
}
|
|
33
31
|
|
|
34
|
-
|
|
32
|
+
export {
|
|
35
33
|
// Hook system
|
|
36
34
|
HookSystem,
|
|
37
35
|
HookPoints,
|
|
@@ -50,3 +48,16 @@ module.exports = {
|
|
|
50
48
|
initializePlugins,
|
|
51
49
|
shutdownPlugins
|
|
52
50
|
}
|
|
51
|
+
|
|
52
|
+
export default {
|
|
53
|
+
HookSystem,
|
|
54
|
+
HookPoints,
|
|
55
|
+
hookSystem,
|
|
56
|
+
hooks,
|
|
57
|
+
PluginLoader,
|
|
58
|
+
pluginLoader,
|
|
59
|
+
PluginRegistry,
|
|
60
|
+
pluginRegistry,
|
|
61
|
+
initializePlugins,
|
|
62
|
+
shutdownPlugins
|
|
63
|
+
}
|
|
@@ -9,37 +9,66 @@
|
|
|
9
9
|
* @version 1.0.0
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
12
|
+
import fs from 'fs/promises'
|
|
13
|
+
import path from 'path'
|
|
14
|
+
import { hookSystem } from './hooks'
|
|
15
|
+
import { eventBus } from '../bus'
|
|
16
|
+
import pathManager from '../infrastructure/path-manager'
|
|
17
|
+
|
|
18
|
+
type PluginSource = 'builtin' | 'global' | 'project'
|
|
19
|
+
type HookHandler = (data: unknown) => unknown | Promise<unknown>
|
|
20
|
+
|
|
21
|
+
interface Plugin {
|
|
22
|
+
name: string
|
|
23
|
+
version?: string
|
|
24
|
+
description?: string
|
|
25
|
+
hooks?: Record<string, HookHandler>
|
|
26
|
+
events?: Record<string, HookHandler>
|
|
27
|
+
commands?: Record<string, { handler: () => void; description?: string }>
|
|
28
|
+
priority?: number
|
|
29
|
+
activate?: (context: PluginContext) => Promise<void>
|
|
30
|
+
deactivate?: () => Promise<void>
|
|
31
|
+
source?: PluginSource
|
|
32
|
+
config?: Record<string, unknown>
|
|
33
|
+
}
|
|
17
34
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
35
|
+
interface PluginContext {
|
|
36
|
+
config: Record<string, unknown>
|
|
37
|
+
eventBus: typeof eventBus
|
|
38
|
+
hookSystem: typeof hookSystem
|
|
39
|
+
projectPath: string
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
interface PluginSpec {
|
|
43
|
+
path: string
|
|
44
|
+
config?: Record<string, unknown>
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
interface CommandInfo {
|
|
48
|
+
handler: () => void
|
|
49
|
+
plugin: string
|
|
50
|
+
description: string
|
|
51
|
+
}
|
|
29
52
|
|
|
30
53
|
class PluginLoader {
|
|
54
|
+
private plugins: Map<string, Plugin>
|
|
55
|
+
private pluginPaths: Map<string, string>
|
|
56
|
+
private initialized: boolean
|
|
57
|
+
private projectPath: string
|
|
58
|
+
private config: Record<string, unknown>
|
|
59
|
+
|
|
31
60
|
constructor() {
|
|
32
61
|
this.plugins = new Map()
|
|
33
62
|
this.pluginPaths = new Map()
|
|
34
63
|
this.initialized = false
|
|
64
|
+
this.projectPath = ''
|
|
65
|
+
this.config = {}
|
|
35
66
|
}
|
|
36
67
|
|
|
37
68
|
/**
|
|
38
69
|
* Initialize plugin system
|
|
39
|
-
* @param {string} projectPath - Project root path
|
|
40
|
-
* @param {Object} config - Project config
|
|
41
70
|
*/
|
|
42
|
-
async initialize(projectPath, config = {}) {
|
|
71
|
+
async initialize(projectPath: string, config: Record<string, unknown> = {}): Promise<void> {
|
|
43
72
|
if (this.initialized) return
|
|
44
73
|
|
|
45
74
|
this.projectPath = projectPath
|
|
@@ -48,7 +77,7 @@ class PluginLoader {
|
|
|
48
77
|
// Load plugins in order
|
|
49
78
|
await this.loadBuiltinPlugins()
|
|
50
79
|
await this.loadGlobalPlugins()
|
|
51
|
-
await this.loadProjectPlugins(config.plugins || [])
|
|
80
|
+
await this.loadProjectPlugins((config.plugins as Array<string | PluginSpec>) || [])
|
|
52
81
|
|
|
53
82
|
this.initialized = true
|
|
54
83
|
}
|
|
@@ -56,14 +85,14 @@ class PluginLoader {
|
|
|
56
85
|
/**
|
|
57
86
|
* Load built-in plugins from core/plugins
|
|
58
87
|
*/
|
|
59
|
-
async loadBuiltinPlugins() {
|
|
88
|
+
async loadBuiltinPlugins(): Promise<void> {
|
|
60
89
|
const builtinPath = path.join(__dirname, '..', 'plugins')
|
|
61
90
|
|
|
62
91
|
try {
|
|
63
92
|
const files = await fs.readdir(builtinPath)
|
|
64
93
|
|
|
65
94
|
for (const file of files) {
|
|
66
|
-
if (file.endsWith('.js')) {
|
|
95
|
+
if (file.endsWith('.js') || file.endsWith('.ts')) {
|
|
67
96
|
const pluginPath = path.join(builtinPath, file)
|
|
68
97
|
await this.loadPlugin(pluginPath, 'builtin')
|
|
69
98
|
}
|
|
@@ -76,17 +105,18 @@ class PluginLoader {
|
|
|
76
105
|
/**
|
|
77
106
|
* Load global plugins from ~/.prjct-cli/plugins
|
|
78
107
|
*/
|
|
79
|
-
async loadGlobalPlugins() {
|
|
108
|
+
async loadGlobalPlugins(): Promise<void> {
|
|
80
109
|
const globalPath = path.join(pathManager.getGlobalStoragePath(), 'plugins')
|
|
81
110
|
|
|
82
111
|
try {
|
|
83
112
|
const files = await fs.readdir(globalPath)
|
|
84
113
|
|
|
85
114
|
for (const file of files) {
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
115
|
+
const filePath = path.join(globalPath, file)
|
|
116
|
+
if (file.endsWith('.js') || file.endsWith('.ts') || (await this.isDirectory(filePath))) {
|
|
117
|
+
const pluginPath = (file.endsWith('.js') || file.endsWith('.ts'))
|
|
118
|
+
? filePath
|
|
119
|
+
: path.join(filePath, 'index.js')
|
|
90
120
|
await this.loadPlugin(pluginPath, 'global')
|
|
91
121
|
}
|
|
92
122
|
}
|
|
@@ -97,9 +127,8 @@ class PluginLoader {
|
|
|
97
127
|
|
|
98
128
|
/**
|
|
99
129
|
* Load project-specific plugins from config
|
|
100
|
-
* @param {Array<string|Object>} plugins - Plugin specs from config
|
|
101
130
|
*/
|
|
102
|
-
async loadProjectPlugins(plugins) {
|
|
131
|
+
async loadProjectPlugins(plugins: Array<string | PluginSpec>): Promise<void> {
|
|
103
132
|
for (const spec of plugins) {
|
|
104
133
|
try {
|
|
105
134
|
if (typeof spec === 'string') {
|
|
@@ -125,24 +154,21 @@ class PluginLoader {
|
|
|
125
154
|
await this.loadPlugin(fullPath, 'project', spec.config)
|
|
126
155
|
}
|
|
127
156
|
} catch (error) {
|
|
128
|
-
console.error(`Failed to load plugin: ${spec}`, error.message)
|
|
157
|
+
console.error(`Failed to load plugin: ${spec}`, (error as Error).message)
|
|
129
158
|
}
|
|
130
159
|
}
|
|
131
160
|
}
|
|
132
161
|
|
|
133
162
|
/**
|
|
134
163
|
* Load a single plugin
|
|
135
|
-
* @param {string} pluginPath - Path to plugin file
|
|
136
|
-
* @param {string} source - 'builtin', 'global', or 'project'
|
|
137
|
-
* @param {Object} config - Plugin-specific config
|
|
138
164
|
*/
|
|
139
|
-
async loadPlugin(pluginPath, source, config = {}) {
|
|
165
|
+
async loadPlugin(pluginPath: string, source: PluginSource, config: Record<string, unknown> = {}): Promise<void> {
|
|
140
166
|
try {
|
|
141
167
|
// Check if file exists
|
|
142
168
|
await fs.access(pluginPath)
|
|
143
169
|
|
|
144
170
|
// Require the plugin
|
|
145
|
-
const plugin = require(pluginPath)
|
|
171
|
+
const plugin: Plugin = require(pluginPath)
|
|
146
172
|
|
|
147
173
|
// Validate plugin structure
|
|
148
174
|
if (!plugin.name) {
|
|
@@ -158,7 +184,7 @@ class PluginLoader {
|
|
|
158
184
|
this.plugins.set(plugin.name, {
|
|
159
185
|
...plugin,
|
|
160
186
|
source,
|
|
161
|
-
config: { ...config, ...this.config[plugin.name] }
|
|
187
|
+
config: { ...config, ...(this.config[plugin.name] as Record<string, unknown> || {}) }
|
|
162
188
|
})
|
|
163
189
|
this.pluginPaths.set(plugin.name, pluginPath)
|
|
164
190
|
|
|
@@ -175,7 +201,7 @@ class PluginLoader {
|
|
|
175
201
|
// Call activate if exists
|
|
176
202
|
if (typeof plugin.activate === 'function') {
|
|
177
203
|
await plugin.activate({
|
|
178
|
-
config: this.plugins.get(plugin.name)
|
|
204
|
+
config: this.plugins.get(plugin.name)!.config!,
|
|
179
205
|
eventBus,
|
|
180
206
|
hookSystem,
|
|
181
207
|
projectPath: this.projectPath
|
|
@@ -183,22 +209,22 @@ class PluginLoader {
|
|
|
183
209
|
}
|
|
184
210
|
|
|
185
211
|
} catch (error) {
|
|
186
|
-
|
|
212
|
+
const err = error as NodeJS.ErrnoException
|
|
213
|
+
if (err.code === 'ENOENT') {
|
|
187
214
|
// File not found - skip silently
|
|
188
|
-
} else if (
|
|
215
|
+
} else if (err.code === 'MODULE_NOT_FOUND') {
|
|
189
216
|
console.error(`Plugin module not found: ${pluginPath}`)
|
|
190
217
|
} else {
|
|
191
|
-
console.error(`Failed to load plugin from ${pluginPath}:`,
|
|
218
|
+
console.error(`Failed to load plugin from ${pluginPath}:`, err.message)
|
|
192
219
|
}
|
|
193
220
|
}
|
|
194
221
|
}
|
|
195
222
|
|
|
196
223
|
/**
|
|
197
224
|
* Register plugin hooks
|
|
198
|
-
* @param {Plugin} plugin
|
|
199
225
|
*/
|
|
200
|
-
registerPluginHooks(plugin) {
|
|
201
|
-
for (const [hookPoint, handler] of Object.entries(plugin.hooks)) {
|
|
226
|
+
registerPluginHooks(plugin: Plugin): void {
|
|
227
|
+
for (const [hookPoint, handler] of Object.entries(plugin.hooks || {})) {
|
|
202
228
|
hookSystem.register(hookPoint, handler, {
|
|
203
229
|
pluginName: plugin.name,
|
|
204
230
|
priority: plugin.priority || 10
|
|
@@ -208,19 +234,17 @@ class PluginLoader {
|
|
|
208
234
|
|
|
209
235
|
/**
|
|
210
236
|
* Register plugin event listeners
|
|
211
|
-
* @param {Plugin} plugin
|
|
212
237
|
*/
|
|
213
|
-
registerPluginEvents(plugin) {
|
|
214
|
-
for (const [eventType, handler] of Object.entries(plugin.events)) {
|
|
238
|
+
registerPluginEvents(plugin: Plugin): void {
|
|
239
|
+
for (const [eventType, handler] of Object.entries(plugin.events || {})) {
|
|
215
240
|
eventBus.on(eventType, handler)
|
|
216
241
|
}
|
|
217
242
|
}
|
|
218
243
|
|
|
219
244
|
/**
|
|
220
245
|
* Unload a plugin
|
|
221
|
-
* @param {string} name - Plugin name
|
|
222
246
|
*/
|
|
223
|
-
async unloadPlugin(name) {
|
|
247
|
+
async unloadPlugin(name: string): Promise<void> {
|
|
224
248
|
const plugin = this.plugins.get(name)
|
|
225
249
|
if (!plugin) return
|
|
226
250
|
|
|
@@ -234,20 +258,19 @@ class PluginLoader {
|
|
|
234
258
|
|
|
235
259
|
// Remove from loaded plugins
|
|
236
260
|
this.plugins.delete(name)
|
|
237
|
-
this.pluginPaths.delete(name)
|
|
238
261
|
|
|
239
262
|
// Clear require cache
|
|
240
263
|
const pluginPath = this.pluginPaths.get(name)
|
|
241
264
|
if (pluginPath) {
|
|
242
265
|
delete require.cache[require.resolve(pluginPath)]
|
|
243
266
|
}
|
|
267
|
+
this.pluginPaths.delete(name)
|
|
244
268
|
}
|
|
245
269
|
|
|
246
270
|
/**
|
|
247
271
|
* Reload a plugin
|
|
248
|
-
* @param {string} name - Plugin name
|
|
249
272
|
*/
|
|
250
|
-
async reloadPlugin(name) {
|
|
273
|
+
async reloadPlugin(name: string): Promise<void> {
|
|
251
274
|
const pluginPath = this.pluginPaths.get(name)
|
|
252
275
|
const plugin = this.plugins.get(name)
|
|
253
276
|
|
|
@@ -256,47 +279,41 @@ class PluginLoader {
|
|
|
256
279
|
}
|
|
257
280
|
|
|
258
281
|
await this.unloadPlugin(name)
|
|
259
|
-
await this.loadPlugin(pluginPath, plugin.source
|
|
282
|
+
await this.loadPlugin(pluginPath, plugin.source!, plugin.config)
|
|
260
283
|
}
|
|
261
284
|
|
|
262
285
|
/**
|
|
263
286
|
* Get a loaded plugin
|
|
264
|
-
* @param {string} name
|
|
265
|
-
* @returns {Plugin|null}
|
|
266
287
|
*/
|
|
267
|
-
getPlugin(name) {
|
|
288
|
+
getPlugin(name: string): Plugin | null {
|
|
268
289
|
return this.plugins.get(name) || null
|
|
269
290
|
}
|
|
270
291
|
|
|
271
292
|
/**
|
|
272
293
|
* Get all loaded plugins
|
|
273
|
-
* @returns {Plugin[]}
|
|
274
294
|
*/
|
|
275
|
-
getAllPlugins() {
|
|
295
|
+
getAllPlugins(): Plugin[] {
|
|
276
296
|
return Array.from(this.plugins.values())
|
|
277
297
|
}
|
|
278
298
|
|
|
279
299
|
/**
|
|
280
300
|
* Get plugins by source
|
|
281
|
-
* @param {string} source - 'builtin', 'global', or 'project'
|
|
282
|
-
* @returns {Plugin[]}
|
|
283
301
|
*/
|
|
284
|
-
getPluginsBySource(source) {
|
|
302
|
+
getPluginsBySource(source: PluginSource): Plugin[] {
|
|
285
303
|
return this.getAllPlugins().filter(p => p.source === source)
|
|
286
304
|
}
|
|
287
305
|
|
|
288
306
|
/**
|
|
289
307
|
* Get custom commands from all plugins
|
|
290
|
-
* @returns {Object} Map of command name to handler
|
|
291
308
|
*/
|
|
292
|
-
getPluginCommands() {
|
|
293
|
-
const commands = {}
|
|
309
|
+
getPluginCommands(): Record<string, CommandInfo> {
|
|
310
|
+
const commands: Record<string, CommandInfo> = {}
|
|
294
311
|
|
|
295
312
|
for (const plugin of this.plugins.values()) {
|
|
296
313
|
if (plugin.commands) {
|
|
297
314
|
for (const [name, handler] of Object.entries(plugin.commands)) {
|
|
298
315
|
commands[name] = {
|
|
299
|
-
handler,
|
|
316
|
+
handler: handler.handler,
|
|
300
317
|
plugin: plugin.name,
|
|
301
318
|
description: handler.description || `Command from ${plugin.name}`
|
|
302
319
|
}
|
|
@@ -309,10 +326,8 @@ class PluginLoader {
|
|
|
309
326
|
|
|
310
327
|
/**
|
|
311
328
|
* Check if path is a directory
|
|
312
|
-
* @param {string} p
|
|
313
|
-
* @returns {Promise<boolean>}
|
|
314
329
|
*/
|
|
315
|
-
async isDirectory(p) {
|
|
330
|
+
async isDirectory(p: string): Promise<boolean> {
|
|
316
331
|
try {
|
|
317
332
|
const stat = await fs.stat(p)
|
|
318
333
|
return stat.isDirectory()
|
|
@@ -325,7 +340,10 @@ class PluginLoader {
|
|
|
325
340
|
// Singleton instance
|
|
326
341
|
const pluginLoader = new PluginLoader()
|
|
327
342
|
|
|
328
|
-
|
|
343
|
+
export {
|
|
329
344
|
PluginLoader,
|
|
330
|
-
pluginLoader
|
|
345
|
+
pluginLoader,
|
|
346
|
+
Plugin
|
|
331
347
|
}
|
|
348
|
+
|
|
349
|
+
export default { PluginLoader, pluginLoader }
|