prjct-cli 1.22.0 → 1.24.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 +230 -0
- package/bin/prjct +30 -13
- package/dist/bin/prjct-core.mjs +1748 -0
- package/dist/bin/prjct.mjs +17 -36672
- package/dist/cli/linear.mjs +14 -0
- package/dist/daemon/entry.mjs +1429 -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/plugin/loader.ts
DELETED
|
@@ -1,354 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* PluginLoader - Dynamic Plugin Loading for prjct-cli
|
|
3
|
-
*
|
|
4
|
-
* Loads plugins from:
|
|
5
|
-
* 1. Built-in plugins (core/plugins/*)
|
|
6
|
-
* 2. Global plugins (~/.prjct-cli/plugins/*)
|
|
7
|
-
* 3. Project plugins (configured in prjct.config.json)
|
|
8
|
-
*
|
|
9
|
-
* @version 1.0.0
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
import fs from 'node:fs/promises'
|
|
13
|
-
import path from 'node:path'
|
|
14
|
-
import { type EventCallback, eventBus } from '../bus'
|
|
15
|
-
import pathManager from '../infrastructure/path-manager'
|
|
16
|
-
import { getErrorMessage, isNotFoundError } from '../types/fs'
|
|
17
|
-
import { hookSystem } from './hooks'
|
|
18
|
-
|
|
19
|
-
type PluginSource = 'builtin' | 'global' | 'project'
|
|
20
|
-
type HookHandler = (data: unknown) => unknown | Promise<unknown>
|
|
21
|
-
|
|
22
|
-
interface Plugin {
|
|
23
|
-
name: string
|
|
24
|
-
version?: string
|
|
25
|
-
description?: string
|
|
26
|
-
hooks?: Record<string, HookHandler>
|
|
27
|
-
events?: Record<string, EventCallback>
|
|
28
|
-
commands?: Record<string, { handler: () => void; description?: string }>
|
|
29
|
-
priority?: number
|
|
30
|
-
activate?: (context: PluginContext) => Promise<void>
|
|
31
|
-
deactivate?: () => Promise<void>
|
|
32
|
-
source?: PluginSource
|
|
33
|
-
config?: Record<string, unknown>
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
interface PluginContext {
|
|
37
|
-
config: Record<string, unknown>
|
|
38
|
-
eventBus: typeof eventBus
|
|
39
|
-
hookSystem: typeof hookSystem
|
|
40
|
-
projectPath: string
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
interface PluginSpec {
|
|
44
|
-
path: string
|
|
45
|
-
config?: Record<string, unknown>
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
interface CommandInfo {
|
|
49
|
-
handler: () => void
|
|
50
|
-
plugin: string
|
|
51
|
-
description: string
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
class PluginLoader {
|
|
55
|
-
private plugins: Map<string, Plugin>
|
|
56
|
-
private pluginPaths: Map<string, string>
|
|
57
|
-
private initialized: boolean
|
|
58
|
-
private projectPath: string
|
|
59
|
-
private config: Record<string, unknown>
|
|
60
|
-
|
|
61
|
-
constructor() {
|
|
62
|
-
this.plugins = new Map()
|
|
63
|
-
this.pluginPaths = new Map()
|
|
64
|
-
this.initialized = false
|
|
65
|
-
this.projectPath = ''
|
|
66
|
-
this.config = {}
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
/**
|
|
70
|
-
* Initialize plugin system
|
|
71
|
-
*/
|
|
72
|
-
async initialize(projectPath: string, config: Record<string, unknown> = {}): Promise<void> {
|
|
73
|
-
if (this.initialized) return
|
|
74
|
-
|
|
75
|
-
this.projectPath = projectPath
|
|
76
|
-
this.config = config
|
|
77
|
-
|
|
78
|
-
// Load plugins in order
|
|
79
|
-
await this.loadBuiltinPlugins()
|
|
80
|
-
await this.loadGlobalPlugins()
|
|
81
|
-
await this.loadProjectPlugins((config.plugins as Array<string | PluginSpec>) || [])
|
|
82
|
-
|
|
83
|
-
this.initialized = true
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
/**
|
|
87
|
-
* Load built-in plugins from core/plugin/builtin
|
|
88
|
-
*/
|
|
89
|
-
async loadBuiltinPlugins(): Promise<void> {
|
|
90
|
-
const builtinPath = path.join(__dirname, 'builtin')
|
|
91
|
-
|
|
92
|
-
try {
|
|
93
|
-
const files = await fs.readdir(builtinPath)
|
|
94
|
-
|
|
95
|
-
for (const file of files) {
|
|
96
|
-
if (file.endsWith('.js') || file.endsWith('.ts')) {
|
|
97
|
-
const pluginPath = path.join(builtinPath, file)
|
|
98
|
-
await this.loadPlugin(pluginPath, 'builtin')
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
} catch (error) {
|
|
102
|
-
// No built-in plugins directory yet - expected
|
|
103
|
-
if (!isNotFoundError(error)) {
|
|
104
|
-
throw error
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
/**
|
|
110
|
-
* Load global plugins from ~/.prjct-cli/plugins
|
|
111
|
-
*/
|
|
112
|
-
async loadGlobalPlugins(): Promise<void> {
|
|
113
|
-
const globalPath = path.join(pathManager.getGlobalBasePath(), 'plugins')
|
|
114
|
-
|
|
115
|
-
try {
|
|
116
|
-
const files = await fs.readdir(globalPath)
|
|
117
|
-
|
|
118
|
-
for (const file of files) {
|
|
119
|
-
const filePath = path.join(globalPath, file)
|
|
120
|
-
if (file.endsWith('.js') || file.endsWith('.ts') || (await this.isDirectory(filePath))) {
|
|
121
|
-
const pluginPath =
|
|
122
|
-
file.endsWith('.js') || file.endsWith('.ts')
|
|
123
|
-
? filePath
|
|
124
|
-
: path.join(filePath, 'index.js')
|
|
125
|
-
await this.loadPlugin(pluginPath, 'global')
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
} catch (error) {
|
|
129
|
-
// No global plugins directory - expected
|
|
130
|
-
if (!isNotFoundError(error)) {
|
|
131
|
-
throw error
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
/**
|
|
137
|
-
* Load project-specific plugins from config
|
|
138
|
-
*/
|
|
139
|
-
async loadProjectPlugins(plugins: Array<string | PluginSpec>): Promise<void> {
|
|
140
|
-
for (const spec of plugins) {
|
|
141
|
-
try {
|
|
142
|
-
if (typeof spec === 'string') {
|
|
143
|
-
// Simple name or path
|
|
144
|
-
if (spec.startsWith('file://')) {
|
|
145
|
-
// Local file path
|
|
146
|
-
const filePath = spec.replace('file://', '')
|
|
147
|
-
const fullPath = path.resolve(this.projectPath, filePath)
|
|
148
|
-
await this.loadPlugin(fullPath, 'project')
|
|
149
|
-
} else if (spec.startsWith('./') || spec.startsWith('../')) {
|
|
150
|
-
// Relative path
|
|
151
|
-
const fullPath = path.resolve(this.projectPath, spec)
|
|
152
|
-
await this.loadPlugin(fullPath, 'project')
|
|
153
|
-
} else {
|
|
154
|
-
// Plugin name - check if already loaded
|
|
155
|
-
if (!this.plugins.has(spec)) {
|
|
156
|
-
console.warn(`Plugin not found: ${spec}`)
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
} else if (typeof spec === 'object' && spec.path) {
|
|
160
|
-
// Object with path and config
|
|
161
|
-
const fullPath = path.resolve(this.projectPath, spec.path)
|
|
162
|
-
await this.loadPlugin(fullPath, 'project', spec.config)
|
|
163
|
-
}
|
|
164
|
-
} catch (error) {
|
|
165
|
-
console.error(`Failed to load plugin: ${spec}`, getErrorMessage(error))
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
/**
|
|
171
|
-
* Load a single plugin
|
|
172
|
-
*/
|
|
173
|
-
async loadPlugin(
|
|
174
|
-
pluginPath: string,
|
|
175
|
-
source: PluginSource,
|
|
176
|
-
config: Record<string, unknown> = {}
|
|
177
|
-
): Promise<void> {
|
|
178
|
-
try {
|
|
179
|
-
// Check if file exists
|
|
180
|
-
await fs.access(pluginPath)
|
|
181
|
-
|
|
182
|
-
// Import the plugin dynamically
|
|
183
|
-
const pluginModule = await import(pluginPath)
|
|
184
|
-
const plugin: Plugin = pluginModule.default || pluginModule
|
|
185
|
-
|
|
186
|
-
// Validate plugin structure
|
|
187
|
-
if (!plugin.name) {
|
|
188
|
-
throw new Error('Plugin must have a name property')
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
if (this.plugins.has(plugin.name)) {
|
|
192
|
-
console.warn(`Plugin already loaded: ${plugin.name}`)
|
|
193
|
-
return
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
// Store plugin
|
|
197
|
-
this.plugins.set(plugin.name, {
|
|
198
|
-
...plugin,
|
|
199
|
-
source,
|
|
200
|
-
config: { ...config, ...((this.config[plugin.name] as Record<string, unknown>) || {}) },
|
|
201
|
-
})
|
|
202
|
-
this.pluginPaths.set(plugin.name, pluginPath)
|
|
203
|
-
|
|
204
|
-
// Register hooks
|
|
205
|
-
if (plugin.hooks) {
|
|
206
|
-
this.registerPluginHooks(plugin)
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
// Register event listeners
|
|
210
|
-
if (plugin.events) {
|
|
211
|
-
this.registerPluginEvents(plugin)
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
// Call activate if exists
|
|
215
|
-
if (typeof plugin.activate === 'function') {
|
|
216
|
-
await plugin.activate({
|
|
217
|
-
config: this.plugins.get(plugin.name)!.config!,
|
|
218
|
-
eventBus,
|
|
219
|
-
hookSystem,
|
|
220
|
-
projectPath: this.projectPath,
|
|
221
|
-
})
|
|
222
|
-
}
|
|
223
|
-
} catch (error) {
|
|
224
|
-
const err = error as NodeJS.ErrnoException
|
|
225
|
-
if (err.code === 'ENOENT') {
|
|
226
|
-
// File not found - skip silently
|
|
227
|
-
} else if (err.code === 'MODULE_NOT_FOUND') {
|
|
228
|
-
console.error(`Plugin module not found: ${pluginPath}`)
|
|
229
|
-
} else {
|
|
230
|
-
console.error(`Failed to load plugin from ${pluginPath}:`, err.message)
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
/**
|
|
236
|
-
* Register plugin hooks
|
|
237
|
-
*/
|
|
238
|
-
registerPluginHooks(plugin: Plugin): void {
|
|
239
|
-
for (const [hookPoint, handler] of Object.entries(plugin.hooks || {})) {
|
|
240
|
-
hookSystem.register(hookPoint, handler, {
|
|
241
|
-
pluginName: plugin.name,
|
|
242
|
-
priority: plugin.priority || 10,
|
|
243
|
-
})
|
|
244
|
-
}
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
/**
|
|
248
|
-
* Register plugin event listeners
|
|
249
|
-
*/
|
|
250
|
-
registerPluginEvents(plugin: Plugin): void {
|
|
251
|
-
for (const [eventType, handler] of Object.entries(plugin.events || {})) {
|
|
252
|
-
eventBus.on(eventType, handler)
|
|
253
|
-
}
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
/**
|
|
257
|
-
* Unload a plugin
|
|
258
|
-
*/
|
|
259
|
-
async unloadPlugin(name: string): Promise<void> {
|
|
260
|
-
const plugin = this.plugins.get(name)
|
|
261
|
-
if (!plugin) return
|
|
262
|
-
|
|
263
|
-
// Call deactivate if exists
|
|
264
|
-
if (typeof plugin.deactivate === 'function') {
|
|
265
|
-
await plugin.deactivate()
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
// Unregister hooks
|
|
269
|
-
hookSystem.unregisterPlugin(name)
|
|
270
|
-
|
|
271
|
-
// Remove from loaded plugins
|
|
272
|
-
this.plugins.delete(name)
|
|
273
|
-
|
|
274
|
-
// Clear plugin path reference
|
|
275
|
-
this.pluginPaths.delete(name)
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
/**
|
|
279
|
-
* Reload a plugin
|
|
280
|
-
*/
|
|
281
|
-
async reloadPlugin(name: string): Promise<void> {
|
|
282
|
-
const pluginPath = this.pluginPaths.get(name)
|
|
283
|
-
const plugin = this.plugins.get(name)
|
|
284
|
-
|
|
285
|
-
if (!pluginPath || !plugin) {
|
|
286
|
-
throw new Error(`Plugin not found: ${name}`)
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
await this.unloadPlugin(name)
|
|
290
|
-
await this.loadPlugin(pluginPath, plugin.source!, plugin.config)
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
/**
|
|
294
|
-
* Get a loaded plugin
|
|
295
|
-
*/
|
|
296
|
-
getPlugin(name: string): Plugin | null {
|
|
297
|
-
return this.plugins.get(name) || null
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
/**
|
|
301
|
-
* Get all loaded plugins
|
|
302
|
-
*/
|
|
303
|
-
getAllPlugins(): Plugin[] {
|
|
304
|
-
return Array.from(this.plugins.values())
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
/**
|
|
308
|
-
* Get plugins by source
|
|
309
|
-
*/
|
|
310
|
-
getPluginsBySource(source: PluginSource): Plugin[] {
|
|
311
|
-
return this.getAllPlugins().filter((p) => p.source === source)
|
|
312
|
-
}
|
|
313
|
-
|
|
314
|
-
/**
|
|
315
|
-
* Get custom commands from all plugins
|
|
316
|
-
*/
|
|
317
|
-
getPluginCommands(): Record<string, CommandInfo> {
|
|
318
|
-
const commands: Record<string, CommandInfo> = {}
|
|
319
|
-
|
|
320
|
-
for (const plugin of this.plugins.values()) {
|
|
321
|
-
if (plugin.commands) {
|
|
322
|
-
for (const [name, handler] of Object.entries(plugin.commands)) {
|
|
323
|
-
commands[name] = {
|
|
324
|
-
handler: handler.handler,
|
|
325
|
-
plugin: plugin.name,
|
|
326
|
-
description: handler.description || `Command from ${plugin.name}`,
|
|
327
|
-
}
|
|
328
|
-
}
|
|
329
|
-
}
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
return commands
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
/**
|
|
336
|
-
* Check if path is a directory
|
|
337
|
-
*/
|
|
338
|
-
async isDirectory(p: string): Promise<boolean> {
|
|
339
|
-
try {
|
|
340
|
-
const stat = await fs.stat(p)
|
|
341
|
-
return stat.isDirectory()
|
|
342
|
-
} catch (error) {
|
|
343
|
-
if (isNotFoundError(error)) {
|
|
344
|
-
return false
|
|
345
|
-
}
|
|
346
|
-
throw error
|
|
347
|
-
}
|
|
348
|
-
}
|
|
349
|
-
}
|
|
350
|
-
|
|
351
|
-
// Singleton instance
|
|
352
|
-
const pluginLoader = new PluginLoader()
|
|
353
|
-
|
|
354
|
-
export { PluginLoader, pluginLoader, type Plugin }
|
package/core/plugin/registry.ts
DELETED
|
@@ -1,326 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* PluginRegistry - Plugin Discovery and Management
|
|
3
|
-
*
|
|
4
|
-
* Central registry for plugin information, discovery, and management.
|
|
5
|
-
*
|
|
6
|
-
* @version 1.0.0
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
import fs from 'node:fs/promises'
|
|
10
|
-
import path from 'node:path'
|
|
11
|
-
import pathManager from '../infrastructure/path-manager'
|
|
12
|
-
import { getErrorMessage, isNotFoundError } from '../types/fs'
|
|
13
|
-
import { pluginLoader } from './loader'
|
|
14
|
-
|
|
15
|
-
type PluginSource = 'builtin' | 'global' | 'project'
|
|
16
|
-
|
|
17
|
-
interface PluginMetadata {
|
|
18
|
-
name: string
|
|
19
|
-
version: string
|
|
20
|
-
description: string
|
|
21
|
-
path?: string
|
|
22
|
-
source?: PluginSource
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
interface PluginInfo extends PluginMetadata {
|
|
26
|
-
loaded: boolean
|
|
27
|
-
active: boolean
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
class PluginRegistry {
|
|
31
|
-
private availablePlugins: Map<string, PluginMetadata>
|
|
32
|
-
private initialized: boolean
|
|
33
|
-
|
|
34
|
-
constructor() {
|
|
35
|
-
this.availablePlugins = new Map()
|
|
36
|
-
this.initialized = false
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* Initialize registry and discover available plugins
|
|
41
|
-
*/
|
|
42
|
-
async initialize(): Promise<void> {
|
|
43
|
-
if (this.initialized) return
|
|
44
|
-
|
|
45
|
-
await this.discoverPlugins()
|
|
46
|
-
this.initialized = true
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* Discover all available plugins (not necessarily loaded)
|
|
51
|
-
*/
|
|
52
|
-
async discoverPlugins(): Promise<void> {
|
|
53
|
-
// Built-in plugins
|
|
54
|
-
await this.discoverFromPath(path.join(__dirname, '..', 'plugins'), 'builtin')
|
|
55
|
-
|
|
56
|
-
// Global plugins
|
|
57
|
-
await this.discoverFromPath(path.join(pathManager.getGlobalBasePath(), 'plugins'), 'global')
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
/**
|
|
61
|
-
* Discover plugins from a path
|
|
62
|
-
*/
|
|
63
|
-
async discoverFromPath(dir: string, source: PluginSource): Promise<void> {
|
|
64
|
-
try {
|
|
65
|
-
const entries = await fs.readdir(dir, { withFileTypes: true })
|
|
66
|
-
|
|
67
|
-
for (const entry of entries) {
|
|
68
|
-
try {
|
|
69
|
-
let pluginPath: string
|
|
70
|
-
|
|
71
|
-
if (entry.isFile() && (entry.name.endsWith('.js') || entry.name.endsWith('.ts'))) {
|
|
72
|
-
pluginPath = path.join(dir, entry.name)
|
|
73
|
-
} else if (entry.isDirectory()) {
|
|
74
|
-
pluginPath = path.join(dir, entry.name, 'index.js')
|
|
75
|
-
} else {
|
|
76
|
-
continue
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
// Check if file exists
|
|
80
|
-
await fs.access(pluginPath)
|
|
81
|
-
|
|
82
|
-
// Read plugin metadata without loading
|
|
83
|
-
const metadata = await this.readPluginMetadata(pluginPath)
|
|
84
|
-
if (metadata) {
|
|
85
|
-
this.availablePlugins.set(metadata.name, {
|
|
86
|
-
...metadata,
|
|
87
|
-
path: pluginPath,
|
|
88
|
-
source,
|
|
89
|
-
})
|
|
90
|
-
}
|
|
91
|
-
} catch (error) {
|
|
92
|
-
// Skip invalid plugins - ENOENT expected for missing files
|
|
93
|
-
if (!isNotFoundError(error)) {
|
|
94
|
-
console.error(`Plugin discovery error: ${getErrorMessage(error)}`)
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
} catch (error) {
|
|
99
|
-
// Directory doesn't exist - expected
|
|
100
|
-
if (!isNotFoundError(error)) {
|
|
101
|
-
throw error
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
/**
|
|
107
|
-
* Read plugin metadata without fully loading
|
|
108
|
-
*/
|
|
109
|
-
async readPluginMetadata(pluginPath: string): Promise<PluginMetadata | null> {
|
|
110
|
-
try {
|
|
111
|
-
const content = await fs.readFile(pluginPath, 'utf-8')
|
|
112
|
-
|
|
113
|
-
// Extract basic metadata from comments or exports
|
|
114
|
-
const nameMatch = content.match(/name:\s*['"]([^'"]+)['"]/)
|
|
115
|
-
const versionMatch = content.match(/version:\s*['"]([^'"]+)['"]/)
|
|
116
|
-
const descMatch = content.match(/description:\s*['"]([^'"]+)['"]/)
|
|
117
|
-
|
|
118
|
-
if (nameMatch) {
|
|
119
|
-
return {
|
|
120
|
-
name: nameMatch[1],
|
|
121
|
-
version: versionMatch ? versionMatch[1] : '1.0.0',
|
|
122
|
-
description: descMatch ? descMatch[1] : '',
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
// Fallback: try to import (might have side effects)
|
|
127
|
-
const pluginModule = await import(pluginPath)
|
|
128
|
-
const plugin = pluginModule.default || pluginModule
|
|
129
|
-
|
|
130
|
-
if (plugin.name) {
|
|
131
|
-
return {
|
|
132
|
-
name: plugin.name,
|
|
133
|
-
version: plugin.version || '1.0.0',
|
|
134
|
-
description: plugin.description || '',
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
} catch (error) {
|
|
138
|
-
// Can't read metadata - ENOENT or parse error expected
|
|
139
|
-
if (!isNotFoundError(error) && !(error instanceof SyntaxError)) {
|
|
140
|
-
console.error(`Plugin metadata read error: ${getErrorMessage(error)}`)
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
return null
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
/**
|
|
148
|
-
* Get all available plugins
|
|
149
|
-
*/
|
|
150
|
-
getAvailable(): PluginMetadata[] {
|
|
151
|
-
return Array.from(this.availablePlugins.values())
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
/**
|
|
155
|
-
* Get available plugins by source
|
|
156
|
-
*/
|
|
157
|
-
getAvailableBySource(source: PluginSource): PluginMetadata[] {
|
|
158
|
-
return this.getAvailable().filter((p) => p.source === source)
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
/**
|
|
162
|
-
* Check if a plugin is available
|
|
163
|
-
*/
|
|
164
|
-
isAvailable(name: string): boolean {
|
|
165
|
-
return this.availablePlugins.has(name)
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
/**
|
|
169
|
-
* Check if a plugin is loaded
|
|
170
|
-
*/
|
|
171
|
-
isLoaded(name: string): boolean {
|
|
172
|
-
return pluginLoader.getPlugin(name) !== null
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
/**
|
|
176
|
-
* Get plugin info
|
|
177
|
-
*/
|
|
178
|
-
getPluginInfo(name: string): PluginInfo | null {
|
|
179
|
-
const available = this.availablePlugins.get(name)
|
|
180
|
-
const loaded = pluginLoader.getPlugin(name)
|
|
181
|
-
|
|
182
|
-
if (!available && !loaded) return null
|
|
183
|
-
|
|
184
|
-
return {
|
|
185
|
-
...(available || { name, version: '1.0.0', description: '' }),
|
|
186
|
-
loaded: !!loaded,
|
|
187
|
-
active: !!loaded,
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
/**
|
|
192
|
-
* Install a plugin (copy to global plugins)
|
|
193
|
-
*/
|
|
194
|
-
async install(sourcePath: string, name: string | null = null): Promise<void> {
|
|
195
|
-
const globalPluginsPath = path.join(pathManager.getGlobalBasePath(), 'plugins')
|
|
196
|
-
await fs.mkdir(globalPluginsPath, { recursive: true })
|
|
197
|
-
|
|
198
|
-
const stat = await fs.stat(sourcePath)
|
|
199
|
-
|
|
200
|
-
if (stat.isFile()) {
|
|
201
|
-
// Single file plugin
|
|
202
|
-
const pluginName = name || path.basename(sourcePath)
|
|
203
|
-
const destPath = path.join(globalPluginsPath, pluginName)
|
|
204
|
-
await fs.copyFile(sourcePath, destPath)
|
|
205
|
-
} else if (stat.isDirectory()) {
|
|
206
|
-
// Directory plugin
|
|
207
|
-
const pluginName = name || path.basename(sourcePath)
|
|
208
|
-
const destPath = path.join(globalPluginsPath, pluginName)
|
|
209
|
-
await this.copyDirectory(sourcePath, destPath)
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
// Refresh available plugins
|
|
213
|
-
await this.discoverPlugins()
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
/**
|
|
217
|
-
* Uninstall a plugin
|
|
218
|
-
*/
|
|
219
|
-
async uninstall(name: string): Promise<void> {
|
|
220
|
-
const plugin = this.availablePlugins.get(name)
|
|
221
|
-
|
|
222
|
-
if (!plugin) {
|
|
223
|
-
throw new Error(`Plugin not found: ${name}`)
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
if (plugin.source === 'builtin') {
|
|
227
|
-
throw new Error('Cannot uninstall built-in plugins')
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
// Unload if loaded
|
|
231
|
-
if (this.isLoaded(name)) {
|
|
232
|
-
await pluginLoader.unloadPlugin(name)
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
// Delete plugin file/directory
|
|
236
|
-
const pluginPath = plugin.path!
|
|
237
|
-
|
|
238
|
-
if (path.basename(pluginPath) === 'index.js') {
|
|
239
|
-
// Directory plugin
|
|
240
|
-
await fs.rm(path.dirname(pluginPath), { recursive: true })
|
|
241
|
-
} else {
|
|
242
|
-
// Single file plugin
|
|
243
|
-
await fs.unlink(pluginPath)
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
// Remove from registry
|
|
247
|
-
this.availablePlugins.delete(name)
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
/**
|
|
251
|
-
* Copy directory recursively
|
|
252
|
-
*/
|
|
253
|
-
async copyDirectory(src: string, dest: string): Promise<void> {
|
|
254
|
-
await fs.mkdir(dest, { recursive: true })
|
|
255
|
-
const entries = await fs.readdir(src, { withFileTypes: true })
|
|
256
|
-
|
|
257
|
-
for (const entry of entries) {
|
|
258
|
-
const srcPath = path.join(src, entry.name)
|
|
259
|
-
const destPath = path.join(dest, entry.name)
|
|
260
|
-
|
|
261
|
-
if (entry.isDirectory()) {
|
|
262
|
-
await this.copyDirectory(srcPath, destPath)
|
|
263
|
-
} else {
|
|
264
|
-
await fs.copyFile(srcPath, destPath)
|
|
265
|
-
}
|
|
266
|
-
}
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
/**
|
|
270
|
-
* Generate plugin list for display
|
|
271
|
-
*/
|
|
272
|
-
generatePluginList(): string {
|
|
273
|
-
const available = this.getAvailable()
|
|
274
|
-
|
|
275
|
-
if (available.length === 0) {
|
|
276
|
-
return 'No plugins installed.'
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
let output = '## Installed Plugins\n\n'
|
|
280
|
-
|
|
281
|
-
const bySource: Record<PluginSource, PluginMetadata[]> = {
|
|
282
|
-
builtin: [],
|
|
283
|
-
global: [],
|
|
284
|
-
project: [],
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
for (const plugin of available) {
|
|
288
|
-
if (plugin.source) {
|
|
289
|
-
bySource[plugin.source].push(plugin)
|
|
290
|
-
}
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
if (bySource.builtin.length > 0) {
|
|
294
|
-
output += '### Built-in\n'
|
|
295
|
-
for (const p of bySource.builtin) {
|
|
296
|
-
const status = this.isLoaded(p.name) ? '●' : '○'
|
|
297
|
-
output += `- ${status} **${p.name}** v${p.version}\n`
|
|
298
|
-
if (p.description) {
|
|
299
|
-
output += ` ${p.description}\n`
|
|
300
|
-
}
|
|
301
|
-
}
|
|
302
|
-
output += '\n'
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
if (bySource.global.length > 0) {
|
|
306
|
-
output += '### Global\n'
|
|
307
|
-
for (const p of bySource.global) {
|
|
308
|
-
const status = this.isLoaded(p.name) ? '●' : '○'
|
|
309
|
-
output += `- ${status} **${p.name}** v${p.version}\n`
|
|
310
|
-
if (p.description) {
|
|
311
|
-
output += ` ${p.description}\n`
|
|
312
|
-
}
|
|
313
|
-
}
|
|
314
|
-
output += '\n'
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
output += '\n● = loaded, ○ = available'
|
|
318
|
-
|
|
319
|
-
return output
|
|
320
|
-
}
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
// Singleton instance
|
|
324
|
-
const pluginRegistry = new PluginRegistry()
|
|
325
|
-
|
|
326
|
-
export { PluginRegistry, pluginRegistry, type PluginMetadata, type PluginInfo }
|
package/core/schemas/agents.ts
DELETED
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Agents Schema
|
|
3
|
-
*
|
|
4
|
-
* Defines the structure for agents.json - specialized AI agents.
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
export interface AgentSchema {
|
|
8
|
-
name: string
|
|
9
|
-
description: string
|
|
10
|
-
skills: string[]
|
|
11
|
-
patterns: string[]
|
|
12
|
-
filesOwned: string[]
|
|
13
|
-
successRate?: number
|
|
14
|
-
tasksCompleted?: number
|
|
15
|
-
bestFor: string[]
|
|
16
|
-
avoidFor: string[]
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export type AgentsSchema = AgentSchema[]
|
|
20
|
-
|
|
21
|
-
export const DEFAULT_AGENT: Omit<AgentSchema, 'name' | 'description'> = {
|
|
22
|
-
skills: [],
|
|
23
|
-
patterns: [],
|
|
24
|
-
filesOwned: [],
|
|
25
|
-
bestFor: [],
|
|
26
|
-
avoidFor: [],
|
|
27
|
-
}
|