@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,686 @@
|
|
|
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
|
+
Strategies implemented:
|
|
9
|
+
1. tool_choice="required" + parallel_tool_calls=true in API requests
|
|
10
|
+
2. Improved multi-tool system prompt with explicit format guidance
|
|
11
|
+
3. Retry escalation: auto -> required -> required+lower temp
|
|
12
|
+
4. Per-tool tool_choice for single-tool scenarios
|
|
13
|
+
5. Thinking mode suppression via chat_template_kwargs
|
|
14
|
+
6. Dynamic temperature decay on retries
|
|
15
|
+
|
|
16
|
+
Known Issues Fixed:
|
|
17
|
+
1. Template parsing failures after 1-2 tool calls
|
|
18
|
+
2. Reasoning mode interference with structured output
|
|
19
|
+
3. JSON parsing errors from leaked reasoning content
|
|
20
|
+
4. Context window reprocessing issues
|
|
21
|
+
5. Multi-tool calls truncated to single call
|
|
22
|
+
|
|
23
|
+
Usage:
|
|
24
|
+
from qwen_tool_call_wrapper import Qwen35ToolCallClient
|
|
25
|
+
|
|
26
|
+
client = Qwen35ToolCallClient()
|
|
27
|
+
response = client.chat_with_tools(
|
|
28
|
+
messages=[{"role": "user", "content": "Call read_file with path='/etc/hosts'"}],
|
|
29
|
+
tools=[...]
|
|
30
|
+
)
|
|
31
|
+
"""
|
|
32
|
+
|
|
33
|
+
import openai
|
|
34
|
+
import time
|
|
35
|
+
import json
|
|
36
|
+
import logging
|
|
37
|
+
from typing import List, Dict, Any, Optional, Tuple
|
|
38
|
+
from dataclasses import dataclass, asdict
|
|
39
|
+
from datetime import datetime
|
|
40
|
+
from enum import Enum
|
|
41
|
+
|
|
42
|
+
# Configure logging
|
|
43
|
+
logging.basicConfig(
|
|
44
|
+
level=logging.INFO, format="%(asctime)s - %(name)s - %(levelname)s - %(message)s"
|
|
45
|
+
)
|
|
46
|
+
logger = logging.getLogger("qwen35_tool_call")
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
class ToolCallStatus(Enum):
|
|
50
|
+
"""Status of tool call attempts"""
|
|
51
|
+
|
|
52
|
+
SUCCESS = "success"
|
|
53
|
+
FAILURE = "failure"
|
|
54
|
+
RETRY = "retry"
|
|
55
|
+
MAX_RETRIES = "max_retries"
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
@dataclass
|
|
59
|
+
class ToolCallMetrics:
|
|
60
|
+
"""Metrics for tool call performance"""
|
|
61
|
+
|
|
62
|
+
total_attempts: int = 0
|
|
63
|
+
successful_calls: int = 0
|
|
64
|
+
failed_calls: int = 0
|
|
65
|
+
retries: int = 0
|
|
66
|
+
avg_latency_ms: float = 0.0
|
|
67
|
+
last_error: Optional[str] = None
|
|
68
|
+
tool_choice_escalations: int = 0
|
|
69
|
+
parallel_calls_requested: int = 0
|
|
70
|
+
parallel_calls_received: int = 0
|
|
71
|
+
|
|
72
|
+
def to_dict(self) -> Dict:
|
|
73
|
+
return asdict(self)
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
class Qwen35ToolCallError(Exception):
|
|
77
|
+
"""Custom exception for Qwen3.5 tool call failures"""
|
|
78
|
+
|
|
79
|
+
pass
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
class Qwen35ToolCallClient:
|
|
83
|
+
"""
|
|
84
|
+
OpenAI-compatible client optimized for Qwen3.5 35B A3B tool calling.
|
|
85
|
+
|
|
86
|
+
Implements 6 strategies for maximum tool call reliability:
|
|
87
|
+
1. tool_choice + parallel_tool_calls in every request
|
|
88
|
+
2. Explicit multi-tool system prompt with format guidance
|
|
89
|
+
3. Retry escalation: auto -> required -> required+lower temp
|
|
90
|
+
4. Per-tool tool_choice for single-tool scenarios
|
|
91
|
+
5. Thinking mode suppression
|
|
92
|
+
6. Dynamic temperature decay on retries
|
|
93
|
+
"""
|
|
94
|
+
|
|
95
|
+
# Default configuration for Qwen3.5 35B A3B (IQ4_XS quant)
|
|
96
|
+
# Tuned for reliable tool calling with MoE architecture
|
|
97
|
+
DEFAULT_CONFIG = {
|
|
98
|
+
"temperature": 0.6,
|
|
99
|
+
"top_p": 0.9,
|
|
100
|
+
"presence_penalty": 0.0,
|
|
101
|
+
"max_tokens": 4096,
|
|
102
|
+
"enable_thinking": False,
|
|
103
|
+
"max_retries": 3,
|
|
104
|
+
"backoff_factor": 2.0,
|
|
105
|
+
"base_url": "http://127.0.0.1:8080/v1",
|
|
106
|
+
"api_key": "not-needed",
|
|
107
|
+
"model": "qwen35-a3b-iq4xs",
|
|
108
|
+
# Strategy 1: Always pass tool_choice and parallel_tool_calls
|
|
109
|
+
"default_tool_choice": "auto",
|
|
110
|
+
"parallel_tool_calls": True,
|
|
111
|
+
# Strategy 2: Improved multi-tool system prompt
|
|
112
|
+
"batch_tool_calls": True,
|
|
113
|
+
"batch_system_prompt": (
|
|
114
|
+
"When multiple tools are needed, emit ALL tool calls in a single response. "
|
|
115
|
+
"Each tool call must be a separate <tool_call>...</tool_call> block. "
|
|
116
|
+
"Do not call one tool and wait for a response before calling the next. "
|
|
117
|
+
"Emit all <tool_call> blocks together in sequence."
|
|
118
|
+
),
|
|
119
|
+
# Strategy 3: Retry escalation
|
|
120
|
+
"escalate_tool_choice": True,
|
|
121
|
+
# Strategy 5: Per-tool tool_choice for single expected tool
|
|
122
|
+
"use_per_tool_choice": True,
|
|
123
|
+
# Dynamic temperature: lower temp for subsequent tool calls
|
|
124
|
+
# in the same conversation to improve format adherence
|
|
125
|
+
"dynamic_temperature": True,
|
|
126
|
+
"dynamic_temp_decay": 0.5, # multiply temp by this for each retry
|
|
127
|
+
"dynamic_temp_floor": 0.2, # minimum temperature
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
def __init__(
|
|
131
|
+
self, config: Optional[Dict[str, Any]] = None, enable_metrics: bool = True
|
|
132
|
+
):
|
|
133
|
+
"""
|
|
134
|
+
Initialize Qwen3.5 tool call client.
|
|
135
|
+
|
|
136
|
+
Args:
|
|
137
|
+
config: Override default configuration
|
|
138
|
+
enable_metrics: Enable performance metrics tracking
|
|
139
|
+
"""
|
|
140
|
+
self.config = {**self.DEFAULT_CONFIG, **(config or {})}
|
|
141
|
+
self.enable_metrics = enable_metrics
|
|
142
|
+
self.metrics = ToolCallMetrics()
|
|
143
|
+
self._client = None
|
|
144
|
+
|
|
145
|
+
# Initialize OpenAI client
|
|
146
|
+
self._init_client()
|
|
147
|
+
|
|
148
|
+
logger.info(f"Qwen35ToolCallClient initialized with config: {self.config}")
|
|
149
|
+
|
|
150
|
+
def _init_client(self):
|
|
151
|
+
"""Initialize OpenAI-compatible client"""
|
|
152
|
+
try:
|
|
153
|
+
self._client = openai.Client(
|
|
154
|
+
base_url=self.config["base_url"], api_key=self.config["api_key"]
|
|
155
|
+
)
|
|
156
|
+
logger.info(f"Connected to {self.config['base_url']}")
|
|
157
|
+
except Exception as e:
|
|
158
|
+
logger.error(f"Failed to initialize OpenAI client: {e}")
|
|
159
|
+
raise Qwen35ToolCallError(f"Client initialization failed: {e}")
|
|
160
|
+
|
|
161
|
+
def _get_tool_choice(
|
|
162
|
+
self,
|
|
163
|
+
tools: List[Dict[str, Any]],
|
|
164
|
+
attempt: int,
|
|
165
|
+
expected_tool: Optional[str] = None,
|
|
166
|
+
) -> Any:
|
|
167
|
+
"""
|
|
168
|
+
Determine tool_choice based on strategy and attempt number.
|
|
169
|
+
|
|
170
|
+
Strategy 3 (escalation):
|
|
171
|
+
- Attempt 0: use default_tool_choice (usually "auto")
|
|
172
|
+
- Attempt 1+: escalate to "required"
|
|
173
|
+
|
|
174
|
+
Strategy 5 (per-tool):
|
|
175
|
+
- If expected_tool is set and only one tool matches, use per-tool choice
|
|
176
|
+
"""
|
|
177
|
+
# Strategy 5: Per-tool choice for single expected tool
|
|
178
|
+
if expected_tool and self.config.get("use_per_tool_choice") and attempt == 0:
|
|
179
|
+
# Find the tool in the definitions
|
|
180
|
+
for tool in tools:
|
|
181
|
+
func = tool.get("function", {})
|
|
182
|
+
if func.get("name") == expected_tool:
|
|
183
|
+
logger.debug(f"Using per-tool choice: {expected_tool}")
|
|
184
|
+
return {
|
|
185
|
+
"type": "function",
|
|
186
|
+
"function": {"name": expected_tool},
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
# Strategy 3: Escalation on retries
|
|
190
|
+
if attempt > 0 and self.config.get("escalate_tool_choice"):
|
|
191
|
+
self.metrics.tool_choice_escalations += 1
|
|
192
|
+
logger.info(f"Escalating tool_choice to 'required' (attempt {attempt + 1})")
|
|
193
|
+
return "required"
|
|
194
|
+
|
|
195
|
+
return self.config.get("default_tool_choice", "auto")
|
|
196
|
+
|
|
197
|
+
def chat_with_tools(
|
|
198
|
+
self,
|
|
199
|
+
messages: List[Dict[str, str]],
|
|
200
|
+
tools: List[Dict[str, Any]],
|
|
201
|
+
max_retries: Optional[int] = None,
|
|
202
|
+
timeout: int = 120,
|
|
203
|
+
expected_tool: Optional[str] = None,
|
|
204
|
+
expected_tool_calls: Optional[int] = None,
|
|
205
|
+
**kwargs,
|
|
206
|
+
) -> openai.types.chat.ChatCompletion:
|
|
207
|
+
"""
|
|
208
|
+
Chat completion with automatic retry on tool call failures.
|
|
209
|
+
|
|
210
|
+
Implements all 6 strategies:
|
|
211
|
+
1. tool_choice + parallel_tool_calls in every request
|
|
212
|
+
2. Multi-tool system prompt injection
|
|
213
|
+
3. Retry escalation (auto -> required -> required+lower temp)
|
|
214
|
+
4. Per-tool tool_choice for single-tool scenarios
|
|
215
|
+
5. Thinking mode suppression
|
|
216
|
+
6. Dynamic temperature decay
|
|
217
|
+
|
|
218
|
+
Args:
|
|
219
|
+
messages: List of chat messages
|
|
220
|
+
tools: List of tool definitions
|
|
221
|
+
max_retries: Override default max retries
|
|
222
|
+
timeout: Request timeout in seconds
|
|
223
|
+
expected_tool: If set, use per-tool tool_choice (Strategy 5)
|
|
224
|
+
expected_tool_calls: Expected number of tool calls (for validation)
|
|
225
|
+
**kwargs: Additional parameters passed to OpenAI API
|
|
226
|
+
|
|
227
|
+
Returns:
|
|
228
|
+
ChatCompletion response with tool calls
|
|
229
|
+
|
|
230
|
+
Raises:
|
|
231
|
+
Qwen35ToolCallError: After max retries exhausted
|
|
232
|
+
"""
|
|
233
|
+
max_retries = max_retries or self.config["max_retries"]
|
|
234
|
+
|
|
235
|
+
# Track timing
|
|
236
|
+
start_time = time.time()
|
|
237
|
+
|
|
238
|
+
# Make a copy of messages to avoid modifying original
|
|
239
|
+
current_messages = [msg.copy() for msg in messages]
|
|
240
|
+
|
|
241
|
+
# Strategy 2: Inject multi-tool system prompt
|
|
242
|
+
if self.config.get("batch_tool_calls") and len(tools) > 1:
|
|
243
|
+
batch_prompt = self.config.get("batch_system_prompt", "")
|
|
244
|
+
if batch_prompt:
|
|
245
|
+
has_system = any(m.get("role") == "system" for m in current_messages)
|
|
246
|
+
if has_system:
|
|
247
|
+
for m in current_messages:
|
|
248
|
+
if m.get("role") == "system":
|
|
249
|
+
m["content"] = m["content"] + "\n\n" + batch_prompt
|
|
250
|
+
break
|
|
251
|
+
else:
|
|
252
|
+
current_messages.insert(
|
|
253
|
+
0,
|
|
254
|
+
{"role": "system", "content": batch_prompt},
|
|
255
|
+
)
|
|
256
|
+
|
|
257
|
+
# Track parallel call expectations
|
|
258
|
+
if expected_tool_calls and expected_tool_calls > 1:
|
|
259
|
+
self.metrics.parallel_calls_requested += 1
|
|
260
|
+
|
|
261
|
+
# Base temperature for dynamic adjustment
|
|
262
|
+
base_temperature = self.config["temperature"]
|
|
263
|
+
|
|
264
|
+
for attempt in range(max_retries):
|
|
265
|
+
self.metrics.total_attempts += 1
|
|
266
|
+
|
|
267
|
+
# Strategy 6: Dynamic temperature - reduce on retries
|
|
268
|
+
if self.config.get("dynamic_temperature") and attempt > 0:
|
|
269
|
+
decay = self.config.get("dynamic_temp_decay", 0.5)
|
|
270
|
+
floor = self.config.get("dynamic_temp_floor", 0.2)
|
|
271
|
+
current_temp = max(floor, base_temperature * (decay**attempt))
|
|
272
|
+
logger.info(
|
|
273
|
+
f"Dynamic temperature: {current_temp:.2f} (attempt {attempt + 1})"
|
|
274
|
+
)
|
|
275
|
+
else:
|
|
276
|
+
current_temp = base_temperature
|
|
277
|
+
|
|
278
|
+
# Strategy 1 + 3 + 5: Determine tool_choice
|
|
279
|
+
tool_choice = self._get_tool_choice(tools, attempt, expected_tool)
|
|
280
|
+
|
|
281
|
+
try:
|
|
282
|
+
# Build request with all strategies applied
|
|
283
|
+
request_params = {
|
|
284
|
+
"model": self.config["model"],
|
|
285
|
+
"messages": current_messages,
|
|
286
|
+
"tools": tools,
|
|
287
|
+
"tool_choice": tool_choice, # Strategy 1
|
|
288
|
+
"parallel_tool_calls": self.config.get(
|
|
289
|
+
"parallel_tool_calls", True
|
|
290
|
+
), # Strategy 1
|
|
291
|
+
"temperature": current_temp,
|
|
292
|
+
"top_p": self.config["top_p"],
|
|
293
|
+
"presence_penalty": self.config["presence_penalty"],
|
|
294
|
+
"max_tokens": self.config["max_tokens"],
|
|
295
|
+
"timeout": timeout,
|
|
296
|
+
"extra_body": {
|
|
297
|
+
"chat_template_kwargs": {
|
|
298
|
+
"enable_thinking": self.config[
|
|
299
|
+
"enable_thinking"
|
|
300
|
+
] # Strategy 5 (thinking suppression)
|
|
301
|
+
}
|
|
302
|
+
},
|
|
303
|
+
**kwargs,
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
logger.debug(
|
|
307
|
+
f"Attempt {attempt + 1}/{max_retries}: "
|
|
308
|
+
f"tool_choice={tool_choice}, temp={current_temp:.2f}, "
|
|
309
|
+
f"parallel={self.config.get('parallel_tool_calls', True)}"
|
|
310
|
+
)
|
|
311
|
+
|
|
312
|
+
# Make API call
|
|
313
|
+
response = self._client.chat.completions.create(**request_params)
|
|
314
|
+
|
|
315
|
+
# Validate response
|
|
316
|
+
tool_calls = response.choices[0].message.tool_calls
|
|
317
|
+
|
|
318
|
+
if self._validate_tool_call(tool_calls):
|
|
319
|
+
# Success!
|
|
320
|
+
self.metrics.successful_calls += 1
|
|
321
|
+
|
|
322
|
+
# Track parallel call success
|
|
323
|
+
if tool_calls and len(tool_calls) > 1:
|
|
324
|
+
self.metrics.parallel_calls_received += 1
|
|
325
|
+
|
|
326
|
+
# Calculate latency
|
|
327
|
+
latency_ms = (time.time() - start_time) * 1000
|
|
328
|
+
self.metrics.avg_latency_ms = latency_ms
|
|
329
|
+
|
|
330
|
+
logger.info(
|
|
331
|
+
f"Tool call successful after {attempt + 1} attempt(s): "
|
|
332
|
+
f"{len(tool_calls)} call(s)"
|
|
333
|
+
)
|
|
334
|
+
return response
|
|
335
|
+
else:
|
|
336
|
+
# Invalid format, retry with correction
|
|
337
|
+
logger.warning(f"Invalid tool call format on attempt {attempt + 1}")
|
|
338
|
+
current_messages = self._correct_prompt(current_messages, response)
|
|
339
|
+
self.metrics.retries += 1
|
|
340
|
+
|
|
341
|
+
if attempt < max_retries - 1:
|
|
342
|
+
# Exponential backoff
|
|
343
|
+
backoff = self.config["backoff_factor"] ** attempt
|
|
344
|
+
time.sleep(backoff)
|
|
345
|
+
logger.info(f"Retrying in {backoff:.1f}s...")
|
|
346
|
+
|
|
347
|
+
except Exception as e:
|
|
348
|
+
self.metrics.last_error = str(e)
|
|
349
|
+
logger.error(f"Error on attempt {attempt + 1}: {e}")
|
|
350
|
+
|
|
351
|
+
if attempt == max_retries - 1:
|
|
352
|
+
# Last attempt failed
|
|
353
|
+
self.metrics.failed_calls += 1
|
|
354
|
+
raise Qwen35ToolCallError(
|
|
355
|
+
f"Failed after {max_retries} attempts: {str(e)}"
|
|
356
|
+
)
|
|
357
|
+
|
|
358
|
+
# Retry with backoff
|
|
359
|
+
backoff = self.config["backoff_factor"] ** attempt
|
|
360
|
+
time.sleep(backoff)
|
|
361
|
+
|
|
362
|
+
# Should not reach here, but just in case
|
|
363
|
+
self.metrics.failed_calls += 1
|
|
364
|
+
raise Qwen35ToolCallError("Max retries exceeded")
|
|
365
|
+
|
|
366
|
+
def _validate_tool_call(self, tool_calls) -> bool:
|
|
367
|
+
"""
|
|
368
|
+
Validate that tool call has correct format.
|
|
369
|
+
|
|
370
|
+
Checks for:
|
|
371
|
+
- Non-empty tool calls list
|
|
372
|
+
- Valid function name
|
|
373
|
+
- Parseable JSON arguments (OpenAI-compatible API returns JSON)
|
|
374
|
+
- No reasoning content leakage (<thinking>/<think> tags in arguments)
|
|
375
|
+
"""
|
|
376
|
+
if not tool_calls:
|
|
377
|
+
logger.debug("No tool calls returned")
|
|
378
|
+
return False
|
|
379
|
+
|
|
380
|
+
for tool_call in tool_calls:
|
|
381
|
+
# Check function name exists
|
|
382
|
+
if not tool_call.function or not tool_call.function.name:
|
|
383
|
+
logger.debug("Tool call missing function name")
|
|
384
|
+
return False
|
|
385
|
+
|
|
386
|
+
# Check arguments are present
|
|
387
|
+
arguments = tool_call.function.arguments
|
|
388
|
+
if not arguments:
|
|
389
|
+
logger.debug("Tool call missing arguments")
|
|
390
|
+
return False
|
|
391
|
+
|
|
392
|
+
# Check for thinking/reasoning tag leakage in arguments
|
|
393
|
+
if "<thinking>" in arguments or "</thinking>" in arguments:
|
|
394
|
+
logger.debug("Thinking tag leakage detected in arguments")
|
|
395
|
+
return False
|
|
396
|
+
|
|
397
|
+
if "<think>" in arguments or "</think>" in arguments:
|
|
398
|
+
logger.debug("Think tag leakage detected in arguments")
|
|
399
|
+
return False
|
|
400
|
+
|
|
401
|
+
# Validate arguments are parseable JSON
|
|
402
|
+
try:
|
|
403
|
+
parsed = json.loads(arguments)
|
|
404
|
+
if not isinstance(parsed, dict):
|
|
405
|
+
logger.debug(f"Arguments not a JSON object: {type(parsed)}")
|
|
406
|
+
return False
|
|
407
|
+
except (json.JSONDecodeError, TypeError) as e:
|
|
408
|
+
logger.debug(f"Arguments not valid JSON: {e}")
|
|
409
|
+
return False
|
|
410
|
+
|
|
411
|
+
return True
|
|
412
|
+
|
|
413
|
+
def _correct_prompt(
|
|
414
|
+
self, messages: List[Dict], response: openai.types.chat.ChatCompletion
|
|
415
|
+
) -> List[Dict]:
|
|
416
|
+
"""
|
|
417
|
+
Correct prompt after invalid tool call.
|
|
418
|
+
|
|
419
|
+
Appends correction message to guide model toward proper format.
|
|
420
|
+
Uses the official Qwen3 <tool_call> format.
|
|
421
|
+
"""
|
|
422
|
+
invalid_content = response.choices[0].message.content or ""
|
|
423
|
+
|
|
424
|
+
# Add assistant's failed attempt
|
|
425
|
+
messages.append(
|
|
426
|
+
{
|
|
427
|
+
"role": "assistant",
|
|
428
|
+
"content": f"I attempted a tool call but the format was invalid: "
|
|
429
|
+
f"{invalid_content[:200]}",
|
|
430
|
+
}
|
|
431
|
+
)
|
|
432
|
+
|
|
433
|
+
# Add user correction matching the chat template format
|
|
434
|
+
messages.append(
|
|
435
|
+
{
|
|
436
|
+
"role": "user",
|
|
437
|
+
"content": "Please call the tool using the correct format. "
|
|
438
|
+
"You must use the tool calling interface - respond with a tool call, "
|
|
439
|
+
"not with text describing the call. "
|
|
440
|
+
"Use <tool_call> tags with a JSON object containing 'name' and 'arguments' keys.",
|
|
441
|
+
}
|
|
442
|
+
)
|
|
443
|
+
|
|
444
|
+
return messages
|
|
445
|
+
|
|
446
|
+
def execute_tool_call(
|
|
447
|
+
self, tool_calls: List, tool_functions: Dict[str, callable]
|
|
448
|
+
) -> List[Any]:
|
|
449
|
+
"""
|
|
450
|
+
Execute tool calls and collect results.
|
|
451
|
+
|
|
452
|
+
Args:
|
|
453
|
+
tool_calls: List of tool call objects from response
|
|
454
|
+
tool_functions: Dict mapping tool names to functions
|
|
455
|
+
|
|
456
|
+
Returns:
|
|
457
|
+
List of tool results
|
|
458
|
+
"""
|
|
459
|
+
results = []
|
|
460
|
+
|
|
461
|
+
for tool_call in tool_calls:
|
|
462
|
+
tool_name = tool_call.function.name
|
|
463
|
+
tool_args = json.loads(tool_call.function.arguments)
|
|
464
|
+
|
|
465
|
+
logger.info(f"Executing tool: {tool_name} with args: {tool_args}")
|
|
466
|
+
|
|
467
|
+
if tool_name not in tool_functions:
|
|
468
|
+
results.append(
|
|
469
|
+
{
|
|
470
|
+
"tool_name": tool_name,
|
|
471
|
+
"status": "error",
|
|
472
|
+
"error": f"Tool '{tool_name}' not found",
|
|
473
|
+
}
|
|
474
|
+
)
|
|
475
|
+
continue
|
|
476
|
+
|
|
477
|
+
try:
|
|
478
|
+
result = tool_functions[tool_name](**tool_args)
|
|
479
|
+
results.append(
|
|
480
|
+
{"tool_name": tool_name, "status": "success", "result": result}
|
|
481
|
+
)
|
|
482
|
+
except Exception as e:
|
|
483
|
+
results.append(
|
|
484
|
+
{"tool_name": tool_name, "status": "error", "error": str(e)}
|
|
485
|
+
)
|
|
486
|
+
|
|
487
|
+
return results
|
|
488
|
+
|
|
489
|
+
def get_metrics(self) -> ToolCallMetrics:
|
|
490
|
+
"""Get current metrics"""
|
|
491
|
+
return self.metrics
|
|
492
|
+
|
|
493
|
+
def reset_metrics(self):
|
|
494
|
+
"""Reset metrics counters"""
|
|
495
|
+
self.metrics = ToolCallMetrics()
|
|
496
|
+
logger.info("Metrics reset")
|
|
497
|
+
|
|
498
|
+
def get_status(self) -> Dict:
|
|
499
|
+
"""Get client status"""
|
|
500
|
+
return {
|
|
501
|
+
"model": self.config["model"],
|
|
502
|
+
"base_url": self.config["base_url"],
|
|
503
|
+
"metrics": self.metrics.to_dict(),
|
|
504
|
+
"config": {
|
|
505
|
+
k: v for k, v in self.config.items() if k not in ["base_url", "api_key"]
|
|
506
|
+
},
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
|
|
510
|
+
class Qwen35ToolCallAgent:
|
|
511
|
+
"""
|
|
512
|
+
Higher-level agent for Qwen3.5 tool calling workflows.
|
|
513
|
+
|
|
514
|
+
Combines tool calling with execution and result handling.
|
|
515
|
+
|
|
516
|
+
Args:
|
|
517
|
+
tool_definitions: List of OpenAI-format tool definitions (for the API)
|
|
518
|
+
tool_implementations: Dict mapping tool names to callable functions (for execution)
|
|
519
|
+
client_config: Configuration for tool call client
|
|
520
|
+
"""
|
|
521
|
+
|
|
522
|
+
def __init__(
|
|
523
|
+
self,
|
|
524
|
+
tool_definitions: List[Dict[str, Any]],
|
|
525
|
+
tool_implementations: Dict[str, callable],
|
|
526
|
+
client_config: Optional[Dict] = None,
|
|
527
|
+
):
|
|
528
|
+
self.tool_definitions = tool_definitions
|
|
529
|
+
self.tool_implementations = tool_implementations
|
|
530
|
+
self.client = Qwen35ToolCallClient(client_config)
|
|
531
|
+
|
|
532
|
+
logger.info(
|
|
533
|
+
f"Qwen35ToolCallAgent initialized with {len(tool_definitions)} tools: "
|
|
534
|
+
f"{list(tool_implementations.keys())}"
|
|
535
|
+
)
|
|
536
|
+
|
|
537
|
+
def run(
|
|
538
|
+
self,
|
|
539
|
+
user_query: str,
|
|
540
|
+
additional_messages: Optional[List[Dict]] = None,
|
|
541
|
+
expected_tool: Optional[str] = None,
|
|
542
|
+
) -> Tuple[openai.types.chat.ChatCompletion, List[Any]]:
|
|
543
|
+
"""
|
|
544
|
+
Run a complete tool calling workflow.
|
|
545
|
+
|
|
546
|
+
Args:
|
|
547
|
+
user_query: User's input query
|
|
548
|
+
additional_messages: Optional additional conversation history
|
|
549
|
+
expected_tool: If set, use per-tool tool_choice
|
|
550
|
+
|
|
551
|
+
Returns:
|
|
552
|
+
Tuple of (ChatCompletion response, List of tool results)
|
|
553
|
+
"""
|
|
554
|
+
# Build messages
|
|
555
|
+
messages = []
|
|
556
|
+
|
|
557
|
+
if additional_messages:
|
|
558
|
+
messages.extend(additional_messages)
|
|
559
|
+
|
|
560
|
+
messages.append({"role": "user", "content": user_query})
|
|
561
|
+
|
|
562
|
+
# Make tool call request (pass definitions to API)
|
|
563
|
+
response = self.client.chat_with_tools(
|
|
564
|
+
messages=messages,
|
|
565
|
+
tools=self.tool_definitions,
|
|
566
|
+
expected_tool=expected_tool,
|
|
567
|
+
)
|
|
568
|
+
|
|
569
|
+
# Execute tool calls (pass implementations for execution)
|
|
570
|
+
tool_calls = response.choices[0].message.tool_calls
|
|
571
|
+
|
|
572
|
+
if tool_calls:
|
|
573
|
+
results = self.client.execute_tool_call(
|
|
574
|
+
tool_calls, self.tool_implementations
|
|
575
|
+
)
|
|
576
|
+
else:
|
|
577
|
+
results = []
|
|
578
|
+
|
|
579
|
+
return response, results
|
|
580
|
+
|
|
581
|
+
def get_status(self) -> Dict:
|
|
582
|
+
"""Get agent status"""
|
|
583
|
+
return {
|
|
584
|
+
"tools": list(self.tool_implementations.keys()),
|
|
585
|
+
"client_status": self.client.get_status(),
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
|
|
589
|
+
# Convenience function for simple use cases
|
|
590
|
+
def qwen35_chat_with_tools(
|
|
591
|
+
user_query: str,
|
|
592
|
+
tool_definitions: List[Dict],
|
|
593
|
+
tool_implementations: Dict[str, callable],
|
|
594
|
+
config: Optional[Dict] = None,
|
|
595
|
+
) -> Tuple[openai.types.chat.ChatCompletion, List[Any]]:
|
|
596
|
+
"""
|
|
597
|
+
Simple function for quick tool calling with Qwen3.5.
|
|
598
|
+
|
|
599
|
+
Args:
|
|
600
|
+
user_query: User's input
|
|
601
|
+
tool_definitions: OpenAI-format tool definitions
|
|
602
|
+
tool_implementations: Dict mapping tool names to callables
|
|
603
|
+
config: Optional configuration
|
|
604
|
+
|
|
605
|
+
Returns:
|
|
606
|
+
Tuple of (response, results)
|
|
607
|
+
"""
|
|
608
|
+
agent = Qwen35ToolCallAgent(tool_definitions, tool_implementations, config)
|
|
609
|
+
return agent.run(user_query)
|
|
610
|
+
|
|
611
|
+
|
|
612
|
+
# Example usage
|
|
613
|
+
if __name__ == "__main__":
|
|
614
|
+
# Example tool implementations (actual callables)
|
|
615
|
+
def read_file(path: str) -> str:
|
|
616
|
+
"""Read file contents"""
|
|
617
|
+
with open(path, "r") as f:
|
|
618
|
+
return f.read()
|
|
619
|
+
|
|
620
|
+
def get_weather(city: str) -> str:
|
|
621
|
+
"""Get weather for city"""
|
|
622
|
+
return f"Weather in {city}: Sunny, 25C"
|
|
623
|
+
|
|
624
|
+
# Tool implementations: name -> callable
|
|
625
|
+
implementations = {
|
|
626
|
+
"read_file": read_file,
|
|
627
|
+
"get_weather": get_weather,
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
# Tool definitions: OpenAI-format schemas (sent to the API)
|
|
631
|
+
definitions = [
|
|
632
|
+
{
|
|
633
|
+
"type": "function",
|
|
634
|
+
"function": {
|
|
635
|
+
"name": "read_file",
|
|
636
|
+
"description": "Read file contents",
|
|
637
|
+
"parameters": {
|
|
638
|
+
"type": "object",
|
|
639
|
+
"properties": {"path": {"type": "string"}},
|
|
640
|
+
"required": ["path"],
|
|
641
|
+
},
|
|
642
|
+
},
|
|
643
|
+
},
|
|
644
|
+
{
|
|
645
|
+
"type": "function",
|
|
646
|
+
"function": {
|
|
647
|
+
"name": "get_weather",
|
|
648
|
+
"description": "Get weather information",
|
|
649
|
+
"parameters": {
|
|
650
|
+
"type": "object",
|
|
651
|
+
"properties": {"city": {"type": "string"}},
|
|
652
|
+
"required": ["city"],
|
|
653
|
+
},
|
|
654
|
+
},
|
|
655
|
+
},
|
|
656
|
+
]
|
|
657
|
+
|
|
658
|
+
# Initialize agent with both definitions and implementations
|
|
659
|
+
agent = Qwen35ToolCallAgent(definitions, implementations)
|
|
660
|
+
|
|
661
|
+
# Run example
|
|
662
|
+
try:
|
|
663
|
+
response, results = agent.run("Read /etc/hosts and get weather in Sydney")
|
|
664
|
+
|
|
665
|
+
print("\n=== Tool Call Results ===")
|
|
666
|
+
for result in results:
|
|
667
|
+
print(f"Tool: {result['tool_name']}")
|
|
668
|
+
print(f"Status: {result['status']}")
|
|
669
|
+
if result["status"] == "success":
|
|
670
|
+
print(f"Result: {str(result['result'])[:200]}...")
|
|
671
|
+
else:
|
|
672
|
+
print(f"Error: {result['error']}")
|
|
673
|
+
|
|
674
|
+
print("\n=== Metrics ===")
|
|
675
|
+
metrics = agent.client.get_metrics()
|
|
676
|
+
print(f"Total attempts: {metrics.total_attempts}")
|
|
677
|
+
print(f"Successful calls: {metrics.successful_calls}")
|
|
678
|
+
print(f"Escalations: {metrics.tool_choice_escalations}")
|
|
679
|
+
print(f"Parallel requested: {metrics.parallel_calls_requested}")
|
|
680
|
+
print(f"Parallel received: {metrics.parallel_calls_received}")
|
|
681
|
+
print(
|
|
682
|
+
f"Success rate: {metrics.successful_calls / metrics.total_attempts * 100:.1f}%"
|
|
683
|
+
)
|
|
684
|
+
|
|
685
|
+
except Qwen35ToolCallError as e:
|
|
686
|
+
print(f"Tool call failed: {e}")
|