@xandout/libra-harness 0.1.33 → 0.1.90

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 (453) hide show
  1. package/README.md +30 -30
  2. package/dist/agent.d.ts +8 -0
  3. package/dist/agent.d.ts.map +1 -1
  4. package/dist/agent.js +205 -193
  5. package/dist/agent.js.map +1 -1
  6. package/dist/ai-sdk-model.d.ts.map +1 -1
  7. package/dist/ai-sdk-model.js +91 -78
  8. package/dist/ai-sdk-model.js.map +1 -1
  9. package/dist/context.d.ts +2 -0
  10. package/dist/context.d.ts.map +1 -1
  11. package/dist/{extras/extensions → extensions}/auto-steer/extension.d.ts +1 -1
  12. package/dist/extensions/auto-steer/extension.d.ts.map +1 -0
  13. package/dist/extensions/auto-steer/extension.js.map +1 -0
  14. package/dist/extensions/auto-steer/index.d.ts.map +1 -0
  15. package/dist/extensions/auto-steer/index.js.map +1 -0
  16. package/dist/extensions/code-tools/extension.d.ts +15 -0
  17. package/dist/extensions/code-tools/extension.d.ts.map +1 -0
  18. package/dist/extensions/code-tools/extension.js +73 -0
  19. package/dist/extensions/code-tools/extension.js.map +1 -0
  20. package/dist/extensions/code-tools/extension.test.d.ts.map +1 -0
  21. package/dist/extensions/code-tools/extension.test.js +504 -0
  22. package/dist/extensions/code-tools/extension.test.js.map +1 -0
  23. package/dist/extensions/code-tools/index.d.ts.map +1 -0
  24. package/dist/extensions/code-tools/index.js.map +1 -0
  25. package/dist/{extras/extensions → extensions}/code-tools/tools/code-search.d.ts +2 -2
  26. package/dist/extensions/code-tools/tools/code-search.d.ts.map +1 -0
  27. package/dist/{extras/extensions → extensions}/code-tools/tools/code-search.js +1 -1
  28. package/dist/extensions/code-tools/tools/code-search.js.map +1 -0
  29. package/dist/extensions/code-tools/tools/find.d.ts.map +1 -0
  30. package/dist/extensions/code-tools/tools/find.js +83 -0
  31. package/dist/extensions/code-tools/tools/find.js.map +1 -0
  32. package/dist/extensions/code-tools/tools/grep.d.ts.map +1 -0
  33. package/dist/extensions/code-tools/tools/grep.js +90 -0
  34. package/dist/extensions/code-tools/tools/grep.js.map +1 -0
  35. package/dist/extensions/code-tools/tools/read.d.ts.map +1 -0
  36. package/dist/{extras/extensions → extensions}/code-tools/tools/read.js +17 -25
  37. package/dist/extensions/code-tools/tools/read.js.map +1 -0
  38. package/dist/{extras/extensions → extensions}/code-tools/tools/shared.d.ts +5 -1
  39. package/dist/extensions/code-tools/tools/shared.d.ts.map +1 -0
  40. package/dist/{extras/extensions → extensions}/code-tools/tools/shared.js +68 -0
  41. package/dist/extensions/code-tools/tools/shared.js.map +1 -0
  42. package/dist/extensions/code-tools/tools/shell.d.ts +39 -0
  43. package/dist/extensions/code-tools/tools/shell.d.ts.map +1 -0
  44. package/dist/extensions/code-tools/tools/shell.js +441 -0
  45. package/dist/extensions/code-tools/tools/shell.js.map +1 -0
  46. package/dist/{extras/extensions → extensions}/code-tools/tools/todo.d.ts +0 -3
  47. package/dist/extensions/code-tools/tools/todo.d.ts.map +1 -0
  48. package/dist/{extras/extensions → extensions}/code-tools/tools/todo.js +0 -8
  49. package/dist/extensions/code-tools/tools/todo.js.map +1 -0
  50. package/dist/extensions/code-tools/tools/view-image.d.ts +10 -0
  51. package/dist/extensions/code-tools/tools/view-image.d.ts.map +1 -0
  52. package/dist/extensions/code-tools/tools/view-image.js +87 -0
  53. package/dist/extensions/code-tools/tools/view-image.js.map +1 -0
  54. package/dist/extensions/code-tools/tools/write.d.ts.map +1 -0
  55. package/dist/{extras/extensions → extensions}/code-tools/tools/write.js +47 -37
  56. package/dist/extensions/code-tools/tools/write.js.map +1 -0
  57. package/dist/{extras/extensions → extensions}/disk-session/extension.d.ts +45 -2
  58. package/dist/extensions/disk-session/extension.d.ts.map +1 -0
  59. package/dist/extensions/disk-session/extension.js +818 -0
  60. package/dist/extensions/disk-session/extension.js.map +1 -0
  61. package/dist/extensions/disk-session/extension.test.d.ts.map +1 -0
  62. package/dist/{extras/extensions → extensions}/disk-session/extension.test.js +445 -16
  63. package/dist/extensions/disk-session/extension.test.js.map +1 -0
  64. package/dist/extensions/disk-session/index.d.ts +3 -0
  65. package/dist/extensions/disk-session/index.d.ts.map +1 -0
  66. package/dist/extensions/disk-session/index.js +2 -0
  67. package/dist/extensions/disk-session/index.js.map +1 -0
  68. package/dist/{extras/extensions → extensions}/emoji/extension.d.ts +1 -1
  69. package/dist/extensions/emoji/extension.d.ts.map +1 -0
  70. package/dist/extensions/emoji/extension.js.map +1 -0
  71. package/dist/extensions/emoji/index.d.ts.map +1 -0
  72. package/dist/extensions/emoji/index.js.map +1 -0
  73. package/dist/extensions/filesystem/extension.d.ts.map +1 -0
  74. package/dist/extensions/filesystem/extension.js.map +1 -0
  75. package/dist/extensions/filesystem/extension.test.d.ts.map +1 -0
  76. package/dist/extensions/filesystem/extension.test.js.map +1 -0
  77. package/dist/extensions/filesystem/index.d.ts.map +1 -0
  78. package/dist/extensions/filesystem/index.js.map +1 -0
  79. package/dist/extensions/index.d.ts +3 -0
  80. package/dist/extensions/index.d.ts.map +1 -0
  81. package/dist/extensions/index.js +2 -0
  82. package/dist/extensions/index.js.map +1 -0
  83. package/dist/{extras/extensions → extensions}/keyword-extractor/extension.d.ts +1 -1
  84. package/dist/extensions/keyword-extractor/extension.d.ts.map +1 -0
  85. package/dist/{extras/extensions → extensions}/keyword-extractor/extension.js +1 -1
  86. package/dist/extensions/keyword-extractor/extension.js.map +1 -0
  87. package/dist/extensions/keyword-extractor/extension.test.d.ts.map +1 -0
  88. package/dist/extensions/keyword-extractor/extension.test.js.map +1 -0
  89. package/dist/extensions/keyword-extractor/index.d.ts.map +1 -0
  90. package/dist/extensions/keyword-extractor/index.js.map +1 -0
  91. package/dist/extensions/keyword-extractor/nlp.d.ts.map +1 -0
  92. package/dist/extensions/keyword-extractor/nlp.js.map +1 -0
  93. package/dist/extensions/keyword-extractor/nlp.test.d.ts.map +1 -0
  94. package/dist/extensions/keyword-extractor/nlp.test.js.map +1 -0
  95. package/dist/{extras/extension-loader.d.ts → extensions/loader.d.ts} +1 -1
  96. package/dist/extensions/loader.d.ts.map +1 -0
  97. package/dist/{extras/extension-loader.js → extensions/loader.js} +2 -2
  98. package/dist/extensions/loader.js.map +1 -0
  99. package/dist/{extras/extensions → extensions}/logger/extension.d.ts +1 -1
  100. package/dist/extensions/logger/extension.d.ts.map +1 -0
  101. package/dist/{extras/extensions → extensions}/logger/extension.js +1 -1
  102. package/dist/extensions/logger/extension.js.map +1 -0
  103. package/dist/extensions/logger/index.d.ts.map +1 -0
  104. package/dist/extensions/logger/index.js.map +1 -0
  105. package/dist/{extras/extensions → extensions}/mcp/extension.d.ts +1 -1
  106. package/dist/extensions/mcp/extension.d.ts.map +1 -0
  107. package/dist/extensions/mcp/extension.js.map +1 -0
  108. package/dist/extensions/mcp/extension.test.d.ts.map +1 -0
  109. package/dist/{extras/extensions → extensions}/mcp/extension.test.js +1 -1
  110. package/dist/extensions/mcp/extension.test.js.map +1 -0
  111. package/dist/extensions/mcp/index.d.ts.map +1 -0
  112. package/dist/extensions/mcp/index.js.map +1 -0
  113. package/dist/{extras/extensions → extensions}/mem-session/extension.d.ts +2 -2
  114. package/dist/extensions/mem-session/extension.d.ts.map +1 -0
  115. package/dist/extensions/mem-session/extension.js.map +1 -0
  116. package/dist/extensions/mem-session/index.d.ts.map +1 -0
  117. package/dist/extensions/mem-session/index.js.map +1 -0
  118. package/dist/{extras/extensions → extensions}/memory/extension.d.ts +1 -1
  119. package/dist/extensions/memory/extension.d.ts.map +1 -0
  120. package/dist/{extras/extensions → extensions}/memory/extension.js +1 -1
  121. package/dist/extensions/memory/extension.js.map +1 -0
  122. package/dist/extensions/memory/index.d.ts +4 -0
  123. package/dist/extensions/memory/index.d.ts.map +1 -0
  124. package/dist/extensions/memory/index.js.map +1 -0
  125. package/dist/{extras/extensions → extensions}/memory/llm-extractor.d.ts +1 -1
  126. package/dist/extensions/memory/llm-extractor.d.ts.map +1 -0
  127. package/dist/{extras/extensions → extensions}/memory/llm-extractor.js +1 -1
  128. package/dist/extensions/memory/llm-extractor.js.map +1 -0
  129. package/dist/{extras/extensions → extensions}/memory/types.d.ts +2 -2
  130. package/dist/extensions/memory/types.d.ts.map +1 -0
  131. package/dist/extensions/memory/types.js.map +1 -0
  132. package/dist/{extras/extensions → extensions}/otel/extension.d.ts +1 -1
  133. package/dist/extensions/otel/extension.d.ts.map +1 -0
  134. package/dist/{extras/extensions → extensions}/otel/extension.js +1 -1
  135. package/dist/extensions/otel/extension.js.map +1 -0
  136. package/dist/extensions/otel/extension.test.d.ts.map +1 -0
  137. package/dist/{extras/extensions → extensions}/otel/extension.test.js +1 -1
  138. package/dist/extensions/otel/extension.test.js.map +1 -0
  139. package/dist/extensions/otel/index.d.ts.map +1 -0
  140. package/dist/extensions/otel/index.js.map +1 -0
  141. package/dist/extensions/otel/jsonl-span-exporter.d.ts.map +1 -0
  142. package/dist/extensions/otel/jsonl-span-exporter.js.map +1 -0
  143. package/dist/{extras/extensions → extensions}/scripts/extension.d.ts +1 -1
  144. package/dist/extensions/scripts/extension.d.ts.map +1 -0
  145. package/dist/extensions/scripts/extension.js.map +1 -0
  146. package/dist/extensions/scripts/extension.test.d.ts.map +1 -0
  147. package/dist/extensions/scripts/extension.test.js.map +1 -0
  148. package/dist/extensions/scripts/index.d.ts.map +1 -0
  149. package/dist/extensions/scripts/index.js.map +1 -0
  150. package/dist/{extras/extensions → extensions}/skills/extension.d.ts +1 -1
  151. package/dist/extensions/skills/extension.d.ts.map +1 -0
  152. package/dist/extensions/skills/extension.js.map +1 -0
  153. package/dist/extensions/skills/extension.test.d.ts.map +1 -0
  154. package/dist/{extras/extensions → extensions}/skills/extension.test.js +1 -1
  155. package/dist/extensions/skills/extension.test.js.map +1 -0
  156. package/dist/extensions/skills/index.d.ts.map +1 -0
  157. package/dist/extensions/skills/index.js.map +1 -0
  158. package/dist/{extras/extensions → extensions}/streaming/extension.d.ts +1 -1
  159. package/dist/extensions/streaming/extension.d.ts.map +1 -0
  160. package/dist/extensions/streaming/extension.js.map +1 -0
  161. package/dist/extensions/streaming/index.d.ts.map +1 -0
  162. package/dist/extensions/streaming/index.js.map +1 -0
  163. package/dist/{extras/extensions → extensions}/structured-output/extension.d.ts +1 -1
  164. package/dist/extensions/structured-output/extension.d.ts.map +1 -0
  165. package/dist/extensions/structured-output/extension.js.map +1 -0
  166. package/dist/extensions/structured-output/index.d.ts.map +1 -0
  167. package/dist/extensions/structured-output/index.js.map +1 -0
  168. package/dist/{extras/extensions → extensions}/timestamp/extension.d.ts +1 -1
  169. package/dist/extensions/timestamp/extension.d.ts.map +1 -0
  170. package/dist/extensions/timestamp/extension.js.map +1 -0
  171. package/dist/extensions/timestamp/index.d.ts.map +1 -0
  172. package/dist/extensions/timestamp/index.js.map +1 -0
  173. package/dist/{extras/extensions → extensions}/token-stats/extension.d.ts +1 -1
  174. package/dist/extensions/token-stats/extension.d.ts.map +1 -0
  175. package/dist/extensions/token-stats/extension.js.map +1 -0
  176. package/dist/extensions/token-stats/extension.test.d.ts.map +1 -0
  177. package/dist/{extras/extensions → extensions}/token-stats/extension.test.js +1 -1
  178. package/dist/extensions/token-stats/extension.test.js.map +1 -0
  179. package/dist/extensions/token-stats/index.d.ts.map +1 -0
  180. package/dist/extensions/token-stats/index.js.map +1 -0
  181. package/dist/{extras/extensions → extensions}/tool-buffer/extension.d.ts +1 -1
  182. package/dist/extensions/tool-buffer/extension.d.ts.map +1 -0
  183. package/dist/extensions/tool-buffer/extension.js.map +1 -0
  184. package/dist/extensions/tool-buffer/extension.test.d.ts.map +1 -0
  185. package/dist/{extras/extensions → extensions}/tool-buffer/extension.test.js +1 -1
  186. package/dist/extensions/tool-buffer/extension.test.js.map +1 -0
  187. package/dist/extensions/tool-buffer/index.d.ts.map +1 -0
  188. package/dist/extensions/tool-buffer/index.js.map +1 -0
  189. package/dist/{extras/extensions → extensions}/weather-tool/extension.d.ts +1 -1
  190. package/dist/extensions/weather-tool/extension.d.ts.map +1 -0
  191. package/dist/extensions/weather-tool/extension.js.map +1 -0
  192. package/dist/extensions/weather-tool/index.d.ts.map +1 -0
  193. package/dist/extensions/weather-tool/index.js.map +1 -0
  194. package/dist/handle.d.ts +4 -0
  195. package/dist/handle.d.ts.map +1 -1
  196. package/dist/{extras/models → models}/ai-sdk-resolver.d.ts +1 -1
  197. package/dist/models/ai-sdk-resolver.d.ts.map +1 -0
  198. package/dist/{extras/models → models}/ai-sdk-resolver.js +1 -1
  199. package/dist/models/ai-sdk-resolver.js.map +1 -0
  200. package/dist/models/index.d.ts.map +1 -0
  201. package/dist/models/index.js.map +1 -0
  202. package/dist/{extras/models → models}/routing-model.d.ts +1 -1
  203. package/dist/models/routing-model.d.ts.map +1 -0
  204. package/dist/{extras/models → models}/routing-model.js +1 -1
  205. package/dist/models/routing-model.js.map +1 -0
  206. package/dist/openai-provider/index.d.ts.map +1 -0
  207. package/dist/openai-provider/index.js.map +1 -0
  208. package/dist/{extras/openai-provider → openai-provider}/server.d.ts +1 -1
  209. package/dist/openai-provider/server.d.ts.map +1 -0
  210. package/dist/openai-provider/server.js.map +1 -0
  211. package/package.json +108 -83
  212. package/dist/extras/extension-loader.d.ts.map +0 -1
  213. package/dist/extras/extension-loader.js.map +0 -1
  214. package/dist/extras/extensions/auto-steer/extension.d.ts.map +0 -1
  215. package/dist/extras/extensions/auto-steer/extension.js.map +0 -1
  216. package/dist/extras/extensions/auto-steer/index.d.ts.map +0 -1
  217. package/dist/extras/extensions/auto-steer/index.js.map +0 -1
  218. package/dist/extras/extensions/code-tools/extension.d.ts +0 -83
  219. package/dist/extras/extensions/code-tools/extension.d.ts.map +0 -1
  220. package/dist/extras/extensions/code-tools/extension.js +0 -93
  221. package/dist/extras/extensions/code-tools/extension.js.map +0 -1
  222. package/dist/extras/extensions/code-tools/extension.test.d.ts.map +0 -1
  223. package/dist/extras/extensions/code-tools/extension.test.js +0 -656
  224. package/dist/extras/extensions/code-tools/extension.test.js.map +0 -1
  225. package/dist/extras/extensions/code-tools/index.d.ts.map +0 -1
  226. package/dist/extras/extensions/code-tools/index.js.map +0 -1
  227. package/dist/extras/extensions/code-tools/tools/code-search.d.ts.map +0 -1
  228. package/dist/extras/extensions/code-tools/tools/code-search.js.map +0 -1
  229. package/dist/extras/extensions/code-tools/tools/find.d.ts.map +0 -1
  230. package/dist/extras/extensions/code-tools/tools/find.js +0 -161
  231. package/dist/extras/extensions/code-tools/tools/find.js.map +0 -1
  232. package/dist/extras/extensions/code-tools/tools/grep.d.ts.map +0 -1
  233. package/dist/extras/extensions/code-tools/tools/grep.js +0 -307
  234. package/dist/extras/extensions/code-tools/tools/grep.js.map +0 -1
  235. package/dist/extras/extensions/code-tools/tools/read.d.ts.map +0 -1
  236. package/dist/extras/extensions/code-tools/tools/read.js.map +0 -1
  237. package/dist/extras/extensions/code-tools/tools/shared.d.ts.map +0 -1
  238. package/dist/extras/extensions/code-tools/tools/shared.js.map +0 -1
  239. package/dist/extras/extensions/code-tools/tools/shell.d.ts +0 -49
  240. package/dist/extras/extensions/code-tools/tools/shell.d.ts.map +0 -1
  241. package/dist/extras/extensions/code-tools/tools/shell.js +0 -623
  242. package/dist/extras/extensions/code-tools/tools/shell.js.map +0 -1
  243. package/dist/extras/extensions/code-tools/tools/todo.d.ts.map +0 -1
  244. package/dist/extras/extensions/code-tools/tools/todo.js.map +0 -1
  245. package/dist/extras/extensions/code-tools/tools/write.d.ts.map +0 -1
  246. package/dist/extras/extensions/code-tools/tools/write.js.map +0 -1
  247. package/dist/extras/extensions/disk-session/extension.d.ts.map +0 -1
  248. package/dist/extras/extensions/disk-session/extension.js +0 -640
  249. package/dist/extras/extensions/disk-session/extension.js.map +0 -1
  250. package/dist/extras/extensions/disk-session/extension.test.d.ts.map +0 -1
  251. package/dist/extras/extensions/disk-session/extension.test.js.map +0 -1
  252. package/dist/extras/extensions/disk-session/index.d.ts +0 -3
  253. package/dist/extras/extensions/disk-session/index.d.ts.map +0 -1
  254. package/dist/extras/extensions/disk-session/index.js +0 -2
  255. package/dist/extras/extensions/disk-session/index.js.map +0 -1
  256. package/dist/extras/extensions/emoji/extension.d.ts.map +0 -1
  257. package/dist/extras/extensions/emoji/extension.js.map +0 -1
  258. package/dist/extras/extensions/emoji/index.d.ts.map +0 -1
  259. package/dist/extras/extensions/emoji/index.js.map +0 -1
  260. package/dist/extras/extensions/filesystem/extension.d.ts.map +0 -1
  261. package/dist/extras/extensions/filesystem/extension.js.map +0 -1
  262. package/dist/extras/extensions/filesystem/extension.test.d.ts.map +0 -1
  263. package/dist/extras/extensions/filesystem/extension.test.js.map +0 -1
  264. package/dist/extras/extensions/filesystem/index.d.ts.map +0 -1
  265. package/dist/extras/extensions/filesystem/index.js.map +0 -1
  266. package/dist/extras/extensions/keyword-extractor/extension.d.ts.map +0 -1
  267. package/dist/extras/extensions/keyword-extractor/extension.js.map +0 -1
  268. package/dist/extras/extensions/keyword-extractor/extension.test.d.ts.map +0 -1
  269. package/dist/extras/extensions/keyword-extractor/extension.test.js.map +0 -1
  270. package/dist/extras/extensions/keyword-extractor/index.d.ts.map +0 -1
  271. package/dist/extras/extensions/keyword-extractor/index.js.map +0 -1
  272. package/dist/extras/extensions/keyword-extractor/nlp.d.ts.map +0 -1
  273. package/dist/extras/extensions/keyword-extractor/nlp.js.map +0 -1
  274. package/dist/extras/extensions/keyword-extractor/nlp.test.d.ts.map +0 -1
  275. package/dist/extras/extensions/keyword-extractor/nlp.test.js.map +0 -1
  276. package/dist/extras/extensions/logger/extension.d.ts.map +0 -1
  277. package/dist/extras/extensions/logger/extension.js.map +0 -1
  278. package/dist/extras/extensions/logger/index.d.ts.map +0 -1
  279. package/dist/extras/extensions/logger/index.js.map +0 -1
  280. package/dist/extras/extensions/mcp/extension.d.ts.map +0 -1
  281. package/dist/extras/extensions/mcp/extension.js.map +0 -1
  282. package/dist/extras/extensions/mcp/extension.test.d.ts.map +0 -1
  283. package/dist/extras/extensions/mcp/extension.test.js.map +0 -1
  284. package/dist/extras/extensions/mcp/index.d.ts.map +0 -1
  285. package/dist/extras/extensions/mcp/index.js.map +0 -1
  286. package/dist/extras/extensions/mem-session/extension.d.ts.map +0 -1
  287. package/dist/extras/extensions/mem-session/extension.js.map +0 -1
  288. package/dist/extras/extensions/mem-session/index.d.ts.map +0 -1
  289. package/dist/extras/extensions/mem-session/index.js.map +0 -1
  290. package/dist/extras/extensions/memory/extension.d.ts.map +0 -1
  291. package/dist/extras/extensions/memory/extension.js.map +0 -1
  292. package/dist/extras/extensions/memory/index.d.ts +0 -5
  293. package/dist/extras/extensions/memory/index.d.ts.map +0 -1
  294. package/dist/extras/extensions/memory/index.js.map +0 -1
  295. package/dist/extras/extensions/memory/llm-extractor.d.ts.map +0 -1
  296. package/dist/extras/extensions/memory/llm-extractor.js.map +0 -1
  297. package/dist/extras/extensions/memory/types.d.ts.map +0 -1
  298. package/dist/extras/extensions/memory/types.js.map +0 -1
  299. package/dist/extras/extensions/otel/extension.d.ts.map +0 -1
  300. package/dist/extras/extensions/otel/extension.js.map +0 -1
  301. package/dist/extras/extensions/otel/extension.test.d.ts.map +0 -1
  302. package/dist/extras/extensions/otel/extension.test.js.map +0 -1
  303. package/dist/extras/extensions/otel/index.d.ts.map +0 -1
  304. package/dist/extras/extensions/otel/index.js.map +0 -1
  305. package/dist/extras/extensions/otel/jsonl-span-exporter.d.ts.map +0 -1
  306. package/dist/extras/extensions/otel/jsonl-span-exporter.js.map +0 -1
  307. package/dist/extras/extensions/scripts/extension.d.ts.map +0 -1
  308. package/dist/extras/extensions/scripts/extension.js.map +0 -1
  309. package/dist/extras/extensions/scripts/extension.test.d.ts.map +0 -1
  310. package/dist/extras/extensions/scripts/extension.test.js.map +0 -1
  311. package/dist/extras/extensions/scripts/index.d.ts.map +0 -1
  312. package/dist/extras/extensions/scripts/index.js.map +0 -1
  313. package/dist/extras/extensions/skills/extension.d.ts.map +0 -1
  314. package/dist/extras/extensions/skills/extension.js.map +0 -1
  315. package/dist/extras/extensions/skills/extension.test.d.ts.map +0 -1
  316. package/dist/extras/extensions/skills/extension.test.js.map +0 -1
  317. package/dist/extras/extensions/skills/index.d.ts.map +0 -1
  318. package/dist/extras/extensions/skills/index.js.map +0 -1
  319. package/dist/extras/extensions/streaming/extension.d.ts.map +0 -1
  320. package/dist/extras/extensions/streaming/extension.js.map +0 -1
  321. package/dist/extras/extensions/streaming/index.d.ts.map +0 -1
  322. package/dist/extras/extensions/streaming/index.js.map +0 -1
  323. package/dist/extras/extensions/structured-output/extension.d.ts.map +0 -1
  324. package/dist/extras/extensions/structured-output/extension.js.map +0 -1
  325. package/dist/extras/extensions/structured-output/index.d.ts.map +0 -1
  326. package/dist/extras/extensions/structured-output/index.js.map +0 -1
  327. package/dist/extras/extensions/timestamp/extension.d.ts.map +0 -1
  328. package/dist/extras/extensions/timestamp/extension.js.map +0 -1
  329. package/dist/extras/extensions/timestamp/index.d.ts.map +0 -1
  330. package/dist/extras/extensions/timestamp/index.js.map +0 -1
  331. package/dist/extras/extensions/token-stats/extension.d.ts.map +0 -1
  332. package/dist/extras/extensions/token-stats/extension.js.map +0 -1
  333. package/dist/extras/extensions/token-stats/extension.test.d.ts.map +0 -1
  334. package/dist/extras/extensions/token-stats/extension.test.js.map +0 -1
  335. package/dist/extras/extensions/token-stats/index.d.ts.map +0 -1
  336. package/dist/extras/extensions/token-stats/index.js.map +0 -1
  337. package/dist/extras/extensions/tool-buffer/extension.d.ts.map +0 -1
  338. package/dist/extras/extensions/tool-buffer/extension.js.map +0 -1
  339. package/dist/extras/extensions/tool-buffer/extension.test.d.ts.map +0 -1
  340. package/dist/extras/extensions/tool-buffer/extension.test.js.map +0 -1
  341. package/dist/extras/extensions/tool-buffer/index.d.ts.map +0 -1
  342. package/dist/extras/extensions/tool-buffer/index.js.map +0 -1
  343. package/dist/extras/extensions/weather-tool/extension.d.ts.map +0 -1
  344. package/dist/extras/extensions/weather-tool/extension.js.map +0 -1
  345. package/dist/extras/extensions/weather-tool/index.d.ts.map +0 -1
  346. package/dist/extras/extensions/weather-tool/index.js.map +0 -1
  347. package/dist/extras/models/ai-sdk-resolver.d.ts.map +0 -1
  348. package/dist/extras/models/ai-sdk-resolver.js.map +0 -1
  349. package/dist/extras/models/index.d.ts.map +0 -1
  350. package/dist/extras/models/index.js.map +0 -1
  351. package/dist/extras/models/routing-model.d.ts.map +0 -1
  352. package/dist/extras/models/routing-model.js.map +0 -1
  353. package/dist/extras/openai-provider/index.d.ts.map +0 -1
  354. package/dist/extras/openai-provider/index.js.map +0 -1
  355. package/dist/extras/openai-provider/server.d.ts.map +0 -1
  356. package/dist/extras/openai-provider/server.js.map +0 -1
  357. /package/dist/{extras/extensions → extensions}/auto-steer/extension.js +0 -0
  358. /package/dist/{extras/extensions → extensions}/auto-steer/extension.json +0 -0
  359. /package/dist/{extras/extensions → extensions}/auto-steer/index.d.ts +0 -0
  360. /package/dist/{extras/extensions → extensions}/auto-steer/index.js +0 -0
  361. /package/dist/{extras/extensions → extensions}/code-tools/extension.json +0 -0
  362. /package/dist/{extras/extensions → extensions}/code-tools/extension.test.d.ts +0 -0
  363. /package/dist/{extras/extensions → extensions}/code-tools/index.d.ts +0 -0
  364. /package/dist/{extras/extensions → extensions}/code-tools/index.js +0 -0
  365. /package/dist/{extras/extensions → extensions}/code-tools/tools/find.d.ts +0 -0
  366. /package/dist/{extras/extensions → extensions}/code-tools/tools/grep.d.ts +0 -0
  367. /package/dist/{extras/extensions → extensions}/code-tools/tools/read.d.ts +0 -0
  368. /package/dist/{extras/extensions → extensions}/code-tools/tools/write.d.ts +0 -0
  369. /package/dist/{extras/extensions → extensions}/disk-session/extension.json +0 -0
  370. /package/dist/{extras/extensions → extensions}/disk-session/extension.test.d.ts +0 -0
  371. /package/dist/{extras/extensions → extensions}/emoji/extension.js +0 -0
  372. /package/dist/{extras/extensions → extensions}/emoji/extension.json +0 -0
  373. /package/dist/{extras/extensions → extensions}/emoji/index.d.ts +0 -0
  374. /package/dist/{extras/extensions → extensions}/emoji/index.js +0 -0
  375. /package/dist/{extras/extensions → extensions}/filesystem/extension.d.ts +0 -0
  376. /package/dist/{extras/extensions → extensions}/filesystem/extension.js +0 -0
  377. /package/dist/{extras/extensions → extensions}/filesystem/extension.json +0 -0
  378. /package/dist/{extras/extensions → extensions}/filesystem/extension.test.d.ts +0 -0
  379. /package/dist/{extras/extensions → extensions}/filesystem/extension.test.js +0 -0
  380. /package/dist/{extras/extensions → extensions}/filesystem/index.d.ts +0 -0
  381. /package/dist/{extras/extensions → extensions}/filesystem/index.js +0 -0
  382. /package/dist/{extras/extensions → extensions}/keyword-extractor/extension.json +0 -0
  383. /package/dist/{extras/extensions → extensions}/keyword-extractor/extension.test.d.ts +0 -0
  384. /package/dist/{extras/extensions → extensions}/keyword-extractor/extension.test.js +0 -0
  385. /package/dist/{extras/extensions → extensions}/keyword-extractor/index.d.ts +0 -0
  386. /package/dist/{extras/extensions → extensions}/keyword-extractor/index.js +0 -0
  387. /package/dist/{extras/extensions → extensions}/keyword-extractor/nlp.d.ts +0 -0
  388. /package/dist/{extras/extensions → extensions}/keyword-extractor/nlp.js +0 -0
  389. /package/dist/{extras/extensions → extensions}/keyword-extractor/nlp.test.d.ts +0 -0
  390. /package/dist/{extras/extensions → extensions}/keyword-extractor/nlp.test.js +0 -0
  391. /package/dist/{extras/extensions → extensions}/logger/extension.json +0 -0
  392. /package/dist/{extras/extensions → extensions}/logger/index.d.ts +0 -0
  393. /package/dist/{extras/extensions → extensions}/logger/index.js +0 -0
  394. /package/dist/{extras/extensions → extensions}/mcp/extension.js +0 -0
  395. /package/dist/{extras/extensions → extensions}/mcp/extension.json +0 -0
  396. /package/dist/{extras/extensions → extensions}/mcp/extension.test.d.ts +0 -0
  397. /package/dist/{extras/extensions → extensions}/mcp/index.d.ts +0 -0
  398. /package/dist/{extras/extensions → extensions}/mcp/index.js +0 -0
  399. /package/dist/{extras/extensions → extensions}/mem-session/extension.js +0 -0
  400. /package/dist/{extras/extensions → extensions}/mem-session/extension.json +0 -0
  401. /package/dist/{extras/extensions → extensions}/mem-session/index.d.ts +0 -0
  402. /package/dist/{extras/extensions → extensions}/mem-session/index.js +0 -0
  403. /package/dist/{extras/extensions → extensions}/memory/extension.json +0 -0
  404. /package/dist/{extras/extensions → extensions}/memory/index.js +0 -0
  405. /package/dist/{extras/extensions → extensions}/memory/types.js +0 -0
  406. /package/dist/{extras/extensions → extensions}/otel/extension.json +0 -0
  407. /package/dist/{extras/extensions → extensions}/otel/extension.test.d.ts +0 -0
  408. /package/dist/{extras/extensions → extensions}/otel/index.d.ts +0 -0
  409. /package/dist/{extras/extensions → extensions}/otel/index.js +0 -0
  410. /package/dist/{extras/extensions → extensions}/otel/jsonl-span-exporter.d.ts +0 -0
  411. /package/dist/{extras/extensions → extensions}/otel/jsonl-span-exporter.js +0 -0
  412. /package/dist/{extras/extensions → extensions}/scripts/extension.js +0 -0
  413. /package/dist/{extras/extensions → extensions}/scripts/extension.json +0 -0
  414. /package/dist/{extras/extensions → extensions}/scripts/extension.test.d.ts +0 -0
  415. /package/dist/{extras/extensions → extensions}/scripts/extension.test.js +0 -0
  416. /package/dist/{extras/extensions → extensions}/scripts/index.d.ts +0 -0
  417. /package/dist/{extras/extensions → extensions}/scripts/index.js +0 -0
  418. /package/dist/{extras/extensions → extensions}/skills/extension.js +0 -0
  419. /package/dist/{extras/extensions → extensions}/skills/extension.json +0 -0
  420. /package/dist/{extras/extensions → extensions}/skills/extension.test.d.ts +0 -0
  421. /package/dist/{extras/extensions → extensions}/skills/index.d.ts +0 -0
  422. /package/dist/{extras/extensions → extensions}/skills/index.js +0 -0
  423. /package/dist/{extras/extensions → extensions}/streaming/extension.js +0 -0
  424. /package/dist/{extras/extensions → extensions}/streaming/extension.json +0 -0
  425. /package/dist/{extras/extensions → extensions}/streaming/index.d.ts +0 -0
  426. /package/dist/{extras/extensions → extensions}/streaming/index.js +0 -0
  427. /package/dist/{extras/extensions → extensions}/structured-output/extension.js +0 -0
  428. /package/dist/{extras/extensions → extensions}/structured-output/extension.json +0 -0
  429. /package/dist/{extras/extensions → extensions}/structured-output/index.d.ts +0 -0
  430. /package/dist/{extras/extensions → extensions}/structured-output/index.js +0 -0
  431. /package/dist/{extras/extensions → extensions}/timestamp/extension.js +0 -0
  432. /package/dist/{extras/extensions → extensions}/timestamp/extension.json +0 -0
  433. /package/dist/{extras/extensions → extensions}/timestamp/index.d.ts +0 -0
  434. /package/dist/{extras/extensions → extensions}/timestamp/index.js +0 -0
  435. /package/dist/{extras/extensions → extensions}/token-stats/extension.js +0 -0
  436. /package/dist/{extras/extensions → extensions}/token-stats/extension.json +0 -0
  437. /package/dist/{extras/extensions → extensions}/token-stats/extension.test.d.ts +0 -0
  438. /package/dist/{extras/extensions → extensions}/token-stats/index.d.ts +0 -0
  439. /package/dist/{extras/extensions → extensions}/token-stats/index.js +0 -0
  440. /package/dist/{extras/extensions → extensions}/tool-buffer/extension.js +0 -0
  441. /package/dist/{extras/extensions → extensions}/tool-buffer/extension.json +0 -0
  442. /package/dist/{extras/extensions → extensions}/tool-buffer/extension.test.d.ts +0 -0
  443. /package/dist/{extras/extensions → extensions}/tool-buffer/index.d.ts +0 -0
  444. /package/dist/{extras/extensions → extensions}/tool-buffer/index.js +0 -0
  445. /package/dist/{extras/extensions → extensions}/weather-tool/extension.js +0 -0
  446. /package/dist/{extras/extensions → extensions}/weather-tool/extension.json +0 -0
  447. /package/dist/{extras/extensions → extensions}/weather-tool/index.d.ts +0 -0
  448. /package/dist/{extras/extensions → extensions}/weather-tool/index.js +0 -0
  449. /package/dist/{extras/models → models}/index.d.ts +0 -0
  450. /package/dist/{extras/models → models}/index.js +0 -0
  451. /package/dist/{extras/openai-provider → openai-provider}/index.d.ts +0 -0
  452. /package/dist/{extras/openai-provider → openai-provider}/index.js +0 -0
  453. /package/dist/{extras/openai-provider → openai-provider}/server.js +0 -0
