@qjp88995/agent-runtime 0.0.0-stage → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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 +59 -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,100 @@
1
+ import { z } from 'zod';
2
+
3
+ /**
4
+ * 落库消息的数据模型。搬自 agent-base `@ab/shared` 的 `schemas/agent.ts`(2026-11-11),
5
+ * 判据注释保留要点;改动:`ToolResultImage.src` 从 uuid 放宽为不透明字符串
6
+ * (字节存哪由宿主的 `ImageSource` 端口决定,runtime 不认识存储中心)。
7
+ *
8
+ * 刻意与 AI SDK 的 UIMessage.parts 不同:tool-call 与 tool-result 拆成两个 part
9
+ * (SDK 是合并态的 `tool-${name}`)。拆分格式厂商无关、不受 SDK 版本内部形状变化影响。
10
+ */
11
+
12
+ /**
13
+ * 一张交给模型看的图(tool-result part 的 `images[]` 元素)。
14
+ *
15
+ * 库里只有 `src`,没有字节:投影层按它发一个引用,字节在请求前由图片递送解析
16
+ * (Files API / 公网 URL / base64 三档)。「模型看得见的一切都必须能从库里重建」,
17
+ * 所以 `src` 指向的内容必须不可变(换内容就是新的 `src`)。
18
+ */
19
+ export const ToolResultImageSchema = z.object({
20
+ /** 字节的不可变身份(内容寻址的对象 id 等),由宿主的 `ImageSource` 解析。 */
21
+ src: z.string().min(1),
22
+ /** **完整子类型**(`image/jpeg`),不是顶层段 `image`。 */
23
+ mediaType: z.string(),
24
+ /** 进入对话那一刻在工作区的路径(之后可能被移走,只作提示)。 */
25
+ path: z.string().optional(),
26
+ /** 归一化后的字节数。 */
27
+ bytes: z.number().int().nonnegative().optional(),
28
+ /** 归一化后的像素尺寸。 */
29
+ width: z.number().int().positive().optional(),
30
+ height: z.number().int().positive().optional(),
31
+ /** 原始像素尺寸 `"3000x2000"`,**只在真的缩过时写**(模型据此换算坐标)。 */
32
+ origin: z.string().optional(),
33
+ });
34
+ export type ToolResultImage = z.infer<typeof ToolResultImageSchema>;
35
+
36
+ /** 落库 part 上的厂商 metadata:与 providerOptions 同形(命名空间 → JSON 对象)。 */
37
+ export const PartProviderMetadataSchema = z.record(
38
+ z.string(),
39
+ z.record(z.string(), z.json())
40
+ );
41
+ export type PartProviderMetadata = z.infer<typeof PartProviderMetadataSchema>;
42
+
43
+ export const MessagePartSchema = z.discriminatedUnion('type', [
44
+ z.object({ type: z.literal('text'), text: z.string() }),
45
+ z.object({
46
+ type: z.literal('reasoning'),
47
+ text: z.string(),
48
+ /**
49
+ * 这一段思考产出了多久(毫秒):第一个 `reasoning-delta` 到最后一个。
50
+ * 不取「请求发出」为起点(那段里有网络与排队)。可空:拿不到时间的路径没有它。
51
+ */
52
+ durationMs: z.number().int().nonnegative().optional(),
53
+ }),
54
+ z.object({
55
+ type: z.literal('tool-call'),
56
+ toolCallId: z.string(),
57
+ toolName: z.string(),
58
+ input: z.unknown(),
59
+ /**
60
+ * 厂商要求原样回传的不透明数据(Gemini 的思考签名),重放时作为这条 tool-call 的
61
+ * `providerOptions` 发回。**只存模型句柄 `replayedMetadataKeys` 声明的命名空间**:
62
+ * 别家的 metadata 原样回放会改变它们的请求形状。
63
+ */
64
+ providerMetadata: PartProviderMetadataSchema.optional(),
65
+ }),
66
+ z.object({
67
+ type: z.literal('tool-result'),
68
+ toolCallId: z.string(),
69
+ toolName: z.string(),
70
+ /** **渲染后的文本**(给人看,也是给模型看的那份),不存结构化结果。 */
71
+ output: z.unknown(),
72
+ isError: z.boolean().optional(),
73
+ /**
74
+ * 平台针对这一次调用追加的系统提示(如重复调用提醒)。与 `output` 分开存,
75
+ * 拼接只在投影期发生;不影响 `isError`。
76
+ */
77
+ systemNote: z.string().optional(),
78
+ /** 给程序认领实体用的最小结构化引用(如子 Agent 的会话 handle),由工具提供。 */
79
+ ref: z.record(z.string(), z.unknown()).optional(),
80
+ /** 这次调用交给模型看的图片(只有 `src`,见 `ToolResultImageSchema`)。 */
81
+ images: z.array(ToolResultImageSchema).optional(),
82
+ /**
83
+ * 上下文裁剪**不许**把这条结果的正文换成存根(如用户对提问的回答:短、且丢了
84
+ * 无从重得)。由工具声明,随结果落库。整行压缩不受它约束。
85
+ */
86
+ pinned: z.boolean().optional(),
87
+ }),
88
+ ]);
89
+ export type MessagePart = z.infer<typeof MessagePartSchema>;
90
+
91
+ /**
92
+ * 宿主往会话里塞的几种 user 行的标记(写在消息行 metadata 的 `kind` 上)。
93
+ * 落库存纯正文,围栏只在投影期拼;前端按它渲成系统标记而不是用户气泡。
94
+ */
95
+ /** 上下文压缩产生的 checkpoint 行。 */
96
+ export const COMPACTION_CHECKPOINT_KIND = 'compaction-checkpoint';
97
+ /** 旧式重复调用提醒行(新的挂在 tool-result 的 `systemNote` 上;历史行仍要认得)。 */
98
+ export const LOOP_REMINDER_KIND = 'loop-reminder';
99
+ /** 待办结账提醒行。 */
100
+ export const TODO_REMINDER_KIND = 'todo-reminder';
@@ -0,0 +1,476 @@
1
+ import { z } from 'zod';
2
+
3
+ import {
4
+ AWAIT_RENEW_INTERVAL_MS,
5
+ type SubagentAwaitLease,
6
+ } from '../ports/coordination.js';
7
+ import {
8
+ type Logger,
9
+ type LoggerFactory,
10
+ silentLogger,
11
+ } from '../ports/logger.js';
12
+ import {
13
+ AgentTool,
14
+ type ToolAccepted,
15
+ toolAccepted,
16
+ } from '../tools/agent-tool.base.js';
17
+ import type { ToolContext } from '../tools/agent-tool.interface.js';
18
+ import {
19
+ DELEGATE_FORMER_NAMES,
20
+ DELEGATE_TOOL_NAME,
21
+ } from '../tools/builtin-names.js';
22
+ import type { ToolMeta } from '../tools/tool-meta.js';
23
+ import type { ToolRegistry } from '../tools/tool-registry.js';
24
+ import { toolError, type ToolOut } from '../tools/tool-result.js';
25
+ import { wrapSubagentResult } from './milestone-body.js';
26
+ import {
27
+ canSpawnDeeper,
28
+ DEPTH_EXHAUSTED_HINT,
29
+ MAX_SUBAGENT_DEPTH,
30
+ treeFullHint,
31
+ } from './spawn-guards.js';
32
+ import type { SubagentSessions } from './subagent-sessions.js';
33
+
34
+ /**
35
+ * 同步等待缺省上限。**到点不算失败**:父放弃等待、拿到 handle,子照常跑完并把结论回投
36
+ * inbox。选小了的代价是「同步退化成异步」,不是丢结果——它只在子真的卡死时把父放出来
37
+ * (兜底扫描只在启动时跑,不设上限的话父就陪着泄漏的子一起挂到重启)。
38
+ */
39
+ export const DELEGATE_SYNC_WAIT_MS = 30 * 60_000;
40
+
41
+ /** 轮询间隔。判据是子会话行上的游标,一次读而已。 */
42
+ export const DELEGATE_POLL_INTERVAL_MS = 1_500;
43
+
44
+ const InputSchema = z.object({
45
+ agentType: z
46
+ .string()
47
+ .optional()
48
+ .describe(
49
+ '**派生新的**子 Agent 时填:子 Agent 名称,取自 system prompt 里' +
50
+ '【可派生的子 Agent】列表。与 handle 二选一,不要同时给。'
51
+ ),
52
+ handle: z
53
+ .string()
54
+ .optional()
55
+ .describe(
56
+ '给**已经派生过的**子 Agent 追加任务时填:本工具当初返回给你的那个 handle。' +
57
+ '它会带着你们之前的全部往来继续做事,适合修改/补充/换个角度重做。' +
58
+ '与 agentType 二选一,不要同时给;只能是你自己派生过的子 Agent。'
59
+ ),
60
+ title: z
61
+ .string()
62
+ .min(1)
63
+ .max(80)
64
+ .describe(
65
+ '一句话任务标题(≤80 字),概括这次要它做什么,用于界面展示。' +
66
+ '例如「调研 Claude Code 的读前写机制」「把第三段压到 200 字」。'
67
+ ),
68
+ prompt: z
69
+ .string()
70
+ .min(1)
71
+ .describe(
72
+ '这次交给它的任务。**派生新的**子 Agent 时它看不到你的对话历史,所有必要' +
73
+ '背景都要写进来;**追加任务**时它记得你们之前的往来(包括它自己交付过的' +
74
+ '内容),只写这次要改什么、为什么,不要把它上次的产出重新粘一遍。'
75
+ ),
76
+ });
77
+ type Input = z.infer<typeof InputSchema>;
78
+
79
+ /**
80
+ * 同步模式的返回:子 Agent 这一轮的完整产出。与回投 inbox 的那份**同源**
81
+ * (`SubagentSessions.buildResult`),包括中和处理。
82
+ */
83
+ interface Out {
84
+ handle: string;
85
+ body: string;
86
+ status: string;
87
+ stopReason: string | null;
88
+ /** 宿主在派生时给的说明(`SpawnPolicy.onSubagentCreated`),拼在回执最前面。只在有时出现。 */
89
+ notes?: string[];
90
+ }
91
+
92
+ /** 后台受理的回执也要带上派生时的说明。 */
93
+ type DelegateAccepted = ToolAccepted & { notes?: string[] };
94
+
95
+ type Started =
96
+ | {
97
+ kind: 'ok';
98
+ handle: string;
99
+ cursorBefore: number | null;
100
+ leased: boolean;
101
+ notes?: string[];
102
+ }
103
+ | { kind: 'error'; message: string };
104
+
105
+ function minutesText(ms: number): string {
106
+ const minutes = ms / 60_000;
107
+ return Number.isInteger(minutes) ? `${minutes} 分钟` : `${ms / 1000} 秒`;
108
+ }
109
+
110
+ /** `Delegate` 的登记信息(说明里的等待上限随入参)。 */
111
+ export function delegateToolMeta(
112
+ syncWaitMs: number = DELEGATE_SYNC_WAIT_MS
113
+ ): ToolMeta {
114
+ return {
115
+ name: DELEGATE_TOOL_NAME,
116
+ formerNames: DELEGATE_FORMER_NAMES,
117
+ description:
118
+ '把一段子任务交给子 Agent 独立完成。**派生一个新的**就给 agentType;' +
119
+ '**让之前派生过的那个继续做事**(修改、补充、换个角度重做)就给它的 handle,' +
120
+ '它记得你们之前的全部往来,不必重复背景。' +
121
+ `**默认同步等待并直接返回这一轮的产出**(最长等 ${minutesText(syncWaitMs)},` +
122
+ '超时自动转为后台并返回 handle);' +
123
+ '需要同时推进多件事时传 run_in_background: true,届时立即拿到 handle,' +
124
+ '结论稍后作为一条新消息回到你的上下文。' +
125
+ '注意同一步里发多个同步调用会**依次**等待(工具是串行执行的),' +
126
+ '要并行就用 run_in_background。' +
127
+ '新派生的子 Agent 完全看不到你的对话历史,任务描述必须自包含。' +
128
+ '**子 Agent 交回来的东西不一定是最终结论**:它信息不够时会把「已确定的部分 + 卡在哪 + ' +
129
+ '还需要什么」交回来等你补充——这种情况用它的 handle 把缺的信息告诉它,它接着往下做。',
130
+ category: 'system',
131
+ };
132
+ }
133
+
134
+ export interface DelegateToolDeps {
135
+ subagents: SubagentSessions;
136
+ awaitLease: SubagentAwaitLease;
137
+ /** 缺省 `DELEGATE_SYNC_WAIT_MS`。 */
138
+ syncWaitMs?: number;
139
+ /** 缺省 `DELEGATE_POLL_INTERVAL_MS`。 */
140
+ pollIntervalMs?: number;
141
+ /** 租约续租间隔,缺省 `AWAIT_RENEW_INTERVAL_MS`。 */
142
+ renewIntervalMs?: number;
143
+ /** 深度上限,缺省 `MAX_SUBAGENT_DEPTH`(与 `canDelegate` 用同一个值)。 */
144
+ maxDepth?: number;
145
+ logger?: LoggerFactory;
146
+ }
147
+
148
+ /**
149
+ * 子 Agent 的唯一入口(原 agent-base `SpawnAgent`):**派生一个新的**(给 `agentType`),
150
+ * 或**给已经派生过的追加任务**(给 `handle`)。一个工具、一个参数区分。
151
+ *
152
+ * 两种模式的分歧只在起跑段(新建:问宿主、占名额、建会话;追加:校验归属、投一条消息),
153
+ * 之后完全一样——等子跑到 idle 终态、取这一轮的产出、包围栏、等不到就降级转后台。
154
+ *
155
+ * 追加任务不是「重新派生一个」:子会话的完整历史都在,重新派生等于让一个全新的子从零读
156
+ * 一遍需求、父还得把初稿全文复述给它。
157
+ *
158
+ * 同步与异步是同一条实现:子会话都是独立持久跑的(会话行 + inbox + loop + 兜底扫描),
159
+ * 区别只在父等不等。所以这里覆盖 `runInBackground`,不用基类那个进程内 fire-and-forget
160
+ * (重启即丢)。
161
+ */
162
+ export class DelegateTool extends AgentTool<Input, Out> {
163
+ readonly inputSchema = InputSchema;
164
+
165
+ protected override readonly supportsBackground = true;
166
+
167
+ /**
168
+ * 比同步等待上限大一档:等待器到点会走**优雅降级**(返回 handle,告诉模型转后台了),
169
+ * 基类那道 race 只会给一句没信息量的超时,还把子的结果变成孤儿。这一层赢了说明等待器
170
+ * 自己有 bug。
171
+ */
172
+ protected override readonly timeoutMs: number;
173
+
174
+ private readonly logger: Logger;
175
+ private readonly syncWaitMs: number;
176
+ private readonly pollIntervalMs: number;
177
+ private readonly renewIntervalMs: number;
178
+ private readonly maxDepth: number;
179
+
180
+ constructor(private readonly deps: DelegateToolDeps) {
181
+ super();
182
+ this.syncWaitMs = deps.syncWaitMs ?? DELEGATE_SYNC_WAIT_MS;
183
+ this.pollIntervalMs = deps.pollIntervalMs ?? DELEGATE_POLL_INTERVAL_MS;
184
+ this.renewIntervalMs = deps.renewIntervalMs ?? AWAIT_RENEW_INTERVAL_MS;
185
+ this.maxDepth = deps.maxDepth ?? MAX_SUBAGENT_DEPTH;
186
+ this.timeoutMs = this.syncWaitMs + 60_000;
187
+ this.logger = (deps.logger ?? silentLogger)('DelegateTool');
188
+ }
189
+
190
+ /** 同步:让子跑起来 → 等它到达 idle 终态 → 返回这一轮的产出。 */
191
+ protected async run(
192
+ input: Input,
193
+ ctx: ToolContext
194
+ ): Promise<ToolOut<Out> | ToolAccepted> {
195
+ const started = await this.start(input, ctx, { lease: true });
196
+ if (started.kind !== 'ok') return started;
197
+ const { handle, cursorBefore, notes } = started;
198
+
199
+ // 拿不到租约就退回异步:没有租约就没有互斥,硬等下去会和收尾各投一次。
200
+ // **追加任务时租约必须先于投递**,`start()` 已在投递前拿过;这里只为新派生补上
201
+ // (它的 handle 要等会话建出来才存在)。
202
+ if (!started.leased && !(await this.deps.awaitLease.begin(handle))) {
203
+ return withNotes(toolAccepted(handle, '无法登记同步等待'), notes);
204
+ }
205
+
206
+ if (await this.waitForChild(handle, cursorBefore, ctx)) {
207
+ return this.collect(handle, cursorBefore, notes);
208
+ }
209
+
210
+ // 等不到了(超时 / 用户中止)。抢投递权:抢到 = 成功放弃,之后由收尾回投;没抢到 =
211
+ // 收尾刚刚接管,说明子其实已经跑完了,直接取产物。
212
+ if (await this.deps.awaitLease.claim(handle, 'parent')) {
213
+ const why = ctx.abortSignal.aborted ? '已中止等待' : '等待超时';
214
+ this.logger.warn(
215
+ `Delegate(${handle}) 同步等待未完成,已转后台(${why})`
216
+ );
217
+ return withNotes(toolAccepted(handle, why), notes);
218
+ }
219
+ return this.collect(handle, cursorBefore, notes);
220
+ }
221
+
222
+ /** 异步:让子跑起来即返 handle,回投交给收尾。 */
223
+ protected override async runInBackground(
224
+ input: Input,
225
+ ctx: ToolContext
226
+ ): Promise<ToolOut<Out> | ToolAccepted> {
227
+ const started = await this.start(input, ctx, { lease: false });
228
+ if (started.kind !== 'ok') return started;
229
+ return withNotes(toolAccepted(started.handle), started.notes);
230
+ }
231
+
232
+ /**
233
+ * 两种模式共用的起跑段:返回 handle 与**这一轮开始前**的游标(null = 子从未 settle 过)。
234
+ * 它同时是同步等待的判据起点与取产出的起点,故父拿到的恒是「这一轮新说的话」。
235
+ */
236
+ private async start(
237
+ input: Input,
238
+ ctx: ToolContext,
239
+ opts: { lease: boolean }
240
+ ): Promise<Started> {
241
+ const mode = resolveMode(input);
242
+ if (mode.kind === 'error') return mode;
243
+ return mode.mode === 'follow-up'
244
+ ? this.startFollowUp(input, ctx, mode.handle, opts)
245
+ : this.startSpawn(input, ctx, mode.agentType);
246
+ }
247
+
248
+ /**
249
+ * 新建。深度守卫:触顶时本工具已从工具集摘掉(`canDelegate`),这里再挡一次。**只挡
250
+ * 新建**——触顶的那一层从来没派生过任何子,不可能持有 handle。
251
+ */
252
+ private async startSpawn(
253
+ input: Input,
254
+ ctx: ToolContext,
255
+ agentType: string
256
+ ): Promise<Started> {
257
+ if (!canSpawnDeeper(ctx.depth, this.maxDepth)) {
258
+ return toolError(DEPTH_EXHAUSTED_HINT);
259
+ }
260
+ const out = await this.deps.subagents.spawn({
261
+ agentName: agentType,
262
+ title: input.title,
263
+ prompt: input.prompt,
264
+ parentSessionId: ctx.sessionId,
265
+ rootSessionId: ctx.rootSessionId,
266
+ parentRunId: ctx.runId,
267
+ depth: ctx.depth,
268
+ userId: ctx.userId,
269
+ agent: ctx.agent,
270
+ sessionMetadata: ctx.sessionMetadata,
271
+ initiatorPermissions: ctx.initiatorPermissions ?? new Set(),
272
+ });
273
+ if (!out.ok) {
274
+ switch (out.reason) {
275
+ case 'refused':
276
+ return toolError(out.message);
277
+ case 'tree_full':
278
+ return toolError(treeFullHint(this.deps.subagents.maxLivePerTree));
279
+ default:
280
+ return toolError(
281
+ '该子 Agent 不存在或未在当前 Agent 中定义,无法派生。可选项见 system prompt 里的【可派生的子 Agent】列表。'
282
+ );
283
+ }
284
+ }
285
+ return {
286
+ kind: 'ok',
287
+ handle: out.childSessionId,
288
+ cursorBefore: null,
289
+ leased: false,
290
+ ...(out.notes ? { notes: out.notes } : {}),
291
+ };
292
+ }
293
+
294
+ /**
295
+ * 追加任务:校验归属 → (同步模式)拿租约 → 投递。三步的顺序都是必须的:
296
+ *
297
+ * - **校验先于租约**:给一个不属于本父的会话种下租约,会让真正在等它的父被收尾跳过
298
+ * 投递——一次静默丢失的回执。
299
+ * - **租约先于投递**:反过来的话子可能在父开始等之前就跑完,收尾拿不到租约便回投
300
+ * inbox,父随后又同步取一份——双份回执。
301
+ * - **游标读在投递之前**:投递后再读可能读到子已经推进过的新值,父会拿着上一轮的结果
302
+ * 立刻返回。
303
+ */
304
+ private async startFollowUp(
305
+ input: Input,
306
+ ctx: ToolContext,
307
+ handle: string,
308
+ opts: { lease: boolean }
309
+ ): Promise<Started> {
310
+ const target = await this.deps.subagents.resolveFollowUpTarget({
311
+ childSessionId: handle,
312
+ parentSessionId: ctx.sessionId,
313
+ });
314
+ if (!target.ok) {
315
+ // 两种拒绝给不同的话:「没这个子」要它核对 handle,「不是你的子」要它明白这条路
316
+ // 根本不通——合成一句「无法追加」的话,模型只会换个 id 再试。
317
+ return toolError(
318
+ target.reason === 'not_found'
319
+ ? `找不到 handle 为 ${handle} 的子 Agent。请核对本工具当初返回给你的 id;` +
320
+ '如果这是一个全新的任务,改用 agentType 派生一个新的。'
321
+ : `handle 为 ${handle} 的子 Agent 不是你派生的,你不能给它派任务。` +
322
+ '只有你自己派生出来的子 Agent 才能追加任务;' +
323
+ '你派生的子 Agent 自己再往下派生的那一层,要由它去指挥。'
324
+ );
325
+ }
326
+ // 拿不到租约不阻断投递——任务不该因为「没法同步等」而丢掉,调用方据 leased 退回异步。
327
+ const leased = opts.lease
328
+ ? await this.deps.awaitLease.begin(handle)
329
+ : false;
330
+ await this.deps.subagents.deliverFollowUp({
331
+ childSessionId: handle,
332
+ prompt: input.prompt,
333
+ userId: ctx.userId,
334
+ });
335
+ return { kind: 'ok', handle, cursorBefore: target.cursorBefore, leased };
336
+ }
337
+
338
+ /**
339
+ * 轮询到子的游标越过 `cursorBefore`。false = 没等到(超时或中止)。判据取游标而非「子有没有
340
+ * 新消息」:游标是收尾的 CAS 写的,它一推进就意味着收尾已经走过 claim——父此刻去取产物,
341
+ * 绝不会与「收尾正打算投 inbox」撞车。
342
+ */
343
+ private async waitForChild(
344
+ handle: string,
345
+ cursorBefore: number | null,
346
+ ctx: ToolContext
347
+ ): Promise<boolean> {
348
+ const deadline = Date.now() + this.syncWaitMs;
349
+ let nextRenew = Date.now() + this.renewIntervalMs;
350
+ for (;;) {
351
+ if (ctx.abortSignal.aborted) return false;
352
+ if (await this.deps.subagents.hasAdvancedPast(handle, cursorBefore)) {
353
+ return true;
354
+ }
355
+ if (Date.now() >= deadline) return false;
356
+ await sleep(this.pollIntervalMs, ctx.abortSignal);
357
+ if (Date.now() >= nextRenew) {
358
+ await this.deps.awaitLease.renew(handle);
359
+ nextRenew = Date.now() + this.renewIntervalMs;
360
+ }
361
+ }
362
+ }
363
+
364
+ private async collect(
365
+ handle: string,
366
+ cursorBefore: number | null,
367
+ notes?: string[]
368
+ ): Promise<ToolOut<Out>> {
369
+ const result = await this.deps.subagents.buildResult(handle, cursorBefore);
370
+ return { kind: 'ok', handle, ...result, ...(notes ? { notes } : {}) };
371
+ }
372
+
373
+ /**
374
+ * 产出包围栏,与异步路径(`MessageHub.take` 取出回执时包的那道)逐字同源:子的产出是
375
+ * 不可信外部输入,裸拼的话正文与它之后的平台文案在字节层面无从区分。
376
+ */
377
+ protected render(out: { kind: 'ok' } & Out): string {
378
+ return joinNotes(
379
+ wrapSubagentResult(out.body, {
380
+ handle: out.handle,
381
+ status: out.status,
382
+ reason: out.stopReason,
383
+ }),
384
+ out.notes
385
+ );
386
+ }
387
+
388
+ /**
389
+ * 子会话 id 单独落进 `MessagePart.ref`——界面的子 Agent 卡靠它取状态、下钻、停止。
390
+ * **三种「子已经在跑」的形态都给**(同步跑完 / 后台受理 / 等待降级),只有真正没跑起来
391
+ * 的才没有。没有它前端只能拿正则从文本里抠 id,文案一改就静默失效。
392
+ */
393
+ protected override persistRef(
394
+ out: ToolOut<Out> | ToolAccepted
395
+ ): Record<string, unknown> | undefined {
396
+ return out.kind === 'error' ? undefined : { handle: out.handle };
397
+ }
398
+
399
+ /**
400
+ * 降级文案**必须是 accepted 不是 error**:子此刻正常在跑,结论稍后照样回投。用 error
401
+ * 表达会让界面把一个跑得好好的子 Agent 画成失败。
402
+ */
403
+ protected override renderAccepted(out: DelegateAccepted): string {
404
+ // note 只有降级路径才有:模型明确要了结果却没拿到,得知道为什么,以及「别重新派生」
405
+ // ——它看到「没结果」的第一反应就是重试,而子还在跑,重试等于白烧一个子 Agent。
406
+ const text = out.note
407
+ ? `子 Agent 仍在运行(${out.note}),已转为后台(handle=${out.handle})。` +
408
+ '不要重新派生它,也不要重复发送 —— 它做完后结论会作为一条新消息回到你这里。请先处理其它工作。'
409
+ : `子 Agent 已在后台运行(handle=${out.handle})。你不必等待——它完成后结论会自动回到你这里。请继续处理其它工作。`;
410
+ return joinNotes(text, out.notes);
411
+ }
412
+ }
413
+
414
+ /** 登记 `Delegate`。 */
415
+ export function registerDelegateTool(
416
+ tools: ToolRegistry,
417
+ deps: DelegateToolDeps
418
+ ): DelegateTool {
419
+ const tool = new DelegateTool(deps);
420
+ tools.register(delegateToolMeta(deps.syncWaitMs), tool);
421
+ return tool;
422
+ }
423
+
424
+ /**
425
+ * 判定这次是「派生新的」还是「给已有的追加任务」。**两者都给必须明确报错,不能静默偏向
426
+ * 某一个**:静默挑一个的话,模型以为自己在改稿、实际白派生了一个全新的子 Agent 从零重写,
427
+ * 而拿到的产出看起来完全正常。schema 表达不了「恰填其一」(注册表要往 `ZodObject` 上注入
428
+ * `run_in_background`),所以这道判断落在运行时。
429
+ */
430
+ function resolveMode(
431
+ input: Input
432
+ ):
433
+ | { kind: 'ok'; mode: 'spawn'; agentType: string }
434
+ | { kind: 'ok'; mode: 'follow-up'; handle: string }
435
+ | { kind: 'error'; message: string } {
436
+ const agentType = input.agentType?.trim() || undefined;
437
+ const handle = input.handle?.trim() || undefined;
438
+ if (agentType && handle) {
439
+ return toolError(
440
+ 'agentType 与 handle 只能给一个:要派生一个新的子 Agent 就只给 agentType,' +
441
+ '要让已经派生过的那个继续做事就只给 handle(它会带着之前的往来接着做)。'
442
+ );
443
+ }
444
+ if (handle) return { kind: 'ok', mode: 'follow-up', handle };
445
+ if (agentType) return { kind: 'ok', mode: 'spawn', agentType };
446
+ return toolError(
447
+ '缺少 agentType 或 handle:要派生一个新的子 Agent 就给 agentType' +
448
+ '(可选项见 system prompt 里的【可派生的子 Agent】列表);' +
449
+ '要让已经派生过的那个继续做事就给它的 handle。'
450
+ );
451
+ }
452
+
453
+ function withNotes(
454
+ accepted: ToolAccepted,
455
+ notes: string[] | undefined
456
+ ): DelegateAccepted {
457
+ return notes ? { ...accepted, notes } : accepted;
458
+ }
459
+
460
+ /** 说明各占一行,接一个空行再是正文;没有说明原样返回。 */
461
+ function joinNotes(text: string, notes: readonly string[] | undefined): string {
462
+ return notes && notes.length > 0 ? `${notes.join('\n')}\n\n${text}` : text;
463
+ }
464
+
465
+ /** 可中止的 sleep:信号一来立刻醒。 */
466
+ function sleep(ms: number, signal: AbortSignal): Promise<void> {
467
+ return new Promise(resolve => {
468
+ const timer = setTimeout(done, ms);
469
+ signal.addEventListener('abort', done, { once: true });
470
+ function done(): void {
471
+ clearTimeout(timer);
472
+ signal.removeEventListener('abort', done);
473
+ resolve();
474
+ }
475
+ });
476
+ }
@@ -0,0 +1,63 @@
1
+ export {
2
+ DELEGATE_POLL_INTERVAL_MS,
3
+ DELEGATE_SYNC_WAIT_MS,
4
+ DelegateTool,
5
+ type DelegateToolDeps,
6
+ delegateToolMeta,
7
+ registerDelegateTool,
8
+ } from './delegate.tool.js';
9
+ export {
10
+ buildMilestoneBody,
11
+ escapeSubagentFence,
12
+ isFailedTerminal,
13
+ type MilestoneTerminal,
14
+ normalizeMilestoneStatus,
15
+ type SubagentResultFence,
16
+ wrapSubagentResult,
17
+ } from './milestone-body.js';
18
+ export { type ScanResult, scanSubagentOutput } from './output-scan.js';
19
+ export {
20
+ registrySpawnPolicy,
21
+ type RegistrySpawnPolicyOptions,
22
+ } from './registry-spawn-policy.js';
23
+ export {
24
+ buildSubagentIndexBlock,
25
+ DESC_LIMIT,
26
+ OWN_GROUP_HEADING,
27
+ type SubagentIndexEntry,
28
+ } from './roster-block.js';
29
+ export {
30
+ buildSubagentSituationBlock,
31
+ DEFAULT_AGENT_PROMPT_BLOCK,
32
+ type SubagentSituationOptions,
33
+ } from './situation-block.js';
34
+ export {
35
+ canDelegate,
36
+ canSpawnDeeper,
37
+ DEPTH_EXHAUSTED_HINT,
38
+ MAX_LIVE_SUBS_PER_TREE,
39
+ MAX_SUBAGENT_DEPTH,
40
+ TREE_FULL_HINT,
41
+ treeFullHint,
42
+ } from './spawn-guards.js';
43
+ export {
44
+ GENERAL_PURPOSE_PROMPT,
45
+ GENERAL_PURPOSE_SUBAGENT,
46
+ type SubagentAccess,
47
+ type SubagentMeta,
48
+ type SubagentProvider,
49
+ SubagentRegistry,
50
+ type SubagentRegistryOptions,
51
+ } from './subagent-registry.js';
52
+ export {
53
+ type FollowUpTarget,
54
+ type SpawnCheck,
55
+ type SpawnOutcome,
56
+ type SpawnPolicy,
57
+ type SpawnRequest,
58
+ SUBAGENT_SWEEP_IDLE_MS,
59
+ type SubagentResult,
60
+ SubagentSessions,
61
+ type SubagentSessionsDeps,
62
+ type SubagentTickInfo,
63
+ } from './subagent-sessions.js';