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,228 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Chain of Thought Reasoning
|
|
3
|
+
* Implements step-by-step reasoning for complex commands
|
|
4
|
+
*
|
|
5
|
+
* @module agentic/chain-of-thought
|
|
6
|
+
* @version 1.0.0
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
interface Context {
|
|
10
|
+
projectId?: string | null
|
|
11
|
+
projectPath: string
|
|
12
|
+
params: Record<string, unknown>
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
interface State {
|
|
16
|
+
now?: string | null
|
|
17
|
+
next?: string | null
|
|
18
|
+
shipped?: string | null
|
|
19
|
+
analysis?: string | null
|
|
20
|
+
[key: string]: unknown
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
interface ReasoningStep {
|
|
24
|
+
step: string
|
|
25
|
+
passed: boolean
|
|
26
|
+
details?: string
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
interface ReasoningResult {
|
|
30
|
+
commandName: string
|
|
31
|
+
reasoning: {
|
|
32
|
+
steps: ReasoningStep[]
|
|
33
|
+
allPassed: boolean
|
|
34
|
+
criticalIssues: string[]
|
|
35
|
+
} | null
|
|
36
|
+
plan: string[]
|
|
37
|
+
confidence: number
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Commands that require chain of thought reasoning
|
|
42
|
+
*/
|
|
43
|
+
const REASONING_REQUIRED_COMMANDS = ['ship', 'feature', 'spec', 'cleanup', 'migrate']
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Check if command requires reasoning
|
|
47
|
+
*/
|
|
48
|
+
function requiresReasoning(commandName: string): boolean {
|
|
49
|
+
return REASONING_REQUIRED_COMMANDS.includes(commandName)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Reason through a command before execution
|
|
54
|
+
*/
|
|
55
|
+
async function reason(commandName: string, context: Context, state: State): Promise<ReasoningResult> {
|
|
56
|
+
const steps: ReasoningStep[] = []
|
|
57
|
+
const plan: string[] = []
|
|
58
|
+
const criticalIssues: string[] = []
|
|
59
|
+
|
|
60
|
+
switch (commandName) {
|
|
61
|
+
case 'ship':
|
|
62
|
+
// Check prerequisites
|
|
63
|
+
if (state.now && !state.now.includes('No current task')) {
|
|
64
|
+
steps.push({ step: 'Has active task', passed: true })
|
|
65
|
+
} else {
|
|
66
|
+
steps.push({ step: 'Has active task', passed: false, details: 'No active task to ship' })
|
|
67
|
+
criticalIssues.push('No active task')
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Check if there's content to ship
|
|
71
|
+
if (state.shipped) {
|
|
72
|
+
steps.push({ step: 'Shipped log accessible', passed: true })
|
|
73
|
+
} else {
|
|
74
|
+
steps.push({ step: 'Shipped log accessible', passed: false, details: 'shipped.md not found' })
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// Plan
|
|
78
|
+
plan.push('Read current task from now.md')
|
|
79
|
+
plan.push('Calculate duration')
|
|
80
|
+
plan.push('Append to shipped.md')
|
|
81
|
+
plan.push('Clear now.md')
|
|
82
|
+
plan.push('Update metrics')
|
|
83
|
+
break
|
|
84
|
+
|
|
85
|
+
case 'feature':
|
|
86
|
+
// Check if description provided
|
|
87
|
+
if (context.params.description || context.params.feature) {
|
|
88
|
+
steps.push({ step: 'Has feature description', passed: true })
|
|
89
|
+
} else {
|
|
90
|
+
steps.push({ step: 'Has feature description', passed: false, details: 'No description provided' })
|
|
91
|
+
criticalIssues.push('Missing feature description')
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// Check roadmap accessibility
|
|
95
|
+
if (state.analysis) {
|
|
96
|
+
steps.push({ step: 'Project analyzed', passed: true })
|
|
97
|
+
} else {
|
|
98
|
+
steps.push({ step: 'Project analyzed', passed: false, details: 'Run /p:sync first' })
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// Plan
|
|
102
|
+
plan.push('Parse feature description')
|
|
103
|
+
plan.push('Generate tasks breakdown')
|
|
104
|
+
plan.push('Add to roadmap.md')
|
|
105
|
+
plan.push('Add tasks to next.md')
|
|
106
|
+
plan.push('Suggest starting first task')
|
|
107
|
+
break
|
|
108
|
+
|
|
109
|
+
case 'spec':
|
|
110
|
+
// Check if feature name provided
|
|
111
|
+
if (context.params.feature || context.params.name) {
|
|
112
|
+
steps.push({ step: 'Has spec name', passed: true })
|
|
113
|
+
} else {
|
|
114
|
+
steps.push({ step: 'Has spec name', passed: false, details: 'No spec name provided' })
|
|
115
|
+
criticalIssues.push('Missing spec name')
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// Plan
|
|
119
|
+
plan.push('Generate spec template')
|
|
120
|
+
plan.push('Analyze requirements')
|
|
121
|
+
plan.push('Create spec file')
|
|
122
|
+
plan.push('Link to roadmap')
|
|
123
|
+
break
|
|
124
|
+
|
|
125
|
+
case 'cleanup':
|
|
126
|
+
// Check for analysis
|
|
127
|
+
if (state.analysis) {
|
|
128
|
+
steps.push({ step: 'Has code analysis', passed: true })
|
|
129
|
+
} else {
|
|
130
|
+
steps.push({ step: 'Has code analysis', passed: false, details: 'Run /p:analyze first' })
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// Plan
|
|
134
|
+
plan.push('Scan for unused code')
|
|
135
|
+
plan.push('Identify dead imports')
|
|
136
|
+
plan.push('List files to clean')
|
|
137
|
+
plan.push('Show preview')
|
|
138
|
+
plan.push('Wait for approval')
|
|
139
|
+
plan.push('Execute cleanup')
|
|
140
|
+
break
|
|
141
|
+
|
|
142
|
+
case 'migrate':
|
|
143
|
+
// Always warn for migrate
|
|
144
|
+
steps.push({
|
|
145
|
+
step: 'Migration safety check',
|
|
146
|
+
passed: true,
|
|
147
|
+
details: 'Will require manual approval',
|
|
148
|
+
})
|
|
149
|
+
|
|
150
|
+
// Plan
|
|
151
|
+
plan.push('Analyze current state')
|
|
152
|
+
plan.push('Generate migration plan')
|
|
153
|
+
plan.push('Show affected files')
|
|
154
|
+
plan.push('Request approval')
|
|
155
|
+
plan.push('Execute migration')
|
|
156
|
+
plan.push('Verify results')
|
|
157
|
+
break
|
|
158
|
+
|
|
159
|
+
default:
|
|
160
|
+
// Generic plan
|
|
161
|
+
plan.push('Execute command')
|
|
162
|
+
break
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// Calculate confidence
|
|
166
|
+
const passedSteps = steps.filter((s) => s.passed).length
|
|
167
|
+
const totalSteps = steps.length
|
|
168
|
+
const confidence = totalSteps > 0 ? passedSteps / totalSteps : 1
|
|
169
|
+
|
|
170
|
+
return {
|
|
171
|
+
commandName,
|
|
172
|
+
reasoning:
|
|
173
|
+
steps.length > 0
|
|
174
|
+
? {
|
|
175
|
+
steps,
|
|
176
|
+
allPassed: criticalIssues.length === 0,
|
|
177
|
+
criticalIssues,
|
|
178
|
+
}
|
|
179
|
+
: null,
|
|
180
|
+
plan,
|
|
181
|
+
confidence,
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Format reasoning plan for display
|
|
187
|
+
*/
|
|
188
|
+
function formatPlan(result: ReasoningResult): string {
|
|
189
|
+
const lines: string[] = []
|
|
190
|
+
|
|
191
|
+
lines.push(`📋 Chain of Thought: ${result.commandName}`)
|
|
192
|
+
lines.push('')
|
|
193
|
+
|
|
194
|
+
if (result.reasoning) {
|
|
195
|
+
lines.push('Steps:')
|
|
196
|
+
result.reasoning.steps.forEach((step) => {
|
|
197
|
+
const icon = step.passed ? '✅' : '❌'
|
|
198
|
+
lines.push(` ${icon} ${step.step}`)
|
|
199
|
+
if (step.details) {
|
|
200
|
+
lines.push(` ${step.details}`)
|
|
201
|
+
}
|
|
202
|
+
})
|
|
203
|
+
lines.push('')
|
|
204
|
+
|
|
205
|
+
if (result.reasoning.criticalIssues.length > 0) {
|
|
206
|
+
lines.push('Critical Issues:')
|
|
207
|
+
result.reasoning.criticalIssues.forEach((issue) => {
|
|
208
|
+
lines.push(` ⚠️ ${issue}`)
|
|
209
|
+
})
|
|
210
|
+
lines.push('')
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
if (result.plan.length > 0) {
|
|
215
|
+
lines.push('Plan:')
|
|
216
|
+
result.plan.forEach((step, i) => {
|
|
217
|
+
lines.push(` ${i + 1}. ${step}`)
|
|
218
|
+
})
|
|
219
|
+
lines.push('')
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
lines.push(`Confidence: ${Math.round(result.confidence * 100)}%`)
|
|
223
|
+
|
|
224
|
+
return lines.join('\n')
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
export { requiresReasoning, reason, formatPlan, REASONING_REQUIRED_COMMANDS }
|
|
228
|
+
export default { requiresReasoning, reason, formatPlan }
|
|
@@ -0,0 +1,384 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Command Executor Class
|
|
3
|
+
* Orchestrates command execution with agentic delegation.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import path from 'path'
|
|
7
|
+
import os from 'os'
|
|
8
|
+
import templateLoader from '../template-loader'
|
|
9
|
+
import contextBuilder from '../context-builder'
|
|
10
|
+
import promptBuilder from '../prompt-builder'
|
|
11
|
+
import toolRegistry from '../tool-registry'
|
|
12
|
+
import { validate, formatError } from '../validation-rules'
|
|
13
|
+
import loopDetector from '../loop-detector'
|
|
14
|
+
import chainOfThought from '../chain-of-thought'
|
|
15
|
+
import semanticCompression from '../semantic-compression'
|
|
16
|
+
import responseTemplates from '../response-templates'
|
|
17
|
+
import memorySystem from '../memory-system'
|
|
18
|
+
import groundTruth from '../ground-truth'
|
|
19
|
+
import thinkBlocks from '../think-blocks'
|
|
20
|
+
import parallelTools from '../parallel-tools'
|
|
21
|
+
import planMode from '../plan-mode'
|
|
22
|
+
import { signalStart, signalEnd } from './status-signal'
|
|
23
|
+
import type { ExecutionResult, SimpleExecutionResult, ExecutionToolsFn } from './types'
|
|
24
|
+
|
|
25
|
+
export class CommandExecutor {
|
|
26
|
+
/**
|
|
27
|
+
* Signal that a command is running (for status line)
|
|
28
|
+
*/
|
|
29
|
+
signalStart(commandName: string): void {
|
|
30
|
+
signalStart(commandName)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Signal that command has finished (for status line)
|
|
35
|
+
*/
|
|
36
|
+
signalEnd(): void {
|
|
37
|
+
signalEnd()
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Execute a prjct command with full agentic delegation
|
|
42
|
+
*/
|
|
43
|
+
async execute(
|
|
44
|
+
commandName: string,
|
|
45
|
+
params: Record<string, unknown>,
|
|
46
|
+
projectPath: string
|
|
47
|
+
): Promise<ExecutionResult> {
|
|
48
|
+
// Signal start for status line
|
|
49
|
+
this.signalStart(commandName)
|
|
50
|
+
|
|
51
|
+
// Context for loop detection
|
|
52
|
+
const loopContext = (params.task as string) || (params.description as string) || ''
|
|
53
|
+
|
|
54
|
+
// Check if we're in a loop BEFORE attempting
|
|
55
|
+
if (loopDetector.shouldEscalate(commandName, loopContext)) {
|
|
56
|
+
const escalation = loopDetector.getEscalationInfo(commandName, loopContext)
|
|
57
|
+
this.signalEnd()
|
|
58
|
+
return {
|
|
59
|
+
success: false,
|
|
60
|
+
error: escalation?.message,
|
|
61
|
+
escalation,
|
|
62
|
+
isLoopDetected: true,
|
|
63
|
+
suggestion: escalation?.suggestion,
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
try {
|
|
68
|
+
// 1. Load template
|
|
69
|
+
const template = await templateLoader.load(commandName)
|
|
70
|
+
|
|
71
|
+
// 2. Build METADATA context only (lazy loading - no file reads yet)
|
|
72
|
+
const metadataContext = await contextBuilder.build(projectPath, params)
|
|
73
|
+
|
|
74
|
+
// 2.5. VALIDATE: Pre-flight checks with specific errors
|
|
75
|
+
const validation = await validate(commandName, metadataContext as unknown as Parameters<typeof validate>[1])
|
|
76
|
+
if (!validation.valid) {
|
|
77
|
+
this.signalEnd()
|
|
78
|
+
return {
|
|
79
|
+
success: false,
|
|
80
|
+
error: formatError(validation),
|
|
81
|
+
validation,
|
|
82
|
+
isValidationError: true,
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// 2.55. P3.4 PLAN MODE: Check if command requires planning
|
|
87
|
+
const requiresPlanning = planMode.requiresPlanning(commandName)
|
|
88
|
+
const isDestructive = planMode.isDestructive(commandName)
|
|
89
|
+
const isInPlanningMode = planMode.isInPlanningMode(metadataContext.projectId!)
|
|
90
|
+
|
|
91
|
+
// Start planning mode if required and not already in it
|
|
92
|
+
let activePlan = null
|
|
93
|
+
if (requiresPlanning && !isInPlanningMode && !params.skipPlanning) {
|
|
94
|
+
activePlan = planMode.startPlanning(metadataContext.projectId!, commandName, params)
|
|
95
|
+
} else if (isInPlanningMode) {
|
|
96
|
+
activePlan = planMode.getActivePlan(metadataContext.projectId!)
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// 2.6. GROUND TRUTH: Verify actual state before critical operations
|
|
100
|
+
let groundTruthResult = null
|
|
101
|
+
if (groundTruth.requiresVerification(commandName)) {
|
|
102
|
+
const preState = await contextBuilder.loadStateForCommand(metadataContext, commandName)
|
|
103
|
+
groundTruthResult = await groundTruth.verify(
|
|
104
|
+
commandName,
|
|
105
|
+
metadataContext as unknown as Parameters<typeof groundTruth.verify>[1],
|
|
106
|
+
preState
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
// Log warnings but don't block (user can override)
|
|
110
|
+
if (!groundTruthResult.verified && groundTruthResult.warnings.length > 0) {
|
|
111
|
+
console.log(groundTruth.formatWarnings(groundTruthResult))
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// 2.7. THINK BLOCKS (P3.1): Dynamic reasoning based on triggers
|
|
116
|
+
let thinkBlock = null
|
|
117
|
+
const preThinkState =
|
|
118
|
+
groundTruthResult?.actual || (await contextBuilder.loadStateForCommand(metadataContext, commandName))
|
|
119
|
+
const thinkTrigger = thinkBlocks.detectTrigger(
|
|
120
|
+
commandName,
|
|
121
|
+
metadataContext as unknown as Parameters<typeof thinkBlocks.detectTrigger>[1],
|
|
122
|
+
preThinkState as Parameters<typeof thinkBlocks.detectTrigger>[2]
|
|
123
|
+
)
|
|
124
|
+
if (thinkTrigger) {
|
|
125
|
+
thinkBlock = await thinkBlocks.generate(
|
|
126
|
+
thinkTrigger,
|
|
127
|
+
commandName,
|
|
128
|
+
metadataContext as unknown as Parameters<typeof thinkBlocks.generate>[2],
|
|
129
|
+
preThinkState as Parameters<typeof thinkBlocks.generate>[3]
|
|
130
|
+
)
|
|
131
|
+
|
|
132
|
+
// Log think block if in debug mode
|
|
133
|
+
if (process.env.PRJCT_DEBUG === 'true') {
|
|
134
|
+
console.log(thinkBlocks.format(thinkBlock, true))
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// 2.8. CHAIN OF THOUGHT: Reasoning for critical commands
|
|
139
|
+
let reasoning = null
|
|
140
|
+
if (chainOfThought.requiresReasoning(commandName)) {
|
|
141
|
+
const reasoningState = await contextBuilder.loadStateForCommand(metadataContext, commandName)
|
|
142
|
+
reasoning = await chainOfThought.reason(
|
|
143
|
+
commandName,
|
|
144
|
+
metadataContext as unknown as Parameters<typeof chainOfThought.reason>[1],
|
|
145
|
+
reasoningState as Parameters<typeof chainOfThought.reason>[2]
|
|
146
|
+
)
|
|
147
|
+
|
|
148
|
+
// If reasoning shows critical issues, warn but continue
|
|
149
|
+
if (reasoning.reasoning && !reasoning.reasoning.allPassed) {
|
|
150
|
+
console.log('⚠️ Chain of Thought detected issues:')
|
|
151
|
+
console.log(chainOfThought.formatPlan(reasoning))
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// 3. AGENTIC: Claude decides agent assignment via templates
|
|
156
|
+
let context: Record<string, unknown> = metadataContext as unknown as Record<string, unknown>
|
|
157
|
+
|
|
158
|
+
// Provide agent info to context so Claude can delegate
|
|
159
|
+
context = {
|
|
160
|
+
...context,
|
|
161
|
+
agentsPath: path.join(os.homedir(), '.prjct-cli', 'projects', metadataContext.projectId || '', 'agents'),
|
|
162
|
+
agentRoutingPath: path.join(__dirname, '..', '..', '..', 'templates', 'agentic', 'agent-routing.md'),
|
|
163
|
+
agenticDelegation: true,
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// 6. Load state with filtered context
|
|
167
|
+
const rawState = await contextBuilder.loadState(metadataContext)
|
|
168
|
+
|
|
169
|
+
// 6.5. SEMANTIC COMPRESSION: Compress state for reduced token usage
|
|
170
|
+
const compressedState: Record<string, unknown> = {}
|
|
171
|
+
for (const [key, content] of Object.entries(rawState)) {
|
|
172
|
+
if (content) {
|
|
173
|
+
const compressed = semanticCompression.compress(content, key)
|
|
174
|
+
compressedState[key] = {
|
|
175
|
+
raw: content,
|
|
176
|
+
summary: compressed.summary,
|
|
177
|
+
compressed,
|
|
178
|
+
}
|
|
179
|
+
} else {
|
|
180
|
+
compressedState[key] = { raw: null, summary: 'Empty', compressed: null }
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// Use compressed summaries for prompt, keep raw for tool execution
|
|
185
|
+
const state = {
|
|
186
|
+
...rawState,
|
|
187
|
+
_compressed: compressedState,
|
|
188
|
+
_compressionMetrics: semanticCompression.getMetrics(),
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
// 7. MEMORY: Load learned patterns AND relevant memories for this command
|
|
192
|
+
let learnedPatterns = null
|
|
193
|
+
let relevantMemories = null
|
|
194
|
+
if (metadataContext.projectId) {
|
|
195
|
+
learnedPatterns = {
|
|
196
|
+
commit_footer: await memorySystem.getSmartDecision(metadataContext.projectId, 'commit_footer'),
|
|
197
|
+
branch_naming: await memorySystem.getSmartDecision(metadataContext.projectId, 'branch_naming'),
|
|
198
|
+
test_before_ship: await memorySystem.getSmartDecision(metadataContext.projectId, 'test_before_ship'),
|
|
199
|
+
preferred_agent: await memorySystem.getSmartDecision(
|
|
200
|
+
metadataContext.projectId,
|
|
201
|
+
`preferred_agent_${commandName}`
|
|
202
|
+
),
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
// P3.3: Get relevant memories for context
|
|
206
|
+
relevantMemories = await memorySystem.getRelevantMemories(
|
|
207
|
+
metadataContext.projectId,
|
|
208
|
+
{ commandName, params },
|
|
209
|
+
5
|
|
210
|
+
)
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// 9. Build prompt - NO agent assignment here, Claude decides via templates
|
|
214
|
+
const planInfo = {
|
|
215
|
+
isPlanning: requiresPlanning || isInPlanningMode,
|
|
216
|
+
requiresApproval: isDestructive && !params.approved,
|
|
217
|
+
active: activePlan,
|
|
218
|
+
allowedTools: planMode.getAllowedTools(isInPlanningMode, template.frontmatter['allowed-tools'] || []),
|
|
219
|
+
}
|
|
220
|
+
// Agent is null - Claude assigns via Task tool using agent-routing.md
|
|
221
|
+
const prompt = promptBuilder.build(
|
|
222
|
+
template,
|
|
223
|
+
context as Parameters<typeof promptBuilder.build>[1],
|
|
224
|
+
state,
|
|
225
|
+
null,
|
|
226
|
+
learnedPatterns,
|
|
227
|
+
thinkBlock,
|
|
228
|
+
relevantMemories,
|
|
229
|
+
planInfo
|
|
230
|
+
)
|
|
231
|
+
|
|
232
|
+
// Log agentic mode
|
|
233
|
+
console.log(`🤖 Agentic delegation enabled - Claude will assign agent via Task tool`)
|
|
234
|
+
|
|
235
|
+
// Record successful attempt
|
|
236
|
+
loopDetector.recordSuccess(commandName, loopContext)
|
|
237
|
+
|
|
238
|
+
// Signal end for status line
|
|
239
|
+
this.signalEnd()
|
|
240
|
+
|
|
241
|
+
return {
|
|
242
|
+
success: true,
|
|
243
|
+
template,
|
|
244
|
+
context,
|
|
245
|
+
state,
|
|
246
|
+
prompt,
|
|
247
|
+
agenticDelegation: true,
|
|
248
|
+
agentsPath: context.agentsPath as string,
|
|
249
|
+
agentRoutingPath: context.agentRoutingPath as string,
|
|
250
|
+
reasoning,
|
|
251
|
+
thinkBlock,
|
|
252
|
+
groundTruth: groundTruthResult,
|
|
253
|
+
compressionMetrics: state._compressionMetrics,
|
|
254
|
+
learnedPatterns,
|
|
255
|
+
relevantMemories,
|
|
256
|
+
formatResponse: (data: unknown) => responseTemplates.format(commandName, data as Parameters<typeof responseTemplates.format>[1]),
|
|
257
|
+
formatThinkBlock: (verbose: boolean) => thinkBlocks.format(thinkBlock, verbose),
|
|
258
|
+
parallel: {
|
|
259
|
+
execute: (toolCalls: unknown[]) => parallelTools.execute(toolCalls as Parameters<typeof parallelTools.execute>[0]),
|
|
260
|
+
readAll: (paths: string[]) => parallelTools.readAll(paths),
|
|
261
|
+
canParallelize: (tools: string[]) => parallelTools.canParallelize(tools),
|
|
262
|
+
getMetrics: () => parallelTools.getMetrics(),
|
|
263
|
+
},
|
|
264
|
+
memory: {
|
|
265
|
+
create: (memory: unknown) =>
|
|
266
|
+
memorySystem.createMemory(metadataContext.projectId!, memory as Parameters<typeof memorySystem.createMemory>[1]),
|
|
267
|
+
autoRemember: (type: string, value: string, ctx?: string) =>
|
|
268
|
+
memorySystem.autoRemember(metadataContext.projectId!, type, value, ctx),
|
|
269
|
+
search: (query: string) => memorySystem.searchMemories(metadataContext.projectId!, query),
|
|
270
|
+
findByTags: (tags: string[]) => memorySystem.findByTags(metadataContext.projectId!, tags),
|
|
271
|
+
getStats: () => memorySystem.getMemoryStats(metadataContext.projectId!),
|
|
272
|
+
},
|
|
273
|
+
plan: {
|
|
274
|
+
active: activePlan,
|
|
275
|
+
isPlanning: requiresPlanning || isInPlanningMode,
|
|
276
|
+
isDestructive,
|
|
277
|
+
requiresApproval: isDestructive && !params.approved,
|
|
278
|
+
recordInfo: (info: unknown) =>
|
|
279
|
+
planMode.recordGatheredInfo(metadataContext.projectId!, info as Parameters<typeof planMode.recordGatheredInfo>[1]),
|
|
280
|
+
setAnalysis: (analysis: unknown) => planMode.setAnalysis(metadataContext.projectId!, analysis),
|
|
281
|
+
propose: (plan: unknown) =>
|
|
282
|
+
planMode.proposePlan(metadataContext.projectId!, plan as Parameters<typeof planMode.proposePlan>[1]),
|
|
283
|
+
approve: (feedback?: string | null) => planMode.approvePlan(metadataContext.projectId!, feedback),
|
|
284
|
+
reject: (reason?: string | null) => planMode.rejectPlan(metadataContext.projectId!, reason),
|
|
285
|
+
getApprovalPrompt: () =>
|
|
286
|
+
planMode.generateApprovalPrompt(commandName, context as Parameters<typeof planMode.generateApprovalPrompt>[1]),
|
|
287
|
+
startExecution: () => planMode.startExecution(metadataContext.projectId!),
|
|
288
|
+
getNextStep: () => planMode.getNextStep(metadataContext.projectId!),
|
|
289
|
+
completeStep: (result?: unknown) => planMode.completeStep(metadataContext.projectId!, result),
|
|
290
|
+
failStep: (error: string) => planMode.failStep(metadataContext.projectId!, error),
|
|
291
|
+
abort: (reason?: string) => planMode.abortPlan(metadataContext.projectId!, reason),
|
|
292
|
+
getStatus: () => planMode.formatStatus(metadataContext.projectId!),
|
|
293
|
+
getAllowedTools: () =>
|
|
294
|
+
planMode.getAllowedTools(isInPlanningMode, template.frontmatter['allowed-tools'] || []),
|
|
295
|
+
},
|
|
296
|
+
}
|
|
297
|
+
} catch (error) {
|
|
298
|
+
// Signal end for status line
|
|
299
|
+
this.signalEnd()
|
|
300
|
+
|
|
301
|
+
// Record failed attempt for loop detection
|
|
302
|
+
const attemptInfo = loopDetector.recordAttempt(commandName, loopContext, {
|
|
303
|
+
success: false,
|
|
304
|
+
error: (error as Error).message,
|
|
305
|
+
})
|
|
306
|
+
|
|
307
|
+
// Check if we should escalate after this failure
|
|
308
|
+
if (attemptInfo.shouldEscalate) {
|
|
309
|
+
const escalation = loopDetector.getEscalationInfo(commandName, loopContext)
|
|
310
|
+
return {
|
|
311
|
+
success: false,
|
|
312
|
+
error: escalation?.message,
|
|
313
|
+
escalation,
|
|
314
|
+
isLoopDetected: true,
|
|
315
|
+
suggestion: escalation?.suggestion,
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
return {
|
|
320
|
+
success: false,
|
|
321
|
+
error: (error as Error).message,
|
|
322
|
+
attemptNumber: attemptInfo.attemptNumber,
|
|
323
|
+
isLooping: attemptInfo.isLooping,
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
/**
|
|
329
|
+
* Execute tool with permission check
|
|
330
|
+
*/
|
|
331
|
+
async executeTool(toolName: string, args: unknown[], allowedTools: string[]): Promise<unknown> {
|
|
332
|
+
// Check if tool is allowed
|
|
333
|
+
if (!toolRegistry.isAllowed(toolName, allowedTools)) {
|
|
334
|
+
throw new Error(`Tool ${toolName} not allowed for this command`)
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
// Get tool function
|
|
338
|
+
const tool = toolRegistry.get(toolName)
|
|
339
|
+
if (!tool) {
|
|
340
|
+
throw new Error(`Tool ${toolName} not found`)
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
// Execute tool
|
|
344
|
+
return await tool(...args)
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
/**
|
|
348
|
+
* Simple execution for direct tool access (legacy migration helper)
|
|
349
|
+
*/
|
|
350
|
+
async executeSimple(
|
|
351
|
+
commandName: string,
|
|
352
|
+
executionFn: ExecutionToolsFn,
|
|
353
|
+
projectPath: string
|
|
354
|
+
): Promise<SimpleExecutionResult> {
|
|
355
|
+
try {
|
|
356
|
+
// Load template to get allowed tools
|
|
357
|
+
const template = await templateLoader.load(commandName)
|
|
358
|
+
const allowedTools = template.frontmatter['allowed-tools'] || []
|
|
359
|
+
|
|
360
|
+
// Build context
|
|
361
|
+
const context = await contextBuilder.build(projectPath)
|
|
362
|
+
|
|
363
|
+
// Create tools proxy that checks permissions
|
|
364
|
+
const tools = {
|
|
365
|
+
read: async (filePath: string) => this.executeTool('Read', [filePath], allowedTools),
|
|
366
|
+
write: async (filePath: string, content: string) => this.executeTool('Write', [filePath, content], allowedTools),
|
|
367
|
+
bash: async (command: string) => this.executeTool('Bash', [command], allowedTools),
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
// Execute user function with tools
|
|
371
|
+
const result = await executionFn(tools, context)
|
|
372
|
+
|
|
373
|
+
return {
|
|
374
|
+
success: true,
|
|
375
|
+
result,
|
|
376
|
+
}
|
|
377
|
+
} catch (error) {
|
|
378
|
+
return {
|
|
379
|
+
success: false,
|
|
380
|
+
error: (error as Error).message,
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Command Executor
|
|
3
|
+
* Orchestrates command execution with agentic delegation.
|
|
4
|
+
*
|
|
5
|
+
* @module agentic/command-executor
|
|
6
|
+
* @version 3.4
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
export type { ExecutionResult, SimpleExecutionResult, ExecutionToolsFn } from './types'
|
|
10
|
+
export { signalStart, signalEnd } from './status-signal'
|
|
11
|
+
export { CommandExecutor } from './command-executor'
|
|
12
|
+
|
|
13
|
+
import { CommandExecutor } from './command-executor'
|
|
14
|
+
|
|
15
|
+
const commandExecutor = new CommandExecutor()
|
|
16
|
+
export default commandExecutor
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Status Signal
|
|
3
|
+
* Running file for status line integration
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import fs from 'fs'
|
|
7
|
+
import path from 'path'
|
|
8
|
+
import os from 'os'
|
|
9
|
+
|
|
10
|
+
const RUNNING_FILE = path.join(os.homedir(), '.prjct-cli', '.running')
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Signal that a command is running (for status line)
|
|
14
|
+
*/
|
|
15
|
+
export function signalStart(commandName: string): void {
|
|
16
|
+
try {
|
|
17
|
+
const dir = path.dirname(RUNNING_FILE)
|
|
18
|
+
if (!fs.existsSync(dir)) {
|
|
19
|
+
fs.mkdirSync(dir, { recursive: true })
|
|
20
|
+
}
|
|
21
|
+
fs.writeFileSync(RUNNING_FILE, `/p:${commandName}`)
|
|
22
|
+
} catch {
|
|
23
|
+
// Silently ignore - status line is optional
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Signal that command has finished (for status line)
|
|
29
|
+
*/
|
|
30
|
+
export function signalEnd(): void {
|
|
31
|
+
try {
|
|
32
|
+
if (fs.existsSync(RUNNING_FILE)) {
|
|
33
|
+
fs.unlinkSync(RUNNING_FILE)
|
|
34
|
+
}
|
|
35
|
+
} catch {
|
|
36
|
+
// Silently ignore - status line is optional
|
|
37
|
+
}
|
|
38
|
+
}
|