@qvac/harness 0.1.0 → 0.1.1

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 (460) hide show
  1. package/dist/harness.bundle +8 -59
  2. package/dist/prebuilds-manifest.json +0 -8
  3. package/dist-lib/index.d.ts +240 -0
  4. package/dist-lib/index.js +1063 -0
  5. package/dist-lib/lib/audio-transcode-bare.d.ts +2 -0
  6. package/dist-lib/lib/audio-transcode-bare.js +145 -0
  7. package/dist-lib/lib/audio-transcode-node.d.ts +2 -0
  8. package/dist-lib/lib/audio-transcode-node.js +6 -0
  9. package/dist-lib/lib/capabilities/audio-resample.d.ts +14 -0
  10. package/dist-lib/lib/capabilities/audio-resample.js +72 -0
  11. package/dist-lib/lib/capabilities/completion.d.ts +288 -0
  12. package/dist-lib/lib/capabilities/completion.js +1077 -0
  13. package/dist-lib/lib/capabilities/download.d.ts +46 -0
  14. package/dist-lib/lib/capabilities/download.js +124 -0
  15. package/dist-lib/lib/capabilities/embed.d.ts +20 -0
  16. package/dist-lib/lib/capabilities/embed.js +13 -0
  17. package/dist-lib/lib/capabilities/kv-cache.d.ts +13 -0
  18. package/dist-lib/lib/capabilities/kv-cache.js +21 -0
  19. package/dist-lib/lib/capabilities/prompt-prefix.d.ts +6 -0
  20. package/dist-lib/lib/capabilities/prompt-prefix.js +10 -0
  21. package/dist-lib/lib/capabilities/speech-lexicon.d.ts +5 -0
  22. package/dist-lib/lib/capabilities/speech-lexicon.js +32 -0
  23. package/dist-lib/lib/capabilities/speech-text.d.ts +6 -0
  24. package/dist-lib/lib/capabilities/speech-text.js +79 -0
  25. package/dist-lib/lib/capabilities/tool-names.d.ts +3 -0
  26. package/dist-lib/lib/capabilities/tool-names.js +3 -0
  27. package/dist-lib/lib/capabilities/tool-selection.d.ts +43 -0
  28. package/dist-lib/lib/capabilities/tool-selection.js +60 -0
  29. package/dist-lib/lib/capabilities/tool-turns.d.ts +9 -0
  30. package/dist-lib/lib/capabilities/tool-turns.js +101 -0
  31. package/dist-lib/lib/capabilities/usage-breakdown.d.ts +27 -0
  32. package/dist-lib/lib/capabilities/usage-breakdown.js +44 -0
  33. package/dist-lib/lib/capabilities/vision-history.d.ts +3 -0
  34. package/dist-lib/lib/capabilities/vision-history.js +21 -0
  35. package/dist-lib/lib/capabilities/voice.d.ts +78 -0
  36. package/dist-lib/lib/capabilities/voice.js +189 -0
  37. package/dist-lib/lib/connect.d.ts +76 -0
  38. package/dist-lib/lib/connect.js +789 -0
  39. package/dist-lib/lib/context-window.d.ts +7 -0
  40. package/dist-lib/lib/context-window.js +90 -0
  41. package/dist-lib/lib/contract-types.d.ts +210 -0
  42. package/dist-lib/lib/contract-types.js +1 -0
  43. package/dist-lib/lib/diagram-repair.d.ts +21 -0
  44. package/dist-lib/lib/diagram-repair.js +58 -0
  45. package/dist-lib/lib/dns-lookup.d.ts +1 -0
  46. package/dist-lib/lib/dns-lookup.js +13 -0
  47. package/dist-lib/lib/error-fields.d.ts +2 -0
  48. package/dist-lib/lib/error-fields.js +8 -0
  49. package/dist-lib/lib/fetch-node.d.ts +1 -0
  50. package/dist-lib/lib/fetch-node.js +1 -0
  51. package/dist-lib/lib/hardware/capability-probe.d.ts +9 -0
  52. package/dist-lib/lib/hardware/capability-probe.js +99 -0
  53. package/dist-lib/lib/hardware/gpu-classify.d.ts +2 -0
  54. package/dist-lib/lib/hardware/gpu-classify.js +32 -0
  55. package/dist-lib/lib/hardware/gpu-probe-addon.d.ts +2 -0
  56. package/dist-lib/lib/hardware/gpu-probe-addon.js +42 -0
  57. package/dist-lib/lib/hardware/gpu-stats.bare.d.ts +1 -0
  58. package/dist-lib/lib/hardware/gpu-stats.bare.js +24 -0
  59. package/dist-lib/lib/hardware/gpu-stats.stub.d.ts +1 -0
  60. package/dist-lib/lib/hardware/gpu-stats.stub.js +3 -0
  61. package/dist-lib/lib/hardware/memory-budget.d.ts +8 -0
  62. package/dist-lib/lib/hardware/memory-budget.js +1 -0
  63. package/dist-lib/lib/hardware/parsers.d.ts +7 -0
  64. package/dist-lib/lib/hardware/parsers.js +41 -0
  65. package/dist-lib/lib/headers-bare.d.ts +1 -0
  66. package/dist-lib/lib/headers-bare.js +1 -0
  67. package/dist-lib/lib/headers-node.d.ts +4 -0
  68. package/dist-lib/lib/headers-node.js +1 -0
  69. package/dist-lib/lib/helpers/buffer-burst.d.ts +1 -0
  70. package/dist-lib/lib/helpers/buffer-burst.js +20 -0
  71. package/dist-lib/lib/helpers/control-tokens.d.ts +7 -0
  72. package/dist-lib/lib/helpers/control-tokens.js +32 -0
  73. package/dist-lib/lib/helpers/join-guard.d.ts +6 -0
  74. package/dist-lib/lib/helpers/join-guard.js +46 -0
  75. package/dist-lib/lib/helpers/markup-stream-filter.d.ts +5 -0
  76. package/dist-lib/lib/helpers/markup-stream-filter.js +75 -0
  77. package/dist-lib/lib/helpers/race-abort.d.ts +5 -0
  78. package/dist-lib/lib/helpers/race-abort.js +18 -0
  79. package/dist-lib/lib/helpers/retry-memo.d.ts +5 -0
  80. package/dist-lib/lib/helpers/retry-memo.js +12 -0
  81. package/dist-lib/lib/helpers/run-outcome.d.ts +33 -0
  82. package/dist-lib/lib/helpers/run-outcome.js +204 -0
  83. package/dist-lib/lib/helpers/spawn-path.d.ts +5 -0
  84. package/dist-lib/lib/helpers/spawn-path.js +57 -0
  85. package/dist-lib/lib/helpers/text-coalescer.d.ts +15 -0
  86. package/dist-lib/lib/helpers/text-coalescer.js +34 -0
  87. package/dist-lib/lib/helpers/thinking.d.ts +8 -0
  88. package/dist-lib/lib/helpers/thinking.js +95 -0
  89. package/dist-lib/lib/helpers/tool-call-markup.d.ts +20 -0
  90. package/dist-lib/lib/helpers/tool-call-markup.js +201 -0
  91. package/dist-lib/lib/helpers/tool-intent.d.ts +7 -0
  92. package/dist-lib/lib/helpers/tool-intent.js +21 -0
  93. package/dist-lib/lib/helpers/tool-label.d.ts +8 -0
  94. package/dist-lib/lib/helpers/tool-label.js +131 -0
  95. package/dist-lib/lib/hooks/built-in/arg-repair.d.ts +5 -0
  96. package/dist-lib/lib/hooks/built-in/arg-repair.js +88 -0
  97. package/dist-lib/lib/hooks/built-in/egress.d.ts +5 -0
  98. package/dist-lib/lib/hooks/built-in/egress.js +29 -0
  99. package/dist-lib/lib/hooks/built-in/index.d.ts +3 -0
  100. package/dist-lib/lib/hooks/built-in/index.js +3 -0
  101. package/dist-lib/lib/hooks/built-in/skill-catalog.d.ts +10 -0
  102. package/dist-lib/lib/hooks/built-in/skill-catalog.js +17 -0
  103. package/dist-lib/lib/hooks/pipeline.d.ts +20 -0
  104. package/dist-lib/lib/hooks/pipeline.js +49 -0
  105. package/dist-lib/lib/hooks/registry.d.ts +2 -0
  106. package/dist-lib/lib/hooks/registry.js +6 -0
  107. package/dist-lib/lib/hooks/run.d.ts +5 -0
  108. package/dist-lib/lib/hooks/run.js +83 -0
  109. package/dist-lib/lib/hooks/types.d.ts +57 -0
  110. package/dist-lib/lib/hooks/types.js +1 -0
  111. package/dist-lib/lib/log.d.ts +5 -0
  112. package/dist-lib/lib/log.js +37 -0
  113. package/dist-lib/lib/model-download-progress.d.ts +22 -0
  114. package/dist-lib/lib/model-download-progress.js +95 -0
  115. package/dist-lib/lib/models/context.d.ts +5 -0
  116. package/dist-lib/lib/models/context.js +12 -0
  117. package/dist-lib/lib/models/embed-config.d.ts +14 -0
  118. package/dist-lib/lib/models/embed-config.js +31 -0
  119. package/dist-lib/lib/models/gpu-selection.d.ts +3 -0
  120. package/dist-lib/lib/models/gpu-selection.js +26 -0
  121. package/dist-lib/lib/models/kv-cache.d.ts +4 -0
  122. package/dist-lib/lib/models/kv-cache.js +6 -0
  123. package/dist-lib/lib/models/llm-presets.d.ts +10 -0
  124. package/dist-lib/lib/models/llm-presets.js +58 -0
  125. package/dist-lib/lib/models/model-catalog-constants.d.ts +29 -0
  126. package/dist-lib/lib/models/model-catalog-constants.js +103 -0
  127. package/dist-lib/lib/models/model-catalog.d.ts +125 -0
  128. package/dist-lib/lib/models/model-catalog.js +371 -0
  129. package/dist-lib/lib/models/model-delete.d.ts +18 -0
  130. package/dist-lib/lib/models/model-delete.js +47 -0
  131. package/dist-lib/lib/models/model-handle.d.ts +18 -0
  132. package/dist-lib/lib/models/model-handle.js +33 -0
  133. package/dist-lib/lib/models/model-list.d.ts +42 -0
  134. package/dist-lib/lib/models/model-list.js +123 -0
  135. package/dist-lib/lib/models/model-pool.d.ts +116 -0
  136. package/dist-lib/lib/models/model-pool.js +356 -0
  137. package/dist-lib/lib/models/model-source.d.ts +6 -0
  138. package/dist-lib/lib/models/model-source.js +21 -0
  139. package/dist-lib/lib/models/music-catalog.d.ts +12 -0
  140. package/dist-lib/lib/models/music-catalog.js +26 -0
  141. package/dist-lib/lib/models/opencl-cache.d.ts +5 -0
  142. package/dist-lib/lib/models/opencl-cache.js +50 -0
  143. package/dist-lib/lib/models/sdk-faults.d.ts +21 -0
  144. package/dist-lib/lib/models/sdk-faults.js +66 -0
  145. package/dist-lib/lib/models/tool-dialect.d.ts +2 -0
  146. package/dist-lib/lib/models/tool-dialect.js +19 -0
  147. package/dist-lib/lib/models/tts-model-default.d.ts +3 -0
  148. package/dist-lib/lib/models/tts-model-default.js +13 -0
  149. package/dist-lib/lib/no-redirect-fetch-bare.d.ts +15 -0
  150. package/dist-lib/lib/no-redirect-fetch-bare.js +59 -0
  151. package/dist-lib/lib/no-redirect-fetch-impl.d.ts +39 -0
  152. package/dist-lib/lib/no-redirect-fetch-impl.js +80 -0
  153. package/dist-lib/lib/no-redirect-fetch-node.d.ts +4 -0
  154. package/dist-lib/lib/no-redirect-fetch-node.js +52 -0
  155. package/dist-lib/lib/prompt.d.ts +22 -0
  156. package/dist-lib/lib/prompt.js +77 -0
  157. package/dist-lib/lib/queue.d.ts +9 -0
  158. package/dist-lib/lib/queue.js +48 -0
  159. package/dist-lib/lib/resolution-detector.d.ts +5 -0
  160. package/dist-lib/lib/resolution-detector.js +100 -0
  161. package/dist-lib/lib/rpc-session.d.ts +8 -0
  162. package/dist-lib/lib/rpc-session.js +20 -0
  163. package/dist-lib/lib/sdk-config-loader.node.d.ts +1 -0
  164. package/dist-lib/lib/sdk-config-loader.node.js +1 -0
  165. package/dist-lib/lib/sdk-loader.d.ts +30 -0
  166. package/dist-lib/lib/sdk-loader.js +53 -0
  167. package/dist-lib/lib/sdk-storage.d.ts +8 -0
  168. package/dist-lib/lib/sdk-storage.js +24 -0
  169. package/dist-lib/lib/serve.d.ts +3 -0
  170. package/dist-lib/lib/serve.js +612 -0
  171. package/dist-lib/lib/spawn.d.ts +62 -0
  172. package/dist-lib/lib/spawn.js +71 -0
  173. package/dist-lib/lib/staging.d.ts +4 -0
  174. package/dist-lib/lib/staging.js +28 -0
  175. package/dist-lib/lib/storage.d.ts +18 -0
  176. package/dist-lib/lib/storage.js +26 -0
  177. package/dist-lib/lib/tmp-path.d.ts +7 -0
  178. package/dist-lib/lib/tmp-path.js +17 -0
  179. package/dist-lib/lib/tool-call-display.d.ts +21 -0
  180. package/dist-lib/lib/tool-call-display.js +1 -0
  181. package/dist-lib/lib/tools/catalog.d.ts +13 -0
  182. package/dist-lib/lib/tools/catalog.js +13 -0
  183. package/dist-lib/lib/tools/create-documents.d.ts +3 -0
  184. package/dist-lib/lib/tools/create-documents.js +87 -0
  185. package/dist-lib/lib/tools/edit-documents.d.ts +3 -0
  186. package/dist-lib/lib/tools/edit-documents.js +122 -0
  187. package/dist-lib/lib/tools/edit-image.d.ts +25 -0
  188. package/dist-lib/lib/tools/edit-image.js +271 -0
  189. package/dist-lib/lib/tools/exec/adapters/adapter.d.ts +27 -0
  190. package/dist-lib/lib/tools/exec/adapters/adapter.js +1 -0
  191. package/dist-lib/lib/tools/exec/adapters/python/attachments.d.ts +26 -0
  192. package/dist-lib/lib/tools/exec/adapters/python/attachments.js +160 -0
  193. package/dist-lib/lib/tools/exec/adapters/python/create-effect.d.ts +7 -0
  194. package/dist-lib/lib/tools/exec/adapters/python/create-effect.js +290 -0
  195. package/dist-lib/lib/tools/exec/adapters/python/loader.d.ts +11 -0
  196. package/dist-lib/lib/tools/exec/adapters/python/loader.js +94 -0
  197. package/dist-lib/lib/tools/exec/adapters/python/memfs.d.ts +47 -0
  198. package/dist-lib/lib/tools/exec/adapters/python/memfs.js +85 -0
  199. package/dist-lib/lib/tools/exec/adapters/python/output-policy.d.ts +13 -0
  200. package/dist-lib/lib/tools/exec/adapters/python/output-policy.js +129 -0
  201. package/dist-lib/lib/tools/exec/adapters/python/pyodide.d.ts +19 -0
  202. package/dist-lib/lib/tools/exec/adapters/python/pyodide.js +107 -0
  203. package/dist-lib/lib/tools/exec/adapters/python/python-adapter.d.ts +75 -0
  204. package/dist-lib/lib/tools/exec/adapters/python/python-adapter.js +1094 -0
  205. package/dist-lib/lib/tools/exec/adapters/python/run-session.d.ts +75 -0
  206. package/dist-lib/lib/tools/exec/adapters/python/run-session.js +273 -0
  207. package/dist-lib/lib/tools/exec/adapters/python/wheels.d.ts +38 -0
  208. package/dist-lib/lib/tools/exec/adapters/python/wheels.js +102 -0
  209. package/dist-lib/lib/tools/exec/adapters/python/worker/client.d.ts +7 -0
  210. package/dist-lib/lib/tools/exec/adapters/python/worker/client.js +188 -0
  211. package/dist-lib/lib/tools/exec/adapters/python/worker/entry.d.ts +1 -0
  212. package/dist-lib/lib/tools/exec/adapters/python/worker/entry.js +105 -0
  213. package/dist-lib/lib/tools/exec/adapters/python/worker/protocol.d.ts +38 -0
  214. package/dist-lib/lib/tools/exec/adapters/python/worker/protocol.js +41 -0
  215. package/dist-lib/lib/tools/exec/adapters/python/worker/spawn-bare.d.ts +2 -0
  216. package/dist-lib/lib/tools/exec/adapters/python/worker/spawn-bare.js +30 -0
  217. package/dist-lib/lib/tools/exec/adapters/python/worker/spawn-node.d.ts +13 -0
  218. package/dist-lib/lib/tools/exec/adapters/python/worker/spawn-node.js +45 -0
  219. package/dist-lib/lib/tools/exec/adapters/shell/shell-adapter.d.ts +12 -0
  220. package/dist-lib/lib/tools/exec/adapters/shell/shell-adapter.js +20 -0
  221. package/dist-lib/lib/tools/exec/obsidian/cli-process.d.ts +8 -0
  222. package/dist-lib/lib/tools/exec/obsidian/cli-process.js +74 -0
  223. package/dist-lib/lib/tools/exec/obsidian/cli.d.ts +18 -0
  224. package/dist-lib/lib/tools/exec/obsidian/cli.js +153 -0
  225. package/dist-lib/lib/tools/exec/obsidian/command.d.ts +5 -0
  226. package/dist-lib/lib/tools/exec/obsidian/command.js +18 -0
  227. package/dist-lib/lib/tools/exec/obsidian/guidance.d.ts +5 -0
  228. package/dist-lib/lib/tools/exec/obsidian/guidance.js +18 -0
  229. package/dist-lib/lib/tools/exec/obsidian/note-name.d.ts +1 -0
  230. package/dist-lib/lib/tools/exec/obsidian/note-name.js +6 -0
  231. package/dist-lib/lib/tools/exec/obsidian/output.d.ts +1 -0
  232. package/dist-lib/lib/tools/exec/obsidian/output.js +31 -0
  233. package/dist-lib/lib/tools/exec/obsidian/route.d.ts +19 -0
  234. package/dist-lib/lib/tools/exec/obsidian/route.js +85 -0
  235. package/dist-lib/lib/tools/exec/obsidian/safe-path.d.ts +3 -0
  236. package/dist-lib/lib/tools/exec/obsidian/safe-path.js +56 -0
  237. package/dist-lib/lib/tools/exec/obsidian/vault-create.d.ts +1 -0
  238. package/dist-lib/lib/tools/exec/obsidian/vault-create.js +40 -0
  239. package/dist-lib/lib/tools/exec/obsidian/vault-fs.d.ts +3 -0
  240. package/dist-lib/lib/tools/exec/obsidian/vault-fs.js +57 -0
  241. package/dist-lib/lib/tools/exec/obsidian/vault-paths.d.ts +20 -0
  242. package/dist-lib/lib/tools/exec/obsidian/vault-paths.js +171 -0
  243. package/dist-lib/lib/tools/exec/obsidian/vault-read.d.ts +11 -0
  244. package/dist-lib/lib/tools/exec/obsidian/vault-read.js +119 -0
  245. package/dist-lib/lib/tools/exec/obsidian/vault-write.d.ts +7 -0
  246. package/dist-lib/lib/tools/exec/obsidian/vault-write.js +134 -0
  247. package/dist-lib/lib/tools/exec/runner.d.ts +62 -0
  248. package/dist-lib/lib/tools/exec/runner.js +87 -0
  249. package/dist-lib/lib/tools/exec/scope.d.ts +3 -0
  250. package/dist-lib/lib/tools/exec/scope.js +97 -0
  251. package/dist-lib/lib/tools/exec/shell-argv.d.ts +2 -0
  252. package/dist-lib/lib/tools/exec/shell-argv.js +48 -0
  253. package/dist-lib/lib/tools/exec.d.ts +29 -0
  254. package/dist-lib/lib/tools/exec.js +459 -0
  255. package/dist-lib/lib/tools/file-glob.d.ts +15 -0
  256. package/dist-lib/lib/tools/file-glob.js +112 -0
  257. package/dist-lib/lib/tools/fs/drive.d.ts +26 -0
  258. package/dist-lib/lib/tools/fs/drive.js +1 -0
  259. package/dist-lib/lib/tools/fs/glob.d.ts +1 -0
  260. package/dist-lib/lib/tools/fs/glob.js +34 -0
  261. package/dist-lib/lib/tools/fs/local.d.ts +2 -0
  262. package/dist-lib/lib/tools/fs/local.js +29 -0
  263. package/dist-lib/lib/tools/fs/read.d.ts +2 -0
  264. package/dist-lib/lib/tools/fs/read.js +17 -0
  265. package/dist-lib/lib/tools/fs/remote-protocol.d.ts +40 -0
  266. package/dist-lib/lib/tools/fs/remote-protocol.js +1 -0
  267. package/dist-lib/lib/tools/fs/remote.d.ts +17 -0
  268. package/dist-lib/lib/tools/fs/remote.js +131 -0
  269. package/dist-lib/lib/tools/fs/scope.d.ts +37 -0
  270. package/dist-lib/lib/tools/fs/scope.js +130 -0
  271. package/dist-lib/lib/tools/fs/walk.d.ts +15 -0
  272. package/dist-lib/lib/tools/fs/walk.js +38 -0
  273. package/dist-lib/lib/tools/fs/write.d.ts +4 -0
  274. package/dist-lib/lib/tools/fs/write.js +5 -0
  275. package/dist-lib/lib/tools/generate-image.d.ts +111 -0
  276. package/dist-lib/lib/tools/generate-image.js +369 -0
  277. package/dist-lib/lib/tools/generate-music.d.ts +124 -0
  278. package/dist-lib/lib/tools/generate-music.js +522 -0
  279. package/dist-lib/lib/tools/grep.d.ts +5 -0
  280. package/dist-lib/lib/tools/grep.js +158 -0
  281. package/dist-lib/lib/tools/http-methods.d.ts +1 -0
  282. package/dist-lib/lib/tools/http-methods.js +1 -0
  283. package/dist-lib/lib/tools/http-request/encode-fields.d.ts +2 -0
  284. package/dist-lib/lib/tools/http-request/encode-fields.js +69 -0
  285. package/dist-lib/lib/tools/http-request/truncate-response.d.ts +1 -0
  286. package/dist-lib/lib/tools/http-request/truncate-response.js +83 -0
  287. package/dist-lib/lib/tools/http-request/utils.d.ts +27 -0
  288. package/dist-lib/lib/tools/http-request/utils.js +84 -0
  289. package/dist-lib/lib/tools/http-request.d.ts +20 -0
  290. package/dist-lib/lib/tools/http-request.js +177 -0
  291. package/dist-lib/lib/tools/mcp/utils.d.ts +47 -0
  292. package/dist-lib/lib/tools/mcp/utils.js +172 -0
  293. package/dist-lib/lib/tools/mcp-call.d.ts +14 -0
  294. package/dist-lib/lib/tools/mcp-call.js +155 -0
  295. package/dist-lib/lib/tools/model-args.d.ts +1 -0
  296. package/dist-lib/lib/tools/model-args.js +4 -0
  297. package/dist-lib/lib/tools/operations/builders.d.ts +17 -0
  298. package/dist-lib/lib/tools/operations/builders.js +179 -0
  299. package/dist-lib/lib/tools/operations/compile.d.ts +7 -0
  300. package/dist-lib/lib/tools/operations/compile.js +92 -0
  301. package/dist-lib/lib/tools/operations/gmail-message.d.ts +15 -0
  302. package/dist-lib/lib/tools/operations/gmail-message.js +62 -0
  303. package/dist-lib/lib/tools/operations/manifest.d.ts +60 -0
  304. package/dist-lib/lib/tools/operations/manifest.js +50 -0
  305. package/dist-lib/lib/tools/outbound-guard.d.ts +10 -0
  306. package/dist-lib/lib/tools/outbound-guard.js +127 -0
  307. package/dist-lib/lib/tools/private-ip.d.ts +4 -0
  308. package/dist-lib/lib/tools/private-ip.js +126 -0
  309. package/dist-lib/lib/tools/rag-search.d.ts +2 -0
  310. package/dist-lib/lib/tools/rag-search.js +98 -0
  311. package/dist-lib/lib/tools/read-files.d.ts +5 -0
  312. package/dist-lib/lib/tools/read-files.js +153 -0
  313. package/dist-lib/lib/tools/skill.d.ts +10 -0
  314. package/dist-lib/lib/tools/skill.js +123 -0
  315. package/dist-lib/lib/tools/skills/auth-resolver.d.ts +43 -0
  316. package/dist-lib/lib/tools/skills/auth-resolver.js +121 -0
  317. package/dist-lib/lib/tools/skills/bin-check.d.ts +9 -0
  318. package/dist-lib/lib/tools/skills/bin-check.js +56 -0
  319. package/dist-lib/lib/tools/skills/bundled-dir.d.ts +2 -0
  320. package/dist-lib/lib/tools/skills/bundled-dir.js +117 -0
  321. package/dist-lib/lib/tools/skills/bundled-hash.d.ts +4 -0
  322. package/dist-lib/lib/tools/skills/bundled-hash.js +12 -0
  323. package/dist-lib/lib/tools/skills/catalog.d.ts +60 -0
  324. package/dist-lib/lib/tools/skills/catalog.js +203 -0
  325. package/dist-lib/lib/tools/skills/cli-argv.d.ts +9 -0
  326. package/dist-lib/lib/tools/skills/cli-argv.js +147 -0
  327. package/dist-lib/lib/tools/skills/cli-schema-check.d.ts +3 -0
  328. package/dist-lib/lib/tools/skills/cli-schema-check.js +62 -0
  329. package/dist-lib/lib/tools/skills/cli-schema-load.d.ts +4 -0
  330. package/dist-lib/lib/tools/skills/cli-schema-load.js +90 -0
  331. package/dist-lib/lib/tools/skills/cli-schema-types.d.ts +30 -0
  332. package/dist-lib/lib/tools/skills/cli-schema-types.js +1 -0
  333. package/dist-lib/lib/tools/skills/cli-schema.d.ts +7 -0
  334. package/dist-lib/lib/tools/skills/cli-schema.js +35 -0
  335. package/dist-lib/lib/tools/skills/credential-check.d.ts +20 -0
  336. package/dist-lib/lib/tools/skills/credential-check.js +94 -0
  337. package/dist-lib/lib/tools/skills/credential-grants.d.ts +9 -0
  338. package/dist-lib/lib/tools/skills/credential-grants.js +25 -0
  339. package/dist-lib/lib/tools/skills/credential-health.d.ts +8 -0
  340. package/dist-lib/lib/tools/skills/credential-health.js +51 -0
  341. package/dist-lib/lib/tools/skills/credential-slots.d.ts +7 -0
  342. package/dist-lib/lib/tools/skills/credential-slots.js +8 -0
  343. package/dist-lib/lib/tools/skills/frontmatter-parser.d.ts +23 -0
  344. package/dist-lib/lib/tools/skills/frontmatter-parser.js +68 -0
  345. package/dist-lib/lib/tools/skills/index.d.ts +5 -0
  346. package/dist-lib/lib/tools/skills/index.js +5 -0
  347. package/dist-lib/lib/tools/skills/manifest-parse.d.ts +12 -0
  348. package/dist-lib/lib/tools/skills/manifest-parse.js +199 -0
  349. package/dist-lib/lib/tools/skills/manifest.d.ts +47 -0
  350. package/dist-lib/lib/tools/skills/manifest.js +1 -0
  351. package/dist-lib/lib/tools/skills/mention-name.d.ts +1 -0
  352. package/dist-lib/lib/tools/skills/mention-name.js +4 -0
  353. package/dist-lib/lib/tools/skills/mention.d.ts +6 -0
  354. package/dist-lib/lib/tools/skills/mention.js +42 -0
  355. package/dist-lib/lib/tools/skills/obsidian-readiness.d.ts +16 -0
  356. package/dist-lib/lib/tools/skills/obsidian-readiness.js +95 -0
  357. package/dist-lib/lib/tools/skills/overlay-crud.d.ts +18 -0
  358. package/dist-lib/lib/tools/skills/overlay-crud.js +98 -0
  359. package/dist-lib/lib/tools/skills/overlay-dir.d.ts +2 -0
  360. package/dist-lib/lib/tools/skills/overlay-dir.js +22 -0
  361. package/dist-lib/lib/tools/skills/overlay-watch.d.ts +13 -0
  362. package/dist-lib/lib/tools/skills/overlay-watch.js +44 -0
  363. package/dist-lib/lib/tools/skills/scope-key.d.ts +7 -0
  364. package/dist-lib/lib/tools/skills/scope-key.js +7 -0
  365. package/dist-lib/lib/tools/skills/setup-routes.d.ts +4 -0
  366. package/dist-lib/lib/tools/skills/setup-routes.js +14 -0
  367. package/dist-lib/lib/tools/skills/skill-settings.d.ts +16 -0
  368. package/dist-lib/lib/tools/skills/skill-settings.js +33 -0
  369. package/dist-lib/lib/tools/skills/skill-state-constants.d.ts +12 -0
  370. package/dist-lib/lib/tools/skills/skill-state-constants.js +14 -0
  371. package/dist-lib/lib/tools/skills/skill-state.d.ts +40 -0
  372. package/dist-lib/lib/tools/skills/skill-state.js +117 -0
  373. package/dist-lib/lib/tools/skills/tool-grants.d.ts +5 -0
  374. package/dist-lib/lib/tools/skills/tool-grants.js +14 -0
  375. package/dist-lib/lib/tools/toolsets.d.ts +8 -0
  376. package/dist-lib/lib/tools/toolsets.js +20 -0
  377. package/dist-lib/lib/tools/url-guard.d.ts +8 -0
  378. package/dist-lib/lib/tools/url-guard.js +40 -0
  379. package/dist-lib/lib/tools/web-fetch.d.ts +8 -0
  380. package/dist-lib/lib/tools/web-fetch.js +302 -0
  381. package/dist-lib/lib/tools/web-search.d.ts +6 -0
  382. package/dist-lib/lib/tools/web-search.js +55 -0
  383. package/dist-lib/lib/transport.d.ts +12 -0
  384. package/dist-lib/lib/transport.js +59 -0
  385. package/dist-lib/lib/user-agent.d.ts +1 -0
  386. package/dist-lib/lib/user-agent.js +1 -0
  387. package/dist-lib/lib/validating-lookup.d.ts +17 -0
  388. package/dist-lib/lib/validating-lookup.js +25 -0
  389. package/dist-lib/lib/wav-encode.d.ts +5 -0
  390. package/dist-lib/lib/wav-encode.js +24 -0
  391. package/dist-lib/lib/web-fetch/embedded-state.d.ts +1 -0
  392. package/dist-lib/lib/web-fetch/embedded-state.js +131 -0
  393. package/dist-lib/lib/web-fetch/extract.d.ts +6 -0
  394. package/dist-lib/lib/web-fetch/extract.js +65 -0
  395. package/dist-lib/lib/web-fetch/images.d.ts +3 -0
  396. package/dist-lib/lib/web-fetch/images.js +43 -0
  397. package/dist-lib/lib/web-fetch/video.d.ts +5 -0
  398. package/dist-lib/lib/web-fetch/video.js +42 -0
  399. package/dist-lib/lib/web-search/engine-registry.d.ts +7 -0
  400. package/dist-lib/lib/web-search/engine-registry.js +17 -0
  401. package/dist-lib/lib/web-search/engines/aol.d.ts +3 -0
  402. package/dist-lib/lib/web-search/engines/aol.js +81 -0
  403. package/dist-lib/lib/web-search/engines/bing.d.ts +3 -0
  404. package/dist-lib/lib/web-search/engines/bing.js +111 -0
  405. package/dist-lib/lib/web-search/engines/brave.d.ts +3 -0
  406. package/dist-lib/lib/web-search/engines/brave.js +59 -0
  407. package/dist-lib/lib/web-search/engines/duckduckgo.d.ts +3 -0
  408. package/dist-lib/lib/web-search/engines/duckduckgo.js +112 -0
  409. package/dist-lib/lib/web-search/engines/google.d.ts +3 -0
  410. package/dist-lib/lib/web-search/engines/google.js +92 -0
  411. package/dist-lib/lib/web-search/engines/wikipedia.d.ts +3 -0
  412. package/dist-lib/lib/web-search/engines/wikipedia.js +37 -0
  413. package/dist-lib/lib/web-search/engines/yahoo.d.ts +3 -0
  414. package/dist-lib/lib/web-search/engines/yahoo.js +81 -0
  415. package/dist-lib/lib/web-search/fetch-html.d.ts +25 -0
  416. package/dist-lib/lib/web-search/fetch-html.js +97 -0
  417. package/dist-lib/lib/web-search/format-results.d.ts +3 -0
  418. package/dist-lib/lib/web-search/format-results.js +14 -0
  419. package/dist-lib/lib/web-search/html-helpers.d.ts +3 -0
  420. package/dist-lib/lib/web-search/html-helpers.js +24 -0
  421. package/dist-lib/lib/web-search/merge-results.d.ts +2 -0
  422. package/dist-lib/lib/web-search/merge-results.js +53 -0
  423. package/dist-lib/lib/web-search/orchestrator.d.ts +14 -0
  424. package/dist-lib/lib/web-search/orchestrator.js +50 -0
  425. package/dist-lib/lib/web-search/types.d.ts +34 -0
  426. package/dist-lib/lib/web-search/types.js +1 -0
  427. package/dist-lib/lib/web-search/url-helpers.d.ts +1 -0
  428. package/dist-lib/lib/web-search/url-helpers.js +11 -0
  429. package/dist-lib/lib/web-search/url-normalize.d.ts +1 -0
  430. package/dist-lib/lib/web-search/url-normalize.js +25 -0
  431. package/dist-lib/lib/web-search/user-agents.d.ts +3 -0
  432. package/dist-lib/lib/web-search/user-agents.js +3 -0
  433. package/dist-lib/lib/wire.d.ts +50 -0
  434. package/dist-lib/lib/wire.js +145 -0
  435. package/dist-lib/schema/baseline.d.ts +8 -0
  436. package/dist-lib/schema/baseline.js +35 -0
  437. package/dist-lib/schema/build.d.ts +1 -0
  438. package/dist-lib/schema/build.js +39 -0
  439. package/dist-lib/schema/generate.d.ts +20 -0
  440. package/dist-lib/schema/generate.js +149 -0
  441. package/dist-lib/schema/harness.d.ts +2 -0
  442. package/dist-lib/schema/harness.js +745 -0
  443. package/dist-lib/schema/release-tags.d.ts +5 -0
  444. package/dist-lib/schema/release-tags.js +58 -0
  445. package/dist-lib/spec/bind.d.ts +2 -0
  446. package/dist-lib/spec/bind.js +124 -0
  447. package/dist-lib/spec/calls.d.ts +3 -0
  448. package/dist-lib/spec/calls.js +41 -0
  449. package/dist-lib/spec/hrpc/hrpc.json +356 -0
  450. package/dist-lib/spec/hrpc/index.d.ts +3 -0
  451. package/dist-lib/spec/hrpc/index.js +463 -0
  452. package/dist-lib/spec/hrpc/messages.d.ts +4 -0
  453. package/dist-lib/spec/hrpc/messages.js +3102 -0
  454. package/dist-lib/spec/hyperschema/index.js +3102 -0
  455. package/dist-lib/spec/hyperschema/schema.json +2290 -0
  456. package/dist-lib/spec/hyperschema/types.d.ts +554 -0
  457. package/dist-lib/spec/index.d.ts +8 -0
  458. package/dist-lib/spec/index.js +1 -0
  459. package/package.json +239 -64
  460. package/.gitattributes +0 -1
