prjct-cli 1.22.0 → 1.23.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 +147 -0
- package/bin/prjct +30 -13
- package/dist/bin/prjct.mjs +917 -35845
- package/dist/bin/prjct.mjs.map +7 -0
- package/dist/cli/linear.mjs +16 -0
- package/dist/cli/linear.mjs.map +7 -0
- package/dist/templates.json +1 -0
- package/package.json +4 -5
- package/bin/prjct.ts +0 -342
- package/core/__tests__/agentic/analysis-injection.test.ts +0 -377
- package/core/__tests__/agentic/cache-eviction.test.ts +0 -294
- package/core/__tests__/agentic/command-context.test.ts +0 -281
- package/core/__tests__/agentic/command-executor.test.ts +0 -659
- package/core/__tests__/agentic/domain-classifier.test.ts +0 -330
- package/core/__tests__/agentic/injection-validator.test.ts +0 -255
- package/core/__tests__/agentic/memory-system.test.ts +0 -281
- package/core/__tests__/agentic/plan-mode.test.ts +0 -386
- package/core/__tests__/agentic/prompt-assembly.test.ts +0 -298
- package/core/__tests__/agentic/prompt-builder.test.ts +0 -243
- package/core/__tests__/agentic/response-validator.test.ts +0 -263
- package/core/__tests__/agentic/semantic-matching.test.ts +0 -131
- package/core/__tests__/agentic/smart-context.test.ts +0 -372
- package/core/__tests__/agentic/tech-normalizer.test.ts +0 -136
- package/core/__tests__/agentic/token-budget.test.ts +0 -294
- package/core/__tests__/ai-tools/formatters.test.ts +0 -476
- package/core/__tests__/domain/bm25.test.ts +0 -225
- package/core/__tests__/domain/change-propagator.test.ts +0 -100
- package/core/__tests__/domain/fibonacci.test.ts +0 -113
- package/core/__tests__/domain/file-hasher.test.ts +0 -146
- package/core/__tests__/domain/file-ranker.test.ts +0 -169
- package/core/__tests__/domain/git-cochange.test.ts +0 -121
- package/core/__tests__/domain/import-graph.test.ts +0 -156
- package/core/__tests__/domain/velocity.test.ts +0 -623
- package/core/__tests__/infrastructure/performance-tracker.test.ts +0 -328
- package/core/__tests__/schemas/model.test.ts +0 -272
- package/core/__tests__/services/dependency-validator.test.ts +0 -175
- package/core/__tests__/services/hierarchical-agent-resolver.test.ts +0 -359
- package/core/__tests__/services/nested-context-resolver.test.ts +0 -443
- package/core/__tests__/services/project-index.test.ts +0 -355
- package/core/__tests__/services/staleness-checker.test.ts +0 -204
- package/core/__tests__/storage/analysis-storage.test.ts +0 -641
- package/core/__tests__/storage/archive-storage.test.ts +0 -455
- package/core/__tests__/storage/safe-reader.test.ts +0 -262
- package/core/__tests__/storage/sqlite-migration.test.ts +0 -1016
- package/core/__tests__/storage/state-storage-feedback.test.ts +0 -463
- package/core/__tests__/storage/state-storage-history.test.ts +0 -469
- package/core/__tests__/storage/storage-manager.test.ts +0 -383
- package/core/__tests__/storage/subtask-handoff.test.ts +0 -237
- package/core/__tests__/types/fs.test.ts +0 -125
- package/core/__tests__/utils/date-helper.test.ts +0 -449
- package/core/__tests__/utils/output.test.ts +0 -278
- package/core/__tests__/utils/preserve-sections.test.ts +0 -216
- package/core/__tests__/utils/project-commands.test.ts +0 -71
- package/core/__tests__/utils/retry.test.ts +0 -381
- package/core/__tests__/workflow/state-machine.test.ts +0 -216
- package/core/agentic/agent-router.ts +0 -150
- package/core/agentic/anti-hallucination.ts +0 -141
- package/core/agentic/chain-of-thought.ts +0 -234
- package/core/agentic/command-classifier.ts +0 -141
- package/core/agentic/command-context.ts +0 -168
- package/core/agentic/command-executor.ts +0 -471
- package/core/agentic/context-builder.ts +0 -285
- package/core/agentic/domain-classifier.ts +0 -525
- package/core/agentic/environment-block.ts +0 -102
- package/core/agentic/ground-truth.ts +0 -706
- package/core/agentic/index.ts +0 -193
- package/core/agentic/injection-validator.ts +0 -208
- package/core/agentic/loop-detector.ts +0 -451
- package/core/agentic/memory-system.ts +0 -1547
- package/core/agentic/orchestrator-executor.ts +0 -579
- package/core/agentic/plan-mode.ts +0 -525
- package/core/agentic/prompt-builder.ts +0 -1069
- package/core/agentic/response-validator.ts +0 -98
- package/core/agentic/services.ts +0 -167
- package/core/agentic/skill-loader.ts +0 -106
- package/core/agentic/smart-context.ts +0 -393
- package/core/agentic/tech-normalizer.ts +0 -167
- package/core/agentic/template-executor.ts +0 -272
- package/core/agentic/template-loader.ts +0 -109
- package/core/agentic/token-budget.ts +0 -226
- package/core/agentic/tool-registry.ts +0 -146
- package/core/agents/index.ts +0 -28
- package/core/agents/performance.ts +0 -429
- package/core/ai-tools/formatters.ts +0 -341
- package/core/ai-tools/generator.ts +0 -144
- package/core/ai-tools/index.ts +0 -15
- package/core/ai-tools/registry.ts +0 -201
- package/core/bus/bus.ts +0 -314
- package/core/bus/index.ts +0 -8
- package/core/cli/linear.ts +0 -500
- package/core/cli/lint-meta-commentary.ts +0 -177
- package/core/cli/start.ts +0 -386
- package/core/commands/analysis.ts +0 -1274
- package/core/commands/analytics.ts +0 -342
- package/core/commands/base.ts +0 -118
- package/core/commands/cleanup.ts +0 -157
- package/core/commands/command-data.ts +0 -463
- package/core/commands/commands.ts +0 -306
- package/core/commands/context.ts +0 -238
- package/core/commands/design.ts +0 -77
- package/core/commands/index.ts +0 -19
- package/core/commands/maintenance.ts +0 -77
- package/core/commands/performance.ts +0 -114
- package/core/commands/planning.ts +0 -662
- package/core/commands/register.ts +0 -127
- package/core/commands/registry.ts +0 -444
- package/core/commands/setup.ts +0 -280
- package/core/commands/shipping.ts +0 -267
- package/core/commands/snapshots.ts +0 -297
- package/core/commands/uninstall.ts +0 -542
- package/core/commands/velocity.ts +0 -149
- package/core/commands/workflow.ts +0 -505
- package/core/config/command-context.config.json +0 -66
- package/core/constants/index.ts +0 -379
- package/core/context/generator.ts +0 -368
- package/core/context-tools/files-tool.ts +0 -577
- package/core/context-tools/imports-tool.ts +0 -400
- package/core/context-tools/index.ts +0 -434
- package/core/context-tools/recent-tool.ts +0 -301
- package/core/context-tools/signatures-tool.ts +0 -495
- package/core/context-tools/summary-tool.ts +0 -301
- package/core/context-tools/token-counter.ts +0 -273
- package/core/context-tools/types.ts +0 -253
- package/core/domain/agent-generator.ts +0 -186
- package/core/domain/agent-loader.ts +0 -419
- package/core/domain/analyzer.ts +0 -387
- package/core/domain/architecture-generator.ts +0 -108
- package/core/domain/bm25.ts +0 -525
- package/core/domain/change-propagator.ts +0 -162
- package/core/domain/context-estimator.ts +0 -175
- package/core/domain/fibonacci.ts +0 -128
- package/core/domain/file-hasher.ts +0 -296
- package/core/domain/file-ranker.ts +0 -151
- package/core/domain/git-cochange.ts +0 -250
- package/core/domain/import-graph.ts +0 -315
- package/core/domain/snapshot-manager.ts +0 -415
- package/core/domain/task-stack.ts +0 -578
- package/core/domain/velocity.ts +0 -470
- package/core/errors.ts +0 -335
- package/core/events/events.ts +0 -85
- package/core/events/index.ts +0 -8
- package/core/index.ts +0 -481
- package/core/infrastructure/agent-detector.ts +0 -135
- package/core/infrastructure/ai-provider.ts +0 -578
- package/core/infrastructure/author-detector.ts +0 -133
- package/core/infrastructure/capability-installer.ts +0 -76
- package/core/infrastructure/claude-agent.ts +0 -297
- package/core/infrastructure/command-installer.ts +0 -752
- package/core/infrastructure/config-manager.ts +0 -364
- package/core/infrastructure/editors-config.ts +0 -172
- package/core/infrastructure/path-manager.ts +0 -571
- package/core/infrastructure/performance-tracker.ts +0 -326
- package/core/infrastructure/permission-manager.ts +0 -289
- package/core/infrastructure/setup.ts +0 -1061
- package/core/infrastructure/update-checker.ts +0 -246
- package/core/integrations/issue-tracker/enricher.ts +0 -271
- package/core/integrations/issue-tracker/index.ts +0 -8
- package/core/integrations/issue-tracker/manager.ts +0 -286
- package/core/integrations/issue-tracker/types.ts +0 -310
- package/core/integrations/jira/cache.ts +0 -57
- package/core/integrations/jira/client.ts +0 -688
- package/core/integrations/jira/index.ts +0 -23
- package/core/integrations/jira/service.ts +0 -244
- package/core/integrations/linear/cache.ts +0 -68
- package/core/integrations/linear/client.ts +0 -436
- package/core/integrations/linear/index.ts +0 -20
- package/core/integrations/linear/service.ts +0 -260
- package/core/integrations/linear/sync.ts +0 -314
- package/core/outcomes/analyzer.ts +0 -286
- package/core/outcomes/index.ts +0 -34
- package/core/outcomes/recorder.ts +0 -195
- package/core/plugin/builtin/webhook.ts +0 -148
- package/core/plugin/hooks.ts +0 -315
- package/core/plugin/index.ts +0 -50
- package/core/plugin/loader.ts +0 -354
- package/core/plugin/registry.ts +0 -326
- package/core/schemas/agents.ts +0 -27
- package/core/schemas/analysis.ts +0 -530
- package/core/schemas/classification.ts +0 -91
- package/core/schemas/command-context.ts +0 -29
- package/core/schemas/enriched-task.ts +0 -291
- package/core/schemas/ideas.ts +0 -114
- package/core/schemas/index.ts +0 -53
- package/core/schemas/issues.ts +0 -159
- package/core/schemas/llm-output.ts +0 -170
- package/core/schemas/metrics.ts +0 -143
- package/core/schemas/model.ts +0 -153
- package/core/schemas/outcomes.ts +0 -487
- package/core/schemas/performance.ts +0 -128
- package/core/schemas/permissions.ts +0 -180
- package/core/schemas/prd.ts +0 -450
- package/core/schemas/project.ts +0 -57
- package/core/schemas/roadmap.ts +0 -322
- package/core/schemas/schemas.ts +0 -38
- package/core/schemas/shipped.ts +0 -109
- package/core/schemas/state.ts +0 -284
- package/core/schemas/velocity.ts +0 -103
- package/core/server/index.ts +0 -21
- package/core/server/routes-extended.ts +0 -566
- package/core/server/routes.ts +0 -176
- package/core/server/server.ts +0 -149
- package/core/server/sse.ts +0 -192
- package/core/services/agent-generator.ts +0 -385
- package/core/services/agent-service.ts +0 -168
- package/core/services/breakdown-service.ts +0 -124
- package/core/services/context-generator.ts +0 -445
- package/core/services/context-selector.ts +0 -429
- package/core/services/dependency-validator.ts +0 -318
- package/core/services/diff-generator.ts +0 -313
- package/core/services/doctor-service.ts +0 -423
- package/core/services/file-categorizer.ts +0 -448
- package/core/services/file-scorer.ts +0 -270
- package/core/services/git-analyzer.ts +0 -293
- package/core/services/hierarchical-agent-resolver.ts +0 -236
- package/core/services/hooks-service.ts +0 -685
- package/core/services/index.ts +0 -46
- package/core/services/local-state-generator.ts +0 -158
- package/core/services/memory-service.ts +0 -181
- package/core/services/nested-context-resolver.ts +0 -842
- package/core/services/project-index.ts +0 -911
- package/core/services/project-service.ts +0 -155
- package/core/services/session-tracker.ts +0 -287
- package/core/services/skill-installer.ts +0 -447
- package/core/services/skill-lock.ts +0 -132
- package/core/services/skill-service.ts +0 -306
- package/core/services/stack-detector.ts +0 -229
- package/core/services/staleness-checker.ts +0 -327
- package/core/services/sync-service.ts +0 -1515
- package/core/services/sync-verifier.ts +0 -253
- package/core/services/watch-service.ts +0 -312
- package/core/session/compaction.ts +0 -248
- package/core/session/index.ts +0 -35
- package/core/session/log-migration.ts +0 -88
- package/core/session/metrics.ts +0 -323
- package/core/session/session-log-manager.ts +0 -307
- package/core/session/task-session-manager.ts +0 -404
- package/core/session/utils.ts +0 -51
- package/core/storage/analysis-storage.ts +0 -373
- package/core/storage/archive-storage.ts +0 -205
- package/core/storage/database.ts +0 -575
- package/core/storage/ideas-storage.ts +0 -298
- package/core/storage/index-storage.ts +0 -523
- package/core/storage/index.ts +0 -79
- package/core/storage/metrics-storage.ts +0 -321
- package/core/storage/migrate-json.ts +0 -720
- package/core/storage/queue-storage.ts +0 -336
- package/core/storage/safe-reader.ts +0 -105
- package/core/storage/shipped-storage.ts +0 -253
- package/core/storage/state-storage.ts +0 -1035
- package/core/storage/storage-manager.ts +0 -205
- package/core/storage/storage.ts +0 -177
- package/core/storage/velocity-storage.ts +0 -149
- package/core/sync/auth-config.ts +0 -138
- package/core/sync/index.ts +0 -31
- package/core/sync/oauth-handler.ts +0 -143
- package/core/sync/sync-client.ts +0 -251
- package/core/sync/sync-manager.ts +0 -327
- package/core/tsconfig.json +0 -22
- package/core/types/agentic.ts +0 -760
- package/core/types/agents.ts +0 -150
- package/core/types/bus.ts +0 -193
- package/core/types/citations.ts +0 -22
- package/core/types/commands.ts +0 -399
- package/core/types/config.ts +0 -92
- package/core/types/core.ts +0 -96
- package/core/types/diff.ts +0 -41
- package/core/types/domain.ts +0 -71
- package/core/types/errors.ts +0 -111
- package/core/types/events.ts +0 -42
- package/core/types/fs.ts +0 -72
- package/core/types/index.ts +0 -510
- package/core/types/infrastructure.ts +0 -210
- package/core/types/integrations.ts +0 -31
- package/core/types/jira.ts +0 -51
- package/core/types/logger.ts +0 -17
- package/core/types/memory.ts +0 -313
- package/core/types/outcomes.ts +0 -190
- package/core/types/output.ts +0 -47
- package/core/types/plugin.ts +0 -25
- package/core/types/project-sync.ts +0 -129
- package/core/types/provider.ts +0 -163
- package/core/types/server.ts +0 -71
- package/core/types/services.ts +0 -84
- package/core/types/session.ts +0 -135
- package/core/types/stack.ts +0 -19
- package/core/types/storage.ts +0 -318
- package/core/types/sync-verifier.ts +0 -33
- package/core/types/sync.ts +0 -121
- package/core/types/task.ts +0 -72
- package/core/types/template.ts +0 -24
- package/core/types/utils.ts +0 -92
- package/core/types/workflow.ts +0 -23
- package/core/utils/agent-stream.ts +0 -140
- package/core/utils/animations.ts +0 -251
- package/core/utils/branding.ts +0 -88
- package/core/utils/cache.ts +0 -187
- package/core/utils/citations.ts +0 -39
- package/core/utils/collection-filters.ts +0 -209
- package/core/utils/date-helper.ts +0 -176
- package/core/utils/error-messages.ts +0 -38
- package/core/utils/file-helper.ts +0 -277
- package/core/utils/fs-helpers.ts +0 -14
- package/core/utils/help.ts +0 -314
- package/core/utils/jsonl-helper.ts +0 -290
- package/core/utils/keychain.ts +0 -127
- package/core/utils/logger.ts +0 -77
- package/core/utils/markdown-builder.ts +0 -280
- package/core/utils/next-steps.ts +0 -95
- package/core/utils/output.ts +0 -403
- package/core/utils/preserve-sections.ts +0 -218
- package/core/utils/project-commands.ts +0 -126
- package/core/utils/project-credentials.ts +0 -143
- package/core/utils/provider-cache.ts +0 -49
- package/core/utils/retry.ts +0 -318
- package/core/utils/runtime.ts +0 -108
- package/core/utils/session-helper.ts +0 -278
- package/core/utils/subtask-table.ts +0 -227
- package/core/utils/version.ts +0 -128
- package/core/wizard/index.ts +0 -13
- package/core/wizard/onboarding.ts +0 -633
- package/core/workflow/index.ts +0 -7
- package/core/workflow/state-machine.ts +0 -198
- package/core/workflow/workflow-preferences.ts +0 -294
- package/dist/core/infrastructure/command-installer.js +0 -1141
- package/dist/core/infrastructure/editors-config.js +0 -177
- package/dist/core/infrastructure/setup.js +0 -2244
- package/dist/core/utils/version.js +0 -141
- package/templates/agentic/agent-routing.md +0 -45
- package/templates/agentic/agents/uxui.md +0 -63
- package/templates/agentic/checklist-routing.md +0 -98
- package/templates/agentic/orchestrator.md +0 -68
- package/templates/agentic/task-fragmentation.md +0 -89
- package/templates/agents/AGENTS.md +0 -68
- package/templates/analysis/analyze.md +0 -84
- package/templates/analysis/patterns.md +0 -60
- package/templates/antigravity/SKILL.md +0 -39
- package/templates/architect/discovery.md +0 -67
- package/templates/architect/phases.md +0 -59
- package/templates/checklists/architecture.md +0 -28
- package/templates/checklists/code-quality.md +0 -28
- package/templates/checklists/data.md +0 -33
- package/templates/checklists/documentation.md +0 -33
- package/templates/checklists/infrastructure.md +0 -33
- package/templates/checklists/performance.md +0 -33
- package/templates/checklists/security.md +0 -33
- package/templates/checklists/testing.md +0 -33
- package/templates/checklists/ux-ui.md +0 -37
- package/templates/commands/analyze.md +0 -56
- package/templates/commands/auth.md +0 -234
- package/templates/commands/bug.md +0 -163
- package/templates/commands/cleanup.md +0 -19
- package/templates/commands/dash.md +0 -99
- package/templates/commands/design.md +0 -15
- package/templates/commands/done.md +0 -291
- package/templates/commands/enrich.md +0 -174
- package/templates/commands/git.md +0 -295
- package/templates/commands/history.md +0 -389
- package/templates/commands/idea.md +0 -88
- package/templates/commands/impact.md +0 -864
- package/templates/commands/init.md +0 -54
- package/templates/commands/jira.md +0 -278
- package/templates/commands/linear.md +0 -288
- package/templates/commands/merge.md +0 -206
- package/templates/commands/next.md +0 -80
- package/templates/commands/p.md +0 -67
- package/templates/commands/p.toml +0 -37
- package/templates/commands/pause.md +0 -136
- package/templates/commands/plan.md +0 -696
- package/templates/commands/prd.md +0 -356
- package/templates/commands/resume.md +0 -171
- package/templates/commands/review.md +0 -276
- package/templates/commands/serve.md +0 -118
- package/templates/commands/setup.md +0 -91
- package/templates/commands/ship.md +0 -475
- package/templates/commands/skill.md +0 -259
- package/templates/commands/spec.md +0 -218
- package/templates/commands/status.md +0 -207
- package/templates/commands/sync.md +0 -104
- package/templates/commands/task.md +0 -312
- package/templates/commands/test.md +0 -93
- package/templates/commands/update.md +0 -63
- package/templates/commands/verify.md +0 -204
- package/templates/commands/workflow.md +0 -150
- package/templates/config/skill-mappings.json +0 -82
- package/templates/context/dashboard.md +0 -256
- package/templates/context/roadmap.md +0 -221
- package/templates/cursor/commands/bug.md +0 -8
- package/templates/cursor/commands/done.md +0 -4
- package/templates/cursor/commands/pause.md +0 -6
- package/templates/cursor/commands/resume.md +0 -4
- package/templates/cursor/commands/ship.md +0 -8
- package/templates/cursor/commands/sync.md +0 -4
- package/templates/cursor/commands/task.md +0 -8
- package/templates/cursor/p.md +0 -29
- package/templates/cursor/router.mdc +0 -28
- package/templates/design/api.md +0 -95
- package/templates/design/architecture.md +0 -77
- package/templates/design/component.md +0 -89
- package/templates/design/database.md +0 -78
- package/templates/design/flow.md +0 -94
- package/templates/global/ANTIGRAVITY.md +0 -254
- package/templates/global/CLAUDE.md +0 -497
- package/templates/global/CURSOR.mdc +0 -266
- package/templates/global/GEMINI.md +0 -293
- package/templates/global/STORAGE-SPEC.md +0 -391
- package/templates/global/WINDSURF.md +0 -266
- package/templates/global/modules/CLAUDE-commands.md +0 -70
- package/templates/global/modules/CLAUDE-core.md +0 -105
- package/templates/global/modules/CLAUDE-git.md +0 -50
- package/templates/global/modules/CLAUDE-intelligence.md +0 -92
- package/templates/global/modules/CLAUDE-storage.md +0 -50
- package/templates/global/modules/module-config.json +0 -36
- package/templates/mcp-config.json +0 -19
- package/templates/permissions/default.jsonc +0 -60
- package/templates/permissions/permissive.jsonc +0 -49
- package/templates/permissions/strict.jsonc +0 -58
- package/templates/planning-methodology.md +0 -195
- package/templates/skills/code-review.md +0 -47
- package/templates/skills/debug.md +0 -61
- package/templates/skills/refactor.md +0 -47
- package/templates/subagents/agent-base.md +0 -20
- package/templates/subagents/domain/backend.md +0 -109
- package/templates/subagents/domain/database.md +0 -121
- package/templates/subagents/domain/devops.md +0 -152
- package/templates/subagents/domain/frontend.md +0 -103
- package/templates/subagents/domain/testing.md +0 -169
- package/templates/subagents/pm-expert.md +0 -366
- package/templates/subagents/workflow/chief-architect.md +0 -657
- package/templates/subagents/workflow/prjct-planner.md +0 -159
- package/templates/subagents/workflow/prjct-shipper.md +0 -188
- package/templates/subagents/workflow/prjct-workflow.md +0 -98
- package/templates/tools/bash.txt +0 -22
- package/templates/tools/edit.txt +0 -18
- package/templates/tools/glob.txt +0 -19
- package/templates/tools/grep.txt +0 -21
- package/templates/tools/read.txt +0 -14
- package/templates/tools/task.txt +0 -20
- package/templates/tools/webfetch.txt +0 -16
- package/templates/tools/websearch.txt +0 -18
- package/templates/tools/write.txt +0 -17
- package/templates/windsurf/router.md +0 -28
- package/templates/windsurf/workflows/bug.md +0 -8
- package/templates/windsurf/workflows/done.md +0 -4
- package/templates/windsurf/workflows/pause.md +0 -4
- package/templates/windsurf/workflows/resume.md +0 -4
- package/templates/windsurf/workflows/ship.md +0 -8
- package/templates/windsurf/workflows/sync.md +0 -4
- package/templates/windsurf/workflows/task.md +0 -8
package/core/utils/help.ts
DELETED
|
@@ -1,314 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Help System - Structured help output for prjct CLI
|
|
3
|
-
*
|
|
4
|
-
* Provides consistent, well-formatted help text for all commands.
|
|
5
|
-
*
|
|
6
|
-
* @see PRJ-133
|
|
7
|
-
* @module utils/help
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
import chalk from 'chalk'
|
|
11
|
-
import { CATEGORIES, COMMANDS } from '../commands/command-data'
|
|
12
|
-
import { VERSION } from './version'
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* Terminal commands that run directly in the shell
|
|
16
|
-
*/
|
|
17
|
-
const TERMINAL_COMMANDS = [
|
|
18
|
-
{
|
|
19
|
-
name: 'start',
|
|
20
|
-
description: 'First-time setup wizard',
|
|
21
|
-
example: 'prjct start',
|
|
22
|
-
},
|
|
23
|
-
{
|
|
24
|
-
name: 'init',
|
|
25
|
-
description: 'Initialize project in current directory',
|
|
26
|
-
example: 'prjct init',
|
|
27
|
-
},
|
|
28
|
-
{
|
|
29
|
-
name: 'sync',
|
|
30
|
-
description: 'Sync project state and update context files',
|
|
31
|
-
example: 'prjct sync',
|
|
32
|
-
},
|
|
33
|
-
{
|
|
34
|
-
name: 'watch',
|
|
35
|
-
description: 'Auto-sync on file changes',
|
|
36
|
-
example: 'prjct watch',
|
|
37
|
-
options: ['--verbose', '--debounce=<ms>', '--interval=<sec>'],
|
|
38
|
-
},
|
|
39
|
-
{
|
|
40
|
-
name: 'hooks',
|
|
41
|
-
description: 'Manage git hooks for auto-sync',
|
|
42
|
-
example: 'prjct hooks install',
|
|
43
|
-
subcommands: ['install', 'uninstall', 'status'],
|
|
44
|
-
},
|
|
45
|
-
{
|
|
46
|
-
name: 'doctor',
|
|
47
|
-
description: 'Check system health and dependencies',
|
|
48
|
-
example: 'prjct doctor',
|
|
49
|
-
},
|
|
50
|
-
{
|
|
51
|
-
name: 'serve',
|
|
52
|
-
description: 'Start web dashboard server',
|
|
53
|
-
example: 'prjct serve [port]',
|
|
54
|
-
},
|
|
55
|
-
{
|
|
56
|
-
name: 'context',
|
|
57
|
-
description: 'Smart context filtering tools for AI',
|
|
58
|
-
example: 'prjct context files "add auth"',
|
|
59
|
-
subcommands: ['files', 'signatures', 'imports', 'recent', 'summary'],
|
|
60
|
-
},
|
|
61
|
-
{
|
|
62
|
-
name: 'linear',
|
|
63
|
-
description: 'Linear issue tracker CLI',
|
|
64
|
-
example: 'prjct linear list',
|
|
65
|
-
subcommands: ['list', 'get', 'create', 'update'],
|
|
66
|
-
},
|
|
67
|
-
{
|
|
68
|
-
name: 'uninstall',
|
|
69
|
-
description: 'Complete system removal of prjct',
|
|
70
|
-
example: 'prjct uninstall --backup',
|
|
71
|
-
options: ['--force', '--backup', '--dry-run', '--keep-package'],
|
|
72
|
-
},
|
|
73
|
-
]
|
|
74
|
-
|
|
75
|
-
/**
|
|
76
|
-
* Global CLI flags
|
|
77
|
-
*/
|
|
78
|
-
const GLOBAL_FLAGS = [
|
|
79
|
-
{ flag: '-q, --quiet', description: 'Suppress all output (errors to stderr only)' },
|
|
80
|
-
{ flag: '-v, --version', description: 'Show version and provider status' },
|
|
81
|
-
{ flag: '-h, --help', description: 'Show this help message' },
|
|
82
|
-
]
|
|
83
|
-
|
|
84
|
-
/**
|
|
85
|
-
* Format the main help output
|
|
86
|
-
*/
|
|
87
|
-
export function formatMainHelp(): string {
|
|
88
|
-
const lines: string[] = []
|
|
89
|
-
|
|
90
|
-
// Header
|
|
91
|
-
lines.push('')
|
|
92
|
-
lines.push(`${chalk.cyan.bold('prjct')} v${VERSION} - Context layer for AI coding agents`)
|
|
93
|
-
lines.push(chalk.dim('Works with Claude Code, Gemini CLI, Cursor, Windsurf, and more.'))
|
|
94
|
-
lines.push('')
|
|
95
|
-
|
|
96
|
-
// Quick Start
|
|
97
|
-
lines.push(chalk.bold('QUICK START'))
|
|
98
|
-
lines.push(chalk.dim('─'.repeat(60)))
|
|
99
|
-
lines.push(
|
|
100
|
-
` ${chalk.green('1.')} prjct start ${chalk.dim('# Configure AI providers')}`
|
|
101
|
-
)
|
|
102
|
-
lines.push(` ${chalk.green('2.')} cd my-project && prjct init`)
|
|
103
|
-
lines.push(` ${chalk.green('3.')} Open in Claude Code / Gemini CLI / Cursor`)
|
|
104
|
-
lines.push(` ${chalk.green('4.')} p. sync ${chalk.dim('# Analyze project')}`)
|
|
105
|
-
lines.push('')
|
|
106
|
-
|
|
107
|
-
// Terminal Commands
|
|
108
|
-
lines.push(chalk.bold('TERMINAL COMMANDS'))
|
|
109
|
-
lines.push(chalk.dim('─'.repeat(60)))
|
|
110
|
-
for (const cmd of TERMINAL_COMMANDS) {
|
|
111
|
-
const name = `prjct ${cmd.name}`.padEnd(22)
|
|
112
|
-
lines.push(` ${name} ${cmd.description}`)
|
|
113
|
-
}
|
|
114
|
-
lines.push('')
|
|
115
|
-
|
|
116
|
-
// AI Agent Commands
|
|
117
|
-
lines.push(`${chalk.bold('AI AGENT COMMANDS')} ${chalk.dim('(inside Claude/Gemini/Cursor)')}`)
|
|
118
|
-
lines.push(chalk.dim('─'.repeat(60)))
|
|
119
|
-
lines.push(` ${'Command'.padEnd(22)} Description`)
|
|
120
|
-
lines.push(` ${chalk.dim('─'.repeat(56))}`)
|
|
121
|
-
|
|
122
|
-
// Core commands
|
|
123
|
-
const coreCommands = COMMANDS.filter((c) => c.group === 'core' && c.usage?.claude)
|
|
124
|
-
for (const cmd of coreCommands.slice(0, 10)) {
|
|
125
|
-
const usage = `p. ${cmd.name}`.padEnd(22)
|
|
126
|
-
lines.push(` ${usage} ${cmd.description}`)
|
|
127
|
-
}
|
|
128
|
-
lines.push(
|
|
129
|
-
` ${chalk.dim(`... and ${coreCommands.length - 10} more (run 'prjct help commands')`)}`
|
|
130
|
-
)
|
|
131
|
-
lines.push('')
|
|
132
|
-
|
|
133
|
-
// Global Flags
|
|
134
|
-
lines.push(chalk.bold('FLAGS'))
|
|
135
|
-
lines.push(chalk.dim('─'.repeat(60)))
|
|
136
|
-
for (const flag of GLOBAL_FLAGS) {
|
|
137
|
-
lines.push(` ${flag.flag.padEnd(22)} ${flag.description}`)
|
|
138
|
-
}
|
|
139
|
-
lines.push('')
|
|
140
|
-
|
|
141
|
-
// More Info
|
|
142
|
-
lines.push(chalk.bold('MORE INFO'))
|
|
143
|
-
lines.push(chalk.dim('─'.repeat(60)))
|
|
144
|
-
lines.push(` Documentation: ${chalk.cyan('https://prjct.app')}`)
|
|
145
|
-
lines.push(` GitHub: ${chalk.cyan('https://github.com/jlopezlira/prjct-cli')}`)
|
|
146
|
-
lines.push(` Per-command: prjct help <command>`)
|
|
147
|
-
lines.push('')
|
|
148
|
-
|
|
149
|
-
return lines.join('\n')
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
/**
|
|
153
|
-
* Format help for a specific terminal command
|
|
154
|
-
*/
|
|
155
|
-
export function formatTerminalCommandHelp(commandName: string): string | null {
|
|
156
|
-
const cmd = TERMINAL_COMMANDS.find((c) => c.name === commandName)
|
|
157
|
-
if (!cmd) return null
|
|
158
|
-
|
|
159
|
-
const lines: string[] = []
|
|
160
|
-
|
|
161
|
-
lines.push('')
|
|
162
|
-
lines.push(`${chalk.cyan.bold(`prjct ${cmd.name}`)} - ${cmd.description}`)
|
|
163
|
-
lines.push('')
|
|
164
|
-
|
|
165
|
-
lines.push(chalk.bold('USAGE'))
|
|
166
|
-
lines.push(` ${cmd.example}`)
|
|
167
|
-
lines.push('')
|
|
168
|
-
|
|
169
|
-
if (cmd.options) {
|
|
170
|
-
lines.push(chalk.bold('OPTIONS'))
|
|
171
|
-
for (const opt of cmd.options) {
|
|
172
|
-
lines.push(` ${opt}`)
|
|
173
|
-
}
|
|
174
|
-
lines.push('')
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
if (cmd.subcommands) {
|
|
178
|
-
lines.push(chalk.bold('SUBCOMMANDS'))
|
|
179
|
-
for (const sub of cmd.subcommands) {
|
|
180
|
-
lines.push(` ${sub}`)
|
|
181
|
-
}
|
|
182
|
-
lines.push('')
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
return lines.join('\n')
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
/**
|
|
189
|
-
* Format help for an AI agent command
|
|
190
|
-
*/
|
|
191
|
-
export function formatAgentCommandHelp(commandName: string): string | null {
|
|
192
|
-
const cmd = COMMANDS.find((c) => c.name === commandName)
|
|
193
|
-
if (!cmd) return null
|
|
194
|
-
|
|
195
|
-
const lines: string[] = []
|
|
196
|
-
|
|
197
|
-
lines.push('')
|
|
198
|
-
lines.push(`${chalk.cyan.bold(`p. ${cmd.name}`)} - ${cmd.description}`)
|
|
199
|
-
lines.push('')
|
|
200
|
-
|
|
201
|
-
lines.push(chalk.bold('USAGE'))
|
|
202
|
-
if (cmd.usage?.claude) {
|
|
203
|
-
lines.push(` Claude/Gemini: ${cmd.usage.claude.replace('/p:', 'p. ')}`)
|
|
204
|
-
}
|
|
205
|
-
if (cmd.usage?.terminal) {
|
|
206
|
-
lines.push(` Terminal: ${cmd.usage.terminal}`)
|
|
207
|
-
}
|
|
208
|
-
lines.push('')
|
|
209
|
-
|
|
210
|
-
if (cmd.params) {
|
|
211
|
-
lines.push(chalk.bold('PARAMETERS'))
|
|
212
|
-
lines.push(` ${cmd.params}`)
|
|
213
|
-
lines.push('')
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
if (cmd.features && cmd.features.length > 0) {
|
|
217
|
-
lines.push(chalk.bold('FEATURES'))
|
|
218
|
-
for (const feature of cmd.features) {
|
|
219
|
-
lines.push(` • ${feature}`)
|
|
220
|
-
}
|
|
221
|
-
lines.push('')
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
if (cmd.blockingRules) {
|
|
225
|
-
lines.push(chalk.bold('REQUIREMENTS'))
|
|
226
|
-
lines.push(` ${chalk.yellow('⚠')} ${cmd.blockingRules.check}`)
|
|
227
|
-
lines.push('')
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
// Category info
|
|
231
|
-
const category = CATEGORIES[cmd.group]
|
|
232
|
-
if (category) {
|
|
233
|
-
lines.push(chalk.dim(`Category: ${category.title}`))
|
|
234
|
-
if (cmd.isOptional) {
|
|
235
|
-
lines.push(chalk.dim('This is an optional command.'))
|
|
236
|
-
}
|
|
237
|
-
lines.push('')
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
return lines.join('\n')
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
/**
|
|
244
|
-
* Format help for a specific command (auto-detect type)
|
|
245
|
-
*/
|
|
246
|
-
export function formatCommandHelp(commandName: string): string {
|
|
247
|
-
// Try terminal command first
|
|
248
|
-
const terminalHelp = formatTerminalCommandHelp(commandName)
|
|
249
|
-
if (terminalHelp) return terminalHelp
|
|
250
|
-
|
|
251
|
-
// Try agent command
|
|
252
|
-
const agentHelp = formatAgentCommandHelp(commandName)
|
|
253
|
-
if (agentHelp) return agentHelp
|
|
254
|
-
|
|
255
|
-
// Command not found
|
|
256
|
-
return `
|
|
257
|
-
${chalk.yellow(`Command '${commandName}' not found.`)}
|
|
258
|
-
|
|
259
|
-
Run 'prjct help' to see all available commands.
|
|
260
|
-
`
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
/**
|
|
264
|
-
* Format list of all commands grouped by category
|
|
265
|
-
*/
|
|
266
|
-
export function formatCommandList(): string {
|
|
267
|
-
const lines: string[] = []
|
|
268
|
-
|
|
269
|
-
lines.push('')
|
|
270
|
-
lines.push(chalk.cyan.bold('All Commands'))
|
|
271
|
-
lines.push('')
|
|
272
|
-
|
|
273
|
-
// Group by category
|
|
274
|
-
const categories = Object.entries(CATEGORIES).sort((a, b) => a[1].order - b[1].order)
|
|
275
|
-
|
|
276
|
-
for (const [categoryKey, category] of categories) {
|
|
277
|
-
const categoryCommands = COMMANDS.filter((c) => c.group === categoryKey)
|
|
278
|
-
if (categoryCommands.length === 0) continue
|
|
279
|
-
|
|
280
|
-
lines.push(
|
|
281
|
-
`${chalk.bold(category.title)} ${chalk.dim(`(${categoryCommands.length} commands)`)}`
|
|
282
|
-
)
|
|
283
|
-
lines.push(chalk.dim(category.description))
|
|
284
|
-
lines.push('')
|
|
285
|
-
|
|
286
|
-
for (const cmd of categoryCommands) {
|
|
287
|
-
const name = `p. ${cmd.name}`.padEnd(18)
|
|
288
|
-
const desc =
|
|
289
|
-
cmd.description.length > 45 ? `${cmd.description.slice(0, 42)}...` : cmd.description
|
|
290
|
-
lines.push(` ${name} ${desc}`)
|
|
291
|
-
}
|
|
292
|
-
lines.push('')
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
lines.push(chalk.dim("Run 'prjct help <command>' for detailed help on a specific command."))
|
|
296
|
-
lines.push('')
|
|
297
|
-
|
|
298
|
-
return lines.join('\n')
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
/**
|
|
302
|
-
* Get help output based on topic
|
|
303
|
-
*/
|
|
304
|
-
export function getHelp(topic?: string): string {
|
|
305
|
-
if (!topic) {
|
|
306
|
-
return formatMainHelp()
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
if (topic === 'commands' || topic === 'all') {
|
|
310
|
-
return formatCommandList()
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
return formatCommandHelp(topic)
|
|
314
|
-
}
|
|
@@ -1,290 +0,0 @@
|
|
|
1
|
-
import fsSync from 'node:fs'
|
|
2
|
-
import fs from 'node:fs/promises'
|
|
3
|
-
import path from 'node:path'
|
|
4
|
-
import readline from 'node:readline'
|
|
5
|
-
import { STORAGE_LIMITS } from '../constants'
|
|
6
|
-
import { isNotFoundError } from '../types/fs'
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* JSONL Helper - Centralized JSONL parsing and writing
|
|
10
|
-
*
|
|
11
|
-
* Eliminates duplicated JSONL logic across:
|
|
12
|
-
* - session-manager.ts (_parseJsonLines)
|
|
13
|
-
* - commands.ts (inline parsing)
|
|
14
|
-
* - analyzer.ts (inline parsing)
|
|
15
|
-
*
|
|
16
|
-
* JSONL Format: One JSON object per line, newline-separated
|
|
17
|
-
* Example:
|
|
18
|
-
* {"ts":"2025-10-04T14:30:00Z","type":"feature_add","name":"auth"}
|
|
19
|
-
* {"ts":"2025-10-04T15:00:00Z","type":"task_start","task":"JWT"}
|
|
20
|
-
*/
|
|
21
|
-
|
|
22
|
-
interface FileSizeWarning {
|
|
23
|
-
sizeMB: number
|
|
24
|
-
isLarge: boolean
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* Parse JSONL content into array of objects
|
|
29
|
-
* Handles malformed lines gracefully (skips them)
|
|
30
|
-
*/
|
|
31
|
-
export function parseJsonLines<T = Record<string, unknown>>(content: string): T[] {
|
|
32
|
-
const lines = content.split('\n').filter((line) => line.trim())
|
|
33
|
-
const entries: T[] = []
|
|
34
|
-
|
|
35
|
-
for (const line of lines) {
|
|
36
|
-
try {
|
|
37
|
-
entries.push(JSON.parse(line) as T)
|
|
38
|
-
} catch (_error) {
|
|
39
|
-
// Skip malformed lines silently (JSON parse error expected)
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
return entries
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
/**
|
|
47
|
-
* Convert array of objects to JSONL string
|
|
48
|
-
*/
|
|
49
|
-
export function stringifyJsonLines(objects: unknown[]): string {
|
|
50
|
-
return `${objects.map((obj) => JSON.stringify(obj)).join('\n')}\n`
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* Read and parse JSONL file
|
|
55
|
-
*/
|
|
56
|
-
export async function readJsonLines<T = Record<string, unknown>>(filePath: string): Promise<T[]> {
|
|
57
|
-
try {
|
|
58
|
-
const content = await fs.readFile(filePath, 'utf-8')
|
|
59
|
-
return parseJsonLines<T>(content)
|
|
60
|
-
} catch (error) {
|
|
61
|
-
if (isNotFoundError(error)) {
|
|
62
|
-
return [] // File doesn't exist, return empty array
|
|
63
|
-
}
|
|
64
|
-
throw error
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
* Write array of objects to JSONL file (overwrites)
|
|
70
|
-
*/
|
|
71
|
-
export async function writeJsonLines(filePath: string, objects: unknown[]): Promise<void> {
|
|
72
|
-
const content = stringifyJsonLines(objects)
|
|
73
|
-
await fs.writeFile(filePath, content, 'utf-8')
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
/**
|
|
77
|
-
* Append a single object to JSONL file
|
|
78
|
-
* Uses append mode for efficiency (no full file read/write)
|
|
79
|
-
*/
|
|
80
|
-
export async function appendJsonLine(filePath: string, object: unknown): Promise<void> {
|
|
81
|
-
const line = `${JSON.stringify(object)}\n`
|
|
82
|
-
await fs.appendFile(filePath, line, 'utf-8')
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
/**
|
|
86
|
-
* Append multiple objects to JSONL file
|
|
87
|
-
*/
|
|
88
|
-
export async function appendJsonLines(filePath: string, objects: unknown[]): Promise<void> {
|
|
89
|
-
const content = stringifyJsonLines(objects)
|
|
90
|
-
await fs.appendFile(filePath, content, 'utf-8')
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
/**
|
|
94
|
-
* Filter JSONL file entries by predicate
|
|
95
|
-
* Reads all entries, filters, returns matching ones
|
|
96
|
-
*/
|
|
97
|
-
export async function filterJsonLines<T = Record<string, unknown>>(
|
|
98
|
-
filePath: string,
|
|
99
|
-
predicate: (entry: T) => boolean
|
|
100
|
-
): Promise<T[]> {
|
|
101
|
-
const entries = await readJsonLines<T>(filePath)
|
|
102
|
-
return entries.filter(predicate)
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
/**
|
|
106
|
-
* Count lines in JSONL file (non-empty, parseable lines)
|
|
107
|
-
*/
|
|
108
|
-
export async function countJsonLines(filePath: string): Promise<number> {
|
|
109
|
-
try {
|
|
110
|
-
const content = await fs.readFile(filePath, 'utf-8')
|
|
111
|
-
const lines = content.split('\n').filter((line) => line.trim())
|
|
112
|
-
return lines.length
|
|
113
|
-
} catch (error) {
|
|
114
|
-
if (isNotFoundError(error)) {
|
|
115
|
-
return 0
|
|
116
|
-
}
|
|
117
|
-
throw error
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
/**
|
|
122
|
-
* Get last N entries from JSONL file
|
|
123
|
-
* Efficient for large files (reads whole file but only returns last N)
|
|
124
|
-
*/
|
|
125
|
-
export async function getLastJsonLines<T = Record<string, unknown>>(
|
|
126
|
-
filePath: string,
|
|
127
|
-
n: number
|
|
128
|
-
): Promise<T[]> {
|
|
129
|
-
const entries = await readJsonLines<T>(filePath)
|
|
130
|
-
return entries.slice(-n)
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
/**
|
|
134
|
-
* Get first N entries from JSONL file
|
|
135
|
-
*/
|
|
136
|
-
export async function getFirstJsonLines<T = Record<string, unknown>>(
|
|
137
|
-
filePath: string,
|
|
138
|
-
n: number
|
|
139
|
-
): Promise<T[]> {
|
|
140
|
-
const entries = await readJsonLines<T>(filePath)
|
|
141
|
-
return entries.slice(0, n)
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
/**
|
|
145
|
-
* Merge multiple JSONL files into one array
|
|
146
|
-
* Useful for reading multiple sessions
|
|
147
|
-
*/
|
|
148
|
-
export async function mergeJsonLines<T = Record<string, unknown>>(
|
|
149
|
-
filePaths: string[]
|
|
150
|
-
): Promise<T[]> {
|
|
151
|
-
const allEntries: T[] = []
|
|
152
|
-
|
|
153
|
-
for (const filePath of filePaths) {
|
|
154
|
-
const entries = await readJsonLines<T>(filePath)
|
|
155
|
-
allEntries.push(...entries)
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
return allEntries
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
/**
|
|
162
|
-
* Check if JSONL file is empty or doesn't exist
|
|
163
|
-
*/
|
|
164
|
-
export async function isJsonLinesEmpty(filePath: string): Promise<boolean> {
|
|
165
|
-
const count = await countJsonLines(filePath)
|
|
166
|
-
return count === 0
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
/**
|
|
170
|
-
* Read JSONL file with streaming (memory-efficient for large files)
|
|
171
|
-
* Only reads last N lines instead of loading entire file
|
|
172
|
-
*/
|
|
173
|
-
export async function readJsonLinesStreaming<T = Record<string, unknown>>(
|
|
174
|
-
filePath: string,
|
|
175
|
-
maxLines: number = STORAGE_LIMITS.JSONL_MAX_LINES
|
|
176
|
-
): Promise<T[]> {
|
|
177
|
-
try {
|
|
178
|
-
const fileStream = fsSync.createReadStream(filePath)
|
|
179
|
-
const rl = readline.createInterface({
|
|
180
|
-
input: fileStream,
|
|
181
|
-
crlfDelay: Infinity,
|
|
182
|
-
})
|
|
183
|
-
|
|
184
|
-
const lines: T[] = []
|
|
185
|
-
|
|
186
|
-
for await (const line of rl) {
|
|
187
|
-
if (line.trim()) {
|
|
188
|
-
try {
|
|
189
|
-
lines.push(JSON.parse(line) as T)
|
|
190
|
-
} catch (_error) {
|
|
191
|
-
// Skip malformed lines (JSON parse error expected)
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
// Keep only last maxLines
|
|
195
|
-
if (lines.length > maxLines) {
|
|
196
|
-
lines.shift()
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
return lines
|
|
202
|
-
} catch (error) {
|
|
203
|
-
if (isNotFoundError(error)) {
|
|
204
|
-
return []
|
|
205
|
-
}
|
|
206
|
-
throw error
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
/**
|
|
211
|
-
* Get file size in MB
|
|
212
|
-
*/
|
|
213
|
-
export async function getFileSizeMB(filePath: string): Promise<number> {
|
|
214
|
-
try {
|
|
215
|
-
const stats = await fs.stat(filePath)
|
|
216
|
-
return stats.size / (1024 * 1024)
|
|
217
|
-
} catch (error) {
|
|
218
|
-
if (isNotFoundError(error)) {
|
|
219
|
-
return 0
|
|
220
|
-
}
|
|
221
|
-
throw error
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
/**
|
|
226
|
-
* Rotate JSONL file if it exceeds size limit
|
|
227
|
-
* Moves large file to archive with timestamp
|
|
228
|
-
*/
|
|
229
|
-
export async function rotateJsonLinesIfNeeded(
|
|
230
|
-
filePath: string,
|
|
231
|
-
maxSizeMB: number = STORAGE_LIMITS.ROTATION_SIZE_MB
|
|
232
|
-
): Promise<boolean> {
|
|
233
|
-
const sizeMB = await getFileSizeMB(filePath)
|
|
234
|
-
|
|
235
|
-
if (sizeMB < maxSizeMB) {
|
|
236
|
-
return false // No rotation needed
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
// Generate archive filename with timestamp
|
|
240
|
-
const timestamp = new Date().toISOString().split('T')[0] // YYYY-MM-DD
|
|
241
|
-
const dir = path.dirname(filePath)
|
|
242
|
-
const ext = path.extname(filePath)
|
|
243
|
-
const base = path.basename(filePath, ext)
|
|
244
|
-
const archivePath = path.join(dir, `${base}-${timestamp}${ext}`)
|
|
245
|
-
|
|
246
|
-
// Move file to archive
|
|
247
|
-
await fs.rename(filePath, archivePath)
|
|
248
|
-
|
|
249
|
-
console.log(
|
|
250
|
-
`📦 Rotated ${path.basename(filePath)} (${sizeMB.toFixed(1)}MB) → ${path.basename(archivePath)}`
|
|
251
|
-
)
|
|
252
|
-
|
|
253
|
-
return true
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
/**
|
|
257
|
-
* Append JSON line with automatic rotation
|
|
258
|
-
* Checks file size before append and rotates if needed
|
|
259
|
-
*/
|
|
260
|
-
export async function appendJsonLineWithRotation(
|
|
261
|
-
filePath: string,
|
|
262
|
-
object: unknown,
|
|
263
|
-
maxSizeMB: number = STORAGE_LIMITS.ROTATION_SIZE_MB
|
|
264
|
-
): Promise<void> {
|
|
265
|
-
// Rotate if needed (before appending)
|
|
266
|
-
await rotateJsonLinesIfNeeded(filePath, maxSizeMB)
|
|
267
|
-
|
|
268
|
-
// Append normally
|
|
269
|
-
await appendJsonLine(filePath, object)
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
/**
|
|
273
|
-
* Warn if file is large before reading
|
|
274
|
-
* Returns size and whether it's considered large
|
|
275
|
-
*/
|
|
276
|
-
export async function checkFileSizeWarning(
|
|
277
|
-
filePath: string,
|
|
278
|
-
warnThresholdMB: number = STORAGE_LIMITS.LARGE_FILE_WARN_MB
|
|
279
|
-
): Promise<FileSizeWarning> {
|
|
280
|
-
const sizeMB = await getFileSizeMB(filePath)
|
|
281
|
-
const isLarge = sizeMB > warnThresholdMB
|
|
282
|
-
|
|
283
|
-
if (isLarge) {
|
|
284
|
-
console.warn(
|
|
285
|
-
`⚠️ Large file detected: ${path.basename(filePath)} (${sizeMB.toFixed(1)}MB). Reading may use significant memory.`
|
|
286
|
-
)
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
return { sizeMB, isLarge }
|
|
290
|
-
}
|