package/README.md CHANGED
@@ -14,7 +14,7 @@ pnpm add @xandout/libra-harness
14
14
 
15
15
  ```typescript
16
16
  import { Agent } from '@xandout/libra-harness'
17
- import { resolveModel } from '@xandout/libra-harness/extras/models'
17
+ import { resolveModel } from '@xandout/libra-harness/models'
18
18
 
19
19
  // Resolve a model from environment variables (DEEPSEEK_API_KEY, OPENAI_API_KEY, etc.)
20
20
  const model = await resolveModel('deepseek/deepseek-v4-flash')
@@ -140,8 +140,8 @@ agent.use(loggingExtension)
140
140
  Libra ships with a set of optional extensions under `@xandout/libra-harness/extras`. Each is importable via its own subpath — import only what you need:
141
141
 
142
142
  ```typescript
143
- import { createLoggerExtension } from '@xandout/libra-harness/extras/logger'
144
- import { createDiskSessionExtension } from '@xandout/libra-harness/extras/disk-session'
143
+ import { createLoggerExtension } from '@xandout/libra-harness/extensions/logger'
144
+ import { createDiskSessionExtension } from '@xandout/libra-harness/extensions/disk-session'
145
145
 
146
146
  agent.use(createLoggerExtension())
147
147
  agent.use(createDiskSessionExtension({ dir: './sessions' }))
