@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.
Files changed (660) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +888 -0
  3. package/dist/analyzers/index.d.ts +3 -0
  4. package/dist/analyzers/index.d.ts.map +1 -0
  5. package/dist/analyzers/index.js +684 -0
  6. package/dist/analyzers/index.js.map +1 -0
  7. package/dist/benchmarks/agents/naive-agent.d.ts +60 -0
  8. package/dist/benchmarks/agents/naive-agent.d.ts.map +1 -0
  9. package/dist/benchmarks/agents/naive-agent.js +144 -0
  10. package/dist/benchmarks/agents/naive-agent.js.map +1 -0
  11. package/dist/benchmarks/agents/uap-agent.d.ts +167 -0
  12. package/dist/benchmarks/agents/uap-agent.d.ts.map +1 -0
  13. package/dist/benchmarks/agents/uap-agent.js +437 -0
  14. package/dist/benchmarks/agents/uap-agent.js.map +1 -0
  15. package/dist/benchmarks/benchmark.d.ts +328 -0
  16. package/dist/benchmarks/benchmark.d.ts.map +1 -0
  17. package/dist/benchmarks/benchmark.js +112 -0
  18. package/dist/benchmarks/benchmark.js.map +1 -0
  19. package/dist/benchmarks/execution-verifier.d.ts +41 -0
  20. package/dist/benchmarks/execution-verifier.d.ts.map +1 -0
  21. package/dist/benchmarks/execution-verifier.js +340 -0
  22. package/dist/benchmarks/execution-verifier.js.map +1 -0
  23. package/dist/benchmarks/hierarchical-prompting.d.ts +37 -0
  24. package/dist/benchmarks/hierarchical-prompting.d.ts.map +1 -0
  25. package/dist/benchmarks/hierarchical-prompting.js +246 -0
  26. package/dist/benchmarks/hierarchical-prompting.js.map +1 -0
  27. package/dist/benchmarks/improved-benchmark.d.ts +89 -0
  28. package/dist/benchmarks/improved-benchmark.d.ts.map +1 -0
  29. package/dist/benchmarks/improved-benchmark.js +585 -0
  30. package/dist/benchmarks/improved-benchmark.js.map +1 -0
  31. package/dist/benchmarks/index.d.ts +11 -0
  32. package/dist/benchmarks/index.d.ts.map +1 -0
  33. package/dist/benchmarks/index.js +11 -0
  34. package/dist/benchmarks/index.js.map +1 -0
  35. package/dist/benchmarks/model-integration.d.ts +111 -0
  36. package/dist/benchmarks/model-integration.d.ts.map +1 -0
  37. package/dist/benchmarks/model-integration.js +904 -0
  38. package/dist/benchmarks/model-integration.js.map +1 -0
  39. package/dist/benchmarks/multi-turn-agent.d.ts +44 -0
  40. package/dist/benchmarks/multi-turn-agent.d.ts.map +1 -0
  41. package/dist/benchmarks/multi-turn-agent.js +254 -0
  42. package/dist/benchmarks/multi-turn-agent.js.map +1 -0
  43. package/dist/benchmarks/multi-turn-loop.d.ts +57 -0
  44. package/dist/benchmarks/multi-turn-loop.d.ts.map +1 -0
  45. package/dist/benchmarks/multi-turn-loop.js +167 -0
  46. package/dist/benchmarks/multi-turn-loop.js.map +1 -0
  47. package/dist/benchmarks/tasks.d.ts +19 -0
  48. package/dist/benchmarks/tasks.d.ts.map +1 -0
  49. package/dist/benchmarks/tasks.js +435 -0
  50. package/dist/benchmarks/tasks.js.map +1 -0
  51. package/dist/bin/cli.d.ts +3 -0
  52. package/dist/bin/cli.d.ts.map +1 -0
  53. package/dist/bin/cli.js +546 -0
  54. package/dist/bin/cli.js.map +1 -0
  55. package/dist/bin/llama-server-optimize.d.ts +18 -0
  56. package/dist/bin/llama-server-optimize.d.ts.map +1 -0
  57. package/dist/bin/llama-server-optimize.js +708 -0
  58. package/dist/bin/llama-server-optimize.js.map +1 -0
  59. package/dist/bin/policy.d.ts +3 -0
  60. package/dist/bin/policy.d.ts.map +1 -0
  61. package/dist/bin/policy.js +143 -0
  62. package/dist/bin/policy.js.map +1 -0
  63. package/dist/bin/tool-calls.d.ts +3 -0
  64. package/dist/bin/tool-calls.d.ts.map +1 -0
  65. package/dist/bin/tool-calls.js +4 -0
  66. package/dist/bin/tool-calls.js.map +1 -0
  67. package/dist/browser/index.d.ts +2 -0
  68. package/dist/browser/index.d.ts.map +1 -0
  69. package/dist/browser/index.js +2 -0
  70. package/dist/browser/index.js.map +1 -0
  71. package/dist/browser/web-browser.d.ts +30 -0
  72. package/dist/browser/web-browser.d.ts.map +1 -0
  73. package/dist/browser/web-browser.js +93 -0
  74. package/dist/browser/web-browser.js.map +1 -0
  75. package/dist/cli/agent.d.ts +20 -0
  76. package/dist/cli/agent.d.ts.map +1 -0
  77. package/dist/cli/agent.js +474 -0
  78. package/dist/cli/agent.js.map +1 -0
  79. package/dist/cli/analyze.d.ts +7 -0
  80. package/dist/cli/analyze.d.ts.map +1 -0
  81. package/dist/cli/analyze.js +103 -0
  82. package/dist/cli/analyze.js.map +1 -0
  83. package/dist/cli/completion-gates.d.ts +51 -0
  84. package/dist/cli/completion-gates.d.ts.map +1 -0
  85. package/dist/cli/completion-gates.js +201 -0
  86. package/dist/cli/completion-gates.js.map +1 -0
  87. package/dist/cli/compliance.d.ts +8 -0
  88. package/dist/cli/compliance.d.ts.map +1 -0
  89. package/dist/cli/compliance.js +509 -0
  90. package/dist/cli/compliance.js.map +1 -0
  91. package/dist/cli/coord.d.ts +7 -0
  92. package/dist/cli/coord.d.ts.map +1 -0
  93. package/dist/cli/coord.js +138 -0
  94. package/dist/cli/coord.js.map +1 -0
  95. package/dist/cli/dashboard.d.ts +21 -0
  96. package/dist/cli/dashboard.d.ts.map +1 -0
  97. package/dist/cli/dashboard.js +1508 -0
  98. package/dist/cli/dashboard.js.map +1 -0
  99. package/dist/cli/deploy.d.ts +19 -0
  100. package/dist/cli/deploy.d.ts.map +1 -0
  101. package/dist/cli/deploy.js +387 -0
  102. package/dist/cli/deploy.js.map +1 -0
  103. package/dist/cli/droids.d.ts +9 -0
  104. package/dist/cli/droids.d.ts.map +1 -0
  105. package/dist/cli/droids.js +227 -0
  106. package/dist/cli/droids.js.map +1 -0
  107. package/dist/cli/generate.d.ts +17 -0
  108. package/dist/cli/generate.d.ts.map +1 -0
  109. package/dist/cli/generate.js +432 -0
  110. package/dist/cli/generate.js.map +1 -0
  111. package/dist/cli/hooks.d.ts +9 -0
  112. package/dist/cli/hooks.d.ts.map +1 -0
  113. package/dist/cli/hooks.js +464 -0
  114. package/dist/cli/hooks.js.map +1 -0
  115. package/dist/cli/init.d.ts +12 -0
  116. package/dist/cli/init.d.ts.map +1 -0
  117. package/dist/cli/init.js +364 -0
  118. package/dist/cli/init.js.map +1 -0
  119. package/dist/cli/mcp-router.d.ts +16 -0
  120. package/dist/cli/mcp-router.d.ts.map +1 -0
  121. package/dist/cli/mcp-router.js +143 -0
  122. package/dist/cli/mcp-router.js.map +1 -0
  123. package/dist/cli/memory.d.ts +24 -0
  124. package/dist/cli/memory.d.ts.map +1 -0
  125. package/dist/cli/memory.js +885 -0
  126. package/dist/cli/memory.js.map +1 -0
  127. package/dist/cli/model.d.ts +15 -0
  128. package/dist/cli/model.d.ts.map +1 -0
  129. package/dist/cli/model.js +290 -0
  130. package/dist/cli/model.js.map +1 -0
  131. package/dist/cli/patterns.d.ts +26 -0
  132. package/dist/cli/patterns.d.ts.map +1 -0
  133. package/dist/cli/patterns.js +862 -0
  134. package/dist/cli/patterns.js.map +1 -0
  135. package/dist/cli/rtk-validation.d.ts +9 -0
  136. package/dist/cli/rtk-validation.d.ts.map +1 -0
  137. package/dist/cli/rtk-validation.js +9 -0
  138. package/dist/cli/rtk-validation.js.map +1 -0
  139. package/dist/cli/rtk.d.ts +34 -0
  140. package/dist/cli/rtk.d.ts.map +1 -0
  141. package/dist/cli/rtk.js +401 -0
  142. package/dist/cli/rtk.js.map +1 -0
  143. package/dist/cli/schema-diff.d.ts +7 -0
  144. package/dist/cli/schema-diff.d.ts.map +1 -0
  145. package/dist/cli/schema-diff.js +11 -0
  146. package/dist/cli/schema-diff.js.map +1 -0
  147. package/dist/cli/setup-mcp-router.d.ts +8 -0
  148. package/dist/cli/setup-mcp-router.d.ts.map +1 -0
  149. package/dist/cli/setup-mcp-router.js +163 -0
  150. package/dist/cli/setup-mcp-router.js.map +1 -0
  151. package/dist/cli/setup-wizard.d.ts +2 -0
  152. package/dist/cli/setup-wizard.d.ts.map +1 -0
  153. package/dist/cli/setup-wizard.js +806 -0
  154. package/dist/cli/setup-wizard.js.map +1 -0
  155. package/dist/cli/setup.d.ts +15 -0
  156. package/dist/cli/setup.d.ts.map +1 -0
  157. package/dist/cli/setup.js +154 -0
  158. package/dist/cli/setup.js.map +1 -0
  159. package/dist/cli/sync.d.ts +8 -0
  160. package/dist/cli/sync.d.ts.map +1 -0
  161. package/dist/cli/sync.js +395 -0
  162. package/dist/cli/sync.js.map +1 -0
  163. package/dist/cli/task.d.ts +33 -0
  164. package/dist/cli/task.d.ts.map +1 -0
  165. package/dist/cli/task.js +672 -0
  166. package/dist/cli/task.js.map +1 -0
  167. package/dist/cli/tool-calls.d.ts +20 -0
  168. package/dist/cli/tool-calls.d.ts.map +1 -0
  169. package/dist/cli/tool-calls.js +605 -0
  170. package/dist/cli/tool-calls.js.map +1 -0
  171. package/dist/cli/uap.d.ts +10 -0
  172. package/dist/cli/uap.d.ts.map +1 -0
  173. package/dist/cli/uap.js +398 -0
  174. package/dist/cli/uap.js.map +1 -0
  175. package/dist/cli/update.d.ts +10 -0
  176. package/dist/cli/update.d.ts.map +1 -0
  177. package/dist/cli/update.js +300 -0
  178. package/dist/cli/update.js.map +1 -0
  179. package/dist/cli/visualize.d.ts +77 -0
  180. package/dist/cli/visualize.d.ts.map +1 -0
  181. package/dist/cli/visualize.js +287 -0
  182. package/dist/cli/visualize.js.map +1 -0
  183. package/dist/cli/worktree.d.ts +9 -0
  184. package/dist/cli/worktree.d.ts.map +1 -0
  185. package/dist/cli/worktree.js +213 -0
  186. package/dist/cli/worktree.js.map +1 -0
  187. package/dist/coordination/adaptive-patterns.d.ts +65 -0
  188. package/dist/coordination/adaptive-patterns.d.ts.map +1 -0
  189. package/dist/coordination/adaptive-patterns.js +108 -0
  190. package/dist/coordination/adaptive-patterns.js.map +1 -0
  191. package/dist/coordination/auto-agent.d.ts +82 -0
  192. package/dist/coordination/auto-agent.d.ts.map +1 -0
  193. package/dist/coordination/auto-agent.js +145 -0
  194. package/dist/coordination/auto-agent.js.map +1 -0
  195. package/dist/coordination/capability-router.d.ts +79 -0
  196. package/dist/coordination/capability-router.d.ts.map +1 -0
  197. package/dist/coordination/capability-router.js +334 -0
  198. package/dist/coordination/capability-router.js.map +1 -0
  199. package/dist/coordination/database.d.ts +13 -0
  200. package/dist/coordination/database.d.ts.map +1 -0
  201. package/dist/coordination/database.js +136 -0
  202. package/dist/coordination/database.js.map +1 -0
  203. package/dist/coordination/deploy-batcher.d.ts +122 -0
  204. package/dist/coordination/deploy-batcher.d.ts.map +1 -0
  205. package/dist/coordination/deploy-batcher.js +718 -0
  206. package/dist/coordination/deploy-batcher.js.map +1 -0
  207. package/dist/coordination/droid-validator.d.ts +59 -0
  208. package/dist/coordination/droid-validator.d.ts.map +1 -0
  209. package/dist/coordination/droid-validator.js +142 -0
  210. package/dist/coordination/droid-validator.js.map +1 -0
  211. package/dist/coordination/index.d.ts +10 -0
  212. package/dist/coordination/index.d.ts.map +1 -0
  213. package/dist/coordination/index.js +10 -0
  214. package/dist/coordination/index.js.map +1 -0
  215. package/dist/coordination/pattern-router.d.ts +50 -0
  216. package/dist/coordination/pattern-router.d.ts.map +1 -0
  217. package/dist/coordination/pattern-router.js +118 -0
  218. package/dist/coordination/pattern-router.js.map +1 -0
  219. package/dist/coordination/service.d.ts +81 -0
  220. package/dist/coordination/service.d.ts.map +1 -0
  221. package/dist/coordination/service.js +619 -0
  222. package/dist/coordination/service.js.map +1 -0
  223. package/dist/coordination/worktree-enforcer.d.ts +22 -0
  224. package/dist/coordination/worktree-enforcer.d.ts.map +1 -0
  225. package/dist/coordination/worktree-enforcer.js +71 -0
  226. package/dist/coordination/worktree-enforcer.js.map +1 -0
  227. package/dist/generators/claude-md.d.ts +3 -0
  228. package/dist/generators/claude-md.d.ts.map +1 -0
  229. package/dist/generators/claude-md.js +1020 -0
  230. package/dist/generators/claude-md.js.map +1 -0
  231. package/dist/generators/template-loader.d.ts +105 -0
  232. package/dist/generators/template-loader.d.ts.map +1 -0
  233. package/dist/generators/template-loader.js +291 -0
  234. package/dist/generators/template-loader.js.map +1 -0
  235. package/dist/index.d.ts +49 -0
  236. package/dist/index.d.ts.map +1 -0
  237. package/dist/index.js +63 -0
  238. package/dist/index.js.map +1 -0
  239. package/dist/mcp-router/config/parser.d.ts +9 -0
  240. package/dist/mcp-router/config/parser.d.ts.map +1 -0
  241. package/dist/mcp-router/config/parser.js +174 -0
  242. package/dist/mcp-router/config/parser.js.map +1 -0
  243. package/dist/mcp-router/executor/client.d.ts +31 -0
  244. package/dist/mcp-router/executor/client.d.ts.map +1 -0
  245. package/dist/mcp-router/executor/client.js +189 -0
  246. package/dist/mcp-router/executor/client.js.map +1 -0
  247. package/dist/mcp-router/index.d.ts +22 -0
  248. package/dist/mcp-router/index.d.ts.map +1 -0
  249. package/dist/mcp-router/index.js +18 -0
  250. package/dist/mcp-router/index.js.map +1 -0
  251. package/dist/mcp-router/output-compressor.d.ts +26 -0
  252. package/dist/mcp-router/output-compressor.d.ts.map +1 -0
  253. package/dist/mcp-router/output-compressor.js +236 -0
  254. package/dist/mcp-router/output-compressor.js.map +1 -0
  255. package/dist/mcp-router/search/fuzzy.d.ts +26 -0
  256. package/dist/mcp-router/search/fuzzy.d.ts.map +1 -0
  257. package/dist/mcp-router/search/fuzzy.js +94 -0
  258. package/dist/mcp-router/search/fuzzy.js.map +1 -0
  259. package/dist/mcp-router/server.d.ts +50 -0
  260. package/dist/mcp-router/server.d.ts.map +1 -0
  261. package/dist/mcp-router/server.js +229 -0
  262. package/dist/mcp-router/server.js.map +1 -0
  263. package/dist/mcp-router/session-stats.d.ts +37 -0
  264. package/dist/mcp-router/session-stats.d.ts.map +1 -0
  265. package/dist/mcp-router/session-stats.js +56 -0
  266. package/dist/mcp-router/session-stats.js.map +1 -0
  267. package/dist/mcp-router/tools/discover.d.ts +37 -0
  268. package/dist/mcp-router/tools/discover.d.ts.map +1 -0
  269. package/dist/mcp-router/tools/discover.js +65 -0
  270. package/dist/mcp-router/tools/discover.js.map +1 -0
  271. package/dist/mcp-router/tools/execute.d.ts +43 -0
  272. package/dist/mcp-router/tools/execute.d.ts.map +1 -0
  273. package/dist/mcp-router/tools/execute.js +144 -0
  274. package/dist/mcp-router/tools/execute.js.map +1 -0
  275. package/dist/mcp-router/types.d.ts +62 -0
  276. package/dist/mcp-router/types.d.ts.map +1 -0
  277. package/dist/mcp-router/types.js +6 -0
  278. package/dist/mcp-router/types.js.map +1 -0
  279. package/dist/memory/adaptive-context.d.ts +149 -0
  280. package/dist/memory/adaptive-context.d.ts.map +1 -0
  281. package/dist/memory/adaptive-context.js +1095 -0
  282. package/dist/memory/adaptive-context.js.map +1 -0
  283. package/dist/memory/agent-scoped-memory.d.ts +67 -0
  284. package/dist/memory/agent-scoped-memory.d.ts.map +1 -0
  285. package/dist/memory/agent-scoped-memory.js +126 -0
  286. package/dist/memory/agent-scoped-memory.js.map +1 -0
  287. package/dist/memory/ambiguity-detector.d.ts +54 -0
  288. package/dist/memory/ambiguity-detector.d.ts.map +1 -0
  289. package/dist/memory/ambiguity-detector.js +401 -0
  290. package/dist/memory/ambiguity-detector.js.map +1 -0
  291. package/dist/memory/backends/base.d.ts +18 -0
  292. package/dist/memory/backends/base.d.ts.map +1 -0
  293. package/dist/memory/backends/base.js +2 -0
  294. package/dist/memory/backends/base.js.map +1 -0
  295. package/dist/memory/backends/factory.d.ts +4 -0
  296. package/dist/memory/backends/factory.d.ts.map +1 -0
  297. package/dist/memory/backends/factory.js +53 -0
  298. package/dist/memory/backends/factory.js.map +1 -0
  299. package/dist/memory/backends/github.d.ts +27 -0
  300. package/dist/memory/backends/github.d.ts.map +1 -0
  301. package/dist/memory/backends/github.js +134 -0
  302. package/dist/memory/backends/github.js.map +1 -0
  303. package/dist/memory/backends/qdrant-cloud.d.ts +32 -0
  304. package/dist/memory/backends/qdrant-cloud.d.ts.map +1 -0
  305. package/dist/memory/backends/qdrant-cloud.js +167 -0
  306. package/dist/memory/backends/qdrant-cloud.js.map +1 -0
  307. package/dist/memory/context-compressor.d.ts +116 -0
  308. package/dist/memory/context-compressor.d.ts.map +1 -0
  309. package/dist/memory/context-compressor.js +430 -0
  310. package/dist/memory/context-compressor.js.map +1 -0
  311. package/dist/memory/context-pruner.d.ts +55 -0
  312. package/dist/memory/context-pruner.d.ts.map +1 -0
  313. package/dist/memory/context-pruner.js +85 -0
  314. package/dist/memory/context-pruner.js.map +1 -0
  315. package/dist/memory/correction-propagator.d.ts +44 -0
  316. package/dist/memory/correction-propagator.d.ts.map +1 -0
  317. package/dist/memory/correction-propagator.js +156 -0
  318. package/dist/memory/correction-propagator.js.map +1 -0
  319. package/dist/memory/daily-log.d.ts +67 -0
  320. package/dist/memory/daily-log.d.ts.map +1 -0
  321. package/dist/memory/daily-log.js +143 -0
  322. package/dist/memory/daily-log.js.map +1 -0
  323. package/dist/memory/dynamic-retrieval.d.ts +112 -0
  324. package/dist/memory/dynamic-retrieval.d.ts.map +1 -0
  325. package/dist/memory/dynamic-retrieval.js +908 -0
  326. package/dist/memory/dynamic-retrieval.js.map +1 -0
  327. package/dist/memory/embeddings.d.ts +172 -0
  328. package/dist/memory/embeddings.d.ts.map +1 -0
  329. package/dist/memory/embeddings.js +780 -0
  330. package/dist/memory/embeddings.js.map +1 -0
  331. package/dist/memory/generic-uap-patterns.d.ts +7 -0
  332. package/dist/memory/generic-uap-patterns.d.ts.map +1 -0
  333. package/dist/memory/generic-uap-patterns.js +43 -0
  334. package/dist/memory/generic-uap-patterns.js.map +1 -0
  335. package/dist/memory/hierarchical-memory.d.ts +141 -0
  336. package/dist/memory/hierarchical-memory.d.ts.map +1 -0
  337. package/dist/memory/hierarchical-memory.js +485 -0
  338. package/dist/memory/hierarchical-memory.js.map +1 -0
  339. package/dist/memory/knowledge-graph.d.ts +98 -0
  340. package/dist/memory/knowledge-graph.d.ts.map +1 -0
  341. package/dist/memory/knowledge-graph.js +275 -0
  342. package/dist/memory/knowledge-graph.js.map +1 -0
  343. package/dist/memory/memory-consolidator.d.ts +124 -0
  344. package/dist/memory/memory-consolidator.d.ts.map +1 -0
  345. package/dist/memory/memory-consolidator.js +514 -0
  346. package/dist/memory/memory-consolidator.js.map +1 -0
  347. package/dist/memory/memory-maintenance.d.ts +39 -0
  348. package/dist/memory/memory-maintenance.d.ts.map +1 -0
  349. package/dist/memory/memory-maintenance.js +336 -0
  350. package/dist/memory/memory-maintenance.js.map +1 -0
  351. package/dist/memory/model-router.d.ts +105 -0
  352. package/dist/memory/model-router.d.ts.map +1 -0
  353. package/dist/memory/model-router.js +474 -0
  354. package/dist/memory/model-router.js.map +1 -0
  355. package/dist/memory/multi-view-memory.d.ts +134 -0
  356. package/dist/memory/multi-view-memory.d.ts.map +1 -0
  357. package/dist/memory/multi-view-memory.js +430 -0
  358. package/dist/memory/multi-view-memory.js.map +1 -0
  359. package/dist/memory/predictive-memory.d.ts +79 -0
  360. package/dist/memory/predictive-memory.d.ts.map +1 -0
  361. package/dist/memory/predictive-memory.js +294 -0
  362. package/dist/memory/predictive-memory.js.map +1 -0
  363. package/dist/memory/prepopulate.d.ts +76 -0
  364. package/dist/memory/prepopulate.d.ts.map +1 -0
  365. package/dist/memory/prepopulate.js +832 -0
  366. package/dist/memory/prepopulate.js.map +1 -0
  367. package/dist/memory/semantic-compression.d.ts +77 -0
  368. package/dist/memory/semantic-compression.d.ts.map +1 -0
  369. package/dist/memory/semantic-compression.js +359 -0
  370. package/dist/memory/semantic-compression.js.map +1 -0
  371. package/dist/memory/serverless-qdrant.d.ts +102 -0
  372. package/dist/memory/serverless-qdrant.d.ts.map +1 -0
  373. package/dist/memory/serverless-qdrant.js +369 -0
  374. package/dist/memory/serverless-qdrant.js.map +1 -0
  375. package/dist/memory/short-term/factory.d.ts +26 -0
  376. package/dist/memory/short-term/factory.d.ts.map +1 -0
  377. package/dist/memory/short-term/factory.js +28 -0
  378. package/dist/memory/short-term/factory.js.map +1 -0
  379. package/dist/memory/short-term/indexeddb.d.ts +25 -0
  380. package/dist/memory/short-term/indexeddb.d.ts.map +1 -0
  381. package/dist/memory/short-term/indexeddb.js +64 -0
  382. package/dist/memory/short-term/indexeddb.js.map +1 -0
  383. package/dist/memory/short-term/schema.d.ts +6 -0
  384. package/dist/memory/short-term/schema.d.ts.map +1 -0
  385. package/dist/memory/short-term/schema.js +141 -0
  386. package/dist/memory/short-term/schema.js.map +1 -0
  387. package/dist/memory/short-term/sqlite.d.ts +64 -0
  388. package/dist/memory/short-term/sqlite.d.ts.map +1 -0
  389. package/dist/memory/short-term/sqlite.js +274 -0
  390. package/dist/memory/short-term/sqlite.js.map +1 -0
  391. package/dist/memory/speculative-cache.d.ts +111 -0
  392. package/dist/memory/speculative-cache.d.ts.map +1 -0
  393. package/dist/memory/speculative-cache.js +457 -0
  394. package/dist/memory/speculative-cache.js.map +1 -0
  395. package/dist/memory/task-classifier.d.ts +40 -0
  396. package/dist/memory/task-classifier.d.ts.map +1 -0
  397. package/dist/memory/task-classifier.js +342 -0
  398. package/dist/memory/task-classifier.js.map +1 -0
  399. package/dist/memory/terminal-bench-knowledge.d.ts +48 -0
  400. package/dist/memory/terminal-bench-knowledge.d.ts.map +1 -0
  401. package/dist/memory/terminal-bench-knowledge.js +622 -0
  402. package/dist/memory/terminal-bench-knowledge.js.map +1 -0
  403. package/dist/memory/write-gate.d.ts +39 -0
  404. package/dist/memory/write-gate.d.ts.map +1 -0
  405. package/dist/memory/write-gate.js +190 -0
  406. package/dist/memory/write-gate.js.map +1 -0
  407. package/dist/models/api-client.d.ts +46 -0
  408. package/dist/models/api-client.d.ts.map +1 -0
  409. package/dist/models/api-client.js +182 -0
  410. package/dist/models/api-client.js.map +1 -0
  411. package/dist/models/execution-profiles.d.ts +64 -0
  412. package/dist/models/execution-profiles.d.ts.map +1 -0
  413. package/dist/models/execution-profiles.js +403 -0
  414. package/dist/models/execution-profiles.js.map +1 -0
  415. package/dist/models/executor.d.ts +130 -0
  416. package/dist/models/executor.d.ts.map +1 -0
  417. package/dist/models/executor.js +382 -0
  418. package/dist/models/executor.js.map +1 -0
  419. package/dist/models/index.d.ts +19 -0
  420. package/dist/models/index.d.ts.map +1 -0
  421. package/dist/models/index.js +23 -0
  422. package/dist/models/index.js.map +1 -0
  423. package/dist/models/plan-validator.d.ts +37 -0
  424. package/dist/models/plan-validator.d.ts.map +1 -0
  425. package/dist/models/plan-validator.js +179 -0
  426. package/dist/models/plan-validator.js.map +1 -0
  427. package/dist/models/planner.d.ts +73 -0
  428. package/dist/models/planner.d.ts.map +1 -0
  429. package/dist/models/planner.js +375 -0
  430. package/dist/models/planner.js.map +1 -0
  431. package/dist/models/router.d.ts +96 -0
  432. package/dist/models/router.d.ts.map +1 -0
  433. package/dist/models/router.js +523 -0
  434. package/dist/models/router.js.map +1 -0
  435. package/dist/models/types.d.ts +370 -0
  436. package/dist/models/types.d.ts.map +1 -0
  437. package/dist/models/types.js +232 -0
  438. package/dist/models/types.js.map +1 -0
  439. package/dist/models/unified-router.d.ts +152 -0
  440. package/dist/models/unified-router.d.ts.map +1 -0
  441. package/dist/models/unified-router.js +313 -0
  442. package/dist/models/unified-router.js.map +1 -0
  443. package/dist/policies/convert-policy-to-claude.d.ts +3 -0
  444. package/dist/policies/convert-policy-to-claude.d.ts.map +1 -0
  445. package/dist/policies/convert-policy-to-claude.js +87 -0
  446. package/dist/policies/convert-policy-to-claude.js.map +1 -0
  447. package/dist/policies/database-manager.d.ts +27 -0
  448. package/dist/policies/database-manager.d.ts.map +1 -0
  449. package/dist/policies/database-manager.js +198 -0
  450. package/dist/policies/database-manager.js.map +1 -0
  451. package/dist/policies/enforced-tool-router.d.ts +53 -0
  452. package/dist/policies/enforced-tool-router.d.ts.map +1 -0
  453. package/dist/policies/enforced-tool-router.js +80 -0
  454. package/dist/policies/enforced-tool-router.js.map +1 -0
  455. package/dist/policies/index.d.ts +10 -0
  456. package/dist/policies/index.d.ts.map +1 -0
  457. package/dist/policies/index.js +8 -0
  458. package/dist/policies/index.js.map +1 -0
  459. package/dist/policies/policy-gate.d.ts +59 -0
  460. package/dist/policies/policy-gate.d.ts.map +1 -0
  461. package/dist/policies/policy-gate.js +171 -0
  462. package/dist/policies/policy-gate.js.map +1 -0
  463. package/dist/policies/policy-memory.d.ts +18 -0
  464. package/dist/policies/policy-memory.d.ts.map +1 -0
  465. package/dist/policies/policy-memory.js +126 -0
  466. package/dist/policies/policy-memory.js.map +1 -0
  467. package/dist/policies/policy-tools.d.ts +11 -0
  468. package/dist/policies/policy-tools.d.ts.map +1 -0
  469. package/dist/policies/policy-tools.js +66 -0
  470. package/dist/policies/policy-tools.js.map +1 -0
  471. package/dist/policies/schemas/policy.d.ts +69 -0
  472. package/dist/policies/schemas/policy.d.ts.map +1 -0
  473. package/dist/policies/schemas/policy.js +31 -0
  474. package/dist/policies/schemas/policy.js.map +1 -0
  475. package/dist/tasks/coordination.d.ts +83 -0
  476. package/dist/tasks/coordination.d.ts.map +1 -0
  477. package/dist/tasks/coordination.js +291 -0
  478. package/dist/tasks/coordination.js.map +1 -0
  479. package/dist/tasks/database.d.ts +19 -0
  480. package/dist/tasks/database.d.ts.map +1 -0
  481. package/dist/tasks/database.js +149 -0
  482. package/dist/tasks/database.js.map +1 -0
  483. package/dist/tasks/decoder-gate.d.ts +64 -0
  484. package/dist/tasks/decoder-gate.d.ts.map +1 -0
  485. package/dist/tasks/decoder-gate.js +268 -0
  486. package/dist/tasks/decoder-gate.js.map +1 -0
  487. package/dist/tasks/index.d.ts +6 -0
  488. package/dist/tasks/index.d.ts.map +1 -0
  489. package/dist/tasks/index.js +6 -0
  490. package/dist/tasks/index.js.map +1 -0
  491. package/dist/tasks/service.d.ts +40 -0
  492. package/dist/tasks/service.d.ts.map +1 -0
  493. package/dist/tasks/service.js +671 -0
  494. package/dist/tasks/service.js.map +1 -0
  495. package/dist/tasks/types.d.ts +238 -0
  496. package/dist/tasks/types.d.ts.map +1 -0
  497. package/dist/tasks/types.js +74 -0
  498. package/dist/tasks/types.js.map +1 -0
  499. package/dist/telemetry/index.d.ts +2 -0
  500. package/dist/telemetry/index.d.ts.map +1 -0
  501. package/dist/telemetry/index.js +2 -0
  502. package/dist/telemetry/index.js.map +1 -0
  503. package/dist/telemetry/session-telemetry.d.ts +56 -0
  504. package/dist/telemetry/session-telemetry.d.ts.map +1 -0
  505. package/dist/telemetry/session-telemetry.js +807 -0
  506. package/dist/telemetry/session-telemetry.js.map +1 -0
  507. package/dist/types/analysis.d.ts +82 -0
  508. package/dist/types/analysis.d.ts.map +1 -0
  509. package/dist/types/analysis.js +2 -0
  510. package/dist/types/analysis.js.map +1 -0
  511. package/dist/types/config.d.ts +3324 -0
  512. package/dist/types/config.d.ts.map +1 -0
  513. package/dist/types/config.js +418 -0
  514. package/dist/types/config.js.map +1 -0
  515. package/dist/types/coordination.d.ts +240 -0
  516. package/dist/types/coordination.d.ts.map +1 -0
  517. package/dist/types/coordination.js +43 -0
  518. package/dist/types/coordination.js.map +1 -0
  519. package/dist/types/index.d.ts +4 -0
  520. package/dist/types/index.d.ts.map +1 -0
  521. package/dist/types/index.js +4 -0
  522. package/dist/types/index.js.map +1 -0
  523. package/dist/uap-droids-strict.d.ts +59 -0
  524. package/dist/uap-droids-strict.d.ts.map +1 -0
  525. package/dist/uap-droids-strict.js +200 -0
  526. package/dist/uap-droids-strict.js.map +1 -0
  527. package/dist/utils/config-manager.d.ts +30 -0
  528. package/dist/utils/config-manager.d.ts.map +1 -0
  529. package/dist/utils/config-manager.js +41 -0
  530. package/dist/utils/config-manager.js.map +1 -0
  531. package/dist/utils/fetch-with-retry.d.ts +5 -0
  532. package/dist/utils/fetch-with-retry.d.ts.map +1 -0
  533. package/dist/utils/fetch-with-retry.js +61 -0
  534. package/dist/utils/fetch-with-retry.js.map +1 -0
  535. package/dist/utils/merge-claude-md.d.ts +28 -0
  536. package/dist/utils/merge-claude-md.d.ts.map +1 -0
  537. package/dist/utils/merge-claude-md.js +342 -0
  538. package/dist/utils/merge-claude-md.js.map +1 -0
  539. package/dist/utils/rate-limiter.d.ts +58 -0
  540. package/dist/utils/rate-limiter.d.ts.map +1 -0
  541. package/dist/utils/rate-limiter.js +100 -0
  542. package/dist/utils/rate-limiter.js.map +1 -0
  543. package/dist/utils/string-similarity.d.ts +37 -0
  544. package/dist/utils/string-similarity.d.ts.map +1 -0
  545. package/dist/utils/string-similarity.js +114 -0
  546. package/dist/utils/string-similarity.js.map +1 -0
  547. package/dist/utils/validate-json.d.ts +51 -0
  548. package/dist/utils/validate-json.d.ts.map +1 -0
  549. package/dist/utils/validate-json.js +94 -0
  550. package/dist/utils/validate-json.js.map +1 -0
  551. package/docs/INDEX.md +66 -0
  552. package/docs/architecture/MULTI_MODEL.md +224 -0
  553. package/docs/architecture/SYSTEM_ANALYSIS.md +1117 -0
  554. package/docs/architecture/UAP_COMPLIANCE.md +217 -0
  555. package/docs/architecture/UAP_PROTOCOL.md +339 -0
  556. package/docs/architecture/UAP_STRICT_DROIDS.md +172 -0
  557. package/docs/archive/BALLS_MODE_SELF_ANALYSIS.md +260 -0
  558. package/docs/archive/FAILING_TASKS_SOLUTION_PLAN.md +668 -0
  559. package/docs/archive/JINJA2-SYSTEM-MESSAGE-FIX.md +209 -0
  560. package/docs/archive/NPM-PUBLISH-V0.9.1.md +240 -0
  561. package/docs/archive/OPTIMIZATION_OPTIONS.md +334 -0
  562. package/docs/archive/SETUP_IMPROVEMENTS.md +213 -0
  563. package/docs/archive/UAP_GENERIC_OPTIMIZATION_PLAN.md +270 -0
  564. package/docs/archive/UAP_V103_PATTERN_DESIGN.md +315 -0
  565. package/docs/archive/UAP_V104_COMPLIANCE_DESIGN.md +223 -0
  566. package/docs/archive/changelog/2026-03-10_uap-100-compliance.md +77 -0
  567. package/docs/archive/changelog/2026-03-10_uap-full-system-verification.md +109 -0
  568. package/docs/benchmarks/ACCURACY_ANALYSIS.md +471 -0
  569. package/docs/benchmarks/TOKEN_OPTIMIZATION.md +572 -0
  570. package/docs/benchmarks/VALIDATION_PLAN.md +568 -0
  571. package/docs/benchmarks/VALIDATION_RESULTS.md +161 -0
  572. package/docs/deployment/DEPLOYMENT.md +895 -0
  573. package/docs/deployment/DEPLOYMENT_STRATEGIES.md +518 -0
  574. package/docs/deployment/DEPLOY_BATCHER_ANALYSIS.md +856 -0
  575. package/docs/deployment/DEPLOY_BATCHING.md +273 -0
  576. package/docs/deployment/DEPLOY_BUCKETING_ANALYSIS.md +420 -0
  577. package/docs/deployment/QWEN35_LLAMA_CPP.md +265 -0
  578. package/docs/getting-started/INTEGRATION.md +449 -0
  579. package/docs/getting-started/OVERVIEW.md +344 -0
  580. package/docs/getting-started/SETUP.md +203 -0
  581. package/docs/integrations/MCP_ROUTER_SETUP.md +445 -0
  582. package/docs/integrations/RTK_INTEGRATION.md +468 -0
  583. package/docs/operations/TROUBLESHOOTING.md +660 -0
  584. package/docs/reference/API_REFERENCE.md +903 -0
  585. package/docs/reference/FEATURES.md +472 -0
  586. package/docs/reference/HARNESS-MATRIX.md +318 -0
  587. package/docs/reference/UAP_CLI_REFERENCE.md +600 -0
  588. package/docs/research/BEHAVIORAL_PATTERNS.md +228 -0
  589. package/docs/research/DOMAIN_STRATEGIES.md +316 -0
  590. package/docs/research/MEMORY_SYSTEMS_COMPARISON.md +812 -0
  591. package/docs/research/PATTERN_ANALYSIS_2026-01-18.md +436 -0
  592. package/docs/research/PERFORMANCE_ANALYSIS_2026-01-18.md +209 -0
  593. package/docs/research/PERFORMANCE_TEST_PLAN.md +383 -0
  594. package/docs/research/TERMINAL_BENCH_LEARNINGS.md +217 -0
  595. package/package.json +113 -0
  596. package/scripts/README.md +161 -0
  597. package/templates/CLAUDE.template.md +10 -0
  598. package/templates/CLAUDE_ARCHITECTURE.template.md +103 -0
  599. package/templates/CLAUDE_CODING.template.md +127 -0
  600. package/templates/CLAUDE_DROIDS.template.md +109 -0
  601. package/templates/CLAUDE_MEMORY.template.md +131 -0
  602. package/templates/CLAUDE_WORKFLOWS.template.md +139 -0
  603. package/templates/PROJECT.template.md +209 -0
  604. package/templates/SCHEMA.md +57 -0
  605. package/templates/archive/CLAUDE.template.root-v6.md +534 -0
  606. package/templates/archive/CLAUDE.template.v6.md +534 -0
  607. package/templates/hooks/forgecode/pre-compact.sh +68 -0
  608. package/templates/hooks/forgecode/session-start.sh +169 -0
  609. package/templates/hooks/forgecode.plugin.sh +128 -0
  610. package/templates/hooks/pre-compact.sh +74 -0
  611. package/templates/hooks/session-start.sh +366 -0
  612. package/tools/agents/README.md +224 -0
  613. package/tools/agents/UAP/README.md +386 -0
  614. package/tools/agents/UAP/__init__.py +9 -0
  615. package/tools/agents/UAP/cli.py +901 -0
  616. package/tools/agents/UAP/compliance_verify.sh +108 -0
  617. package/tools/agents/UAP/full_verification.sh +126 -0
  618. package/tools/agents/UAP/version.py +32 -0
  619. package/tools/agents/benchmarks/benchmark_memory_systems.py +730 -0
  620. package/tools/agents/benchmarks/results/benchmark_20260106_064817.json +170 -0
  621. package/tools/agents/benchmarks/results/benchmark_20260106_064817.md +51 -0
  622. package/tools/agents/config/chat_template.jinja +77 -0
  623. package/tools/agents/config/tool-call-schema.json +19 -0
  624. package/tools/agents/config/tool-call.gbnf +58 -0
  625. package/tools/agents/docker/Dockerfile.python +52 -0
  626. package/tools/agents/docker/Dockerfile.ubuntu +55 -0
  627. package/tools/agents/docker-compose.qdrant.yml +24 -0
  628. package/tools/agents/install-opencode-local.sh.j2 +135 -0
  629. package/tools/agents/migrations/apply.py +256 -0
  630. package/tools/agents/opencode_uap_agent.py +1505 -0
  631. package/tools/agents/plugin/README.md +91 -0
  632. package/tools/agents/plugin/index.ts +46 -0
  633. package/tools/agents/plugin/pre-compact.sh +68 -0
  634. package/tools/agents/plugin/session-start.sh +175 -0
  635. package/tools/agents/plugin/uap-commands.ts +45 -0
  636. package/tools/agents/plugin/uap-droids.ts +54 -0
  637. package/tools/agents/plugin/uap-patterns.ts +54 -0
  638. package/tools/agents/plugin/uap-skills.ts +52 -0
  639. package/tools/agents/plugins/uap-enforce.ts +314 -0
  640. package/tools/agents/scripts/__pycache__/tool_call_wrapper.cpython-313.pyc +0 -0
  641. package/tools/agents/scripts/chat_template_verifier.py +343 -0
  642. package/tools/agents/scripts/fix-qwen-template.js +38 -0
  643. package/tools/agents/scripts/fix_qwen_chat_template.py +316 -0
  644. package/tools/agents/scripts/generate_lora_training_data.py +412 -0
  645. package/tools/agents/scripts/init_qdrant.py +151 -0
  646. package/tools/agents/scripts/memory_migration.py +560 -0
  647. package/tools/agents/scripts/migrate_memory_to_qdrant.py +110 -0
  648. package/tools/agents/scripts/prepare_lora.sh +512 -0
  649. package/tools/agents/scripts/query_memory.py +200 -0
  650. package/tools/agents/scripts/qwen-tool-call-test.js +38 -0
  651. package/tools/agents/scripts/qwen-tool-call-wrapper.js +38 -0
  652. package/tools/agents/scripts/qwen_tool_call_test.py +464 -0
  653. package/tools/agents/scripts/qwen_tool_call_wrapper.py +686 -0
  654. package/tools/agents/scripts/start-services.sh +96 -0
  655. package/tools/agents/scripts/tool-choice-proxy.cjs +296 -0
  656. package/tools/agents/scripts/tool_call_test.py +656 -0
  657. package/tools/agents/scripts/tool_call_wrapper.py +799 -0
  658. package/tools/agents/tests/test_uap_compliance.py +257 -0
  659. package/tools/agents/uap_agent.py +122 -0
  660. package/tools/agents/uap_agent_install.sh +12 -0