@@ -0,0 +1,1077 @@
1
+ import process from 'process';
2
+ import { contextCandidates } from "../context-window.js";
3
+ import { errorCode, errorMessage } from "../error-fields.js";
4
+ import { bufferBurst } from "../helpers/buffer-burst.js";
5
+ import { endsTurn, stopAtControlToken, stripControlTokens, truncateAtControlToken } from "../helpers/control-tokens.js";
6
+ import { createMarkupStreamFilter } from "../helpers/markup-stream-filter.js";
7
+ import { AbortedError, raceAbort } from "../helpers/race-abort.js";
8
+ import { createRunOutcomeTracker, degenerateAnswer, unnamedWrites, writeReport } from "../helpers/run-outcome.js";
9
+ import { splitThinking } from "../helpers/thinking.js";
10
+ import { clipRawCall, normalizeToolArgs, recoverMarkupToolCalls, recoverPrintedSkillLoad, recoverSkillNamedCall, stripToolCallMarkup, stripToolResponseBlocks, toolCallMarkup } from "../helpers/tool-call-markup.js";
11
+ import { INTENT_PARAM, INTENT_PARAM_DESCRIPTION, takeToolIntent } from "../helpers/tool-intent.js";
12
+ import { HookPipeline } from "../hooks/pipeline.js";
13
+ import { fallbackToolLabel } from "../helpers/tool-label.js";
14
+ import { hlog } from "../log.js";
15
+ import { resolveLlmGenerationParams } from "../models/llm-presets.js";
16
+ import { customToolDialect } from "../models/model-catalog.js";
17
+ import { isContextOverflowError, isSdkModelWedgedError } from "../models/sdk-faults.js";
18
+ import { annotateLastUserTime, skillsPromptSection, systemPromptParts } from "../prompt.js";
19
+ import { isMetadataMethod } from "../tools/mcp/utils.js";
20
+ import { unquoteArg } from "../tools/model-args.js";
21
+ import { SKILL_TOOL_NAME, WEB_SEARCH_TOOL_NAME } from "./tool-names.js";
22
+ import { promptUsageParts, usageBreakdown } from "./usage-breakdown.js";
23
+ import { collectToolGrants, enabledTools, isSelected, skillIsActive, skillsAreSelected } from "./tool-selection.js";
24
+ import { guardToolCall } from "../tools/outbound-guard.js";
25
+ import { isAvailableState } from "../tools/skills/skill-state-constants.js";
26
+ import { resolveImplicitSkill, resolveSkillMention, skillPreloadMessage } from "../tools/skills/mention.js";
27
+ import { permittedTools } from "../tools/toolsets.js";
28
+ import { promptPrefixHash } from "./prompt-prefix.js";
29
+ import { DIRECT_CALL_ID, loadedSkillFilesFrom, loadedSkillsFrom, TOOL_CONTINUATION_NUDGE, toolResultTurn, withoutSkillLoadTurns } from "./tool-turns.js";
30
+ import { projectVisionHistory, visionHistoryCacheKey } from "./vision-history.js";
31
+ export function imageSettingsFrom(agent) {
32
+ if (!agent)
33
+ return undefined;
34
+ const settings = {};
35
+ if (agent.imageModelChoice)
36
+ settings.modelChoice = agent.imageModelChoice;
37
+ if (agent.imageSteps)
38
+ settings.steps = agent.imageSteps;
39
+ if (agent.imageWidth)
40
+ settings.width = agent.imageWidth;
41
+ if (agent.imageHeight)
42
+ settings.height = agent.imageHeight;
43
+ return Object.keys(settings).length ? settings : undefined;
44
+ }
45
+ const BURST_WINDOW_MS = 100;
46
+ const MAX_TOOL_ROUNDS = 10;
47
+ const RUN_WALL_CLOCK_BUDGET_MS = 30 * 60_000;
48
+ function runWallClockBudgetMs() {
49
+ const ms = Number(process.env.QVAC_RUN_BUDGET_MS);
50
+ return ms > 0 ? ms : RUN_WALL_CLOCK_BUDGET_MS;
51
+ }
52
+ const CONTEXT_OVERFLOW_MESSAGE = 'This message is too large for the model context window.';
53
+ const MAX_MUTE_ROUNDS = 1;
54
+ const NARRATED_INTENT = /\b(I['’]ll|I will|Now I|Let me(?! know)|Next,? I)\b[^.!?]*[.!?]?\s*$/i;
55
+ const MAX_WEB_SEARCHES_PER_TURN = 3;
56
+ const MAX_CAPPED_ROUNDS = 1;
57
+ const WEB_SEARCH_LIMIT_MESSAGE = 'Web search limit reached for this question. Answer now from the results already gathered. ' +
58
+ 'If something was not found, say so plainly and mention the most relevant sources. ' +
59
+ 'Do not call web_search again.';
60
+ export function trustedSourcesFrom(history) {
61
+ const sources = [];
62
+ for (const entry of history) {
63
+ const text = String(entry.content ?? '');
64
+ if (entry.role === 'user')
65
+ sources.push({ origin: 'user', text });
66
+ else if (entry.role === 'tool')
67
+ sources.push({ origin: originOfToolTurn(text), text });
68
+ }
69
+ return sources;
70
+ }
71
+ function originOfToolTurn(text) {
72
+ return text.startsWith(`[Tool: ${SKILL_TOOL_NAME} (`) ? 'skill' : 'tool-result';
73
+ }
74
+ const noop = () => { };
75
+ function intentParameters(tool) {
76
+ if (tool.autoApprove === true || INTENT_PARAM in tool.parameters.properties) {
77
+ return tool.parameters;
78
+ }
79
+ return {
80
+ ...tool.parameters,
81
+ properties: {
82
+ [INTENT_PARAM]: { type: 'string', description: INTENT_PARAM_DESCRIPTION },
83
+ ...tool.parameters.properties
84
+ },
85
+ required: [INTENT_PARAM, ...(tool.parameters.required ?? [])]
86
+ };
87
+ }
88
+ export function toSdkTool(tool) {
89
+ return {
90
+ type: 'function',
91
+ name: tool.name,
92
+ description: tool.description,
93
+ parameters: intentParameters(tool)
94
+ };
95
+ }
96
+ function sanitizeTurn(turn) {
97
+ const stripped = stripControlTokens(turn.content);
98
+ const content = turn.role === 'assistant' ? stripToolCallMarkup(stripped) : stripped;
99
+ return content === turn.content ? turn : { ...turn, content };
100
+ }
101
+ function lastUserContent(messages) {
102
+ for (let i = messages.length - 1; i >= 0; i--) {
103
+ const turn = messages[i];
104
+ if (turn?.role === 'user')
105
+ return turn.content;
106
+ }
107
+ return '';
108
+ }
109
+ function lastUserImages(messages) {
110
+ for (let i = messages.length - 1; i >= 0; i--) {
111
+ const turn = messages[i];
112
+ if (turn?.role === 'user')
113
+ return turn.attachments ?? [];
114
+ }
115
+ return [];
116
+ }
117
+ function explicitWebSearchQuery(text, tools, { skillPreloaded }) {
118
+ if (!tools.some((tool) => tool.name === WEB_SEARCH_TOOL_NAME))
119
+ return null;
120
+ if (explicitlyDisablesWebSearch(text))
121
+ return null;
122
+ const named = /\b(?:search|browse|look\s+up|find)\s+(?:the\s+)?(?:web|internet|online)\b/i.test(text);
123
+ const freshness = /\b(?:latest|current|recent)\s+(?:news|events)\b/i.test(text) ||
124
+ /\bwhat(?:'s|\s+is)\s+(?:the\s+)?(?:latest|current|recent)\b/i.test(text);
125
+ const explicit = named || (freshness && !skillPreloaded);
126
+ return explicit && text.trim() ? text.trim() : null;
127
+ }
128
+ function explicitlyDisablesWebSearch(text) {
129
+ return (/\b(?:do\s+not|don't|dont|never)\s+(?:search|browse|look\s+up|find|use)\s+(?:the\s+)?(?:web|internet|online)\b/i.test(text) ||
130
+ /\b(?:avoid|without)\s+(?:searching|browsing|using)\s+(?:the\s+)?(?:web|internet|online)\b/i.test(text));
131
+ }
132
+ function directToolHistory(history, args, output) {
133
+ return [
134
+ ...history,
135
+ {
136
+ role: 'assistant',
137
+ content: toolCallMarkup([{ name: WEB_SEARCH_TOOL_NAME, arguments: args }])
138
+ },
139
+ { role: 'tool', content: toolResultTurn(WEB_SEARCH_TOOL_NAME, DIRECT_CALL_ID, output) }
140
+ ];
141
+ }
142
+ function assistantToolTurn(contentText, calls) {
143
+ if (!calls.length || contentText.includes('<function='))
144
+ return contentText;
145
+ const markup = toolCallMarkup(calls);
146
+ return contentText ? `${contentText}\n${markup}` : markup;
147
+ }
148
+ function preloadLastUser(messages, name, body) {
149
+ for (let i = messages.length - 1; i >= 0; i--) {
150
+ const turn = messages[i];
151
+ if (turn?.role !== 'user')
152
+ continue;
153
+ const next = [...messages];
154
+ next[i] = { ...turn, content: skillPreloadMessage(turn.content, name, body) };
155
+ return next;
156
+ }
157
+ return messages;
158
+ }
159
+ function collectStats(state, stats) {
160
+ if (!stats)
161
+ return;
162
+ if (state.ttft === undefined && stats.timeToFirstToken)
163
+ state.ttft = stats.timeToFirstToken;
164
+ if (state.promptTokensPerSecond === undefined && stats.promptTokensPerSecond) {
165
+ state.promptTokensPerSecond = stats.promptTokensPerSecond;
166
+ }
167
+ if (stats.generatedTokens) {
168
+ state.tokens += stats.generatedTokens;
169
+ if (stats.tokensPerSecond) {
170
+ state.durationMs += (stats.generatedTokens / stats.tokensPerSecond) * 1000;
171
+ state.timedTokens += stats.generatedTokens;
172
+ }
173
+ }
174
+ if (stats.promptTokens)
175
+ state.promptTokens = stats.promptTokens;
176
+ if (stats.cacheTokens)
177
+ state.cacheTokens = stats.cacheTokens;
178
+ }
179
+ function metricsEvent(state, usage) {
180
+ if (!state.tokens)
181
+ return null;
182
+ return {
183
+ type: 'metrics',
184
+ totalTokens: state.tokens,
185
+ durationMs: Math.round(state.durationMs),
186
+ timeToFirstToken: state.ttft,
187
+ promptTokensPerSecond: state.promptTokensPerSecond,
188
+ tokensPerSecond: state.durationMs > 0 ? (state.timedTokens / state.durationMs) * 1000 : undefined,
189
+ promptTokens: state.promptTokens,
190
+ cacheTokens: state.cacheTokens,
191
+ ...(state.ctxSize ? { ctxSize: state.ctxSize } : {}),
192
+ ...(state.backends.length ? { backends: state.backends } : {}),
193
+ ...(usage ? { usage } : {})
194
+ };
195
+ }
196
+ const TOOL_DENIED_MESSAGE = 'The user declined this call. Do not retry it or call it with different arguments to get ' +
197
+ 'around the refusal. Tell the user plainly what you could not do, and never present a ' +
198
+ 'result you did not obtain.';
199
+ function deniedResult() {
200
+ return { error: TOOL_DENIED_MESSAGE, denied: true };
201
+ }
202
+ function denialKey(name, args) {
203
+ try {
204
+ return `${name}:${JSON.stringify(args)}`;
205
+ }
206
+ catch {
207
+ return name;
208
+ }
209
+ }
210
+ function terminalCall(result, outcome, options) {
211
+ return { result, outcome, executed: options.executed };
212
+ }
213
+ function executedCall(result, outcome) {
214
+ return terminalCall(result, outcome, { executed: true });
215
+ }
216
+ function guidanceResult(message) {
217
+ return terminalCall({ error: message, guidance: true }, { kind: 'guidance', message }, {
218
+ executed: false
219
+ });
220
+ }
221
+ function blockedResult(result, reason) {
222
+ return terminalCall(result, { kind: 'blocked', reason }, { executed: false });
223
+ }
224
+ function deniedCall() {
225
+ return terminalCall(deniedResult(), { kind: 'denied', reason: TOOL_DENIED_MESSAGE }, {
226
+ executed: false
227
+ });
228
+ }
229
+ async function executeCall(tool, args, ctx, { approve, signal, denied, sources = [], effect: classified, skipApprovals, onToolActivity, intent, display }) {
230
+ const validationError = tool.validate?.(args, ctx);
231
+ if (validationError) {
232
+ hlog('tool rejected: arguments failed validation', { tool: tool.name });
233
+ return guidanceResult(validationError);
234
+ }
235
+ const refusal = guardToolCall(tool.name, args, sources, {
236
+ externalWrite: tool.externalWrite === true
237
+ });
238
+ if (refusal) {
239
+ hlog('tool refused: unverifiable value in payload', { tool: tool.name });
240
+ onToolActivity?.({
241
+ type: 'tool-activity',
242
+ name: tool.name,
243
+ args,
244
+ resource: tool.resource?.(args) ?? null,
245
+ effect: tool.effect(args, ctx),
246
+ decision: 'blocked'
247
+ });
248
+ return blockedResult({ error: refusal, guidance: true }, refusal);
249
+ }
250
+ const key = denialKey(tool.name, args);
251
+ if (denied?.has(key)) {
252
+ hlog('tool denied already, not asking again', { tool: tool.name });
253
+ return deniedCall();
254
+ }
255
+ const effect = classified ?? tool.effect(args, ctx);
256
+ const resource = tool.resource?.(args) ?? null;
257
+ const autoRun = effect === 'read' || tool.autoApprove === true || skipApprovals === true;
258
+ hlog('tool decision', {
259
+ tool: tool.name,
260
+ effect,
261
+ auto: autoRun,
262
+ asks: Boolean(approve)
263
+ });
264
+ const approved = autoRun ||
265
+ (approve
266
+ ? await raceAbort(approve({
267
+ name: tool.name,
268
+ arguments: args,
269
+ resource,
270
+ effect,
271
+ intent: intent ?? null,
272
+ display: display ?? null
273
+ }), signal)
274
+ : false);
275
+ hlog(`tool ${approved ? 'approved' : 'denied'}`, { tool: tool.name });
276
+ const decision = tool.autoApprove === true || effect === 'read'
277
+ ? 'auto'
278
+ : skipApprovals === true
279
+ ? 'skip-all'
280
+ : approved
281
+ ? 'allowed'
282
+ : 'denied';
283
+ onToolActivity?.({
284
+ type: 'tool-activity',
285
+ name: tool.name,
286
+ args,
287
+ resource,
288
+ effect,
289
+ decision
290
+ });
291
+ if (!approved) {
292
+ denied?.add(key);
293
+ return deniedCall();
294
+ }
295
+ let output;
296
+ let outcome = { kind: 'success' };
297
+ try {
298
+ output = await tool.execute(args, { ...ctx, signal });
299
+ hlog('tool done', { tool: tool.name });
300
+ }
301
+ catch (err) {
302
+ const message = errorMessage(err);
303
+ hlog('tool failed', { tool: tool.name, err: message });
304
+ output = { error: message, code: errorCode(err) };
305
+ outcome = { kind: 'error', message, error: err };
306
+ }
307
+ return executedCall(output, outcome);
308
+ }
309
+ function runToolContext(scope) {
310
+ const { agent, attach, fetchAttachment, ragSearch, progress, askUser, signal, runBudget } = scope;
311
+ const image = imageSettingsFrom(agent);
312
+ return (turnImages = [], ctxSize) => ({
313
+ agentId: agent?.id ?? null,
314
+ ctxSize,
315
+ ...(image ? { image } : {}),
316
+ ...(turnImages.length ? { turnImages } : {}),
317
+ ...(attach ? { attach } : {}),
318
+ ...(fetchAttachment ? { fetchAttachment } : {}),
319
+ ...(ragSearch ? { ragSearch } : {}),
320
+ ...(progress ? { progress } : {}),
321
+ ...(askUser ? { askUser } : {}),
322
+ ...(signal ? { signal } : {}),
323
+ ...(runBudget ? { runBudget } : {})
324
+ });
325
+ }
326
+ function labelOf(name, args, emoji) {
327
+ const display = { label: fallbackToolLabel(name, args) };
328
+ return emoji ? { ...display, iconEmoji: emoji } : display;
329
+ }
330
+ async function settleToolCall(pipeline, execution, call) {
331
+ const folded = await pipeline.runPostToolFold({
332
+ toolName: call.name,
333
+ agentId: call.agentId,
334
+ args: call.args,
335
+ effect: call.effect ?? 'write',
336
+ resource: call.resource,
337
+ toolset: call.tool?.toolset,
338
+ result: execution.result,
339
+ outcome: execution.outcome,
340
+ executed: execution.executed
341
+ });
342
+ return {
343
+ result: folded.result,
344
+ outcome: folded.outcome ?? execution.outcome
345
+ };
346
+ }
347
+ function skillInContext(entry) {
348
+ return entry.status === undefined || isAvailableState(entry.status);
349
+ }
350
+ function unreadySkillState(name, catalog) {
351
+ const status = catalog.find((entry) => entry.name === name)?.status;
352
+ return status !== undefined && !isAvailableState(status) ? status : null;
353
+ }
354
+ function blockedSkillMessage(name, catalog, listShown) {
355
+ if (catalog.some((entry) => entry.name === name)) {
356
+ return (`skill "${name}" is not enabled for this agent. Do not rebuild what it does with another ` +
357
+ `tool — answer from what you already have, or tell the user to enable it in Skills.`);
358
+ }
359
+ return listShown
360
+ ? `there is no skill named "${name}". Load one from the skills list you were shown, or ` +
361
+ `answer from what you already have — do not guess another name.`
362
+ : `there is no skill named "${name}". You were not shown a skills list, which means no ` +
363
+ `skill is available this turn — do not guess another name, and answer from what you ` +
364
+ `already have.`;
365
+ }
366
+ async function resolveToolCalls(toolCalls, enabled, agentId, pipeline, skillNames, signal) {
367
+ const resolved = [];
368
+ for (const call of toolCalls) {
369
+ if (signal?.aborted)
370
+ throw new AbortedError();
371
+ const tool = enabled.find((t) => t.name === call.name);
372
+ if (!tool) {
373
+ const { args } = takeToolIntent(call.arguments);
374
+ resolved.push({
375
+ call,
376
+ args,
377
+ ...(call.raw === undefined ? {} : { rawCall: clipRawCall(call.raw) })
378
+ });
379
+ continue;
380
+ }
381
+ const taken = takeToolIntent(call.arguments);
382
+ const args = normalizeToolArgs(taken.args, Object.keys(tool.parameters.properties));
383
+ const { intent } = taken;
384
+ const fold = await pipeline.runPreToolFold({
385
+ toolName: tool.name,
386
+ args,
387
+ agentId,
388
+ skillNames,
389
+ parameters: tool.parameters,
390
+ signal
391
+ });
392
+ resolved.push(fold.ok
393
+ ? {
394
+ call,
395
+ tool,
396
+ args: fold.args,
397
+ ...(call.raw === undefined ? {} : { rawCall: clipRawCall(call.raw) }),
398
+ ...(intent ? { intent } : {})
399
+ }
400
+ : {
401
+ call,
402
+ tool,
403
+ args,
404
+ rejection: fold.rejection,
405
+ ...(call.raw === undefined ? {} : { rawCall: clipRawCall(call.raw) }),
406
+ ...(intent ? { intent } : {})
407
+ });
408
+ }
409
+ return resolved;
410
+ }
411
+ function unprovenReplay(state, final) {
412
+ if (!state.unproven)
413
+ return null;
414
+ if (state.stopToken)
415
+ return endsTurn(state.stopToken) ? state.unproven : null;
416
+ if (final.stopReason === 'length' || final.stopReason === 'cancelled')
417
+ return null;
418
+ return state.unproven;
419
+ }
420
+ async function* runRoundTokens(sdk, result, state, signal, startInThink = false) {
421
+ const cancelThisRound = () => {
422
+ if (result.requestId)
423
+ sdk.cancel?.({ requestId: result.requestId });
424
+ };
425
+ signal?.addEventListener('abort', cancelThisRound, { once: true });
426
+ const tokens = stopAtControlToken(result.tokenStream, (token) => {
427
+ state.stopToken = token;
428
+ });
429
+ let tokenEvents = 0;
430
+ const events = splitThinking(bufferBurst(tokens, BURST_WINDOW_MS), { startInThink });
431
+ const thinkingFilter = createMarkupStreamFilter();
432
+ const contentFilter = createMarkupStreamFilter();
433
+ try {
434
+ while (true) {
435
+ const next = await events.next();
436
+ if (next.done) {
437
+ state.unproven = next.value;
438
+ const thinkingTail = thinkingFilter.flush();
439
+ if (thinkingTail)
440
+ yield { type: 'thinking', text: thinkingTail };
441
+ const contentTail = contentFilter.flush();
442
+ if (contentTail)
443
+ yield { type: 'content', text: contentTail };
444
+ break;
445
+ }
446
+ if (signal?.aborted)
447
+ throw new AbortedError();
448
+ tokenEvents++;
449
+ if (next.value.type === 'content')
450
+ state.rawContentText += next.value.text;
451
+ const filter = next.value.type === 'thinking' ? thinkingFilter : contentFilter;
452
+ const text = filter.push(next.value.text);
453
+ if (text)
454
+ yield { type: next.value.type, text };
455
+ }
456
+ hlog('stream ended', { events: tokenEvents, stopToken: state.stopToken });
457
+ if (state.stopToken)
458
+ cancelThisRound();
459
+ }
460
+ finally {
461
+ signal?.removeEventListener('abort', cancelThisRound);
462
+ await events.return(null);
463
+ }
464
+ }
465
+ const TRUNCATED_FINAL_MS = 2000;
466
+ function truncatedFinal(final, contentText) {
467
+ const accepted = { contentText, toolCalls: [], raw: { fullText: contentText } };
468
+ let timer;
469
+ const expired = new Promise((resolve) => {
470
+ timer = setTimeout(() => resolve(accepted), TRUNCATED_FINAL_MS);
471
+ });
472
+ const guarded = final.catch((err) => {
473
+ if (isSdkModelWedgedError(err))
474
+ throw err;
475
+ return accepted;
476
+ });
477
+ guarded.catch(noop);
478
+ return Promise.race([guarded, expired]).finally(() => clearTimeout(timer));
479
+ }
480
+ async function* runRecoveredRound(sdk, args) {
481
+ const lease = args.acquireRound ? await args.acquireRound() : null;
482
+ try {
483
+ return yield* runRecoveredRoundWith(sdk, args, lease?.modelId ?? args.modelId);
484
+ }
485
+ finally {
486
+ lease?.release();
487
+ }
488
+ }
489
+ async function* runRecoveredRoundWith(sdk, args, modelId) {
490
+ let lastOverflow = null;
491
+ for (const candidate of contextCandidates(args.history)) {
492
+ if (args.signal?.aborted)
493
+ throw new AbortedError();
494
+ let contentText = '';
495
+ let emitted = false;
496
+ const state = { stopToken: null, unproven: null, rawContentText: '' };
497
+ const cacheable = candidate.history === args.history;
498
+ try {
499
+ const result = sdk.completion({
500
+ modelId,
501
+ history: projectVisionHistory(candidate.history),
502
+ stream: true,
503
+ tools: args.tools,
504
+ generationParams: args.generationParams,
505
+ ...(args.responseFormat ? { responseFormat: args.responseFormat } : {}),
506
+ toolDialect: args.toolDialect,
507
+ ...(cacheable && args.cacheKey ? { kvCache: args.cacheKey } : {})
508
+ });
509
+ result.final.catch(noop);
510
+ const startInThink = args.generationParams?.reasoning_budget === -1;
511
+ for await (const event of runRoundTokens(sdk, result, state, args.signal, startInThink)) {
512
+ if (event.type === 'content')
513
+ contentText += event.text;
514
+ emitted = true;
515
+ yield event;
516
+ }
517
+ const final = state.stopToken
518
+ ? await truncatedFinal(result.final, state.rawContentText)
519
+ : await raceAbort(result.final, args.signal);
520
+ const replay = unprovenReplay(state, final);
521
+ hlog('final', {
522
+ stopReason: final.stopReason,
523
+ toolCalls: final.toolCalls?.length ?? 0,
524
+ stopToken: state.stopToken,
525
+ replay: replay !== null
526
+ });
527
+ return {
528
+ contentText,
529
+ final,
530
+ history: candidate.history,
531
+ cacheable,
532
+ unproven: state.unproven,
533
+ replay
534
+ };
535
+ }
536
+ catch (err) {
537
+ if (!isContextOverflowError(err))
538
+ throw err;
539
+ if (emitted)
540
+ throw new Error(CONTEXT_OVERFLOW_MESSAGE, { cause: err });
541
+ lastOverflow = err;
542
+ }
543
+ }
544
+ if (lastOverflow)
545
+ throw new Error(CONTEXT_OVERFLOW_MESSAGE, { cause: lastOverflow });
546
+ throw new Error('context recovery produced no completion candidate');
547
+ }
548
+ function* reportUnnamedWrites(said, landed) {
549
+ const unreported = writeReport(unnamedWrites(said, landed));
550
+ if (unreported)
551
+ yield { type: 'content', text: unreported };
552
+ }
553
+ export async function* completion(sdk, { modelId, acquireRound, model, agent, ctxSize, cacheKey, thinkingDefault, generationParams: generationParamsOverride, responseFormat, messages: storedMessages, tools: allTools = [], skillCatalog = [], approve, attach, fetchAttachment, ragSearch, progress, askUser, signal, toolConfigs, fsRoots = [], fsWriteRoots = [] }) {
554
+ const pipeline = new HookPipeline();
555
+ const agentId = agent?.id ?? null;
556
+ const tools = permittedTools(allTools, agent?.disabledToolsets);
557
+ const writableRoots = [
558
+ ...fsWriteRoots,
559
+ ...fsRoots.filter((root) => root.kind === 'hyper' && root.writable && !fsWriteRoots.includes(root))
560
+ ];
561
+ const messages = storedMessages.map(sanitizeTurn);
562
+ const stats = { tokens: 0, timedTokens: 0, durationMs: 0, ctxSize, backends: [] };
563
+ let runOutcome = 'abandoned';
564
+ let runError;
565
+ const runOutcomes = createRunOutcomeTracker();
566
+ const landed = runOutcomes.confirmedWrites;
567
+ try {
568
+ if (signal?.aborted)
569
+ throw new AbortedError();
570
+ await pipeline.onRunStart({ agentId, messages });
571
+ const runBudget = {
572
+ deadlineMs: Date.now() + runWallClockBudgetMs(),
573
+ outputBytesUsed: 0
574
+ };
575
+ const toolContext = runToolContext({
576
+ agent,
577
+ attach,
578
+ fetchAttachment,
579
+ ragSearch,
580
+ progress,
581
+ askUser,
582
+ signal,
583
+ runBudget
584
+ });
585
+ const turnImages = lastUserImages(messages);
586
+ const toolsSelected = isSelected(agent?.toolsScope, agent?.enabledTools);
587
+ const skillsSelected = skillsAreSelected(agent?.skillsScope, Boolean(agent));
588
+ const inContextSkills = skillCatalog.filter(skillInContext);
589
+ const mention = resolveSkillMention(lastUserContent(messages), inContextSkills);
590
+ const loadedSkills = loadedSkillsFrom(messages);
591
+ const loadedSkillFiles = loadedSkillFilesFrom(messages);
592
+ const activation = {
593
+ skillsSelected,
594
+ enabledSkills: agent?.enabledSkills ?? [],
595
+ mention: mention?.name ?? null,
596
+ loadedSkills
597
+ };
598
+ const activeSkills = inContextSkills.filter((skill) => skillIsActive(skill.name, activation));
599
+ const { grantedNames, grantedOwners, grantedOps } = collectToolGrants(activeSkills);
600
+ const enabled = responseFormat
601
+ ? []
602
+ : enabledTools(tools, {
603
+ toolsSelected,
604
+ allowlist: agent?.enabledTools ?? [],
605
+ grantedNames,
606
+ grantedOwners,
607
+ hasRoots: fsRoots.length > 0,
608
+ hasWriteRoots: writableRoots.length > 0,
609
+ hasActiveSkills: activeSkills.length > 0
610
+ });
611
+ const sdkTools = enabled.length ? enabled.map((tool) => toSdkTool(tool)) : undefined;
612
+ const reasoningEnabled = agent?.reasoning === 'enabled' ? true : agent?.reasoning === 'disabled' ? false : undefined;
613
+ const deviceReasoning = thinkingDefault === 'enabled' ? true : thinkingDefault === 'disabled' ? false : undefined;
614
+ const resolvedGenerationParams = resolveLlmGenerationParams(model, reasoningEnabled, deviceReasoning);
615
+ const generationParams = generationParamsOverride
616
+ ? { ...resolvedGenerationParams, ...generationParamsOverride }
617
+ : resolvedGenerationParams;
618
+ const loadedThisTurn = new Set();
619
+ let skillIcon = null;
620
+ const skillEmoji = (name) => skillCatalog.find((entry) => entry.name === name)?.emoji ?? null;
621
+ const nudgedSkills = new Set();
622
+ const toolDialect = model ? customToolDialect(model) : undefined;
623
+ let turns = messages;
624
+ let preloadedSkill = null;
625
+ let stubDropped = false;
626
+ const preload = mention ?? resolveImplicitSkill(lastUserContent(messages), activeSkills);
627
+ if (preload) {
628
+ const loader = tools.find((tool) => tool.name === SKILL_TOOL_NAME);
629
+ const loaded = loader ? await loader.execute({ name: preload.name }, toolContext()) : null;
630
+ if (loaded && typeof loaded === 'object' && 'content' in loaded) {
631
+ preloadedSkill = String(loaded.content);
632
+ const inlined = preloadLastUser(messages, preload.name, preloadedSkill);
633
+ turns = withoutSkillLoadTurns(inlined, preload.name);
634
+ stubDropped = turns.length < inlined.length;
635
+ if (!loadedSkills.has(preload.name)) {
636
+ const preloadArgs = { name: preload.name };
637
+ const preloadEffect = 'read';
638
+ const preloadResource = loader?.resource?.(preloadArgs) ?? null;
639
+ yield {
640
+ type: 'tool-call',
641
+ name: SKILL_TOOL_NAME,
642
+ args: preloadArgs,
643
+ effect: preloadEffect,
644
+ display: labelOf(SKILL_TOOL_NAME, preloadArgs, skillEmoji(preload.name))
645
+ };
646
+ yield {
647
+ type: 'tool-activity',
648
+ name: SKILL_TOOL_NAME,
649
+ args: { name: preload.name },
650
+ resource: null,
651
+ effect: 'read',
652
+ decision: 'auto'
653
+ };
654
+ const settled = await settleToolCall(pipeline, executedCall(loaded, { kind: 'success' }), {
655
+ agentId,
656
+ tool: loader,
657
+ name: SKILL_TOOL_NAME,
658
+ args: preloadArgs,
659
+ effect: preloadEffect,
660
+ resource: preloadResource
661
+ });
662
+ yield {
663
+ type: 'tool-result',
664
+ name: SKILL_TOOL_NAME,
665
+ result: settled.result
666
+ };
667
+ }
668
+ }
669
+ }
670
+ if (preload && preloadedSkill) {
671
+ loadedSkills.add(preload.name);
672
+ loadedThisTurn.add(preload.name);
673
+ skillIcon = skillEmoji(preload.name) ?? skillIcon;
674
+ }
675
+ const system = systemPromptParts({
676
+ bio: agent?.bio,
677
+ toolNames: enabled.map((tool) => tool.name),
678
+ skillsSection: skillsPromptSection(activeSkills)
679
+ });
680
+ const systemContent = system.text;
681
+ const promptPrefix = promptPrefixHash({ system: systemContent, tools: sdkTools });
682
+ const promptParts = promptUsageParts({ system, toolSchemas: sdkTools });
683
+ let history = annotateLastUserTime(systemContent ? [{ role: 'system', content: systemContent }, ...turns] : turns);
684
+ let roundCacheKey = stubDropped ? undefined : visionHistoryCacheKey(cacheKey, history);
685
+ const runUsage = () => usageBreakdown(promptParts, stats.cacheTokens, model);
686
+ const denied = new Set();
687
+ let webSearches = 0;
688
+ const sources = trustedSourcesFrom(messages);
689
+ if (preloadedSkill)
690
+ sources.push({ origin: 'skill', text: preloadedSkill });
691
+ const query = explicitWebSearchQuery(lastUserContent(messages), enabled, {
692
+ skillPreloaded: preloadedSkill !== null
693
+ });
694
+ const webSearch = enabled.find((tool) => tool.name === WEB_SEARCH_TOOL_NAME);
695
+ if (query && webSearch) {
696
+ runOutcomes.beginRound();
697
+ const fold = await pipeline.runPreToolFold({
698
+ toolName: webSearch.name,
699
+ args: { query },
700
+ agentId: agent?.id ?? null,
701
+ signal
702
+ });
703
+ const args = fold.ok ? fold.args : { query };
704
+ const searchEffect = webSearch.effect(args);
705
+ const searchResource = webSearch.resource?.(args) ?? null;
706
+ const searchCallDisplay = labelOf(webSearch.name, args, null);
707
+ if (signal?.aborted)
708
+ throw new AbortedError();
709
+ yield {
710
+ type: 'tool-call',
711
+ name: webSearch.name,
712
+ args,
713
+ effect: searchEffect,
714
+ display: searchCallDisplay
715
+ };
716
+ let activity = null;
717
+ const execution = fold.ok
718
+ ? await executeCall(webSearch, args, toolContext(turnImages, ctxSize), {
719
+ approve,
720
+ signal,
721
+ denied,
722
+ skipApprovals: agent?.approvalMode === 'skip-all',
723
+ display: searchCallDisplay,
724
+ onToolActivity: (a) => (activity = a)
725
+ })
726
+ : terminalCall(fold.rejection, { kind: 'guidance', message: fold.rejection.error }, {
727
+ executed: false
728
+ });
729
+ const settled = await settleToolCall(pipeline, execution, {
730
+ agentId,
731
+ tool: webSearch,
732
+ name: webSearch.name,
733
+ args,
734
+ effect: searchEffect,
735
+ resource: searchResource
736
+ });
737
+ const output = settled.result;
738
+ const executionOutcome = settled.outcome;
739
+ runOutcomes.record(output, executionOutcome);
740
+ runOutcomes.finishRound();
741
+ if (fold.ok)
742
+ webSearches++;
743
+ if (!activity && !fold.ok) {
744
+ activity = {
745
+ type: 'tool-activity',
746
+ name: webSearch.name,
747
+ args,
748
+ resource: searchResource,
749
+ effect: searchEffect,
750
+ decision: 'blocked'
751
+ };
752
+ }
753
+ if (activity)
754
+ yield activity;
755
+ yield {
756
+ type: 'tool-result',
757
+ name: webSearch.name,
758
+ result: output
759
+ };
760
+ history = directToolHistory(history, args, output);
761
+ }
762
+ let outcome = 'exhausted';
763
+ let said = '';
764
+ let mute = 0;
765
+ let narrated = false;
766
+ let cappedRounds = 0;
767
+ for (let round = 0; round < MAX_TOOL_ROUNDS; round++) {
768
+ if (signal?.aborted)
769
+ throw new AbortedError();
770
+ if (Date.now() >= runBudget.deadlineMs) {
771
+ outcome = 'time-capped';
772
+ break;
773
+ }
774
+ hlog('round start', {
775
+ round,
776
+ turns: history.length,
777
+ tools: sdkTools?.length ?? 0,
778
+ promptPrefix
779
+ });
780
+ const roundStarted = Date.now();
781
+ const recovered = yield* runRecoveredRound(sdk, {
782
+ modelId,
783
+ acquireRound,
784
+ history,
785
+ tools: sdkTools,
786
+ generationParams,
787
+ responseFormat,
788
+ toolDialect,
789
+ cacheKey: roundCacheKey,
790
+ signal
791
+ });
792
+ const final = recovered.final;
793
+ if (!recovered.cacheable)
794
+ roundCacheKey = undefined;
795
+ history = recovered.history;
796
+ collectStats(stats, final.stats);
797
+ hlog('round stats', { round, wallMs: Date.now() - roundStarted, ...(final.stats ?? {}) });
798
+ const markup = stripToolResponseBlocks(truncateAtControlToken(final.raw.fullText) || recovered.unproven || '');
799
+ let toolCalls = final.toolCalls?.length
800
+ ? final.toolCalls
801
+ : recoverMarkupToolCalls(markup, enabled);
802
+ if (!toolCalls.length && enabled.some((tool) => tool.name === SKILL_TOOL_NAME)) {
803
+ const rescued = recoverPrintedSkillLoad(markup, SKILL_TOOL_NAME);
804
+ const rescuedArgs = rescued[0]?.arguments;
805
+ const alreadyLoaded = rescuedArgs !== undefined &&
806
+ (loadedSkillFiles.get(unquoteArg(rescuedArgs.name))?.has(unquoteArg(rescuedArgs.file)) ??
807
+ false);
808
+ if (!alreadyLoaded)
809
+ toolCalls = rescued;
810
+ if (toolCalls.length)
811
+ hlog('recovered printed skill load', { round });
812
+ }
813
+ if (!toolCalls.length && enabled.some((tool) => tool.name === SKILL_TOOL_NAME)) {
814
+ toolCalls = recoverSkillNamedCall(markup, inContextSkills
815
+ .filter((skill) => !nudgedSkills.has(skill.name))
816
+ .map((skill) => skill.name), SKILL_TOOL_NAME);
817
+ for (const call of toolCalls)
818
+ nudgedSkills.add(unquoteArg(call.arguments.name));
819
+ if (toolCalls.length)
820
+ hlog('recovered skill-named call', { round });
821
+ }
822
+ if (!toolCalls.length) {
823
+ const replay = recovered.replay ? stripToolCallMarkup(recovered.replay) : '';
824
+ if (replay)
825
+ yield { type: 'content', text: replay };
826
+ const spoken = recovered.contentText.trim();
827
+ if (enabled.length && !narrated && !replay && NARRATED_INTENT.test(spoken)) {
828
+ hlog('round narrated a tool call instead of making it', { round });
829
+ narrated = true;
830
+ history = [
831
+ ...history,
832
+ { role: 'assistant', content: spoken },
833
+ { role: 'user', content: TOOL_CONTINUATION_NUDGE }
834
+ ];
835
+ continue;
836
+ }
837
+ if (replay || spoken) {
838
+ said = `${recovered.contentText}\n${replay}`;
839
+ outcome = 'answered';
840
+ break;
841
+ }
842
+ hlog('round produced no answer', { round, mute });
843
+ if (mute++ < MAX_MUTE_ROUNDS)
844
+ continue;
845
+ outcome = 'mute';
846
+ break;
847
+ }
848
+ mute = 0;
849
+ narrated = false;
850
+ const resolved = await resolveToolCalls(toolCalls, enabled, agent?.id ?? null, pipeline, inContextSkills.map((skill) => skill.name), signal);
851
+ if (signal?.aborted)
852
+ throw new AbortedError();
853
+ history = [
854
+ ...history,
855
+ {
856
+ role: 'assistant',
857
+ content: assistantToolTurn(recovered.contentText, resolved.map(({ call, args }) => ({ name: call.name, arguments: args })))
858
+ }
859
+ ];
860
+ let cappedCalls = 0;
861
+ runOutcomes.beginRound();
862
+ for (const { call, tool, args, rawCall, rejection, intent } of resolved) {
863
+ if (signal?.aborted)
864
+ throw new AbortedError();
865
+ const searchCapped = tool?.name === WEB_SEARCH_TOOL_NAME && webSearches >= MAX_WEB_SEARCHES_PER_TURN;
866
+ const callCtx = {
867
+ ...toolContext(turnImages, ctxSize),
868
+ skills: [...loadedSkills].filter((name) => !skillsSelected ||
869
+ (agent?.enabledSkills ?? []).includes(name) ||
870
+ name === mention?.name),
871
+ settings: toolConfigs?.[call.name],
872
+ toolOps: grantedOps,
873
+ fsRoots,
874
+ fsWriteRoots: writableRoots,
875
+ reportBackend: (use) => stats.backends.push(use)
876
+ };
877
+ const skillCall = call.name === SKILL_TOOL_NAME;
878
+ const effect = tool?.effect(args, callCtx) ?? (skillCall ? 'read' : undefined);
879
+ const resource = tool?.resource?.(args) ?? null;
880
+ const skillName = unquoteArg(args?.name ?? args?.skill_name ?? args?.skill);
881
+ const skillReloaded = tool?.name === SKILL_TOOL_NAME && !args?.file && loadedThisTurn.has(skillName);
882
+ const silent = searchCapped || skillReloaded;
883
+ const display = silent
884
+ ? undefined
885
+ : labelOf(call.name, args, skillCall ? skillEmoji(skillName) : skillIcon);
886
+ if (!silent) {
887
+ yield { type: 'tool-call', name: call.name, args, rawCall, effect, display };
888
+ }
889
+ const unreadyState = skillCall ? unreadySkillState(skillName, skillCatalog) : null;
890
+ const skillBlocked = skillCall && !unreadyState && (!tool || !skillIsActive(skillName, activation));
891
+ let activity = null;
892
+ const blockedReason = blockedSkillMessage(skillName, skillCatalog, activeSkills.length > 0);
893
+ const unreadyReason = `skill "${skillName}" is ${unreadyState ?? 'unavailable'} and cannot be used yet. ` +
894
+ `Tell the user to open it in Skills and finish its setup; do not retry.`;
895
+ let execution;
896
+ if (skillReloaded) {
897
+ execution = terminalCall({
898
+ name: skillName,
899
+ content: `${skillName} is already loaded. Follow the instructions you were given and do not load it again.`
900
+ }, { kind: 'guidance', message: `${skillName} is already loaded.` }, { executed: false });
901
+ }
902
+ else if (skillBlocked) {
903
+ execution = blockedResult({ error: blockedReason }, blockedReason);
904
+ }
905
+ else if (unreadyState) {
906
+ execution = blockedResult({ error: unreadyReason }, unreadyReason);
907
+ }
908
+ else if (searchCapped) {
909
+ execution = terminalCall({ content: WEB_SEARCH_LIMIT_MESSAGE }, { kind: 'success' }, { executed: false });
910
+ }
911
+ else if (rejection) {
912
+ execution = terminalCall(rejection, { kind: 'guidance', message: rejection.error }, {
913
+ executed: false
914
+ });
915
+ }
916
+ else if (tool) {
917
+ execution = await executeCall(tool, args, callCtx, {
918
+ approve,
919
+ signal,
920
+ denied,
921
+ sources,
922
+ effect,
923
+ skipApprovals: agent?.approvalMode === 'skip-all',
924
+ intent,
925
+ display,
926
+ onToolActivity: (event) => {
927
+ activity = event;
928
+ }
929
+ });
930
+ }
931
+ else {
932
+ execution = blockedResult({ error: `unknown tool: ${call.name}` }, `unknown tool: ${call.name}`);
933
+ }
934
+ const settled = await settleToolCall(pipeline, execution, {
935
+ agentId,
936
+ tool,
937
+ name: call.name,
938
+ args,
939
+ effect,
940
+ resource
941
+ });
942
+ const output = settled.result;
943
+ const executionOutcome = settled.outcome;
944
+ runOutcomes.record(output, executionOutcome);
945
+ if (searchCapped) {
946
+ cappedCalls++;
947
+ hlog('web_search capped', { searches: webSearches });
948
+ }
949
+ else if (tool?.name === WEB_SEARCH_TOOL_NAME && !rejection)
950
+ webSearches++;
951
+ if (call.name === SKILL_TOOL_NAME &&
952
+ output &&
953
+ typeof output === 'object' &&
954
+ 'content' in output) {
955
+ loadedSkills.add(skillName);
956
+ if ('file' in output && typeof output.file === 'string') {
957
+ const files = loadedSkillFiles.get(skillName) ?? new Set();
958
+ files.add(output.file);
959
+ loadedSkillFiles.set(skillName, files);
960
+ }
961
+ else {
962
+ loadedThisTurn.add(skillName);
963
+ }
964
+ skillIcon = skillEmoji(skillName) ?? skillIcon;
965
+ }
966
+ if (!activity &&
967
+ !silent &&
968
+ (skillBlocked || Boolean(unreadyState) || Boolean(rejection) || !tool)) {
969
+ activity = {
970
+ type: 'tool-activity',
971
+ name: call.name,
972
+ args,
973
+ resource,
974
+ effect: effect ?? 'write',
975
+ decision: 'blocked'
976
+ };
977
+ }
978
+ if (activity)
979
+ yield activity;
980
+ if (!silent) {
981
+ yield {
982
+ type: 'tool-result',
983
+ name: call.name,
984
+ result: output
985
+ };
986
+ }
987
+ const isCompiledOperation = tool?.compiled === true;
988
+ const isMutation = effect === 'write' &&
989
+ ((tool?.toolset === 'mcp-call' && !isMetadataMethod(args.method)) ||
990
+ (isCompiledOperation && tool?.toolset === 'http-request'));
991
+ if (isMutation && executionOutcome.kind === 'success') {
992
+ runOutcomes.confirmWrite(output);
993
+ }
994
+ const turn = toolResultTurn(call.name, call.id, output);
995
+ sources.push({
996
+ origin: call.name === SKILL_TOOL_NAME ? 'skill' : 'tool-result',
997
+ text: turn
998
+ });
999
+ history.push({ role: 'tool', content: turn });
1000
+ }
1001
+ runOutcomes.finishRound();
1002
+ history.push({ role: 'user', content: TOOL_CONTINUATION_NUDGE });
1003
+ if (cappedCalls === resolved.length) {
1004
+ if (cappedRounds++ >= MAX_CAPPED_ROUNDS) {
1005
+ outcome = 'search-capped';
1006
+ break;
1007
+ }
1008
+ }
1009
+ else {
1010
+ cappedRounds = 0;
1011
+ }
1012
+ }
1013
+ if (outcome === 'answered') {
1014
+ yield* reportUnnamedWrites(said, landed);
1015
+ const answered = metricsEvent(stats, runUsage());
1016
+ runOutcome = 'done';
1017
+ if (answered)
1018
+ yield answered;
1019
+ return;
1020
+ }
1021
+ if (signal?.aborted)
1022
+ throw new AbortedError();
1023
+ const recovered = yield* runRecoveredRound(sdk, {
1024
+ modelId,
1025
+ acquireRound,
1026
+ history,
1027
+ tools: undefined,
1028
+ generationParams,
1029
+ cacheKey: roundCacheKey,
1030
+ signal
1031
+ });
1032
+ collectStats(stats, recovered.final.stats);
1033
+ const answer = recovered.replay ? stripToolCallMarkup(recovered.replay) : '';
1034
+ if (answer)
1035
+ yield { type: 'content', text: answer };
1036
+ said = `${recovered.contentText}\n${answer}`;
1037
+ if (!said.trim()) {
1038
+ hlog('degenerate wrap-up', { outcome });
1039
+ yield {
1040
+ type: 'content',
1041
+ text: degenerateAnswer(outcome, history, runOutcomes.facts())
1042
+ };
1043
+ }
1044
+ else {
1045
+ yield* reportUnnamedWrites(said, landed);
1046
+ }
1047
+ const metrics = metricsEvent(stats, runUsage());
1048
+ runOutcome = 'done';
1049
+ if (metrics)
1050
+ yield metrics;
1051
+ }
1052
+ catch (err) {
1053
+ const written = writeReport(landed);
1054
+ if (written)
1055
+ yield { type: 'content', text: written };
1056
+ if (err instanceof AbortedError) {
1057
+ runOutcome = 'aborted';
1058
+ yield { type: 'aborted' };
1059
+ return;
1060
+ }
1061
+ runOutcome = 'error';
1062
+ runError = err;
1063
+ throw err;
1064
+ }
1065
+ finally {
1066
+ await pipeline.onRunEnd({
1067
+ agentId: agent?.id ?? null,
1068
+ stats: {
1069
+ totalTokens: stats.tokens,
1070
+ durationMs: Math.round(stats.durationMs),
1071
+ timeToFirstToken: stats.ttft
1072
+ },
1073
+ outcome: runOutcome,
1074
+ error: runError
1075
+ });
1076
+ }
1077
+ }