@@ -149,37 +149,37 @@ agent.use(createDiskSessionExtension({ dir: './sessions' }))
149
149
 
150
150
  | Extension | Import | Description |
151
151
  |-----------|--------|-------------|
152
- | logger | `@xandout/libra-harness/extras/logger` | Logs each lifecycle stage |
153
- | streaming | `@xandout/libra-harness/extras/streaming` | Streams text/reasoning/tool-input deltas |
154
- | otel | `@xandout/libra-harness/extras/otel` | OpenTelemetry tracing (JSONL or OTLP export) |
155
- | weather-tool | `@xandout/libra-harness/extras/weather-tool` | Registers a `get_weather` tool |
156
- | structured-output | `@xandout/libra-harness/extras/structured-output` | Validates LLM output against a JSON schema |
157
- | mcp | `@xandout/libra-harness/extras/mcp` | Connects to MCP servers, registers tools |
158
- | skills | `@xandout/libra-harness/extras/skills` | Loads Agent Skills from directories |
159
- | filesystem | `@xandout/libra-harness/extras/filesystem` | File read/write/list tools |
160
- | scripts | `@xandout/libra-harness/extras/scripts` | Runs shell scripts in pipeline stages |
161
- | keyword-extractor | `@xandout/libra-harness/extras/keyword-extractor` | Extracts keywords from messages (local NLP) |
162
- | token-stats | `@xandout/libra-harness/extras/token-stats` | Tracks token usage per turn |
163
- | tool-buffer | `@xandout/libra-harness/extras/tool-buffer` | Buffers and replays tool results |
164
- | auto-steer | `@xandout/libra-harness/extras/auto-steer` | Auto-injects steering messages based on conditions |
165
- | emoji | `@xandout/libra-harness/extras/emoji` | Decorates responses with an emoji prefix |
166
- | timestamp | `@xandout/libra-harness/extras/timestamp` | Records start/finish timestamps in metadata |
167
- | disk-session | `@xandout/libra-harness/extras/disk-session` | Disk-backed session history per session ID |
168
- | mem-session | `@xandout/libra-harness/extras/mem-session` | In-memory session history per session ID |
169
- | memory | `@xandout/libra-harness/extras/memory` | Long-term memory with LLM-based extraction |
152
+ | logger | `@xandout/libra-harness/extensions/logger` | Logs each lifecycle stage |
153
+ | streaming | `@xandout/libra-harness/extensions/streaming` | Streams text/reasoning/tool-input deltas |
154
+ | otel | `@xandout/libra-harness/extensions/otel` | OpenTelemetry tracing (JSONL or OTLP export) |
155
+ | weather-tool | `@xandout/libra-harness/extensions/weather-tool` | Registers a `get_weather` tool |
156
+ | structured-output | `@xandout/libra-harness/extensions/structured-output` | Validates LLM output against a JSON schema |
157
+ | mcp | `@xandout/libra-harness/extensions/mcp` | Connects to MCP servers, registers tools |
158
+ | skills | `@xandout/libra-harness/extensions/skills` | Loads Agent Skills from directories |
159
+ | filesystem | `@xandout/libra-harness/extensions/filesystem` | File read/write/list tools |
160
+ | scripts | `@xandout/libra-harness/extensions/scripts` | Runs shell scripts in pipeline stages |
161
+ | keyword-extractor | `@xandout/libra-harness/extensions/keyword-extractor` | Extracts keywords from messages (local NLP) |
162
+ | token-stats | `@xandout/libra-harness/extensions/token-stats` | Tracks token usage per turn |
163
+ | tool-buffer | `@xandout/libra-harness/extensions/tool-buffer` | Buffers and replays tool results |
164
+ | auto-steer | `@xandout/libra-harness/extensions/auto-steer` | Auto-injects steering messages based on conditions |
165
+ | emoji | `@xandout/libra-harness/extensions/emoji` | Decorates responses with an emoji prefix |
166
+ | timestamp | `@xandout/libra-harness/extensions/timestamp` | Records start/finish timestamps in metadata |
167
+ | disk-session | `@xandout/libra-harness/extensions/disk-session` | Disk-backed session history per session ID |
168
+ | mem-session | `@xandout/libra-harness/extensions/mem-session` | In-memory session history per session ID |
169
+ | memory | `@xandout/libra-harness/extensions/memory` | Long-term memory with LLM-based extraction |
170
170
 