@@ -0,0 +1,799 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ UAP Tool Call Wrapper with Retry Logic
4
+
5
+ Model-agnostic OpenAI-compatible tool calling client with automatic retry
6
+ on failures, addressing common issues with local and hosted models.
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
+ Model Profiles:
17
+ Set UAP_MODEL_PROFILE env var to load model-specific defaults.
18
+ Supported profiles: qwen35, llama, generic (default)
19
+ Or pass a custom config dict to override any setting.
20
+
21
+ Usage:
22
+ from tool_call_wrapper import ToolCallClient
23
+
24
+ client = ToolCallClient()
25
+ response = client.chat_with_tools(
26
+ messages=[{"role": "user", "content": "Call read_file with path='/etc/hosts'"}],
27
+ tools=[...]
28
+ )
29
+
30
+ # With explicit model profile
31
+ client = ToolCallClient(config={"model_profile": "qwen35"})
32
+
33
+ Backward Compatibility:
34
+ # Legacy names still work
35
+ from tool_call_wrapper import Qwen35ToolCallClient # alias for ToolCallClient
36
+ """
37
+
38
+ try:
39
+ import openai
40
+ except ImportError:
41
+ raise ImportError(
42
+ "The 'openai' package is required but not installed.\n"
43
+ "Install it with: pip install openai\n"
44
+ "Or: pip install -r requirements.txt"
45
+ )
46
+
47
+ import time
48
+ import json
49
+ import os
50
+ import logging
51
+ from typing import List, Dict, Any, Optional, Tuple
52
+ from dataclasses import dataclass, asdict
53
+ from datetime import datetime
54
+ from enum import Enum
55
+ from pathlib import Path
56
+
57
+ # Configure logging
58
+ logging.basicConfig(
59
+ level=logging.INFO, format="%(asctime)s - %(name)s - %(levelname)s - %(message)s"
60
+ )
61
+ logger = logging.getLogger("uap_tool_call")
62
+
63
+
64
+ # ── Model Profiles ──────────────────────────────────────────────────────────
65
+
66
+ MODEL_PROFILES: Dict[str, Dict[str, Any]] = {
67
+ "generic": {
68
+ "temperature": 0.6,
69
+ "top_p": 0.9,
70
+ "presence_penalty": 0.0,
71
+ "max_tokens": 4096,
72
+ "enable_thinking": False,
73
+ "model": "default",
74
+ "base_url": "http://127.0.0.1:8080/v1",
75
+ "api_key": "not-needed",
76
+ "default_tool_choice": "auto",
77
+ "parallel_tool_calls": True,
78
+ "batch_tool_calls": True,
79
+ "escalate_tool_choice": True,
80
+ "use_per_tool_choice": True,
81
+ "dynamic_temperature": True,
82
+ "dynamic_temp_decay": 0.5,
83
+ "dynamic_temp_floor": 0.2,
84
+ },
85
+ "qwen35": {
86
+ "temperature": 0.6,
87
+ "top_p": 0.9,
88
+ "presence_penalty": 0.0,
89
+ "max_tokens": 4096,
90
+ "enable_thinking": False,
91
+ "model": "qwen35-a3b-iq4xs",
92
+ "base_url": "http://127.0.0.1:8080/v1",
93
+ "api_key": "not-needed",
94
+ "default_tool_choice": "required",
95
+ "parallel_tool_calls": True,
96
+ "batch_tool_calls": True,
97
+ "escalate_tool_choice": True,
98
+ "use_per_tool_choice": True,
99
+ "dynamic_temperature": True,
100
+ "dynamic_temp_decay": 0.5,
101
+ "dynamic_temp_floor": 0.2,
102
+ # Qwen-specific: suppress thinking mode to avoid tag leakage
103
+ "suppress_thinking": True,
104
+ "batch_system_prompt": (
105
+ "CRITICAL: You MUST emit ALL tool calls in a SINGLE response. "
106
+ "Each tool call must be a separate function call. "
107
+ "Do NOT call one tool and wait - emit ALL tool calls together NOW. "
108
+ "If asked to do 3 things, you must produce 3 tool calls in one response."
109
+ ),
110
+ },
111
+ "llama": {
112
+ "temperature": 0.6,
113
+ "top_p": 0.9,
114
+ "presence_penalty": 0.0,
115
+ "max_tokens": 4096,
116
+ "enable_thinking": False,
117
+ "model": "default",
118
+ "base_url": "http://127.0.0.1:8080/v1",
119
+ "api_key": "not-needed",
120
+ "default_tool_choice": "auto",
121
+ "parallel_tool_calls": True,
122
+ "batch_tool_calls": True,
123
+ "escalate_tool_choice": True,
124
+ "use_per_tool_choice": True,
125
+ "dynamic_temperature": True,
126
+ "dynamic_temp_decay": 0.5,
127
+ "dynamic_temp_floor": 0.2,
128
+ },
129
+ }
130
+
131
+ # Default batch system prompt (used when batch_tool_calls is True and no profile-specific one)
132
+ DEFAULT_BATCH_SYSTEM_PROMPT = (
133
+ "When multiple tools are needed, call ALL of them in a single response. "
134
+ "Do not call one tool and wait for a response before calling the next."
135
+ )
136
+
137
+
138
+ def _load_profile(profile_name: str) -> Dict[str, Any]:
139
+ """Load a model profile by name, falling back to generic."""
140
+ base = MODEL_PROFILES.get("generic", {}).copy()
141
+ profile = MODEL_PROFILES.get(profile_name, {})
142
+ base.update(profile)
143
+ return base
144
+
145
+
146
+ def _detect_profile() -> str:
147
+ """Auto-detect model profile from environment."""
148
+ return os.environ.get("UAP_MODEL_PROFILE", "generic")
149
+
150
+
151
+ # ── Core Classes ─────────────────────────────────────────────────────────────
152
+
153
+
154
+ class ToolCallStatus(Enum):
155
+ """Status of tool call attempts"""
156
+
157
+ SUCCESS = "success"
158
+ FAILURE = "failure"
159
+ RETRY = "retry"
160
+ MAX_RETRIES = "max_retries"
161
+
162
+
163
+ @dataclass
164
+ class ToolCallMetrics:
165
+ """Metrics for tool call performance"""
166
+
167
+ total_attempts: int = 0
168
+ successful_calls: int = 0
169
+ failed_calls: int = 0
170
+ retries: int = 0
171
+ avg_latency_ms: float = 0.0
172
+ last_error: Optional[str] = None
173
+ tool_choice_escalations: int = 0
174
+ parallel_calls_requested: int = 0
175
+ parallel_calls_received: int = 0
176
+
177
+ def to_dict(self) -> Dict:
178
+ return asdict(self)
179
+
180
+
181
+ class ToolCallError(Exception):
182
+ """Custom exception for tool call failures"""
183
+
184
+ pass
185
+
186
+
187
+ class ToolCallClient:
188
+ """
189
+ OpenAI-compatible client for reliable tool calling with any model.
190
+
191
+ Implements 6 strategies for maximum tool call reliability:
192
+ 1. tool_choice + parallel_tool_calls in every request
193
+ 2. Explicit multi-tool system prompt with format guidance
194
+ 3. Retry escalation: auto -> required -> required+lower temp
195
+ 4. Per-tool tool_choice for single-tool scenarios
196
+ 5. Thinking mode suppression (model-specific)
197
+ 6. Dynamic temperature decay on retries
198
+
199
+ Supports model profiles for model-specific tuning.
200
+ """
201
+
202
+ DEFAULT_CONFIG = {
203
+ "temperature": 0.6,
204
+ "top_p": 0.9,
205
+ "presence_penalty": 0.0,
206
+ "max_tokens": 4096,
207
+ "enable_thinking": False,
208
+ "max_retries": 3,
209
+ "backoff_factor": 2.0,
210
+ "base_url": "http://127.0.0.1:8080/v1",
211
+ "api_key": "not-needed",
212
+ "model": "default",
213
+ "default_tool_choice": "auto",
214
+ "parallel_tool_calls": True,
215
+ "batch_tool_calls": True,
216
+ "batch_system_prompt": DEFAULT_BATCH_SYSTEM_PROMPT,
217
+ "escalate_tool_choice": True,
218
+ "use_per_tool_choice": True,
219
+ "dynamic_temperature": True,
220
+ "dynamic_temp_decay": 0.5,
221
+ "dynamic_temp_floor": 0.2,
222
+ "suppress_thinking": False,
223
+ }
224
+
225
+ def __init__(
226
+ self, config: Optional[Dict[str, Any]] = None, enable_metrics: bool = True
227
+ ):
228
+ """
229
+ Initialize tool call client.
230
+
231
+ Args:
232
+ config: Override default configuration. Can include "model_profile"
233
+ key to load a named profile as the base.
234
+ enable_metrics: Enable performance metrics tracking
235
+ """
236
+ # Determine base config from profile
237
+ user_config = config or {}
238
+ profile_name = user_config.pop("model_profile", None) or _detect_profile()
239
+ profile_config = _load_profile(profile_name)
240
+
241
+ # Layer: defaults < profile < user overrides
242
+ self.config = {**self.DEFAULT_CONFIG, **profile_config, **user_config}
243
+ self.profile_name = profile_name
244
+ self.enable_metrics = enable_metrics
245
+ self.metrics = ToolCallMetrics()
246
+ self._client = None
247
+
248
+ # Initialize OpenAI client
249
+ self._init_client()
250
+
251
+ logger.info(
252
+ f"ToolCallClient initialized (profile: {profile_name}, "
253
+ f"model: {self.config['model']}, base_url: {self.config['base_url']})"
254
+ )
255
+
256
+ def _init_client(self):
257
+ """Initialize OpenAI-compatible client"""
258
+ try:
259
+ self._client = openai.Client(
260
+ base_url=self.config["base_url"], api_key=self.config["api_key"]
261
+ )
262
+ logger.info(f"Connected to {self.config['base_url']}")
263
+ except Exception as e:
264
+ logger.error(f"Failed to initialize OpenAI client: {e}")
265
+ raise ToolCallError(f"Client initialization failed: {e}")
266
+
267
+ def _get_tool_choice(
268
+ self,
269
+ tools: List[Dict[str, Any]],
270
+ attempt: int,
271
+ expected_tool: Optional[str] = None,
272
+ ) -> Any:
273
+ """
274
+ Determine tool_choice based on strategy and attempt number.
275
+
276
+ Strategy 3 (escalation):
277
+ - Attempt 0: use default_tool_choice (usually "auto")
278
+ - Attempt 1+: escalate to "required"
279
+
280
+ Strategy 5 (per-tool):
281
+ - If expected_tool is set and only one tool matches, use per-tool choice
282
+ """
283
+ # Strategy 5: Per-tool choice for single expected tool
284
+ if expected_tool and self.config.get("use_per_tool_choice") and attempt == 0:
285
+ for tool in tools:
286
+ func = tool.get("function", {})
287
+ if func.get("name") == expected_tool:
288
+ logger.debug(f"Using per-tool choice: {expected_tool}")
289
+ return {
290
+ "type": "function",
291
+ "function": {"name": expected_tool},
292
+ }
293
+
294
+ # Strategy 3: Escalation on retries
295
+ if attempt > 0 and self.config.get("escalate_tool_choice"):
296
+ self.metrics.tool_choice_escalations += 1
297
+ logger.info(f"Escalating tool_choice to 'required' (attempt {attempt + 1})")
298
+ return "required"
299
+
300
+ return self.config.get("default_tool_choice", "auto")
301
+
302
+ def chat_with_tools(
303
+ self,
304
+ messages: List[Dict[str, str]],
305
+ tools: List[Dict[str, Any]],
306
+ max_retries: Optional[int] = None,
307
+ timeout: int = 120,
308
+ expected_tool: Optional[str] = None,
309
+ expected_tool_calls: Optional[int] = None,
310
+ **kwargs,
311
+ ) -> openai.types.chat.ChatCompletion:
312
+ """
313
+ Chat completion with automatic retry on tool call failures.
314
+
315
+ Implements all 6 strategies for reliable tool calling.
316
+
317
+ Args:
318
+ messages: List of chat messages
319
+ tools: List of tool definitions
320
+ max_retries: Override default max retries
321
+ timeout: Request timeout in seconds
322
+ expected_tool: If set, use per-tool tool_choice (Strategy 5)
323
+ expected_tool_calls: Expected number of tool calls (for validation)
324
+ **kwargs: Additional parameters passed to OpenAI API
325
+
326
+ Returns:
327
+ ChatCompletion response with tool calls
328
+
329
+ Raises:
330
+ ToolCallError: After max retries exhausted
331
+ """
332
+ max_retries = max_retries or self.config["max_retries"]
333
+
334
+ # Track timing
335
+ start_time = time.time()
336
+
337
+ # Make a copy of messages to avoid modifying original
338
+ current_messages = [msg.copy() for msg in messages]
339
+
340
+ # Strategy 2: Inject multi-tool system prompt
341
+ if self.config.get("batch_tool_calls") and len(tools) > 1:
342
+ batch_prompt = self.config.get(
343
+ "batch_system_prompt", DEFAULT_BATCH_SYSTEM_PROMPT
344
+ )
345
+ if batch_prompt:
346
+ has_system = any(m.get("role") == "system" for m in current_messages)
347
+ if has_system:
348
+ for m in current_messages:
349
+ if m.get("role") == "system":
350
+ m["content"] = m["content"] + "\n\n" + batch_prompt
351
+ break
352
+ else:
353
+ current_messages.insert(
354
+ 0,
355
+ {"role": "system", "content": batch_prompt},
356
+ )
357
+
358
+ # Track parallel call expectations
359
+ if expected_tool_calls and expected_tool_calls > 1:
360
+ self.metrics.parallel_calls_requested += 1
361
+
362
+ # Base temperature for dynamic adjustment
363
+ base_temperature = self.config["temperature"]
364
+
365
+ for attempt in range(max_retries):
366
+ self.metrics.total_attempts += 1
367
+
368
+ # Strategy 6: Dynamic temperature - reduce on retries
369
+ if self.config.get("dynamic_temperature") and attempt > 0:
370
+ decay = self.config.get("dynamic_temp_decay", 0.5)
371
+ floor = self.config.get("dynamic_temp_floor", 0.2)
372
+ current_temp = max(floor, base_temperature * (decay**attempt))
373
+ logger.info(
374
+ f"Dynamic temperature: {current_temp:.2f} (attempt {attempt + 1})"
375
+ )
376
+ else:
377
+ current_temp = base_temperature
378
+
379
+ # Strategy 1 + 3 + 5: Determine tool_choice
380
+ tool_choice = self._get_tool_choice(tools, attempt, expected_tool)
381
+
382
+ try:
383
+ # Build request with all strategies applied
384
+ request_params = {
385
+ "model": self.config["model"],
386
+ "messages": current_messages,
387
+ "tools": tools,
388
+ "tool_choice": tool_choice,
389
+ "parallel_tool_calls": self.config.get("parallel_tool_calls", True),
390
+ "temperature": current_temp,
391
+ "top_p": self.config["top_p"],
392
+ "presence_penalty": self.config["presence_penalty"],
393
+ "max_tokens": self.config["max_tokens"],
394
+ "timeout": timeout,
395
+ **kwargs,
396
+ }
397
+
398
+ # Strategy 5: Thinking mode suppression (model-specific)
399
+ if self.config.get("suppress_thinking"):
400
+ request_params["extra_body"] = {
401
+ "chat_template_kwargs": {
402
+ "enable_thinking": self.config.get("enable_thinking", False)
403
+ }
404
+ }
405
+
406
+ logger.debug(
407
+ f"Attempt {attempt + 1}/{max_retries}: "
408
+ f"tool_choice={tool_choice}, temp={current_temp:.2f}, "
409
+ f"parallel={self.config.get('parallel_tool_calls', True)}"
410
+ )
411
+
412
+ # Make API call
413
+ response = self._client.chat.completions.create(**request_params)
414
+
415
+ # Validate response
416
+ tool_calls = response.choices[0].message.tool_calls
417
+
418
+ if self._validate_tool_call(tool_calls):
419
+ # Success!
420
+ self.metrics.successful_calls += 1
421
+
422
+ # Track parallel call success
423
+ if tool_calls and len(tool_calls) > 1:
424
+ self.metrics.parallel_calls_received += 1
425
+
426
+ # Calculate latency
427
+ latency_ms = (time.time() - start_time) * 1000
428
+ self.metrics.avg_latency_ms = latency_ms
429
+
430
+ logger.info(
431
+ f"Tool call successful after {attempt + 1} attempt(s): "
432
+ f"{len(tool_calls)} call(s)"
433
+ )
434
+ return response
435
+ else:
436
+ # Invalid format, retry with correction
437
+ logger.warning(f"Invalid tool call format on attempt {attempt + 1}")
438
+ current_messages = self._correct_prompt(current_messages, response)
439
+ self.metrics.retries += 1
440
+
441
+ if attempt < max_retries - 1:
442
+ # Exponential backoff
443
+ backoff = self.config["backoff_factor"] ** attempt
444
+ time.sleep(backoff)
445
+ logger.info(f"Retrying in {backoff:.1f}s...")
446
+
447
+ except Exception as e:
448
+ self.metrics.last_error = str(e)
449
+ logger.error(f"Error on attempt {attempt + 1}: {e}")
450
+
451
+ if attempt == max_retries - 1:
452
+ # Last attempt failed
453
+ self.metrics.failed_calls += 1
454
+ raise ToolCallError(
455
+ f"Failed after {max_retries} attempts: {str(e)}"
456
+ )
457
+
458
+ # Retry with backoff
459
+ backoff = self.config["backoff_factor"] ** attempt
460
+ time.sleep(backoff)
461
+
462
+ # Should not reach here, but just in case
463
+ self.metrics.failed_calls += 1
464
+ raise ToolCallError("Max retries exceeded")
465
+
466
+ def _validate_tool_call(self, tool_calls) -> bool:
467
+ """
468
+ Validate that tool call has correct format.
469
+
470
+ Checks for:
471
+ - Non-empty tool calls list
472
+ - Valid function name
473
+ - Parseable JSON arguments
474
+ - No reasoning content leakage (<thinking>/<think> tags in arguments)
475
+ """
476
+ if not tool_calls:
477
+ logger.debug("No tool calls returned")
478
+ return False
479
+
480
+ for tool_call in tool_calls:
481
+ # Check function name exists
482
+ if not tool_call.function or not tool_call.function.name:
483
+ logger.debug("Tool call missing function name")
484
+ return False
485
+
486
+ # Check arguments are present
487
+ arguments = tool_call.function.arguments
488
+ if not arguments:
489
+ logger.debug("Tool call missing arguments")
490
+ return False
491
+
492
+ # Check for thinking/reasoning tag leakage in arguments
493
+ # This affects models with reasoning modes (Qwen3, DeepSeek, etc.)
494
+ for tag in ["<thinking>", "</thinking>", "<think>", "</think>"]:
495
+ if tag in arguments:
496
+ logger.debug(f"Reasoning tag leakage detected: {tag}")
497
+ return False
498
+
499
+ # Validate arguments are parseable JSON
500
+ try:
501
+ parsed = json.loads(arguments)
502
+ if not isinstance(parsed, dict):
503
+ logger.debug(f"Arguments not a JSON object: {type(parsed)}")
504
+ return False
505
+ except (json.JSONDecodeError, TypeError) as e:
506
+ logger.debug(f"Arguments not valid JSON: {e}")
507
+ return False
508
+
509
+ return True
510
+
511
+ def _correct_prompt(
512
+ self, messages: List[Dict], response: openai.types.chat.ChatCompletion
513
+ ) -> List[Dict]:
514
+ """
515
+ Correct prompt after invalid tool call.
516
+
517
+ Appends correction message to guide model toward proper format.
518
+ """
519
+ invalid_content = response.choices[0].message.content or ""
520
+
521
+ # Add assistant's failed attempt
522
+ messages.append(
523
+ {
524
+ "role": "assistant",
525
+ "content": f"I attempted a tool call but the format was invalid: "
526
+ f"{invalid_content[:200]}",
527
+ }
528
+ )
529
+
530
+ # Add user correction
531
+ messages.append(
532
+ {
533
+ "role": "user",
534
+ "content": "Please call the tool using the correct format. "
535
+ "You must use the tool calling interface - respond with a tool call, "
536
+ "not with text describing the call.",
537
+ }
538
+ )
539
+
540
+ return messages
541
+
542
+ def execute_tool_call(
543
+ self, tool_calls: List, tool_functions: Dict[str, callable]
544
+ ) -> List[Any]:
545
+ """
546
+ Execute tool calls and collect results.
547
+
548
+ Args:
549
+ tool_calls: List of tool call objects from response
550
+ tool_functions: Dict mapping tool names to functions
551
+
552
+ Returns:
553
+ List of tool results
554
+ """
555
+ results = []
556
+
557
+ for tool_call in tool_calls:
558
+ tool_name = tool_call.function.name
559
+ tool_args = json.loads(tool_call.function.arguments)
560
+
561
+ logger.info(f"Executing tool: {tool_name} with args: {tool_args}")
562
+
563
+ if tool_name not in tool_functions:
564
+ results.append(
565
+ {
566
+ "tool_name": tool_name,
567
+ "status": "error",
568
+ "error": f"Tool '{tool_name}' not found",
569
+ }
570
+ )
571
+ continue
572
+
573
+ try:
574
+ result = tool_functions[tool_name](**tool_args)
575
+ results.append(
576
+ {"tool_name": tool_name, "status": "success", "result": result}
577
+ )
578
+ except Exception as e:
579
+ results.append(
580
+ {"tool_name": tool_name, "status": "error", "error": str(e)}
581
+ )
582
+
583
+ return results
584
+
585
+ def get_metrics(self) -> ToolCallMetrics:
586
+ """Get current metrics"""
587
+ return self.metrics
588
+
589
+ def reset_metrics(self):
590
+ """Reset metrics counters"""
591
+ self.metrics = ToolCallMetrics()
592
+ logger.info("Metrics reset")
593
+
594
+ def get_status(self) -> Dict:
595
+ """Get client status"""
596
+ return {
597
+ "profile": self.profile_name,
598
+ "model": self.config["model"],
599
+ "base_url": self.config["base_url"],
600
+ "metrics": self.metrics.to_dict(),
601
+ "config": {
602
+ k: v for k, v in self.config.items() if k not in ["base_url", "api_key"]
603
+ },
604
+ }
605
+
606
+
607
+ class ToolCallAgent:
608
+ """
609
+ Higher-level agent for tool calling workflows.
610
+
611
+ Combines tool calling with execution and result handling.
612
+ Works with any OpenAI-compatible model.
613
+
614
+ Args:
615
+ tool_definitions: List of OpenAI-format tool definitions (for the API)
616
+ tool_implementations: Dict mapping tool names to callable functions (for execution)
617
+ client_config: Configuration for tool call client
618
+ """
619
+
620
+ def __init__(
621
+ self,
622
+ tool_definitions: List[Dict[str, Any]],
623
+ tool_implementations: Dict[str, callable],
624
+ client_config: Optional[Dict] = None,
625
+ ):
626
+ self.tool_definitions = tool_definitions
627
+ self.tool_implementations = tool_implementations
628
+ self.client = ToolCallClient(client_config)
629
+
630
+ logger.info(
631
+ f"ToolCallAgent initialized with {len(tool_definitions)} tools: "
632
+ f"{list(tool_implementations.keys())}"
633
+ )
634
+
635
+ def run(
636
+ self,
637
+ user_query: str,
638
+ additional_messages: Optional[List[Dict]] = None,
639
+ expected_tool: Optional[str] = None,
640
+ ) -> Tuple[openai.types.chat.ChatCompletion, List[Any]]:
641
+ """
642
+ Run a complete tool calling workflow.
643
+
644
+ Args:
645
+ user_query: User's input query
646
+ additional_messages: Optional additional conversation history
647
+ expected_tool: If set, use per-tool tool_choice
648
+
649
+ Returns:
650
+ Tuple of (ChatCompletion response, List of tool results)
651
+ """
652
+ # Build messages
653
+ messages = []
654
+
655
+ if additional_messages:
656
+ messages.extend(additional_messages)
657
+
658
+ messages.append({"role": "user", "content": user_query})
659
+
660
+ # Make tool call request (pass definitions to API)
661
+ response = self.client.chat_with_tools(
662
+ messages=messages,
663
+ tools=self.tool_definitions,
664
+ expected_tool=expected_tool,
665
+ )
666
+
667
+ # Execute tool calls (pass implementations for execution)
668
+ tool_calls = response.choices[0].message.tool_calls
669
+
670
+ if tool_calls:
671
+ results = self.client.execute_tool_call(
672
+ tool_calls, self.tool_implementations
673
+ )
674
+ else:
675
+ results = []
676
+
677
+ return response, results
678
+
679
+ def get_status(self) -> Dict:
680
+ """Get agent status"""
681
+ return {
682
+ "tools": list(self.tool_implementations.keys()),
683
+ "client_status": self.client.get_status(),
684
+ }
685
+
686
+
687
+ # ── Backward Compatibility Aliases ──────────────────────────────────────────
688
+
689
+ # Legacy names still work for existing code
690
+ Qwen35ToolCallClient = ToolCallClient
691
+ Qwen35ToolCallAgent = ToolCallAgent
692
+ Qwen35ToolCallError = ToolCallError
693
+
694
+
695
+ # ── Convenience Function ────────────────────────────────────────────────────
696
+
697
+
698
+ def chat_with_tools(
699
+ user_query: str,
700
+ tool_definitions: List[Dict],
701
+ tool_implementations: Dict[str, callable],
702
+ config: Optional[Dict] = None,
703
+ ) -> Tuple[openai.types.chat.ChatCompletion, List[Any]]:
704
+ """
705
+ Simple function for quick tool calling.
706
+
707
+ Args:
708
+ user_query: User's input
709
+ tool_definitions: OpenAI-format tool definitions
710
+ tool_implementations: Dict mapping tool names to callables
711
+ config: Optional configuration (can include "model_profile" key)
712
+
713
+ Returns:
714
+ Tuple of (response, results)
715
+ """
716
+ agent = ToolCallAgent(tool_definitions, tool_implementations, config)
717
+ return agent.run(user_query)
718
+
719
+
720
+ # Legacy alias
721
+ qwen35_chat_with_tools = chat_with_tools
722
+
723
+
724
+ # ── Example Usage ───────────────────────────────────────────────────────────
725
+
726
+ if __name__ == "__main__":
727
+ # Example tool implementations (actual callables)
728
+ def read_file(path: str) -> str:
729
+ """Read file contents"""
730
+ with open(path, "r") as f:
731
+ return f.read()
732
+
733
+ def get_weather(city: str) -> str:
734
+ """Get weather for city"""
735
+ return f"Weather in {city}: Sunny, 25C"
736
+
737
+ # Tool implementations: name -> callable
738
+ implementations = {
739
+ "read_file": read_file,
740
+ "get_weather": get_weather,
741
+ }
742
+
743
+ # Tool definitions: OpenAI-format schemas (sent to the API)
744
+ definitions = [
745
+ {
746
+ "type": "function",
747
+ "function": {
748
+ "name": "read_file",
749
+ "description": "Read file contents",
750
+ "parameters": {
751
+ "type": "object",
752
+ "properties": {"path": {"type": "string"}},
753
+ "required": ["path"],
754
+ },
755
+ },
756
+ },
757
+ {
758
+ "type": "function",
759
+ "function": {
760
+ "name": "get_weather",
761
+ "description": "Get weather information",
762
+ "parameters": {
763
+ "type": "object",
764
+ "properties": {"city": {"type": "string"}},
765
+ "required": ["city"],
766
+ },
767
+ },
768
+ },
769
+ ]
770
+
771
+ # Initialize agent with both definitions and implementations
772
+ agent = ToolCallAgent(definitions, implementations)
773
+
774
+ # Run example
775
+ try:
776
+ response, results = agent.run("Read /etc/hosts and get weather in Sydney")
777
+
778
+ print("\n=== Tool Call Results ===")
779
+ for result in results:
780
+ print(f"Tool: {result['tool_name']}")
781
+ print(f"Status: {result['status']}")
782
+ if result["status"] == "success":
783
+ print(f"Result: {str(result['result'])[:200]}...")
784
+ else:
785
+ print(f"Error: {result['error']}")
786
+
787
+ print("\n=== Metrics ===")
788
+ metrics = agent.client.get_metrics()
789
+ print(f"Total attempts: {metrics.total_attempts}")
790
+ print(f"Successful calls: {metrics.successful_calls}")
791
+ print(f"Escalations: {metrics.tool_choice_escalations}")
792
+ print(f"Parallel requested: {metrics.parallel_calls_requested}")
793
+ print(f"Parallel received: {metrics.parallel_calls_received}")
794
+ print(
795
+ f"Success rate: {metrics.successful_calls / metrics.total_attempts * 100:.1f}%"
796
+ )
797
+
798
+ except ToolCallError as e:
799
+ print(f"Tool call failed: {e}")