@qjp88995/agent-runtime 0.0.0-stage → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (477) hide show
  1. package/dist/agent-extensions.d.ts +30 -0
  2. package/dist/agent-extensions.d.ts.map +1 -0
  3. package/dist/agent-extensions.js +4 -0
  4. package/dist/agent-extensions.js.map +1 -0
  5. package/dist/builtins/ask-outcome.d.ts +49 -0
  6. package/dist/builtins/ask-outcome.d.ts.map +1 -0
  7. package/dist/builtins/ask-outcome.js +128 -0
  8. package/dist/builtins/ask-outcome.js.map +1 -0
  9. package/dist/builtins/ask-schema.d.ts +110 -0
  10. package/dist/builtins/ask-schema.d.ts.map +1 -0
  11. package/dist/builtins/ask-schema.js +124 -0
  12. package/dist/builtins/ask-schema.js.map +1 -0
  13. package/dist/builtins/ask.service.d.ts +210 -0
  14. package/dist/builtins/ask.service.d.ts.map +1 -0
  15. package/dist/builtins/ask.service.js +373 -0
  16. package/dist/builtins/ask.service.js.map +1 -0
  17. package/dist/builtins/ask.tool.d.ts +49 -0
  18. package/dist/builtins/ask.tool.d.ts.map +1 -0
  19. package/dist/builtins/ask.tool.js +109 -0
  20. package/dist/builtins/ask.tool.js.map +1 -0
  21. package/dist/builtins/index.d.ts +8 -0
  22. package/dist/builtins/index.d.ts.map +1 -0
  23. package/dist/builtins/index.js +8 -0
  24. package/dist/builtins/index.js.map +1 -0
  25. package/dist/builtins/todo-schema.d.ts +90 -0
  26. package/dist/builtins/todo-schema.d.ts.map +1 -0
  27. package/dist/builtins/todo-schema.js +97 -0
  28. package/dist/builtins/todo-schema.js.map +1 -0
  29. package/dist/builtins/todo-settle.hook.d.ts +110 -0
  30. package/dist/builtins/todo-settle.hook.d.ts.map +1 -0
  31. package/dist/builtins/todo-settle.hook.js +174 -0
  32. package/dist/builtins/todo-settle.hook.js.map +1 -0
  33. package/dist/builtins/todo.tool.d.ts +59 -0
  34. package/dist/builtins/todo.tool.d.ts.map +1 -0
  35. package/dist/builtins/todo.tool.js +107 -0
  36. package/dist/builtins/todo.tool.js.map +1 -0
  37. package/dist/context/context-budget-tracker.d.ts +185 -0
  38. package/dist/context/context-budget-tracker.d.ts.map +1 -0
  39. package/dist/context/context-budget-tracker.js +400 -0
  40. package/dist/context/context-budget-tracker.js.map +1 -0
  41. package/dist/context/context-budget.d.ts +48 -0
  42. package/dist/context/context-budget.d.ts.map +1 -0
  43. package/dist/context/context-budget.js +89 -0
  44. package/dist/context/context-budget.js.map +1 -0
  45. package/dist/context/index.d.ts +3 -0
  46. package/dist/context/index.d.ts.map +1 -0
  47. package/dist/context/index.js +3 -0
  48. package/dist/context/index.js.map +1 -0
  49. package/dist/extensions/repeat-call.hook.d.ts +32 -0
  50. package/dist/extensions/repeat-call.hook.d.ts.map +1 -0
  51. package/dist/extensions/repeat-call.hook.js +54 -0
  52. package/dist/extensions/repeat-call.hook.js.map +1 -0
  53. package/dist/hooks/index.d.ts +3 -0
  54. package/dist/hooks/index.d.ts.map +1 -0
  55. package/dist/hooks/index.js +3 -0
  56. package/dist/hooks/index.js.map +1 -0
  57. package/dist/hooks/turn-hook.registry.d.ts +51 -0
  58. package/dist/hooks/turn-hook.registry.d.ts.map +1 -0
  59. package/dist/hooks/turn-hook.registry.js +233 -0
  60. package/dist/hooks/turn-hook.registry.js.map +1 -0
  61. package/dist/hooks/turn-hook.types.d.ts +179 -0
  62. package/dist/hooks/turn-hook.types.d.ts.map +1 -0
  63. package/dist/hooks/turn-hook.types.js +48 -0
  64. package/dist/hooks/turn-hook.types.js.map +1 -0
  65. package/dist/images/byte-cache.d.ts +24 -0
  66. package/dist/images/byte-cache.d.ts.map +1 -0
  67. package/dist/images/byte-cache.js +51 -0
  68. package/dist/images/byte-cache.js.map +1 -0
  69. package/dist/images/delivery.d.ts +115 -0
  70. package/dist/images/delivery.d.ts.map +1 -0
  71. package/dist/images/delivery.js +321 -0
  72. package/dist/images/delivery.js.map +1 -0
  73. package/dist/images/index.d.ts +5 -0
  74. package/dist/images/index.d.ts.map +1 -0
  75. package/dist/images/index.js +5 -0
  76. package/dist/images/index.js.map +1 -0
  77. package/dist/images/prompt.d.ts +151 -0
  78. package/dist/images/prompt.d.ts.map +1 -0
  79. package/dist/images/prompt.js +172 -0
  80. package/dist/images/prompt.js.map +1 -0
  81. package/dist/images/vendor-files.d.ts +93 -0
  82. package/dist/images/vendor-files.d.ts.map +1 -0
  83. package/dist/images/vendor-files.js +156 -0
  84. package/dist/images/vendor-files.js.map +1 -0
  85. package/dist/in-process/conversation-store.d.ts +64 -0
  86. package/dist/in-process/conversation-store.d.ts.map +1 -0
  87. package/dist/in-process/conversation-store.js +222 -0
  88. package/dist/in-process/conversation-store.js.map +1 -0
  89. package/dist/in-process/coordination.d.ts +54 -0
  90. package/dist/in-process/coordination.d.ts.map +1 -0
  91. package/dist/in-process/coordination.js +137 -0
  92. package/dist/in-process/coordination.js.map +1 -0
  93. package/dist/in-process/image-source.d.ts +15 -0
  94. package/dist/in-process/image-source.d.ts.map +1 -0
  95. package/dist/in-process/image-source.js +27 -0
  96. package/dist/in-process/image-source.js.map +1 -0
  97. package/dist/in-process/index.d.ts +36 -0
  98. package/dist/in-process/index.d.ts.map +1 -0
  99. package/dist/in-process/index.js +37 -0
  100. package/dist/in-process/index.js.map +1 -0
  101. package/dist/in-process/question-store.d.ts +28 -0
  102. package/dist/in-process/question-store.d.ts.map +1 -0
  103. package/dist/in-process/question-store.js +122 -0
  104. package/dist/in-process/question-store.js.map +1 -0
  105. package/dist/in-process/run-store.d.ts +36 -0
  106. package/dist/in-process/run-store.d.ts.map +1 -0
  107. package/dist/in-process/run-store.js +81 -0
  108. package/dist/in-process/run-store.js.map +1 -0
  109. package/dist/in-process/session-store.d.ts +33 -0
  110. package/dist/in-process/session-store.d.ts.map +1 -0
  111. package/dist/in-process/session-store.js +93 -0
  112. package/dist/in-process/session-store.js.map +1 -0
  113. package/dist/in-process/stream-bus.d.ts +52 -0
  114. package/dist/in-process/stream-bus.d.ts.map +1 -0
  115. package/dist/in-process/stream-bus.js +200 -0
  116. package/dist/in-process/stream-bus.js.map +1 -0
  117. package/dist/in-process/vendor-file-cache.d.ts +11 -0
  118. package/dist/in-process/vendor-file-cache.d.ts.map +1 -0
  119. package/dist/in-process/vendor-file-cache.js +47 -0
  120. package/dist/in-process/vendor-file-cache.js.map +1 -0
  121. package/dist/index.d.ts +21 -0
  122. package/dist/index.d.ts.map +1 -0
  123. package/dist/index.js +21 -0
  124. package/dist/index.js.map +1 -0
  125. package/dist/loop/active-tick.registry.d.ts +31 -0
  126. package/dist/loop/active-tick.registry.d.ts.map +1 -0
  127. package/dist/loop/active-tick.registry.js +45 -0
  128. package/dist/loop/active-tick.registry.js.map +1 -0
  129. package/dist/loop/index.d.ts +6 -0
  130. package/dist/loop/index.d.ts.map +1 -0
  131. package/dist/loop/index.js +6 -0
  132. package/dist/loop/index.js.map +1 -0
  133. package/dist/loop/loop-driver.d.ts +127 -0
  134. package/dist/loop/loop-driver.d.ts.map +1 -0
  135. package/dist/loop/loop-driver.js +199 -0
  136. package/dist/loop/loop-driver.js.map +1 -0
  137. package/dist/loop/message-hub.d.ts +236 -0
  138. package/dist/loop/message-hub.d.ts.map +1 -0
  139. package/dist/loop/message-hub.js +439 -0
  140. package/dist/loop/message-hub.js.map +1 -0
  141. package/dist/loop/orphan-run.sweeper.d.ts +79 -0
  142. package/dist/loop/orphan-run.sweeper.d.ts.map +1 -0
  143. package/dist/loop/orphan-run.sweeper.js +145 -0
  144. package/dist/loop/orphan-run.sweeper.js.map +1 -0
  145. package/dist/loop/root-host.d.ts +51 -0
  146. package/dist/loop/root-host.d.ts.map +1 -0
  147. package/dist/loop/root-host.js +65 -0
  148. package/dist/loop/root-host.js.map +1 -0
  149. package/dist/ports/context-store.d.ts +69 -0
  150. package/dist/ports/context-store.d.ts.map +1 -0
  151. package/dist/ports/context-store.js +2 -0
  152. package/dist/ports/context-store.js.map +1 -0
  153. package/dist/ports/conversation-store.d.ts +144 -0
  154. package/dist/ports/conversation-store.d.ts.map +1 -0
  155. package/dist/ports/conversation-store.js +2 -0
  156. package/dist/ports/conversation-store.js.map +1 -0
  157. package/dist/ports/coordination.d.ts +76 -0
  158. package/dist/ports/coordination.d.ts.map +1 -0
  159. package/dist/ports/coordination.js +12 -0
  160. package/dist/ports/coordination.js.map +1 -0
  161. package/dist/ports/image-source.d.ts +26 -0
  162. package/dist/ports/image-source.d.ts.map +1 -0
  163. package/dist/ports/image-source.js +2 -0
  164. package/dist/ports/image-source.js.map +1 -0
  165. package/dist/ports/index.d.ts +11 -0
  166. package/dist/ports/index.d.ts.map +1 -0
  167. package/dist/ports/index.js +4 -0
  168. package/dist/ports/index.js.map +1 -0
  169. package/dist/ports/logger.d.ts +14 -0
  170. package/dist/ports/logger.d.ts.map +1 -0
  171. package/dist/ports/logger.js +23 -0
  172. package/dist/ports/logger.js.map +1 -0
  173. package/dist/ports/question-store.d.ts +91 -0
  174. package/dist/ports/question-store.d.ts.map +1 -0
  175. package/dist/ports/question-store.js +8 -0
  176. package/dist/ports/question-store.js.map +1 -0
  177. package/dist/ports/run-store.d.ts +66 -0
  178. package/dist/ports/run-store.d.ts.map +1 -0
  179. package/dist/ports/run-store.js +2 -0
  180. package/dist/ports/run-store.js.map +1 -0
  181. package/dist/ports/session-store.d.ts +72 -0
  182. package/dist/ports/session-store.d.ts.map +1 -0
  183. package/dist/ports/session-store.js +9 -0
  184. package/dist/ports/session-store.js.map +1 -0
  185. package/dist/ports/stream-bus.d.ts +52 -0
  186. package/dist/ports/stream-bus.d.ts.map +1 -0
  187. package/dist/ports/stream-bus.js +2 -0
  188. package/dist/ports/stream-bus.js.map +1 -0
  189. package/dist/ports/vendor-file-cache.d.ts +46 -0
  190. package/dist/ports/vendor-file-cache.d.ts.map +1 -0
  191. package/dist/ports/vendor-file-cache.js +2 -0
  192. package/dist/ports/vendor-file-cache.js.map +1 -0
  193. package/dist/schema/agent-event.d.ts +35 -0
  194. package/dist/schema/agent-event.d.ts.map +1 -0
  195. package/dist/schema/agent-event.js +46 -0
  196. package/dist/schema/agent-event.js.map +1 -0
  197. package/dist/schema/agent-run.d.ts +23 -0
  198. package/dist/schema/agent-run.d.ts.map +1 -0
  199. package/dist/schema/agent-run.js +37 -0
  200. package/dist/schema/agent-run.js.map +1 -0
  201. package/dist/schema/index.d.ts +4 -0
  202. package/dist/schema/index.d.ts.map +1 -0
  203. package/dist/schema/index.js +4 -0
  204. package/dist/schema/index.js.map +1 -0
  205. package/dist/schema/message-part.d.ts +73 -0
  206. package/dist/schema/message-part.d.ts.map +1 -0
  207. package/dist/schema/message-part.js +90 -0
  208. package/dist/schema/message-part.js.map +1 -0
  209. package/dist/subagent/delegate.tool.d.ts +145 -0
  210. package/dist/subagent/delegate.tool.d.ts.map +1 -0
  211. package/dist/subagent/delegate.tool.js +329 -0
  212. package/dist/subagent/delegate.tool.js.map +1 -0
  213. package/dist/subagent/index.d.ts +10 -0
  214. package/dist/subagent/index.d.ts.map +1 -0
  215. package/dist/subagent/index.js +10 -0
  216. package/dist/subagent/index.js.map +1 -0
  217. package/dist/subagent/milestone-body.d.ts +82 -0
  218. package/dist/subagent/milestone-body.d.ts.map +1 -0
  219. package/dist/subagent/milestone-body.js +112 -0
  220. package/dist/subagent/milestone-body.js.map +1 -0
  221. package/dist/subagent/output-scan.d.ts +14 -0
  222. package/dist/subagent/output-scan.d.ts.map +1 -0
  223. package/dist/subagent/output-scan.js +41 -0
  224. package/dist/subagent/output-scan.js.map +1 -0
  225. package/dist/subagent/registry-spawn-policy.d.ts +32 -0
  226. package/dist/subagent/registry-spawn-policy.d.ts.map +1 -0
  227. package/dist/subagent/registry-spawn-policy.js +48 -0
  228. package/dist/subagent/registry-spawn-policy.js.map +1 -0
  229. package/dist/subagent/roster-block.d.ts +45 -0
  230. package/dist/subagent/roster-block.d.ts.map +1 -0
  231. package/dist/subagent/roster-block.js +69 -0
  232. package/dist/subagent/roster-block.js.map +1 -0
  233. package/dist/subagent/situation-block.d.ts +16 -0
  234. package/dist/subagent/situation-block.d.ts.map +1 -0
  235. package/dist/subagent/situation-block.js +71 -0
  236. package/dist/subagent/situation-block.js.map +1 -0
  237. package/dist/subagent/spawn-guards.d.ts +32 -0
  238. package/dist/subagent/spawn-guards.d.ts.map +1 -0
  239. package/dist/subagent/spawn-guards.js +39 -0
  240. package/dist/subagent/spawn-guards.js.map +1 -0
  241. package/dist/subagent/subagent-registry.d.ts +150 -0
  242. package/dist/subagent/subagent-registry.d.ts.map +1 -0
  243. package/dist/subagent/subagent-registry.js +167 -0
  244. package/dist/subagent/subagent-registry.js.map +1 -0
  245. package/dist/subagent/subagent-sessions.d.ts +213 -0
  246. package/dist/subagent/subagent-sessions.d.ts.map +1 -0
  247. package/dist/subagent/subagent-sessions.js +295 -0
  248. package/dist/subagent/subagent-sessions.js.map +1 -0
  249. package/dist/testing/contracts.d.ts +37 -0
  250. package/dist/testing/contracts.d.ts.map +1 -0
  251. package/dist/testing/contracts.js +607 -0
  252. package/dist/testing/contracts.js.map +1 -0
  253. package/dist/testing/index.d.ts +5 -0
  254. package/dist/testing/index.d.ts.map +1 -0
  255. package/dist/testing/index.js +5 -0
  256. package/dist/testing/index.js.map +1 -0
  257. package/dist/testing/stub.d.ts +28 -0
  258. package/dist/testing/stub.d.ts.map +1 -0
  259. package/dist/testing/stub.js +3 -0
  260. package/dist/testing/stub.js.map +1 -0
  261. package/dist/tools/agent-tool.base.d.ts +186 -0
  262. package/dist/tools/agent-tool.base.d.ts.map +1 -0
  263. package/dist/tools/agent-tool.base.js +243 -0
  264. package/dist/tools/agent-tool.base.js.map +1 -0
  265. package/dist/tools/agent-tool.interface.d.ts +95 -0
  266. package/dist/tools/agent-tool.interface.d.ts.map +1 -0
  267. package/dist/tools/agent-tool.interface.js +2 -0
  268. package/dist/tools/agent-tool.interface.js.map +1 -0
  269. package/dist/tools/builtin-names.d.ts +18 -0
  270. package/dist/tools/builtin-names.d.ts.map +1 -0
  271. package/dist/tools/builtin-names.js +20 -0
  272. package/dist/tools/builtin-names.js.map +1 -0
  273. package/dist/tools/index.d.ts +9 -0
  274. package/dist/tools/index.d.ts.map +1 -0
  275. package/dist/tools/index.js +6 -0
  276. package/dist/tools/index.js.map +1 -0
  277. package/dist/tools/tool-definition.d.ts +18 -0
  278. package/dist/tools/tool-definition.d.ts.map +1 -0
  279. package/dist/tools/tool-definition.js +77 -0
  280. package/dist/tools/tool-definition.js.map +1 -0
  281. package/dist/tools/tool-meta.d.ts +55 -0
  282. package/dist/tools/tool-meta.d.ts.map +1 -0
  283. package/dist/tools/tool-meta.js +2 -0
  284. package/dist/tools/tool-meta.js.map +1 -0
  285. package/dist/tools/tool-registry.d.ts +190 -0
  286. package/dist/tools/tool-registry.d.ts.map +1 -0
  287. package/dist/tools/tool-registry.js +379 -0
  288. package/dist/tools/tool-registry.js.map +1 -0
  289. package/dist/tools/tool-result.d.ts +41 -0
  290. package/dist/tools/tool-result.d.ts.map +1 -0
  291. package/dist/tools/tool-result.js +19 -0
  292. package/dist/tools/tool-result.js.map +1 -0
  293. package/dist/tools/tool-wire.d.ts +24 -0
  294. package/dist/tools/tool-wire.d.ts.map +1 -0
  295. package/dist/tools/tool-wire.js +2 -0
  296. package/dist/tools/tool-wire.js.map +1 -0
  297. package/dist/turn/agent-runtime.d.ts +31 -0
  298. package/dist/turn/agent-runtime.d.ts.map +1 -0
  299. package/dist/turn/agent-runtime.js +30 -0
  300. package/dist/turn/agent-runtime.js.map +1 -0
  301. package/dist/turn/chunk-projection.d.ts +32 -0
  302. package/dist/turn/chunk-projection.d.ts.map +1 -0
  303. package/dist/turn/chunk-projection.js +62 -0
  304. package/dist/turn/chunk-projection.js.map +1 -0
  305. package/dist/turn/compaction.d.ts +48 -0
  306. package/dist/turn/compaction.d.ts.map +1 -0
  307. package/dist/turn/compaction.js +89 -0
  308. package/dist/turn/compaction.js.map +1 -0
  309. package/dist/turn/context-overflow.d.ts +11 -0
  310. package/dist/turn/context-overflow.d.ts.map +1 -0
  311. package/dist/turn/context-overflow.js +53 -0
  312. package/dist/turn/context-overflow.js.map +1 -0
  313. package/dist/turn/context-pressure.d.ts +100 -0
  314. package/dist/turn/context-pressure.d.ts.map +1 -0
  315. package/dist/turn/context-pressure.js +21 -0
  316. package/dist/turn/context-pressure.js.map +1 -0
  317. package/dist/turn/events-to-steps.d.ts +8 -0
  318. package/dist/turn/events-to-steps.d.ts.map +1 -0
  319. package/dist/turn/events-to-steps.js +64 -0
  320. package/dist/turn/events-to-steps.js.map +1 -0
  321. package/dist/turn/index.d.ts +17 -0
  322. package/dist/turn/index.d.ts.map +1 -0
  323. package/dist/turn/index.js +16 -0
  324. package/dist/turn/index.js.map +1 -0
  325. package/dist/turn/json-preview.d.ts +22 -0
  326. package/dist/turn/json-preview.d.ts.map +1 -0
  327. package/dist/turn/json-preview.js +34 -0
  328. package/dist/turn/json-preview.js.map +1 -0
  329. package/dist/turn/json-string-field.d.ts +30 -0
  330. package/dist/turn/json-string-field.d.ts.map +1 -0
  331. package/dist/turn/json-string-field.js +125 -0
  332. package/dist/turn/json-string-field.js.map +1 -0
  333. package/dist/turn/loop-reminder.d.ts +79 -0
  334. package/dist/turn/loop-reminder.d.ts.map +1 -0
  335. package/dist/turn/loop-reminder.js +0 -0
  336. package/dist/turn/loop-reminder.js.map +1 -0
  337. package/dist/turn/nul-safe.d.ts +21 -0
  338. package/dist/turn/nul-safe.d.ts.map +1 -0
  339. package/dist/turn/nul-safe.js +23 -0
  340. package/dist/turn/nul-safe.js.map +1 -0
  341. package/dist/turn/parts-from-events.d.ts +71 -0
  342. package/dist/turn/parts-from-events.d.ts.map +1 -0
  343. package/dist/turn/parts-from-events.js +217 -0
  344. package/dist/turn/parts-from-events.js.map +1 -0
  345. package/dist/turn/parts-to-model-messages.d.ts +158 -0
  346. package/dist/turn/parts-to-model-messages.d.ts.map +1 -0
  347. package/dist/turn/parts-to-model-messages.js +334 -0
  348. package/dist/turn/parts-to-model-messages.js.map +1 -0
  349. package/dist/turn/pending-work.d.ts +10 -0
  350. package/dist/turn/pending-work.d.ts.map +1 -0
  351. package/dist/turn/pending-work.js +14 -0
  352. package/dist/turn/pending-work.js.map +1 -0
  353. package/dist/turn/provider-error.d.ts +45 -0
  354. package/dist/turn/provider-error.d.ts.map +1 -0
  355. package/dist/turn/provider-error.js +154 -0
  356. package/dist/turn/provider-error.js.map +1 -0
  357. package/dist/turn/tool-input-preview.d.ts +94 -0
  358. package/dist/turn/tool-input-preview.d.ts.map +1 -0
  359. package/dist/turn/tool-input-preview.js +143 -0
  360. package/dist/turn/tool-input-preview.js.map +1 -0
  361. package/dist/turn/tool-input-progress.d.ts +47 -0
  362. package/dist/turn/tool-input-progress.d.ts.map +1 -0
  363. package/dist/turn/tool-input-progress.js +50 -0
  364. package/dist/turn/tool-input-progress.js.map +1 -0
  365. package/dist/turn/turn-envelope.d.ts +184 -0
  366. package/dist/turn/turn-envelope.d.ts.map +1 -0
  367. package/dist/turn/turn-envelope.js +2 -0
  368. package/dist/turn/turn-envelope.js.map +1 -0
  369. package/dist/turn/turn-journal.d.ts +49 -0
  370. package/dist/turn/turn-journal.d.ts.map +1 -0
  371. package/dist/turn/turn-journal.js +51 -0
  372. package/dist/turn/turn-journal.js.map +1 -0
  373. package/dist/turn/turn-run.d.ts +487 -0
  374. package/dist/turn/turn-run.d.ts.map +1 -0
  375. package/dist/turn/turn-run.js +1167 -0
  376. package/dist/turn/turn-run.js.map +1 -0
  377. package/dist/turn/usage.d.ts +27 -0
  378. package/dist/turn/usage.d.ts.map +1 -0
  379. package/dist/turn/usage.js +51 -0
  380. package/dist/turn/usage.js.map +1 -0
  381. package/package.json +55 -3
  382. package/src/agent-extensions.ts +33 -0
  383. package/src/builtins/ask-outcome.ts +168 -0
  384. package/src/builtins/ask-schema.ts +186 -0
  385. package/src/builtins/ask.service.ts +482 -0
  386. package/src/builtins/ask.tool.ts +138 -0
  387. package/src/builtins/index.ts +25 -0
  388. package/src/builtins/todo-schema.ts +108 -0
  389. package/src/builtins/todo-settle.hook.ts +221 -0
  390. package/src/builtins/todo.tool.ts +134 -0
  391. package/src/context/context-budget-tracker.ts +519 -0
  392. package/src/context/context-budget.ts +124 -0
  393. package/src/context/index.ts +17 -0
  394. package/src/extensions/repeat-call.hook.ts +77 -0
  395. package/src/hooks/index.ts +19 -0
  396. package/src/hooks/turn-hook.registry.ts +307 -0
  397. package/src/hooks/turn-hook.types.ts +210 -0
  398. package/src/images/byte-cache.ts +61 -0
  399. package/src/images/delivery.ts +508 -0
  400. package/src/images/index.ts +35 -0
  401. package/src/images/prompt.ts +289 -0
  402. package/src/images/vendor-files.ts +235 -0
  403. package/src/in-process/conversation-store.ts +304 -0
  404. package/src/in-process/coordination.ts +177 -0
  405. package/src/in-process/image-source.ts +29 -0
  406. package/src/in-process/index.ts +52 -0
  407. package/src/in-process/question-store.ts +155 -0
  408. package/src/in-process/run-store.ts +115 -0
  409. package/src/in-process/session-store.ts +118 -0
  410. package/src/in-process/stream-bus.ts +244 -0
  411. package/src/in-process/vendor-file-cache.ts +67 -0
  412. package/src/index.ts +28 -0
  413. package/src/loop/active-tick.registry.ts +49 -0
  414. package/src/loop/index.ts +25 -0
  415. package/src/loop/loop-driver.ts +275 -0
  416. package/src/loop/message-hub.ts +532 -0
  417. package/src/loop/orphan-run.sweeper.ts +204 -0
  418. package/src/loop/root-host.ts +119 -0
  419. package/src/ports/context-store.ts +71 -0
  420. package/src/ports/conversation-store.ts +165 -0
  421. package/src/ports/coordination.ts +81 -0
  422. package/src/ports/image-source.ts +26 -0
  423. package/src/ports/index.ts +56 -0
  424. package/src/ports/logger.ts +34 -0
  425. package/src/ports/question-store.ts +117 -0
  426. package/src/ports/run-store.ts +69 -0
  427. package/src/ports/session-store.ts +80 -0
  428. package/src/ports/stream-bus.ts +59 -0
  429. package/src/ports/vendor-file-cache.ts +54 -0
  430. package/src/schema/agent-event.ts +69 -0
  431. package/src/schema/agent-run.ts +44 -0
  432. package/src/schema/index.ts +25 -0
  433. package/src/schema/message-part.ts +100 -0
  434. package/src/subagent/delegate.tool.ts +476 -0
  435. package/src/subagent/index.ts +63 -0
  436. package/src/subagent/milestone-body.ts +144 -0
  437. package/src/subagent/output-scan.ts +56 -0
  438. package/src/subagent/registry-spawn-policy.ts +85 -0
  439. package/src/subagent/roster-block.ts +103 -0
  440. package/src/subagent/situation-block.ts +83 -0
  441. package/src/subagent/spawn-guards.ts +54 -0
  442. package/src/subagent/subagent-registry.ts +283 -0
  443. package/src/subagent/subagent-sessions.ts +496 -0
  444. package/src/testing/contracts.ts +882 -0
  445. package/src/testing/index.ts +14 -0
  446. package/src/testing/stub.ts +28 -0
  447. package/src/tools/agent-tool.base.ts +361 -0
  448. package/src/tools/agent-tool.interface.ts +101 -0
  449. package/src/tools/builtin-names.ts +26 -0
  450. package/src/tools/index.ts +39 -0
  451. package/src/tools/tool-definition.ts +93 -0
  452. package/src/tools/tool-meta.ts +60 -0
  453. package/src/tools/tool-registry.ts +513 -0
  454. package/src/tools/tool-result.ts +45 -0
  455. package/src/tools/tool-wire.ts +24 -0
  456. package/src/turn/agent-runtime.ts +43 -0
  457. package/src/turn/chunk-projection.ts +81 -0
  458. package/src/turn/compaction.ts +103 -0
  459. package/src/turn/context-overflow.ts +54 -0
  460. package/src/turn/context-pressure.ts +114 -0
  461. package/src/turn/events-to-steps.ts +73 -0
  462. package/src/turn/index.ts +71 -0
  463. package/src/turn/json-preview.ts +36 -0
  464. package/src/turn/json-string-field.ts +134 -0
  465. package/src/turn/loop-reminder.ts +0 -0
  466. package/src/turn/nul-safe.ts +22 -0
  467. package/src/turn/parts-from-events.ts +248 -0
  468. package/src/turn/parts-to-model-messages.ts +428 -0
  469. package/src/turn/pending-work.ts +14 -0
  470. package/src/turn/provider-error.ts +160 -0
  471. package/src/turn/tool-input-preview.ts +223 -0
  472. package/src/turn/tool-input-progress.ts +76 -0
  473. package/src/turn/turn-envelope.ts +185 -0
  474. package/src/turn/turn-journal.ts +102 -0
  475. package/src/turn/turn-run.ts +1479 -0
  476. package/src/turn/usage.ts +56 -0
  477. package/README.md +0 -3