171
171
  **Priority** controls hook execution order within each lifecycle stage (higher = runs first, ties keep registration order). Set `priority` on any extension whose hooks must run before or after another extension's hooks.
172
172
 
173
- See [`src/extras/README.md`](src/extras/README.md) for full API docs.
173
+ See [`src/extensions/README.md`](src/extensions/README.md) for full API docs.
174
174
 
175
175
  ### Extension loader
176
176
 
177
177
  For larger setups, `loadExtensions` accepts a mix of factory functions, `Extension` objects, and directory paths. It passes a shared config object to each factory, sorts by priority, and handles cleanup:
178
178
 
179
179
  ```typescript
180
- import { loadExtensions, installExtensions, closeExtensions } from '@xandout/libra-harness/extras'
181
- import { createLoggerExtension } from '@xandout/libra-harness/extras/logger'
182
- import { createMcpExtension } from '@xandout/libra-harness/extras/mcp'
180
+ import { loadExtensions, installExtensions, closeExtensions } from '@xandout/libra-harness/extensions'
181
+ import { createLoggerExtension } from '@xandout/libra-harness/extensions/logger'
182
+ import { createMcpExtension } from '@xandout/libra-harness/extensions/mcp'
183
183
 
184
184
  const loaded = await loadExtensions(
185
185
  [
@@ -201,10 +201,10 @@ await closeExtensions(loaded) // calls close() on extensions that have one (
201
201
 
202
202
  ### Native resolver
203
203
 
204
- The easiest way to get a model is `resolveModel` from `@xandout/libra-harness/extras/models`. It reads API keys from environment variables and loads the appropriate AI SDK provider package dynamically:
204
+ The easiest way to get a model is `resolveModel` from `@xandout/libra-harness/models`. It reads API keys from environment variables and loads the appropriate AI SDK provider package dynamically:
205
205
 
206
206
  ```typescript
