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,117 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Version Migration
|
|
3
|
+
* Handles migration between prjct versions.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import configManager from '../config-manager'
|
|
7
|
+
import type { Author, VersionMigrationResult } from './types'
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Check if a project needs migration
|
|
11
|
+
*/
|
|
12
|
+
export async function needsMigration(projectPath: string): Promise<boolean> {
|
|
13
|
+
const structureMigration = await configManager.needsMigration(projectPath)
|
|
14
|
+
if (structureMigration) return true
|
|
15
|
+
|
|
16
|
+
const config = await configManager.readConfig(projectPath)
|
|
17
|
+
if (config && config.version && config.version.startsWith('0.2.')) {
|
|
18
|
+
return true
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
return false
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Migrate config from 0.2.x to 0.3.0 (move authors to global config)
|
|
26
|
+
*/
|
|
27
|
+
export async function migrateConfigTo030(projectPath: string): Promise<VersionMigrationResult> {
|
|
28
|
+
const result: VersionMigrationResult = {
|
|
29
|
+
success: false,
|
|
30
|
+
message: '',
|
|
31
|
+
oldVersion: null,
|
|
32
|
+
newVersion: '0.3.0',
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
try {
|
|
36
|
+
const localConfig = await configManager.readConfig(projectPath)
|
|
37
|
+
if (!localConfig) {
|
|
38
|
+
result.message = 'No config found'
|
|
39
|
+
return result
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
result.oldVersion = localConfig.version || null
|
|
43
|
+
const projectId = localConfig.projectId
|
|
44
|
+
|
|
45
|
+
const globalConfig = await configManager.readGlobalConfig(projectId)
|
|
46
|
+
if (globalConfig && globalConfig.authors && globalConfig.authors.length > 0) {
|
|
47
|
+
const needsCleanup =
|
|
48
|
+
localConfig.authors ||
|
|
49
|
+
localConfig.author ||
|
|
50
|
+
localConfig.version ||
|
|
51
|
+
localConfig.created ||
|
|
52
|
+
localConfig.lastSync
|
|
53
|
+
|
|
54
|
+
if (needsCleanup) {
|
|
55
|
+
delete localConfig.authors
|
|
56
|
+
delete localConfig.author
|
|
57
|
+
delete localConfig.version
|
|
58
|
+
delete localConfig.created
|
|
59
|
+
delete localConfig.lastSync
|
|
60
|
+
await configManager.writeConfig(projectPath, localConfig)
|
|
61
|
+
}
|
|
62
|
+
result.success = true
|
|
63
|
+
result.message = 'Authors already in global config, cleaned up local config'
|
|
64
|
+
return result
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
let authors: Author[] = []
|
|
68
|
+
const now = new Date().toISOString()
|
|
69
|
+
|
|
70
|
+
if (localConfig.authors && Array.isArray(localConfig.authors)) {
|
|
71
|
+
authors = localConfig.authors
|
|
72
|
+
} else if (localConfig.author) {
|
|
73
|
+
authors = [
|
|
74
|
+
{
|
|
75
|
+
name: localConfig.author.name || 'Unknown',
|
|
76
|
+
email: localConfig.author.email || '',
|
|
77
|
+
github: localConfig.author.github || '',
|
|
78
|
+
firstContribution: localConfig.created || now,
|
|
79
|
+
lastActivity: localConfig.lastSync || now,
|
|
80
|
+
},
|
|
81
|
+
]
|
|
82
|
+
} else {
|
|
83
|
+
authors = [
|
|
84
|
+
{
|
|
85
|
+
name: 'Unknown',
|
|
86
|
+
email: '',
|
|
87
|
+
github: '',
|
|
88
|
+
firstContribution: now,
|
|
89
|
+
lastActivity: now,
|
|
90
|
+
},
|
|
91
|
+
]
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const newGlobalConfig = {
|
|
95
|
+
projectId,
|
|
96
|
+
authors,
|
|
97
|
+
version: '0.3.0',
|
|
98
|
+
created: localConfig.created || now,
|
|
99
|
+
lastSync: now,
|
|
100
|
+
}
|
|
101
|
+
await configManager.writeGlobalConfig(projectId, newGlobalConfig)
|
|
102
|
+
|
|
103
|
+
delete localConfig.authors
|
|
104
|
+
delete localConfig.author
|
|
105
|
+
delete localConfig.version
|
|
106
|
+
delete localConfig.created
|
|
107
|
+
delete localConfig.lastSync
|
|
108
|
+
await configManager.writeConfig(projectPath, localConfig)
|
|
109
|
+
|
|
110
|
+
result.success = true
|
|
111
|
+
result.message = `Migrated ${authors.length} author(s) to global config`
|
|
112
|
+
return result
|
|
113
|
+
} catch (error) {
|
|
114
|
+
result.message = `Migration failed: ${(error as Error).message}`
|
|
115
|
+
return result
|
|
116
|
+
}
|
|
117
|
+
}
|
|
@@ -1,10 +1,3 @@
|
|
|
1
|
-
const fs = require('fs').promises
|
|
2
|
-
const path = require('path')
|
|
3
|
-
const crypto = require('crypto')
|
|
4
|
-
const os = require('os')
|
|
5
|
-
const dateHelper = require('../utils/date-helper')
|
|
6
|
-
const fileHelper = require('../utils/file-helper')
|
|
7
|
-
|
|
8
1
|
/**
|
|
9
2
|
* PathManager - Manages project paths between local and global storage
|
|
10
3
|
*
|
|
@@ -15,7 +8,27 @@ const fileHelper = require('../utils/file-helper')
|
|
|
15
8
|
*
|
|
16
9
|
* @version 0.2.1
|
|
17
10
|
*/
|
|
11
|
+
|
|
12
|
+
import fs from 'fs/promises'
|
|
13
|
+
import path from 'path'
|
|
14
|
+
import crypto from 'crypto'
|
|
15
|
+
import os from 'os'
|
|
16
|
+
import * as dateHelper from '../utils/date-helper'
|
|
17
|
+
import * as fileHelper from '../utils/file-helper'
|
|
18
|
+
|
|
19
|
+
interface SessionInfo {
|
|
20
|
+
year: string
|
|
21
|
+
month: string
|
|
22
|
+
day: string
|
|
23
|
+
path: string
|
|
24
|
+
date: Date
|
|
25
|
+
}
|
|
26
|
+
|
|
18
27
|
class PathManager {
|
|
28
|
+
globalBaseDir: string
|
|
29
|
+
globalProjectsDir: string
|
|
30
|
+
globalConfigDir: string
|
|
31
|
+
|
|
19
32
|
constructor() {
|
|
20
33
|
this.globalBaseDir = path.join(os.homedir(), '.prjct-cli')
|
|
21
34
|
this.globalProjectsDir = path.join(this.globalBaseDir, 'projects')
|
|
@@ -25,11 +38,8 @@ class PathManager {
|
|
|
25
38
|
/**
|
|
26
39
|
* Generate a unique project ID from the absolute project path
|
|
27
40
|
* Uses SHA-256 hash of the absolute path for consistency
|
|
28
|
-
*
|
|
29
|
-
* @param {string} projectPath - Absolute path to the project
|
|
30
|
-
* @returns {string} - 12-character hash ID
|
|
31
41
|
*/
|
|
32
|
-
generateProjectId(projectPath) {
|
|
42
|
+
generateProjectId(projectPath: string): string {
|
|
33
43
|
const absolutePath = path.resolve(projectPath)
|
|
34
44
|
const hash = crypto.createHash('sha256').update(absolutePath).digest('hex')
|
|
35
45
|
return hash.substring(0, 12) // Use first 12 chars for readability
|
|
@@ -37,72 +47,52 @@ class PathManager {
|
|
|
37
47
|
|
|
38
48
|
/**
|
|
39
49
|
* Get the base global storage path
|
|
40
|
-
*
|
|
41
|
-
* @returns {string} - Path to global base directory (~/.prjct-cli)
|
|
42
50
|
*/
|
|
43
|
-
getGlobalBasePath() {
|
|
51
|
+
getGlobalBasePath(): string {
|
|
44
52
|
return this.globalBaseDir
|
|
45
53
|
}
|
|
46
54
|
|
|
47
55
|
/**
|
|
48
56
|
* Get the global storage path for a project
|
|
49
|
-
*
|
|
50
|
-
* @param {string} projectId - The project identifier
|
|
51
|
-
* @returns {string} - Path to global project storage
|
|
52
57
|
*/
|
|
53
|
-
getGlobalProjectPath(projectId) {
|
|
58
|
+
getGlobalProjectPath(projectId: string): string {
|
|
54
59
|
return path.join(this.globalProjectsDir, projectId)
|
|
55
60
|
}
|
|
56
61
|
|
|
57
62
|
/**
|
|
58
63
|
* Get the local config file path for a project
|
|
59
|
-
*
|
|
60
|
-
* @param {string} projectPath - Path to the project
|
|
61
|
-
* @returns {string} - Path to .prjct/prjct.config.json
|
|
62
64
|
*/
|
|
63
|
-
getLocalConfigPath(projectPath) {
|
|
65
|
+
getLocalConfigPath(projectPath: string): string {
|
|
64
66
|
return path.join(projectPath, '.prjct', 'prjct.config.json')
|
|
65
67
|
}
|
|
66
68
|
|
|
67
69
|
/**
|
|
68
70
|
* Get the global config file path for a project
|
|
69
71
|
* This file stores authors and other system data that shouldn't be versioned
|
|
70
|
-
*
|
|
71
|
-
* @param {string} projectId - The project identifier
|
|
72
|
-
* @returns {string} - Path to ~/.prjct-cli/projects/{id}/project.json
|
|
73
72
|
*/
|
|
74
|
-
getGlobalProjectConfigPath(projectId) {
|
|
73
|
+
getGlobalProjectConfigPath(projectId: string): string {
|
|
75
74
|
return path.join(this.getGlobalProjectPath(projectId), 'project.json')
|
|
76
75
|
}
|
|
77
76
|
|
|
78
77
|
/**
|
|
79
78
|
* Get the legacy .prjct directory path
|
|
80
|
-
*
|
|
81
|
-
* @param {string} projectPath - Path to the project
|
|
82
|
-
* @returns {string} - Path to legacy .prjct directory
|
|
83
79
|
*/
|
|
84
|
-
getLegacyPrjctPath(projectPath) {
|
|
80
|
+
getLegacyPrjctPath(projectPath: string): string {
|
|
85
81
|
return path.join(projectPath, '.prjct')
|
|
86
82
|
}
|
|
87
83
|
|
|
88
84
|
/**
|
|
89
85
|
* Check if a project has legacy .prjct directory
|
|
90
|
-
*
|
|
91
|
-
* @param {string} projectPath - Path to the project
|
|
92
|
-
* @returns {Promise<boolean>} - True if legacy directory exists
|
|
93
86
|
*/
|
|
94
|
-
async hasLegacyStructure(projectPath) {
|
|
87
|
+
async hasLegacyStructure(projectPath: string): Promise<boolean> {
|
|
95
88
|
const legacyPath = this.getLegacyPrjctPath(projectPath)
|
|
96
89
|
return await fileHelper.dirExists(legacyPath)
|
|
97
90
|
}
|
|
98
91
|
|
|
99
92
|
/**
|
|
100
93
|
* Check if a project has the new config file
|
|
101
|
-
*
|
|
102
|
-
* @param {string} projectPath - Path to the project
|
|
103
|
-
* @returns {Promise<boolean>} - True if config exists
|
|
104
94
|
*/
|
|
105
|
-
async hasConfig(projectPath) {
|
|
95
|
+
async hasConfig(projectPath: string): Promise<boolean> {
|
|
106
96
|
const configPath = this.getLocalConfigPath(projectPath)
|
|
107
97
|
return await fileHelper.fileExists(configPath)
|
|
108
98
|
}
|
|
@@ -110,10 +100,8 @@ class PathManager {
|
|
|
110
100
|
/**
|
|
111
101
|
* Ensure the global directory structure exists
|
|
112
102
|
* Creates all necessary directories in ~/.prjct-cli/
|
|
113
|
-
*
|
|
114
|
-
* @returns {Promise<void>}
|
|
115
103
|
*/
|
|
116
|
-
async ensureGlobalStructure() {
|
|
104
|
+
async ensureGlobalStructure(): Promise<void> {
|
|
117
105
|
await fileHelper.ensureDir(this.globalBaseDir)
|
|
118
106
|
await fileHelper.ensureDir(this.globalProjectsDir)
|
|
119
107
|
await fileHelper.ensureDir(this.globalConfigDir)
|
|
@@ -122,11 +110,8 @@ class PathManager {
|
|
|
122
110
|
/**
|
|
123
111
|
* Ensure the project-specific global structure exists
|
|
124
112
|
* Creates the layered directory structure for a project
|
|
125
|
-
*
|
|
126
|
-
* @param {string} projectId - The project identifier
|
|
127
|
-
* @returns {Promise<string>} - Path to the project's global storage
|
|
128
113
|
*/
|
|
129
|
-
async ensureProjectStructure(projectId) {
|
|
114
|
+
async ensureProjectStructure(projectId: string): Promise<string> {
|
|
130
115
|
await this.ensureGlobalStructure()
|
|
131
116
|
|
|
132
117
|
const projectPath = this.getGlobalProjectPath(projectId)
|
|
@@ -146,12 +131,8 @@ class PathManager {
|
|
|
146
131
|
/**
|
|
147
132
|
* Get session directory path for a specific date
|
|
148
133
|
* Creates hierarchical structure: sessions/YYYY/MM/DD/
|
|
149
|
-
*
|
|
150
|
-
* @param {string} projectId - The project identifier
|
|
151
|
-
* @param {Date} date - Date for the session (defaults to today)
|
|
152
|
-
* @returns {string} - Path to session directory
|
|
153
134
|
*/
|
|
154
|
-
getSessionPath(projectId, date = new Date()) {
|
|
135
|
+
getSessionPath(projectId: string, date: Date = new Date()): string {
|
|
155
136
|
const { year, month, day } = dateHelper.getYearMonthDay(date)
|
|
156
137
|
|
|
157
138
|
return path.join(this.getGlobalProjectPath(projectId), 'sessions', year, month, day)
|
|
@@ -159,22 +140,15 @@ class PathManager {
|
|
|
159
140
|
|
|
160
141
|
/**
|
|
161
142
|
* Get current session directory path (today)
|
|
162
|
-
*
|
|
163
|
-
* @param {string} projectId - The project identifier
|
|
164
|
-
* @returns {string} - Path to today's session directory
|
|
165
143
|
*/
|
|
166
|
-
getCurrentSessionPath(projectId) {
|
|
144
|
+
getCurrentSessionPath(projectId: string): string {
|
|
167
145
|
return this.getSessionPath(projectId, new Date())
|
|
168
146
|
}
|
|
169
147
|
|
|
170
148
|
/**
|
|
171
149
|
* Ensure session directory exists for a specific date
|
|
172
|
-
*
|
|
173
|
-
* @param {string} projectId - The project identifier
|
|
174
|
-
* @param {Date} date - Date for the session (defaults to today)
|
|
175
|
-
* @returns {Promise<string>} - Path to session directory
|
|
176
150
|
*/
|
|
177
|
-
async ensureSessionPath(projectId, date = new Date()) {
|
|
151
|
+
async ensureSessionPath(projectId: string, date: Date = new Date()): Promise<string> {
|
|
178
152
|
const sessionPath = this.getSessionPath(projectId, date)
|
|
179
153
|
await fileHelper.ensureDir(sessionPath)
|
|
180
154
|
return sessionPath
|
|
@@ -182,15 +156,14 @@ class PathManager {
|
|
|
182
156
|
|
|
183
157
|
/**
|
|
184
158
|
* List all session dates for a project
|
|
185
|
-
*
|
|
186
|
-
* @param {string} projectId - The project identifier
|
|
187
|
-
* @param {number} year - Optional year filter
|
|
188
|
-
* @param {number} month - Optional month filter (1-12)
|
|
189
|
-
* @returns {Promise<Array<{year: string, month: string, day: string, path: string}>>} - Array of session info
|
|
190
159
|
*/
|
|
191
|
-
async listSessions(
|
|
160
|
+
async listSessions(
|
|
161
|
+
projectId: string,
|
|
162
|
+
year: number | null = null,
|
|
163
|
+
month: number | null = null
|
|
164
|
+
): Promise<SessionInfo[]> {
|
|
192
165
|
const sessionsDir = path.join(this.getGlobalProjectPath(projectId), 'sessions')
|
|
193
|
-
const sessions = []
|
|
166
|
+
const sessions: SessionInfo[] = []
|
|
194
167
|
|
|
195
168
|
try {
|
|
196
169
|
const years = await fs.readdir(sessionsDir, { withFileTypes: true })
|
|
@@ -223,7 +196,7 @@ class PathManager {
|
|
|
223
196
|
}
|
|
224
197
|
}
|
|
225
198
|
|
|
226
|
-
sessions.sort((a, b) => b.date - a.date)
|
|
199
|
+
sessions.sort((a, b) => b.date.getTime() - a.date.getTime())
|
|
227
200
|
return sessions
|
|
228
201
|
} catch {
|
|
229
202
|
return []
|
|
@@ -232,13 +205,12 @@ class PathManager {
|
|
|
232
205
|
|
|
233
206
|
/**
|
|
234
207
|
* Get sessions within a date range
|
|
235
|
-
*
|
|
236
|
-
* @param {string} projectId - The project identifier
|
|
237
|
-
* @param {Date} fromDate - Start date (inclusive)
|
|
238
|
-
* @param {Date} toDate - End date (inclusive, defaults to today)
|
|
239
|
-
* @returns {Promise<Array>} - Array of session info within range
|
|
240
208
|
*/
|
|
241
|
-
async getSessionsInRange(
|
|
209
|
+
async getSessionsInRange(
|
|
210
|
+
projectId: string,
|
|
211
|
+
fromDate: Date,
|
|
212
|
+
toDate: Date = new Date()
|
|
213
|
+
): Promise<SessionInfo[]> {
|
|
242
214
|
const allSessions = await this.listSessions(projectId)
|
|
243
215
|
|
|
244
216
|
return allSessions.filter((session) => session.date >= fromDate && session.date <= toDate)
|
|
@@ -246,22 +218,15 @@ class PathManager {
|
|
|
246
218
|
|
|
247
219
|
/**
|
|
248
220
|
* Get the path for a specific file in the global structure
|
|
249
|
-
*
|
|
250
|
-
* @param {string} projectId - The project identifier
|
|
251
|
-
* @param {string} layer - The layer (core, progress, planning, analysis, memory)
|
|
252
|
-
* @param {string} filename - The filename
|
|
253
|
-
* @returns {string} - Full path to the file
|
|
254
221
|
*/
|
|
255
|
-
getFilePath(projectId, layer, filename) {
|
|
222
|
+
getFilePath(projectId: string, layer: string, filename: string): string {
|
|
256
223
|
return path.join(this.getGlobalProjectPath(projectId), layer, filename)
|
|
257
224
|
}
|
|
258
225
|
|
|
259
226
|
/**
|
|
260
227
|
* Get all project IDs in global storage
|
|
261
|
-
*
|
|
262
|
-
* @returns {Promise<string[]>} - Array of project IDs
|
|
263
228
|
*/
|
|
264
|
-
async listProjects() {
|
|
229
|
+
async listProjects(): Promise<string[]> {
|
|
265
230
|
try {
|
|
266
231
|
await this.ensureGlobalStructure()
|
|
267
232
|
const entries = await fs.readdir(this.globalProjectsDir, { withFileTypes: true })
|
|
@@ -273,22 +238,16 @@ class PathManager {
|
|
|
273
238
|
|
|
274
239
|
/**
|
|
275
240
|
* Check if a project exists in global storage
|
|
276
|
-
*
|
|
277
|
-
* @param {string} projectId - The project identifier
|
|
278
|
-
* @returns {Promise<boolean>} - True if project exists
|
|
279
241
|
*/
|
|
280
|
-
async projectExists(projectId) {
|
|
242
|
+
async projectExists(projectId: string): Promise<boolean> {
|
|
281
243
|
const projectPath = this.getGlobalProjectPath(projectId)
|
|
282
244
|
return await fileHelper.dirExists(projectPath)
|
|
283
245
|
}
|
|
284
246
|
|
|
285
247
|
/**
|
|
286
248
|
* Get the relative path from home directory for display
|
|
287
|
-
*
|
|
288
|
-
* @param {string} absolutePath - Absolute path
|
|
289
|
-
* @returns {string} - Path with ~ notation
|
|
290
249
|
*/
|
|
291
|
-
getDisplayPath(absolutePath) {
|
|
250
|
+
getDisplayPath(absolutePath: string): string {
|
|
292
251
|
const homeDir = os.homedir()
|
|
293
252
|
if (absolutePath.startsWith(homeDir)) {
|
|
294
253
|
return absolutePath.replace(homeDir, '~')
|
|
@@ -297,4 +256,5 @@ class PathManager {
|
|
|
297
256
|
}
|
|
298
257
|
}
|
|
299
258
|
|
|
300
|
-
|
|
259
|
+
const pathManager = new PathManager()
|
|
260
|
+
export default pathManager
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Session Manager
|
|
3
|
+
* Manages temporal fragmentation of logs and progress data.
|
|
4
|
+
*
|
|
5
|
+
* @module infrastructure/session-manager
|
|
6
|
+
* @version 0.2.1
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
export type {
|
|
10
|
+
SessionEntry,
|
|
11
|
+
SessionMetadata,
|
|
12
|
+
SessionStats,
|
|
13
|
+
MigrationResult,
|
|
14
|
+
SessionInfo,
|
|
15
|
+
} from './types'
|
|
16
|
+
|
|
17
|
+
export { migrateLegacyJsonl, migrateLegacyMarkdown } from './migration'
|
|
18
|
+
export { SessionManager } from './session-manager'
|
|
19
|
+
|
|
20
|
+
import { SessionManager } from './session-manager'
|
|
21
|
+
|
|
22
|
+
const sessionManager = new SessionManager()
|
|
23
|
+
export default sessionManager
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Session Migration
|
|
3
|
+
* Migrate legacy single-file logs to session structure
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import path from 'path'
|
|
7
|
+
import pathManager from '../path-manager'
|
|
8
|
+
import * as dateHelper from '../../utils/date-helper'
|
|
9
|
+
import * as jsonlHelper from '../../utils/jsonl-helper'
|
|
10
|
+
import * as fileHelper from '../../utils/file-helper'
|
|
11
|
+
import type { SessionEntry, MigrationResult, SessionMetadata } from './types'
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Migrate legacy JSONL file
|
|
15
|
+
*/
|
|
16
|
+
export async function migrateLegacyJsonl(
|
|
17
|
+
projectId: string,
|
|
18
|
+
content: string,
|
|
19
|
+
sessionFilename: string,
|
|
20
|
+
updateMetadata: (sessionPath: string, updates: Partial<SessionMetadata>) => Promise<void>,
|
|
21
|
+
ensureMetadata: (sessionPath: string) => Promise<void>
|
|
22
|
+
): Promise<MigrationResult> {
|
|
23
|
+
const entries = jsonlHelper.parseJsonLines(content) as SessionEntry[]
|
|
24
|
+
const sessionGroups = new Map<string, SessionEntry[]>()
|
|
25
|
+
|
|
26
|
+
for (const entry of entries) {
|
|
27
|
+
const date = new Date(entry.timestamp || entry.data?.timestamp || Date.now())
|
|
28
|
+
const dateKey = dateHelper.getDateKey(date)
|
|
29
|
+
|
|
30
|
+
if (!sessionGroups.has(dateKey)) {
|
|
31
|
+
sessionGroups.set(dateKey, [])
|
|
32
|
+
}
|
|
33
|
+
sessionGroups.get(dateKey)!.push(entry)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
let migratedCount = 0
|
|
37
|
+
for (const [dateKey, groupEntries] of sessionGroups) {
|
|
38
|
+
const [year, monthStr, day] = dateKey.split('-')
|
|
39
|
+
const month = parseInt(monthStr, 10)
|
|
40
|
+
const date = new Date(parseInt(year, 10), month - 1, parseInt(day, 10))
|
|
41
|
+
const sessionPath = await pathManager.ensureSessionPath(projectId, date)
|
|
42
|
+
const filePath = path.join(sessionPath, sessionFilename)
|
|
43
|
+
|
|
44
|
+
await jsonlHelper.writeJsonLines(filePath, groupEntries)
|
|
45
|
+
|
|
46
|
+
migratedCount += groupEntries.length
|
|
47
|
+
|
|
48
|
+
await ensureMetadata(sessionPath)
|
|
49
|
+
await updateMetadata(sessionPath, {
|
|
50
|
+
entryCount: groupEntries.length,
|
|
51
|
+
migrated: true,
|
|
52
|
+
migratedAt: dateHelper.getTimestamp(),
|
|
53
|
+
})
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return {
|
|
57
|
+
success: true,
|
|
58
|
+
message: `Migrated ${migratedCount} entries to ${sessionGroups.size} sessions`,
|
|
59
|
+
entriesMigrated: migratedCount,
|
|
60
|
+
sessionsCreated: sessionGroups.size,
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Migrate legacy markdown file
|
|
66
|
+
*/
|
|
67
|
+
export async function migrateLegacyMarkdown(
|
|
68
|
+
sessionPath: string,
|
|
69
|
+
content: string,
|
|
70
|
+
sessionFilename: string,
|
|
71
|
+
updateMetadata: (sessionPath: string, updates: Partial<SessionMetadata>) => Promise<void>
|
|
72
|
+
): Promise<MigrationResult> {
|
|
73
|
+
const filePath = path.join(sessionPath, sessionFilename)
|
|
74
|
+
|
|
75
|
+
await fileHelper.writeFile(filePath, content)
|
|
76
|
+
|
|
77
|
+
await updateMetadata(sessionPath, {
|
|
78
|
+
migrated: true,
|
|
79
|
+
migratedAt: dateHelper.getTimestamp(),
|
|
80
|
+
})
|
|
81
|
+
|
|
82
|
+
return {
|
|
83
|
+
success: true,
|
|
84
|
+
message: 'Migrated markdown content to current session',
|
|
85
|
+
entriesMigrated: 1,
|
|
86
|
+
sessionsCreated: 1,
|
|
87
|
+
}
|
|
88
|
+
}
|