@@ -0,0 +1,14 @@
1
+ /**
2
+ * 测试辅助(`@qjp88995/agent-runtime/testing`):端口契约用例。需要 vitest(可选 peer)。
3
+ */
4
+ export {
5
+ describeQuestionStoreContract,
6
+ describeRunStoreContract,
7
+ describeSessionLockContract,
8
+ describeSessionStoreContract,
9
+ describeStreamBusContract,
10
+ describeSubagentAwaitLeaseContract,
11
+ describeTreeBudgetContract,
12
+ describeVendorFileCacheContract,
13
+ describeWakeChannelContract,
14
+ } from './contracts.js';
@@ -0,0 +1,28 @@
1
+ /**
2
+ * 部分实现的测试替身。
3
+ *
4
+ * 两条都要满足,所以拆成「`satisfies` 校验 + `asStub` 注入」两步:
5
+ *
6
+ * - **键名必须钉在 T 上**:`{ ... } satisfies Stub<T>` 对对象字面量会做多余属性
7
+ * 检查,把方法名打错(或 mock 一个已经改了名的方法)编译期就红。裸
8
+ * `as unknown as T` 完全不校验——那种 mock 永远不会被调用,测试照样绿。
9
+ * - **属性类型必须保持 `Mock`**:所以是 `satisfies` 而不是标注返回类型。标注成 T
10
+ * 会让每个属性解析回接口的 method signature,断言得套一层 `vi.mocked()`,读
11
+ * 引用还要挨 `@typescript-eslint/unbound-method`。
12
+ *
13
+ * ```ts
14
+ * function makeService() {
15
+ * return { list: vi.fn(), findById: vi.fn() } satisfies Stub<FooService>;
16
+ * }
17
+ * const svc = makeService();
18
+ * const ctrl = new FooController(asStub<FooService>(svc));
19
+ * expect(svc.list).toHaveBeenCalled(); // svc.list 是 Mock,不用 vi.mocked
20
+ * ```
21
+ *
22
+ * 替身实现了接口全部成员时直接 `satisfies FooService` 更强(连签名一起校验),
23
+ * `Stub` 是给「只实现被测路径用得到的那几个」准备的。
24
+ */
25
+ export type Stub<T> = Partial<Record<keyof T, unknown>>;
26
+
27
+ /** 把替身喂给期望真实类型的位置 —— 断言只发生在这一处。 */
28
+ export const asStub = <T>(stub: Stub<T>): T => stub as unknown as T;
@@ -0,0 +1,361 @@
1
+ import type { z } from 'zod';
2
+
3
+ import type { ToolResultImage } from '../schema/index.js';
4
+ import type { AgentToolProvider, ToolContext } from './agent-tool.interface.js';
5
+ import { toolError, type ToolOut } from './tool-result.js';
6
+
7
+ /**
8
+ * 后台受理结果 —— `run_in_background: true` 时 `execute` 的返回形状。
9
+ *
10
+ * 与 `ToolOut` 共用判别键 `kind`(三态 `ok`/`error`/`accepted` 互斥),
11
+ * 故调用方一次 switch 就能穷尽,不必先判「这是不是后台调用」。
12
+ */
13
+ export interface ToolAccepted {
14
+ kind: 'accepted';
15
+ /** 供模型后续引用这次后台任务(Delegate 用子会话 id)。 */
16
+ handle: string;
17
+ /**
18
+ * 为什么是后台受理而不是直接给结果。缺省(=调用方本来就要后台)不必填;
19
+ * 「本来要同步等、但等不到了」这类降级填一句,好让模型知道自己没拿到结果
20
+ * 不是因为它请求错了。
21
+ */
22
+ note?: string;
23
+ }
24
+
25
+ export function toolAccepted(handle: string, note?: string): ToolAccepted {
26
+ return note
27
+ ? { kind: 'accepted', handle, note }
28
+ : { kind: 'accepted', handle };
29
+ }
30
+
31
+ /** 重试策略。**默认不重试** —— 不声明就是不重试,见 `AgentTool.retry`。 */
32
+ export interface RetryPolicy {
33
+ /** 总尝试次数,含首次。2 = 首次 + 1 次重试。 */
34
+ maxAttempts: number;
35
+ /**
36
+ * 只有返回 true 的异常才重试。**没有缺省实现是有意的**:能不能重试取决于
37
+ * 这个工具在做什么(网络抖动可以,「找不到」重试一万次还是同一个答案),
38
+ * 基类无从判断,猜错的方向是把一次确定的失败变成 N 倍延迟。
39
+ */
40
+ isRetryable(err: unknown): boolean;
41
+ /** 首次退避毫秒,此后指数翻倍。缺省 200ms。 */
42
+ backoffMs?: number;
43
+ }
44
+
45
+ /** 供 `ToolRegistry` 读取的横切能力(protected 字段它够不着)。 */
46
+ export interface ToolCapabilities {
47
+ timeoutMs: number;
48
+ supportsBackground: boolean;
49
+ }
50
+
51
+ const DEFAULT_TIMEOUT_MS = 30_000;
52
+ const DEFAULT_BACKOFF_MS = 200;
53
+
54
+ /**
55
+ * 全部 agent 工具的基类。**新工具一律继承它,不要直接 implements
56
+ * `AgentToolProvider`** —— 那个接口现在只是基类对注册表的对外契约。
57
+ *
58
+ * ## 它替你做掉的四件事
59
+ *
60
+ * 1. **错误只有一个出口**。子类可以返回 `toolError(...)`,也可以直接抛(域错误、
61
+ * 库错误、意外异常都算),基类统一收编成 `{kind:'error'}`,再经同一条
62
+ * `toModelOutput` 渲染。改造前抛出的那条路径是**绕过 `toModelOutput`** 的
63
+ * ——注册表直接把 `err.message` 喂给模型,而域错误的 message 是写给 HTTP
64
+ * 调用方看的。同一个工具里两条错误路径给出两种质量的文案,正是当时
65
+ * `GetTwinEntry`/`SaveTwinPersona` 那批工具的形态。
66
+ * 2. **`render` 是抽象方法**。漏写是编译错误,不再静默退化成
67
+ * `JSON.stringify` ——那会把 markdown 正文的换行全转义成 `\n` 字面量。
68
+ * 3. **返回类型被钉死**。`execute` 由基类实现且返回 `ToolOut`,注册表内部信封
69
+ * `ok()/fail()` 的误用在类型层面不再可能(`LoadSkill` 曾为此坏过整整一轮:
70
+ * `fail()` 的外层 `ok:true` 让注册表以为调用成功,失败路径根本走不到)。
71
+ * 4. **超时 / 重试 / 后台运行**三个横切机制,子类只声明不实现。
72
+ *
73
+ * ## 三层的嵌套顺序
74
+ *
75
+ * ```
76
+ * 后台 ⊃ 重试 ⊃ 超时 ⊃ run()
77
+ * ```
78
+ *
79
+ * 即:每一次尝试各自计时,**超时本身可以被重试**(瞬态卡顿正是最值得重试的
80
+ * 一类);后台模式下这两层照常在后台生效。反过来把重试放进超时里,会让
81
+ * 「总时长」等于一个尝试的预算,第二次尝试注定跑不完。
82
+ */
83
+ export abstract class AgentTool<TInput, TData> implements AgentToolProvider<
84
+ TInput,
85
+ ToolOut<TData> | ToolAccepted
86
+ > {
87
+ abstract readonly inputSchema: z.ZodType<TInput>;
88
+
89
+ /**
90
+ * 工具正文。**子类实现这个,不是 `execute`**。
91
+ *
92
+ * 失败两种写法都行:返回 `toolError('...')`(措辞可控,首选),或直接抛
93
+ * (基类兜成 `toolError(this.describeError(err))`)。**只有抛出的那条会被
94
+ * 重试**——返回 `toolError` 是工具自己判定的确定性失败,重试没有意义。
95
+ *
96
+ * **也可以返回 `toolAccepted(handle)`**:一次同步调用完全可能中途决定「这个
97
+ * 等不下去了,转后台」(`Delegate` 的等待降级)。那不是失败 —— 用 error 表达
98
+ * 会让下游把一个正常在跑的任务显示成失败。
99
+ *
100
+ * `ctx.abortSignal` 已被基类替换成「用户中止 ∪ 本次超时」的合成信号:
101
+ * 长任务应当监听它并尽早返回,否则超时只能做到「不再等它」,工具本身会
102
+ * 变成没人要结果的幽灵任务继续跑。
103
+ */
104
+ protected abstract run(
105
+ input: TInput,
106
+ ctx: ToolContext
107
+ ): Promise<ToolOut<TData> | ToolAccepted>;
108
+
109
+ /**
110
+ * 成功结果 → 喂给模型的文本。**必须实现**。
111
+ *
112
+ * 长正文(markdown 规则、脚本样本、文件内容)一律**裸出**,不要包 JSON;
113
+ * 元数据用自然语言带一行。另外几条反复踩过的「沉默即误导」:抽样要报总数
114
+ * 与范围、多关键词查询要点名哪几个没匹配上、「零结果」与「搜不到」要分开、
115
+ * 写操作要说清副作用范围。
116
+ */
117
+ protected abstract render(out: { kind: 'ok' } & TData): string;
118
+
119
+ /** 单次尝试的超时。子类覆盖为字面量常量即可。 */
120
+ protected readonly timeoutMs: number = DEFAULT_TIMEOUT_MS;
121
+
122
+ /**
123
+ * 重试策略,**默认关闭**。
124
+ *
125
+ * 开之前先回答一个问题:这个工具重跑两次,效果和跑一次一样吗?`Write`/
126
+ * `Edit`/`CreateUser` 的答案都是否 —— 重试一次就是写两遍、
127
+ * 建两个账号,而调用方看到的仍然只是一次失败。
128
+ */
129
+ protected readonly retry: RetryPolicy | undefined = undefined;
130
+
131
+ /**
132
+ * 声明本工具接受 `run_in_background` 参数(由注册表注入 schema,子类的
133
+ * `inputSchema` 不要自己写它 —— 一个参数只能有一个定义处)。
134
+ *
135
+ * 默认 false:绝大多数工具跑几十毫秒,给它一个「要不要后台」的选项是纯
136
+ * 噪音,模型还得为此付 token 并可能选错。
137
+ */
138
+ protected readonly supportsBackground: boolean = false;
139
+
140
+ /**
141
+ * 后台运行的实现。`supportsBackground` 为 true 且调用方传了
142
+ * `run_in_background: true` 时走这里。
143
+ *
144
+ * **缺省是抛**,不是 fire-and-forget:一个「跑在进程内、没人追踪、重启即丢」
145
+ * 的后台任务是隐性的数据丢失,不该由基类默默提供给每一个后来者。今天唯一
146
+ * 支持后台的 `Delegate` 覆盖了它(子会话本就是持久化的,回投由 finalizer
147
+ * 负责)。将来第二个工具要用时,再据它的真实需求决定是进程内还是落队列。
148
+ */
149
+ protected runInBackground(
150
+ _input: TInput,
151
+ _ctx: ToolContext
152
+ ): Promise<ToolOut<TData> | ToolAccepted> {
153
+ return Promise.reject(
154
+ new Error('该工具声明了 supportsBackground 但未实现 runInBackground()')
155
+ );
156
+ }
157
+
158
+ /** 异常 → 给模型看的一句话。子类可覆盖以翻译自己的域错误。 */
159
+ protected describeError(err: unknown): string {
160
+ return err instanceof Error ? err.message : String(err);
161
+ }
162
+
163
+ /**
164
+ * 落库时随 tool-result part 一起存的**结构化引用**(`MessagePart.ref`)。
165
+ *
166
+ * 默认没有。只有当界面需要从一次工具调用里认出一个实体时才实现它,且**只放
167
+ * 认领所必需的最小信息** —— `output` 已经存了给人看的文本,这里再存一份结果
168
+ * 副本就是同一行里两份长正文。
169
+ */
170
+ protected persistRef(
171
+ _out: ToolOut<TData> | ToolAccepted
172
+ ): Record<string, unknown> | undefined {
173
+ return undefined;
174
+ }
175
+
176
+ /** 供注册表调用(`persistRef` 是 protected,它够不着)。 */
177
+ refFor(out: unknown): Record<string, unknown> | undefined {
178
+ return this.persistRef(out as ToolOut<TData> | ToolAccepted);
179
+ }
180
+
181
+ /**
182
+ * 落库时随 tool-result part 一起存、并交给**模型看**的图片
183
+ * (`MessagePart.images`)。默认没有。
184
+ *
185
+ * 形状照抄 `persistRef`/`refFor` 那一对,理由也一样:注册表在基类外面,
186
+ * protected 够不着。**不要把图塞进 `persistRef` 复用那条路**——`ref` 的约定是
187
+ * 「只放认领实体所必需的最小信息」,塞进去之后那句注释就不再成立。
188
+ *
189
+ * 实现者要保证 `src` 是存储中心对象 id(字节已固化)、`mediaType` 是完整
190
+ * 子类型——判据见 `ToolResultImageSchema` 各字段注释。
191
+ */
192
+ protected persistImages(
193
+ _out: ToolOut<TData> | ToolAccepted
194
+ ): ToolResultImage[] | undefined {
195
+ return undefined;
196
+ }
197
+
198
+ /** 供注册表调用(`persistImages` 是 protected,它够不着)。 */
199
+ imagesFor(out: unknown): ToolResultImage[] | undefined {
200
+ return this.persistImages(out as ToolOut<TData> | ToolAccepted);
201
+ }
202
+
203
+ /**
204
+ * 这次结果**不许被上下文裁剪换成存根**(落库进 `MessagePart.pinned`)。默认 false。
205
+ *
206
+ * 裁剪的前提是「正文是体积、丢了可以重跑」。只有两条都不满足的结果才该钉住——
207
+ * 当前唯一的用例是 `Ask`:一两句话,且是**用户做的决定**,裁掉之后
208
+ * 模型无从重新得知。**别把它当通用的「重要结果」开关**:`Read` 的结果再重要也能
209
+ * 重读。形状照抄 `persistRef`/`refFor`(注册表在基类外面,protected 够不着)。
210
+ */
211
+ protected persistPinned(_out: ToolOut<TData> | ToolAccepted): boolean {
212
+ return false;
213
+ }
214
+
215
+ /** 供注册表调用(`persistPinned` 是 protected,它够不着)。 */
216
+ pinnedFor(out: unknown): boolean {
217
+ return this.persistPinned(out as ToolOut<TData> | ToolAccepted);
218
+ }
219
+
220
+ /** 后台受理 → 给模型看的一句话。子类可覆盖。 */
221
+ protected renderAccepted(out: ToolAccepted): string {
222
+ return `任务已在后台启动(handle=${out.handle})。你不必等待,完成后结果会回到你这里。`;
223
+ }
224
+
225
+ /** 注册表读取横切能力用(`protected` 字段它够不着)。 */
226
+ get capabilities(): ToolCapabilities {
227
+ return {
228
+ timeoutMs: this.timeoutMs,
229
+ supportsBackground: this.supportsBackground,
230
+ };
231
+ }
232
+
233
+ /**
234
+ * 三层组装。**子类不要覆盖** —— 覆盖它就绕开了上面全部四件事。
235
+ *
236
+ * `run_in_background` 由注册表注入 schema,故它会混在 `input` 里到达这里;
237
+ * 取出后**从传给 `run()` 的对象里剥掉**,让子类的 `TInput` 保持干净(它没有
238
+ * 声明过这个字段,留着会让「这个参数归谁管」变得含糊)。
239
+ */
240
+ async execute(
241
+ input: TInput,
242
+ ctx: ToolContext
243
+ ): Promise<ToolOut<TData> | ToolAccepted> {
244
+ const { background, rest } = splitBackgroundFlag(input);
245
+ try {
246
+ if (background && this.supportsBackground) {
247
+ return await this.runInBackground(rest, ctx);
248
+ }
249
+ return await this.withRetry(rest, ctx);
250
+ } catch (err) {
251
+ return toolError(this.describeError(err));
252
+ }
253
+ }
254
+
255
+ /** 三态一次穷尽。基类实现,子类只写 `render`/`renderAccepted`。 */
256
+ toModelOutput(out: ToolOut<TData> | ToolAccepted): string {
257
+ switch (out.kind) {
258
+ case 'ok':
259
+ return this.render(out);
260
+ case 'accepted':
261
+ return this.renderAccepted(out);
262
+ case 'error':
263
+ return out.message;
264
+ }
265
+ }
266
+
267
+ private async withRetry(
268
+ input: TInput,
269
+ ctx: ToolContext
270
+ ): Promise<ToolOut<TData> | ToolAccepted> {
271
+ const policy = this.retry;
272
+ const maxAttempts = Math.max(1, policy?.maxAttempts ?? 1);
273
+ let lastErr: unknown;
274
+
275
+ for (let attempt = 1; attempt <= maxAttempts; attempt++) {
276
+ try {
277
+ return await this.withTimeout(input, ctx);
278
+ } catch (err) {
279
+ lastErr = err;
280
+ const canRetry =
281
+ policy !== undefined &&
282
+ attempt < maxAttempts &&
283
+ policy.isRetryable(err);
284
+ if (!canRetry) throw err;
285
+ // 用户中止时不再重试——那不是瞬态故障,是有人明确要求停下。
286
+ if (ctx.abortSignal.aborted) throw err;
287
+ const backoff =
288
+ (policy.backoffMs ?? DEFAULT_BACKOFF_MS) * 2 ** (attempt - 1);
289
+ await sleep(backoff, ctx.abortSignal);
290
+ }
291
+ }
292
+ throw lastErr;
293
+ }
294
+
295
+ /**
296
+ * 单次尝试的超时。**两道并用,不是重复**:合成 `AbortSignal` 让配合的工具
297
+ * 真正停下(这是改造前缺的那半),`Promise.race` 保证不配合的工具也拖不死
298
+ * 这一轮。
299
+ */
300
+ private async withTimeout(
301
+ input: TInput,
302
+ ctx: ToolContext
303
+ ): Promise<ToolOut<TData> | ToolAccepted> {
304
+ const timeoutMs = this.timeoutMs;
305
+ const ac = new AbortController();
306
+ const timer = setTimeout(() => ac.abort(), timeoutMs);
307
+ try {
308
+ const signal = AbortSignal.any([ctx.abortSignal, ac.signal]);
309
+ // 先把 run() 的两种结局都收敛成 resolve —— 否则 race 里 timeout 赢时
310
+ // run() 迟到的 rejection 无人接管,会冒成 unhandledRejection 打崩进程。
311
+ const work = this.run(input, { ...ctx, abortSignal: signal }).then(
312
+ out => ({ ok: true as const, out }),
313
+ (err: unknown) => ({ ok: false as const, err })
314
+ );
315
+ const timeout = new Promise<'timeout'>(resolve => {
316
+ ac.signal.addEventListener('abort', () => resolve('timeout'), {
317
+ once: true,
318
+ });
319
+ });
320
+ const raced = await Promise.race([work, timeout]);
321
+ if (raced === 'timeout') {
322
+ return toolError(`工具执行超过 ${timeoutMs}ms 未返回`);
323
+ }
324
+ if (!raced.ok) throw raced.err;
325
+ return raced.out;
326
+ } finally {
327
+ clearTimeout(timer);
328
+ }
329
+ }
330
+ }
331
+
332
+ /**
333
+ * 剥出注册表注入的 `run_in_background`。
334
+ *
335
+ * 键名是 snake_case、与本仓其余 camelCase 参数不一致,那是**有意**对齐
336
+ * Claude Code 的同名参数——理由与工具名用 PascalCase 是同一条:模型在训练
337
+ * 语料里见过海量样本,工具调用准确率是实打实的收益。因为它只在这里和注册表
338
+ * 注入处出现两次,不会扩散成两套命名风格。
339
+ */
340
+ function splitBackgroundFlag<TInput>(input: TInput): {
341
+ background: boolean;
342
+ rest: TInput;
343
+ } {
344
+ if (input === null || typeof input !== 'object') {
345
+ return { background: false, rest: input };
346
+ }
347
+ const { run_in_background: flag, ...rest } = input as Record<string, unknown>;
348
+ return { background: flag === true, rest: rest as TInput };
349
+ }
350
+
351
+ function sleep(ms: number, signal: AbortSignal): Promise<void> {
352
+ return new Promise(resolve => {
353
+ const timer = setTimeout(done, ms);
354
+ signal.addEventListener('abort', done, { once: true });
355
+ function done(): void {
356
+ clearTimeout(timer);
357
+ signal.removeEventListener('abort', done);
358
+ resolve();
359
+ }
360
+ });
361
+ }
@@ -0,0 +1,101 @@
1
+ import type { z } from 'zod';
2
+
3
+ import type { AgentExtensions } from '../agent-extensions.js';
4
+ import type { MessagePart } from '../schema/index.js';
5
+
6
+ /** 工具执行上下文。刻意不含任何渠道概念(本项目单渠道)。 */
7
+ export interface ToolContext {
8
+ /** 当前 agent_run 的 id。 */
9
+ runId: string;
10
+ /** 根 turn 的 id,跨父子共享。 */
11
+ streamId: string;
12
+ /** 根会话 id —— agent 产物库的树级作用域键(pre-1b:= sessionId)。 */
13
+ rootSessionId: string;
14
+ /** 当前 loop 的会话 id —— 产物 writer 审计。 */
15
+ sessionId: string;
16
+ /** 发起者,可空(系统触发时)。 */
17
+ userId: string | null;
18
+ /**
19
+ * 跑的是哪个 agent:`id` 与模型能力之外,全是宿主经 `AgentExtensions` 加的字段
20
+ * (随本轮所跑的那一版配置下来,工具不必再查库)。
21
+ */
22
+ agent: ToolAgentContext;
23
+ /**
24
+ * 会话上的不透明附加信息(宿主写、宿主的工具读,内核不解释;派子 Agent 时子会话继承)。
25
+ * 缺省空对象。
26
+ */
27
+ sessionMetadata: Readonly<Record<string, unknown>>;
28
+ /** subagent 深度,根为 0。 */
29
+ depth: number;
30
+ /**
31
+ * 本轮发起人此刻的权限点(`Initiator.permissions`)。**可选、缺省按空**:只给「派不派得出
32
+ * 要权限点的内置子 Agent」这类判据用——**不是工具权限的门**,要权限的工具各自现查。
33
+ */
34
+ initiatorPermissions?: ReadonlySet<string>;
35
+ /** 同一轮内可变:前一个工具的修改对后续工具可见。 */
36
+ metadata: Record<string, unknown>;
37
+ abortSignal: AbortSignal;
38
+ toolCallId: string;
39
+ /**
40
+ * 异步工具的回投通道:绑定到**当前会话**(`sessionId`),由宿主实现
41
+ * (投进 inbox + 唤醒会话)。
42
+ * 供 async 工具的后台段(execute 返回受理占位后 fire-and-forget 的部分)
43
+ * 把真结果投回 inbox,由下一轮 drain 拾取。
44
+ */
45
+ postToInbox?: (input: {
46
+ kind: 'user_message' | 'tool_result';
47
+ source?: Record<string, unknown>;
48
+ parts: MessagePart[];
49
+ }) => Promise<void>;
50
+ }
51
+
52
+ /** `ToolContext.agent`:agent id、本轮模型能力,加上宿主的扩展字段。 */
53
+ export type ToolAgentContext = {
54
+ /** agent 的 id(宿主定义;内置形式可以是名字)。 */
55
+ id: string;
56
+ /**
57
+ * 本轮模型标了哪些能力(模型目录里的能力名)。`Delegate` 据此拒绝派一个替「自己已有的
58
+ * 能力」顶替的子 Agent。缺省空数组。
59
+ */
60
+ modelCapabilities: readonly string[];
61
+ } & AgentExtensions;
62
+
63
+ /** `AgentToolProvider.isAvailable` / `describe` 看得到的那份 agent 配置(宿主的扩展字段)。 */
64
+ export type ToolAvailabilityView = AgentExtensions;
65
+
66
+ /**
67
+ * 工具实现契约。Provider 永不 import 'ai' —— 由 ToolRegistry
68
+ * 负责包成 AI SDK 的 tool()。这个解耦让工具层不受 SDK 版本影响。
69
+ */
70
+ export interface AgentToolProvider<TInput = unknown, TOutput = unknown> {
71
+ readonly inputSchema: z.ZodType<TInput>;
72
+ execute(input: TInput, ctx: ToolContext): Promise<TOutput>;
73
+ /**
74
+ * 结构化结果 → 喂模型的文本。缺省直接序列化整个结果。
75
+ * 双轨的落点:结构化那份落库/发 SSE,只有这里返回的进模型上下文。
76
+ */
77
+ toModelOutput?(output: TOutput): string;
78
+ /**
79
+ * 这一轮能不能用(缺省 = 能)。不能用就从本轮工具集摘掉(`unavailableToolNames`
80
+ * → loop 的摘除清单),而不是端上桌让模型调一次、收回一句「未配置」,还在自述
81
+ * 能力时承诺做不到的事。判据写在工具自己身上:部署级开关(取数账号配没配)、
82
+ * agent 级配置(联网服务选没选)都由工具回答,loop 一个具体工具名都不必认识。
83
+ *
84
+ * **这不是门**:工具里的判空 / 拒绝照留,这里只决定端不端上桌。每轮现问,不在
85
+ * 启动时快照——开关由别的 provider 的 `onModuleInit` 决定。可以是异步的(WebFetch
86
+ * 要查一次联网服务是哪家:有的家没有读网页接口),但答案必须在相邻两轮之间稳定——
87
+ * 工具表一变,前缀缓存整段 miss。
88
+ */
89
+ isAvailable?(agent: ToolAvailabilityView): boolean | Promise<boolean>;
90
+ /**
91
+ * 这份 agent 配置下的工具说明(缺省或返回 `null` = 装饰器里的 `description`)。给「说明要跟着
92
+ * 配置走」的工具用:WebSearch / WebFetch 的说明由所选联网服务的适配器追加或替换。每轮现问,
93
+ * 与 `isAvailable` 同时机;loop 与「下一轮预览」用同一份(`ToolRegistry.descriptionsFor`)。
94
+ *
95
+ * 答案进工具表:**只许随配置变**(管理员改了配置,相邻两轮才可以不同),别掺按「现在」算的东西——
96
+ * 工具表一变,前缀缓存整段 miss。
97
+ */
98
+ describe?(
99
+ agent: ToolAvailabilityView
100
+ ): string | null | Promise<string | null>;
101
+ }
@@ -0,0 +1,26 @@
1
+ /**
2
+ * runtime 自带的三个通用工具的名字。**前后端、宿主都从这里取,别各写各的字面量**——
3
+ * 名字对不上时不报错也不告警,只是界面上某块静默空着(待办面板、提问卡片、子 Agent 卡)。
4
+ *
5
+ * 2026-11-11 改成单个动词(原名是 agent-base 的 `SpawnAgent` / `TodoWrite` /
6
+ * `AskUserQuestion`)。旧名登记为 `formerNames`:库里的旧历史照常以现名投影给模型
7
+ * (`ToolRegistry.toolNameAliases`),宿主前端从历史里认这几个工具时也要认旧名
8
+ * (`isToolNamed`)。
9
+ */
10
+ export const DELEGATE_TOOL_NAME = 'Delegate';
11
+ export const DELEGATE_FORMER_NAMES = ['SpawnAgent'] as const;
12
+
13
+ export const TODO_TOOL_NAME = 'Todo';
14
+ export const TODO_FORMER_NAMES = ['TodoWrite'] as const;
15
+
16
+ export const ASK_TOOL_NAME = 'Ask';
17
+ export const ASK_FORMER_NAMES = ['AskUserQuestion'] as const;
18
+
19
+ /** `name` 是不是这个工具(现名或任一旧名)。前端从历史里认工具用。 */
20
+ export function isToolNamed(
21
+ name: string,
22
+ current: string,
23
+ former: readonly string[]
24
+ ): boolean {
25
+ return name === current || former.includes(name);
26
+ }
@@ -0,0 +1,39 @@
1
+ export {
2
+ AgentTool,
3
+ type RetryPolicy,
4
+ type ToolAccepted,
5
+ toolAccepted,
6
+ type ToolCapabilities,
7
+ } from './agent-tool.base.js';
8
+ export type {
9
+ AgentToolProvider,
10
+ ToolAgentContext,
11
+ ToolAvailabilityView,
12
+ ToolContext,
13
+ } from './agent-tool.interface.js';
14
+ export {
15
+ ASK_FORMER_NAMES,
16
+ ASK_TOOL_NAME,
17
+ DELEGATE_FORMER_NAMES,
18
+ DELEGATE_TOOL_NAME,
19
+ isToolNamed,
20
+ TODO_FORMER_NAMES,
21
+ TODO_TOOL_NAME,
22
+ } from './builtin-names.js';
23
+ export { digestInputSchema, type SchemaDigest } from './tool-definition.js';
24
+ export type { ToolMeta } from './tool-meta.js';
25
+ export {
26
+ type ToolAgentView,
27
+ ToolRegistry,
28
+ type ToolRegistryOptions,
29
+ type ToolSetOptions,
30
+ } from './tool-registry.js';
31
+ export {
32
+ fail,
33
+ ok,
34
+ safe,
35
+ toolError,
36
+ type ToolOut,
37
+ type ToolResult,
38
+ } from './tool-result.js';
39
+ export type { ToolDefinitionWire, ToolParamWire } from './tool-wire.js';
@@ -0,0 +1,93 @@
1
+ import { z } from 'zod';
2
+
3
+ import type { ToolParamWire } from './tool-wire.js';
4
+
5
+ /** `digestInputSchema` 的产物:参数表 + 摊不平时的说明。 */
6
+ export interface SchemaDigest {
7
+ params: ToolParamWire[];
8
+ schemaNote: string | null;
9
+ }
10
+
11
+ /**
12
+ * 把工具的 zod inputSchema 摊平成后台「工具列表」页的参数表。
13
+ *
14
+ * 走 `z.toJSONSchema`(`unrepresentable: 'any'`——遇到表示不了的类型退化成
15
+ * any,不抛)再取顶层 properties。工具入参在本仓约定就是 `z.object`,非对象
16
+ * 结构(如测试 stub 的 `z.unknown()`)不硬摊,如实给一句说明。
17
+ *
18
+ * **绝不抛**:这是展示路径,一个工具的 schema 转不动不该拖垮整张列表。
19
+ */
20
+ export function digestInputSchema(schema: z.ZodType): SchemaDigest {
21
+ let json: Record<string, unknown>;
22
+ try {
23
+ json = z.toJSONSchema(schema, {
24
+ unrepresentable: 'any',
25
+ io: 'input',
26
+ });
27
+ } catch (err) {
28
+ return {
29
+ params: [],
30
+ schemaNote: `schema 转换失败:${err instanceof Error ? err.message : String(err)}`,
31
+ };
32
+ }
33
+
34
+ const properties = json.properties;
35
+ if (
36
+ json.type !== 'object' ||
37
+ typeof properties !== 'object' ||
38
+ properties === null
39
+ ) {
40
+ return {
41
+ params: [],
42
+ schemaNote: `入参不是对象结构:${JSON.stringify(json)}`,
43
+ };
44
+ }
45
+
46
+ const required = new Set(
47
+ Array.isArray(json.required) ? (json.required as string[]) : []
48
+ );
49
+ const params = Object.entries(properties as Record<string, unknown>).map(
50
+ ([key, prop]) => ({
51
+ key,
52
+ type: typeLabel(prop),
53
+ required: required.has(key),
54
+ description: descriptionOf(prop),
55
+ })
56
+ );
57
+ return { params, schemaNote: null };
58
+ }
59
+
60
+ function descriptionOf(prop: unknown): string | null {
61
+ if (typeof prop !== 'object' || prop === null) return null;
62
+ const d = (prop as { description?: unknown }).description;
63
+ return typeof d === 'string' ? d : null;
64
+ }
65
+
66
+ /**
67
+ * JSON schema 片段 → 人读的类型标签。尽力而为:认不出的形状退化成 JSON 原文
68
+ * ——比一个笼统的 any 有信息量(那正是要审阅的东西)。
69
+ */
70
+ function typeLabel(prop: unknown): string {
71
+ if (typeof prop !== 'object' || prop === null) return 'any';
72
+ const p = prop as Record<string, unknown>;
73
+
74
+ if (Array.isArray(p.enum)) {
75
+ return p.enum.map(v => JSON.stringify(v)).join(' | ');
76
+ }
77
+ if (Array.isArray(p.anyOf)) {
78
+ return (p.anyOf as unknown[]).map(typeLabel).join(' | ');
79
+ }
80
+ if (p.type === 'array') {
81
+ return `${typeLabel(p.items)}[]`;
82
+ }
83
+ if (Array.isArray(p.type)) {
84
+ return (p.type as unknown[]).join(' | ');
85
+ }
86
+ if (typeof p.type === 'string') {
87
+ return p.format === 'uuid' ? `${p.type}(uuid)` : p.type;
88
+ }
89
+ // 空对象 = 任意值(z.unknown / unrepresentable 退化);其余原样亮出来。
90
+ return Object.keys(p).filter(k => k !== 'description').length === 0
91
+ ? 'any'
92
+ : JSON.stringify(p);
93
+ }