207
- import { resolveModel } from '@xandout/libra-harness/extras/models'
207
+ import { resolveModel } from '@xandout/libra-harness/models'
208
208
 
209
209
  // Reads DEEPSEEK_API_KEY from env, loads @ai-sdk/deepseek
210
210
  const model = await resolveModel('deepseek/deepseek-v4-flash')
@@ -244,7 +244,7 @@ const model = new AISdkModel(openai('gpt-4.1-mini'))
244
244
  Route requests to different models based on input content — e.g. send images to a vision model:
245
245
 
246
246
  ```typescript
247
- import { createRoutingModel, hasImageInput } from '@xandout/libra-harness/extras/models'
247
+ import { createRoutingModel, hasImageInput } from '@xandout/libra-harness/models'
248
248
 
249
249
  const model = createRoutingModel({
250
250
  default: await resolveModel('deepseek/deepseek-v4-flash'),
@@ -274,8 +274,8 @@ Expose Libra agents as OpenAI-compatible models. Any framework that supports a c
274
274
 
275
275
  ```typescript
276
276
  import { Agent } from '@xandout/libra-harness'
277
- import { resolveModel } from '@xandout/libra-harness/extras/models'
278
- import { createOpenAICompatibleServer } from '@xandout/libra-harness/extras/openai-provider'
277
+ import { resolveModel } from '@xandout/libra-harness/models'
278
+ import { createOpenAICompatibleServer } from '@xandout/libra-harness/openai-provider'
279
279
 
