@miller-tech/uap 1.0.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 +888 -0
- package/dist/analyzers/index.d.ts +3 -0
- package/dist/analyzers/index.d.ts.map +1 -0
- package/dist/analyzers/index.js +684 -0
- package/dist/analyzers/index.js.map +1 -0
- package/dist/benchmarks/agents/naive-agent.d.ts +60 -0
- package/dist/benchmarks/agents/naive-agent.d.ts.map +1 -0
- package/dist/benchmarks/agents/naive-agent.js +144 -0
- package/dist/benchmarks/agents/naive-agent.js.map +1 -0
- package/dist/benchmarks/agents/uap-agent.d.ts +167 -0
- package/dist/benchmarks/agents/uap-agent.d.ts.map +1 -0
- package/dist/benchmarks/agents/uap-agent.js +437 -0
- package/dist/benchmarks/agents/uap-agent.js.map +1 -0
- package/dist/benchmarks/benchmark.d.ts +328 -0
- package/dist/benchmarks/benchmark.d.ts.map +1 -0
- package/dist/benchmarks/benchmark.js +112 -0
- package/dist/benchmarks/benchmark.js.map +1 -0
- package/dist/benchmarks/execution-verifier.d.ts +41 -0
- package/dist/benchmarks/execution-verifier.d.ts.map +1 -0
- package/dist/benchmarks/execution-verifier.js +340 -0
- package/dist/benchmarks/execution-verifier.js.map +1 -0
- package/dist/benchmarks/hierarchical-prompting.d.ts +37 -0
- package/dist/benchmarks/hierarchical-prompting.d.ts.map +1 -0
- package/dist/benchmarks/hierarchical-prompting.js +246 -0
- package/dist/benchmarks/hierarchical-prompting.js.map +1 -0
- package/dist/benchmarks/improved-benchmark.d.ts +89 -0
- package/dist/benchmarks/improved-benchmark.d.ts.map +1 -0
- package/dist/benchmarks/improved-benchmark.js +585 -0
- package/dist/benchmarks/improved-benchmark.js.map +1 -0
- package/dist/benchmarks/index.d.ts +11 -0
- package/dist/benchmarks/index.d.ts.map +1 -0
- package/dist/benchmarks/index.js +11 -0
- package/dist/benchmarks/index.js.map +1 -0
- package/dist/benchmarks/model-integration.d.ts +111 -0
- package/dist/benchmarks/model-integration.d.ts.map +1 -0
- package/dist/benchmarks/model-integration.js +904 -0
- package/dist/benchmarks/model-integration.js.map +1 -0
- package/dist/benchmarks/multi-turn-agent.d.ts +44 -0
- package/dist/benchmarks/multi-turn-agent.d.ts.map +1 -0
- package/dist/benchmarks/multi-turn-agent.js +254 -0
- package/dist/benchmarks/multi-turn-agent.js.map +1 -0
- package/dist/benchmarks/multi-turn-loop.d.ts +57 -0
- package/dist/benchmarks/multi-turn-loop.d.ts.map +1 -0
- package/dist/benchmarks/multi-turn-loop.js +167 -0
- package/dist/benchmarks/multi-turn-loop.js.map +1 -0
- package/dist/benchmarks/tasks.d.ts +19 -0
- package/dist/benchmarks/tasks.d.ts.map +1 -0
- package/dist/benchmarks/tasks.js +435 -0
- package/dist/benchmarks/tasks.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 +546 -0
- package/dist/bin/cli.js.map +1 -0
- package/dist/bin/llama-server-optimize.d.ts +18 -0
- package/dist/bin/llama-server-optimize.d.ts.map +1 -0
- package/dist/bin/llama-server-optimize.js +708 -0
- package/dist/bin/llama-server-optimize.js.map +1 -0
- package/dist/bin/policy.d.ts +3 -0
- package/dist/bin/policy.d.ts.map +1 -0
- package/dist/bin/policy.js +143 -0
- package/dist/bin/policy.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/browser/index.d.ts +2 -0
- package/dist/browser/index.d.ts.map +1 -0
- package/dist/browser/index.js +2 -0
- package/dist/browser/index.js.map +1 -0
- package/dist/browser/web-browser.d.ts +30 -0
- package/dist/browser/web-browser.d.ts.map +1 -0
- package/dist/browser/web-browser.js +93 -0
- package/dist/browser/web-browser.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 +474 -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/completion-gates.d.ts +51 -0
- package/dist/cli/completion-gates.d.ts.map +1 -0
- package/dist/cli/completion-gates.js +201 -0
- package/dist/cli/completion-gates.js.map +1 -0
- package/dist/cli/compliance.d.ts +8 -0
- package/dist/cli/compliance.d.ts.map +1 -0
- package/dist/cli/compliance.js +509 -0
- package/dist/cli/compliance.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 +21 -0
- package/dist/cli/dashboard.d.ts.map +1 -0
- package/dist/cli/dashboard.js +1508 -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 +387 -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 +464 -0
- package/dist/cli/hooks.js.map +1 -0
- package/dist/cli/init.d.ts +12 -0
- package/dist/cli/init.d.ts.map +1 -0
- package/dist/cli/init.js +364 -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 +885 -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 +290 -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 +862 -0
- package/dist/cli/patterns.js.map +1 -0
- package/dist/cli/rtk-validation.d.ts +9 -0
- package/dist/cli/rtk-validation.d.ts.map +1 -0
- package/dist/cli/rtk-validation.js +9 -0
- package/dist/cli/rtk-validation.js.map +1 -0
- package/dist/cli/rtk.d.ts +34 -0
- package/dist/cli/rtk.d.ts.map +1 -0
- package/dist/cli/rtk.js +401 -0
- package/dist/cli/rtk.js.map +1 -0
- package/dist/cli/schema-diff.d.ts +7 -0
- package/dist/cli/schema-diff.d.ts.map +1 -0
- package/dist/cli/schema-diff.js +11 -0
- package/dist/cli/schema-diff.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-wizard.d.ts +2 -0
- package/dist/cli/setup-wizard.d.ts.map +1 -0
- package/dist/cli/setup-wizard.js +806 -0
- package/dist/cli/setup-wizard.js.map +1 -0
- package/dist/cli/setup.d.ts +15 -0
- package/dist/cli/setup.d.ts.map +1 -0
- package/dist/cli/setup.js +154 -0
- package/dist/cli/setup.js.map +1 -0
- package/dist/cli/sync.d.ts +8 -0
- package/dist/cli/sync.d.ts.map +1 -0
- package/dist/cli/sync.js +395 -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 +672 -0
- package/dist/cli/task.js.map +1 -0
- package/dist/cli/tool-calls.d.ts +20 -0
- package/dist/cli/tool-calls.d.ts.map +1 -0
- package/dist/cli/tool-calls.js +605 -0
- package/dist/cli/tool-calls.js.map +1 -0
- package/dist/cli/uap.d.ts +10 -0
- package/dist/cli/uap.d.ts.map +1 -0
- package/dist/cli/uap.js +398 -0
- package/dist/cli/uap.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 +213 -0
- package/dist/cli/worktree.js.map +1 -0
- package/dist/coordination/adaptive-patterns.d.ts +65 -0
- package/dist/coordination/adaptive-patterns.d.ts.map +1 -0
- package/dist/coordination/adaptive-patterns.js +108 -0
- package/dist/coordination/adaptive-patterns.js.map +1 -0
- package/dist/coordination/auto-agent.d.ts +82 -0
- package/dist/coordination/auto-agent.d.ts.map +1 -0
- package/dist/coordination/auto-agent.js +145 -0
- package/dist/coordination/auto-agent.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 +334 -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 +136 -0
- package/dist/coordination/database.js.map +1 -0
- package/dist/coordination/deploy-batcher.d.ts +122 -0
- package/dist/coordination/deploy-batcher.d.ts.map +1 -0
- package/dist/coordination/deploy-batcher.js +718 -0
- package/dist/coordination/deploy-batcher.js.map +1 -0
- package/dist/coordination/droid-validator.d.ts +59 -0
- package/dist/coordination/droid-validator.d.ts.map +1 -0
- package/dist/coordination/droid-validator.js +142 -0
- package/dist/coordination/droid-validator.js.map +1 -0
- package/dist/coordination/index.d.ts +10 -0
- package/dist/coordination/index.d.ts.map +1 -0
- package/dist/coordination/index.js +10 -0
- package/dist/coordination/index.js.map +1 -0
- package/dist/coordination/pattern-router.d.ts +50 -0
- package/dist/coordination/pattern-router.d.ts.map +1 -0
- package/dist/coordination/pattern-router.js +118 -0
- package/dist/coordination/pattern-router.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 +619 -0
- package/dist/coordination/service.js.map +1 -0
- package/dist/coordination/worktree-enforcer.d.ts +22 -0
- package/dist/coordination/worktree-enforcer.d.ts.map +1 -0
- package/dist/coordination/worktree-enforcer.js +71 -0
- package/dist/coordination/worktree-enforcer.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 +1020 -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 +49 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +63 -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 +189 -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 +144 -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 +149 -0
- package/dist/memory/adaptive-context.d.ts.map +1 -0
- package/dist/memory/adaptive-context.js +1095 -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/ambiguity-detector.d.ts +54 -0
- package/dist/memory/ambiguity-detector.d.ts.map +1 -0
- package/dist/memory/ambiguity-detector.js +401 -0
- package/dist/memory/ambiguity-detector.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 +27 -0
- package/dist/memory/backends/github.d.ts.map +1 -0
- package/dist/memory/backends/github.js +134 -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 +167 -0
- package/dist/memory/backends/qdrant-cloud.js.map +1 -0
- package/dist/memory/context-compressor.d.ts +116 -0
- package/dist/memory/context-compressor.d.ts.map +1 -0
- package/dist/memory/context-compressor.js +430 -0
- package/dist/memory/context-compressor.js.map +1 -0
- package/dist/memory/context-pruner.d.ts +55 -0
- package/dist/memory/context-pruner.d.ts.map +1 -0
- package/dist/memory/context-pruner.js +85 -0
- package/dist/memory/context-pruner.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 +112 -0
- package/dist/memory/dynamic-retrieval.d.ts.map +1 -0
- package/dist/memory/dynamic-retrieval.js +908 -0
- package/dist/memory/dynamic-retrieval.js.map +1 -0
- package/dist/memory/embeddings.d.ts +172 -0
- package/dist/memory/embeddings.d.ts.map +1 -0
- package/dist/memory/embeddings.js +780 -0
- package/dist/memory/embeddings.js.map +1 -0
- package/dist/memory/generic-uap-patterns.d.ts +7 -0
- package/dist/memory/generic-uap-patterns.d.ts.map +1 -0
- package/dist/memory/generic-uap-patterns.js +43 -0
- package/dist/memory/generic-uap-patterns.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 +485 -0
- package/dist/memory/hierarchical-memory.js.map +1 -0
- package/dist/memory/knowledge-graph.d.ts +98 -0
- package/dist/memory/knowledge-graph.d.ts.map +1 -0
- package/dist/memory/knowledge-graph.js +275 -0
- package/dist/memory/knowledge-graph.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 +336 -0
- package/dist/memory/memory-maintenance.js.map +1 -0
- package/dist/memory/model-router.d.ts +105 -0
- package/dist/memory/model-router.d.ts.map +1 -0
- package/dist/memory/model-router.js +474 -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 +430 -0
- package/dist/memory/multi-view-memory.js.map +1 -0
- package/dist/memory/predictive-memory.d.ts +79 -0
- package/dist/memory/predictive-memory.d.ts.map +1 -0
- package/dist/memory/predictive-memory.js +294 -0
- package/dist/memory/predictive-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 +832 -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 +359 -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 +141 -0
- package/dist/memory/short-term/schema.js.map +1 -0
- package/dist/memory/short-term/sqlite.d.ts +64 -0
- package/dist/memory/short-term/sqlite.d.ts.map +1 -0
- package/dist/memory/short-term/sqlite.js +274 -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 +457 -0
- package/dist/memory/speculative-cache.js.map +1 -0
- package/dist/memory/task-classifier.d.ts +40 -0
- package/dist/memory/task-classifier.d.ts.map +1 -0
- package/dist/memory/task-classifier.js +342 -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 +622 -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/api-client.d.ts +46 -0
- package/dist/models/api-client.d.ts.map +1 -0
- package/dist/models/api-client.js +182 -0
- package/dist/models/api-client.js.map +1 -0
- package/dist/models/execution-profiles.d.ts +64 -0
- package/dist/models/execution-profiles.d.ts.map +1 -0
- package/dist/models/execution-profiles.js +403 -0
- package/dist/models/execution-profiles.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 +382 -0
- package/dist/models/executor.js.map +1 -0
- package/dist/models/index.d.ts +19 -0
- package/dist/models/index.d.ts.map +1 -0
- package/dist/models/index.js +23 -0
- package/dist/models/index.js.map +1 -0
- package/dist/models/plan-validator.d.ts +37 -0
- package/dist/models/plan-validator.d.ts.map +1 -0
- package/dist/models/plan-validator.js +179 -0
- package/dist/models/plan-validator.js.map +1 -0
- package/dist/models/planner.d.ts +73 -0
- package/dist/models/planner.d.ts.map +1 -0
- package/dist/models/planner.js +375 -0
- package/dist/models/planner.js.map +1 -0
- package/dist/models/router.d.ts +96 -0
- package/dist/models/router.d.ts.map +1 -0
- package/dist/models/router.js +523 -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 +232 -0
- package/dist/models/types.js.map +1 -0
- package/dist/models/unified-router.d.ts +152 -0
- package/dist/models/unified-router.d.ts.map +1 -0
- package/dist/models/unified-router.js +313 -0
- package/dist/models/unified-router.js.map +1 -0
- package/dist/policies/convert-policy-to-claude.d.ts +3 -0
- package/dist/policies/convert-policy-to-claude.d.ts.map +1 -0
- package/dist/policies/convert-policy-to-claude.js +87 -0
- package/dist/policies/convert-policy-to-claude.js.map +1 -0
- package/dist/policies/database-manager.d.ts +27 -0
- package/dist/policies/database-manager.d.ts.map +1 -0
- package/dist/policies/database-manager.js +198 -0
- package/dist/policies/database-manager.js.map +1 -0
- package/dist/policies/enforced-tool-router.d.ts +53 -0
- package/dist/policies/enforced-tool-router.d.ts.map +1 -0
- package/dist/policies/enforced-tool-router.js +80 -0
- package/dist/policies/enforced-tool-router.js.map +1 -0
- package/dist/policies/index.d.ts +10 -0
- package/dist/policies/index.d.ts.map +1 -0
- package/dist/policies/index.js +8 -0
- package/dist/policies/index.js.map +1 -0
- package/dist/policies/policy-gate.d.ts +59 -0
- package/dist/policies/policy-gate.d.ts.map +1 -0
- package/dist/policies/policy-gate.js +171 -0
- package/dist/policies/policy-gate.js.map +1 -0
- package/dist/policies/policy-memory.d.ts +18 -0
- package/dist/policies/policy-memory.d.ts.map +1 -0
- package/dist/policies/policy-memory.js +126 -0
- package/dist/policies/policy-memory.js.map +1 -0
- package/dist/policies/policy-tools.d.ts +11 -0
- package/dist/policies/policy-tools.d.ts.map +1 -0
- package/dist/policies/policy-tools.js +66 -0
- package/dist/policies/policy-tools.js.map +1 -0
- package/dist/policies/schemas/policy.d.ts +69 -0
- package/dist/policies/schemas/policy.d.ts.map +1 -0
- package/dist/policies/schemas/policy.js +31 -0
- package/dist/policies/schemas/policy.js.map +1 -0
- package/dist/tasks/coordination.d.ts +83 -0
- package/dist/tasks/coordination.d.ts.map +1 -0
- package/dist/tasks/coordination.js +291 -0
- package/dist/tasks/coordination.js.map +1 -0
- package/dist/tasks/database.d.ts +19 -0
- package/dist/tasks/database.d.ts.map +1 -0
- package/dist/tasks/database.js +149 -0
- package/dist/tasks/database.js.map +1 -0
- package/dist/tasks/decoder-gate.d.ts +64 -0
- package/dist/tasks/decoder-gate.d.ts.map +1 -0
- package/dist/tasks/decoder-gate.js +268 -0
- package/dist/tasks/decoder-gate.js.map +1 -0
- package/dist/tasks/index.d.ts +6 -0
- package/dist/tasks/index.d.ts.map +1 -0
- package/dist/tasks/index.js +6 -0
- package/dist/tasks/index.js.map +1 -0
- package/dist/tasks/service.d.ts +40 -0
- package/dist/tasks/service.d.ts.map +1 -0
- package/dist/tasks/service.js +671 -0
- package/dist/tasks/service.js.map +1 -0
- package/dist/tasks/types.d.ts +238 -0
- package/dist/tasks/types.d.ts.map +1 -0
- package/dist/tasks/types.js +74 -0
- package/dist/tasks/types.js.map +1 -0
- package/dist/telemetry/index.d.ts +2 -0
- package/dist/telemetry/index.d.ts.map +1 -0
- package/dist/telemetry/index.js +2 -0
- package/dist/telemetry/index.js.map +1 -0
- package/dist/telemetry/session-telemetry.d.ts +56 -0
- package/dist/telemetry/session-telemetry.d.ts.map +1 -0
- package/dist/telemetry/session-telemetry.js +807 -0
- package/dist/telemetry/session-telemetry.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 +3324 -0
- package/dist/types/config.d.ts.map +1 -0
- package/dist/types/config.js +418 -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/uap-droids-strict.d.ts +59 -0
- package/dist/uap-droids-strict.d.ts.map +1 -0
- package/dist/uap-droids-strict.js +200 -0
- package/dist/uap-droids-strict.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/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/rate-limiter.d.ts +58 -0
- package/dist/utils/rate-limiter.d.ts.map +1 -0
- package/dist/utils/rate-limiter.js +100 -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 +94 -0
- package/dist/utils/validate-json.js.map +1 -0
- package/docs/INDEX.md +66 -0
- package/docs/architecture/MULTI_MODEL.md +224 -0
- package/docs/architecture/SYSTEM_ANALYSIS.md +1117 -0
- package/docs/architecture/UAP_COMPLIANCE.md +217 -0
- package/docs/architecture/UAP_PROTOCOL.md +339 -0
- package/docs/architecture/UAP_STRICT_DROIDS.md +172 -0
- package/docs/archive/BALLS_MODE_SELF_ANALYSIS.md +260 -0
- package/docs/archive/FAILING_TASKS_SOLUTION_PLAN.md +668 -0
- package/docs/archive/JINJA2-SYSTEM-MESSAGE-FIX.md +209 -0
- package/docs/archive/NPM-PUBLISH-V0.9.1.md +240 -0
- package/docs/archive/OPTIMIZATION_OPTIONS.md +334 -0
- package/docs/archive/SETUP_IMPROVEMENTS.md +213 -0
- package/docs/archive/UAP_GENERIC_OPTIMIZATION_PLAN.md +270 -0
- package/docs/archive/UAP_V103_PATTERN_DESIGN.md +315 -0
- package/docs/archive/UAP_V104_COMPLIANCE_DESIGN.md +223 -0
- package/docs/archive/changelog/2026-03-10_uap-100-compliance.md +77 -0
- package/docs/archive/changelog/2026-03-10_uap-full-system-verification.md +109 -0
- package/docs/benchmarks/ACCURACY_ANALYSIS.md +471 -0
- package/docs/benchmarks/TOKEN_OPTIMIZATION.md +572 -0
- package/docs/benchmarks/VALIDATION_PLAN.md +568 -0
- package/docs/benchmarks/VALIDATION_RESULTS.md +161 -0
- package/docs/deployment/DEPLOYMENT.md +895 -0
- package/docs/deployment/DEPLOYMENT_STRATEGIES.md +518 -0
- package/docs/deployment/DEPLOY_BATCHER_ANALYSIS.md +856 -0
- package/docs/deployment/DEPLOY_BATCHING.md +273 -0
- package/docs/deployment/DEPLOY_BUCKETING_ANALYSIS.md +420 -0
- package/docs/deployment/QWEN35_LLAMA_CPP.md +265 -0
- package/docs/getting-started/INTEGRATION.md +449 -0
- package/docs/getting-started/OVERVIEW.md +344 -0
- package/docs/getting-started/SETUP.md +203 -0
- package/docs/integrations/MCP_ROUTER_SETUP.md +445 -0
- package/docs/integrations/RTK_INTEGRATION.md +468 -0
- package/docs/operations/TROUBLESHOOTING.md +660 -0
- package/docs/reference/API_REFERENCE.md +903 -0
- package/docs/reference/FEATURES.md +472 -0
- package/docs/reference/HARNESS-MATRIX.md +318 -0
- package/docs/reference/UAP_CLI_REFERENCE.md +600 -0
- package/docs/research/BEHAVIORAL_PATTERNS.md +228 -0
- package/docs/research/DOMAIN_STRATEGIES.md +316 -0
- package/docs/research/MEMORY_SYSTEMS_COMPARISON.md +812 -0
- package/docs/research/PATTERN_ANALYSIS_2026-01-18.md +436 -0
- package/docs/research/PERFORMANCE_ANALYSIS_2026-01-18.md +209 -0
- package/docs/research/PERFORMANCE_TEST_PLAN.md +383 -0
- package/docs/research/TERMINAL_BENCH_LEARNINGS.md +217 -0
- package/package.json +113 -0
- package/scripts/README.md +161 -0
- package/templates/CLAUDE.template.md +10 -0
- package/templates/CLAUDE_ARCHITECTURE.template.md +103 -0
- package/templates/CLAUDE_CODING.template.md +127 -0
- package/templates/CLAUDE_DROIDS.template.md +109 -0
- package/templates/CLAUDE_MEMORY.template.md +131 -0
- package/templates/CLAUDE_WORKFLOWS.template.md +139 -0
- package/templates/PROJECT.template.md +209 -0
- package/templates/SCHEMA.md +57 -0
- package/templates/archive/CLAUDE.template.root-v6.md +534 -0
- package/templates/archive/CLAUDE.template.v6.md +534 -0
- package/templates/hooks/forgecode/pre-compact.sh +68 -0
- package/templates/hooks/forgecode/session-start.sh +169 -0
- package/templates/hooks/forgecode.plugin.sh +128 -0
- package/templates/hooks/pre-compact.sh +74 -0
- package/templates/hooks/session-start.sh +366 -0
- package/tools/agents/README.md +224 -0
- package/tools/agents/UAP/README.md +386 -0
- package/tools/agents/UAP/__init__.py +9 -0
- package/tools/agents/UAP/cli.py +901 -0
- package/tools/agents/UAP/compliance_verify.sh +108 -0
- package/tools/agents/UAP/full_verification.sh +126 -0
- package/tools/agents/UAP/version.py +32 -0
- package/tools/agents/benchmarks/benchmark_memory_systems.py +730 -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 +77 -0
- package/tools/agents/config/tool-call-schema.json +19 -0
- package/tools/agents/config/tool-call.gbnf +58 -0
- package/tools/agents/docker/Dockerfile.python +52 -0
- package/tools/agents/docker/Dockerfile.ubuntu +55 -0
- package/tools/agents/docker-compose.qdrant.yml +24 -0
- package/tools/agents/install-opencode-local.sh.j2 +135 -0
- package/tools/agents/migrations/apply.py +256 -0
- package/tools/agents/opencode_uap_agent.py +1505 -0
- package/tools/agents/plugin/README.md +91 -0
- package/tools/agents/plugin/index.ts +46 -0
- package/tools/agents/plugin/pre-compact.sh +68 -0
- package/tools/agents/plugin/session-start.sh +175 -0
- package/tools/agents/plugin/uap-commands.ts +45 -0
- package/tools/agents/plugin/uap-droids.ts +54 -0
- package/tools/agents/plugin/uap-patterns.ts +54 -0
- package/tools/agents/plugin/uap-skills.ts +52 -0
- package/tools/agents/plugins/uap-enforce.ts +314 -0
- package/tools/agents/scripts/__pycache__/tool_call_wrapper.cpython-313.pyc +0 -0
- package/tools/agents/scripts/chat_template_verifier.py +343 -0
- package/tools/agents/scripts/fix-qwen-template.js +38 -0
- package/tools/agents/scripts/fix_qwen_chat_template.py +316 -0
- package/tools/agents/scripts/generate_lora_training_data.py +412 -0
- package/tools/agents/scripts/init_qdrant.py +151 -0
- package/tools/agents/scripts/memory_migration.py +560 -0
- package/tools/agents/scripts/migrate_memory_to_qdrant.py +110 -0
- package/tools/agents/scripts/prepare_lora.sh +512 -0
- package/tools/agents/scripts/query_memory.py +200 -0
- package/tools/agents/scripts/qwen-tool-call-test.js +38 -0
- package/tools/agents/scripts/qwen-tool-call-wrapper.js +38 -0
- package/tools/agents/scripts/qwen_tool_call_test.py +464 -0
- package/tools/agents/scripts/qwen_tool_call_wrapper.py +686 -0
- package/tools/agents/scripts/start-services.sh +96 -0
- package/tools/agents/scripts/tool-choice-proxy.cjs +296 -0
- package/tools/agents/scripts/tool_call_test.py +656 -0
- package/tools/agents/scripts/tool_call_wrapper.py +799 -0
- package/tools/agents/tests/test_uap_compliance.py +257 -0
- package/tools/agents/uap_agent.py +122 -0
- package/tools/agents/uap_agent_install.sh +12 -0
|
@@ -0,0 +1,862 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import ora from 'ora';
|
|
3
|
+
import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'fs';
|
|
4
|
+
import { join, dirname } from 'path';
|
|
5
|
+
import { execSync, execFileSync } from 'child_process';
|
|
6
|
+
import { QdrantClient } from '@qdrant/js-client-rest';
|
|
7
|
+
import { AgentContextConfigSchema } from '../types/index.js';
|
|
8
|
+
/**
|
|
9
|
+
* Load .uap.json config from the current working directory.
|
|
10
|
+
*/
|
|
11
|
+
function loadConfig(cwd) {
|
|
12
|
+
const configPath = join(cwd, '.uap.json');
|
|
13
|
+
if (!existsSync(configPath)) {
|
|
14
|
+
console.log(chalk.red(' No .uap.json found. Run `uap init` first.'));
|
|
15
|
+
return null;
|
|
16
|
+
}
|
|
17
|
+
const raw = JSON.parse(readFileSync(configPath, 'utf-8'));
|
|
18
|
+
return AgentContextConfigSchema.parse(raw);
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Get pattern RAG settings from config, with defaults.
|
|
22
|
+
*/
|
|
23
|
+
function getPatternRagConfig(config) {
|
|
24
|
+
return {
|
|
25
|
+
enabled: config.memory?.patternRag?.enabled ?? false,
|
|
26
|
+
collection: config.memory?.patternRag?.collection ?? 'agent_patterns',
|
|
27
|
+
embeddingModel: config.memory?.patternRag?.embeddingModel ?? 'all-MiniLM-L6-v2',
|
|
28
|
+
vectorSize: config.memory?.patternRag?.vectorSize ?? 384,
|
|
29
|
+
scoreThreshold: config.memory?.patternRag?.scoreThreshold ?? 0.35,
|
|
30
|
+
topK: config.memory?.patternRag?.topK ?? 2,
|
|
31
|
+
indexScript: config.memory?.patternRag?.indexScript ?? './agents/scripts/index_patterns_to_qdrant.py',
|
|
32
|
+
queryScript: config.memory?.patternRag?.queryScript ?? './agents/scripts/query_patterns.py',
|
|
33
|
+
sourceFile: config.memory?.patternRag?.sourceFile ?? 'CLAUDE.md',
|
|
34
|
+
sourceFiles: config.memory?.patternRag?.sourceFiles ?? [],
|
|
35
|
+
skillsDir: config.memory?.patternRag?.skillsDir,
|
|
36
|
+
maxBodyChars: config.memory?.patternRag?.maxBodyChars ?? 400,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Resolve the Qdrant endpoint from config.
|
|
41
|
+
*/
|
|
42
|
+
function getQdrantEndpoint(config) {
|
|
43
|
+
const endpoint = config.memory?.longTerm?.endpoint || 'localhost:6333';
|
|
44
|
+
return endpoint.startsWith('http://') || endpoint.startsWith('https://')
|
|
45
|
+
? endpoint
|
|
46
|
+
: `http://${endpoint}`;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Find a working Python with sentence-transformers available.
|
|
50
|
+
*/
|
|
51
|
+
export function findPython(cwd) {
|
|
52
|
+
const candidates = [
|
|
53
|
+
join(cwd, 'agents', '.venv', 'bin', 'python'),
|
|
54
|
+
join(cwd, '.venv', 'bin', 'python'),
|
|
55
|
+
'python3',
|
|
56
|
+
'python',
|
|
57
|
+
];
|
|
58
|
+
for (const py of candidates) {
|
|
59
|
+
try {
|
|
60
|
+
execSync(`${py} -c "import sentence_transformers" 2>/dev/null`, { cwd, stdio: 'pipe' });
|
|
61
|
+
return py;
|
|
62
|
+
}
|
|
63
|
+
catch {
|
|
64
|
+
// Try next candidate
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Bootstrap a Python venv at agents/.venv with sentence-transformers + qdrant-client.
|
|
71
|
+
* Returns the python binary path on success, null on failure.
|
|
72
|
+
* Best-effort: doesn't throw.
|
|
73
|
+
*/
|
|
74
|
+
export function ensurePythonVenv(cwd) {
|
|
75
|
+
const venvDir = join(cwd, 'agents', '.venv');
|
|
76
|
+
const venvPython = join(venvDir, 'bin', 'python');
|
|
77
|
+
// If venv already has the deps, return immediately
|
|
78
|
+
try {
|
|
79
|
+
execSync(`${venvPython} -c "import sentence_transformers; import qdrant_client"`, {
|
|
80
|
+
cwd,
|
|
81
|
+
stdio: 'pipe',
|
|
82
|
+
});
|
|
83
|
+
return venvPython;
|
|
84
|
+
}
|
|
85
|
+
catch {
|
|
86
|
+
// Need to create or install deps
|
|
87
|
+
}
|
|
88
|
+
// Find a system python3 to create the venv
|
|
89
|
+
let systemPython = null;
|
|
90
|
+
for (const candidate of ['python3', 'python']) {
|
|
91
|
+
try {
|
|
92
|
+
execSync(`${candidate} --version`, { stdio: 'pipe' });
|
|
93
|
+
systemPython = candidate;
|
|
94
|
+
break;
|
|
95
|
+
}
|
|
96
|
+
catch {
|
|
97
|
+
// try next
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
if (!systemPython)
|
|
101
|
+
return null;
|
|
102
|
+
try {
|
|
103
|
+
// Create venv if it doesn't exist
|
|
104
|
+
if (!existsSync(venvPython)) {
|
|
105
|
+
execSync(`${systemPython} -m venv ${venvDir}`, { cwd, stdio: 'pipe', timeout: 30000 });
|
|
106
|
+
}
|
|
107
|
+
// Install deps (uses hardcoded package names, no user input)
|
|
108
|
+
execSync(`${venvPython} -m pip install --quiet sentence-transformers qdrant-client`, {
|
|
109
|
+
cwd,
|
|
110
|
+
stdio: 'pipe',
|
|
111
|
+
timeout: 300000, // 5 min for large deps
|
|
112
|
+
});
|
|
113
|
+
return venvPython;
|
|
114
|
+
}
|
|
115
|
+
catch {
|
|
116
|
+
return null;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
export async function patternsCommand(action, options = {}) {
|
|
120
|
+
const cwd = process.cwd();
|
|
121
|
+
switch (action) {
|
|
122
|
+
case 'status':
|
|
123
|
+
await showPatternStatus(cwd);
|
|
124
|
+
break;
|
|
125
|
+
case 'index':
|
|
126
|
+
await indexPatterns(cwd, options);
|
|
127
|
+
break;
|
|
128
|
+
case 'query':
|
|
129
|
+
await queryPatterns(cwd, options);
|
|
130
|
+
break;
|
|
131
|
+
case 'generate':
|
|
132
|
+
await generateScripts(cwd, options);
|
|
133
|
+
break;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Show pattern RAG status: collection info, pattern count, last indexed.
|
|
138
|
+
*/
|
|
139
|
+
async function showPatternStatus(cwd) {
|
|
140
|
+
console.log(chalk.bold('\n=== Pattern RAG Status ===\n'));
|
|
141
|
+
const config = loadConfig(cwd);
|
|
142
|
+
if (!config)
|
|
143
|
+
return;
|
|
144
|
+
const rag = getPatternRagConfig(config);
|
|
145
|
+
console.log(` ${chalk.dim('Enabled:')} ${rag.enabled ? chalk.green('yes') : chalk.yellow('no')}`);
|
|
146
|
+
console.log(` ${chalk.dim('Collection:')} ${rag.collection}`);
|
|
147
|
+
console.log(` ${chalk.dim('Embedding:')} ${rag.embeddingModel}`);
|
|
148
|
+
console.log(` ${chalk.dim('Score Threshold:')} ${rag.scoreThreshold}`);
|
|
149
|
+
console.log(` ${chalk.dim('Top-K:')} ${rag.topK}`);
|
|
150
|
+
console.log(` ${chalk.dim('Source:')} ${rag.sourceFile}`);
|
|
151
|
+
console.log('');
|
|
152
|
+
// Check Qdrant collection
|
|
153
|
+
const url = getQdrantEndpoint(config);
|
|
154
|
+
try {
|
|
155
|
+
const client = new QdrantClient({ url });
|
|
156
|
+
const collections = await client.getCollections();
|
|
157
|
+
const found = collections.collections.find((c) => c.name === rag.collection);
|
|
158
|
+
if (found) {
|
|
159
|
+
const info = await client.getCollection(rag.collection);
|
|
160
|
+
console.log(chalk.green(` Qdrant collection '${rag.collection}':`));
|
|
161
|
+
console.log(` Points: ${info.points_count ?? 'unknown'}`);
|
|
162
|
+
console.log(` Indexed: ${info.indexed_vectors_count ?? 'unknown'}`);
|
|
163
|
+
console.log(` Status: ${info.status}`);
|
|
164
|
+
}
|
|
165
|
+
else {
|
|
166
|
+
console.log(chalk.yellow(` Collection '${rag.collection}' not found.`));
|
|
167
|
+
console.log(chalk.dim(' Run `uap patterns index` to create it.'));
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
catch {
|
|
171
|
+
console.log(chalk.dim(' Qdrant not available. Run `uap memory start` first.'));
|
|
172
|
+
}
|
|
173
|
+
// Check Python + scripts
|
|
174
|
+
const python = findPython(cwd);
|
|
175
|
+
console.log('');
|
|
176
|
+
console.log(` ${chalk.dim('Python:')} ${python ? chalk.green(python) : chalk.red('not found')}`);
|
|
177
|
+
console.log(` ${chalk.dim('Index script:')} ${existsSync(join(cwd, rag.indexScript)) ? chalk.green('found') : chalk.yellow('missing')}`);
|
|
178
|
+
console.log(` ${chalk.dim('Query script:')} ${existsSync(join(cwd, rag.queryScript)) ? chalk.green('found') : chalk.yellow('missing')}`);
|
|
179
|
+
console.log('');
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Index patterns from CLAUDE.md into the Qdrant collection.
|
|
183
|
+
* Uses the Python index script if available.
|
|
184
|
+
*/
|
|
185
|
+
async function indexPatterns(cwd, options) {
|
|
186
|
+
const config = loadConfig(cwd);
|
|
187
|
+
if (!config)
|
|
188
|
+
return;
|
|
189
|
+
const rag = getPatternRagConfig(config);
|
|
190
|
+
const spinner = ora('Indexing patterns...').start();
|
|
191
|
+
// Prefer the Python script if it exists
|
|
192
|
+
const scriptPath = join(cwd, rag.indexScript);
|
|
193
|
+
if (existsSync(scriptPath)) {
|
|
194
|
+
const python = findPython(cwd);
|
|
195
|
+
if (!python) {
|
|
196
|
+
spinner.fail('Python with sentence-transformers not found.');
|
|
197
|
+
console.log(chalk.dim(' Install: pip install sentence-transformers qdrant-client'));
|
|
198
|
+
console.log(chalk.dim(' Or create venv: python3 -m venv agents/.venv && agents/.venv/bin/pip install sentence-transformers qdrant-client'));
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
try {
|
|
202
|
+
const output = execFileSync(python, [scriptPath], {
|
|
203
|
+
cwd,
|
|
204
|
+
encoding: 'utf-8',
|
|
205
|
+
timeout: 120000,
|
|
206
|
+
});
|
|
207
|
+
spinner.succeed('Patterns indexed successfully.');
|
|
208
|
+
if (options.verbose) {
|
|
209
|
+
console.log(chalk.dim(output));
|
|
210
|
+
}
|
|
211
|
+
else {
|
|
212
|
+
// Extract summary line
|
|
213
|
+
const summaryMatch = output.match(/Total: (\d+) documents/);
|
|
214
|
+
if (summaryMatch) {
|
|
215
|
+
console.log(chalk.green(` ${summaryMatch[0]}`));
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
catch (err) {
|
|
220
|
+
spinner.fail('Pattern indexing failed.');
|
|
221
|
+
if (err instanceof Error) {
|
|
222
|
+
console.log(chalk.red(` ${err.message.split('\n').slice(0, 3).join('\n ')}`));
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
return;
|
|
226
|
+
}
|
|
227
|
+
// No script found - offer to generate
|
|
228
|
+
spinner.warn('Index script not found.');
|
|
229
|
+
console.log(chalk.dim(` Expected: ${rag.indexScript}`));
|
|
230
|
+
console.log(chalk.dim(' Run `uap patterns generate` to create the scripts.'));
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* Query patterns from the Qdrant collection.
|
|
234
|
+
* Uses the Python query script for real semantic embeddings.
|
|
235
|
+
*/
|
|
236
|
+
async function queryPatterns(cwd, options) {
|
|
237
|
+
const search = options.search;
|
|
238
|
+
if (!search) {
|
|
239
|
+
console.log(chalk.red(' Search term required. Usage: uap patterns query <search>'));
|
|
240
|
+
return;
|
|
241
|
+
}
|
|
242
|
+
const config = loadConfig(cwd);
|
|
243
|
+
if (!config)
|
|
244
|
+
return;
|
|
245
|
+
const rag = getPatternRagConfig(config);
|
|
246
|
+
const topK = parseInt(options.top || String(rag.topK));
|
|
247
|
+
const minScore = parseFloat(options.minScore || String(rag.scoreThreshold));
|
|
248
|
+
const format = options.format || 'text';
|
|
249
|
+
// Prefer Python script for real embeddings
|
|
250
|
+
const scriptPath = join(cwd, rag.queryScript);
|
|
251
|
+
if (existsSync(scriptPath)) {
|
|
252
|
+
const python = findPython(cwd);
|
|
253
|
+
if (!python) {
|
|
254
|
+
console.log(chalk.red(' Python with sentence-transformers not found.'));
|
|
255
|
+
return;
|
|
256
|
+
}
|
|
257
|
+
try {
|
|
258
|
+
const output = execFileSync(python, [
|
|
259
|
+
scriptPath,
|
|
260
|
+
search,
|
|
261
|
+
'--top',
|
|
262
|
+
String(topK),
|
|
263
|
+
'--min-score',
|
|
264
|
+
String(minScore),
|
|
265
|
+
'--format',
|
|
266
|
+
format,
|
|
267
|
+
], { cwd, encoding: 'utf-8', timeout: 30000 });
|
|
268
|
+
if (format === 'json') {
|
|
269
|
+
// Parse and pretty-print
|
|
270
|
+
const patterns = JSON.parse(output);
|
|
271
|
+
if (patterns.length === 0) {
|
|
272
|
+
console.log(chalk.yellow(' No matching patterns found.'));
|
|
273
|
+
return;
|
|
274
|
+
}
|
|
275
|
+
for (const p of patterns) {
|
|
276
|
+
const abbr = p.abbreviation ? ` (${p.abbreviation})` : '';
|
|
277
|
+
console.log(`\n ${chalk.green(`[${p.score.toFixed(3)}]`)} ${chalk.bold(`P${p.id}: ${p.title}${abbr}`)}`);
|
|
278
|
+
console.log(` ${chalk.dim(p.body.slice(0, rag.maxBodyChars))}${p.body.length > rag.maxBodyChars ? '...' : ''}`);
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
else {
|
|
282
|
+
console.log(output);
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
catch (err) {
|
|
286
|
+
if (err instanceof Error && err.message.includes('Connection refused')) {
|
|
287
|
+
console.log(chalk.dim(' Qdrant not available. Run `uap memory start` first.'));
|
|
288
|
+
}
|
|
289
|
+
else {
|
|
290
|
+
console.log(chalk.red(' Pattern query failed.'));
|
|
291
|
+
if (err instanceof Error) {
|
|
292
|
+
console.log(chalk.dim(` ${err.message.split('\n').slice(0, 2).join('\n ')}`));
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
return;
|
|
297
|
+
}
|
|
298
|
+
// Fallback: direct Qdrant query with keyword matching
|
|
299
|
+
console.log(chalk.yellow(' Query script not found. Using fallback keyword search (less accurate).'));
|
|
300
|
+
console.log(chalk.dim(` For semantic search, run \`uap patterns generate\` to create the Python scripts.\n`));
|
|
301
|
+
try {
|
|
302
|
+
const url = getQdrantEndpoint(config);
|
|
303
|
+
const client = new QdrantClient({ url });
|
|
304
|
+
const collections = await client.getCollections();
|
|
305
|
+
const found = collections.collections.some((c) => c.name === rag.collection);
|
|
306
|
+
if (!found) {
|
|
307
|
+
console.log(chalk.yellow(` Collection '${rag.collection}' not found.`));
|
|
308
|
+
console.log(chalk.dim(' Run `uap patterns index` first.'));
|
|
309
|
+
return;
|
|
310
|
+
}
|
|
311
|
+
// Scroll through all points and do keyword matching as fallback
|
|
312
|
+
const result = await client.scroll(rag.collection, { limit: 100, with_payload: true });
|
|
313
|
+
const keywords = search.toLowerCase().split(/\s+/);
|
|
314
|
+
const matches = result.points
|
|
315
|
+
.map((p) => {
|
|
316
|
+
const payload = p.payload;
|
|
317
|
+
const title = String(payload.title || '').toLowerCase();
|
|
318
|
+
const body = String(payload.body || '').toLowerCase();
|
|
319
|
+
const kws = payload.keywords || [];
|
|
320
|
+
let score = 0;
|
|
321
|
+
for (const kw of keywords) {
|
|
322
|
+
if (title.includes(kw))
|
|
323
|
+
score += 2;
|
|
324
|
+
if (body.includes(kw))
|
|
325
|
+
score += 1;
|
|
326
|
+
if (kws.some((k) => k.includes(kw)))
|
|
327
|
+
score += 1.5;
|
|
328
|
+
}
|
|
329
|
+
return {
|
|
330
|
+
id: p.id,
|
|
331
|
+
title: payload.title,
|
|
332
|
+
body: payload.body,
|
|
333
|
+
abbreviation: payload.abbreviation,
|
|
334
|
+
score,
|
|
335
|
+
};
|
|
336
|
+
})
|
|
337
|
+
.filter((m) => m.score > 0)
|
|
338
|
+
.sort((a, b) => b.score - a.score)
|
|
339
|
+
.slice(0, topK);
|
|
340
|
+
if (matches.length === 0) {
|
|
341
|
+
console.log(chalk.yellow(' No matching patterns found.'));
|
|
342
|
+
return;
|
|
343
|
+
}
|
|
344
|
+
for (const m of matches) {
|
|
345
|
+
const abbr = m.abbreviation ? ` (${m.abbreviation})` : '';
|
|
346
|
+
console.log(`\n ${chalk.green(`[${m.score.toFixed(1)}]`)} ${chalk.bold(`P${m.id}: ${m.title}${abbr}`)}`);
|
|
347
|
+
const body = String(m.body || '');
|
|
348
|
+
console.log(` ${chalk.dim(body.slice(0, rag.maxBodyChars))}${body.length > rag.maxBodyChars ? '...' : ''}`);
|
|
349
|
+
}
|
|
350
|
+
console.log('');
|
|
351
|
+
}
|
|
352
|
+
catch {
|
|
353
|
+
console.log(chalk.dim(' Qdrant not available. Run `uap memory start` first.'));
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
/**
|
|
357
|
+
* Generate the Python index/query scripts for pattern RAG.
|
|
358
|
+
*/
|
|
359
|
+
export async function generateScripts(cwd, options = {}) {
|
|
360
|
+
const config = loadConfig(cwd);
|
|
361
|
+
if (!config)
|
|
362
|
+
return;
|
|
363
|
+
const rag = getPatternRagConfig(config);
|
|
364
|
+
const endpoint = config.memory?.longTerm?.endpoint || 'localhost:6333';
|
|
365
|
+
const endpointUrl = endpoint.startsWith('http')
|
|
366
|
+
? new URL(endpoint)
|
|
367
|
+
: new URL(`http://${endpoint}`);
|
|
368
|
+
const host = endpointUrl.hostname;
|
|
369
|
+
const port = parseInt(endpointUrl.port) || 6333;
|
|
370
|
+
// Generate index script
|
|
371
|
+
const indexPath = join(cwd, rag.indexScript);
|
|
372
|
+
const indexDir = dirname(indexPath);
|
|
373
|
+
if (!existsSync(indexDir)) {
|
|
374
|
+
mkdirSync(indexDir, { recursive: true });
|
|
375
|
+
}
|
|
376
|
+
if (existsSync(indexPath) && !options.force) {
|
|
377
|
+
console.log(chalk.yellow(` Index script already exists: ${rag.indexScript}`));
|
|
378
|
+
console.log(chalk.dim(' Use --force to overwrite.'));
|
|
379
|
+
}
|
|
380
|
+
else {
|
|
381
|
+
writeFileSync(indexPath, generateIndexScript(rag, host, port));
|
|
382
|
+
execFileSync('chmod', ['+x', indexPath]);
|
|
383
|
+
console.log(chalk.green(` Created: ${rag.indexScript}`));
|
|
384
|
+
}
|
|
385
|
+
// Generate query script
|
|
386
|
+
const queryPath = join(cwd, rag.queryScript);
|
|
387
|
+
const queryDir = dirname(queryPath);
|
|
388
|
+
if (!existsSync(queryDir)) {
|
|
389
|
+
mkdirSync(queryDir, { recursive: true });
|
|
390
|
+
}
|
|
391
|
+
if (existsSync(queryPath) && !options.force) {
|
|
392
|
+
console.log(chalk.yellow(` Query script already exists: ${rag.queryScript}`));
|
|
393
|
+
console.log(chalk.dim(' Use --force to overwrite.'));
|
|
394
|
+
}
|
|
395
|
+
else {
|
|
396
|
+
writeFileSync(queryPath, generateQueryScript(rag, host, port));
|
|
397
|
+
execFileSync('chmod', ['+x', queryPath]);
|
|
398
|
+
console.log(chalk.green(` Created: ${rag.queryScript}`));
|
|
399
|
+
}
|
|
400
|
+
console.log(chalk.dim('\n Install Python deps: pip install sentence-transformers qdrant-client'));
|
|
401
|
+
}
|
|
402
|
+
function generateIndexScript(rag, host, port) {
|
|
403
|
+
// Build the list of additional source files for the Python script
|
|
404
|
+
const sourceFilesJson = JSON.stringify(rag.sourceFiles || []);
|
|
405
|
+
const skillsDirValue = rag.skillsDir ? `"${rag.skillsDir}"` : 'None';
|
|
406
|
+
return `#!/usr/bin/env python3
|
|
407
|
+
"""
|
|
408
|
+
Extract knowledge from project documentation and index into Qdrant.
|
|
409
|
+
|
|
410
|
+
Scans multiple sources:
|
|
411
|
+
1. CLAUDE.md (with @include resolution)
|
|
412
|
+
2. AGENTS.md and other configured source files
|
|
413
|
+
3. .claude/skills/*/SKILL.md (skill files)
|
|
414
|
+
|
|
415
|
+
Creates/updates the '${rag.collection}' collection with embeddings from
|
|
416
|
+
${rag.embeddingModel} for on-demand retrieval by the Pattern RAG system.
|
|
417
|
+
|
|
418
|
+
Generated by: uap patterns generate (v0.8.1+)
|
|
419
|
+
"""
|
|
420
|
+
|
|
421
|
+
import re
|
|
422
|
+
import sys
|
|
423
|
+
import hashlib
|
|
424
|
+
from pathlib import Path
|
|
425
|
+
from datetime import datetime, timezone
|
|
426
|
+
from typing import Optional
|
|
427
|
+
|
|
428
|
+
from sentence_transformers import SentenceTransformer
|
|
429
|
+
from qdrant_client import QdrantClient
|
|
430
|
+
from qdrant_client.models import Distance, VectorParams, PointStruct
|
|
431
|
+
|
|
432
|
+
PROJECT_ROOT = Path(__file__).resolve().parents[2]
|
|
433
|
+
PRIMARY_SOURCE = PROJECT_ROOT / "${rag.sourceFile}"
|
|
434
|
+
ADDITIONAL_SOURCES = ${sourceFilesJson}
|
|
435
|
+
SKILLS_DIR: Optional[str] = ${skillsDirValue}
|
|
436
|
+
QDRANT_HOST = "${host}"
|
|
437
|
+
QDRANT_PORT = ${port}
|
|
438
|
+
COLLECTION_NAME = "${rag.collection}"
|
|
439
|
+
EMBEDDING_MODEL = "${rag.embeddingModel}"
|
|
440
|
+
VECTOR_SIZE = ${rag.vectorSize}
|
|
441
|
+
MAX_BODY_CHARS = 2000
|
|
442
|
+
|
|
443
|
+
|
|
444
|
+
def resolve_includes(text: str, base_dir: Path) -> str:
|
|
445
|
+
"""Resolve @include directives (e.g. @hooks-session-start.md)."""
|
|
446
|
+
def replace_include(match):
|
|
447
|
+
filename = match.group(1).strip()
|
|
448
|
+
# Search common locations
|
|
449
|
+
candidates = [
|
|
450
|
+
base_dir / filename,
|
|
451
|
+
base_dir / ".claude" / "hooks" / filename,
|
|
452
|
+
base_dir / ".claude" / filename,
|
|
453
|
+
base_dir / "docs" / filename,
|
|
454
|
+
]
|
|
455
|
+
for candidate in candidates:
|
|
456
|
+
if candidate.exists():
|
|
457
|
+
return candidate.read_text()
|
|
458
|
+
return match.group(0) # Keep original if not found
|
|
459
|
+
|
|
460
|
+
return re.sub(r"^@(\\S+\\.md)$", replace_include, text, flags=re.MULTILINE)
|
|
461
|
+
|
|
462
|
+
|
|
463
|
+
def extract_numbered_patterns(text: str) -> list[dict]:
|
|
464
|
+
"""Extract '### Pattern N: Title' blocks (legacy format)."""
|
|
465
|
+
patterns = []
|
|
466
|
+
pattern_regex = re.compile(
|
|
467
|
+
r"### Pattern (\\d+): (.+?)(?:\\s*\\((\\w+)\\))?\\n(.*?)(?=\\n### Pattern \\d+:|\\n## |\\n---|\\Z)",
|
|
468
|
+
re.DOTALL,
|
|
469
|
+
)
|
|
470
|
+
for match in pattern_regex.finditer(text):
|
|
471
|
+
number = int(match.group(1))
|
|
472
|
+
title = match.group(2).strip()
|
|
473
|
+
abbreviation = match.group(3) or ""
|
|
474
|
+
body = match.group(4).strip()
|
|
475
|
+
if len(body) > MAX_BODY_CHARS:
|
|
476
|
+
body = body[:MAX_BODY_CHARS] + "\\n... (truncated)"
|
|
477
|
+
patterns.append({
|
|
478
|
+
"title": title, "abbreviation": abbreviation,
|
|
479
|
+
"category": "pattern", "source": "CLAUDE.md",
|
|
480
|
+
"keywords": list(set(title.lower().split())),
|
|
481
|
+
"body": body,
|
|
482
|
+
"content_hash": hashlib.md5(body.encode()).hexdigest(),
|
|
483
|
+
})
|
|
484
|
+
return patterns
|
|
485
|
+
|
|
486
|
+
|
|
487
|
+
def extract_sections(text: str, source_name: str) -> list[dict]:
|
|
488
|
+
"""Extract ## and ### heading sections from any markdown file."""
|
|
489
|
+
sections = []
|
|
490
|
+
# Split on ## headings (level 2 and 3)
|
|
491
|
+
heading_regex = re.compile(r"^(#{2,3})\\s+(.+)$", re.MULTILINE)
|
|
492
|
+
matches = list(heading_regex.finditer(text))
|
|
493
|
+
|
|
494
|
+
for i, match in enumerate(matches):
|
|
495
|
+
level = len(match.group(1))
|
|
496
|
+
title = match.group(2).strip()
|
|
497
|
+
|
|
498
|
+
# Skip HTML comments, empty titles, very short titles
|
|
499
|
+
if title.startswith("<!--") or len(title) < 3:
|
|
500
|
+
continue
|
|
501
|
+
|
|
502
|
+
# Get body until next heading of same or higher level
|
|
503
|
+
start = match.end()
|
|
504
|
+
end = matches[i + 1].start() if i + 1 < len(matches) else len(text)
|
|
505
|
+
body = text[start:end].strip()
|
|
506
|
+
|
|
507
|
+
# Skip empty or trivial sections
|
|
508
|
+
if len(body) < 20:
|
|
509
|
+
continue
|
|
510
|
+
|
|
511
|
+
if len(body) > MAX_BODY_CHARS:
|
|
512
|
+
body = body[:MAX_BODY_CHARS] + "\\n... (truncated)"
|
|
513
|
+
|
|
514
|
+
# Classify category from source name and content
|
|
515
|
+
category = classify_section(title, body, source_name)
|
|
516
|
+
|
|
517
|
+
# Build keywords from title
|
|
518
|
+
keywords = [w.lower() for w in re.findall(r"[a-zA-Z]{3,}", title)]
|
|
519
|
+
|
|
520
|
+
sections.append({
|
|
521
|
+
"title": title,
|
|
522
|
+
"abbreviation": "",
|
|
523
|
+
"category": category,
|
|
524
|
+
"source": source_name,
|
|
525
|
+
"keywords": keywords,
|
|
526
|
+
"body": body,
|
|
527
|
+
"content_hash": hashlib.md5(body.encode()).hexdigest(),
|
|
528
|
+
})
|
|
529
|
+
|
|
530
|
+
return sections
|
|
531
|
+
|
|
532
|
+
|
|
533
|
+
def classify_section(title: str, body: str, source: str) -> str:
|
|
534
|
+
"""Classify a section into a category based on content signals."""
|
|
535
|
+
t = title.lower()
|
|
536
|
+
b = body.lower()[:500]
|
|
537
|
+
|
|
538
|
+
if "skill" in source.lower():
|
|
539
|
+
return "skill"
|
|
540
|
+
if any(w in t for w in ["deploy", "kubernetes", "k8s", "cluster", "infra"]):
|
|
541
|
+
return "infrastructure"
|
|
542
|
+
if any(w in t for w in ["security", "auth", "secret", "owasp", "xss"]):
|
|
543
|
+
return "security"
|
|
544
|
+
if any(w in t for w in ["test", "coverage", "vitest", "jest"]):
|
|
545
|
+
return "testing"
|
|
546
|
+
if any(w in t for w in ["performance", "optimize", "cache", "latency"]):
|
|
547
|
+
return "performance"
|
|
548
|
+
if any(w in t for w in ["workflow", "protocol", "checklist", "process"]):
|
|
549
|
+
return "workflow"
|
|
550
|
+
if any(w in t for w in ["database", "postgres", "sql", "pgdog", "cnpg"]):
|
|
551
|
+
return "database"
|
|
552
|
+
if any(w in t for w in ["observ", "monitor", "metric", "log", "trace"]):
|
|
553
|
+
return "observability"
|
|
554
|
+
if any(w in t for w in ["design", "ui", "ux", "css", "style", "theme"]):
|
|
555
|
+
return "design"
|
|
556
|
+
if any(w in t for w in ["review", "quality", "lint", "code"]):
|
|
557
|
+
return "code-quality"
|
|
558
|
+
if "terraform" in b or "iac" in t:
|
|
559
|
+
return "infrastructure"
|
|
560
|
+
return "general"
|
|
561
|
+
|
|
562
|
+
|
|
563
|
+
def extract_skill_frontmatter(text: str) -> tuple[str, str]:
|
|
564
|
+
"""Extract name and description from YAML frontmatter."""
|
|
565
|
+
fm_match = re.match(r"^---\\n(.*?)\\n---", text, re.DOTALL)
|
|
566
|
+
if not fm_match:
|
|
567
|
+
return "", ""
|
|
568
|
+
fm = fm_match.group(1)
|
|
569
|
+
name_match = re.search(r"^name:\\s*(.+)$", fm, re.MULTILINE)
|
|
570
|
+
desc_match = re.search(r'^description:\\s*["\\'"]?(.+?)["\\'"]?\\s*$', fm, re.MULTILINE)
|
|
571
|
+
name = name_match.group(1).strip().strip('"').strip("'") if name_match else ""
|
|
572
|
+
desc = desc_match.group(1).strip().strip('"').strip("'") if desc_match else ""
|
|
573
|
+
return name, desc
|
|
574
|
+
|
|
575
|
+
|
|
576
|
+
def scan_skills(project_root: Path, skills_dir: Optional[str]) -> list[dict]:
|
|
577
|
+
"""Scan .claude/skills/*/SKILL.md files."""
|
|
578
|
+
docs = []
|
|
579
|
+
# Auto-detect skills directory
|
|
580
|
+
candidates = []
|
|
581
|
+
if skills_dir:
|
|
582
|
+
candidates.append(project_root / skills_dir)
|
|
583
|
+
candidates.extend([
|
|
584
|
+
project_root / ".claude" / "skills",
|
|
585
|
+
project_root / ".factory" / "skills",
|
|
586
|
+
])
|
|
587
|
+
|
|
588
|
+
for skills_path in candidates:
|
|
589
|
+
if not skills_path.is_dir():
|
|
590
|
+
continue
|
|
591
|
+
skill_files = sorted(skills_path.glob("*/SKILL.md"))
|
|
592
|
+
for sf in skill_files:
|
|
593
|
+
text = sf.read_text()
|
|
594
|
+
skill_name, skill_desc = extract_skill_frontmatter(text)
|
|
595
|
+
if not skill_name:
|
|
596
|
+
skill_name = sf.parent.name
|
|
597
|
+
|
|
598
|
+
# Extract sections from the skill file
|
|
599
|
+
sections = extract_sections(text, f"skill:{skill_name}")
|
|
600
|
+
|
|
601
|
+
# If no sections extracted, index the whole skill as one doc
|
|
602
|
+
if not sections and len(text.strip()) > 50:
|
|
603
|
+
body = text.strip()
|
|
604
|
+
if len(body) > MAX_BODY_CHARS:
|
|
605
|
+
body = body[:MAX_BODY_CHARS] + "\\n... (truncated)"
|
|
606
|
+
sections = [{
|
|
607
|
+
"title": skill_name,
|
|
608
|
+
"abbreviation": "",
|
|
609
|
+
"category": "skill",
|
|
610
|
+
"source": f"skill:{skill_name}",
|
|
611
|
+
"keywords": [w.lower() for w in re.findall(r"[a-zA-Z]{3,}", skill_name + " " + skill_desc)],
|
|
612
|
+
"body": body,
|
|
613
|
+
"content_hash": hashlib.md5(body.encode()).hexdigest(),
|
|
614
|
+
}]
|
|
615
|
+
|
|
616
|
+
# Add skill description as keywords to all sections
|
|
617
|
+
if skill_desc:
|
|
618
|
+
desc_keywords = [w.lower() for w in re.findall(r"[a-zA-Z]{3,}", skill_desc)]
|
|
619
|
+
for s in sections:
|
|
620
|
+
s["keywords"] = list(set(s["keywords"] + desc_keywords))
|
|
621
|
+
|
|
622
|
+
docs.extend(sections)
|
|
623
|
+
if docs:
|
|
624
|
+
break # Use first found skills directory
|
|
625
|
+
|
|
626
|
+
return docs
|
|
627
|
+
|
|
628
|
+
|
|
629
|
+
def deduplicate(docs: list[dict]) -> list[dict]:
|
|
630
|
+
"""Remove duplicate documents by content hash."""
|
|
631
|
+
seen = set()
|
|
632
|
+
unique = []
|
|
633
|
+
for d in docs:
|
|
634
|
+
h = d["content_hash"]
|
|
635
|
+
if h not in seen:
|
|
636
|
+
seen.add(h)
|
|
637
|
+
unique.append(d)
|
|
638
|
+
return unique
|
|
639
|
+
|
|
640
|
+
|
|
641
|
+
def index_to_qdrant(docs: list[dict]) -> None:
|
|
642
|
+
"""Create collection and upsert document embeddings."""
|
|
643
|
+
if not docs:
|
|
644
|
+
print(" No documents to index — skipping")
|
|
645
|
+
return
|
|
646
|
+
|
|
647
|
+
client = QdrantClient(host=QDRANT_HOST, port=QDRANT_PORT)
|
|
648
|
+
model = SentenceTransformer(EMBEDDING_MODEL, device="cpu")
|
|
649
|
+
|
|
650
|
+
# Recreate collection
|
|
651
|
+
collections = [c.name for c in client.get_collections().collections]
|
|
652
|
+
if COLLECTION_NAME in collections:
|
|
653
|
+
client.delete_collection(COLLECTION_NAME)
|
|
654
|
+
print(f" Deleted existing '{COLLECTION_NAME}' collection")
|
|
655
|
+
|
|
656
|
+
client.create_collection(
|
|
657
|
+
collection_name=COLLECTION_NAME,
|
|
658
|
+
vectors_config=VectorParams(size=VECTOR_SIZE, distance=Distance.COSINE),
|
|
659
|
+
)
|
|
660
|
+
print(f" Created '{COLLECTION_NAME}' collection ({VECTOR_SIZE}-dim cosine)")
|
|
661
|
+
|
|
662
|
+
# Assign sequential IDs and build embeddings
|
|
663
|
+
points = []
|
|
664
|
+
for idx, doc in enumerate(docs, start=1):
|
|
665
|
+
embed_text = f"{doc['title']}. {' '.join(doc['keywords'][:10])}. {doc['body'][:500]}"
|
|
666
|
+
vector = model.encode(embed_text).tolist()
|
|
667
|
+
points.append(PointStruct(
|
|
668
|
+
id=idx, vector=vector,
|
|
669
|
+
payload={
|
|
670
|
+
"title": doc["title"],
|
|
671
|
+
"abbreviation": doc.get("abbreviation", ""),
|
|
672
|
+
"category": doc["category"],
|
|
673
|
+
"source": doc.get("source", ""),
|
|
674
|
+
"detection": doc.get("detection", ""),
|
|
675
|
+
"keywords": doc["keywords"],
|
|
676
|
+
"body": doc["body"],
|
|
677
|
+
"content_hash": doc["content_hash"],
|
|
678
|
+
"indexed_at": datetime.now(tz=timezone.utc).isoformat(),
|
|
679
|
+
},
|
|
680
|
+
))
|
|
681
|
+
|
|
682
|
+
# Batch upsert (Qdrant handles large batches fine)
|
|
683
|
+
BATCH_SIZE = 100
|
|
684
|
+
for i in range(0, len(points), BATCH_SIZE):
|
|
685
|
+
batch = points[i:i + BATCH_SIZE]
|
|
686
|
+
client.upsert(collection_name=COLLECTION_NAME, points=batch)
|
|
687
|
+
print(f" Indexed {len(points)} documents")
|
|
688
|
+
|
|
689
|
+
|
|
690
|
+
def main():
|
|
691
|
+
print("=== UAP Pattern Indexer (v2 — multi-source) ===")
|
|
692
|
+
all_docs: list[dict] = []
|
|
693
|
+
|
|
694
|
+
# 1. Primary source (CLAUDE.md) with @include resolution
|
|
695
|
+
if PRIMARY_SOURCE.exists():
|
|
696
|
+
text = PRIMARY_SOURCE.read_text()
|
|
697
|
+
text = resolve_includes(text, PROJECT_ROOT)
|
|
698
|
+
print(f" Read {PRIMARY_SOURCE.name} ({len(text)} bytes, includes resolved)")
|
|
699
|
+
|
|
700
|
+
# Try legacy numbered patterns first
|
|
701
|
+
patterns = extract_numbered_patterns(text)
|
|
702
|
+
if patterns:
|
|
703
|
+
print(f" Extracted {len(patterns)} numbered patterns")
|
|
704
|
+
all_docs.extend(patterns)
|
|
705
|
+
|
|
706
|
+
# Also extract heading-based sections
|
|
707
|
+
sections = extract_sections(text, PRIMARY_SOURCE.name)
|
|
708
|
+
if sections:
|
|
709
|
+
print(f" Extracted {len(sections)} sections from {PRIMARY_SOURCE.name}")
|
|
710
|
+
all_docs.extend(sections)
|
|
711
|
+
else:
|
|
712
|
+
print(f" {PRIMARY_SOURCE.name} not found — skipping")
|
|
713
|
+
|
|
714
|
+
# 2. Additional source files (AGENTS.md, etc.)
|
|
715
|
+
for src_name in ADDITIONAL_SOURCES:
|
|
716
|
+
src_path = PROJECT_ROOT / src_name
|
|
717
|
+
if src_path.exists():
|
|
718
|
+
text = src_path.read_text()
|
|
719
|
+
sections = extract_sections(text, src_name)
|
|
720
|
+
print(f" Extracted {len(sections)} sections from {src_name}")
|
|
721
|
+
all_docs.extend(sections)
|
|
722
|
+
else:
|
|
723
|
+
print(f" {src_name} not found — skipping")
|
|
724
|
+
|
|
725
|
+
# 3. Auto-detect common files if no additional sources configured
|
|
726
|
+
if not ADDITIONAL_SOURCES:
|
|
727
|
+
for auto_file in ["AGENTS.md", "CONTRIBUTING.md"]:
|
|
728
|
+
auto_path = PROJECT_ROOT / auto_file
|
|
729
|
+
if auto_path.exists():
|
|
730
|
+
text = auto_path.read_text()
|
|
731
|
+
sections = extract_sections(text, auto_file)
|
|
732
|
+
if sections:
|
|
733
|
+
print(f" Auto-detected {auto_file}: {len(sections)} sections")
|
|
734
|
+
all_docs.extend(sections)
|
|
735
|
+
|
|
736
|
+
# 4. Scan skill files
|
|
737
|
+
skills = scan_skills(PROJECT_ROOT, SKILLS_DIR)
|
|
738
|
+
if skills:
|
|
739
|
+
print(f" Scanned skills: {len(skills)} documents")
|
|
740
|
+
all_docs.extend(skills)
|
|
741
|
+
|
|
742
|
+
# Deduplicate
|
|
743
|
+
all_docs = deduplicate(all_docs)
|
|
744
|
+
print(f" Total unique documents: {len(all_docs)}")
|
|
745
|
+
|
|
746
|
+
# Index
|
|
747
|
+
index_to_qdrant(all_docs)
|
|
748
|
+
|
|
749
|
+
# Summary by category
|
|
750
|
+
categories: dict[str, int] = {}
|
|
751
|
+
for d in all_docs:
|
|
752
|
+
categories[d["category"]] = categories.get(d["category"], 0) + 1
|
|
753
|
+
print("\\n=== Summary by Category ===")
|
|
754
|
+
for cat, count in sorted(categories.items(), key=lambda x: -x[1]):
|
|
755
|
+
print(f" {cat:>20}: {count}")
|
|
756
|
+
|
|
757
|
+
print(f"\\nTotal: {len(all_docs)} documents in '{COLLECTION_NAME}' collection")
|
|
758
|
+
|
|
759
|
+
|
|
760
|
+
if __name__ == "__main__":
|
|
761
|
+
main()
|
|
762
|
+
`;
|
|
763
|
+
}
|
|
764
|
+
function generateQueryScript(rag, host, port) {
|
|
765
|
+
return `#!/usr/bin/env python3
|
|
766
|
+
"""
|
|
767
|
+
Query the ${rag.collection} Qdrant collection for task-relevant patterns.
|
|
768
|
+
|
|
769
|
+
Generated by: uap patterns generate
|
|
770
|
+
"""
|
|
771
|
+
|
|
772
|
+
import argparse
|
|
773
|
+
import json
|
|
774
|
+
import sys
|
|
775
|
+
|
|
776
|
+
from sentence_transformers import SentenceTransformer
|
|
777
|
+
from qdrant_client import QdrantClient
|
|
778
|
+
|
|
779
|
+
QDRANT_HOST = "${host}"
|
|
780
|
+
QDRANT_PORT = ${port}
|
|
781
|
+
COLLECTION_NAME = "${rag.collection}"
|
|
782
|
+
EMBEDDING_MODEL = "${rag.embeddingModel}"
|
|
783
|
+
|
|
784
|
+
_model = None
|
|
785
|
+
|
|
786
|
+
|
|
787
|
+
def get_model():
|
|
788
|
+
global _model
|
|
789
|
+
if _model is None:
|
|
790
|
+
_model = SentenceTransformer(EMBEDDING_MODEL, device="cpu")
|
|
791
|
+
return _model
|
|
792
|
+
|
|
793
|
+
|
|
794
|
+
def query_patterns(query: str, top_k: int = ${rag.topK}, min_score: float = ${rag.scoreThreshold}) -> list[dict]:
|
|
795
|
+
client = QdrantClient(host=QDRANT_HOST, port=QDRANT_PORT)
|
|
796
|
+
model = get_model()
|
|
797
|
+
vector = model.encode(query).tolist()
|
|
798
|
+
results = client.query_points(
|
|
799
|
+
collection_name=COLLECTION_NAME,
|
|
800
|
+
query=vector,
|
|
801
|
+
limit=top_k,
|
|
802
|
+
score_threshold=min_score,
|
|
803
|
+
)
|
|
804
|
+
patterns = []
|
|
805
|
+
for hit in results.points:
|
|
806
|
+
patterns.append({
|
|
807
|
+
"id": hit.id,
|
|
808
|
+
"score": round(hit.score, 4),
|
|
809
|
+
"title": hit.payload.get("title", ""),
|
|
810
|
+
"abbreviation": hit.payload.get("abbreviation", ""),
|
|
811
|
+
"category": hit.payload.get("category", ""),
|
|
812
|
+
"body": hit.payload.get("body", ""),
|
|
813
|
+
})
|
|
814
|
+
return patterns
|
|
815
|
+
|
|
816
|
+
|
|
817
|
+
def format_for_context(patterns: list[dict]) -> str:
|
|
818
|
+
if not patterns:
|
|
819
|
+
return ""
|
|
820
|
+
lines = ["<uap-patterns>"]
|
|
821
|
+
for p in patterns:
|
|
822
|
+
abbr = f" ({p['abbreviation']})" if p["abbreviation"] else ""
|
|
823
|
+
lines.append(f"### Pattern {p['id']}: {p['title']}{abbr}")
|
|
824
|
+
lines.append(f"Relevance: {p['score']}")
|
|
825
|
+
lines.append(p["body"])
|
|
826
|
+
lines.append("")
|
|
827
|
+
lines.append("</uap-patterns>")
|
|
828
|
+
return "\\n".join(lines)
|
|
829
|
+
|
|
830
|
+
|
|
831
|
+
def main():
|
|
832
|
+
parser = argparse.ArgumentParser(description="Query UAP pattern collection")
|
|
833
|
+
parser.add_argument("query", help="Task description to match patterns against")
|
|
834
|
+
parser.add_argument("--top", type=int, default=${rag.topK})
|
|
835
|
+
parser.add_argument("--min-score", type=float, default=${rag.scoreThreshold})
|
|
836
|
+
parser.add_argument("--format", choices=["text", "json", "context"], default="text")
|
|
837
|
+
args = parser.parse_args()
|
|
838
|
+
try:
|
|
839
|
+
patterns = query_patterns(args.query, top_k=args.top, min_score=args.min_score)
|
|
840
|
+
except Exception as e:
|
|
841
|
+
print(f"ERROR: {e}", file=sys.stderr)
|
|
842
|
+
sys.exit(1)
|
|
843
|
+
if args.format == "json":
|
|
844
|
+
print(json.dumps(patterns, indent=2))
|
|
845
|
+
elif args.format == "context":
|
|
846
|
+
print(format_for_context(patterns))
|
|
847
|
+
else:
|
|
848
|
+
if not patterns:
|
|
849
|
+
print("No matching patterns found.")
|
|
850
|
+
return
|
|
851
|
+
for p in patterns:
|
|
852
|
+
abbr = f" ({p['abbreviation']})" if p["abbreviation"] else ""
|
|
853
|
+
print(f"[{p['score']:.3f}] P{p['id']}: {p['title']}{abbr} [{p['category']}]")
|
|
854
|
+
print(f" {p['body'][:200]}...")
|
|
855
|
+
print()
|
|
856
|
+
|
|
857
|
+
|
|
858
|
+
if __name__ == "__main__":
|
|
859
|
+
main()
|
|
860
|
+
`;
|
|
861
|
+
}
|
|
862
|
+
//# sourceMappingURL=patterns.js.map
|