prjct-cli 0.11.4 → 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 +72 -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 +246 -54
- 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.ts +405 -0
- 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} +99 -89
- 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} +35 -18
- 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} +62 -23
- 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 +203 -403
- 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/BentoGrid/BentoGrid.tsx +18 -0
- 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/EmptyState/EmptyState.tsx +58 -0
- 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/IdeasCard/IdeasCard.tsx +48 -0
- 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/ProgressRing/ProgressRing.tsx +51 -0
- 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/RoadmapCard/RoadmapCard.tsx +77 -0
- package/packages/web/components/RoadmapCard/RoadmapCard.types.ts +15 -0
- package/packages/web/components/RoadmapCard/index.ts +2 -0
- package/packages/web/components/ShipsCard/ShipsCard.tsx +52 -0
- 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/SparklineChart/SparklineChart.tsx +38 -0
- 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/StreakCard/StreakCard.tsx +53 -0
- 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/components/ui/tooltip.tsx +2 -2
- 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/next-env.d.ts +1 -1
- package/packages/web/package.json +10 -6
- 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 -128
- package/core/agentic/chain-of-thought.js +0 -578
- package/core/agentic/command-executor.js +0 -421
- 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 -850
- package/core/agentic/parallel-tools.js +0 -366
- package/core/agentic/plan-mode.js +0 -572
- package/core/agentic/prompt-builder.js +0 -338
- 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 -799
- 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/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,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plan Mode Constants
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Commands that require planning mode
|
|
7
|
+
*/
|
|
8
|
+
export const PLAN_REQUIRED_COMMANDS = [
|
|
9
|
+
'feature', // New features need planning
|
|
10
|
+
'spec', // Specs are planning by definition
|
|
11
|
+
'design', // Architecture needs planning
|
|
12
|
+
'refactor', // Refactoring needs impact analysis
|
|
13
|
+
'migrate', // Migrations are high-risk
|
|
14
|
+
]
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Commands that are destructive and need approval
|
|
18
|
+
*/
|
|
19
|
+
export const DESTRUCTIVE_COMMANDS = [
|
|
20
|
+
'ship', // Commits and pushes
|
|
21
|
+
'cleanup', // Deletes files/code
|
|
22
|
+
'git', // Git operations
|
|
23
|
+
'migrate', // Database/schema changes
|
|
24
|
+
]
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Read-only tools allowed in planning mode
|
|
28
|
+
*/
|
|
29
|
+
export const PLANNING_TOOLS = ['Read', 'Glob', 'Grep', 'GetTimestamp', 'GetDate', 'GetDateTime']
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Plan status enum
|
|
33
|
+
*/
|
|
34
|
+
export const PLAN_STATUS = {
|
|
35
|
+
GATHERING: 'gathering', // Collecting information
|
|
36
|
+
ANALYZING: 'analyzing', // Understanding context
|
|
37
|
+
PROPOSING: 'proposing', // Generating plan
|
|
38
|
+
PENDING_APPROVAL: 'pending', // Waiting for user
|
|
39
|
+
APPROVED: 'approved', // User approved
|
|
40
|
+
REJECTED: 'rejected', // User rejected
|
|
41
|
+
EXECUTING: 'executing', // Running the plan
|
|
42
|
+
COMPLETED: 'completed', // Done
|
|
43
|
+
ABORTED: 'aborted', // User stopped mid-execution
|
|
44
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plan Mode System
|
|
3
|
+
*
|
|
4
|
+
* P3.4: Plan Mode + Approval Flow
|
|
5
|
+
* Separates planning from execution for better user confidence.
|
|
6
|
+
*
|
|
7
|
+
* Pattern from: Devin AI, Windsurf, Kiro
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
export type {
|
|
11
|
+
PlanParams,
|
|
12
|
+
GatheredInfo,
|
|
13
|
+
ProposedPlan,
|
|
14
|
+
PlanStep,
|
|
15
|
+
Plan,
|
|
16
|
+
ApprovalPrompt,
|
|
17
|
+
ApprovalContext,
|
|
18
|
+
} from './types'
|
|
19
|
+
|
|
20
|
+
export { PLAN_STATUS, PLAN_REQUIRED_COMMANDS, DESTRUCTIVE_COMMANDS, PLANNING_TOOLS } from './constants'
|
|
21
|
+
export { generateApprovalPrompt } from './approval'
|
|
22
|
+
export { PlanMode } from './plan-mode'
|
|
23
|
+
|
|
24
|
+
import { PlanMode } from './plan-mode'
|
|
25
|
+
|
|
26
|
+
// Export singleton
|
|
27
|
+
const planMode = new PlanMode()
|
|
28
|
+
export default planMode
|
|
@@ -0,0 +1,406 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plan Mode Class
|
|
3
|
+
* Core plan management functionality
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type { Plan, PlanParams, GatheredInfo, ProposedPlan, PlanStep, ApprovalContext, ApprovalPrompt } from './types'
|
|
7
|
+
import { PLAN_STATUS, PLAN_REQUIRED_COMMANDS, DESTRUCTIVE_COMMANDS, PLANNING_TOOLS } from './constants'
|
|
8
|
+
import { generateApprovalPrompt } from './approval'
|
|
9
|
+
|
|
10
|
+
export class PlanMode {
|
|
11
|
+
activePlans: Map<string, Plan>
|
|
12
|
+
|
|
13
|
+
constructor() {
|
|
14
|
+
this.activePlans = new Map() // projectId -> plan state
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Check if command requires planning mode
|
|
19
|
+
*/
|
|
20
|
+
requiresPlanning(commandName: string): boolean {
|
|
21
|
+
return PLAN_REQUIRED_COMMANDS.includes(commandName)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Check if command is destructive and needs approval
|
|
26
|
+
*/
|
|
27
|
+
isDestructive(commandName: string): boolean {
|
|
28
|
+
return DESTRUCTIVE_COMMANDS.includes(commandName)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Check if tool is allowed in planning mode
|
|
33
|
+
*/
|
|
34
|
+
isToolAllowedInPlanning(toolName: string): boolean {
|
|
35
|
+
return PLANNING_TOOLS.includes(toolName)
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Get allowed tools for current mode
|
|
40
|
+
*/
|
|
41
|
+
getAllowedTools(inPlanningMode: boolean, templateTools: string[]): string[] {
|
|
42
|
+
if (!inPlanningMode) {
|
|
43
|
+
return templateTools
|
|
44
|
+
}
|
|
45
|
+
// In planning mode, only allow read-only tools
|
|
46
|
+
return templateTools.filter((tool) => PLANNING_TOOLS.includes(tool))
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Start planning mode for a command
|
|
51
|
+
*/
|
|
52
|
+
startPlanning(projectId: string, commandName: string, params: PlanParams): Plan {
|
|
53
|
+
const plan: Plan = {
|
|
54
|
+
id: `plan_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
|
|
55
|
+
projectId,
|
|
56
|
+
command: commandName,
|
|
57
|
+
params,
|
|
58
|
+
status: PLAN_STATUS.GATHERING,
|
|
59
|
+
startedAt: new Date().toISOString(),
|
|
60
|
+
gatheredInfo: [],
|
|
61
|
+
analysis: null,
|
|
62
|
+
proposedPlan: null,
|
|
63
|
+
userFeedback: null,
|
|
64
|
+
approvedAt: null,
|
|
65
|
+
executionStartedAt: null,
|
|
66
|
+
completedAt: null,
|
|
67
|
+
steps: [],
|
|
68
|
+
currentStep: 0,
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
this.activePlans.set(projectId, plan)
|
|
72
|
+
return plan
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Get active plan for project
|
|
77
|
+
*/
|
|
78
|
+
getActivePlan(projectId: string): Plan | null {
|
|
79
|
+
return this.activePlans.get(projectId) || null
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Check if project is in planning mode
|
|
84
|
+
*/
|
|
85
|
+
isInPlanningMode(projectId: string): boolean {
|
|
86
|
+
const plan = this.getActivePlan(projectId)
|
|
87
|
+
if (!plan) return false
|
|
88
|
+
return [PLAN_STATUS.GATHERING, PLAN_STATUS.ANALYZING, PLAN_STATUS.PROPOSING, PLAN_STATUS.PENDING_APPROVAL].includes(
|
|
89
|
+
plan.status
|
|
90
|
+
)
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Record gathered information
|
|
95
|
+
*/
|
|
96
|
+
recordGatheredInfo(projectId: string, info: GatheredInfo): void {
|
|
97
|
+
const plan = this.getActivePlan(projectId)
|
|
98
|
+
if (!plan) return
|
|
99
|
+
|
|
100
|
+
plan.gatheredInfo.push({
|
|
101
|
+
...info,
|
|
102
|
+
gatheredAt: new Date().toISOString(),
|
|
103
|
+
})
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Update plan status
|
|
108
|
+
*/
|
|
109
|
+
updateStatus(projectId: string, status: string): void {
|
|
110
|
+
const plan = this.getActivePlan(projectId)
|
|
111
|
+
if (!plan) return
|
|
112
|
+
|
|
113
|
+
plan.status = status
|
|
114
|
+
|
|
115
|
+
// Track timestamps for key transitions
|
|
116
|
+
if (status === PLAN_STATUS.APPROVED) {
|
|
117
|
+
plan.approvedAt = new Date().toISOString()
|
|
118
|
+
} else if (status === PLAN_STATUS.EXECUTING) {
|
|
119
|
+
plan.executionStartedAt = new Date().toISOString()
|
|
120
|
+
} else if (status === PLAN_STATUS.COMPLETED || status === PLAN_STATUS.ABORTED) {
|
|
121
|
+
plan.completedAt = new Date().toISOString()
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Set analysis results
|
|
127
|
+
*/
|
|
128
|
+
setAnalysis(projectId: string, analysis: unknown): void {
|
|
129
|
+
const plan = this.getActivePlan(projectId)
|
|
130
|
+
if (!plan) return
|
|
131
|
+
|
|
132
|
+
plan.analysis = analysis
|
|
133
|
+
plan.status = PLAN_STATUS.ANALYZING
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Propose a plan for user approval
|
|
138
|
+
*/
|
|
139
|
+
proposePlan(projectId: string, proposedPlan: ProposedPlan): ReturnType<typeof this.formatPlanForApproval> | null {
|
|
140
|
+
const plan = this.getActivePlan(projectId)
|
|
141
|
+
if (!plan) return null
|
|
142
|
+
|
|
143
|
+
plan.proposedPlan = proposedPlan
|
|
144
|
+
plan.status = PLAN_STATUS.PENDING_APPROVAL
|
|
145
|
+
|
|
146
|
+
return this.formatPlanForApproval(plan)
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Format plan for user approval display
|
|
151
|
+
*/
|
|
152
|
+
formatPlanForApproval(plan: Plan) {
|
|
153
|
+
const proposed = plan.proposedPlan
|
|
154
|
+
|
|
155
|
+
return {
|
|
156
|
+
summary: proposed?.summary || `Plan for: ${plan.command}`,
|
|
157
|
+
approach: proposed?.approach,
|
|
158
|
+
steps: proposed?.steps || [],
|
|
159
|
+
risks: proposed?.risks || [],
|
|
160
|
+
alternatives: proposed?.alternatives || [],
|
|
161
|
+
estimatedTime: proposed?.estimatedTime,
|
|
162
|
+
affectedFiles: proposed?.affectedFiles || [],
|
|
163
|
+
requiresConfirmation: true,
|
|
164
|
+
planId: plan.id,
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* User approves the plan
|
|
170
|
+
*/
|
|
171
|
+
approvePlan(
|
|
172
|
+
projectId: string,
|
|
173
|
+
feedback: string | null = null
|
|
174
|
+
): { approved: boolean; planId: string; steps: PlanStep[]; message: string } | null {
|
|
175
|
+
const plan = this.getActivePlan(projectId)
|
|
176
|
+
if (!plan || plan.status !== PLAN_STATUS.PENDING_APPROVAL) {
|
|
177
|
+
return null
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
plan.userFeedback = feedback
|
|
181
|
+
plan.status = PLAN_STATUS.APPROVED
|
|
182
|
+
plan.approvedAt = new Date().toISOString()
|
|
183
|
+
|
|
184
|
+
// Convert proposed plan to executable steps
|
|
185
|
+
plan.steps = (plan.proposedPlan?.steps || []).map((step, index) => ({
|
|
186
|
+
index,
|
|
187
|
+
description: typeof step === 'string' ? step : step.description || '',
|
|
188
|
+
status: 'pending' as const,
|
|
189
|
+
tool: typeof step === 'string' ? undefined : step.tool,
|
|
190
|
+
args: typeof step === 'string' ? undefined : step.args,
|
|
191
|
+
}))
|
|
192
|
+
|
|
193
|
+
return {
|
|
194
|
+
approved: true,
|
|
195
|
+
planId: plan.id,
|
|
196
|
+
steps: plan.steps,
|
|
197
|
+
message: `Plan approved. ${plan.steps.length} steps to execute.`,
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* User rejects the plan
|
|
203
|
+
*/
|
|
204
|
+
rejectPlan(
|
|
205
|
+
projectId: string,
|
|
206
|
+
reason: string | null = null
|
|
207
|
+
): { rejected: boolean; planId: string; reason: string | null; message: string } | null {
|
|
208
|
+
const plan = this.getActivePlan(projectId)
|
|
209
|
+
if (!plan) return null
|
|
210
|
+
|
|
211
|
+
plan.status = PLAN_STATUS.REJECTED
|
|
212
|
+
plan.userFeedback = reason
|
|
213
|
+
plan.completedAt = new Date().toISOString()
|
|
214
|
+
|
|
215
|
+
// Clear active plan
|
|
216
|
+
this.activePlans.delete(projectId)
|
|
217
|
+
|
|
218
|
+
return {
|
|
219
|
+
rejected: true,
|
|
220
|
+
planId: plan.id,
|
|
221
|
+
reason,
|
|
222
|
+
message: 'Plan rejected. No changes made.',
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* Start executing approved plan
|
|
228
|
+
*/
|
|
229
|
+
startExecution(projectId: string): ReturnType<typeof this.getNextStep> {
|
|
230
|
+
const plan = this.getActivePlan(projectId)
|
|
231
|
+
if (!plan || plan.status !== PLAN_STATUS.APPROVED) {
|
|
232
|
+
return null
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
plan.status = PLAN_STATUS.EXECUTING
|
|
236
|
+
plan.executionStartedAt = new Date().toISOString()
|
|
237
|
+
plan.currentStep = 0
|
|
238
|
+
|
|
239
|
+
return this.getNextStep(projectId)
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
* Get next step to execute
|
|
244
|
+
*/
|
|
245
|
+
getNextStep(
|
|
246
|
+
projectId: string
|
|
247
|
+
): { stepNumber: number; totalSteps: number; step: PlanStep; progress: number } | null {
|
|
248
|
+
const plan = this.getActivePlan(projectId)
|
|
249
|
+
if (!plan || plan.status !== PLAN_STATUS.EXECUTING) {
|
|
250
|
+
return null
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
const step = plan.steps[plan.currentStep]
|
|
254
|
+
if (!step) {
|
|
255
|
+
// All steps complete
|
|
256
|
+
this.completePlan(projectId)
|
|
257
|
+
return null
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
return {
|
|
261
|
+
stepNumber: plan.currentStep + 1,
|
|
262
|
+
totalSteps: plan.steps.length,
|
|
263
|
+
step,
|
|
264
|
+
progress: Math.round((plan.currentStep / plan.steps.length) * 100),
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
/**
|
|
269
|
+
* Mark current step as complete
|
|
270
|
+
*/
|
|
271
|
+
completeStep(projectId: string, result: unknown = {}): ReturnType<typeof this.getNextStep> {
|
|
272
|
+
const plan = this.getActivePlan(projectId)
|
|
273
|
+
if (!plan || plan.status !== PLAN_STATUS.EXECUTING) {
|
|
274
|
+
return null
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
// Update current step
|
|
278
|
+
plan.steps[plan.currentStep].status = 'completed'
|
|
279
|
+
plan.steps[plan.currentStep].result = result
|
|
280
|
+
plan.steps[plan.currentStep].completedAt = new Date().toISOString()
|
|
281
|
+
|
|
282
|
+
// Move to next step
|
|
283
|
+
plan.currentStep++
|
|
284
|
+
|
|
285
|
+
return this.getNextStep(projectId)
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
/**
|
|
289
|
+
* Mark step as failed
|
|
290
|
+
*/
|
|
291
|
+
failStep(projectId: string, error: string): { failed: boolean; step: number; error: string; options: string[] } | null {
|
|
292
|
+
const plan = this.getActivePlan(projectId)
|
|
293
|
+
if (!plan) return null
|
|
294
|
+
|
|
295
|
+
plan.steps[plan.currentStep].status = 'failed'
|
|
296
|
+
plan.steps[plan.currentStep].error = error
|
|
297
|
+
|
|
298
|
+
return {
|
|
299
|
+
failed: true,
|
|
300
|
+
step: plan.currentStep + 1,
|
|
301
|
+
error,
|
|
302
|
+
options: ['retry', 'skip', 'abort'],
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
/**
|
|
307
|
+
* Complete the plan
|
|
308
|
+
*/
|
|
309
|
+
completePlan(projectId: string) {
|
|
310
|
+
const plan = this.getActivePlan(projectId)
|
|
311
|
+
if (!plan) return null
|
|
312
|
+
|
|
313
|
+
plan.status = PLAN_STATUS.COMPLETED
|
|
314
|
+
plan.completedAt = new Date().toISOString()
|
|
315
|
+
|
|
316
|
+
const summary = {
|
|
317
|
+
planId: plan.id,
|
|
318
|
+
command: plan.command,
|
|
319
|
+
totalSteps: plan.steps.length,
|
|
320
|
+
completedSteps: plan.steps.filter((s) => s.status === 'completed').length,
|
|
321
|
+
failedSteps: plan.steps.filter((s) => s.status === 'failed').length,
|
|
322
|
+
duration: this._calculateDuration(plan.executionStartedAt, plan.completedAt),
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
// Clear active plan
|
|
326
|
+
this.activePlans.delete(projectId)
|
|
327
|
+
|
|
328
|
+
return summary
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
/**
|
|
332
|
+
* Abort plan execution
|
|
333
|
+
*/
|
|
334
|
+
abortPlan(projectId: string, reason: string = 'User requested') {
|
|
335
|
+
const plan = this.getActivePlan(projectId)
|
|
336
|
+
if (!plan) return null
|
|
337
|
+
|
|
338
|
+
plan.status = PLAN_STATUS.ABORTED
|
|
339
|
+
plan.completedAt = new Date().toISOString()
|
|
340
|
+
plan.abortReason = reason
|
|
341
|
+
|
|
342
|
+
const summary = {
|
|
343
|
+
aborted: true,
|
|
344
|
+
planId: plan.id,
|
|
345
|
+
reason,
|
|
346
|
+
completedSteps: plan.steps.filter((s) => s.status === 'completed').length,
|
|
347
|
+
totalSteps: plan.steps.length,
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
// Clear active plan
|
|
351
|
+
this.activePlans.delete(projectId)
|
|
352
|
+
|
|
353
|
+
return summary
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
/**
|
|
357
|
+
* Generate approval prompt for destructive commands
|
|
358
|
+
*/
|
|
359
|
+
generateApprovalPrompt(commandName: string, context: ApprovalContext): ApprovalPrompt {
|
|
360
|
+
return generateApprovalPrompt(commandName, context)
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
/**
|
|
364
|
+
* Format plan status for display
|
|
365
|
+
*/
|
|
366
|
+
formatStatus(projectId: string): string {
|
|
367
|
+
const plan = this.getActivePlan(projectId)
|
|
368
|
+
if (!plan) return 'No active plan'
|
|
369
|
+
|
|
370
|
+
const statusEmoji: Record<string, string> = {
|
|
371
|
+
[PLAN_STATUS.GATHERING]: '🔍',
|
|
372
|
+
[PLAN_STATUS.ANALYZING]: '🧠',
|
|
373
|
+
[PLAN_STATUS.PROPOSING]: '📝',
|
|
374
|
+
[PLAN_STATUS.PENDING_APPROVAL]: '⏳',
|
|
375
|
+
[PLAN_STATUS.APPROVED]: '✅',
|
|
376
|
+
[PLAN_STATUS.EXECUTING]: '⚡',
|
|
377
|
+
[PLAN_STATUS.COMPLETED]: '🎉',
|
|
378
|
+
[PLAN_STATUS.REJECTED]: '❌',
|
|
379
|
+
[PLAN_STATUS.ABORTED]: '🛑',
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
const lines = [`${statusEmoji[plan.status] || '📋'} Plan: ${plan.command}`, `Status: ${plan.status}`]
|
|
383
|
+
|
|
384
|
+
if (plan.status === PLAN_STATUS.EXECUTING) {
|
|
385
|
+
const progress = Math.round((plan.currentStep / plan.steps.length) * 100)
|
|
386
|
+
lines.push(`Progress: ${plan.currentStep}/${plan.steps.length} (${progress}%)`)
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
return lines.join('\n')
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
/**
|
|
393
|
+
* Calculate duration between two timestamps
|
|
394
|
+
*/
|
|
395
|
+
private _calculateDuration(start: string | null, end: string | null): string | null {
|
|
396
|
+
if (!start || !end) return null
|
|
397
|
+
const ms = new Date(end).getTime() - new Date(start).getTime()
|
|
398
|
+
const seconds = Math.floor(ms / 1000)
|
|
399
|
+
const minutes = Math.floor(seconds / 60)
|
|
400
|
+
const hours = Math.floor(minutes / 60)
|
|
401
|
+
|
|
402
|
+
if (hours > 0) return `${hours}h ${minutes % 60}m`
|
|
403
|
+
if (minutes > 0) return `${minutes}m ${seconds % 60}s`
|
|
404
|
+
return `${seconds}s`
|
|
405
|
+
}
|
|
406
|
+
}
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plan Mode Types
|
|
3
|
+
*
|
|
4
|
+
* Types for the planning system that gathers context,
|
|
5
|
+
* proposes plans, and executes approved changes.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type { CommandParams } from '../../types'
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Parameters passed to planning mode.
|
|
12
|
+
* Extends standard CommandParams with planning-specific options.
|
|
13
|
+
*/
|
|
14
|
+
export interface PlanParams extends CommandParams {
|
|
15
|
+
/** Skip approval prompt */
|
|
16
|
+
autoApprove?: boolean
|
|
17
|
+
/** Verbose output during planning */
|
|
18
|
+
verbose?: boolean
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Information gathered during the planning phase.
|
|
23
|
+
*/
|
|
24
|
+
export interface GatheredInfo {
|
|
25
|
+
/** Type of information (e.g., 'file_content', 'git_status', 'analysis') */
|
|
26
|
+
type: GatheredInfoType
|
|
27
|
+
/** Source of the information (e.g., file path, command) */
|
|
28
|
+
source: string
|
|
29
|
+
/** The gathered data */
|
|
30
|
+
data: string | GatheredFileData | GatheredAnalysisData
|
|
31
|
+
/** When this info was gathered */
|
|
32
|
+
gatheredAt: string
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export type GatheredInfoType =
|
|
36
|
+
| 'file_content'
|
|
37
|
+
| 'git_status'
|
|
38
|
+
| 'git_diff'
|
|
39
|
+
| 'analysis'
|
|
40
|
+
| 'dependencies'
|
|
41
|
+
| 'structure'
|
|
42
|
+
|
|
43
|
+
export interface GatheredFileData {
|
|
44
|
+
path: string
|
|
45
|
+
content: string
|
|
46
|
+
lines: number
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export interface GatheredAnalysisData {
|
|
50
|
+
summary: string
|
|
51
|
+
findings: string[]
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* A proposed plan for executing changes.
|
|
56
|
+
*/
|
|
57
|
+
export interface ProposedPlan {
|
|
58
|
+
/** Brief summary of what will be done */
|
|
59
|
+
summary: string
|
|
60
|
+
/** Detailed approach explanation */
|
|
61
|
+
approach: string
|
|
62
|
+
/** Steps to execute */
|
|
63
|
+
steps: PlanStepDefinition[]
|
|
64
|
+
/** Potential risks */
|
|
65
|
+
risks?: string[]
|
|
66
|
+
/** Alternative approaches considered */
|
|
67
|
+
alternatives?: string[]
|
|
68
|
+
/** Estimated time to complete */
|
|
69
|
+
estimatedTime?: string
|
|
70
|
+
/** Files that will be modified */
|
|
71
|
+
affectedFiles: string[]
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export interface PlanStepDefinition {
|
|
75
|
+
/** Step description */
|
|
76
|
+
description: string
|
|
77
|
+
/** Tool to use (if any) */
|
|
78
|
+
tool?: string
|
|
79
|
+
/** Arguments for the tool */
|
|
80
|
+
args?: string[]
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* A step in the plan with execution status.
|
|
85
|
+
*/
|
|
86
|
+
export interface PlanStep {
|
|
87
|
+
index: number
|
|
88
|
+
description: string
|
|
89
|
+
status: 'pending' | 'completed' | 'failed'
|
|
90
|
+
tool?: string
|
|
91
|
+
args?: string[]
|
|
92
|
+
result?: PlanStepResult
|
|
93
|
+
completedAt?: string
|
|
94
|
+
error?: string
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export interface PlanStepResult {
|
|
98
|
+
success: boolean
|
|
99
|
+
output?: string
|
|
100
|
+
filesModified?: string[]
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Plan status values.
|
|
105
|
+
*/
|
|
106
|
+
export type PlanStatus =
|
|
107
|
+
| 'gathering'
|
|
108
|
+
| 'analyzing'
|
|
109
|
+
| 'proposing'
|
|
110
|
+
| 'awaiting_approval'
|
|
111
|
+
| 'executing'
|
|
112
|
+
| 'completed'
|
|
113
|
+
| 'aborted'
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* A complete plan instance.
|
|
117
|
+
*/
|
|
118
|
+
export interface Plan {
|
|
119
|
+
id: string
|
|
120
|
+
projectId: string
|
|
121
|
+
command: string
|
|
122
|
+
params: PlanParams
|
|
123
|
+
status: PlanStatus
|
|
124
|
+
startedAt: string
|
|
125
|
+
gatheredInfo: GatheredInfo[]
|
|
126
|
+
analysis: PlanAnalysis | null
|
|
127
|
+
proposedPlan: ProposedPlan | null
|
|
128
|
+
userFeedback: string | null
|
|
129
|
+
approvedAt: string | null
|
|
130
|
+
executionStartedAt: string | null
|
|
131
|
+
completedAt: string | null
|
|
132
|
+
steps: PlanStep[]
|
|
133
|
+
currentStep: number
|
|
134
|
+
abortReason?: string
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
export interface PlanAnalysis {
|
|
138
|
+
complexity: 'low' | 'medium' | 'high'
|
|
139
|
+
riskLevel: 'low' | 'medium' | 'high'
|
|
140
|
+
estimatedDuration: string
|
|
141
|
+
dependencies: string[]
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Prompt shown to user for approval.
|
|
146
|
+
*/
|
|
147
|
+
export interface ApprovalPrompt {
|
|
148
|
+
title: string
|
|
149
|
+
message: string
|
|
150
|
+
details?: string[]
|
|
151
|
+
options: ApprovalOption[]
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
export interface ApprovalOption {
|
|
155
|
+
key: string
|
|
156
|
+
label: string
|
|
157
|
+
action: 'approve' | 'reject' | 'modify' | 'abort'
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Context for approval decisions.
|
|
162
|
+
*/
|
|
163
|
+
export interface ApprovalContext {
|
|
164
|
+
/** Current git branch */
|
|
165
|
+
branch?: string
|
|
166
|
+
/** Files that will be changed */
|
|
167
|
+
changedFiles: ChangedFile[]
|
|
168
|
+
/** Proposed commit message */
|
|
169
|
+
commitMessage?: string
|
|
170
|
+
/** Files that will be deleted */
|
|
171
|
+
filesToDelete: string[]
|
|
172
|
+
/** Total lines of code affected */
|
|
173
|
+
linesOfCode?: number
|
|
174
|
+
/** Type of operation */
|
|
175
|
+
operation: ApprovalOperation
|
|
176
|
+
/** Warnings to show user */
|
|
177
|
+
warnings: string[]
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
export interface ChangedFile {
|
|
181
|
+
path: string
|
|
182
|
+
action: 'create' | 'modify' | 'delete'
|
|
183
|
+
linesAdded?: number
|
|
184
|
+
linesRemoved?: number
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
export type ApprovalOperation =
|
|
188
|
+
| 'create_files'
|
|
189
|
+
| 'modify_files'
|
|
190
|
+
| 'delete_files'
|
|
191
|
+
| 'git_commit'
|
|
192
|
+
| 'git_push'
|
|
193
|
+
| 'run_command'
|