280
280
  const model = await resolveModel('deepseek/deepseek-v4-flash')
281
281
 
package/dist/agent.d.ts CHANGED
@@ -89,6 +89,8 @@ export declare class Agent {
89
89
  private installingExtension?;
90
90
  private readonly activeHandles;
91
91
  constructor(config: AgentConfig);
92
+ /** The configured model for this agent. */
93
+ get model(): Model;
92
94
  /**
93
95
  * Append content to the system prompt. This is a one-time mutation
94
96
  * typically called by extensions at install time (e.g. the skills
@@ -157,6 +159,10 @@ export declare class Agent {
157
159
  run(request: AgentRequest): RunHandle;
158
160
  private mergeTools;
159
161
  private executeTurn;
162
+ private executeTurnIteration;
163
+ private handleNoToolCalls;
164
+ private handleTurnError;
165
+ private generateModelResponse;
160
166
  /**
161
167
  * Build the response, run beforeResponse + afterTurn hooks, and return.
162
168
  * All turn exit paths go through here so extensions (session, memory,
@@ -171,6 +177,8 @@ export declare class Agent {
171
177
  * observability extensions can inspect it via `afterTurn`.
172
178
  */
173
179
  private finishWithError;
180
+ private processInternalCalls;
181
+ private executeToolBatch;
174
182
  private executeToolCall;
175
183
  /**
176
184
  * Race a promise against an abort signal. Returns `undefined` if the
@@ -1 +1 @@
1
- {"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../src/agent.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../src/agent.ts"],"names":[],"mappings":"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"}
package/dist/agent.js CHANGED
@@ -34,6 +34,10 @@ export class Agent {
34
34
  this.tools.set(tool.name, tool);
35
35
  }
36
36
  }
37
+ /** The configured model for this agent. */
38
+ get model() {
39
+ return this.config.model;
40
+ }
37
41
  // ── System Prompt ──────────────────────────────────────────────────
38
42
  /**
39
43
  * Append content to the system prompt. This is a one-time mutation
@@ -198,7 +202,7 @@ export class Agent {
198
202
  turn.halt = (reason) => handle.halt(reason);
199
203
  // Kick off the turn. We store the promise on the handle so `handle.done`
200
204
  // and `await handle` both resolve to the same result.
201
- handle.done = this.executeTurn(turn, maxIter, steeringQueue).finally(() => {
205
+ handle.done = this.executeTurn(turn, maxIter, steeringQueue, handle).finally(() => {
202
206
  this.activeHandles.delete(handle);
203
207
  });
204
208
  return handle;
@@ -209,7 +213,7 @@ export class Agent {
209
213
  all.set(t.name, t);
210
214
  return [...all.values()];
211
215
  }
212
- async executeTurn(turn, maxIter, steeringQueue) {
216
+ async executeTurn(turn, maxIter, steeringQueue, handle) {
213
217
  let iterations = 0;
214
218
  const allToolCalls = [];
215
219
  try {
@@ -218,197 +222,161 @@ export class Agent {
218
222
  // beforeContext — last chance to modify context before the LLM loop.
219
223
  await this.runHooks('beforeContext', { turn });
220
224
  for (;;) {
221
- // ── Check halt ──
222
- if (turn.signal.aborted) {
223
- return await this.finishTurn(turn, '', 'halted', iterations, allToolCalls);
224
- }
225
- // ── Check max iterations ──
226
- if (iterations >= maxIter) {
227
- return await this.finishTurn(turn, '', 'max_iterations', iterations, allToolCalls);
228
- }
229
- // ── Drain steering messages ──
230
- this.drainSteering(turn, steeringQueue);
231
- // ── beforeLLM ──
232
- const modelRequest = {
233
- messages: turn.messages,
234
- tools: turn.tools.length > 0 ? turn.tools.map(toToolDefinition) : undefined,
235
- systemPrompt: turn.systemPrompt,
236
- temperature: this.config.temperature,
237
- maxTokens: this.config.maxTokens,
238
- reasoningEffort: this.config.reasoningEffort,
239
- providerOptions: this.config.providerOptions,
240
- signal: turn.signal,
241
- };
242
- const beforeLLMResult = await this.runHooks('beforeLLM', { turn, modelRequest });
243
- // Halt may have been called during beforeLLM hooks.
244
- if (turn.signal.aborted) {
245
- return await this.finishTurn(turn, '', 'halted', iterations, allToolCalls);
246
- }
247
- let modelResponse;
248
- if (beforeLLMResult.skipped && beforeLLMResult.value) {
249
- modelResponse = beforeLLMResult.value;
250
- }
251
- else {
252
- try {
253
- modelResponse = await this.config.model.generate(modelRequest);
254
- }
255
- catch (err) {
256
- if (turn.signal.aborted) {
257
- return await this.finishTurn(turn, '', 'halted', iterations, allToolCalls);
258
- }
259
- throw err;
260
- }
261
- }
262
- // ── afterLLM ──
263
- await this.runHooks('afterLLM', { turn, modelRequest, modelResponse });
225
+ const result = await this.executeTurnIteration(turn, maxIter, steeringQueue, handle, iterations, allToolCalls);
226
+ if (result.status === 'finish')
227
+ return result.response;
264
228
  iterations++;
265
- // Add the assistant message to the conversation.
266
- turn.messages.push(modelResponse.message);
267
- // ── Halt may have been called during afterLLM hooks ──
268
- if (turn.signal.aborted) {
269
- return await this.finishTurn(turn, messageContentToText(modelResponse.message.content), 'halted', iterations, allToolCalls);
270
- }
271
- // ── No tool calls → final response (unless steering pending) ──
272
- const toolCalls = modelResponse.message.toolCalls;
273
- if (!toolCalls || toolCalls.length === 0) {
274
- // If steering messages arrived during the LLM call, don't end
275
- // the turn — drain them and loop so the agent can respond.
276
- if (steeringQueue.length > 0) {
277
- this.drainSteering(turn, steeringQueue);
278
- continue;
279
- }
280
- return await this.finishTurn(turn, messageContentToText(modelResponse.message.content), 'stop', iterations, allToolCalls);
281
- }
282
- // ── Separate external (pass-through) from internal (execute) tool calls ──
283
- const externalCalls = [];
284
- const internalCalls = [];
285
- for (const tc of toolCalls) {
286
- const tool = turn.tools.find((t) => t.name === tc.name);
287
- if (tool?.external)
288
- externalCalls.push(tc);
289
- else
290
- internalCalls.push(tc);
291
- }
292
- // ── External tool calls → return to caller for execution ──
293
- if (externalCalls.length > 0) {
294
- allToolCalls.push(...externalCalls);
295
- // If there are also internal calls in this batch, execute those first
296
- // (the model may have mixed both in one response). The external calls
297
- // are still returned — the caller will see them and the internal results.
298
- if (internalCalls.length > 0) {
299
- allToolCalls.push(...internalCalls);
300
- if (turn.signal.aborted) {
301
- return await this.finishTurn(turn, '', 'halted', iterations, allToolCalls);
302
- }
303
- const mixedResults = await Promise.all(internalCalls.map(async (toolCall) => {
304
- const beforeToolCtx = { turn, toolCall };
305
- const beforeToolResult = await this.runHooks('beforeTool', beforeToolCtx);
306
- let toolResult;
307
- if (beforeToolResult.skipped && beforeToolResult.value) {
308
- toolResult = beforeToolResult.value;
309
- }
310
- else {
311
- toolResult = await this.executeToolCall(toolCall, turn);
312
- }
313
- const afterToolCtx = { turn, toolCall, toolResult };
314
- const afterToolResult = await this.runHooks('afterTool', afterToolCtx);
315
- if (afterToolResult.value) {
316
- toolResult = afterToolResult.value;
317
- }
318
- return { toolCall, toolResult };
319
- }));
320
- for (const { toolCall, toolResult } of mixedResults) {
321
- turn.messages.push({
322
- role: 'tool',
323
- content: toolResult.content,
324
- toolCallId: toolCall.id,
325
- name: toolCall.name,
326
- });
327
- }
328
- // Drain steering after mixed tool results too.
329
- this.drainSteering(turn, steeringQueue);
330
- }
331
- // Return external tool calls to the caller. The assistant message
332
- // (with toolCalls) is already in turn.messages from the push above.
333
- return await this.finishTurn(turn, messageContentToText(modelResponse.message.content), 'tool_calls', iterations, allToolCalls, externalCalls);
334
- }
335
- // ── Execute internal tool calls ──
336
- allToolCalls.push(...internalCalls);
337
- // Check halt before starting the batch.
338
- if (turn.signal.aborted) {
339
- return await this.finishTurn(turn, '', 'halted', iterations, allToolCalls);
340
- }
341
- // Execute all internal tool calls in the batch concurrently.
342
- // Each tool call runs its beforeTool → execute → afterTool pipeline
343
- // independently. Results are collected in order and appended to
344
- // turn.messages after all complete, preserving the model's ordering.
345
- const results = await Promise.all(internalCalls.map(async (toolCall) => {
346
- // beforeTool — can short-circuit with a synthetic result.
347
- const beforeToolCtx = { turn, toolCall };
348
- const beforeToolResult = await this.runHooks('beforeTool', beforeToolCtx);
349
- let toolResult;
350
- if (beforeToolResult.skipped && beforeToolResult.value) {
351
- toolResult = beforeToolResult.value;
352
- }
353
- else {
354
- toolResult = await this.executeToolCall(toolCall, turn);
355
- }
356
- // afterTool — can modify the result.
357
- const afterToolCtx = { turn, toolCall, toolResult };
358
- const afterToolResult = await this.runHooks('afterTool', afterToolCtx);
359
- if (afterToolResult.value) {
360
- toolResult = afterToolResult.value;
361
- }
362
- return { toolCall, toolResult };
363
- }));
364
- // Append results to messages in the original order.
365
- for (const { toolCall, toolResult } of results) {
366
- turn.messages.push({
367
- role: 'tool',
368
- content: toolResult.content,
369
- toolCallId: toolCall.id,
370
- name: toolCall.name,
371
- });
372
- }
373
- // ── Drain steering messages right after tool results ──
374
- // This ensures the model sees steering directives immediately
375
- // alongside tool results, rather than waiting for the next
376
- // loop iteration's drain at the top.
377
- this.drainSteering(turn, steeringQueue);
378
- // Loop continues — the model will see the tool results.
379
229
  }
380
230
  }
381
231
  catch (err) {
382
- if (turn.signal.aborted) {
383
- return await this.finishTurn(turn, '', 'halted', iterations, allToolCalls);
232
+ return await this.handleTurnError(turn, err, iterations, allToolCalls);
233
+ }
234
+ }
235
+ async executeTurnIteration(turn, maxIter, steeringQueue, handle, iterations, allToolCalls) {
236
+ // ── Check halt ──
237
+ if (turn.signal.aborted) {
238
+ return { status: 'finish', response: await this.finishTurn(turn, '', 'halted', iterations, allToolCalls) };
239
+ }
240
+ // ── Check max iterations ──
241
+ if (iterations >= maxIter) {
242
+ return { status: 'finish', response: await this.finishTurn(turn, '', 'max_iterations', iterations, allToolCalls) };
243
+ }
244
+ // ── Drain steering messages ──
245
+ this.drainSteering(turn, steeringQueue);
246
+ const modelResponse = await this.generateModelResponse(turn);
247
+ if (!modelResponse) {
248
+ return { status: 'finish', response: await this.finishTurn(turn, '', 'halted', iterations, allToolCalls) };
249
+ }
250
+ // Add the assistant message to the conversation.
251
+ turn.messages.push(modelResponse.message);
252
+ // ── Emit text blurb immediately upon arrival ──
253
+ const blurbText = messageContentToText(modelResponse.message.content);
254
+ if (blurbText.trim()) {
255
+ try {
256
+ turn.request.onMessage?.(blurbText);
384
257
  }
385
- // Fire onError hooks — extensions can observe or recover.
386
- // Hooks take precedence over the error policy.
387
- const errorResult = await this.runHooks('onError', { turn, error: err });
388
- if (errorResult.skipped && errorResult.value) {
389
- const response = errorResult.value;
390
- turn.response = response;
391
- await this.runHooks('afterTurn', { turn });
392
- return response;
258
+ catch (err) {
259
+ console.error('[agent] request.onMessage error:', err);
393
260
  }
394
- // No hook recovered — apply the configured error policy.
395
- const policy = this.config.errorPolicy ?? DEFAULT_ERROR_POLICY;
396
- if (policy === 'throw') {
397
- throw err;
261
+ handle?.emitMessage(blurbText);
262
+ }
263
+ // ── Halt may have been called during afterLLM hooks ──
264
+ if (turn.signal.aborted) {
265
+ return { status: 'finish', response: await this.finishTurn(turn, blurbText, 'halted', iterations + 1, allToolCalls) };
266
+ }
267
+ // ── No tool calls → final response (unless steering pending) ──
268
+ const toolCalls = modelResponse.message.toolCalls;
269
+ if (!toolCalls || toolCalls.length === 0) {
270
+ const result = await this.handleNoToolCalls(turn, modelResponse, steeringQueue, iterations + 1, allToolCalls);
271
+ if (result.status === 'finish')
272
+ return { status: 'finish', response: result.response };
273
+ return { status: 'continue' };
274
+ }
275
+ // ── Separate external (pass-through) from internal (execute) tool calls ──
276
+ const externalCalls = [];
277
+ const internalCalls = [];
278
+ for (const tc of toolCalls) {
279
+ const tool = turn.tools.find((t) => t.name === tc.name);
280
+ if (tool?.external)
281
+ externalCalls.push(tc);
282
+ else
283
+ internalCalls.push(tc);
284
+ }
285
+ // ── External tool calls → return to caller for execution ──
286
+ if (externalCalls.length > 0) {
287
+ allToolCalls.push(...externalCalls);
288
+ if (internalCalls.length > 0) {
289
+ const haltedResponse = await this.processInternalCalls(turn, internalCalls, allToolCalls, steeringQueue, iterations + 1);
290
+ if (haltedResponse)
291
+ return { status: 'finish', response: haltedResponse };
398
292
  }
399
- if (policy === 'fallback') {
400
- return await this.finishWithError(turn, err, iterations, allToolCalls);
293
+ // Return external tool calls to the caller. The assistant message
294
+ // (with toolCalls) is already in turn.messages from the push above.
295
+ return { status: 'finish', response: await this.finishTurn(turn, messageContentToText(modelResponse.message.content), 'tool_calls', iterations + 1, allToolCalls, externalCalls) };
296
+ }
297
+ // ── Execute internal tool calls ──
298
+ const haltedResponse = await this.processInternalCalls(turn, internalCalls, allToolCalls, steeringQueue, iterations + 1);
299
+ if (haltedResponse)
300
+ return { status: 'finish', response: haltedResponse };
301
+ return { status: 'continue' };
302
+ }
303
+ async handleNoToolCalls(turn, modelResponse, steeringQueue, iterations, allToolCalls) {
304
+ const textContent = messageContentToText(modelResponse.message.content).trim();
305
+ if (!textContent) {
306
+ turn.messages.push({
307
+ role: 'user',
308
+ content: 'You sent an empty response. Please provide a meaningful response to the last completed task. Do not acknowledge this empty response, just provide the expected output.'
309
+ });
310
+ return { status: 'continue' };
311
+ }
312
+ if (steeringQueue.length > 0) {
313
+ this.drainSteering(turn, steeringQueue);
314
+ return { status: 'continue' };
315
+ }
316
+ return { status: 'finish', response: await this.finishTurn(turn, textContent, 'stop', iterations, allToolCalls) };
317
+ }
318
+ async handleTurnError(turn, err, iterations, allToolCalls) {
319
+ if (turn.signal.aborted) {
320
+ return await this.finishTurn(turn, '', 'halted', iterations, allToolCalls);
321
+ }
322
+ // Fire onError hooks — extensions can observe or recover.
323
+ // Hooks take precedence over the error policy.
324
+ const errorResult = await this.runHooks('onError', { turn, error: err });
325
+ if (errorResult.skipped && errorResult.value) {
326
+ const response = errorResult.value;
327
+ turn.response = response;
328
+ await this.runHooks('afterTurn', { turn });
329
+ return response;
330
+ }
331
+ // No hook recovered — apply the configured error policy.
332
+ const policy = this.config.errorPolicy ?? DEFAULT_ERROR_POLICY;
333
+ if (policy === 'throw') {
334
+ throw err;
335
+ }
336
+ if (policy === 'fallback') {
337
+ return await this.finishWithError(turn, err, iterations, allToolCalls);
338
+ }
339
+ // Custom policy function — return a response to recover,
340
+ // return undefined to rethrow.
341
+ const customResponse = await policy({ error: err, turn });
342
+ if (customResponse) {
343
+ turn.response = customResponse;
344
+ await this.runHooks('afterTurn', { turn });
345
+ return customResponse;
346
+ }
347
+ throw err;
348
+ }
349
+ async generateModelResponse(turn) {
350
+ const modelRequest = {
351
+ messages: turn.messages,
352
+ tools: turn.tools.length > 0 ? turn.tools.map(toToolDefinition) : undefined,
353
+ systemPrompt: turn.systemPrompt,
354
+ temperature: this.config.temperature,
355
+ maxTokens: this.config.maxTokens,
356
+ reasoningEffort: this.config.reasoningEffort,
357
+ providerOptions: this.config.providerOptions,
358
+ signal: turn.signal,
359
+ };
360
+ const beforeLLMResult = await this.runHooks('beforeLLM', { turn, modelRequest });
361
+ // Halt may have been called during beforeLLM hooks.
362
+ if (turn.signal.aborted)
363
+ return undefined;
364
+ let modelResponse;
365
+ if (beforeLLMResult.skipped && beforeLLMResult.value) {
366
+ modelResponse = beforeLLMResult.value;
367
+ }
368
+ else {
369
+ try {
370
+ modelResponse = await this.config.model.generate(modelRequest);
401
371
  }
402
- // Custom policy function — return a response to recover,
403
- // return undefined to rethrow.
404
- const customResponse = await policy({ error: err, turn });
405
- if (customResponse) {
406
- turn.response = customResponse;
407
- await this.runHooks('afterTurn', { turn });
408
- return customResponse;
372
+ catch (err) {
373
+ if (turn.signal.aborted)
374
+ return undefined;
375
+ throw err;
409
376
  }
410
- throw err;
411
377
  }
378
+ await this.runHooks('afterLLM', { turn, modelRequest, modelResponse });
379
+ return modelResponse;
412
380
  }
413
381
  /**
414
382
  * Build the response, run beforeResponse + afterTurn hooks, and return.
@@ -440,6 +408,42 @@ export class Agent {
440
408
  await this.runHooks('afterTurn', { turn });
441
409
  return response;
442
410
  }
411
+ async processInternalCalls(turn, internalCalls, allToolCalls, steeringQueue, iterations) {
412
+ allToolCalls.push(...internalCalls);
413
+ if (turn.signal.aborted) {
414
+ return await this.finishTurn(turn, '', 'halted', iterations, allToolCalls);
415
+ }
416
+ await this.executeToolBatch(turn, internalCalls);
417
+ this.drainSteering(turn, steeringQueue);
418
+ return undefined;
419
+ }
420
+ async executeToolBatch(turn, internalCalls) {
421
+ const results = await Promise.all(internalCalls.map(async (toolCall) => {
422
+ const beforeToolCtx = { turn, toolCall };
423
+ const beforeToolResult = await this.runHooks('beforeTool', beforeToolCtx);
424
+ let toolResult;
425
+ if (beforeToolResult.skipped && beforeToolResult.value) {
426
+ toolResult = beforeToolResult.value;
427
+ }
428
+ else {
429
+ toolResult = await this.executeToolCall(toolCall, turn);
430
+ }
431
+ const afterToolCtx = { turn, toolCall, toolResult };
432
+ const afterToolResult = await this.runHooks('afterTool', afterToolCtx);
433
+ if (afterToolResult.value) {
434
+ toolResult = afterToolResult.value;
435
+ }
436
+ return { toolCall, toolResult };
437
+ }));
438
+ for (const { toolCall, toolResult } of results) {
439
+ turn.messages.push({
440
+ role: 'tool',
441
+ content: toolResult.content,
442
+ toolCallId: toolCall.id,
443
+ name: toolCall.name,
444
+ });
445
+ }
446
+ }
443
447
  async executeToolCall(toolCall, turn) {
444
448
  const tool = turn.tools.find((t) => t.name === toolCall.name);
445
449
  if (!tool) {
@@ -524,16 +528,9 @@ export class Agent {
524
528
  drainSteering(turn, steeringQueue) {
525
529
  while (steeringQueue.length > 0) {
526
530
  const msg = steeringQueue.shift();
527
- // Inject a system directive + user message pair. The system
528
- // message tells the model to treat the steering as an
529
- // interruption; the user message carries the actual content.
530
- // Models deprioritize mid-conversation system messages, so we
531
- // pair it with a user message (which models can't ignore) and
532
- // use the system message to frame it as a hard redirect.
533
- turn.messages.push({
534
- role: 'system',
535
- content: '[steering] The user has sent a new directive. You must address it immediately. Do not continue the previous task — pivot to the user\'s new request now.',
536
- });
531
+ // Inject the steering directive as a user message. We do not inject a
532
+ // role: 'system' message here because LLM providers (Anthropic, Gemini,
533
+ // OpenAI) forbid or reject mid-conversation system messages.
537
534
  turn.messages.push({
538
535
  role: 'user',
539
536
  content: `[steering] ${msg}`,
@@ -578,6 +575,7 @@ export class Agent {
578
575
  class RunHandleImpl {
579
576
  abort;
580
577
  steeringQueue;
578
+ messageListeners = [];
581
579
  _done;
582
580
  constructor(abort, steeringQueue) {
583
581
  this.abort = abort;
@@ -606,6 +604,20 @@ class RunHandleImpl {
606
604
  halt(reason = 'halted') {
607
605
  this.abort.abort(reason);
608
606
  }
607
+ onMessage(callback) {
608
+ this.messageListeners.push(callback);
609
+ return this;
610
+ }
611
+ emitMessage(message) {
612
+ for (const listener of this.messageListeners) {
613
+ try {
614
+ listener(message);
615
+ }
616
+ catch (err) {
617
+ console.error('[handle] onMessage listener error:', err);
618
+ }
619
+ }
620
+ }
609
621
  // Thenable — allows `await handle` to work.
610
622
  then(onfulfilled, onrejected) {
611
623
  return this.done.then(onfulfilled, onrejected);