universal-agent-protocol 0.5.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/LICENSE +21 -0
- package/README.md +462 -0
- package/dist/analyzers/index.d.ts +3 -0
- package/dist/analyzers/index.d.ts.map +1 -0
- package/dist/analyzers/index.js +656 -0
- package/dist/analyzers/index.js.map +1 -0
- package/dist/bin/cli.d.ts +3 -0
- package/dist/bin/cli.d.ts.map +1 -0
- package/dist/bin/cli.js +506 -0
- package/dist/bin/cli.js.map +1 -0
- package/dist/bin/tool-calls.d.ts +3 -0
- package/dist/bin/tool-calls.d.ts.map +1 -0
- package/dist/bin/tool-calls.js +4 -0
- package/dist/bin/tool-calls.js.map +1 -0
- package/dist/cli/agent.d.ts +20 -0
- package/dist/cli/agent.d.ts.map +1 -0
- package/dist/cli/agent.js +434 -0
- package/dist/cli/agent.js.map +1 -0
- package/dist/cli/analyze.d.ts +7 -0
- package/dist/cli/analyze.d.ts.map +1 -0
- package/dist/cli/analyze.js +103 -0
- package/dist/cli/analyze.js.map +1 -0
- package/dist/cli/coord.d.ts +7 -0
- package/dist/cli/coord.d.ts.map +1 -0
- package/dist/cli/coord.js +138 -0
- package/dist/cli/coord.js.map +1 -0
- package/dist/cli/dashboard.d.ts +8 -0
- package/dist/cli/dashboard.d.ts.map +1 -0
- package/dist/cli/dashboard.js +704 -0
- package/dist/cli/dashboard.js.map +1 -0
- package/dist/cli/deploy.d.ts +19 -0
- package/dist/cli/deploy.d.ts.map +1 -0
- package/dist/cli/deploy.js +267 -0
- package/dist/cli/deploy.js.map +1 -0
- package/dist/cli/droids.d.ts +9 -0
- package/dist/cli/droids.d.ts.map +1 -0
- package/dist/cli/droids.js +227 -0
- package/dist/cli/droids.js.map +1 -0
- package/dist/cli/generate.d.ts +17 -0
- package/dist/cli/generate.d.ts.map +1 -0
- package/dist/cli/generate.js +432 -0
- package/dist/cli/generate.js.map +1 -0
- package/dist/cli/hooks.d.ts +9 -0
- package/dist/cli/hooks.d.ts.map +1 -0
- package/dist/cli/hooks.js +374 -0
- package/dist/cli/hooks.js.map +1 -0
- package/dist/cli/init.d.ts +11 -0
- package/dist/cli/init.d.ts.map +1 -0
- package/dist/cli/init.js +316 -0
- package/dist/cli/init.js.map +1 -0
- package/dist/cli/mcp-router.d.ts +16 -0
- package/dist/cli/mcp-router.d.ts.map +1 -0
- package/dist/cli/mcp-router.js +143 -0
- package/dist/cli/mcp-router.js.map +1 -0
- package/dist/cli/memory.d.ts +24 -0
- package/dist/cli/memory.d.ts.map +1 -0
- package/dist/cli/memory.js +877 -0
- package/dist/cli/memory.js.map +1 -0
- package/dist/cli/model.d.ts +15 -0
- package/dist/cli/model.d.ts.map +1 -0
- package/dist/cli/model.js +270 -0
- package/dist/cli/model.js.map +1 -0
- package/dist/cli/patterns.d.ts +26 -0
- package/dist/cli/patterns.d.ts.map +1 -0
- package/dist/cli/patterns.js +587 -0
- package/dist/cli/patterns.js.map +1 -0
- package/dist/cli/setup-mcp-router.d.ts +8 -0
- package/dist/cli/setup-mcp-router.d.ts.map +1 -0
- package/dist/cli/setup-mcp-router.js +163 -0
- package/dist/cli/setup-mcp-router.js.map +1 -0
- package/dist/cli/setup.d.ts +13 -0
- package/dist/cli/setup.d.ts.map +1 -0
- package/dist/cli/setup.js +146 -0
- package/dist/cli/setup.js.map +1 -0
- package/dist/cli/sync.d.ts +7 -0
- package/dist/cli/sync.d.ts.map +1 -0
- package/dist/cli/sync.js +26 -0
- package/dist/cli/sync.js.map +1 -0
- package/dist/cli/task.d.ts +33 -0
- package/dist/cli/task.d.ts.map +1 -0
- package/dist/cli/task.js +616 -0
- package/dist/cli/task.js.map +1 -0
- package/dist/cli/tool-calls.d.ts +8 -0
- package/dist/cli/tool-calls.d.ts.map +1 -0
- package/dist/cli/tool-calls.js +239 -0
- package/dist/cli/tool-calls.js.map +1 -0
- package/dist/cli/update.d.ts +10 -0
- package/dist/cli/update.d.ts.map +1 -0
- package/dist/cli/update.js +300 -0
- package/dist/cli/update.js.map +1 -0
- package/dist/cli/visualize.d.ts +77 -0
- package/dist/cli/visualize.d.ts.map +1 -0
- package/dist/cli/visualize.js +287 -0
- package/dist/cli/visualize.js.map +1 -0
- package/dist/cli/worktree.d.ts +9 -0
- package/dist/cli/worktree.d.ts.map +1 -0
- package/dist/cli/worktree.js +175 -0
- package/dist/cli/worktree.js.map +1 -0
- package/dist/coordination/capability-router.d.ts +79 -0
- package/dist/coordination/capability-router.d.ts.map +1 -0
- package/dist/coordination/capability-router.js +324 -0
- package/dist/coordination/capability-router.js.map +1 -0
- package/dist/coordination/database.d.ts +13 -0
- package/dist/coordination/database.d.ts.map +1 -0
- package/dist/coordination/database.js +131 -0
- package/dist/coordination/database.js.map +1 -0
- package/dist/coordination/deploy-batcher.d.ts +101 -0
- package/dist/coordination/deploy-batcher.d.ts.map +1 -0
- package/dist/coordination/deploy-batcher.js +565 -0
- package/dist/coordination/deploy-batcher.js.map +1 -0
- package/dist/coordination/index.d.ts +5 -0
- package/dist/coordination/index.d.ts.map +1 -0
- package/dist/coordination/index.js +5 -0
- package/dist/coordination/index.js.map +1 -0
- package/dist/coordination/service.d.ts +81 -0
- package/dist/coordination/service.d.ts.map +1 -0
- package/dist/coordination/service.js +603 -0
- package/dist/coordination/service.js.map +1 -0
- package/dist/generators/claude-md.d.ts +3 -0
- package/dist/generators/claude-md.d.ts.map +1 -0
- package/dist/generators/claude-md.js +977 -0
- package/dist/generators/claude-md.js.map +1 -0
- package/dist/generators/template-loader.d.ts +105 -0
- package/dist/generators/template-loader.d.ts.map +1 -0
- package/dist/generators/template-loader.js +291 -0
- package/dist/generators/template-loader.js.map +1 -0
- package/dist/index.d.ts +47 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +59 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp-router/config/parser.d.ts +9 -0
- package/dist/mcp-router/config/parser.d.ts.map +1 -0
- package/dist/mcp-router/config/parser.js +174 -0
- package/dist/mcp-router/config/parser.js.map +1 -0
- package/dist/mcp-router/executor/client.d.ts +31 -0
- package/dist/mcp-router/executor/client.d.ts.map +1 -0
- package/dist/mcp-router/executor/client.js +187 -0
- package/dist/mcp-router/executor/client.js.map +1 -0
- package/dist/mcp-router/index.d.ts +22 -0
- package/dist/mcp-router/index.d.ts.map +1 -0
- package/dist/mcp-router/index.js +18 -0
- package/dist/mcp-router/index.js.map +1 -0
- package/dist/mcp-router/output-compressor.d.ts +26 -0
- package/dist/mcp-router/output-compressor.d.ts.map +1 -0
- package/dist/mcp-router/output-compressor.js +236 -0
- package/dist/mcp-router/output-compressor.js.map +1 -0
- package/dist/mcp-router/search/fuzzy.d.ts +26 -0
- package/dist/mcp-router/search/fuzzy.d.ts.map +1 -0
- package/dist/mcp-router/search/fuzzy.js +94 -0
- package/dist/mcp-router/search/fuzzy.js.map +1 -0
- package/dist/mcp-router/server.d.ts +50 -0
- package/dist/mcp-router/server.d.ts.map +1 -0
- package/dist/mcp-router/server.js +229 -0
- package/dist/mcp-router/server.js.map +1 -0
- package/dist/mcp-router/session-stats.d.ts +37 -0
- package/dist/mcp-router/session-stats.d.ts.map +1 -0
- package/dist/mcp-router/session-stats.js +56 -0
- package/dist/mcp-router/session-stats.js.map +1 -0
- package/dist/mcp-router/tools/discover.d.ts +37 -0
- package/dist/mcp-router/tools/discover.d.ts.map +1 -0
- package/dist/mcp-router/tools/discover.js +65 -0
- package/dist/mcp-router/tools/discover.js.map +1 -0
- package/dist/mcp-router/tools/execute.d.ts +43 -0
- package/dist/mcp-router/tools/execute.d.ts.map +1 -0
- package/dist/mcp-router/tools/execute.js +103 -0
- package/dist/mcp-router/tools/execute.js.map +1 -0
- package/dist/mcp-router/types.d.ts +62 -0
- package/dist/mcp-router/types.d.ts.map +1 -0
- package/dist/mcp-router/types.js +6 -0
- package/dist/mcp-router/types.js.map +1 -0
- package/dist/memory/adaptive-context.d.ts +146 -0
- package/dist/memory/adaptive-context.d.ts.map +1 -0
- package/dist/memory/adaptive-context.js +1022 -0
- package/dist/memory/adaptive-context.js.map +1 -0
- package/dist/memory/agent-scoped-memory.d.ts +67 -0
- package/dist/memory/agent-scoped-memory.d.ts.map +1 -0
- package/dist/memory/agent-scoped-memory.js +126 -0
- package/dist/memory/agent-scoped-memory.js.map +1 -0
- package/dist/memory/backends/base.d.ts +18 -0
- package/dist/memory/backends/base.d.ts.map +1 -0
- package/dist/memory/backends/base.js +2 -0
- package/dist/memory/backends/base.js.map +1 -0
- package/dist/memory/backends/factory.d.ts +4 -0
- package/dist/memory/backends/factory.d.ts.map +1 -0
- package/dist/memory/backends/factory.js +53 -0
- package/dist/memory/backends/factory.js.map +1 -0
- package/dist/memory/backends/github.d.ts +22 -0
- package/dist/memory/backends/github.d.ts.map +1 -0
- package/dist/memory/backends/github.js +118 -0
- package/dist/memory/backends/github.js.map +1 -0
- package/dist/memory/backends/qdrant-cloud.d.ts +32 -0
- package/dist/memory/backends/qdrant-cloud.d.ts.map +1 -0
- package/dist/memory/backends/qdrant-cloud.js +168 -0
- package/dist/memory/backends/qdrant-cloud.js.map +1 -0
- package/dist/memory/context-compressor.d.ts +74 -0
- package/dist/memory/context-compressor.d.ts.map +1 -0
- package/dist/memory/context-compressor.js +289 -0
- package/dist/memory/context-compressor.js.map +1 -0
- package/dist/memory/correction-propagator.d.ts +44 -0
- package/dist/memory/correction-propagator.d.ts.map +1 -0
- package/dist/memory/correction-propagator.js +156 -0
- package/dist/memory/correction-propagator.js.map +1 -0
- package/dist/memory/daily-log.d.ts +67 -0
- package/dist/memory/daily-log.d.ts.map +1 -0
- package/dist/memory/daily-log.js +143 -0
- package/dist/memory/daily-log.js.map +1 -0
- package/dist/memory/dynamic-retrieval.d.ts +110 -0
- package/dist/memory/dynamic-retrieval.d.ts.map +1 -0
- package/dist/memory/dynamic-retrieval.js +688 -0
- package/dist/memory/dynamic-retrieval.js.map +1 -0
- package/dist/memory/embeddings.d.ts +116 -0
- package/dist/memory/embeddings.d.ts.map +1 -0
- package/dist/memory/embeddings.js +461 -0
- package/dist/memory/embeddings.js.map +1 -0
- package/dist/memory/hierarchical-memory.d.ts +141 -0
- package/dist/memory/hierarchical-memory.d.ts.map +1 -0
- package/dist/memory/hierarchical-memory.js +477 -0
- package/dist/memory/hierarchical-memory.js.map +1 -0
- package/dist/memory/memory-consolidator.d.ts +124 -0
- package/dist/memory/memory-consolidator.d.ts.map +1 -0
- package/dist/memory/memory-consolidator.js +514 -0
- package/dist/memory/memory-consolidator.js.map +1 -0
- package/dist/memory/memory-maintenance.d.ts +39 -0
- package/dist/memory/memory-maintenance.d.ts.map +1 -0
- package/dist/memory/memory-maintenance.js +305 -0
- package/dist/memory/memory-maintenance.js.map +1 -0
- package/dist/memory/model-router.d.ts +102 -0
- package/dist/memory/model-router.d.ts.map +1 -0
- package/dist/memory/model-router.js +448 -0
- package/dist/memory/model-router.js.map +1 -0
- package/dist/memory/multi-view-memory.d.ts +134 -0
- package/dist/memory/multi-view-memory.d.ts.map +1 -0
- package/dist/memory/multi-view-memory.js +420 -0
- package/dist/memory/multi-view-memory.js.map +1 -0
- package/dist/memory/prepopulate.d.ts +76 -0
- package/dist/memory/prepopulate.d.ts.map +1 -0
- package/dist/memory/prepopulate.js +815 -0
- package/dist/memory/prepopulate.js.map +1 -0
- package/dist/memory/semantic-compression.d.ts +77 -0
- package/dist/memory/semantic-compression.d.ts.map +1 -0
- package/dist/memory/semantic-compression.js +348 -0
- package/dist/memory/semantic-compression.js.map +1 -0
- package/dist/memory/serverless-qdrant.d.ts +102 -0
- package/dist/memory/serverless-qdrant.d.ts.map +1 -0
- package/dist/memory/serverless-qdrant.js +369 -0
- package/dist/memory/serverless-qdrant.js.map +1 -0
- package/dist/memory/short-term/factory.d.ts +26 -0
- package/dist/memory/short-term/factory.d.ts.map +1 -0
- package/dist/memory/short-term/factory.js +28 -0
- package/dist/memory/short-term/factory.js.map +1 -0
- package/dist/memory/short-term/indexeddb.d.ts +25 -0
- package/dist/memory/short-term/indexeddb.d.ts.map +1 -0
- package/dist/memory/short-term/indexeddb.js +64 -0
- package/dist/memory/short-term/indexeddb.js.map +1 -0
- package/dist/memory/short-term/schema.d.ts +6 -0
- package/dist/memory/short-term/schema.d.ts.map +1 -0
- package/dist/memory/short-term/schema.js +119 -0
- package/dist/memory/short-term/schema.js.map +1 -0
- package/dist/memory/short-term/sqlite.d.ts +50 -0
- package/dist/memory/short-term/sqlite.d.ts.map +1 -0
- package/dist/memory/short-term/sqlite.js +221 -0
- package/dist/memory/short-term/sqlite.js.map +1 -0
- package/dist/memory/speculative-cache.d.ts +111 -0
- package/dist/memory/speculative-cache.d.ts.map +1 -0
- package/dist/memory/speculative-cache.js +409 -0
- package/dist/memory/speculative-cache.js.map +1 -0
- package/dist/memory/task-classifier.d.ts +34 -0
- package/dist/memory/task-classifier.d.ts.map +1 -0
- package/dist/memory/task-classifier.js +300 -0
- package/dist/memory/task-classifier.js.map +1 -0
- package/dist/memory/terminal-bench-knowledge.d.ts +48 -0
- package/dist/memory/terminal-bench-knowledge.d.ts.map +1 -0
- package/dist/memory/terminal-bench-knowledge.js +399 -0
- package/dist/memory/terminal-bench-knowledge.js.map +1 -0
- package/dist/memory/write-gate.d.ts +39 -0
- package/dist/memory/write-gate.d.ts.map +1 -0
- package/dist/memory/write-gate.js +190 -0
- package/dist/memory/write-gate.js.map +1 -0
- package/dist/models/executor.d.ts +130 -0
- package/dist/models/executor.d.ts.map +1 -0
- package/dist/models/executor.js +383 -0
- package/dist/models/executor.js.map +1 -0
- package/dist/models/index.d.ts +15 -0
- package/dist/models/index.d.ts.map +1 -0
- package/dist/models/index.js +17 -0
- package/dist/models/index.js.map +1 -0
- package/dist/models/planner.d.ts +71 -0
- package/dist/models/planner.d.ts.map +1 -0
- package/dist/models/planner.js +344 -0
- package/dist/models/planner.js.map +1 -0
- package/dist/models/router.d.ts +75 -0
- package/dist/models/router.d.ts.map +1 -0
- package/dist/models/router.js +344 -0
- package/dist/models/router.js.map +1 -0
- package/dist/models/types.d.ts +370 -0
- package/dist/models/types.d.ts.map +1 -0
- package/dist/models/types.js +181 -0
- package/dist/models/types.js.map +1 -0
- package/dist/tasks/coordination.d.ts +74 -0
- package/dist/tasks/coordination.d.ts.map +1 -0
- package/dist/tasks/coordination.js +237 -0
- package/dist/tasks/coordination.js.map +1 -0
- package/dist/tasks/database.d.ts +14 -0
- package/dist/tasks/database.d.ts.map +1 -0
- package/dist/tasks/database.js +128 -0
- package/dist/tasks/database.js.map +1 -0
- package/dist/tasks/index.d.ts +5 -0
- package/dist/tasks/index.d.ts.map +1 -0
- package/dist/tasks/index.js +5 -0
- package/dist/tasks/index.js.map +1 -0
- package/dist/tasks/service.d.ts +39 -0
- package/dist/tasks/service.d.ts.map +1 -0
- package/dist/tasks/service.js +582 -0
- package/dist/tasks/service.js.map +1 -0
- package/dist/tasks/types.d.ts +224 -0
- package/dist/tasks/types.d.ts.map +1 -0
- package/dist/tasks/types.js +64 -0
- package/dist/tasks/types.js.map +1 -0
- package/dist/types/analysis.d.ts +82 -0
- package/dist/types/analysis.d.ts.map +1 -0
- package/dist/types/analysis.js +2 -0
- package/dist/types/analysis.js.map +1 -0
- package/dist/types/config.d.ts +3023 -0
- package/dist/types/config.d.ts.map +1 -0
- package/dist/types/config.js +292 -0
- package/dist/types/config.js.map +1 -0
- package/dist/types/coordination.d.ts +240 -0
- package/dist/types/coordination.d.ts.map +1 -0
- package/dist/types/coordination.js +43 -0
- package/dist/types/coordination.js.map +1 -0
- package/dist/types/index.d.ts +4 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +4 -0
- package/dist/types/index.js.map +1 -0
- package/dist/utils/calculate-average.d.ts +15 -0
- package/dist/utils/calculate-average.d.ts.map +1 -0
- package/dist/utils/calculate-average.js +21 -0
- package/dist/utils/calculate-average.js.map +1 -0
- package/dist/utils/config-manager.d.ts +30 -0
- package/dist/utils/config-manager.d.ts.map +1 -0
- package/dist/utils/config-manager.js +41 -0
- package/dist/utils/config-manager.js.map +1 -0
- package/dist/utils/dijkstra.d.ts +17 -0
- package/dist/utils/dijkstra.d.ts.map +1 -0
- package/dist/utils/dijkstra.js +91 -0
- package/dist/utils/dijkstra.js.map +1 -0
- package/dist/utils/fetch-with-retry.d.ts +5 -0
- package/dist/utils/fetch-with-retry.d.ts.map +1 -0
- package/dist/utils/fetch-with-retry.js +61 -0
- package/dist/utils/fetch-with-retry.js.map +1 -0
- package/dist/utils/merge-claude-md.d.ts +28 -0
- package/dist/utils/merge-claude-md.d.ts.map +1 -0
- package/dist/utils/merge-claude-md.js +342 -0
- package/dist/utils/merge-claude-md.js.map +1 -0
- package/dist/utils/order-processor-refactored.d.ts +126 -0
- package/dist/utils/order-processor-refactored.d.ts.map +1 -0
- package/dist/utils/order-processor-refactored.js +165 -0
- package/dist/utils/order-processor-refactored.js.map +1 -0
- package/dist/utils/order-processor-strategy.d.ts +72 -0
- package/dist/utils/order-processor-strategy.d.ts.map +1 -0
- package/dist/utils/order-processor-strategy.js +158 -0
- package/dist/utils/order-processor-strategy.js.map +1 -0
- package/dist/utils/order-processor.d.ts +242 -0
- package/dist/utils/order-processor.d.ts.map +1 -0
- package/dist/utils/order-processor.js +370 -0
- package/dist/utils/order-processor.js.map +1 -0
- package/dist/utils/rate-limiter-simple.d.ts +58 -0
- package/dist/utils/rate-limiter-simple.d.ts.map +1 -0
- package/dist/utils/rate-limiter-simple.js +100 -0
- package/dist/utils/rate-limiter-simple.js.map +1 -0
- package/dist/utils/rate-limiter.d.ts +62 -0
- package/dist/utils/rate-limiter.d.ts.map +1 -0
- package/dist/utils/rate-limiter.js +150 -0
- package/dist/utils/rate-limiter.js.map +1 -0
- package/dist/utils/string-similarity.d.ts +37 -0
- package/dist/utils/string-similarity.d.ts.map +1 -0
- package/dist/utils/string-similarity.js +114 -0
- package/dist/utils/string-similarity.js.map +1 -0
- package/dist/utils/validate-json.d.ts +51 -0
- package/dist/utils/validate-json.d.ts.map +1 -0
- package/dist/utils/validate-json.js +99 -0
- package/dist/utils/validate-json.js.map +1 -0
- package/package.json +96 -0
- package/templates/CLAUDE.template.md +11 -0
- package/templates/CLAUDE_ARCHITECTURE.template.md +103 -0
- package/templates/CLAUDE_CODING.template.md +125 -0
- package/templates/CLAUDE_DROIDS.template.md +109 -0
- package/templates/CLAUDE_MEMORY.template.md +130 -0
- package/templates/CLAUDE_WORKFLOWS.template.md +136 -0
- package/templates/PROJECT.template.md +209 -0
- package/templates/SCHEMA.md +57 -0
- package/templates/archive/CLAUDE.template.root-v6.md +762 -0
- package/templates/archive/CLAUDE.template.v6.md +762 -0
- package/templates/hooks/pre-compact.sh +68 -0
- package/templates/hooks/session-start.sh +106 -0
- package/tools/agents/README.md +224 -0
- package/tools/agents/UAP/README.md +351 -0
- package/tools/agents/UAP/__init__.py +9 -0
- package/tools/agents/UAP/cli.py +675 -0
- package/tools/agents/UAP/version.py +2 -0
- package/tools/agents/benchmarks/benchmark_memory_systems.py +637 -0
- package/tools/agents/benchmarks/results/benchmark_20260106_064817.json +170 -0
- package/tools/agents/benchmarks/results/benchmark_20260106_064817.md +51 -0
- package/tools/agents/config/chat_template.jinja +172 -0
- package/tools/agents/docker-compose.qdrant.yml +24 -0
- package/tools/agents/migrations/apply.py +256 -0
- package/tools/agents/scripts/fix_qwen_chat_template.py +314 -0
- package/tools/agents/scripts/init_qdrant.py +151 -0
- package/tools/agents/scripts/memory_migration.py +518 -0
- package/tools/agents/scripts/migrate_memory_to_qdrant.py +113 -0
- package/tools/agents/scripts/query_memory.py +189 -0
- package/tools/agents/scripts/qwen_tool_call_test.py +419 -0
- package/tools/agents/scripts/qwen_tool_call_wrapper.py +517 -0
- package/tools/agents/scripts/start-services.sh +96 -0
- package/tools/agents/tests/test_uap_compliance.py +257 -0
|
@@ -0,0 +1,977 @@
|
|
|
1
|
+
import Handlebars from 'handlebars';
|
|
2
|
+
import { existsSync, readFileSync, readdirSync, statSync } from 'fs';
|
|
3
|
+
import { join, dirname } from 'path';
|
|
4
|
+
import { fileURLToPath } from 'url';
|
|
5
|
+
import { prepopulateMemory } from '../memory/prepopulate.js';
|
|
6
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
7
|
+
const __dirname = dirname(__filename);
|
|
8
|
+
export async function generateClaudeMd(analysis, config) {
|
|
9
|
+
// Determine platform mode
|
|
10
|
+
const hasWebDatabase = !!config.memory?.shortTerm?.webDatabase;
|
|
11
|
+
const forceDesktop = config.memory?.shortTerm?.forceDesktop;
|
|
12
|
+
const isWebPlatform = hasWebDatabase && !forceDesktop;
|
|
13
|
+
// Use appropriate template
|
|
14
|
+
const template = isWebPlatform ? getWebTemplate() : getDesktopTemplate();
|
|
15
|
+
// Register PROJECT partial if PROJECT.md exists
|
|
16
|
+
const projectContent = getProjectTemplate();
|
|
17
|
+
if (projectContent) {
|
|
18
|
+
Handlebars.registerPartial('PROJECT', projectContent);
|
|
19
|
+
}
|
|
20
|
+
const compiled = Handlebars.compile(template);
|
|
21
|
+
// Build comprehensive context from analysis + auto-population
|
|
22
|
+
const context = await buildContext(analysis, config);
|
|
23
|
+
return compiled(context);
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Get project-specific template content.
|
|
27
|
+
*
|
|
28
|
+
* PROJECT.md contains all project-specific configuration, making template
|
|
29
|
+
* upgrades seamless - no merge conflicts between universal patterns and
|
|
30
|
+
* project-specific content.
|
|
31
|
+
*
|
|
32
|
+
* Search order:
|
|
33
|
+
* 1. .factory/PROJECT.md (preferred location)
|
|
34
|
+
* 2. templates/PROJECT.md (fallback)
|
|
35
|
+
* 3. PROJECT.md (root fallback)
|
|
36
|
+
*/
|
|
37
|
+
function getProjectTemplate() {
|
|
38
|
+
const cwd = process.cwd();
|
|
39
|
+
const locations = [
|
|
40
|
+
join(cwd, '.factory/PROJECT.md'), // Preferred: Factory config dir
|
|
41
|
+
join(cwd, 'templates/PROJECT.md'), // Fallback: templates dir
|
|
42
|
+
join(cwd, 'templates/PROJECT.template.md'), // Template version
|
|
43
|
+
join(cwd, 'PROJECT.md'), // Root fallback
|
|
44
|
+
];
|
|
45
|
+
for (const path of locations) {
|
|
46
|
+
if (existsSync(path)) {
|
|
47
|
+
try {
|
|
48
|
+
return readFileSync(path, 'utf-8');
|
|
49
|
+
}
|
|
50
|
+
catch (e) {
|
|
51
|
+
console.warn(`Warning: Found PROJECT.md at ${path} but couldn't read it: ${e}`);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
async function buildContext(analysis, config) {
|
|
58
|
+
const cwd = process.cwd();
|
|
59
|
+
// Detect web vs desktop
|
|
60
|
+
const hasWebDatabase = !!config.memory?.shortTerm?.webDatabase;
|
|
61
|
+
const forceDesktop = config.memory?.shortTerm?.forceDesktop;
|
|
62
|
+
const isWebPlatform = hasWebDatabase && !forceDesktop;
|
|
63
|
+
// Long-term memory config
|
|
64
|
+
let longTermBackend = 'Qdrant';
|
|
65
|
+
let longTermEndpoint = config.memory?.longTerm?.endpoint || 'localhost:6333';
|
|
66
|
+
const longTermCollection = config.memory?.longTerm?.collection || 'agent_memory';
|
|
67
|
+
if (config.memory?.longTerm?.provider === 'github') {
|
|
68
|
+
longTermBackend = 'GitHub';
|
|
69
|
+
longTermEndpoint = `${config.memory?.longTerm?.github?.repo || 'owner/repo'}/${config.memory?.longTerm?.github?.path || '.uap/memory'}`;
|
|
70
|
+
}
|
|
71
|
+
else if (config.memory?.longTerm?.provider === 'qdrant-cloud') {
|
|
72
|
+
longTermBackend = 'Qdrant Cloud';
|
|
73
|
+
longTermEndpoint = config.memory?.longTerm?.qdrantCloud?.url || 'https://xxxxxx.aws.cloud.qdrant.io:6333';
|
|
74
|
+
}
|
|
75
|
+
// Prepopulate memory from project
|
|
76
|
+
let prepopulated = null;
|
|
77
|
+
try {
|
|
78
|
+
prepopulated = await prepopulateMemory(cwd, { docs: true, git: true, skills: true, limit: 200 });
|
|
79
|
+
}
|
|
80
|
+
catch (e) {
|
|
81
|
+
console.warn('Failed to prepopulate memory:', e);
|
|
82
|
+
}
|
|
83
|
+
// Build repository structure
|
|
84
|
+
const repoStructure = buildRepositoryStructure(cwd, analysis);
|
|
85
|
+
// Discover skills, droids, commands
|
|
86
|
+
const discoveredSkills = prepopulated?.skills || [];
|
|
87
|
+
const skills = discoveredSkills.filter(s => s.type === 'skill');
|
|
88
|
+
const droids = discoveredSkills.filter(s => s.type === 'droid');
|
|
89
|
+
// Commands discovered from prepopulate (unused currently but kept for reference)
|
|
90
|
+
// const commands = discoveredSkills.filter(s => s.type === 'command');
|
|
91
|
+
// Build skill mappings table
|
|
92
|
+
const skillMappings = buildSkillMappings(skills);
|
|
93
|
+
// Build language droids table
|
|
94
|
+
const languageDroids = buildLanguageDroidsTable(droids, analysis.languages);
|
|
95
|
+
// Build file type routing
|
|
96
|
+
const fileTypeRouting = buildFileTypeRouting(analysis.languages);
|
|
97
|
+
// Build discovered skills table
|
|
98
|
+
const discoveredSkillsTable = buildDiscoveredSkillsTable(skills);
|
|
99
|
+
// Extract troubleshooting from git history
|
|
100
|
+
const troubleshooting = buildTroubleshootingSection(prepopulated?.longTerm || []);
|
|
101
|
+
// Build architecture overview
|
|
102
|
+
const architectureOverview = buildArchitectureOverview(analysis);
|
|
103
|
+
// Build core components section
|
|
104
|
+
const coreComponents = buildCoreComponentsSection(analysis);
|
|
105
|
+
// Build key config files
|
|
106
|
+
const keyConfigFiles = buildKeyConfigFiles(analysis);
|
|
107
|
+
// Build essential commands
|
|
108
|
+
const essentialCommands = buildEssentialCommands(analysis);
|
|
109
|
+
// Build prepopulated knowledge section
|
|
110
|
+
const prepopulatedKnowledge = buildPrepopulatedKnowledge(prepopulated);
|
|
111
|
+
// Build cluster contexts
|
|
112
|
+
const clusterContexts = buildClusterContexts(analysis);
|
|
113
|
+
// Build project URLs
|
|
114
|
+
const projectUrls = buildProjectUrls(analysis);
|
|
115
|
+
// Build key workflows
|
|
116
|
+
const keyWorkflows = buildKeyWorkflows(analysis);
|
|
117
|
+
// Build infrastructure workflow
|
|
118
|
+
const infraWorkflow = buildInfraWorkflow(analysis);
|
|
119
|
+
// Build MCP plugins
|
|
120
|
+
const mcpPlugins = buildMcpPlugins(cwd);
|
|
121
|
+
// Build primary skills for decision loop
|
|
122
|
+
const primarySkills = buildPrimarySkills(skills);
|
|
123
|
+
// Build language examples
|
|
124
|
+
const languageExamples = buildLanguageExamples(analysis.languages);
|
|
125
|
+
// Build relevant patterns (pruned by project type to save tokens)
|
|
126
|
+
const relevantPatterns = buildRelevantPatterns(analysis);
|
|
127
|
+
// Template version for reproducibility
|
|
128
|
+
const TEMPLATE_VERSION = '10.16-opt';
|
|
129
|
+
return {
|
|
130
|
+
// Project basics
|
|
131
|
+
PROJECT_NAME: analysis.projectName || config.project.name,
|
|
132
|
+
DESCRIPTION: analysis.description || config.project.description || '',
|
|
133
|
+
DEFAULT_BRANCH: analysis.defaultBranch || config.project.defaultBranch || 'main',
|
|
134
|
+
TEMPLATE_VERSION,
|
|
135
|
+
// Issue tracker
|
|
136
|
+
ISSUE_TRACKER: analysis.issueTracker ?
|
|
137
|
+
`Use [${analysis.issueTracker.name}](${analysis.issueTracker.url || '#'}) for issue tracking.` :
|
|
138
|
+
null,
|
|
139
|
+
// Memory config
|
|
140
|
+
MEMORY_DB_PATH: config.memory?.shortTerm?.path || 'agents/data/memory/short_term.db',
|
|
141
|
+
MEMORY_QUERY_CMD: 'uap memory query',
|
|
142
|
+
MEMORY_STORE_CMD: 'uap memory store',
|
|
143
|
+
MEMORY_START_CMD: 'uap memory start',
|
|
144
|
+
MEMORY_STATUS_CMD: 'uap memory status',
|
|
145
|
+
MEMORY_STOP_CMD: 'uap memory stop',
|
|
146
|
+
SHORT_TERM_LIMIT: config.memory?.shortTerm?.maxEntries || 50,
|
|
147
|
+
LONG_TERM_BACKEND: longTermBackend,
|
|
148
|
+
LONG_TERM_ENDPOINT: longTermEndpoint,
|
|
149
|
+
LONG_TERM_COLLECTION: longTermCollection,
|
|
150
|
+
SCREENSHOTS_PATH: 'agents/data/screenshots',
|
|
151
|
+
DOCKER_COMPOSE_PATH: existsSync(join(cwd, 'agents/docker-compose.yml')) ? 'agents/docker-compose.yml' :
|
|
152
|
+
existsSync(join(cwd, 'docker-compose.yml')) ? 'docker-compose.yml' : null,
|
|
153
|
+
// Worktree config
|
|
154
|
+
WORKTREE_DIR: config.worktrees?.directory || '.worktrees',
|
|
155
|
+
WORKTREE_CREATE_CMD: 'uap worktree create',
|
|
156
|
+
WORKTREE_PR_CMD: 'uap worktree pr',
|
|
157
|
+
WORKTREE_CLEANUP_CMD: 'uap worktree cleanup',
|
|
158
|
+
WORKTREE_APPLIES_TO: 'Application code, configs, workflows, documentation, CLAUDE.md itself',
|
|
159
|
+
BRANCH_PREFIX: config.worktrees?.branchPrefix || 'feature/',
|
|
160
|
+
// Paths
|
|
161
|
+
SKILLS_PATH: '.factory/skills/',
|
|
162
|
+
DROIDS_PATH: '.factory/droids/',
|
|
163
|
+
COMMANDS_PATH: '.factory/commands/',
|
|
164
|
+
DOCS_PATH: analysis.directories.docs[0] || 'docs',
|
|
165
|
+
FIXES_PATH: existsSync(join(cwd, 'docs/fixes')) ? 'docs/fixes/' : null,
|
|
166
|
+
CHANGELOG_PATH: existsSync(join(cwd, 'docs/changelog')) ? 'docs/changelog' : null,
|
|
167
|
+
CHANGELOG_TEMPLATE: existsSync(join(cwd, 'docs/changelog/CHANGELOG_TEMPLATE.md')) ? 'docs/changelog/CHANGELOG_TEMPLATE.md' : null,
|
|
168
|
+
WORKFLOW_DOCS_PATH: existsSync(join(cwd, 'docs/workflows/GIT_WORKTREE_WORKFLOW.md')) ? 'docs/workflows/GIT_WORKTREE_WORKFLOW.md' : null,
|
|
169
|
+
// Commands
|
|
170
|
+
TEST_COMMAND: analysis.commands.test || 'npm test',
|
|
171
|
+
LINT_COMMAND: analysis.commands.lint || 'npm run lint',
|
|
172
|
+
BUILD_COMMAND: analysis.commands.build || 'npm run build',
|
|
173
|
+
HOOKS_INSTALL_CMD: existsSync(join(cwd, '.factory/scripts/install-hooks.sh')) ? '.factory/scripts/install-hooks.sh' : null,
|
|
174
|
+
// Skills and droids
|
|
175
|
+
PRIMARY_SKILLS: primarySkills,
|
|
176
|
+
SKILL_MAPPINGS: skillMappings,
|
|
177
|
+
DISCOVERED_SKILLS: discoveredSkillsTable,
|
|
178
|
+
LANGUAGE_DROIDS: languageDroids,
|
|
179
|
+
LANGUAGE_EXAMPLES: languageExamples,
|
|
180
|
+
FILE_TYPE_ROUTING: fileTypeRouting,
|
|
181
|
+
// Repository structure (support both old @REPOSITORY_STRUCTURE and new REPOSITORY_STRUCTURE)
|
|
182
|
+
'@REPOSITORY_STRUCTURE': repoStructure,
|
|
183
|
+
REPOSITORY_STRUCTURE: repoStructure,
|
|
184
|
+
STRUCTURE_DATE: new Date().toLocaleString('en-US', { month: 'long', year: 'numeric' }),
|
|
185
|
+
// Path migrations (if detected from git history)
|
|
186
|
+
PATH_MIGRATIONS: null, // TODO: detect from git mv history
|
|
187
|
+
// Clusters and URLs
|
|
188
|
+
CLUSTER_CONTEXTS: clusterContexts,
|
|
189
|
+
PROJECT_URLS: projectUrls,
|
|
190
|
+
KEY_WORKFLOWS: keyWorkflows,
|
|
191
|
+
ESSENTIAL_COMMANDS: essentialCommands,
|
|
192
|
+
// Architecture
|
|
193
|
+
ARCHITECTURE_OVERVIEW: architectureOverview,
|
|
194
|
+
DATABASE_ARCHITECTURE: analysis.databases.length > 0 ? buildDatabaseArchitecture(analysis) : null,
|
|
195
|
+
// Core components
|
|
196
|
+
CORE_COMPONENTS: coreComponents,
|
|
197
|
+
// Auth flow
|
|
198
|
+
AUTH_FLOW: analysis.authentication ? buildAuthFlow(analysis) : null,
|
|
199
|
+
// Gateway knowledge
|
|
200
|
+
GATEWAY_KNOWLEDGE: null, // Project-specific, detected from k8s/istio files
|
|
201
|
+
// Multi-environment
|
|
202
|
+
MULTI_ENV_CONFIG: null, // Project-specific
|
|
203
|
+
// Infrastructure
|
|
204
|
+
HAS_INFRA: analysis.directories.infrastructure.length > 0 || config.template?.sections?.pipelineOnly,
|
|
205
|
+
HAS_PIPELINE_POLICY: config.template?.sections?.pipelineOnly || false,
|
|
206
|
+
INFRA_WORKFLOW: infraWorkflow,
|
|
207
|
+
CLUSTER_IDENTIFY: analysis.clusters?.enabled ? 'Identify which cluster(s) affected' : null,
|
|
208
|
+
// Troubleshooting
|
|
209
|
+
TROUBLESHOOTING: troubleshooting,
|
|
210
|
+
// Key config files
|
|
211
|
+
KEY_CONFIG_FILES: keyConfigFiles,
|
|
212
|
+
// MCP plugins
|
|
213
|
+
MCP_PLUGINS: mcpPlugins,
|
|
214
|
+
// Prepopulated knowledge
|
|
215
|
+
PREPOPULATED_KNOWLEDGE: prepopulatedKnowledge ? true : null,
|
|
216
|
+
RECENT_ACTIVITY: prepopulatedKnowledge?.recentActivity || null,
|
|
217
|
+
LEARNED_LESSONS: prepopulatedKnowledge?.learnedLessons || null,
|
|
218
|
+
KNOWN_GOTCHAS: prepopulatedKnowledge?.knownGotchas || null,
|
|
219
|
+
HOT_SPOTS: prepopulatedKnowledge?.hotSpots || null,
|
|
220
|
+
// Platform detection
|
|
221
|
+
IS_WEB_PLATFORM: isWebPlatform,
|
|
222
|
+
IS_DESKTOP_PLATFORM: !isWebPlatform,
|
|
223
|
+
// Benchmark mode detection (#34) - conditional domain knowledge
|
|
224
|
+
// Enable for terminal-bench tasks to include domain-specific patterns
|
|
225
|
+
// Disable for production to save ~300 tokens
|
|
226
|
+
IS_BENCHMARK: config.template?.sections?.benchmark ||
|
|
227
|
+
existsSync(join(cwd, '.tbench')) ||
|
|
228
|
+
existsSync(join(cwd, 'verifier.sh')) ||
|
|
229
|
+
process.env.UAM_BENCHMARK_MODE === 'true',
|
|
230
|
+
// PROJECT.md separation support
|
|
231
|
+
HAS_PROJECT_MD: existsSync(join(cwd, '.factory/PROJECT.md')) ||
|
|
232
|
+
existsSync(join(cwd, 'templates/PROJECT.md')) ||
|
|
233
|
+
existsSync(join(cwd, 'PROJECT.md')),
|
|
234
|
+
// Relevant patterns (pruned by project type to save ~800 tokens)
|
|
235
|
+
RELEVANT_PATTERNS: relevantPatterns,
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
function buildRepositoryStructure(cwd, analysis) {
|
|
239
|
+
const lines = [];
|
|
240
|
+
const visited = new Set();
|
|
241
|
+
// Standard directories to look for
|
|
242
|
+
const standardDirs = [
|
|
243
|
+
{ path: 'apps', comment: 'Deployable applications' },
|
|
244
|
+
{ path: 'services', comment: 'Backend microservices' },
|
|
245
|
+
{ path: 'packages', comment: 'Shared packages' },
|
|
246
|
+
{ path: 'libs', comment: 'Shared libraries' },
|
|
247
|
+
{ path: 'src', comment: 'Source code' },
|
|
248
|
+
{ path: 'infra', comment: 'Infrastructure as Code' },
|
|
249
|
+
{ path: 'infrastructure', comment: 'Infrastructure as Code' },
|
|
250
|
+
{ path: 'terraform', comment: 'Terraform configurations' },
|
|
251
|
+
{ path: 'k8s', comment: 'Kubernetes manifests' },
|
|
252
|
+
{ path: 'helm', comment: 'Helm charts' },
|
|
253
|
+
{ path: 'tools', comment: 'Development tools' },
|
|
254
|
+
{ path: 'scripts', comment: 'Automation scripts' },
|
|
255
|
+
{ path: 'tests', comment: 'Test suites' },
|
|
256
|
+
{ path: 'test', comment: 'Test suites' },
|
|
257
|
+
{ path: 'docs', comment: 'Documentation' },
|
|
258
|
+
{ path: '.factory', comment: 'Factory AI configuration' },
|
|
259
|
+
{ path: '.github', comment: 'GitHub configuration' },
|
|
260
|
+
{ path: '.gitlab', comment: 'GitLab configuration' },
|
|
261
|
+
];
|
|
262
|
+
for (const { path, comment } of standardDirs) {
|
|
263
|
+
const fullPath = join(cwd, path);
|
|
264
|
+
if (existsSync(fullPath) && statSync(fullPath).isDirectory()) {
|
|
265
|
+
visited.add(path);
|
|
266
|
+
lines.push(`├── ${path}/`.padEnd(35) + `# ${comment}`);
|
|
267
|
+
// List subdirectories
|
|
268
|
+
try {
|
|
269
|
+
const subdirs = readdirSync(fullPath, { withFileTypes: true })
|
|
270
|
+
.filter(d => d.isDirectory() && !d.name.startsWith('.'))
|
|
271
|
+
.slice(0, 8);
|
|
272
|
+
for (let i = 0; i < subdirs.length; i++) {
|
|
273
|
+
const prefix = i === subdirs.length - 1 ? '│ └── ' : '│ ├── ';
|
|
274
|
+
const subComment = getSubdirComment(path, subdirs[i].name, join(fullPath, subdirs[i].name));
|
|
275
|
+
lines.push(`${prefix}${subdirs[i].name}/`.padEnd(35) + (subComment ? `# ${subComment}` : ''));
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
catch {
|
|
279
|
+
// Ignore permission errors
|
|
280
|
+
}
|
|
281
|
+
lines.push('│');
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
// Add component directories from analysis
|
|
285
|
+
for (const comp of analysis.components) {
|
|
286
|
+
const dirPath = comp.path.split('/')[0];
|
|
287
|
+
if (!visited.has(dirPath) && existsSync(join(cwd, dirPath))) {
|
|
288
|
+
visited.add(dirPath);
|
|
289
|
+
lines.push(`├── ${dirPath}/`.padEnd(35) + `# ${comp.description || comp.name}`);
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
// Remove trailing separator
|
|
293
|
+
if (lines.length > 0 && lines[lines.length - 1] === '│') {
|
|
294
|
+
lines.pop();
|
|
295
|
+
}
|
|
296
|
+
return lines.join('\n');
|
|
297
|
+
}
|
|
298
|
+
function getSubdirComment(parentDir, subdir, fullPath) {
|
|
299
|
+
// Check for package.json, README, etc. to get description
|
|
300
|
+
const packageJsonPath = join(fullPath, 'package.json');
|
|
301
|
+
if (existsSync(packageJsonPath)) {
|
|
302
|
+
try {
|
|
303
|
+
const pkg = JSON.parse(readFileSync(packageJsonPath, 'utf-8'));
|
|
304
|
+
if (pkg.description)
|
|
305
|
+
return pkg.description.slice(0, 40);
|
|
306
|
+
}
|
|
307
|
+
catch {
|
|
308
|
+
// Ignore
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
// Default comments based on common patterns
|
|
312
|
+
const patterns = {
|
|
313
|
+
apps: {
|
|
314
|
+
api: 'REST API',
|
|
315
|
+
web: 'Web frontend',
|
|
316
|
+
mobile: 'Mobile app',
|
|
317
|
+
admin: 'Admin dashboard',
|
|
318
|
+
cms: 'CMS',
|
|
319
|
+
},
|
|
320
|
+
services: {
|
|
321
|
+
auth: 'Authentication service',
|
|
322
|
+
gateway: 'API Gateway',
|
|
323
|
+
},
|
|
324
|
+
'.factory': {
|
|
325
|
+
droids: 'Custom AI agents',
|
|
326
|
+
skills: 'Reusable skills',
|
|
327
|
+
commands: 'CLI commands',
|
|
328
|
+
scripts: 'Automation scripts',
|
|
329
|
+
},
|
|
330
|
+
'.github': {
|
|
331
|
+
workflows: 'CI/CD pipelines',
|
|
332
|
+
},
|
|
333
|
+
};
|
|
334
|
+
return patterns[parentDir]?.[subdir] || '';
|
|
335
|
+
}
|
|
336
|
+
function buildSkillMappings(skills) {
|
|
337
|
+
if (skills.length === 0)
|
|
338
|
+
return null;
|
|
339
|
+
const lines = [];
|
|
340
|
+
for (const skill of skills) {
|
|
341
|
+
if (skill.name.includes('design') || skill.name.includes('ui')) {
|
|
342
|
+
lines.push(`| UI/Design work (buttons, modals, colors, layouts) | \`${skill.name}\` |`);
|
|
343
|
+
}
|
|
344
|
+
else if (skill.name.includes('frontend') || skill.name.includes('react')) {
|
|
345
|
+
lines.push(`| React/TypeScript/Frontend | \`${skill.name}\` |`);
|
|
346
|
+
}
|
|
347
|
+
else if (skill.name.includes('backend') || skill.name.includes('api')) {
|
|
348
|
+
lines.push(`| Backend/API development | \`${skill.name}\` |`);
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
return lines.length > 0 ? lines.join('\n') : null;
|
|
352
|
+
}
|
|
353
|
+
function buildLanguageDroidsTable(droids, languages) {
|
|
354
|
+
const languageDroids = droids.filter(d => d.name.includes('-pro') ||
|
|
355
|
+
d.name.includes('specialist') ||
|
|
356
|
+
languages.some(l => d.name.toLowerCase().includes(l.toLowerCase())));
|
|
357
|
+
if (languageDroids.length === 0 && languages.length > 0) {
|
|
358
|
+
// Generate suggested droids based on detected languages
|
|
359
|
+
const suggestions = [];
|
|
360
|
+
for (const lang of languages.slice(0, 5)) {
|
|
361
|
+
const langLower = lang.toLowerCase();
|
|
362
|
+
if (langLower.includes('typescript') || langLower.includes('javascript')) {
|
|
363
|
+
suggestions.push('| `javascript-pro` | ES6+, async patterns, Node.js, promises, event loops |');
|
|
364
|
+
}
|
|
365
|
+
else if (langLower.includes('python')) {
|
|
366
|
+
suggestions.push('| `python-pro` | Async/await, decorators, generators, pytest, type hints |');
|
|
367
|
+
}
|
|
368
|
+
else if (langLower.includes('c++') || langLower.includes('cpp')) {
|
|
369
|
+
suggestions.push('| `cpp-pro` | C++20 with RAII, smart pointers, STL, templates, move semantics |');
|
|
370
|
+
}
|
|
371
|
+
else if (langLower.includes('rust')) {
|
|
372
|
+
suggestions.push('| `rust-pro` | Ownership, lifetimes, async, error handling, macros |');
|
|
373
|
+
}
|
|
374
|
+
else if (langLower.includes('go')) {
|
|
375
|
+
suggestions.push('| `go-pro` | Concurrency, channels, interfaces, error handling |');
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
return suggestions.length > 0 ? [...new Set(suggestions)].join('\n') : null;
|
|
379
|
+
}
|
|
380
|
+
return languageDroids.map(d => `| \`${d.name}\` | ${d.description || `${d.platform} language specialist`} |`).join('\n') || null;
|
|
381
|
+
}
|
|
382
|
+
function buildDiscoveredSkillsTable(skills) {
|
|
383
|
+
if (skills.length === 0)
|
|
384
|
+
return null;
|
|
385
|
+
return skills.slice(0, 10).map(s => {
|
|
386
|
+
const purpose = s.description || `${s.platform} skill`;
|
|
387
|
+
const useWhen = s.name.includes('design') ? 'UI/design work' :
|
|
388
|
+
s.name.includes('test') ? 'Testing and QA' :
|
|
389
|
+
s.name.includes('review') ? 'Code review' :
|
|
390
|
+
'Specialized tasks';
|
|
391
|
+
return `| \`${s.name}\` | ${purpose} | ${useWhen} |`;
|
|
392
|
+
}).join('\n');
|
|
393
|
+
}
|
|
394
|
+
function buildTroubleshootingSection(memories) {
|
|
395
|
+
// Extract fix-related memories
|
|
396
|
+
const fixes = memories.filter(m => m.tags?.includes('bug-fix') ||
|
|
397
|
+
m.tags?.includes('revert') ||
|
|
398
|
+
m.content.toLowerCase().includes('fix') ||
|
|
399
|
+
m.content.toLowerCase().includes('resolved')).slice(0, 15);
|
|
400
|
+
if (fixes.length === 0)
|
|
401
|
+
return null;
|
|
402
|
+
const lines = [];
|
|
403
|
+
for (const fix of fixes) {
|
|
404
|
+
// Extract symptom and solution from content
|
|
405
|
+
const content = fix.content;
|
|
406
|
+
let symptom = '';
|
|
407
|
+
let solution = '';
|
|
408
|
+
if (content.includes('Bug fixed:')) {
|
|
409
|
+
symptom = content.replace('Bug fixed:', '').split('.')[0].trim();
|
|
410
|
+
solution = content.split('.').slice(1).join('.').trim() || 'See commit for details';
|
|
411
|
+
}
|
|
412
|
+
else if (content.includes('Failed approach')) {
|
|
413
|
+
symptom = content.split(':')[1]?.split('.')[0]?.trim() || content.slice(0, 50);
|
|
414
|
+
solution = 'Avoid this approach';
|
|
415
|
+
}
|
|
416
|
+
else {
|
|
417
|
+
symptom = content.slice(0, 60) + (content.length > 60 ? '...' : '');
|
|
418
|
+
solution = 'See memory for details';
|
|
419
|
+
}
|
|
420
|
+
if (symptom) {
|
|
421
|
+
lines.push(`| ${symptom} | ${solution.slice(0, 60)} |`);
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
if (lines.length === 0)
|
|
425
|
+
return null;
|
|
426
|
+
return `| Symptom | Solution |\n|---------|----------|\n${lines.join('\n')}`;
|
|
427
|
+
}
|
|
428
|
+
function buildArchitectureOverview(analysis) {
|
|
429
|
+
const sections = [];
|
|
430
|
+
// Infrastructure overview
|
|
431
|
+
if (analysis.infrastructure.iac || analysis.infrastructure.containerOrchestration) {
|
|
432
|
+
sections.push('### Infrastructure\n');
|
|
433
|
+
if (analysis.infrastructure.iac) {
|
|
434
|
+
sections.push(`- **IaC**: ${analysis.infrastructure.iac}`);
|
|
435
|
+
}
|
|
436
|
+
if (analysis.infrastructure.containerOrchestration) {
|
|
437
|
+
sections.push(`- **Orchestration**: ${analysis.infrastructure.containerOrchestration}`);
|
|
438
|
+
}
|
|
439
|
+
if (analysis.infrastructure.cloud && analysis.infrastructure.cloud.length > 0) {
|
|
440
|
+
sections.push(`- **Cloud**: ${analysis.infrastructure.cloud.join(', ')}`);
|
|
441
|
+
}
|
|
442
|
+
sections.push('');
|
|
443
|
+
}
|
|
444
|
+
// Component overview
|
|
445
|
+
if (analysis.components.length > 0) {
|
|
446
|
+
sections.push('### Components\n');
|
|
447
|
+
for (const comp of analysis.components.slice(0, 8)) {
|
|
448
|
+
sections.push(`- **${comp.name}** (\`${comp.path}\`): ${comp.description || `${comp.language} ${comp.framework || 'application'}`}`);
|
|
449
|
+
}
|
|
450
|
+
sections.push('');
|
|
451
|
+
}
|
|
452
|
+
return sections.length > 0 ? sections.join('\n') : null;
|
|
453
|
+
}
|
|
454
|
+
function buildCoreComponentsSection(analysis) {
|
|
455
|
+
if (analysis.components.length === 0)
|
|
456
|
+
return null;
|
|
457
|
+
const sections = [];
|
|
458
|
+
for (const comp of analysis.components.slice(0, 6)) {
|
|
459
|
+
sections.push(`### ${comp.name} (\`${comp.path}\`)\n`);
|
|
460
|
+
sections.push(`- **Language**: ${comp.language}`);
|
|
461
|
+
if (comp.framework) {
|
|
462
|
+
sections.push(`- **Framework**: ${comp.framework}`);
|
|
463
|
+
}
|
|
464
|
+
if (comp.description) {
|
|
465
|
+
sections.push(`- ${comp.description}`);
|
|
466
|
+
}
|
|
467
|
+
sections.push('');
|
|
468
|
+
}
|
|
469
|
+
return sections.join('\n');
|
|
470
|
+
}
|
|
471
|
+
function buildDatabaseArchitecture(analysis) {
|
|
472
|
+
const lines = [];
|
|
473
|
+
for (const db of analysis.databases) {
|
|
474
|
+
lines.push(`- **${db.type}**: ${db.purpose || 'Primary database'}`);
|
|
475
|
+
}
|
|
476
|
+
return lines.join('\n');
|
|
477
|
+
}
|
|
478
|
+
function buildAuthFlow(analysis) {
|
|
479
|
+
if (!analysis.authentication)
|
|
480
|
+
return '';
|
|
481
|
+
const sections = [];
|
|
482
|
+
sections.push(`**Provider**: ${analysis.authentication.provider}\n`);
|
|
483
|
+
if (analysis.authentication.description) {
|
|
484
|
+
sections.push(analysis.authentication.description);
|
|
485
|
+
}
|
|
486
|
+
return sections.join('\n');
|
|
487
|
+
}
|
|
488
|
+
function buildKeyConfigFiles(analysis) {
|
|
489
|
+
const files = [];
|
|
490
|
+
// Add key files from analysis
|
|
491
|
+
for (const kf of analysis.keyFiles.slice(0, 15)) {
|
|
492
|
+
files.push({ file: kf.file, purpose: kf.purpose });
|
|
493
|
+
}
|
|
494
|
+
if (files.length === 0)
|
|
495
|
+
return null;
|
|
496
|
+
return files.map(f => `| \`${f.file}\` | ${f.purpose} |`).join('\n');
|
|
497
|
+
}
|
|
498
|
+
function buildEssentialCommands(analysis) {
|
|
499
|
+
const commands = [];
|
|
500
|
+
// Test command
|
|
501
|
+
if (analysis.commands.test && analysis.commands.test !== 'npm test') {
|
|
502
|
+
commands.push(`# Tests\n${analysis.commands.test}`);
|
|
503
|
+
}
|
|
504
|
+
// Lint command
|
|
505
|
+
if (analysis.commands.lint) {
|
|
506
|
+
commands.push(`# Linting\n${analysis.commands.lint}`);
|
|
507
|
+
}
|
|
508
|
+
// Build command
|
|
509
|
+
if (analysis.commands.build) {
|
|
510
|
+
commands.push(`# Build\n${analysis.commands.build}`);
|
|
511
|
+
}
|
|
512
|
+
// Infrastructure command
|
|
513
|
+
if (analysis.infrastructure.iac === 'Terraform') {
|
|
514
|
+
const infraPath = analysis.directories.infrastructure[0] || 'infra/terraform';
|
|
515
|
+
commands.push(`# Terraform\ncd ${infraPath} && terraform plan`);
|
|
516
|
+
}
|
|
517
|
+
return commands.length > 0 ? commands.join('\n\n') : null;
|
|
518
|
+
}
|
|
519
|
+
function buildClusterContexts(analysis) {
|
|
520
|
+
if (!analysis.clusters?.enabled || !analysis.clusters.contexts)
|
|
521
|
+
return null;
|
|
522
|
+
return analysis.clusters.contexts.map(c => `kubectl config use-context ${c.context} # ${c.name} (${c.purpose})`).join('\n');
|
|
523
|
+
}
|
|
524
|
+
function buildProjectUrls(analysis) {
|
|
525
|
+
if (analysis.urls.length === 0)
|
|
526
|
+
return null;
|
|
527
|
+
return analysis.urls.map(u => `- **${u.name}**: ${u.value}`).join('\n');
|
|
528
|
+
}
|
|
529
|
+
function buildKeyWorkflows(analysis) {
|
|
530
|
+
if (!analysis.ciCd?.workflows || analysis.ciCd.workflows.length === 0)
|
|
531
|
+
return null;
|
|
532
|
+
return analysis.ciCd.workflows.slice(0, 10).map(w => `├── ${w.file}`.padEnd(35) + `# ${w.purpose}`).join('\n');
|
|
533
|
+
}
|
|
534
|
+
function buildInfraWorkflow(analysis) {
|
|
535
|
+
if (analysis.directories.infrastructure.length === 0)
|
|
536
|
+
return null;
|
|
537
|
+
const infraPath = analysis.directories.infrastructure[0];
|
|
538
|
+
const planCmd = analysis.infrastructure.iac === 'Terraform' ? 'terraform plan' :
|
|
539
|
+
analysis.infrastructure.iac === 'Pulumi' ? 'pulumi preview' :
|
|
540
|
+
'infrastructure plan';
|
|
541
|
+
return `1. **Create worktree** for infrastructure changes
|
|
542
|
+
2. Update infrastructure in \`${infraPath}/\`
|
|
543
|
+
3. Update CI/CD workflows in \`.github/workflows/\`
|
|
544
|
+
4. Run \`${planCmd}\`
|
|
545
|
+
5. Update secrets via GitHub Actions (not locally)
|
|
546
|
+
6. **Create PR** with automated review`;
|
|
547
|
+
}
|
|
548
|
+
function buildMcpPlugins(cwd) {
|
|
549
|
+
const mcpPath = join(cwd, '.mcp.json');
|
|
550
|
+
if (!existsSync(mcpPath))
|
|
551
|
+
return null;
|
|
552
|
+
try {
|
|
553
|
+
const mcp = JSON.parse(readFileSync(mcpPath, 'utf-8'));
|
|
554
|
+
if (!mcp.mcpServers && !mcp.plugins)
|
|
555
|
+
return null;
|
|
556
|
+
const plugins = mcp.mcpServers || mcp.plugins || {};
|
|
557
|
+
const lines = [];
|
|
558
|
+
for (const [name, config] of Object.entries(plugins)) {
|
|
559
|
+
const desc = config.description ||
|
|
560
|
+
config.purpose ||
|
|
561
|
+
'MCP plugin';
|
|
562
|
+
lines.push(`| \`${name}\` | ${desc} |`);
|
|
563
|
+
}
|
|
564
|
+
return lines.length > 0 ? lines.join('\n') : null;
|
|
565
|
+
}
|
|
566
|
+
catch {
|
|
567
|
+
return null;
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
function buildPrimarySkills(skills) {
|
|
571
|
+
const primary = skills.filter(s => s.name.includes('design') ||
|
|
572
|
+
s.name.includes('frontend') ||
|
|
573
|
+
s.name.includes('ui')).slice(0, 3);
|
|
574
|
+
if (primary.length === 0)
|
|
575
|
+
return null;
|
|
576
|
+
return primary.map(s => `│ ├─ Use ${s.name} for ${s.description || 'specialized work'} │`).join('\n');
|
|
577
|
+
}
|
|
578
|
+
function buildLanguageExamples(languages) {
|
|
579
|
+
const examples = [];
|
|
580
|
+
for (const lang of languages.slice(0, 3)) {
|
|
581
|
+
const langLower = lang.toLowerCase();
|
|
582
|
+
if (langLower.includes('c++') || langLower.includes('cpp')) {
|
|
583
|
+
examples.push(`# For C++ work\nTask(subagent_type: "cpp-pro", prompt: "Refactor X using RAII...")`);
|
|
584
|
+
}
|
|
585
|
+
else if (langLower.includes('python')) {
|
|
586
|
+
examples.push(`# For Python work\nTask(subagent_type: "python-pro", prompt: "Optimize async handlers...")`);
|
|
587
|
+
}
|
|
588
|
+
else if (langLower.includes('rust')) {
|
|
589
|
+
examples.push(`# For Rust work\nTask(subagent_type: "rust-pro", prompt: "Implement with proper lifetimes...")`);
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
return examples.length > 0 ? examples.join('\n\n') : null;
|
|
593
|
+
}
|
|
594
|
+
function buildFileTypeRouting(languages) {
|
|
595
|
+
const routing = [];
|
|
596
|
+
const added = new Set();
|
|
597
|
+
for (const lang of languages) {
|
|
598
|
+
const langLower = lang.toLowerCase();
|
|
599
|
+
if ((langLower.includes('typescript') || langLower.includes('javascript')) && !added.has('ts')) {
|
|
600
|
+
routing.push('| `.ts`, `.tsx`, `.js`, `.jsx` | TypeScript/JavaScript | `typescript-node-expert` |');
|
|
601
|
+
added.add('ts');
|
|
602
|
+
}
|
|
603
|
+
if (langLower.includes('python') && !added.has('py')) {
|
|
604
|
+
routing.push('| `.py` | Python | `python-pro` |');
|
|
605
|
+
added.add('py');
|
|
606
|
+
}
|
|
607
|
+
if ((langLower.includes('c++') || langLower.includes('cpp')) && !added.has('cpp')) {
|
|
608
|
+
routing.push('| `.cpp`, `.h`, `.hpp` | C++ | `cpp-pro` |');
|
|
609
|
+
added.add('cpp');
|
|
610
|
+
}
|
|
611
|
+
if (langLower.includes('rust') && !added.has('rs')) {
|
|
612
|
+
routing.push('| `.rs` | Rust | `rust-pro` |');
|
|
613
|
+
added.add('rs');
|
|
614
|
+
}
|
|
615
|
+
if (langLower.includes('go') && !added.has('go')) {
|
|
616
|
+
routing.push('| `.go` | Go | `go-pro` |');
|
|
617
|
+
added.add('go');
|
|
618
|
+
}
|
|
619
|
+
if (langLower.includes('java') && !added.has('java')) {
|
|
620
|
+
routing.push('| `.java` | Java | `java-pro` |');
|
|
621
|
+
added.add('java');
|
|
622
|
+
}
|
|
623
|
+
}
|
|
624
|
+
// Always add Terraform and YAML for infrastructure projects
|
|
625
|
+
if (!added.has('tf')) {
|
|
626
|
+
routing.push('| `.tf` | Terraform | Direct handling |');
|
|
627
|
+
}
|
|
628
|
+
if (!added.has('yaml')) {
|
|
629
|
+
routing.push('| `.yaml`, `.yml` | Kubernetes/Config | Direct handling |');
|
|
630
|
+
}
|
|
631
|
+
return routing.length > 0 ? routing.join('\n') : null;
|
|
632
|
+
}
|
|
633
|
+
/**
|
|
634
|
+
* OPTIMIZATION 9: More aggressive pattern pruning based on project type.
|
|
635
|
+
* Prunes domain-specific patterns (Chess, Compression impossible, Polyglot, etc.)
|
|
636
|
+
* that don't apply to the project, saving ~800 tokens of context window.
|
|
637
|
+
*
|
|
638
|
+
* Now also categorizes patterns by priority for clearer guidance.
|
|
639
|
+
*/
|
|
640
|
+
function buildRelevantPatterns(analysis) {
|
|
641
|
+
const languages = analysis.languages.map(l => l.toLowerCase());
|
|
642
|
+
const hasInfra = analysis.directories.infrastructure.length > 0;
|
|
643
|
+
const hasSecurity = languages.some(l => l.includes('python') || l.includes('javascript') || l.includes('typescript'));
|
|
644
|
+
const hasGit = true; // All projects use git
|
|
645
|
+
const hasCLI = analysis.components.some(c => c.name.toLowerCase().includes('cli') ||
|
|
646
|
+
c.description?.toLowerCase().includes('command') ||
|
|
647
|
+
c.description?.toLowerCase().includes('script'));
|
|
648
|
+
// CRITICAL patterns - always included, proven high-impact
|
|
649
|
+
const critical = [
|
|
650
|
+
'P12 (OEV)', // Output Existence - 37% of failures
|
|
651
|
+
'P26 (NMI)', // Near-Miss Iteration - converted 2 tasks
|
|
652
|
+
'P35 (DFA)', // Decoder-First - compression failures
|
|
653
|
+
];
|
|
654
|
+
// HIGH priority - usually relevant
|
|
655
|
+
const high = [
|
|
656
|
+
'P3 (StateProtect)', 'P17 (CE)', 'P32 (CEV)',
|
|
657
|
+
];
|
|
658
|
+
// Standard patterns - based on project type
|
|
659
|
+
const standard = [
|
|
660
|
+
'P1 (EnvIsolation)', 'P2 (Recipe)', 'P8 (CLIoverLib)',
|
|
661
|
+
'P13 (IRL)', 'P15 (ER)', 'P16 (TFE)',
|
|
662
|
+
];
|
|
663
|
+
// Conditionally add domain patterns
|
|
664
|
+
if (hasSecurity)
|
|
665
|
+
high.push('P10 (Whitelist)', 'P20 (AT)');
|
|
666
|
+
if (hasGit)
|
|
667
|
+
standard.push('P22 (GRF)');
|
|
668
|
+
if (hasInfra)
|
|
669
|
+
standard.push('P25 (SCP)', 'P28 (SST)');
|
|
670
|
+
if (hasCLI)
|
|
671
|
+
critical.push('P32 (CEV)'); // CLI Execution Verification
|
|
672
|
+
if (languages.some(l => l.includes('rust') || l.includes('c++') || l.includes('python'))) {
|
|
673
|
+
standard.push('P33 (NST)');
|
|
674
|
+
}
|
|
675
|
+
// Domain-specific (only add if detected)
|
|
676
|
+
const domain = [];
|
|
677
|
+
if (analysis.components.some(c => c.name.toLowerCase().includes('chess') || c.description?.toLowerCase().includes('chess'))) {
|
|
678
|
+
domain.push('P21 (CEI)');
|
|
679
|
+
}
|
|
680
|
+
if (analysis.components.some(c => c.name.toLowerCase().includes('compress') || c.description?.toLowerCase().includes('compress'))) {
|
|
681
|
+
domain.push('P23 (CID)', 'P31 (RTV)');
|
|
682
|
+
}
|
|
683
|
+
// OPTIMIZATION 9: Format with priority levels for clarity
|
|
684
|
+
const lines = [];
|
|
685
|
+
lines.push(`**CRITICAL** (check every task): ${critical.join(', ')}`);
|
|
686
|
+
lines.push(`**HIGH**: ${high.join(', ')}`);
|
|
687
|
+
if (standard.length > 0)
|
|
688
|
+
lines.push(`**Standard**: ${standard.slice(0, 8).join(', ')}`);
|
|
689
|
+
if (domain.length > 0)
|
|
690
|
+
lines.push(`**Domain**: ${domain.join(', ')}`);
|
|
691
|
+
return lines.join('\n');
|
|
692
|
+
}
|
|
693
|
+
/**
|
|
694
|
+
* Filter out noisy/fragmented content from prepopulated knowledge.
|
|
695
|
+
* Removes: table fragments, badge/image references, testimonials, README marketing content.
|
|
696
|
+
*/
|
|
697
|
+
function isNoisyContent(content) {
|
|
698
|
+
// Filter out table fragments
|
|
699
|
+
if (content.startsWith('|') || content.includes('|---|'))
|
|
700
|
+
return true;
|
|
701
|
+
// Filter out badge/image references
|
|
702
|
+
if (content.includes('[image:') || content.includes('!['))
|
|
703
|
+
return true;
|
|
704
|
+
// Filter out HTML fragments
|
|
705
|
+
if (content.includes('<div') || content.includes('</div>'))
|
|
706
|
+
return true;
|
|
707
|
+
// Filter out very short content (likely fragments)
|
|
708
|
+
if (content.length < 30)
|
|
709
|
+
return true;
|
|
710
|
+
// Filter out content that's mostly symbols/punctuation
|
|
711
|
+
const alphaCount = (content.match(/[a-zA-Z]/g) || []).length;
|
|
712
|
+
if (alphaCount < content.length * 0.5)
|
|
713
|
+
return true;
|
|
714
|
+
// Filter out testimonials and marketing quotes
|
|
715
|
+
if (content.includes('*"') || content.includes('"*') || content.includes('> *"'))
|
|
716
|
+
return true;
|
|
717
|
+
// Filter out README-style content (installation instructions, promo text)
|
|
718
|
+
if (content.includes('npm install') && content.includes('global'))
|
|
719
|
+
return true;
|
|
720
|
+
if (content.includes('conversation') && content.includes('assistant'))
|
|
721
|
+
return true;
|
|
722
|
+
if (content.includes('After') && content.includes('months'))
|
|
723
|
+
return true;
|
|
724
|
+
// Filter out command examples that are documentation, not lessons
|
|
725
|
+
if (content.startsWith('$ uap') || content.startsWith('$uap'))
|
|
726
|
+
return true;
|
|
727
|
+
if (content.startsWith('bash <(curl'))
|
|
728
|
+
return true;
|
|
729
|
+
// Filter out generic promotional phrases
|
|
730
|
+
if (content.includes('NOT limited') || content.includes('automatically route'))
|
|
731
|
+
return true;
|
|
732
|
+
// Filter out README content patterns (setup instructions, feature descriptions)
|
|
733
|
+
if (content.includes('Install & Init') || content.includes('npm i -g'))
|
|
734
|
+
return true;
|
|
735
|
+
if (content.includes('CLAUDE.md Generated') || content.includes('Auto-populated'))
|
|
736
|
+
return true;
|
|
737
|
+
if (content.includes('Close-Out') || content.includes('Merge → Deploy'))
|
|
738
|
+
return true;
|
|
739
|
+
if (content.includes('context-field research') || content.includes('Results from'))
|
|
740
|
+
return true;
|
|
741
|
+
// Filter out gate/checklist content already in template
|
|
742
|
+
if (content.includes('Three gates must pass') || content.includes('Gate 1'))
|
|
743
|
+
return true;
|
|
744
|
+
// Filter out content that's clearly documentation excerpts, not learned lessons
|
|
745
|
+
if (content.includes('never commits directly to main') || content.includes('All changes use worktrees'))
|
|
746
|
+
return true;
|
|
747
|
+
if (content.includes("Work isn't") && content.includes('deployed'))
|
|
748
|
+
return true;
|
|
749
|
+
if (content.includes('36 patterns discovered'))
|
|
750
|
+
return true;
|
|
751
|
+
return false;
|
|
752
|
+
}
|
|
753
|
+
function buildPrepopulatedKnowledge(prepopulated) {
|
|
754
|
+
if (!prepopulated)
|
|
755
|
+
return null;
|
|
756
|
+
const { shortTerm, longTerm } = prepopulated;
|
|
757
|
+
// Recent activity from short-term (skip noisy content)
|
|
758
|
+
const recentActivity = shortTerm
|
|
759
|
+
.filter(m => (m.type === 'action' || m.type === 'observation') && !isNoisyContent(m.content))
|
|
760
|
+
.slice(0, 10)
|
|
761
|
+
.map(m => `- ${m.content.slice(0, 100)}${m.content.length > 100 ? '...' : ''}`)
|
|
762
|
+
.join('\n');
|
|
763
|
+
// Learned lessons from long-term - filter noise and use sentence-aware truncation
|
|
764
|
+
const learnedLessons = longTerm
|
|
765
|
+
.filter(m => (m.tags?.includes('bug-fix') || m.tags?.includes('lesson') || (m.importance && m.importance >= 7)) &&
|
|
766
|
+
!isNoisyContent(m.content))
|
|
767
|
+
.slice(0, 10)
|
|
768
|
+
.map(m => {
|
|
769
|
+
const content = m.content;
|
|
770
|
+
// Truncate at sentence boundary rather than mid-word
|
|
771
|
+
const truncated = content.length > 200
|
|
772
|
+
? content.slice(0, 200).replace(/[^.!?]*$/, '') || content.slice(0, 200)
|
|
773
|
+
: content;
|
|
774
|
+
const suffix = content.length > truncated.length ? '...' : '';
|
|
775
|
+
return `- **${m.tags?.slice(0, 2).join(', ') || 'general'}**: ${truncated}${suffix}`;
|
|
776
|
+
})
|
|
777
|
+
.join('\n');
|
|
778
|
+
// Known gotchas (from reverts and high-importance fixes) - filter noise
|
|
779
|
+
const knownGotchas = longTerm
|
|
780
|
+
.filter(m => (m.tags?.includes('revert') || m.tags?.includes('failed-approach') || m.content.includes('avoid')) &&
|
|
781
|
+
!isNoisyContent(m.content))
|
|
782
|
+
.slice(0, 5)
|
|
783
|
+
.map(m => {
|
|
784
|
+
const content = m.content;
|
|
785
|
+
const truncated = content.length > 200
|
|
786
|
+
? content.slice(0, 200).replace(/[^.!?]*$/, '') || content.slice(0, 200)
|
|
787
|
+
: content;
|
|
788
|
+
const suffix = content.length > truncated.length ? '...' : '';
|
|
789
|
+
return `- ⚠️ ${truncated}${suffix}`;
|
|
790
|
+
})
|
|
791
|
+
.join('\n');
|
|
792
|
+
// Hot spots
|
|
793
|
+
const hotSpotMemory = longTerm.find(m => m.id === 'git-hotspots');
|
|
794
|
+
const hotSpots = hotSpotMemory?.content || 'No hot spots detected yet.';
|
|
795
|
+
if (!recentActivity && !learnedLessons && !knownGotchas) {
|
|
796
|
+
return null;
|
|
797
|
+
}
|
|
798
|
+
return {
|
|
799
|
+
recentActivity: recentActivity || 'No recent activity recorded.',
|
|
800
|
+
learnedLessons: learnedLessons || 'No lessons recorded yet.',
|
|
801
|
+
knownGotchas: knownGotchas || 'No gotchas recorded yet.',
|
|
802
|
+
hotSpots,
|
|
803
|
+
};
|
|
804
|
+
}
|
|
805
|
+
function getDesktopTemplate() {
|
|
806
|
+
// Check locations in order:
|
|
807
|
+
// 1. User's project templates directory
|
|
808
|
+
// 2. Package's templates directory (for npm installed version)
|
|
809
|
+
// 3. Node modules (when installed as dependency)
|
|
810
|
+
// 4. Fallback inline template
|
|
811
|
+
const userTemplatePath = join(process.cwd(), 'templates/CLAUDE.template.md');
|
|
812
|
+
const packageTemplatePath = join(__dirname, '../../templates/CLAUDE.template.md');
|
|
813
|
+
const nodeModulesPath = join(process.cwd(), 'node_modules/universal-agent-memory/templates/CLAUDE.template.md');
|
|
814
|
+
const templatePaths = [
|
|
815
|
+
{ path: userTemplatePath, name: 'project templates' },
|
|
816
|
+
{ path: packageTemplatePath, name: 'package templates' },
|
|
817
|
+
{ path: nodeModulesPath, name: 'node_modules' },
|
|
818
|
+
];
|
|
819
|
+
for (const { path, name } of templatePaths) {
|
|
820
|
+
if (existsSync(path)) {
|
|
821
|
+
try {
|
|
822
|
+
return readFileSync(path, 'utf-8');
|
|
823
|
+
}
|
|
824
|
+
catch (e) {
|
|
825
|
+
console.warn(`Warning: Found template at ${name} but couldn't read it: ${e}`);
|
|
826
|
+
}
|
|
827
|
+
}
|
|
828
|
+
}
|
|
829
|
+
console.info('Using built-in fallback template. For full features, ensure templates/CLAUDE.template.md exists.');
|
|
830
|
+
// Fallback inline template for desktop
|
|
831
|
+
return `<coding_guidelines>
|
|
832
|
+
|
|
833
|
+
# CLAUDE.md - {{PROJECT_NAME}} Development Guide
|
|
834
|
+
|
|
835
|
+
You are Autonomous Claude, a self-directed AI agent with full control over this virtual machine. You operate continuously, making your own decisions.
|
|
836
|
+
|
|
837
|
+
{{#if ISSUE_TRACKER}}
|
|
838
|
+
**Note**: {{{ISSUE_TRACKER}}}
|
|
839
|
+
{{/if}}
|
|
840
|
+
|
|
841
|
+
---
|
|
842
|
+
|
|
843
|
+
## ⚠️⚠️⚠️ CRITICAL: MANDATORY DECISION LOOP ⚠️⚠️⚠️
|
|
844
|
+
|
|
845
|
+
**FOLLOW THIS FOR EVERY ACTION. NO EXCEPTIONS.**
|
|
846
|
+
|
|
847
|
+
1. **READ MEMORY FIRST**
|
|
848
|
+
- Query short-term: \`sqlite3 {{MEMORY_DB_PATH}} "SELECT * FROM memories ORDER BY id DESC LIMIT 20;"\`
|
|
849
|
+
- Query long-term: \`{{MEMORY_QUERY_CMD}} "<keywords>"\`
|
|
850
|
+
|
|
851
|
+
2. **CHECK SKILLS** before implementing (see \`{{SKILLS_PATH}}\`)
|
|
852
|
+
|
|
853
|
+
3. **CREATE WORKTREE** for ANY code changes
|
|
854
|
+
- \`{{WORKTREE_CREATE_CMD}} <slug>\`
|
|
855
|
+
- NEVER commit directly to {{DEFAULT_BRANCH}}
|
|
856
|
+
|
|
857
|
+
4. **UPDATE MEMORY** after significant actions
|
|
858
|
+
- \`{{MEMORY_STORE_CMD}} lesson "What you learned" --tags tag1,tag2 --importance 7\`
|
|
859
|
+
|
|
860
|
+
---
|
|
861
|
+
|
|
862
|
+
## Memory System
|
|
863
|
+
|
|
864
|
+
- **Short-term**: \`{{MEMORY_DB_PATH}}\` (SQLite, last {{SHORT_TERM_LIMIT}} entries)
|
|
865
|
+
- **Long-term**: {{LONG_TERM_BACKEND}} at \`{{LONG_TERM_ENDPOINT}}\`
|
|
866
|
+
|
|
867
|
+
---
|
|
868
|
+
|
|
869
|
+
## Repository Structure
|
|
870
|
+
|
|
871
|
+
\`\`\`
|
|
872
|
+
{{PROJECT_NAME}}/
|
|
873
|
+
{{{@REPOSITORY_STRUCTURE}}}
|
|
874
|
+
\`\`\`
|
|
875
|
+
|
|
876
|
+
{{#if ARCHITECTURE_OVERVIEW}}
|
|
877
|
+
## Architecture
|
|
878
|
+
|
|
879
|
+
{{{ARCHITECTURE_OVERVIEW}}}
|
|
880
|
+
{{/if}}
|
|
881
|
+
|
|
882
|
+
{{#if CORE_COMPONENTS}}
|
|
883
|
+
## Components
|
|
884
|
+
|
|
885
|
+
{{{CORE_COMPONENTS}}}
|
|
886
|
+
{{/if}}
|
|
887
|
+
|
|
888
|
+
{{#if TROUBLESHOOTING}}
|
|
889
|
+
## Troubleshooting
|
|
890
|
+
|
|
891
|
+
{{{TROUBLESHOOTING}}}
|
|
892
|
+
{{/if}}
|
|
893
|
+
|
|
894
|
+
---
|
|
895
|
+
|
|
896
|
+
## Completion Checklist
|
|
897
|
+
|
|
898
|
+
- [ ] Tests pass
|
|
899
|
+
- [ ] Worktree used
|
|
900
|
+
- [ ] Memory updated
|
|
901
|
+
- [ ] PR created (not direct commit)
|
|
902
|
+
|
|
903
|
+
</coding_guidelines>
|
|
904
|
+
`;
|
|
905
|
+
}
|
|
906
|
+
function getWebTemplate() {
|
|
907
|
+
return `<coding_guidelines>
|
|
908
|
+
|
|
909
|
+
# AGENT.md - {{PROJECT_NAME}} Development Guide
|
|
910
|
+
|
|
911
|
+
You are an AI agent helping with this project. Follow best practices and maintain context.
|
|
912
|
+
|
|
913
|
+
{{#if DESCRIPTION}}
|
|
914
|
+
> {{DESCRIPTION}}
|
|
915
|
+
{{/if}}
|
|
916
|
+
|
|
917
|
+
---
|
|
918
|
+
|
|
919
|
+
## ⛔ MANDATORY RULES
|
|
920
|
+
|
|
921
|
+
1. **BRANCH REQUIREMENT**: Never commit directly to {{DEFAULT_BRANCH}}. Use feature branches.
|
|
922
|
+
2. **MEMORY**: Store significant learnings to \`.uap/memory/\`
|
|
923
|
+
3. **TODO LIST**: Create todo list for multi-step tasks (3+ steps)
|
|
924
|
+
|
|
925
|
+
---
|
|
926
|
+
|
|
927
|
+
## Memory System
|
|
928
|
+
|
|
929
|
+
### Short-term (localStorage)
|
|
930
|
+
|
|
931
|
+
Key: \`agent_context_{{PROJECT_NAME}}\`
|
|
932
|
+
|
|
933
|
+
### Long-term (GitHub: \`.uap/memory/\`)
|
|
934
|
+
|
|
935
|
+
Store memories as JSON files for persistent knowledge.
|
|
936
|
+
|
|
937
|
+
---
|
|
938
|
+
|
|
939
|
+
## Repository Structure
|
|
940
|
+
|
|
941
|
+
\`\`\`
|
|
942
|
+
{{PROJECT_NAME}}/
|
|
943
|
+
{{{@REPOSITORY_STRUCTURE}}}
|
|
944
|
+
\`\`\`
|
|
945
|
+
|
|
946
|
+
{{#if ARCHITECTURE_OVERVIEW}}
|
|
947
|
+
## Architecture
|
|
948
|
+
|
|
949
|
+
{{{ARCHITECTURE_OVERVIEW}}}
|
|
950
|
+
{{/if}}
|
|
951
|
+
|
|
952
|
+
{{#if CORE_COMPONENTS}}
|
|
953
|
+
## Components
|
|
954
|
+
|
|
955
|
+
{{{CORE_COMPONENTS}}}
|
|
956
|
+
{{/if}}
|
|
957
|
+
|
|
958
|
+
---
|
|
959
|
+
|
|
960
|
+
## Workflow
|
|
961
|
+
|
|
962
|
+
1. Create feature branch: \`git checkout -b {{BRANCH_PREFIX}}<description>\`
|
|
963
|
+
2. Make changes, commit, push
|
|
964
|
+
3. Create PR via GitHub UI
|
|
965
|
+
|
|
966
|
+
---
|
|
967
|
+
|
|
968
|
+
## Quick Reference
|
|
969
|
+
|
|
970
|
+
- **Test**: \`{{TEST_COMMAND}}\`
|
|
971
|
+
- **Build**: \`{{BUILD_COMMAND}}\`
|
|
972
|
+
- **Lint**: \`{{LINT_COMMAND}}\`
|
|
973
|
+
|
|
974
|
+
</coding_guidelines>
|
|
975
|
+
`;
|
|
976
|
+
}
|
|
977
|
+
//# sourceMappingURL=claude-md.js.map
|