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,517 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Qwen3.5 Tool Call Wrapper with Retry Logic
|
|
4
|
+
|
|
5
|
+
Provides robust tool calling for Qwen3.5 35B A3B with automatic retry
|
|
6
|
+
on failures, addressing known issues with early termination.
|
|
7
|
+
|
|
8
|
+
Known Issues Fixed:
|
|
9
|
+
1. Template parsing failures after 1-2 tool calls
|
|
10
|
+
2. Reasoning mode interference with structured output
|
|
11
|
+
3. JSON parsing errors from leaked reasoning content
|
|
12
|
+
4. Context window reprocessing issues
|
|
13
|
+
|
|
14
|
+
Usage:
|
|
15
|
+
from qwen_tool_call_wrapper import Qwen35ToolCallClient
|
|
16
|
+
|
|
17
|
+
client = Qwen35ToolCallClient()
|
|
18
|
+
response = client.chat_with_tools(
|
|
19
|
+
messages=[{"role": "user", "content": "Call read_file with path='/etc/hosts'"}],
|
|
20
|
+
tools=[...]
|
|
21
|
+
)
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
import openai
|
|
25
|
+
import time
|
|
26
|
+
import json
|
|
27
|
+
import logging
|
|
28
|
+
from typing import List, Dict, Any, Optional, Tuple
|
|
29
|
+
from dataclasses import dataclass, asdict
|
|
30
|
+
from datetime import datetime
|
|
31
|
+
from enum import Enum
|
|
32
|
+
|
|
33
|
+
# Configure logging
|
|
34
|
+
logging.basicConfig(
|
|
35
|
+
level=logging.INFO, format="%(asctime)s - %(name)s - %(levelname)s - %(message)s"
|
|
36
|
+
)
|
|
37
|
+
logger = logging.getLogger("qwen35_tool_call")
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class ToolCallStatus(Enum):
|
|
41
|
+
"""Status of tool call attempts"""
|
|
42
|
+
|
|
43
|
+
SUCCESS = "success"
|
|
44
|
+
FAILURE = "failure"
|
|
45
|
+
RETRY = "retry"
|
|
46
|
+
MAX_RETRIES = "max_retries"
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
@dataclass
|
|
50
|
+
class ToolCallMetrics:
|
|
51
|
+
"""Metrics for tool call performance"""
|
|
52
|
+
|
|
53
|
+
total_attempts: int = 0
|
|
54
|
+
successful_calls: int = 0
|
|
55
|
+
failed_calls: int = 0
|
|
56
|
+
retries: int = 0
|
|
57
|
+
avg_latency_ms: float = 0.0
|
|
58
|
+
last_error: Optional[str] = None
|
|
59
|
+
|
|
60
|
+
def to_dict(self) -> Dict:
|
|
61
|
+
return asdict(self)
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
class Qwen35ToolCallError(Exception):
|
|
65
|
+
"""Custom exception for Qwen3.5 tool call failures"""
|
|
66
|
+
|
|
67
|
+
pass
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
class Qwen35ToolCallClient:
|
|
71
|
+
"""
|
|
72
|
+
OpenAI-compatible client optimized for Qwen3.5 35B A3B tool calling.
|
|
73
|
+
|
|
74
|
+
Implements:
|
|
75
|
+
- Automatic retry with exponential backoff
|
|
76
|
+
- Prompt correction for failed tool calls
|
|
77
|
+
- Metrics tracking and monitoring
|
|
78
|
+
- Thinking mode disablement
|
|
79
|
+
- Template validation
|
|
80
|
+
"""
|
|
81
|
+
|
|
82
|
+
# Default configuration for Qwen3.5
|
|
83
|
+
DEFAULT_CONFIG = {
|
|
84
|
+
"temperature": 0.6,
|
|
85
|
+
"top_p": 0.95,
|
|
86
|
+
"top_k": 20,
|
|
87
|
+
"presence_penalty": 1.5,
|
|
88
|
+
"max_tokens": 32768,
|
|
89
|
+
"enable_thinking": False,
|
|
90
|
+
"tool_call_parser": "qwen3_coder",
|
|
91
|
+
"max_retries": 3,
|
|
92
|
+
"backoff_factor": 2.0,
|
|
93
|
+
"base_url": "http://127.0.0.1:8080/v1",
|
|
94
|
+
"api_key": "not-needed",
|
|
95
|
+
"model": "qwen35-a3b-iq4xs",
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
def __init__(
|
|
99
|
+
self, config: Optional[Dict[str, Any]] = None, enable_metrics: bool = True
|
|
100
|
+
):
|
|
101
|
+
"""
|
|
102
|
+
Initialize Qwen3.5 tool call client.
|
|
103
|
+
|
|
104
|
+
Args:
|
|
105
|
+
config: Override default configuration
|
|
106
|
+
enable_metrics: Enable performance metrics tracking
|
|
107
|
+
"""
|
|
108
|
+
self.config = {**self.DEFAULT_CONFIG, **(config or {})}
|
|
109
|
+
self.enable_metrics = enable_metrics
|
|
110
|
+
self.metrics = ToolCallMetrics()
|
|
111
|
+
self._client = None
|
|
112
|
+
|
|
113
|
+
# Initialize OpenAI client
|
|
114
|
+
self._init_client()
|
|
115
|
+
|
|
116
|
+
logger.info(f"Qwen35ToolCallClient initialized with config: {self.config}")
|
|
117
|
+
|
|
118
|
+
def _init_client(self):
|
|
119
|
+
"""Initialize OpenAI-compatible client"""
|
|
120
|
+
try:
|
|
121
|
+
self._client = openai.Client(
|
|
122
|
+
base_url=self.config["base_url"], api_key=self.config["api_key"]
|
|
123
|
+
)
|
|
124
|
+
logger.info(f"Connected to {self.config['base_url']}")
|
|
125
|
+
except Exception as e:
|
|
126
|
+
logger.error(f"Failed to initialize OpenAI client: {e}")
|
|
127
|
+
raise Qwen35ToolCallError(f"Client initialization failed: {e}")
|
|
128
|
+
|
|
129
|
+
def chat_with_tools(
|
|
130
|
+
self,
|
|
131
|
+
messages: List[Dict[str, str]],
|
|
132
|
+
tools: List[Dict[str, Any]],
|
|
133
|
+
max_retries: Optional[int] = None,
|
|
134
|
+
timeout: int = 120,
|
|
135
|
+
**kwargs,
|
|
136
|
+
) -> openai.types.chat.ChatCompletion:
|
|
137
|
+
"""
|
|
138
|
+
Chat completion with automatic retry on tool call failures.
|
|
139
|
+
|
|
140
|
+
This is the main method for making tool calls with Qwen3.5.
|
|
141
|
+
It implements exponential backoff and prompt correction.
|
|
142
|
+
|
|
143
|
+
Args:
|
|
144
|
+
messages: List of chat messages
|
|
145
|
+
tools: List of tool definitions
|
|
146
|
+
max_retries: Override default max retries
|
|
147
|
+
timeout: Request timeout in seconds
|
|
148
|
+
**kwargs: Additional parameters passed to OpenAI API
|
|
149
|
+
|
|
150
|
+
Returns:
|
|
151
|
+
ChatCompletion response with tool calls
|
|
152
|
+
|
|
153
|
+
Raises:
|
|
154
|
+
Qwen35ToolCallError: After max retries exhausted
|
|
155
|
+
"""
|
|
156
|
+
max_retries = max_retries or self.config["max_retries"]
|
|
157
|
+
|
|
158
|
+
# Track timing
|
|
159
|
+
start_time = time.time()
|
|
160
|
+
|
|
161
|
+
# Make a copy of messages to avoid modifying original
|
|
162
|
+
current_messages = [msg.copy() for msg in messages]
|
|
163
|
+
|
|
164
|
+
for attempt in range(max_retries):
|
|
165
|
+
self.metrics.total_attempts += 1
|
|
166
|
+
|
|
167
|
+
try:
|
|
168
|
+
# Build request with Qwen3.5 optimizations
|
|
169
|
+
request_params = {
|
|
170
|
+
"model": self.config["model"],
|
|
171
|
+
"messages": current_messages,
|
|
172
|
+
"tools": tools,
|
|
173
|
+
"temperature": self.config["temperature"],
|
|
174
|
+
"top_p": self.config["top_p"],
|
|
175
|
+
"top_k": self.config["top_k"],
|
|
176
|
+
"presence_penalty": self.config["presence_penalty"],
|
|
177
|
+
"max_tokens": self.config["max_tokens"],
|
|
178
|
+
"timeout": timeout,
|
|
179
|
+
"extra_body": {
|
|
180
|
+
"chat_template_kwargs": {
|
|
181
|
+
"enable_thinking": self.config["enable_thinking"]
|
|
182
|
+
}
|
|
183
|
+
},
|
|
184
|
+
**kwargs,
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
logger.debug(f"Attempt {attempt + 1}/{max_retries}: Sending request")
|
|
188
|
+
|
|
189
|
+
# Make API call
|
|
190
|
+
response = self._client.chat.completions.create(**request_params)
|
|
191
|
+
|
|
192
|
+
# Validate response
|
|
193
|
+
tool_calls = response.choices[0].message.tool_calls
|
|
194
|
+
|
|
195
|
+
if self._validate_tool_call(tool_calls):
|
|
196
|
+
# Success!
|
|
197
|
+
self.metrics.successful_calls += 1
|
|
198
|
+
|
|
199
|
+
# Calculate latency
|
|
200
|
+
latency_ms = (time.time() - start_time) * 1000
|
|
201
|
+
self.metrics.avg_latency_ms = latency_ms
|
|
202
|
+
|
|
203
|
+
logger.info(f"Tool call successful after {attempt + 1} attempt(s)")
|
|
204
|
+
return response
|
|
205
|
+
else:
|
|
206
|
+
# Invalid format, retry with correction
|
|
207
|
+
logger.warning(f"Invalid tool call format on attempt {attempt + 1}")
|
|
208
|
+
current_messages = self._correct_prompt(current_messages, response)
|
|
209
|
+
self.metrics.retries += 1
|
|
210
|
+
|
|
211
|
+
if attempt < max_retries - 1:
|
|
212
|
+
# Exponential backoff
|
|
213
|
+
backoff = self.config["backoff_factor"] ** attempt
|
|
214
|
+
time.sleep(backoff)
|
|
215
|
+
logger.info(f"Retrying in {backoff:.1f}s...")
|
|
216
|
+
|
|
217
|
+
except Exception as e:
|
|
218
|
+
self.metrics.last_error = str(e)
|
|
219
|
+
logger.error(f"Error on attempt {attempt + 1}: {e}")
|
|
220
|
+
|
|
221
|
+
if attempt == max_retries - 1:
|
|
222
|
+
# Last attempt failed
|
|
223
|
+
raise Qwen35ToolCallError(
|
|
224
|
+
f"Failed after {max_retries} attempts: {str(e)}"
|
|
225
|
+
)
|
|
226
|
+
|
|
227
|
+
# Retry with backoff
|
|
228
|
+
backoff = self.config["backoff_factor"] ** attempt
|
|
229
|
+
time.sleep(backoff)
|
|
230
|
+
|
|
231
|
+
# Should not reach here, but just in case
|
|
232
|
+
raise Qwen35ToolCallError("Max retries exceeded")
|
|
233
|
+
|
|
234
|
+
def _validate_tool_call(self, tool_calls) -> bool:
|
|
235
|
+
"""
|
|
236
|
+
Validate that tool call has correct format.
|
|
237
|
+
|
|
238
|
+
Checks for:
|
|
239
|
+
- Non-empty tool calls list
|
|
240
|
+
- Proper parameter format with <parameter> tags
|
|
241
|
+
- No reasoning content leakage
|
|
242
|
+
"""
|
|
243
|
+
if not tool_calls:
|
|
244
|
+
logger.debug("No tool calls returned")
|
|
245
|
+
return False
|
|
246
|
+
|
|
247
|
+
tool_call = tool_calls[0]
|
|
248
|
+
|
|
249
|
+
# Check for reasoning content leakage
|
|
250
|
+
content = tool_call.function.arguments
|
|
251
|
+
|
|
252
|
+
# Verify proper parameter format
|
|
253
|
+
has_open_param = "<parameter>" in content
|
|
254
|
+
has_close_param = "</parameter>" in content
|
|
255
|
+
|
|
256
|
+
if not has_open_param or not has_close_param:
|
|
257
|
+
logger.debug(f"Invalid parameter format: {content[:100]}...")
|
|
258
|
+
return False
|
|
259
|
+
|
|
260
|
+
# Check for thinking tag leakage
|
|
261
|
+
if "<thinking>" in content or "</thinking>" in content:
|
|
262
|
+
logger.debug("Thinking tag leakage detected")
|
|
263
|
+
return False
|
|
264
|
+
|
|
265
|
+
return True
|
|
266
|
+
|
|
267
|
+
def _correct_prompt(
|
|
268
|
+
self, messages: List[Dict], response: openai.types.chat.ChatCompletion
|
|
269
|
+
) -> List[Dict]:
|
|
270
|
+
"""
|
|
271
|
+
Correct prompt after invalid tool call.
|
|
272
|
+
|
|
273
|
+
Appends correction message to guide model toward proper format.
|
|
274
|
+
"""
|
|
275
|
+
invalid_content = response.choices[0].message.content
|
|
276
|
+
|
|
277
|
+
# Add assistant's failed attempt
|
|
278
|
+
messages.append(
|
|
279
|
+
{
|
|
280
|
+
"role": "assistant",
|
|
281
|
+
"content": f"Invalid tool call format detected. "
|
|
282
|
+
f"Content: {invalid_content[:200]}...",
|
|
283
|
+
}
|
|
284
|
+
)
|
|
285
|
+
|
|
286
|
+
# Add user correction
|
|
287
|
+
messages.append(
|
|
288
|
+
{
|
|
289
|
+
"role": "user",
|
|
290
|
+
"content": "Please use the correct tool format. "
|
|
291
|
+
"Example format:\n"
|
|
292
|
+
"<function=tool_name>\n"
|
|
293
|
+
"<parameter=arg_name>value</parameter>\n"
|
|
294
|
+
"</function>",
|
|
295
|
+
}
|
|
296
|
+
)
|
|
297
|
+
|
|
298
|
+
return messages
|
|
299
|
+
|
|
300
|
+
def execute_tool_call(
|
|
301
|
+
self, tool_calls: List, tool_functions: Dict[str, callable]
|
|
302
|
+
) -> List[Any]:
|
|
303
|
+
"""
|
|
304
|
+
Execute tool calls and collect results.
|
|
305
|
+
|
|
306
|
+
Args:
|
|
307
|
+
tool_calls: List of tool call objects from response
|
|
308
|
+
tool_functions: Dict mapping tool names to functions
|
|
309
|
+
|
|
310
|
+
Returns:
|
|
311
|
+
List of tool results
|
|
312
|
+
"""
|
|
313
|
+
results = []
|
|
314
|
+
|
|
315
|
+
for tool_call in tool_calls:
|
|
316
|
+
tool_name = tool_call.function.name
|
|
317
|
+
tool_args = json.loads(tool_call.function.arguments)
|
|
318
|
+
|
|
319
|
+
logger.info(f"Executing tool: {tool_name} with args: {tool_args}")
|
|
320
|
+
|
|
321
|
+
if tool_name not in tool_functions:
|
|
322
|
+
results.append(
|
|
323
|
+
{
|
|
324
|
+
"tool_name": tool_name,
|
|
325
|
+
"status": "error",
|
|
326
|
+
"error": f"Tool '{tool_name}' not found",
|
|
327
|
+
}
|
|
328
|
+
)
|
|
329
|
+
continue
|
|
330
|
+
|
|
331
|
+
try:
|
|
332
|
+
result = tool_functions[tool_name](**tool_args)
|
|
333
|
+
results.append(
|
|
334
|
+
{"tool_name": tool_name, "status": "success", "result": result}
|
|
335
|
+
)
|
|
336
|
+
except Exception as e:
|
|
337
|
+
results.append(
|
|
338
|
+
{"tool_name": tool_name, "status": "error", "error": str(e)}
|
|
339
|
+
)
|
|
340
|
+
|
|
341
|
+
return results
|
|
342
|
+
|
|
343
|
+
def get_metrics(self) -> ToolCallMetrics:
|
|
344
|
+
"""Get current metrics"""
|
|
345
|
+
return self.metrics
|
|
346
|
+
|
|
347
|
+
def reset_metrics(self):
|
|
348
|
+
"""Reset metrics counters"""
|
|
349
|
+
self.metrics = ToolCallMetrics()
|
|
350
|
+
logger.info("Metrics reset")
|
|
351
|
+
|
|
352
|
+
def get_status(self) -> Dict:
|
|
353
|
+
"""Get client status"""
|
|
354
|
+
return {
|
|
355
|
+
"model": self.config["model"],
|
|
356
|
+
"base_url": self.config["base_url"],
|
|
357
|
+
"metrics": self.metrics.to_dict(),
|
|
358
|
+
"config": {
|
|
359
|
+
k: v for k, v in self.config.items() if k not in ["base_url", "api_key"]
|
|
360
|
+
},
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
|
|
364
|
+
class Qwen35ToolCallAgent:
|
|
365
|
+
"""
|
|
366
|
+
Higher-level agent for Qwen3.5 tool calling workflows.
|
|
367
|
+
|
|
368
|
+
Combines tool calling with execution and result handling.
|
|
369
|
+
"""
|
|
370
|
+
|
|
371
|
+
def __init__(
|
|
372
|
+
self, tool_functions: Dict[str, callable], client_config: Optional[Dict] = None
|
|
373
|
+
):
|
|
374
|
+
"""
|
|
375
|
+
Initialize Qwen3.5 tool call agent.
|
|
376
|
+
|
|
377
|
+
Args:
|
|
378
|
+
tool_functions: Dict mapping tool names to callable functions
|
|
379
|
+
client_config: Configuration for tool call client
|
|
380
|
+
"""
|
|
381
|
+
self.tool_functions = tool_functions
|
|
382
|
+
self.client = Qwen35ToolCallClient(client_config)
|
|
383
|
+
|
|
384
|
+
logger.info(f"Qwen35ToolCallAgent initialized with {len(tool_functions)} tools")
|
|
385
|
+
|
|
386
|
+
def run(
|
|
387
|
+
self, user_query: str, additional_messages: Optional[List[Dict]] = None
|
|
388
|
+
) -> Tuple[openai.types.chat.ChatCompletion, List[Any]]:
|
|
389
|
+
"""
|
|
390
|
+
Run a complete tool calling workflow.
|
|
391
|
+
|
|
392
|
+
Args:
|
|
393
|
+
user_query: User's input query
|
|
394
|
+
additional_messages: Optional additional conversation history
|
|
395
|
+
|
|
396
|
+
Returns:
|
|
397
|
+
Tuple of (ChatCompletion response, List of tool results)
|
|
398
|
+
"""
|
|
399
|
+
# Build messages
|
|
400
|
+
messages = []
|
|
401
|
+
|
|
402
|
+
if additional_messages:
|
|
403
|
+
messages.extend(additional_messages)
|
|
404
|
+
|
|
405
|
+
messages.append({"role": "user", "content": user_query})
|
|
406
|
+
|
|
407
|
+
# Make tool call request
|
|
408
|
+
response = self.client.chat_with_tools(
|
|
409
|
+
messages=messages, tools=list(self.tool_functions.values())
|
|
410
|
+
)
|
|
411
|
+
|
|
412
|
+
# Execute tool calls
|
|
413
|
+
tool_calls = response.choices[0].message.tool_calls
|
|
414
|
+
|
|
415
|
+
if tool_calls:
|
|
416
|
+
results = self.client.execute_tool_call(tool_calls, self.tool_functions)
|
|
417
|
+
else:
|
|
418
|
+
results = []
|
|
419
|
+
|
|
420
|
+
return response, results
|
|
421
|
+
|
|
422
|
+
def get_status(self) -> Dict:
|
|
423
|
+
"""Get agent status"""
|
|
424
|
+
return {
|
|
425
|
+
"tools": list(self.tool_functions.keys()),
|
|
426
|
+
"client_status": self.client.get_status(),
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
|
|
430
|
+
# Convenience function for simple use cases
|
|
431
|
+
def qwen35_chat_with_tools(
|
|
432
|
+
user_query: str,
|
|
433
|
+
tools: List[Dict],
|
|
434
|
+
tool_functions: Dict[str, callable],
|
|
435
|
+
config: Optional[Dict] = None,
|
|
436
|
+
) -> Tuple[openai.types.chat.ChatCompletion, List[Any]]:
|
|
437
|
+
"""
|
|
438
|
+
Simple function for quick tool calling with Qwen3.5.
|
|
439
|
+
|
|
440
|
+
Args:
|
|
441
|
+
user_query: User's input
|
|
442
|
+
tools: Tool definitions
|
|
443
|
+
tool_functions: Tool implementations
|
|
444
|
+
config: Optional configuration
|
|
445
|
+
|
|
446
|
+
Returns:
|
|
447
|
+
Tuple of (response, results)
|
|
448
|
+
"""
|
|
449
|
+
agent = Qwen35ToolCallAgent(tool_functions, config)
|
|
450
|
+
return agent.run(user_query)
|
|
451
|
+
|
|
452
|
+
|
|
453
|
+
# Example usage
|
|
454
|
+
if __name__ == "__main__":
|
|
455
|
+
# Example tools
|
|
456
|
+
def read_file(path: str) -> str:
|
|
457
|
+
"""Read file contents"""
|
|
458
|
+
with open(path, "r") as f:
|
|
459
|
+
return f.read()
|
|
460
|
+
|
|
461
|
+
def get_weather(city: str) -> str:
|
|
462
|
+
"""Get weather for city"""
|
|
463
|
+
return f"Weather in {city}: Sunny, 25°C"
|
|
464
|
+
|
|
465
|
+
tool_functions = {
|
|
466
|
+
"read_file": {
|
|
467
|
+
"type": "function",
|
|
468
|
+
"function": {
|
|
469
|
+
"name": "read_file",
|
|
470
|
+
"description": "Read file contents",
|
|
471
|
+
"parameters": {
|
|
472
|
+
"type": "object",
|
|
473
|
+
"properties": {"path": {"type": "string"}},
|
|
474
|
+
"required": ["path"],
|
|
475
|
+
},
|
|
476
|
+
},
|
|
477
|
+
},
|
|
478
|
+
"get_weather": {
|
|
479
|
+
"type": "function",
|
|
480
|
+
"function": {
|
|
481
|
+
"name": "get_weather",
|
|
482
|
+
"description": "Get weather information",
|
|
483
|
+
"parameters": {
|
|
484
|
+
"type": "object",
|
|
485
|
+
"properties": {"city": {"type": "string"}},
|
|
486
|
+
"required": ["city"],
|
|
487
|
+
},
|
|
488
|
+
},
|
|
489
|
+
},
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
# Initialize agent
|
|
493
|
+
agent = Qwen35ToolCallAgent(tool_functions)
|
|
494
|
+
|
|
495
|
+
# Run example
|
|
496
|
+
try:
|
|
497
|
+
response, results = agent.run("Read /etc/hosts and get weather in Sydney")
|
|
498
|
+
|
|
499
|
+
print("\n=== Tool Call Results ===")
|
|
500
|
+
for result in results:
|
|
501
|
+
print(f"Tool: {result['tool_name']}")
|
|
502
|
+
print(f"Status: {result['status']}")
|
|
503
|
+
if result["status"] == "success":
|
|
504
|
+
print(f"Result: {result['result'][:200]}...")
|
|
505
|
+
else:
|
|
506
|
+
print(f"Error: {result['error']}")
|
|
507
|
+
|
|
508
|
+
print("\n=== Metrics ===")
|
|
509
|
+
metrics = agent.client.get_metrics()
|
|
510
|
+
print(f"Total attempts: {metrics.total_attempts}")
|
|
511
|
+
print(f"Successful calls: {metrics.successful_calls}")
|
|
512
|
+
print(
|
|
513
|
+
f"Success rate: {metrics.successful_calls / metrics.total_attempts * 100:.1f}%"
|
|
514
|
+
)
|
|
515
|
+
|
|
516
|
+
except Qwen35ToolCallError as e:
|
|
517
|
+
print(f"Tool call failed: {e}")
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Start agent support services (Qdrant vector database)
|
|
3
|
+
#
|
|
4
|
+
# Usage:
|
|
5
|
+
# ./agents/scripts/start-services.sh # Start services
|
|
6
|
+
# ./agents/scripts/start-services.sh stop # Stop services
|
|
7
|
+
# ./agents/scripts/start-services.sh status # Check status
|
|
8
|
+
|
|
9
|
+
set -e
|
|
10
|
+
|
|
11
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
12
|
+
AGENTS_DIR="$(dirname "$SCRIPT_DIR")"
|
|
13
|
+
|
|
14
|
+
cd "$AGENTS_DIR"
|
|
15
|
+
|
|
16
|
+
case "${1:-start}" in
|
|
17
|
+
start)
|
|
18
|
+
echo "Starting agent services..."
|
|
19
|
+
docker-compose up -d
|
|
20
|
+
|
|
21
|
+
echo "Waiting for Qdrant to be healthy..."
|
|
22
|
+
for _ in {1..30}; do
|
|
23
|
+
if curl -s http://localhost:6333/healthz > /dev/null 2>&1; then
|
|
24
|
+
echo "Qdrant is ready!"
|
|
25
|
+
break
|
|
26
|
+
fi
|
|
27
|
+
sleep 1
|
|
28
|
+
done
|
|
29
|
+
|
|
30
|
+
# Check if claude_memory collection exists
|
|
31
|
+
COLLECTIONS=$(curl -s http://localhost:6333/collections | grep -o '"name":"[^"]*"' | grep claude_memory || true)
|
|
32
|
+
if [ -z "$COLLECTIONS" ]; then
|
|
33
|
+
echo "Creating claude_memory collection..."
|
|
34
|
+
curl -s -X PUT http://localhost:6333/collections/claude_memory \
|
|
35
|
+
-H "Content-Type: application/json" \
|
|
36
|
+
-d '{"vectors": {"size": 384, "distance": "Cosine"}}' > /dev/null
|
|
37
|
+
|
|
38
|
+
# Check if we need to migrate memories
|
|
39
|
+
MEMORY_FILE="$AGENTS_DIR/data/memory/long_term.json"
|
|
40
|
+
if [ -f "$MEMORY_FILE" ]; then
|
|
41
|
+
echo "Migrating long-term memories to Qdrant..."
|
|
42
|
+
if [ -f "$AGENTS_DIR/.venv/bin/python" ]; then
|
|
43
|
+
"$AGENTS_DIR/.venv/bin/python" "$SCRIPT_DIR/migrate_memory_to_qdrant.py"
|
|
44
|
+
else
|
|
45
|
+
echo "Warning: Virtual environment not found. Run:"
|
|
46
|
+
echo " python3 -m venv agents/.venv"
|
|
47
|
+
echo " agents/.venv/bin/pip install sentence-transformers qdrant-client"
|
|
48
|
+
echo " agents/.venv/bin/python agents/scripts/migrate_memory_to_qdrant.py"
|
|
49
|
+
fi
|
|
50
|
+
fi
|
|
51
|
+
else
|
|
52
|
+
echo "claude_memory collection already exists"
|
|
53
|
+
fi
|
|
54
|
+
|
|
55
|
+
echo ""
|
|
56
|
+
echo "Agent services started:"
|
|
57
|
+
echo " - Qdrant: http://localhost:6333"
|
|
58
|
+
echo " - SQLite: $AGENTS_DIR/data/memory/short_term.db"
|
|
59
|
+
;;
|
|
60
|
+
|
|
61
|
+
stop)
|
|
62
|
+
echo "Stopping agent services..."
|
|
63
|
+
docker-compose down
|
|
64
|
+
echo "Services stopped."
|
|
65
|
+
;;
|
|
66
|
+
|
|
67
|
+
status)
|
|
68
|
+
echo "=== Agent Services Status ==="
|
|
69
|
+
echo ""
|
|
70
|
+
|
|
71
|
+
# Qdrant status
|
|
72
|
+
if curl -s http://localhost:6333/healthz > /dev/null 2>&1; then
|
|
73
|
+
echo "Qdrant: RUNNING"
|
|
74
|
+
POINTS=$(curl -s http://localhost:6333/collections/claude_memory 2>/dev/null | grep -o '"points_count":[0-9]*' | cut -d: -f2 || echo "0")
|
|
75
|
+
echo " - Collection: claude_memory ($POINTS points)"
|
|
76
|
+
else
|
|
77
|
+
echo "Qdrant: NOT RUNNING"
|
|
78
|
+
echo " Run: ./agents/scripts/start-services.sh"
|
|
79
|
+
fi
|
|
80
|
+
|
|
81
|
+
echo ""
|
|
82
|
+
|
|
83
|
+
# SQLite status
|
|
84
|
+
if [ -f "$AGENTS_DIR/data/memory/short_term.db" ]; then
|
|
85
|
+
MEMORIES=$(sqlite3 "$AGENTS_DIR/data/memory/short_term.db" "SELECT COUNT(*) FROM memories;" 2>/dev/null || echo "0")
|
|
86
|
+
echo "Short-term memory: $MEMORIES entries"
|
|
87
|
+
else
|
|
88
|
+
echo "Short-term memory: NOT INITIALIZED"
|
|
89
|
+
fi
|
|
90
|
+
;;
|
|
91
|
+
|
|
92
|
+
*)
|
|
93
|
+
echo "Usage: $0 {start|stop|status}"
|
|
94
|
+
exit 1
|
|
95
|
+
;;
|
|
96
|
+
esac
|