@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,400 @@
1
+ import { generateText } from 'ai';
2
+ import { silentLogger } from '../ports/logger.js';
3
+ import { COMPACTION_CHECKPOINT_KIND } from '../schema/index.js';
4
+ import { COMPACTION_INSTRUCTION, judgeSummary } from '../turn/compaction.js';
5
+ import { measureModelMessageChars, } from '../turn/context-pressure.js';
6
+ import { partsToModelMessages, } from '../turn/parts-to-model-messages.js';
7
+ import { charsToTokens, computeContextThreshold, computePruneCut, measureRowChars, } from './context-budget.js';
8
+ /**
9
+ * 一个 tick 最多压缩几次(含失败的尝试)。
10
+ *
11
+ * **2 = 一次 + 一次重试**。再多没有意义:一个不肯好好写摘要的模型第三次多半还是
12
+ * 那样,而每次尝试都是一整个上下文的全量请求 —— 空转与真压缩一样贵,还各断一次
13
+ * 前缀缓存。压不动就让这一轮照常发出去,撞爆了自有溢出补救接手。
14
+ */
15
+ const MAX_COMPACTION_ATTEMPTS = 2;
16
+ /**
17
+ * 还活着的那条 checkpoint 行的 seq(`seq > compactedUpto` 的最后一条)。
18
+ *
19
+ * 取**最后一条**而不是第一条:正常情况下只有一条,多出来的只可能是历史遗留,
20
+ * 而新的切点要覆盖的是最靠后那条 —— 覆盖它就顺带覆盖了它前面所有的。
21
+ */
22
+ function lastCheckpointSeq(rows, compactedUpto) {
23
+ let found = null;
24
+ for (const r of rows) {
25
+ if (compactedUpto !== null && r.seq <= compactedUpto)
26
+ continue;
27
+ if (r.kind === COMPACTION_CHECKPOINT_KIND)
28
+ found = r.seq;
29
+ }
30
+ return found;
31
+ }
32
+ /**
33
+ * 一个 tick 的上下文预算管家。
34
+ *
35
+ * **持有轮初那批行的快照,全程不再查库拿历史**。两条理由,都不是性能:
36
+ *
37
+ * 1. 「本轮已开的行不许进阴影区」——快照里根本没有本轮的行(`loadContext` 跑在
38
+ * 第一次 `drainInbox` 之前,本轮的用户消息那时还在 inbox 里),这条因此是
39
+ * 结构上成立的,不靠谁记得去判断。
40
+ * 2. 重新查库投影会把 drain 消息的**围栏**抹掉(内存里那些用的是 `modelParts`,
41
+ * 与落库的 `parts` 不同)。这也是 `ContextRelief` 只替换头部的原因。
42
+ */
43
+ export class ContextBudgetTracker {
44
+ deps;
45
+ rows = [];
46
+ storedRows = [];
47
+ prunedUpto = null;
48
+ compactedUpto = null;
49
+ /**
50
+ * 上一条还活着的 checkpoint 行的 seq(没有则 null)。
51
+ *
52
+ * 新的压缩切点**必须覆盖它**:留着它就会同时存在两份摘要,而投影层只提头一条,
53
+ * 另一条会按 seq 落在保留段中间——同一段历史被讲两遍,且其中一遍是过期的。
54
+ */
55
+ checkpointSeq = null;
56
+ baseline = null;
57
+ /** 已经报过一次「模型没填容量」的 warn,别每步刷一条。 */
58
+ warnedNoCapacity = false;
59
+ /**
60
+ * 本 tick 已经尝试过几次压缩。
61
+ *
62
+ * **失败的也算**:一个不肯好好写摘要的模型,重试第三次多半还是那样,而每次
63
+ * 都是一整个上下文的全量请求 —— 空转的代价与真压缩一样贵。
64
+ */
65
+ compactionAttempts = 0;
66
+ constructor(deps) {
67
+ this.deps = deps;
68
+ }
69
+ /** `TurnHost.loadContext`:投影出带裁剪与压缩的历史,同时留下本轮要用的快照。 */
70
+ async load() {
71
+ const { rows, prunedUptoSeq, compactedUptoSeq, baselineContextTokens } = await this.deps.store.loadContextInputs(this.deps.sessionId);
72
+ this.storedRows = rows;
73
+ this.rows = rows.map(r => ({
74
+ seq: r.seq,
75
+ chars: measureRowChars(r.parts),
76
+ }));
77
+ this.prunedUpto = prunedUptoSeq;
78
+ this.compactedUpto = compactedUptoSeq;
79
+ this.checkpointSeq = lastCheckpointSeq(rows, compactedUptoSeq);
80
+ this.baseline = baselineContextTokens;
81
+ return this.project({ upto: null });
82
+ }
83
+ /**
84
+ * 快照的投影,可选只取 `seq ≤ upto` 的那一段(算 `replaces` 用)。
85
+ *
86
+ * 收成一个方法而不是各处各写一次 `partsToModelMessages(...)`:**两个指针必须
87
+ * 一起传**,漏掉压缩指针那一处会把已经压掉的行重新投出来,而症状只是「压缩
88
+ * 好像没生效」。
89
+ *
90
+ * **checkpoint 行不受 `upto` 约束**:它的 seq 是全场最大的,而投影层把它提到了
91
+ * 历史最前面 —— `messages` 的头部因此是「checkpoint + 前 upto 条」。按 seq 卡掉
92
+ * 它,算出来的 `replaces` 就比真实头部少一条,splice 会把尾部整体错位一格。
93
+ */
94
+ project(opts) {
95
+ const upto = opts.upto;
96
+ const rows = upto === null
97
+ ? this.storedRows
98
+ : this.storedRows.filter(r => r.seq <= upto || r.seq === this.checkpointSeq);
99
+ return partsToModelMessages(rows, {
100
+ prunedUptoSeq: this.prunedUpto,
101
+ compactedUptoSeq: this.compactedUpto,
102
+ ...this.deps.projection,
103
+ });
104
+ }
105
+ /**
106
+ * 本轮的触发线。**也给前端**(经 `TurnResult.contextThreshold` 落进
107
+ * metadata)——界面上那个「快满了」的变色判据必须与这里同源,各写一个 0.8
108
+ * 的结果是界面说「还早」而日志里已经在裁了。
109
+ */
110
+ thresholdOf(maxContextTokens) {
111
+ return computeContextThreshold({
112
+ maxContextTokens,
113
+ maxOutputTokens: this.deps.maxOutputTokens,
114
+ reserveFactor: this.deps.reserveFactor,
115
+ });
116
+ }
117
+ /** 本轮的触发线;容量未知时为 null(那时压根不做主动裁剪)。 */
118
+ get threshold() {
119
+ const max = this.deps.maxContextTokens;
120
+ return max === null ? null : this.thresholdOf(max);
121
+ }
122
+ /**
123
+ * `beforeModelCall` 的正体:超阈值就腾空间,返回新的头部。
124
+ *
125
+ * **两级,顺序固定**:先裁剪(免模型、零成本、单次就能吃掉长会话的大头),
126
+ * 裁到头仍不够才压缩(要花一次全量请求)。免模型的路径永远该先跑,模型摘要
127
+ * 是兜底 —— 裁剪把压缩的触发频率压得很低正是期望的结果。
128
+ */
129
+ async relieve(pressure) {
130
+ // **provider 已经拒了**:跳过一切阈值判断。阈值是我们对「快满了」的猜测,
131
+ // 这一刻已经不是猜测。这条路同时覆盖了「模型没填 max_context_tokens、平时
132
+ // 压根不主动腾」的那一类会话——它们唯一的保护就是这里。
133
+ if (pressure.overflowed) {
134
+ const retainTokens = this.deps.retainRatio * this.estimatedHistoryTokens();
135
+ const why = 'provider reported context overflow';
136
+ return ((await this.prune(retainTokens, why)) ??
137
+ this.compact(pressure, why, retainTokens));
138
+ }
139
+ const max = this.deps.maxContextTokens;
140
+ if (max === null) {
141
+ // **不猜容量、也不改用纯估算去判断**:没有真实数字时任何阈值都是编的。
142
+ // 这类会话不做主动腾空间,只靠上面那条溢出补救兜底——provider 真报了超限
143
+ // 的话,它已经替我们判定了必要性。
144
+ if (!this.warnedNoCapacity) {
145
+ this.warnedNoCapacity = true;
146
+ this.deps.logger.warn(`session ${this.deps.sessionId}: model has no max_context_tokens, context pruning is off for this turn`);
147
+ }
148
+ return null;
149
+ }
150
+ const base = pressure.lastStepInputTokens ?? this.baseline;
151
+ // 会话头一轮:既没调过模型、也没有上一轮留下的基线。此时历史必然很短。
152
+ if (base === null)
153
+ return null;
154
+ const estimate = base + charsToTokens(pressure.charsSinceLastStep);
155
+ const threshold = this.thresholdOf(max);
156
+ if (estimate < threshold)
157
+ return null;
158
+ // 保留量相对**可用空间**而不是整个窗口:窗口里给输出预留的那块,历史本来
159
+ // 就不该占。
160
+ const retainTokens = threshold * this.deps.retainRatio;
161
+ const why = `~${Math.round(estimate)} ≥ ${Math.round(threshold)} of ${max}`;
162
+ return ((await this.prune(retainTokens, why)) ??
163
+ this.compact(pressure, why, retainTokens));
164
+ }
165
+ /**
166
+ * 还在上下文里的那段历史有多大(按 `字符数 / 4` 估)。
167
+ *
168
+ * **只在溢出补救那条路上用**:那时可能连模型窗口都不知道(`max_context_tokens`
169
+ * 没填),拿不到触发线,也就没有「触发线 × 保留比例」这个口径。用历史自己的
170
+ * 规模当分母是这种情况下唯一站得住的做法——刚刚撞爆过,所以它约等于窗口。
171
+ *
172
+ * 注意这是**原始行**的规模:裁剪已经把一部分正文换成存根了,故这是个高估,
173
+ * 方向是「多腾一点」。撞爆之后宁可多腾。
174
+ */
175
+ estimatedHistoryTokens() {
176
+ const chars = this.survivingRows().reduce((sum, r) => sum + r.chars, 0);
177
+ return charsToTokens(chars);
178
+ }
179
+ /**
180
+ * 尚未被压缩掉的那部分快照。**切点只能在这里面算** —— 已经压掉的行在模型眼里
181
+ * 不存在了,把它们算进保留预算会让预算凭空少一块,切点随之偏晚。
182
+ */
183
+ survivingRows() {
184
+ const upto = this.compactedUpto;
185
+ return upto === null ? this.rows : this.rows.filter(r => r.seq > upto);
186
+ }
187
+ /** 第一级:把裁剪指针往前推。腾不动返回 null(交给压缩)。 */
188
+ async prune(retainTokens, why) {
189
+ const cut = computePruneCut(this.survivingRows(), retainTokens);
190
+ if (cut === null || (this.prunedUpto !== null && cut <= this.prunedUpto)) {
191
+ return null;
192
+ }
193
+ const before = this.project({ upto: cut });
194
+ const prevPruned = this.prunedUpto;
195
+ this.prunedUpto = cut;
196
+ const head = this.project({ upto: cut });
197
+ if (head.length !== before.length) {
198
+ // 裁剪只换 tool-result 的正文,**条数必须一模一样**——这是「只替换头部」
199
+ // 那条对齐的前提。真变了就是有人把裁剪改成了会增删消息的东西,此时按
200
+ // `before.length` 去 splice 会把尾部错位(历史与围栏消息一起被吃掉),
201
+ // 而那是静默的。宁可这一轮不腾空间。
202
+ this.prunedUpto = prevPruned;
203
+ this.deps.logger.error(`session ${this.deps.sessionId}: pruning changed message count (${before.length} → ${head.length}), skipping relief`);
204
+ return null;
205
+ }
206
+ await this.deps.store.advancePrunedUpto(this.deps.sessionId, cut);
207
+ this.deps.logger.log(`session ${this.deps.sessionId}: pruned tool results up to seq ${cut} (${why} tokens)`);
208
+ return { head, replaces: before.length };
209
+ }
210
+ /**
211
+ * 第二级:让模型把前面那段历史写成一份交接说明,整段换成一条 checkpoint。
212
+ *
213
+ * **失败一律返回 null、不抛。** 主动的阈值检查里超线不等于撞爆,这一轮多半
214
+ * 照样发得出去;为了「上下文快满了」把一轮本来能成的对话打死,比什么都不做更
215
+ * 糟。真撞爆的那条路(溢出补救)自己会判定必要性——它拿到 null 就把 provider
216
+ * 的原始错误原样抛出,抛错的判断权在内核那一侧,不在这里。
217
+ */
218
+ async compact(pressure, why, retainTokens) {
219
+ const cutBySize = computePruneCut(this.survivingRows(), retainTokens);
220
+ // **切点必须覆盖上一条 checkpoint**:留着它就是两份摘要同时在历史里,而
221
+ // 投影层只把最早那条提到头,另一条会按 seq 落在保留段中间——同一段历史讲两遍,
222
+ // 其中一遍还是过期的。
223
+ //
224
+ // 这个 clamp **只抬高一个真实存在的切点**,不能拿它去制造切点:`cutBySize`
225
+ // 为 null 时保留段本来就在预算之内,此时若只因为「有一条 checkpoint」就压,
226
+ // 那是拿一次全量请求去把上一份摘要重写一遍,压力一点没降。
227
+ if (cutBySize === null) {
228
+ // 已经压到头了。**debug 级、且不写库**:腾不出空间时压力不会下降,下一步
229
+ // 还会再问一次,warn 会变成每步一条。
230
+ this.deps.logger.debug(`session ${this.deps.sessionId}: over threshold (${why}) but nothing left to compact`);
231
+ return null;
232
+ }
233
+ const cut = Math.max(cutBySize, this.checkpointSeq ?? 0);
234
+ if (this.compactedUpto !== null && cut <= this.compactedUpto)
235
+ return null;
236
+ if (this.compactionAttempts >= MAX_COMPACTION_ATTEMPTS) {
237
+ this.deps.logger.debug(`session ${this.deps.sessionId}: compaction already attempted ${this.compactionAttempts}× this tick, standing down`);
238
+ return null;
239
+ }
240
+ this.compactionAttempts++;
241
+ // 顶掉的是**当前投影下**的那一段头部,不是原始行的大小:裁剪可能已经把它们
242
+ // 换成存根了,拿原文去比会高估源、让一份其实没压缩多少的摘要蒙混过关。
243
+ const before = this.project({ upto: cut });
244
+ if (before.length === 0)
245
+ return null;
246
+ const sourceChars = measureModelMessageChars(before);
247
+ let summary;
248
+ try {
249
+ const result = await generateText({
250
+ model: this.deps.llm.model,
251
+ // 逐字重放:同一份 instructions、同一份工具定义、同样的历史,**只在末尾
252
+ // 追加一条压缩指令**。这样这次调用能命中 provider 的 warm prefix。
253
+ instructions: pressure.request.system,
254
+ messages: [
255
+ ...pressure.request.messages,
256
+ { role: 'user', content: COMPACTION_INSTRUCTION },
257
+ ],
258
+ tools: pressure.request.tools,
259
+ providerOptions: this.deps.llm.providerOptions,
260
+ abortSignal: pressure.request.abortSignal,
261
+ });
262
+ // **只取 text**。reasoning 丢掉(那是模型的私有推理,落进历史等于把它
263
+ // 泄给后续每一轮);tool call 也丢掉(收下就会造出一个没有 result 的
264
+ // 孤儿 tool_use,各家协议一律 400)。模型如果只调了工具没写字,下面
265
+ // `judgeSummary` 会以「没有产出任何文本」拒掉。
266
+ summary = result.text;
267
+ }
268
+ catch (err) {
269
+ this.deps.logger.error(`session ${this.deps.sessionId}: compaction request failed: ${String(err)}`);
270
+ return null;
271
+ }
272
+ const verdict = judgeSummary(summary, sourceChars);
273
+ if (!verdict.ok) {
274
+ // 静默丢掉一次全量请求是最贵的那种沉默:钱花了、前缀缓存也断了,日志里
275
+ // 却什么都没有。
276
+ this.deps.logger.error(`session ${this.deps.sessionId}: rejected compaction summary (${verdict.reason})`);
277
+ return null;
278
+ }
279
+ const row = await this.deps.store.appendCheckpoint({
280
+ sessionId: this.deps.sessionId,
281
+ seq: cut,
282
+ summary: summary.trim(),
283
+ });
284
+ this.compactedUpto = cut;
285
+ this.checkpointSeq = row.seq;
286
+ // 快照跟着补上这条新行。
287
+ //
288
+ // **本 tick 里其实不会再触发第二次腾空间**:切点取的正是「尾部累计刚超过保留
289
+ // 预算」的那一行,压完之后保留段必然恰好在预算之内,下一步 `computePruneCut`
290
+ // 两级都返回 null。留着这几行是为了让对象**始终自洽** —— 只更新指针不更新快照
291
+ // 的话,谁哪天动了触发条件(比如按剩余空间动态收紧保留比例),错位会以「顶掉的
292
+ // 条数差一格」的形态静默出现,而那正是最难查的一类。
293
+ this.storedRows = [...this.storedRows, row];
294
+ this.rows = [
295
+ ...this.rows,
296
+ { seq: row.seq, chars: measureRowChars(row.parts) },
297
+ ];
298
+ const head = partsToModelMessages([row], this.deps.projection);
299
+ this.deps.logger.log(`session ${this.deps.sessionId}: compacted history up to seq ${cut} into checkpoint ${row.id} (${why} tokens, ${sourceChars} → ${summary.trim().length} chars)`);
300
+ return { head, replaces: before.length };
301
+ }
302
+ }
303
+ /**
304
+ * tracker 在 `TurnContext.turnState` 里的键。**导出**:宿主按它预置
305
+ * (`createContextBudgetTracker` 的用法示例),插件按它取用,两边分叉的症状是上下文预算
306
+ * 静默关闭——没有报错,只有会话在某一天撞爆 context window。
307
+ */
308
+ export const CONTEXT_BUDGET_TURN_STATE_KEY = 'context-budget';
309
+ /**
310
+ * 取本轮的 tracker。**用 `instanceof` 而不是类型断言**:`turnState` 是一张各插件
311
+ * 混住的异构表,断言在这里等于「相信键上放对了东西」,而放错的那一天不会报错。
312
+ */
313
+ function trackerOf(ctx) {
314
+ const found = ctx.turnState.get(CONTEXT_BUDGET_TURN_STATE_KEY);
315
+ return found instanceof ContextBudgetTracker ? found : null;
316
+ }
317
+ /** 宿主不给时的缺省参数(照抄 dsh 跑过真实负载的那一组)。 */
318
+ export const CONTEXT_BUDGET_DEFAULTS = {
319
+ /** 预留几倍的最大输出(见 `ThresholdInput.reserveFactor`)。 */
320
+ reserveFactor: 1,
321
+ /** 腾空间时保留触发线的多大比例给最近的历史。 */
322
+ retainRatio: 0.16,
323
+ };
324
+ /**
325
+ * 建本轮的 tracker。宿主在 `TurnHost` 里这样接:
326
+ *
327
+ * ```ts
328
+ * const budget = createContextBudgetTracker({ store, sessionId, llm, maxContextTokens, … });
329
+ * const host: TurnHost = {
330
+ * loadContext: () => budget.load(),
331
+ * turnState: new Map([[CONTEXT_BUDGET_TURN_STATE_KEY, budget]]),
332
+ * …
333
+ * };
334
+ * // 终态:budget.threshold 落进 metadata,界面的「快满了」与这里同源。
335
+ * ```
336
+ *
337
+ * **tracker 由宿主建、经 `turnState` 交给钩子**,钩子自己不建:它同时是
338
+ * `loadContext` 的投影源与终态 `contextThreshold` 的来源,三方必须是同一个实例;
339
+ * 且切点跑在第一次 drain 之后,那时懒建出来的快照会把本轮的用户消息算进可裁剪的
340
+ * 阴影区。
341
+ *
342
+ * 阈值参数在 agent-base 里走系统参数(只有真实负载上才知道合不合适,调它们不该
343
+ * 要一次发版);这里由宿主传入,宿主自己决定从哪读。
344
+ */
345
+ export function createContextBudgetTracker(opts) {
346
+ return new ContextBudgetTracker({
347
+ store: opts.store,
348
+ logger: opts.logger ?? silentLogger(''),
349
+ sessionId: opts.sessionId,
350
+ llm: opts.llm,
351
+ maxContextTokens: opts.maxContextTokens,
352
+ maxOutputTokens: opts.maxOutputTokens,
353
+ reserveFactor: opts.reserveFactor ?? CONTEXT_BUDGET_DEFAULTS.reserveFactor,
354
+ retainRatio: opts.retainRatio ?? CONTEXT_BUDGET_DEFAULTS.retainRatio,
355
+ ...(opts.projection ? { projection: opts.projection } : {}),
356
+ });
357
+ }
358
+ export const CONTEXT_BUDGET_HOOK_META = {
359
+ name: 'context-budget',
360
+ point: 'beforeModelCall',
361
+ order: 100,
362
+ // **压缩是一次完整的 LLM 调用**(逐字重放整个会话前缀),分钟级。缺省的 5s
363
+ // 会把它一律掐成超时;而把默认值抬上去等于让其余每个点的保护一起松掉。
364
+ // 这道超时是第二重保护——摘要请求本身带着本轮的 abortSignal,停止按钮先生效。
365
+ timeoutMs: 300_000,
366
+ // **腾不出空间不该把一轮本来能成的对话打死**:主动路径上超线只是我们对
367
+ // 「快满了」的猜测,这一轮多半照样发得出去。tracker 内部已经把压缩失败吞成
368
+ // null,会漏到这里的只剩裁剪指针那次存储写——它失败时下一轮重新读,
369
+ // 状态仍然自洽。真撞爆的那条路(`overflowed`)拿到 null 会把 provider 的
370
+ // 原始错误原样抛出,判断权在内核那一侧。
371
+ onError: 'open',
372
+ };
373
+ /**
374
+ * 上下文预算的 `beforeModelCall` 钩子:取宿主预置的 tracker,把压力转给它。
375
+ *
376
+ * **单例点**——两个插件先后替换 `messages` 的头部,第二个看到的已经不是原始
377
+ * 历史,它算出的 `replaces` 对不上任何一段真实前缀。
378
+ */
379
+ export class ContextBudgetHook {
380
+ logger;
381
+ constructor(logger = silentLogger('')) {
382
+ this.logger = logger;
383
+ }
384
+ beforeModelCall(ctx, pressure) {
385
+ const tracker = trackerOf(ctx);
386
+ if (!tracker) {
387
+ // 接线坏了(宿主没预置),**不是**「这一轮不需要腾」。不抛:抛了就是拿
388
+ // 每一轮对话给一个接线错误陪葬;但必须响亮到日志里,否则症状要等到会话
389
+ // 撞爆 context window 才出现,那时离成因已经很远了。
390
+ this.logger.error(`run ${ctx.runId}: no context-budget tracker on this turn, context pruning is off`);
391
+ return Promise.resolve(null);
392
+ }
393
+ return tracker.relieve(pressure);
394
+ }
395
+ }
396
+ /** 把上下文预算钩子挂到注册表上。 */
397
+ export function registerContextBudgetHook(hooks, logger) {
398
+ hooks.register(CONTEXT_BUDGET_HOOK_META, new ContextBudgetHook(logger));
399
+ }
400
+ //# sourceMappingURL=context-budget-tracker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context-budget-tracker.js","sourceRoot":"","sources":["../../src/context/context-budget-tracker.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,48 @@
1
+ import type { MessagePart } from '../schema/index.js';
2
+ export interface ThresholdInput {
3
+ maxContextTokens: number;
4
+ /** 模型的单次最大输出;null = 运营没填。 */
5
+ maxOutputTokens: number | null;
6
+ /**
7
+ * 预留几倍的最大输出。**默认 1**(完整预留)。
8
+ *
9
+ * 代价是不对称的:早裁一次的代价是断一次前缀缓存、丢几段老工具结果正文;
10
+ * 撞爆的代价是整轮挂掉,而且此后这个会话**每一次**发言都失败。不对称到这个
11
+ * 程度时不该为省几个 token 去赌模型这次不会吐满。调小它等于押注「实际输出
12
+ * 只会用到上限的一部分」——那个押注多数时候赢,输一次就是上面那个后果。
13
+ */
14
+ reserveFactor: number;
15
+ }
16
+ /**
17
+ * 什么时候该腾空间:**当剩余空间装不下一次完整的模型输出**。
18
+ *
19
+ * 真正的硬约束从来是 `上下文 + 本次输出 ≤ 窗口`,固定比例(原来的 0.8)只是在
20
+ * 猜这条线,而且在两端都猜错:1M 窗口按 0.8 要留 20 万 token 的余量,荒谬;8k
21
+ * 窗口配 4k 输出的模型按 0.8 只留 1.6k,一次满输出就撞。按输出算是**尺度自适应**
22
+ * 的,小窗口自动更保守、大窗口自动更激进。
23
+ */
24
+ export declare function computeContextThreshold(i: ThresholdInput): number;
25
+ /**
26
+ * 一行落库消息的字符规模。
27
+ *
28
+ * 逐 part 序列化,与 `measureModelMessageChars` 同口径(都只求相对大小,不求准)。
29
+ */
30
+ export declare function measureRowChars(parts: MessagePart[]): number;
31
+ export interface PrunableRow {
32
+ seq: number;
33
+ chars: number;
34
+ }
35
+ /**
36
+ * 新的裁剪切点:从**尾部**往前留够 `retainTokens` 的预算,剩下的全进阴影区。
37
+ * 返回 `null` = 整段历史都在保留预算之内,没什么可切的。
38
+ *
39
+ * `rows` 必须按 seq 升序(`listMessages` 的既有口径)。
40
+ *
41
+ * **成块推进,不是每轮挪一点。** 保留预算取的是模型容量的一个固定比例,所以
42
+ * 同一段历史反复检查会算出同一个切点、第二次直接无事发生;而「每轮往前挪几行」
43
+ * 那种写法每挪一次就断一次 provider 的前缀缓存,挪得越碎命中率越低。
44
+ */
45
+ export declare function computePruneCut(rows: PrunableRow[], retainTokens: number): number | null;
46
+ /** 字符数折成 token 的估算值。 */
47
+ export declare function charsToTokens(chars: number): number;
48
+ //# sourceMappingURL=context-budget.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context-budget.d.ts","sourceRoot":"","sources":["../../src/context/context-budget.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AA6CtD,MAAM,WAAW,cAAc;IAC7B,gBAAgB,EAAE,MAAM,CAAC;IACzB,6BAA6B;IAC7B,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B;;;;;;;OAOG;IACH,aAAa,EAAE,MAAM,CAAC;CACvB;AAED;;;;;;;GAOG;AACH,wBAAgB,uBAAuB,CAAC,CAAC,EAAE,cAAc,GAAG,MAAM,CAQjE;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,WAAW,EAAE,GAAG,MAAM,CAM5D;AAED,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAC7B,IAAI,EAAE,WAAW,EAAE,EACnB,YAAY,EAAE,MAAM,GACnB,MAAM,GAAG,IAAI,CASf;AAED,wBAAwB;AACxB,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEnD"}
@@ -0,0 +1,89 @@
1
+ /**
2
+ * 上下文预算的纯函数层:一行有多大、切点切在哪。
3
+ *
4
+ * 与 `parts-to-model-messages.ts` 的分工——那边管「阴影区里的行投影成什么样」,
5
+ * 这边管「阴影区的边界在哪」。两者都不碰库。
6
+ */
7
+ /** 估算 token 时用的字符折算率。见 `ContextPressure.charsSinceLastStep` 的判据。 */
8
+ const CHARS_PER_TOKEN = 4;
9
+ /**
10
+ * 触发线的下限,占窗口的比例。
11
+ *
12
+ * 有些模型的 `max_output_tokens` 就等于半个窗口甚至更多(8k/4k 那一代很常见)。
13
+ * 不夹的话触发线会掉到 50% 以下、极端情形直接为 0 —— 变成「永远在触发、永远
14
+ * 裁不动」,每步刷一行日志。夹在这里等于承认「这种模型你就是只能用一半上下文」,
15
+ * 那是事实,不是妥协。
16
+ */
17
+ const THRESHOLD_FLOOR_RATIO = 0.5;
18
+ /**
19
+ * 触发线的上限,占窗口的比例。
20
+ *
21
+ * `max_output_tokens` 很小的模型(1M 窗口配 1k 输出)会把触发线推到 99.9%,而
22
+ * 我们补在基线上的增量是 `chars / 4` 估的、对中文严重低估。这 8% 就是留给估算
23
+ * 误差的。
24
+ *
25
+ * **实际上这条在主流大窗口模型上是常态而非例外**:它们的
26
+ * `max_output / max_context` 普遍在 8% 以下(1M/64k = 6.4%),所以触发线基本
27
+ * 恒等于 92%。公式真正起作用的是小窗口那一端(32k/8k = 25%)—— 而那正是固定
28
+ * 比例最容易出事的地方。
29
+ */
30
+ const THRESHOLD_CEIL_RATIO = 0.92;
31
+ /**
32
+ * `max_output_tokens` 没填时,按窗口的这个比例假设。
33
+ *
34
+ * 取 0.2 使得 `reserveFactor = 1` 时公式恰好退化成「窗口 × 0.8」—— 也就是这套
35
+ * 东西最初那个固定阈值。旧行为成了新公式的一个特例,不必为「模型没填输出上限」
36
+ * 另开一条代码路径。
37
+ */
38
+ const DEFAULT_OUTPUT_RATIO = 0.2;
39
+ /**
40
+ * 什么时候该腾空间:**当剩余空间装不下一次完整的模型输出**。
41
+ *
42
+ * 真正的硬约束从来是 `上下文 + 本次输出 ≤ 窗口`,固定比例(原来的 0.8)只是在
43
+ * 猜这条线,而且在两端都猜错:1M 窗口按 0.8 要留 20 万 token 的余量,荒谬;8k
44
+ * 窗口配 4k 输出的模型按 0.8 只留 1.6k,一次满输出就撞。按输出算是**尺度自适应**
45
+ * 的,小窗口自动更保守、大窗口自动更激进。
46
+ */
47
+ export function computeContextThreshold(i) {
48
+ const assumedOutput = i.maxOutputTokens ?? i.maxContextTokens * DEFAULT_OUTPUT_RATIO;
49
+ const raw = i.maxContextTokens - assumedOutput * i.reserveFactor;
50
+ return Math.min(Math.max(raw, i.maxContextTokens * THRESHOLD_FLOOR_RATIO), i.maxContextTokens * THRESHOLD_CEIL_RATIO);
51
+ }
52
+ /**
53
+ * 一行落库消息的字符规模。
54
+ *
55
+ * 逐 part 序列化,与 `measureModelMessageChars` 同口径(都只求相对大小,不求准)。
56
+ */
57
+ export function measureRowChars(parts) {
58
+ let total = 0;
59
+ for (const part of parts) {
60
+ total += JSON.stringify(part)?.length ?? 0;
61
+ }
62
+ return total;
63
+ }
64
+ /**
65
+ * 新的裁剪切点:从**尾部**往前留够 `retainTokens` 的预算,剩下的全进阴影区。
66
+ * 返回 `null` = 整段历史都在保留预算之内,没什么可切的。
67
+ *
68
+ * `rows` 必须按 seq 升序(`listMessages` 的既有口径)。
69
+ *
70
+ * **成块推进,不是每轮挪一点。** 保留预算取的是模型容量的一个固定比例,所以
71
+ * 同一段历史反复检查会算出同一个切点、第二次直接无事发生;而「每轮往前挪几行」
72
+ * 那种写法每挪一次就断一次 provider 的前缀缓存,挪得越碎命中率越低。
73
+ */
74
+ export function computePruneCut(rows, retainTokens) {
75
+ let retained = 0;
76
+ for (let i = rows.length - 1; i >= 0; i--) {
77
+ retained += rows[i].chars / CHARS_PER_TOKEN;
78
+ // 这一行**自己**就是压垮保留预算的那一行,故它也进阴影区(切点是闭区间的
79
+ // 上界)。把它留在外面会让「保留预算」变成一个只增不减的软上限。
80
+ if (retained > retainTokens)
81
+ return rows[i].seq;
82
+ }
83
+ return null;
84
+ }
85
+ /** 字符数折成 token 的估算值。 */
86
+ export function charsToTokens(chars) {
87
+ return chars / CHARS_PER_TOKEN;
88
+ }
89
+ //# sourceMappingURL=context-budget.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context-budget.js","sourceRoot":"","sources":["../../src/context/context-budget.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AAEH,oEAAoE;AACpE,MAAM,eAAe,GAAG,CAAC,CAAC;AAE1B;;;;;;;GAOG;AACH,MAAM,qBAAqB,GAAG,GAAG,CAAC;AAElC;;;;;;;;;;;GAWG;AACH,MAAM,oBAAoB,GAAG,IAAI,CAAC;AAElC;;;;;;GAMG;AACH,MAAM,oBAAoB,GAAG,GAAG,CAAC;AAiBjC;;;;;;;GAOG;AACH,MAAM,UAAU,uBAAuB,CAAC,CAAiB;IACvD,MAAM,aAAa,GACjB,CAAC,CAAC,eAAe,IAAI,CAAC,CAAC,gBAAgB,GAAG,oBAAoB,CAAC;IACjE,MAAM,GAAG,GAAG,CAAC,CAAC,gBAAgB,GAAG,aAAa,GAAG,CAAC,CAAC,aAAa,CAAC;IACjE,OAAO,IAAI,CAAC,GAAG,CACb,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC,gBAAgB,GAAG,qBAAqB,CAAC,EACzD,CAAC,CAAC,gBAAgB,GAAG,oBAAoB,CAC1C,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAAC,KAAoB;IAClD,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,KAAK,IAAI,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,MAAM,IAAI,CAAC,CAAC;IAC7C,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAOD;;;;;;;;;GASG;AACH,MAAM,UAAU,eAAe,CAC7B,IAAmB,EACnB,YAAoB;IAEpB,IAAI,QAAQ,GAAG,CAAC,CAAC;IACjB,KAAK,IAAI,CAAC,GAAG,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAC1C,QAAQ,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,eAAe,CAAC;QAC5C,wCAAwC;QACxC,kCAAkC;QAClC,IAAI,QAAQ,GAAG,YAAY;YAAE,OAAO,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;IAClD,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,wBAAwB;AACxB,MAAM,UAAU,aAAa,CAAC,KAAa;IACzC,OAAO,KAAK,GAAG,eAAe,CAAC;AACjC,CAAC"}
@@ -0,0 +1,3 @@
1
+ export { charsToTokens, computeContextThreshold, computePruneCut, measureRowChars, type PrunableRow, type ThresholdInput, } from './context-budget.js';
2
+ export { CONTEXT_BUDGET_DEFAULTS, CONTEXT_BUDGET_HOOK_META, CONTEXT_BUDGET_TURN_STATE_KEY, ContextBudgetHook, ContextBudgetTracker, createContextBudgetTracker, registerContextBudgetHook, } from './context-budget-tracker.js';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/context/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,EACb,uBAAuB,EACvB,eAAe,EACf,eAAe,EACf,KAAK,WAAW,EAChB,KAAK,cAAc,GACpB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,uBAAuB,EACvB,wBAAwB,EACxB,6BAA6B,EAC7B,iBAAiB,EACjB,oBAAoB,EACpB,0BAA0B,EAC1B,yBAAyB,GAC1B,MAAM,6BAA6B,CAAC"}
@@ -0,0 +1,3 @@
1
+ export { charsToTokens, computeContextThreshold, computePruneCut, measureRowChars, } from './context-budget.js';
2
+ export { CONTEXT_BUDGET_DEFAULTS, CONTEXT_BUDGET_HOOK_META, CONTEXT_BUDGET_TURN_STATE_KEY, ContextBudgetHook, ContextBudgetTracker, createContextBudgetTracker, registerContextBudgetHook, } from './context-budget-tracker.js';
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/context/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,EACb,uBAAuB,EACvB,eAAe,EACf,eAAe,GAGhB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,uBAAuB,EACvB,wBAAwB,EACxB,6BAA6B,EAC7B,iBAAiB,EACjB,oBAAoB,EACpB,0BAA0B,EAC1B,yBAAyB,GAC1B,MAAM,6BAA6B,CAAC"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * 重复工具调用提醒,**作为扩展接在 turn hook 上**——内核因此不再认识「重复调用」
3
+ * 这件事,它只知道「发起一次工具调用前问一句 preToolUse」。
4
+ *
5
+ * 纯文本层(链怎么记、什么时候出声、说什么)仍在 `runtime/loop-reminder.ts`,
6
+ * 本文件只做接线。
7
+ *
8
+ * **记账与投递在同一个点上**:记在**调用发起处**(被拒绝、报错的调用一样计数
9
+ * ——模型反复撞一个必失败的调用正是最该提醒的循环),劝告随决策的 `systemNote`
10
+ * 挂到**同一次调用的结果**上,归属天然精确。
11
+ *
12
+ * **不能改成「订阅事件流去记账」**(讨论中出现过这个说法,是错的):note 是同步
13
+ * 调用、同步返回劝告,而劝告要跟着这次调用的结果走。改成订阅就是异步消费同步
14
+ * 生产,`tool-call` 事件还没被处理、结果已经落定——竞态,症状是「提醒偶尔不
15
+ * 出现」。能靠订阅的只有不影响本轮行为的事后观测。
16
+ */
17
+ import type { TurnHookRegistry } from '../hooks/turn-hook.registry.js';
18
+ import { type PreToolUseResult, type TurnContext, type TurnHookImpl, type TurnHookMeta } from '../hooks/turn-hook.types.js';
19
+ import type { ToolRegistry } from '../tools/tool-registry.js';
20
+ /**
21
+ * 记账链。**order 取最小**:链要看到最接近模型原始输出的那份入参,别的
22
+ * `preToolUse` 插件改写过之后再记,会把「同一次调用」判成换了参数。
23
+ */
24
+ export declare const REPEAT_CALL_HOOK_META: TurnHookMeta;
25
+ export declare class RepeatCallHook implements TurnHookImpl {
26
+ private readonly tools;
27
+ constructor(tools: ToolRegistry);
28
+ preToolUse(ctx: TurnContext, toolName: string, input: unknown): Promise<PreToolUseResult>;
29
+ }
30
+ /** 把重复调用提醒挂到注册表上(runtime 的缺省扩展,宿主可以不挂)。 */
31
+ export declare function registerRepeatCallHook(hooks: TurnHookRegistry, tools: ToolRegistry): void;
32
+ //# sourceMappingURL=repeat-call.hook.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"repeat-call.hook.d.ts","sourceRoot":"","sources":["../../src/extensions/repeat-call.hook.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AACvE,OAAO,EACL,KAAK,gBAAgB,EACrB,KAAK,WAAW,EAChB,KAAK,YAAY,EACjB,KAAK,YAAY,EAElB,MAAM,6BAA6B,CAAC;AACrC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAM9D;;;GAGG;AACH,eAAO,MAAM,qBAAqB,EAAE,YAKnC,CAAC;AAEF,qBAAa,cAAe,YAAW,YAAY;IACrC,OAAO,CAAC,QAAQ,CAAC,KAAK;gBAAL,KAAK,EAAE,YAAY;IAEhD,UAAU,CACR,GAAG,EAAE,WAAW,EAChB,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,OAAO,GACb,OAAO,CAAC,gBAAgB,CAAC;CAmB7B;AAED,2CAA2C;AAC3C,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,gBAAgB,EACvB,KAAK,EAAE,YAAY,GAClB,IAAI,CAEN"}