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
|
@@ -0,0 +1,340 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Task Stack Manager - Core class
|
|
3
|
+
* Handles multiple concurrent tasks with pause/resume capability
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import path from 'path'
|
|
7
|
+
import fs from 'fs/promises'
|
|
8
|
+
import { exec } from 'child_process'
|
|
9
|
+
import { promisify } from 'util'
|
|
10
|
+
import type { TaskEntry, MigrationResult, SwitchResult, StackSummary } from './types'
|
|
11
|
+
import { parseNowFile, formatDuration } from './parser'
|
|
12
|
+
import { ensureStackFile, appendToStack, readStack, writeStack, updateNowFile } from './storage'
|
|
13
|
+
|
|
14
|
+
const execAsync = promisify(exec)
|
|
15
|
+
|
|
16
|
+
export class TaskStack {
|
|
17
|
+
projectPath: string
|
|
18
|
+
stackPath: string
|
|
19
|
+
nowPath: string
|
|
20
|
+
|
|
21
|
+
constructor(projectPath: string) {
|
|
22
|
+
this.projectPath = projectPath
|
|
23
|
+
this.stackPath = path.join(projectPath, 'core', 'stack.jsonl')
|
|
24
|
+
this.nowPath = path.join(projectPath, 'core', 'now.md')
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Initialize stack system - migrate from legacy now.md if needed
|
|
29
|
+
*/
|
|
30
|
+
async initialize(): Promise<MigrationResult> {
|
|
31
|
+
try {
|
|
32
|
+
// Check if stack already exists
|
|
33
|
+
await fs.access(this.stackPath)
|
|
34
|
+
return { migrated: false }
|
|
35
|
+
} catch {
|
|
36
|
+
// Stack doesn't exist, check for legacy now.md
|
|
37
|
+
return await this.migrateFromLegacy()
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Migrate from legacy now.md to stack system
|
|
43
|
+
*/
|
|
44
|
+
async migrateFromLegacy(): Promise<MigrationResult> {
|
|
45
|
+
try {
|
|
46
|
+
const nowContent = await fs.readFile(this.nowPath, 'utf8')
|
|
47
|
+
|
|
48
|
+
if (!nowContent.trim() || nowContent.includes('No active task')) {
|
|
49
|
+
// Empty or no task, just create empty stack
|
|
50
|
+
await ensureStackFile(this.stackPath)
|
|
51
|
+
return { migrated: true, hadTask: false }
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Parse task from now.md
|
|
55
|
+
const task = parseNowFile(nowContent)
|
|
56
|
+
|
|
57
|
+
// Create initial stack entry
|
|
58
|
+
const entry: TaskEntry = {
|
|
59
|
+
id: `task-${Date.now()}`,
|
|
60
|
+
task: task.description || 'Migrated task',
|
|
61
|
+
agent: task.agent || 'unknown',
|
|
62
|
+
status: 'active',
|
|
63
|
+
started: task.started || new Date().toISOString(),
|
|
64
|
+
paused: null,
|
|
65
|
+
resumed: null,
|
|
66
|
+
completed: null,
|
|
67
|
+
duration: null,
|
|
68
|
+
complexity: task.complexity || 'moderate',
|
|
69
|
+
dev: task.dev || 'unknown',
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Write to stack
|
|
73
|
+
await appendToStack(this.stackPath, entry)
|
|
74
|
+
|
|
75
|
+
return { migrated: true, hadTask: true, task: entry }
|
|
76
|
+
} catch (error) {
|
|
77
|
+
// No now.md or error reading, just create empty stack
|
|
78
|
+
await ensureStackFile(this.stackPath)
|
|
79
|
+
return { migrated: true, hadTask: false, error: (error as Error).message }
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// Re-expose parseNowFile for compatibility
|
|
84
|
+
parseNowFile(content: string) {
|
|
85
|
+
return parseNowFile(content)
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// Re-expose formatDuration for compatibility
|
|
89
|
+
formatDuration(ms: number): string {
|
|
90
|
+
return formatDuration(ms)
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Get active task
|
|
95
|
+
*/
|
|
96
|
+
async getActiveTask(): Promise<TaskEntry | null> {
|
|
97
|
+
const stack = await readStack(this.stackPath)
|
|
98
|
+
return stack.find((task) => task.status === 'active') || null
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Get paused tasks
|
|
103
|
+
*/
|
|
104
|
+
async getPausedTasks(): Promise<TaskEntry[]> {
|
|
105
|
+
const stack = await readStack(this.stackPath)
|
|
106
|
+
return stack
|
|
107
|
+
.filter((task) => task.status === 'paused')
|
|
108
|
+
.sort((a, b) => new Date(b.paused!).getTime() - new Date(a.paused!).getTime())
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Get all incomplete tasks
|
|
113
|
+
*/
|
|
114
|
+
async getIncompleteTasks(): Promise<TaskEntry[]> {
|
|
115
|
+
const stack = await readStack(this.stackPath)
|
|
116
|
+
return stack.filter((task) => task.status !== 'completed')
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Start a new task
|
|
121
|
+
*/
|
|
122
|
+
async startTask(description: string, agent: string = 'general', complexity: string = 'moderate'): Promise<TaskEntry> {
|
|
123
|
+
// Check if there's already an active task
|
|
124
|
+
const active = await this.getActiveTask()
|
|
125
|
+
if (active) {
|
|
126
|
+
throw new Error(`Already working on: ${active.task}. Use /p:pause to pause it first.`)
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
const entry: TaskEntry = {
|
|
130
|
+
id: `task-${Date.now()}`,
|
|
131
|
+
task: description,
|
|
132
|
+
agent,
|
|
133
|
+
status: 'active',
|
|
134
|
+
started: new Date().toISOString(),
|
|
135
|
+
paused: null,
|
|
136
|
+
resumed: null,
|
|
137
|
+
completed: null,
|
|
138
|
+
duration: null,
|
|
139
|
+
complexity,
|
|
140
|
+
dev: await this.getCurrentDev(),
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
await appendToStack(this.stackPath, entry)
|
|
144
|
+
await updateNowFile(this.nowPath, entry, null, formatDuration)
|
|
145
|
+
|
|
146
|
+
return entry
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Pause the active task
|
|
151
|
+
*/
|
|
152
|
+
async pauseTask(reason: string = ''): Promise<TaskEntry> {
|
|
153
|
+
const active = await this.getActiveTask()
|
|
154
|
+
if (!active) {
|
|
155
|
+
throw new Error('No active task to pause')
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// Update the task
|
|
159
|
+
active.status = 'paused'
|
|
160
|
+
active.paused = new Date().toISOString()
|
|
161
|
+
if (reason) {
|
|
162
|
+
active.pauseReason = reason
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// Rewrite stack with updated task
|
|
166
|
+
await this.updateTask(active)
|
|
167
|
+
|
|
168
|
+
// Update now.md to show paused state
|
|
169
|
+
await updateNowFile(this.nowPath, null, `Paused: ${active.task}`, formatDuration)
|
|
170
|
+
|
|
171
|
+
return active
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Resume a paused task
|
|
176
|
+
*/
|
|
177
|
+
async resumeTask(taskId: string | null = null): Promise<TaskEntry> {
|
|
178
|
+
// Check if there's an active task
|
|
179
|
+
const active = await this.getActiveTask()
|
|
180
|
+
if (active) {
|
|
181
|
+
throw new Error(`Already working on: ${active.task}. Complete or pause it first.`)
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
const paused = await this.getPausedTasks()
|
|
185
|
+
if (paused.length === 0) {
|
|
186
|
+
throw new Error('No paused tasks to resume')
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
let taskToResume: TaskEntry | undefined
|
|
190
|
+
if (taskId) {
|
|
191
|
+
taskToResume = paused.find((t) => t.id === taskId)
|
|
192
|
+
if (!taskToResume) {
|
|
193
|
+
throw new Error(`Task ${taskId} not found or not paused`)
|
|
194
|
+
}
|
|
195
|
+
} else {
|
|
196
|
+
// Resume most recently paused
|
|
197
|
+
taskToResume = paused[0]
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// Update the task
|
|
201
|
+
taskToResume.status = 'active'
|
|
202
|
+
taskToResume.resumed = new Date().toISOString()
|
|
203
|
+
|
|
204
|
+
// Calculate paused duration
|
|
205
|
+
if (taskToResume.paused) {
|
|
206
|
+
const pausedMs = Date.now() - new Date(taskToResume.paused).getTime()
|
|
207
|
+
taskToResume.pausedDuration = (taskToResume.pausedDuration || 0) + pausedMs
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// Rewrite stack with updated task
|
|
211
|
+
await this.updateTask(taskToResume)
|
|
212
|
+
|
|
213
|
+
// Update now.md
|
|
214
|
+
await updateNowFile(this.nowPath, taskToResume, null, formatDuration)
|
|
215
|
+
|
|
216
|
+
return taskToResume
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* Complete the active task
|
|
221
|
+
*/
|
|
222
|
+
async completeTask(): Promise<TaskEntry> {
|
|
223
|
+
const active = await this.getActiveTask()
|
|
224
|
+
if (!active) {
|
|
225
|
+
throw new Error('No active task to complete')
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
// Update the task
|
|
229
|
+
active.status = 'completed'
|
|
230
|
+
active.completed = new Date().toISOString()
|
|
231
|
+
|
|
232
|
+
// Calculate duration (excluding paused time)
|
|
233
|
+
const totalMs = Date.now() - new Date(active.started).getTime()
|
|
234
|
+
const pausedMs = active.pausedDuration || 0
|
|
235
|
+
active.duration = totalMs - pausedMs
|
|
236
|
+
active.durationFormatted = formatDuration(active.duration)
|
|
237
|
+
|
|
238
|
+
// Rewrite stack with updated task
|
|
239
|
+
await this.updateTask(active)
|
|
240
|
+
|
|
241
|
+
// Clear now.md
|
|
242
|
+
await updateNowFile(this.nowPath, null, '', formatDuration)
|
|
243
|
+
|
|
244
|
+
return active
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* Switch tasks (atomic pause + resume/start)
|
|
249
|
+
*/
|
|
250
|
+
async switchTask(targetTaskOrDescription: string): Promise<SwitchResult> {
|
|
251
|
+
const active = await this.getActiveTask()
|
|
252
|
+
let pausedTask: TaskEntry | null = null
|
|
253
|
+
|
|
254
|
+
// Pause current if exists
|
|
255
|
+
if (active) {
|
|
256
|
+
pausedTask = await this.pauseTask('Switched to another task')
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
try {
|
|
260
|
+
// Check if target is a task ID or description
|
|
261
|
+
const paused = await this.getPausedTasks()
|
|
262
|
+
const existingTask = paused.find((t) => t.id === targetTaskOrDescription)
|
|
263
|
+
|
|
264
|
+
if (existingTask) {
|
|
265
|
+
// Resume existing task
|
|
266
|
+
return {
|
|
267
|
+
paused: pausedTask,
|
|
268
|
+
resumed: await this.resumeTask(targetTaskOrDescription),
|
|
269
|
+
type: 'resumed',
|
|
270
|
+
}
|
|
271
|
+
} else {
|
|
272
|
+
// Start new task
|
|
273
|
+
return {
|
|
274
|
+
paused: pausedTask,
|
|
275
|
+
started: await this.startTask(targetTaskOrDescription),
|
|
276
|
+
type: 'started',
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
} catch (error) {
|
|
280
|
+
// If switch fails, resume the original task
|
|
281
|
+
if (pausedTask) {
|
|
282
|
+
await this.resumeTask(pausedTask.id)
|
|
283
|
+
}
|
|
284
|
+
throw error
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
/**
|
|
289
|
+
* Update a task in the stack
|
|
290
|
+
*/
|
|
291
|
+
async updateTask(updatedTask: TaskEntry): Promise<void> {
|
|
292
|
+
const stack = await readStack(this.stackPath)
|
|
293
|
+
const index = stack.findIndex((t) => t.id === updatedTask.id)
|
|
294
|
+
|
|
295
|
+
if (index === -1) {
|
|
296
|
+
throw new Error(`Task ${updatedTask.id} not found`)
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
stack[index] = updatedTask
|
|
300
|
+
await writeStack(this.stackPath, stack)
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
/**
|
|
304
|
+
* Update now.md to reflect current state
|
|
305
|
+
*/
|
|
306
|
+
async updateNowFile(task: TaskEntry | null, customContent: string | null = null): Promise<void> {
|
|
307
|
+
await updateNowFile(this.nowPath, task, customContent, formatDuration)
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
/**
|
|
311
|
+
* Get current developer from git or system
|
|
312
|
+
*/
|
|
313
|
+
async getCurrentDev(): Promise<string> {
|
|
314
|
+
try {
|
|
315
|
+
const { stdout } = await execAsync('git config user.name')
|
|
316
|
+
return stdout.trim()
|
|
317
|
+
} catch {
|
|
318
|
+
return 'unknown'
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
/**
|
|
323
|
+
* Get stack summary for display
|
|
324
|
+
*/
|
|
325
|
+
async getStackSummary(): Promise<StackSummary> {
|
|
326
|
+
const active = await this.getActiveTask()
|
|
327
|
+
const paused = await this.getPausedTasks()
|
|
328
|
+
const stack = await readStack(this.stackPath)
|
|
329
|
+
const completed = stack.filter((t) => t.status === 'completed')
|
|
330
|
+
|
|
331
|
+
return {
|
|
332
|
+
active,
|
|
333
|
+
paused,
|
|
334
|
+
pausedCount: paused.length,
|
|
335
|
+
completed,
|
|
336
|
+
completedCount: completed.length,
|
|
337
|
+
totalTasks: stack.length,
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Task Stack Types
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
export interface TaskEntry {
|
|
6
|
+
id: string
|
|
7
|
+
task: string
|
|
8
|
+
agent: string
|
|
9
|
+
status: 'active' | 'paused' | 'completed'
|
|
10
|
+
started: string
|
|
11
|
+
paused: string | null
|
|
12
|
+
resumed: string | null
|
|
13
|
+
completed: string | null
|
|
14
|
+
duration: number | null
|
|
15
|
+
durationFormatted?: string
|
|
16
|
+
complexity: string
|
|
17
|
+
dev: string
|
|
18
|
+
pauseReason?: string
|
|
19
|
+
pausedDuration?: number
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface ParsedNowFile {
|
|
23
|
+
description: string
|
|
24
|
+
started: string | null
|
|
25
|
+
agent: string | null
|
|
26
|
+
complexity: string | null
|
|
27
|
+
dev: string | null
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export interface MigrationResult {
|
|
31
|
+
migrated: boolean
|
|
32
|
+
hadTask?: boolean
|
|
33
|
+
task?: TaskEntry
|
|
34
|
+
error?: string
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export interface SwitchResult {
|
|
38
|
+
paused: TaskEntry | null
|
|
39
|
+
resumed?: TaskEntry
|
|
40
|
+
started?: TaskEntry
|
|
41
|
+
type: 'resumed' | 'started'
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export interface StackSummary {
|
|
45
|
+
active: TaskEntry | null
|
|
46
|
+
paused: TaskEntry[]
|
|
47
|
+
pausedCount: number
|
|
48
|
+
completed: TaskEntry[]
|
|
49
|
+
completedCount: number
|
|
50
|
+
totalTasks: number
|
|
51
|
+
}
|
|
@@ -4,17 +4,37 @@
|
|
|
4
4
|
* This file is required by bin/prjct after setup verification
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
import { PrjctCommands } from './commands'
|
|
8
|
+
import registry from './command-registry'
|
|
9
|
+
import out from './utils/output'
|
|
10
|
+
|
|
11
|
+
interface Command {
|
|
12
|
+
name: string
|
|
13
|
+
description: string
|
|
14
|
+
category: string
|
|
15
|
+
params?: string
|
|
16
|
+
implemented: boolean
|
|
17
|
+
deprecated?: boolean
|
|
18
|
+
replacedBy?: string
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
interface ParsedCommandArgs {
|
|
22
|
+
parsedArgs: string[]
|
|
23
|
+
options: Record<string, string | boolean>
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
interface CommandResult {
|
|
27
|
+
success?: boolean
|
|
28
|
+
message?: string
|
|
29
|
+
}
|
|
10
30
|
|
|
11
|
-
async function main() {
|
|
31
|
+
async function main(): Promise<void> {
|
|
12
32
|
const [commandName, ...rawArgs] = process.argv.slice(2)
|
|
13
33
|
|
|
14
34
|
// === SPECIAL COMMANDS (version, help) ===
|
|
15
35
|
|
|
16
36
|
if (['-v', '--version', 'version'].includes(commandName)) {
|
|
17
|
-
const packageJson =
|
|
37
|
+
const packageJson = await import('../package.json')
|
|
18
38
|
console.log(`prjct-cli v${packageJson.version}`)
|
|
19
39
|
process.exit(0)
|
|
20
40
|
}
|
|
@@ -66,7 +86,7 @@ async function main() {
|
|
|
66
86
|
const commands = new PrjctCommands()
|
|
67
87
|
|
|
68
88
|
// 6. Execute command
|
|
69
|
-
let result
|
|
89
|
+
let result: CommandResult | undefined
|
|
70
90
|
|
|
71
91
|
// Commands with special option handling
|
|
72
92
|
if (commandName === 'design') {
|
|
@@ -87,9 +107,32 @@ async function main() {
|
|
|
87
107
|
const taskOrNumber = parsedArgs.join(' ')
|
|
88
108
|
result = await commands.build(taskOrNumber)
|
|
89
109
|
} else {
|
|
90
|
-
// Standard commands
|
|
110
|
+
// Standard commands - type-safe invocation
|
|
91
111
|
const param = parsedArgs.join(' ') || null
|
|
92
|
-
|
|
112
|
+
const standardCommands: Record<string, (p: string | null) => Promise<CommandResult>> = {
|
|
113
|
+
now: (p) => commands.now(p),
|
|
114
|
+
done: () => commands.done(),
|
|
115
|
+
next: () => commands.next(),
|
|
116
|
+
init: (p) => commands.init(p),
|
|
117
|
+
feature: (p) => commands.feature(p || ''),
|
|
118
|
+
bug: (p) => commands.bug(p || ''),
|
|
119
|
+
architect: (p) => commands.architect(p || 'execute'),
|
|
120
|
+
ship: (p) => commands.ship(p),
|
|
121
|
+
context: () => commands.context(),
|
|
122
|
+
recap: () => commands.recap(),
|
|
123
|
+
stuck: (p) => commands.stuck(p || ''),
|
|
124
|
+
roadmap: () => commands.roadmap(),
|
|
125
|
+
status: () => commands.status(),
|
|
126
|
+
sync: () => commands.sync(),
|
|
127
|
+
start: () => commands.start(),
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
const handler = standardCommands[commandName]
|
|
131
|
+
if (handler) {
|
|
132
|
+
result = await handler(param)
|
|
133
|
+
} else {
|
|
134
|
+
throw new Error(`Command '${commandName}' has no handler`)
|
|
135
|
+
}
|
|
93
136
|
}
|
|
94
137
|
|
|
95
138
|
// 7. Display result
|
|
@@ -101,9 +144,9 @@ async function main() {
|
|
|
101
144
|
out.end()
|
|
102
145
|
process.exit(result && result.success ? 0 : 1)
|
|
103
146
|
} catch (error) {
|
|
104
|
-
console.error('Error:', error.message)
|
|
147
|
+
console.error('Error:', (error as Error).message)
|
|
105
148
|
if (process.env.DEBUG) {
|
|
106
|
-
console.error(error.stack)
|
|
149
|
+
console.error((error as Error).stack)
|
|
107
150
|
}
|
|
108
151
|
// Show branding footer even on error
|
|
109
152
|
out.end()
|
|
@@ -114,9 +157,9 @@ async function main() {
|
|
|
114
157
|
/**
|
|
115
158
|
* Parse command arguments dynamically
|
|
116
159
|
*/
|
|
117
|
-
function parseCommandArgs(cmd, rawArgs) {
|
|
118
|
-
const parsedArgs = []
|
|
119
|
-
const options = {}
|
|
160
|
+
function parseCommandArgs(cmd: Command, rawArgs: string[]): ParsedCommandArgs {
|
|
161
|
+
const parsedArgs: string[] = []
|
|
162
|
+
const options: Record<string, string | boolean> = {}
|
|
120
163
|
|
|
121
164
|
for (let i = 0; i < rawArgs.length; i++) {
|
|
122
165
|
const arg = rawArgs[i]
|
|
@@ -142,12 +185,12 @@ function parseCommandArgs(cmd, rawArgs) {
|
|
|
142
185
|
/**
|
|
143
186
|
* Display help using registry
|
|
144
187
|
*/
|
|
145
|
-
function displayHelp() {
|
|
188
|
+
function displayHelp(): void {
|
|
146
189
|
const categories = registry.getCategories()
|
|
147
|
-
const categorizedCommands = {}
|
|
190
|
+
const categorizedCommands: Record<string, Command[]> = {}
|
|
148
191
|
|
|
149
192
|
// Group commands by category (exclude deprecated)
|
|
150
|
-
registry.getTerminalCommands().forEach((cmd) => {
|
|
193
|
+
registry.getTerminalCommands().forEach((cmd: Command) => {
|
|
151
194
|
if (cmd.deprecated) return
|
|
152
195
|
|
|
153
196
|
if (!categorizedCommands[cmd.category]) {
|
|
@@ -181,9 +224,9 @@ function displayHelp() {
|
|
|
181
224
|
|
|
182
225
|
// Run CLI
|
|
183
226
|
main().catch((error) => {
|
|
184
|
-
console.error('Fatal error:', error.message)
|
|
227
|
+
console.error('Fatal error:', (error as Error).message)
|
|
185
228
|
if (process.env.DEBUG) {
|
|
186
|
-
console.error(error.stack)
|
|
229
|
+
console.error((error as Error).stack)
|
|
187
230
|
}
|
|
188
231
|
process.exit(1)
|
|
189
232
|
})
|
|
@@ -6,23 +6,61 @@
|
|
|
6
6
|
* @version 0.5.0
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
import fs from 'fs'
|
|
10
|
+
import path from 'path'
|
|
11
|
+
|
|
12
|
+
interface AgentCapabilities {
|
|
13
|
+
mcp: boolean
|
|
14
|
+
filesystem: string
|
|
15
|
+
markdown: boolean
|
|
16
|
+
emojis: boolean
|
|
17
|
+
colors: boolean
|
|
18
|
+
interactive: boolean
|
|
19
|
+
agents: boolean
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
interface AgentConfig {
|
|
23
|
+
configFile: string | null
|
|
24
|
+
commandPrefix: string
|
|
25
|
+
responseStyle: string
|
|
26
|
+
dataDir: string
|
|
27
|
+
agentsDir: string | null
|
|
28
|
+
commandsDir: string | null
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
interface AgentEnvironment {
|
|
32
|
+
hasMCP: boolean
|
|
33
|
+
sandboxed: boolean
|
|
34
|
+
persistent: boolean
|
|
35
|
+
agentSystem: boolean
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
interface AgentInfo {
|
|
39
|
+
type: string
|
|
40
|
+
name: string
|
|
41
|
+
isSupported: boolean
|
|
42
|
+
capabilities: AgentCapabilities
|
|
43
|
+
config: AgentConfig
|
|
44
|
+
environment: AgentEnvironment
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
declare const global: typeof globalThis & {
|
|
48
|
+
mcp?: {
|
|
49
|
+
filesystem?: unknown
|
|
50
|
+
}
|
|
51
|
+
}
|
|
11
52
|
|
|
12
53
|
/**
|
|
13
54
|
* Detects the current execution environment (Claude or Terminal).
|
|
14
55
|
* Provides appropriate capabilities and configuration for each environment.
|
|
15
56
|
*/
|
|
16
57
|
class AgentDetector {
|
|
17
|
-
|
|
18
|
-
this.detectedAgent = null
|
|
19
|
-
}
|
|
58
|
+
private detectedAgent: AgentInfo | null = null
|
|
20
59
|
|
|
21
60
|
/**
|
|
22
61
|
* Main detection method - Claude or CLI fallback
|
|
23
|
-
* @returns {Object} Agent information
|
|
24
62
|
*/
|
|
25
|
-
async detect() {
|
|
63
|
+
async detect(): Promise<AgentInfo> {
|
|
26
64
|
if (this.detectedAgent) {
|
|
27
65
|
return this.detectedAgent
|
|
28
66
|
}
|
|
@@ -40,9 +78,8 @@ class AgentDetector {
|
|
|
40
78
|
|
|
41
79
|
/**
|
|
42
80
|
* Check if running in Claude environment
|
|
43
|
-
* @returns {boolean} True if Claude detected
|
|
44
81
|
*/
|
|
45
|
-
isClaudeEnvironment() {
|
|
82
|
+
isClaudeEnvironment(): boolean {
|
|
46
83
|
// Environment variables
|
|
47
84
|
if (process.env.CLAUDE_AGENT || process.env.ANTHROPIC_CLAUDE) {
|
|
48
85
|
return true
|
|
@@ -78,7 +115,7 @@ class AgentDetector {
|
|
|
78
115
|
* Get Claude agent configuration
|
|
79
116
|
* Works for both Claude Code and Claude Desktop
|
|
80
117
|
*/
|
|
81
|
-
getClaudeAgent() {
|
|
118
|
+
getClaudeAgent(): AgentInfo {
|
|
82
119
|
return {
|
|
83
120
|
type: 'claude',
|
|
84
121
|
name: 'Claude (Code + Desktop)',
|
|
@@ -112,7 +149,7 @@ class AgentDetector {
|
|
|
112
149
|
/**
|
|
113
150
|
* Get terminal agent configuration (fallback)
|
|
114
151
|
*/
|
|
115
|
-
getTerminalAgent() {
|
|
152
|
+
getTerminalAgent(): AgentInfo {
|
|
116
153
|
return {
|
|
117
154
|
type: 'terminal',
|
|
118
155
|
name: 'Terminal/CLI',
|
|
@@ -146,7 +183,7 @@ class AgentDetector {
|
|
|
146
183
|
/**
|
|
147
184
|
* Force set agent type (for testing)
|
|
148
185
|
*/
|
|
149
|
-
setAgent(type) {
|
|
186
|
+
setAgent(type: string): AgentInfo {
|
|
150
187
|
switch (type) {
|
|
151
188
|
case 'claude':
|
|
152
189
|
this.detectedAgent = this.getClaudeAgent()
|
|
@@ -162,26 +199,25 @@ class AgentDetector {
|
|
|
162
199
|
/**
|
|
163
200
|
* Reset detection (clear cache)
|
|
164
201
|
*/
|
|
165
|
-
reset() {
|
|
202
|
+
reset(): void {
|
|
166
203
|
this.detectedAgent = null
|
|
167
204
|
}
|
|
168
205
|
|
|
169
206
|
/**
|
|
170
207
|
* Check if current environment is Claude
|
|
171
|
-
* @returns {boolean} True if Claude
|
|
172
208
|
*/
|
|
173
|
-
isClaude() {
|
|
209
|
+
isClaude(): boolean {
|
|
174
210
|
const agent = this.detectedAgent || this.isClaudeEnvironment()
|
|
175
|
-
return agent === true || (agent && agent
|
|
211
|
+
return agent === true || (typeof agent === 'object' && agent?.type === 'claude')
|
|
176
212
|
}
|
|
177
213
|
|
|
178
214
|
/**
|
|
179
215
|
* Check if current environment is Terminal/CLI
|
|
180
|
-
* @returns {boolean} True if terminal
|
|
181
216
|
*/
|
|
182
|
-
isTerminal() {
|
|
217
|
+
isTerminal(): boolean {
|
|
183
218
|
return !this.isClaude()
|
|
184
219
|
}
|
|
185
220
|
}
|
|
186
221
|
|
|
187
|
-
|
|
222
|
+
const agentDetector = new AgentDetector()
|
|
223
|
+
export default agentDetector
|