@animalabs/agent-framework 0.26.2 → 0.28.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 (371) hide show
  1. package/README.md +99 -8
  2. package/dist/src/agent.d.ts +291 -23
  3. package/dist/src/agent.d.ts.map +1 -1
  4. package/dist/src/agent.js +596 -61
  5. package/dist/src/agent.js.map +1 -1
  6. package/dist/src/api/server.d.ts.map +1 -1
  7. package/dist/src/api/server.js +5 -4
  8. package/dist/src/api/server.js.map +1 -1
  9. package/dist/src/auto-continue.d.ts +34 -0
  10. package/dist/src/auto-continue.d.ts.map +1 -0
  11. package/dist/src/auto-continue.js +36 -0
  12. package/dist/src/auto-continue.js.map +1 -0
  13. package/dist/src/code-execution/isolate/scripts.d.ts +11 -0
  14. package/dist/src/code-execution/isolate/scripts.d.ts.map +1 -1
  15. package/dist/src/code-execution/isolate/scripts.js +5 -1
  16. package/dist/src/code-execution/isolate/scripts.js.map +1 -1
  17. package/dist/src/cut-off-round.d.ts +24 -0
  18. package/dist/src/cut-off-round.d.ts.map +1 -0
  19. package/dist/src/cut-off-round.js +87 -0
  20. package/dist/src/cut-off-round.js.map +1 -0
  21. package/dist/src/framework.d.ts +1038 -193
  22. package/dist/src/framework.d.ts.map +1 -1
  23. package/dist/src/framework.js +5967 -1514
  24. package/dist/src/framework.js.map +1 -1
  25. package/dist/src/gate/event-gate.d.ts +405 -46
  26. package/dist/src/gate/event-gate.d.ts.map +1 -1
  27. package/dist/src/gate/event-gate.js +2646 -399
  28. package/dist/src/gate/event-gate.js.map +1 -1
  29. package/dist/src/gate/index.d.ts +3 -2
  30. package/dist/src/gate/index.d.ts.map +1 -1
  31. package/dist/src/gate/index.js +2 -1
  32. package/dist/src/gate/index.js.map +1 -1
  33. package/dist/src/gate/recipe-reconcile.d.ts +103 -0
  34. package/dist/src/gate/recipe-reconcile.d.ts.map +1 -0
  35. package/dist/src/gate/recipe-reconcile.js +325 -0
  36. package/dist/src/gate/recipe-reconcile.js.map +1 -0
  37. package/dist/src/gate/reply-judge.d.ts +116 -0
  38. package/dist/src/gate/reply-judge.d.ts.map +1 -0
  39. package/dist/src/gate/reply-judge.js +467 -0
  40. package/dist/src/gate/reply-judge.js.map +1 -0
  41. package/dist/src/gate/types.d.ts +229 -8
  42. package/dist/src/gate/types.d.ts.map +1 -1
  43. package/dist/src/heartbeat/heartbeat.d.ts +184 -0
  44. package/dist/src/heartbeat/heartbeat.d.ts.map +1 -0
  45. package/dist/src/heartbeat/heartbeat.js +752 -0
  46. package/dist/src/heartbeat/heartbeat.js.map +1 -0
  47. package/dist/src/heartbeat/reminder-time.d.ts +5 -0
  48. package/dist/src/heartbeat/reminder-time.d.ts.map +1 -0
  49. package/dist/src/heartbeat/reminder-time.js +107 -0
  50. package/dist/src/heartbeat/reminder-time.js.map +1 -0
  51. package/dist/src/index.d.ts +10 -4
  52. package/dist/src/index.d.ts.map +1 -1
  53. package/dist/src/index.js +7 -2
  54. package/dist/src/index.js.map +1 -1
  55. package/dist/src/mcpl/capability-mask.d.ts.map +1 -1
  56. package/dist/src/mcpl/capability-mask.js +3 -2
  57. package/dist/src/mcpl/capability-mask.js.map +1 -1
  58. package/dist/src/mcpl/channel-registry.d.ts +433 -113
  59. package/dist/src/mcpl/channel-registry.d.ts.map +1 -1
  60. package/dist/src/mcpl/channel-registry.js +1154 -435
  61. package/dist/src/mcpl/channel-registry.js.map +1 -1
  62. package/dist/src/mcpl/conversation-router.d.ts +16 -8
  63. package/dist/src/mcpl/conversation-router.d.ts.map +1 -1
  64. package/dist/src/mcpl/conversation-router.js +29 -15
  65. package/dist/src/mcpl/conversation-router.js.map +1 -1
  66. package/dist/src/mcpl/convert-block.d.ts.map +1 -1
  67. package/dist/src/mcpl/convert-block.js +14 -2
  68. package/dist/src/mcpl/convert-block.js.map +1 -1
  69. package/dist/src/mcpl/hook-orchestrator.d.ts +7 -1
  70. package/dist/src/mcpl/hook-orchestrator.d.ts.map +1 -1
  71. package/dist/src/mcpl/hook-orchestrator.js +32 -7
  72. package/dist/src/mcpl/hook-orchestrator.js.map +1 -1
  73. package/dist/src/mcpl/inbound-source.d.ts +26 -10
  74. package/dist/src/mcpl/inbound-source.d.ts.map +1 -1
  75. package/dist/src/mcpl/inbound-source.js +40 -69
  76. package/dist/src/mcpl/inbound-source.js.map +1 -1
  77. package/dist/src/mcpl/index.d.ts +5 -1
  78. package/dist/src/mcpl/index.d.ts.map +1 -1
  79. package/dist/src/mcpl/index.js +4 -0
  80. package/dist/src/mcpl/index.js.map +1 -1
  81. package/dist/src/mcpl/inference-router.d.ts +14 -2
  82. package/dist/src/mcpl/inference-router.d.ts.map +1 -1
  83. package/dist/src/mcpl/inference-router.js +73 -28
  84. package/dist/src/mcpl/inference-router.js.map +1 -1
  85. package/dist/src/mcpl/prose-grammar.d.ts +4 -0
  86. package/dist/src/mcpl/prose-grammar.d.ts.map +1 -1
  87. package/dist/src/mcpl/prose-grammar.js +6 -0
  88. package/dist/src/mcpl/prose-grammar.js.map +1 -1
  89. package/dist/src/mcpl/protocol-family.d.ts.map +1 -1
  90. package/dist/src/mcpl/protocol-family.js +3 -0
  91. package/dist/src/mcpl/protocol-family.js.map +1 -1
  92. package/dist/src/mcpl/push-coalescer.d.ts +20 -2
  93. package/dist/src/mcpl/push-coalescer.d.ts.map +1 -1
  94. package/dist/src/mcpl/push-coalescer.js +33 -11
  95. package/dist/src/mcpl/push-coalescer.js.map +1 -1
  96. package/dist/src/mcpl/reference-fetcher.d.ts +63 -42
  97. package/dist/src/mcpl/reference-fetcher.d.ts.map +1 -1
  98. package/dist/src/mcpl/reference-fetcher.js +177 -145
  99. package/dist/src/mcpl/reference-fetcher.js.map +1 -1
  100. package/dist/src/mcpl/references.d.ts +380 -46
  101. package/dist/src/mcpl/references.d.ts.map +1 -1
  102. package/dist/src/mcpl/references.js +736 -77
  103. package/dist/src/mcpl/references.js.map +1 -1
  104. package/dist/src/mcpl/server-connection.d.ts +93 -4
  105. package/dist/src/mcpl/server-connection.d.ts.map +1 -1
  106. package/dist/src/mcpl/server-connection.js +176 -11
  107. package/dist/src/mcpl/server-connection.js.map +1 -1
  108. package/dist/src/mcpl/tags.d.ts +9 -2
  109. package/dist/src/mcpl/tags.d.ts.map +1 -1
  110. package/dist/src/mcpl/tags.js +12 -2
  111. package/dist/src/mcpl/tags.js.map +1 -1
  112. package/dist/src/mcpl/tool-lifecycle.d.ts +11 -0
  113. package/dist/src/mcpl/tool-lifecycle.d.ts.map +1 -1
  114. package/dist/src/mcpl/tool-lifecycle.js +21 -0
  115. package/dist/src/mcpl/tool-lifecycle.js.map +1 -1
  116. package/dist/src/mcpl/tool-presence.d.ts +311 -0
  117. package/dist/src/mcpl/tool-presence.d.ts.map +1 -0
  118. package/dist/src/mcpl/tool-presence.js +697 -0
  119. package/dist/src/mcpl/tool-presence.js.map +1 -0
  120. package/dist/src/mcpl/tool-result-normalize.d.ts +9 -3
  121. package/dist/src/mcpl/tool-result-normalize.d.ts.map +1 -1
  122. package/dist/src/mcpl/tool-result-normalize.js +14 -6
  123. package/dist/src/mcpl/tool-result-normalize.js.map +1 -1
  124. package/dist/src/mcpl/tool-signature.d.ts +46 -0
  125. package/dist/src/mcpl/tool-signature.d.ts.map +1 -0
  126. package/dist/src/mcpl/tool-signature.js +321 -0
  127. package/dist/src/mcpl/tool-signature.js.map +1 -0
  128. package/dist/src/mcpl/toolset-host.d.ts +251 -0
  129. package/dist/src/mcpl/toolset-host.d.ts.map +1 -0
  130. package/dist/src/mcpl/toolset-host.js +720 -0
  131. package/dist/src/mcpl/toolset-host.js.map +1 -0
  132. package/dist/src/mcpl/toolsets-module.d.ts +83 -0
  133. package/dist/src/mcpl/toolsets-module.d.ts.map +1 -0
  134. package/dist/src/mcpl/toolsets-module.js +523 -0
  135. package/dist/src/mcpl/toolsets-module.js.map +1 -0
  136. package/dist/src/mcpl/transport.d.ts +2 -2
  137. package/dist/src/mcpl/transport.d.ts.map +1 -1
  138. package/dist/src/mcpl/transport.js +3 -2
  139. package/dist/src/mcpl/transport.js.map +1 -1
  140. package/dist/src/mcpl/types.d.ts +24 -2
  141. package/dist/src/mcpl/types.d.ts.map +1 -1
  142. package/dist/src/mcpl/types.js.map +1 -1
  143. package/dist/src/mcpl/visible-content.d.ts +7 -9
  144. package/dist/src/mcpl/visible-content.d.ts.map +1 -1
  145. package/dist/src/mcpl/visible-content.js +21 -9
  146. package/dist/src/mcpl/visible-content.js.map +1 -1
  147. package/dist/src/module-registry.d.ts +27 -9
  148. package/dist/src/module-registry.d.ts.map +1 -1
  149. package/dist/src/module-registry.js +77 -17
  150. package/dist/src/module-registry.js.map +1 -1
  151. package/dist/src/modules/discord/index.js +1 -1
  152. package/dist/src/modules/discord/index.js.map +1 -1
  153. package/dist/src/modules/history/index.d.ts +2 -1
  154. package/dist/src/modules/history/index.d.ts.map +1 -1
  155. package/dist/src/modules/history/index.js +73 -28
  156. package/dist/src/modules/history/index.js.map +1 -1
  157. package/dist/src/modules/history/semantic.d.ts +108 -6
  158. package/dist/src/modules/history/semantic.d.ts.map +1 -1
  159. package/dist/src/modules/history/semantic.js +273 -57
  160. package/dist/src/modules/history/semantic.js.map +1 -1
  161. package/dist/src/modules/workspace/answers.d.ts +22 -0
  162. package/dist/src/modules/workspace/answers.d.ts.map +1 -0
  163. package/dist/src/modules/workspace/answers.js +123 -0
  164. package/dist/src/modules/workspace/answers.js.map +1 -0
  165. package/dist/src/modules/workspace/branch-intent.d.ts +5 -3
  166. package/dist/src/modules/workspace/branch-intent.d.ts.map +1 -1
  167. package/dist/src/modules/workspace/branch-intent.js +6 -2
  168. package/dist/src/modules/workspace/branch-intent.js.map +1 -1
  169. package/dist/src/modules/workspace/direct-write.d.ts +184 -0
  170. package/dist/src/modules/workspace/direct-write.d.ts.map +1 -0
  171. package/dist/src/modules/workspace/direct-write.js +417 -0
  172. package/dist/src/modules/workspace/direct-write.js.map +1 -0
  173. package/dist/src/modules/workspace/disk-agreement.d.ts +33 -11
  174. package/dist/src/modules/workspace/disk-agreement.d.ts.map +1 -1
  175. package/dist/src/modules/workspace/disk-agreement.js +48 -17
  176. package/dist/src/modules/workspace/disk-agreement.js.map +1 -1
  177. package/dist/src/modules/workspace/edit-text.d.ts +27 -12
  178. package/dist/src/modules/workspace/edit-text.d.ts.map +1 -1
  179. package/dist/src/modules/workspace/edit-text.js +61 -29
  180. package/dist/src/modules/workspace/edit-text.js.map +1 -1
  181. package/dist/src/modules/workspace/effects.d.ts +10 -0
  182. package/dist/src/modules/workspace/effects.d.ts.map +1 -1
  183. package/dist/src/modules/workspace/effects.js +21 -14
  184. package/dist/src/modules/workspace/effects.js.map +1 -1
  185. package/dist/src/modules/workspace/index.d.ts +308 -78
  186. package/dist/src/modules/workspace/index.d.ts.map +1 -1
  187. package/dist/src/modules/workspace/index.js +2103 -720
  188. package/dist/src/modules/workspace/index.js.map +1 -1
  189. package/dist/src/modules/workspace/observe.d.ts +75 -63
  190. package/dist/src/modules/workspace/observe.d.ts.map +1 -1
  191. package/dist/src/modules/workspace/observe.js +366 -180
  192. package/dist/src/modules/workspace/observe.js.map +1 -1
  193. package/dist/src/modules/workspace/read-page.d.ts +41 -0
  194. package/dist/src/modules/workspace/read-page.d.ts.map +1 -0
  195. package/dist/src/modules/workspace/read-page.js +219 -0
  196. package/dist/src/modules/workspace/read-page.js.map +1 -0
  197. package/dist/src/modules/workspace/reconcile.d.ts.map +1 -1
  198. package/dist/src/modules/workspace/reconcile.js +26 -16
  199. package/dist/src/modules/workspace/reconcile.js.map +1 -1
  200. package/dist/src/modules/workspace/result-text.d.ts +68 -0
  201. package/dist/src/modules/workspace/result-text.d.ts.map +1 -0
  202. package/dist/src/modules/workspace/result-text.js +94 -0
  203. package/dist/src/modules/workspace/result-text.js.map +1 -0
  204. package/dist/src/modules/workspace/sync.d.ts +9 -0
  205. package/dist/src/modules/workspace/sync.d.ts.map +1 -1
  206. package/dist/src/modules/workspace/sync.js +14 -0
  207. package/dist/src/modules/workspace/sync.js.map +1 -1
  208. package/dist/src/modules/workspace/text.d.ts +29 -12
  209. package/dist/src/modules/workspace/text.d.ts.map +1 -1
  210. package/dist/src/modules/workspace/text.js +35 -33
  211. package/dist/src/modules/workspace/text.js.map +1 -1
  212. package/dist/src/modules/workspace/types.d.ts +137 -60
  213. package/dist/src/modules/workspace/types.d.ts.map +1 -1
  214. package/dist/src/modules/workspace/types.js.map +1 -1
  215. package/dist/src/modules/workspace/watcher.d.ts.map +1 -1
  216. package/dist/src/modules/workspace/watcher.js +8 -3
  217. package/dist/src/modules/workspace/watcher.js.map +1 -1
  218. package/dist/src/prose-drafts.d.ts +4 -3
  219. package/dist/src/prose-drafts.d.ts.map +1 -1
  220. package/dist/src/prose-drafts.js +3 -2
  221. package/dist/src/prose-drafts.js.map +1 -1
  222. package/dist/src/reasoning-loss-notice.d.ts +23 -0
  223. package/dist/src/reasoning-loss-notice.d.ts.map +1 -0
  224. package/dist/src/reasoning-loss-notice.js +50 -0
  225. package/dist/src/reasoning-loss-notice.js.map +1 -0
  226. package/dist/src/reasoning-loss.d.ts +24 -0
  227. package/dist/src/reasoning-loss.d.ts.map +1 -0
  228. package/dist/src/reasoning-loss.js +102 -0
  229. package/dist/src/reasoning-loss.js.map +1 -0
  230. package/dist/src/send-tools.d.ts +3 -2
  231. package/dist/src/send-tools.d.ts.map +1 -1
  232. package/dist/src/send-tools.js +3 -2
  233. package/dist/src/send-tools.js.map +1 -1
  234. package/dist/src/sent-rows.d.ts +59 -0
  235. package/dist/src/sent-rows.d.ts.map +1 -0
  236. package/dist/src/sent-rows.js +145 -0
  237. package/dist/src/sent-rows.js.map +1 -0
  238. package/dist/src/silent-heartbeat.d.ts +17 -10
  239. package/dist/src/silent-heartbeat.d.ts.map +1 -1
  240. package/dist/src/silent-heartbeat.js.map +1 -1
  241. package/dist/src/stable-hash.d.ts +3 -0
  242. package/dist/src/stable-hash.d.ts.map +1 -0
  243. package/dist/src/stable-hash.js +15 -0
  244. package/dist/src/stable-hash.js.map +1 -0
  245. package/dist/src/stored-injections.d.ts +99 -0
  246. package/dist/src/stored-injections.d.ts.map +1 -0
  247. package/dist/src/stored-injections.js +106 -0
  248. package/dist/src/stored-injections.js.map +1 -0
  249. package/dist/src/text-as-stored.d.ts +4 -3
  250. package/dist/src/text-as-stored.d.ts.map +1 -1
  251. package/dist/src/text-as-stored.js +4 -3
  252. package/dist/src/text-as-stored.js.map +1 -1
  253. package/dist/src/thinking-drops.d.ts +74 -0
  254. package/dist/src/thinking-drops.d.ts.map +1 -0
  255. package/dist/src/thinking-drops.js +96 -0
  256. package/dist/src/thinking-drops.js.map +1 -0
  257. package/dist/src/tool-args.d.ts +12 -0
  258. package/dist/src/tool-args.d.ts.map +1 -1
  259. package/dist/src/tool-args.js +35 -1
  260. package/dist/src/tool-args.js.map +1 -1
  261. package/dist/src/tool-image-ledger.d.ts +9 -8
  262. package/dist/src/tool-image-ledger.d.ts.map +1 -1
  263. package/dist/src/tool-image-ledger.js +9 -8
  264. package/dist/src/tool-image-ledger.js.map +1 -1
  265. package/dist/src/tool-presentation.d.ts.map +1 -1
  266. package/dist/src/tool-presentation.js +3 -1
  267. package/dist/src/tool-presentation.js.map +1 -1
  268. package/dist/src/tool-result-guard.d.ts +12 -6
  269. package/dist/src/tool-result-guard.d.ts.map +1 -1
  270. package/dist/src/tool-result-guard.js +44 -17
  271. package/dist/src/tool-result-guard.js.map +1 -1
  272. package/dist/src/tool-result-history.d.ts +176 -24
  273. package/dist/src/tool-result-history.d.ts.map +1 -1
  274. package/dist/src/tool-result-history.js +411 -91
  275. package/dist/src/tool-result-history.js.map +1 -1
  276. package/dist/src/tune-out/coordinator.d.ts +17 -9
  277. package/dist/src/tune-out/coordinator.d.ts.map +1 -1
  278. package/dist/src/tune-out/coordinator.js +84 -37
  279. package/dist/src/tune-out/coordinator.js.map +1 -1
  280. package/dist/src/tune-out/tools.d.ts +4 -1
  281. package/dist/src/tune-out/tools.d.ts.map +1 -1
  282. package/dist/src/types/agent.d.ts +217 -7
  283. package/dist/src/types/agent.d.ts.map +1 -1
  284. package/dist/src/types/events.d.ts +33 -9
  285. package/dist/src/types/events.d.ts.map +1 -1
  286. package/dist/src/types/framework.d.ts +39 -3
  287. package/dist/src/types/framework.d.ts.map +1 -1
  288. package/dist/src/types/module.d.ts +95 -9
  289. package/dist/src/types/module.d.ts.map +1 -1
  290. package/dist/src/types/trace.d.ts +91 -3
  291. package/dist/src/types/trace.d.ts.map +1 -1
  292. package/package.json +5 -4
  293. package/src/agent.ts +661 -67
  294. package/src/api/server.ts +5 -4
  295. package/src/auto-continue.ts +43 -0
  296. package/src/code-execution/isolate/scripts.ts +11 -3
  297. package/src/cut-off-round.ts +98 -0
  298. package/src/framework.ts +6168 -1540
  299. package/src/gate/event-gate.ts +2895 -405
  300. package/src/gate/index.ts +10 -1
  301. package/src/gate/recipe-reconcile.ts +355 -0
  302. package/src/gate/reply-judge.ts +512 -0
  303. package/src/gate/types.ts +234 -9
  304. package/src/heartbeat/heartbeat.ts +804 -0
  305. package/src/heartbeat/reminder-time.ts +107 -0
  306. package/src/index.ts +11 -4
  307. package/src/mcpl/capability-mask.ts +3 -2
  308. package/src/mcpl/channel-registry.ts +1222 -468
  309. package/src/mcpl/conversation-router.ts +34 -16
  310. package/src/mcpl/convert-block.ts +14 -1
  311. package/src/mcpl/hook-orchestrator.ts +33 -6
  312. package/src/mcpl/inbound-source.ts +42 -69
  313. package/src/mcpl/index.ts +6 -1
  314. package/src/mcpl/inference-router.ts +79 -34
  315. package/src/mcpl/prose-grammar.ts +7 -0
  316. package/src/mcpl/protocol-family.ts +2 -0
  317. package/src/mcpl/push-coalescer.ts +51 -13
  318. package/src/mcpl/reference-fetcher.ts +201 -162
  319. package/src/mcpl/references.ts +851 -77
  320. package/src/mcpl/server-connection.ts +189 -11
  321. package/src/mcpl/tags.ts +13 -2
  322. package/src/mcpl/tool-lifecycle.ts +21 -0
  323. package/src/mcpl/tool-presence.ts +716 -0
  324. package/src/mcpl/tool-result-normalize.ts +18 -6
  325. package/src/mcpl/tool-signature.ts +316 -0
  326. package/src/mcpl/toolset-host.ts +727 -0
  327. package/src/mcpl/toolsets-module.ts +545 -0
  328. package/src/mcpl/transport.ts +3 -2
  329. package/src/mcpl/types.ts +25 -2
  330. package/src/mcpl/visible-content.ts +22 -9
  331. package/src/module-registry.ts +85 -26
  332. package/src/modules/discord/index.ts +1 -1
  333. package/src/modules/history/index.ts +70 -30
  334. package/src/modules/history/semantic.ts +308 -54
  335. package/src/modules/workspace/answers.ts +133 -0
  336. package/src/modules/workspace/branch-intent.ts +10 -5
  337. package/src/modules/workspace/direct-write.ts +460 -0
  338. package/src/modules/workspace/disk-agreement.ts +52 -21
  339. package/src/modules/workspace/edit-text.ts +84 -35
  340. package/src/modules/workspace/effects.ts +22 -13
  341. package/src/modules/workspace/index.ts +2142 -723
  342. package/src/modules/workspace/observe.ts +381 -177
  343. package/src/modules/workspace/read-page.ts +228 -0
  344. package/src/modules/workspace/reconcile.ts +27 -15
  345. package/src/modules/workspace/result-text.ts +121 -0
  346. package/src/modules/workspace/sync.ts +16 -0
  347. package/src/modules/workspace/text.ts +58 -32
  348. package/src/modules/workspace/types.ts +137 -60
  349. package/src/modules/workspace/watcher.ts +8 -3
  350. package/src/prose-drafts.ts +4 -3
  351. package/src/reasoning-loss-notice.ts +62 -0
  352. package/src/reasoning-loss.ts +120 -0
  353. package/src/send-tools.ts +3 -2
  354. package/src/sent-rows.ts +162 -0
  355. package/src/silent-heartbeat.ts +17 -10
  356. package/src/stable-hash.ts +14 -0
  357. package/src/stored-injections.ts +131 -0
  358. package/src/text-as-stored.ts +4 -3
  359. package/src/thinking-drops.ts +135 -0
  360. package/src/tool-args.ts +34 -1
  361. package/src/tool-image-ledger.ts +9 -8
  362. package/src/tool-presentation.ts +3 -1
  363. package/src/tool-result-guard.ts +45 -17
  364. package/src/tool-result-history.ts +471 -90
  365. package/src/tune-out/coordinator.ts +80 -37
  366. package/src/tune-out/tools.ts +4 -1
  367. package/src/types/agent.ts +220 -7
  368. package/src/types/events.ts +33 -9
  369. package/src/types/framework.ts +36 -3
  370. package/src/types/module.ts +91 -9
  371. package/src/types/trace.ts +94 -3
@@ -18,7 +18,7 @@
18
18
  import { randomUUID } from 'node:crypto';
19
19
  import type { ContentBlock } from '@animalabs/membrane';
20
20
  import type { StoredMessage } from '@animalabs/context-manager';
21
- import type { ChannelRegistry, TuneOutParams } from '../mcpl/channel-registry.js';
21
+ import type { ChannelRef, ChannelRegistry, TuneOutParams } from '../mcpl/channel-registry.js';
22
22
  import type { McplServerRegistry } from '../mcpl/server-registry.js';
23
23
  import { CapabilityGrant } from '../mcpl/capability-grant.js';
24
24
  import { armAfter, armAt } from '../deadline-timer.js';
@@ -45,7 +45,7 @@ const CUT_MARK = " [cut to fit; the whole message is in the channel's history]";
45
45
  * its transport is now where the repeat tried to open it again (`transport`,
46
46
  * from the framework's dispatch), then how to change the settings.
47
47
  */
48
- export function alreadyTunedOutText(channelId: string, p: TuneOutParams, transport?: string): string {
48
+ export function alreadyTunedOutText(shown: string, p: TuneOutParams, transport?: string): string {
49
49
  // A duration so long its end is past what a Date can hold has no time to show.
50
50
  const expires = p.expiresAtMs !== undefined ? new Date(p.expiresAtMs) : undefined;
51
51
  const until = expires && Number.isFinite(expires.getTime())
@@ -53,7 +53,7 @@ export function alreadyTunedOutText(channelId: string, p: TuneOutParams, transpo
53
53
  : '';
54
54
  // A thrown error's words may end without a stop.
55
55
  const now = transport === undefined ? '' : /[.!?]$/.test(transport) ? `${transport} ` : `${transport}. `;
56
- return `Nothing changed${transport !== undefined ? ' in the tune-out' : ''}: ${JSON.stringify(channelId)} is already `
56
+ return `Nothing changed${transport !== undefined ? ' in the tune-out' : ''}: ${JSON.stringify(shown)} is already `
57
57
  + `tuned out, with cadenceSeconds ${p.cadenceSeconds}, backlogCap ${p.backlogCap} and maxWakes ${p.maxWakes}${until}. `
58
58
  + now
59
59
  + 'To change those, cancel it first with tune_out mode "cancel", which delivers its backlog to you now, then call '
@@ -113,7 +113,7 @@ export interface TuneOutFrameworkHooks {
113
113
  /** Move the subconscious window anchor (never forward past active epochs). */
114
114
  setSubconsciousAnchor: (sequence: number) => void;
115
115
  /** True when a channel is bound to a conversation-fork agent. */
116
- isForkBound: (channelId: string) => boolean;
116
+ isForkBound: (channel: ChannelRef) => boolean;
117
117
  /** Gate privileged-users list (#77: privileged authors wake, like mentions). */
118
118
  isPrivilegedAuthor: (authorId: string | null | undefined) => boolean;
119
119
  /** speak_in_channel master switch (recipe-side, canary-gated). */
@@ -144,6 +144,15 @@ export class TuneOutCoordinator {
144
144
  return `${serverId}\0${channelId}`;
145
145
  }
146
146
 
147
+ /** A channel as the resident and the subconscious are shown it
148
+ * (ChannelRegistry.nameShown): its id, or, where another server registers
149
+ * the same id, its server-qualified name, which tune_out and
150
+ * cancel_tuneout take back; or, for a channel no string picks alone, its
151
+ * id and its server. */
152
+ private shown(serverId: string, channelId: string): string {
153
+ return this.channelRegistry.nameShown({ serverId, channelId });
154
+ }
155
+
147
156
  /** Restart cadence + expiry timers and re-anchor after a process restart. */
148
157
  resumeActiveEpochs(): void {
149
158
  let oldestAnchor: number | null = null;
@@ -232,17 +241,17 @@ export class TuneOutCoordinator {
232
241
  + 'whoever runs this host.',
233
242
  };
234
243
  }
235
- if (this.hooks.isForkBound(channelId)) {
244
+ if (this.hooks.isForkBound({ serverId, channelId })) {
236
245
  return {
237
246
  ok: false,
238
- error: `Nothing changed: a conversation is bound to ${JSON.stringify(channelId)}, so its messages go to that `
247
+ error: `Nothing changed: a conversation is bound to ${JSON.stringify(this.shown(serverId, channelId))}, so its messages go to that `
239
248
  + "conversation, and tune_out won't divert a channel while one is. Calling tune_out on it again won't change "
240
249
  + 'that until the conversation ends, which happens only once the channel has been quiet for a while. Tune '
241
250
  + 'out a different channel, or ask whoever runs this host if this one should be diverted.',
242
251
  };
243
252
  }
244
253
  const current = this.channelRegistry.getTuneOutState(serverId, channelId);
245
- if (current) return { ok: false, error: alreadyTunedOutText(channelId, current.params), alreadyTunedOut: true };
254
+ if (current) return { ok: false, error: alreadyTunedOutText(this.shown(serverId, channelId), current.params), alreadyTunedOut: true };
246
255
  // A tool's input reaches here as the model wrote it, and the store can't
247
256
  // keep a NaN or an Infinity: its append would throw after the registry
248
257
  // had marked the channel tuned out. So each option is read as a number
@@ -328,7 +337,7 @@ export class TuneOutCoordinator {
328
337
  const ended = this.channelRegistry.cancelTuneOut(serverId, channelId, 'open', source);
329
338
  if (!ended) {
330
339
  // Its reader is the resident's tune_out: cancel_tuneout finds the channel first.
331
- return { ok: false, error: this.notTunedOut(channelId, 'you') };
340
+ return { ok: false, error: this.notTunedOut(this.shown(serverId, channelId), 'you') };
332
341
  }
333
342
  this.clearTimers(serverId, channelId);
334
343
  this.divertedSinceInvocation.delete(this.key(serverId, channelId));
@@ -359,10 +368,12 @@ export class TuneOutCoordinator {
359
368
  .join('\n');
360
369
  return `${authorOf(m)}: ${text}`;
361
370
  };
362
- const lifecycle = `[Tune-out: ${channelId} cancelled — ${reason}, ${ended.wakeCount} wake${ended.wakeCount === 1 ? '' : 's'}]`;
371
+ // The channel as the resident and the subconscious are shown it.
372
+ const name = this.shown(serverId, channelId);
373
+ const lifecycle = `[Tune-out: ${name} cancelled — ${reason}, ${ended.wakeCount} wake${ended.wakeCount === 1 ? '' : 's'}]`;
363
374
  const render = (lines: string[], truncated: number): string => {
364
375
  const attrs = [
365
- `channel="${channelId}"`,
376
+ `channel="${name}"`,
366
377
  `messages=${backlog.length}`,
367
378
  ...(truncated > 0 ? [`truncated=${truncated} (oldest; fetch_history covers the rest)`] : []),
368
379
  ];
@@ -441,7 +452,9 @@ export class TuneOutCoordinator {
441
452
  this.hooks.addMessage(
442
453
  subName,
443
454
  [{ type: 'text', text: subconsciousNote }],
444
- { kind: 'subconscious-note', channelId, epochId },
455
+ // With its server: a conversational row whose channel the framework
456
+ // reads (repinChannel), where another server's channel can share the id.
457
+ { kind: 'subconscious-note', channelId, serverId, epochId },
445
458
  );
446
459
  }
447
460
  const primary = this.hooks.primaryName();
@@ -467,7 +480,7 @@ export class TuneOutCoordinator {
467
480
  : '';
468
481
  this.hooks.addMessage(
469
482
  'user',
470
- [{ type: 'text', text: `[Tune-out cancelled: ${channelId} — ${reason}.${truncNote}${heldNote}]` }],
483
+ [{ type: 'text', text: `[Tune-out cancelled: ${this.shown(serverId, channelId)} — ${reason}.${truncNote}${heldNote}]` }],
471
484
  { system: true, kind: 'tune-out-cancel-report', channelId },
472
485
  subName,
473
486
  );
@@ -481,7 +494,7 @@ export class TuneOutCoordinator {
481
494
  subName,
482
495
  );
483
496
  }
484
- this.hooks.requestInference(subName, `tune-out cancelled: ${channelId}`, 'tune-out');
497
+ this.hooks.requestInference(subName, `tune-out cancelled: ${name}`, 'tune-out');
485
498
  }
486
499
  this.hooks.emitTrace({ type: 'tune-out:cancelled', serverId, channelId, epochId, reason, wakeCount: ended.wakeCount });
487
500
  return { ok: true };
@@ -649,16 +662,17 @@ export class TuneOutCoordinator {
649
662
  if (!subName) return;
650
663
  const key = this.key(serverId, channelId);
651
664
 
665
+ const shown = this.shown(serverId, channelId);
652
666
  const notice = trigger === 'wake'
653
- ? `[Tune-out wake: ${channelId} — ${count} addressed message${count === 1 ? '' : 's'}]`
654
- : `[Tune-out cadence: ${channelId} — ${count} diverted message${count === 1 ? '' : 's'} since your last look]`;
667
+ ? `[Tune-out wake: ${shown} — ${count} addressed message${count === 1 ? '' : 's'}]`
668
+ : `[Tune-out cadence: ${shown} — ${count} diverted message${count === 1 ? '' : 's'} since your last look]`;
655
669
  this.hooks.addMessage(
656
670
  'user',
657
671
  [{ type: 'text', text: notice }],
658
672
  { system: true, kind: `tune-out-${trigger}`, channelId },
659
673
  subName,
660
674
  );
661
- this.hooks.requestInference(subName, `tune-out ${trigger}: ${channelId}`, 'tune-out');
675
+ this.hooks.requestInference(subName, `tune-out ${trigger}: ${shown}`, 'tune-out');
662
676
  // Counted from here only once the turn has been asked for, so a turn that
663
677
  // throws leaves its messages for the next period's turn.
664
678
  this.divertedSinceInvocation.set(key, 0);
@@ -740,6 +754,8 @@ export class TuneOutCoordinator {
740
754
  async handleSubconsciousTool(
741
755
  name: string,
742
756
  input: Record<string, unknown>,
757
+ /** The calling turn's own channels, for a call made inside it (the framework's callOwnChannels). */
758
+ own: readonly ChannelRef[] = [],
743
759
  ): Promise<{ success: boolean; data?: unknown; error?: string; isError?: boolean }> {
744
760
  switch (name) {
745
761
  case 'deliver_summary': {
@@ -755,19 +771,48 @@ export class TuneOutCoordinator {
755
771
  }
756
772
  const subName = this.hooks.subconsciousName();
757
773
  if (!subName) return { success: false, error: 'subconscious not configured', isError: true };
758
- // Verbatim, under its own participant name, into the resident's window.
774
+ // Verbatim, under its own participant name, into the resident's window,
775
+ // tagged with the channel the name means and its server, since the
776
+ // framework reads a conversational row's channel (repinChannel). The
777
+ // name means what it means to every channel tool: inside the calling
778
+ // turn, the id of one of the turn's own channels means that channel,
779
+ // refused where its server no longer registers it or the turn has
780
+ // channels with that id on two servers (ownChannelFor); otherwise a
781
+ // name several registered channels answer to is refused with them
782
+ // (sharedNameRefusalFor). So no row is left for a re-pin to read as
783
+ // another server's channel. A name no registered channel answers to
784
+ // is kept as given, with no server, which a re-pin reads by name when
785
+ // it weighs the row, as it reads any message without its server.
786
+ const mine = this.channelRegistry.ownChannelFor(channelId, own, 'deliver');
787
+ if (mine && 'error' in mine) return { success: false, error: mine.error, isError: true };
788
+ const shared = mine ? undefined : this.channelRegistry.sharedNameRefusalFor(channelId, 'nothing was delivered');
789
+ if (shared) return { success: false, error: shared, isError: true };
790
+ const [named] = mine ? [mine.channel] : this.channelRegistry.channelsNamed(channelId);
759
791
  this.hooks.addMessage(subName, [{ type: 'text', text }], {
760
792
  kind: 'subconscious-summary',
761
- channelId,
793
+ ...(named ? { channelId: named.channelId, serverId: named.serverId } : { channelId }),
762
794
  });
763
795
  return { success: true, data: { delivered: true } };
764
796
  }
765
797
  case 'cancel_tuneout': {
766
- const channelId = String(input.channelId ?? '');
767
- const located = this.findByChannel(channelId);
768
- if (!located) return { success: false, error: this.notTunedOut(channelId, 'the resident'), isError: true };
798
+ const name = String(input.channelId ?? '');
799
+ // The name means what it means to every channel tool, the
800
+ // resident's tune_out included: inside the calling turn, the id of
801
+ // one of the turn's own channels means that channel (ownChannelFor);
802
+ // otherwise a name several registered channels answer to is refused
803
+ // (channelsNamed), whichever of them is tuned out, never taken to be
804
+ // the tuned-out one.
805
+ const mine = this.channelRegistry.ownChannelFor(name, own);
806
+ if (mine && 'error' in mine) return { success: false, error: mine.error, isError: true };
807
+ const named = mine ? [mine.channel] : this.channelRegistry.channelsNamed(name);
808
+ const shared = mine ? undefined : this.channelRegistry.sharedNameRefusalFor(name);
809
+ if (shared) return { success: false, error: shared, isError: true };
810
+ const channel = named[0];
811
+ if (!channel || !this.channelRegistry.getTuneOutState(channel.serverId, channel.channelId)) {
812
+ return { success: false, error: this.notTunedOut(name, 'the resident'), isError: true };
813
+ }
769
814
  const note = typeof input.text === 'string' && input.text.trim() ? input.text.trim() : undefined;
770
- const result = this.cancel(located.serverId, channelId, 'subconscious', 'subconscious judgment', note);
815
+ const result = this.cancel(channel.serverId, channel.channelId, 'subconscious', 'subconscious judgment', note);
771
816
  return result.ok
772
817
  ? { success: true, data: { cancelled: true } }
773
818
  : { success: false, error: result.error, isError: true };
@@ -817,7 +862,11 @@ export class TuneOutCoordinator {
817
862
  if (!text) {
818
863
  return { success: false, error: 'Nothing was posted: speak_in_channel needs the message in "text".', isError: true };
819
864
  }
820
- return this.channelRegistry.publishForAgent(channelId, text, this.hooks.subconsciousName() ?? 'Subconscious');
865
+ // Inside the calling turn, the id of one of the turn's own channels
866
+ // means that channel, as for every channel tool (ownChannelFor).
867
+ const mine = this.channelRegistry.ownChannelFor(channelId, own, 'publish');
868
+ if (mine && 'error' in mine) return { success: false, error: mine.error, isError: true };
869
+ return this.channelRegistry.publishForAgent(mine ? mine.channel : channelId, text, this.hooks.subconsciousName() ?? 'Subconscious');
821
870
  }
822
871
  default:
823
872
  return { success: false, error: `unknown subconscious tool: ${name}`, isError: true };
@@ -825,32 +874,26 @@ export class TuneOutCoordinator {
825
874
  }
826
875
 
827
876
  /**
828
- * A cancel of a channel that isn't tuned out: which channels are, so the
829
- * next call can name one, and how a tune-out ends without one. `backlogTo`
877
+ * A cancel of a channel that isn't tuned out, by the name the caller gave
878
+ * or knows it by: which channels are, so the next call can name one, and
879
+ * how a tune-out ends without one. `backlogTo`
830
880
  * names the resident as the message's reader knows it: "you" to the
831
881
  * resident, "the resident" to the subconscious. It speaks of connected
832
882
  * channels because listActive reads the registered ones: removing a server
833
883
  * drops its channels and keeps their tune-outs, so a tune-out there is in
834
- * neither this list nor findByChannel's lookup, and the text claims nothing
835
- * about it.
884
+ * neither this list nor the name's lookup (channelsNamed, which reads the
885
+ * registered channels too), and the text claims nothing about it.
836
886
  */
837
- private notTunedOut(channelId: string, backlogTo: 'you' | 'the resident'): string {
838
- const active = this.listActive().map((e) => JSON.stringify(e.channelId));
887
+ private notTunedOut(name: string, backlogTo: 'you' | 'the resident'): string {
888
+ const active = this.listActive().map((e) => JSON.stringify(this.shown(e.serverId, e.channelId)));
839
889
  const opening = active.length === 0
840
890
  ? 'no connected channel is tuned out now.'
841
- : `no connected channel ${JSON.stringify(channelId)} is tuned out. Connected channels tuned out now: `
891
+ : `no connected channel ${JSON.stringify(name)} is tuned out. Connected channels tuned out now: `
842
892
  + `${active.join(', ')}.`;
843
893
  return `Nothing was cancelled: ${opening} A tune-out also ends by itself when its duration runs out, or at the `
844
894
  + `first wake past its wake budget, and its backlog goes to ${backlogTo} then.`;
845
895
  }
846
896
 
847
- private findByChannel(channelId: string): { serverId: string } | null {
848
- for (const entry of this.listActive()) {
849
- if (entry.channelId === channelId) return { serverId: entry.serverId };
850
- }
851
- return null;
852
- }
853
-
854
897
  /** Stop all timers (framework shutdown). */
855
898
  stop(): void {
856
899
  for (const timer of this.cadenceTimers.values()) clearTimeout(timer);
@@ -113,7 +113,10 @@ export interface SubconsciousConfig {
113
113
  * agent-prefixed identifier.
114
114
  */
115
115
  name?: string;
116
- /** Model id; defaults to the primary agent's (same-model side-process). */
116
+ /** Model id; defaults to the primary agent's (same-model side-process).
117
+ * Another id, compared exactly, makes the subconscious leave out the
118
+ * fields that describe the primary's model, its window and its thinking
119
+ * binding (SUBCONSCIOUS_MODEL_FIELDS); nothing here sets its own. */
117
120
  model?: string;
118
121
  /**
119
122
  * The voice/criteria mode block — recipe-side and co-authored with the
@@ -2,6 +2,7 @@ import type { ContentBlock, YieldingStream } from '@animalabs/membrane';
2
2
  import type { ContextStrategy } from '@animalabs/context-manager';
3
3
  import type { ToolCallId, ToolResult, ToolCall } from './events.js';
4
4
  import type { SilentHeartbeatTick } from '../silent-heartbeat.js';
5
+ import type { WakeLine } from '../gate/types.js';
5
6
 
6
7
  export type SameRoundThinkTextPolicy = 'public' | 'private';
7
8
  export type SameRoundThinkTextPolicySource =
@@ -9,6 +10,25 @@ export type SameRoundThinkTextPolicySource =
9
10
  | 'recipe'
10
11
  | 'compatibility_default';
11
12
 
13
+ /** What a continuation's `[continue]` row says (InferenceRequest.autoContinueRun). */
14
+ export interface AutoContinueRun {
15
+ /** How the agent stops, as the row puts it ("call skip_reply"). */
16
+ stop: string;
17
+ /** The turn before ended in words some or all of which were held, not
18
+ * sent, because a send in it may already have posted where they were
19
+ * going. */
20
+ heldAfterSend?: boolean;
21
+ /** Set by the scheduler: the continuation is the turn's only cause. */
22
+ sole?: boolean;
23
+ }
24
+
25
+ /** `AgentConfig.autoContinue` as an object (`true` means `{}`). */
26
+ export interface AutoContinueConfig {
27
+ /** Continuations in a row before the agent waits for the next event:
28
+ * a whole number, 1 to 20. Default 3. */
29
+ maxConsecutive?: number;
30
+ }
31
+
12
32
  /**
13
33
  * Configuration for an agent.
14
34
  */
@@ -62,7 +82,11 @@ export interface AgentConfig {
62
82
  temperature?: number;
63
83
 
64
84
  /** Max input tokens before framework breaks a yielding stream and
65
- * restarts with recompiled (compressed) context. Default: 150000. */
85
+ * restarts with recompiled (compressed) context. Default: 150000. Not
86
+ * checked mid-turn for an agent whose model binds its thinking
87
+ * (`thinkingBinding.binds`) with `physicalWindowTokens` set: a new stream
88
+ * there would take the turn's own earlier reasoning out of the request, and
89
+ * the window projection still guards the provider's hard cap. */
66
90
  maxStreamTokens?: number;
67
91
 
68
92
  /**
@@ -75,7 +99,9 @@ export interface AgentConfig {
75
99
  * request the provider will 400 (issue #92: a legal compile can walk past
76
100
  * the physical window mid-turn). The projection runs once a call on the
77
101
  * stream has reported its prompt. Unset → no projection; only the
78
- * maxStreamTokens restart applies.
102
+ * maxStreamTokens restart applies. A value is converted to a number as a
103
+ * comparison converts it, so a string such as "200000" reads as its number;
104
+ * one whose number isn't finite, such as null, reads as unset.
79
105
  */
80
106
  physicalWindowTokens?: number;
81
107
 
@@ -133,7 +159,9 @@ export interface AgentConfig {
133
159
  * Extended thinking config. When `enabled: true`, the agent runs with
134
160
  * Anthropic's native extended thinking; responses include `thinking` blocks
135
161
  * with cryptographic signatures, and the API enforces `temperature: 1`
136
- * (Membrane handles this). Omit or set `enabled: false` to disable.
162
+ * (Membrane handles this). Omit or set `enabled: false` to disable, except
163
+ * on a model whose thinking is always on (Fable, Mythos), which thinks
164
+ * whatever this says.
137
165
  */
138
166
  thinking?: {
139
167
  enabled: boolean;
@@ -143,10 +171,109 @@ export interface AgentConfig {
143
171
  /**
144
172
  * How thinking content is returned: 'summarized' (readable summary) or
145
173
  * 'omitted' (empty thinking field, signature only). Fable 5 / Opus 4.7+
146
- * default to 'omitted' — set 'summarized' to receive thinking text.
174
+ * default to 'omitted' — set 'summarized' to receive thinking text. A
175
+ * model whose thinking is always on (Fable, Mythos) is sent a thinking
176
+ * config only to carry `thinkingBinding.dropBlock`, so this reaches it
177
+ * only with that set.
147
178
  */
148
179
  display?: 'summarized' | 'omitted';
149
180
  };
181
+ /**
182
+ * How the provider binds this agent's signed thinking to the conversation
183
+ * before it. A host sets it from what it knows of the agent's model and
184
+ * route.
185
+ */
186
+ thinkingBinding?: {
187
+ /**
188
+ * Ask the provider to drop a signed thinking block whose earlier
189
+ * conversation has changed, as a fold changes it, rather than refuse the
190
+ * request. An account that enforces the binding otherwise answers such a
191
+ * request with a 400. One that doesn't decides for itself: the four
192
+ * accounts tried on 2026-10-18 dropped such blocks silently, so there the
193
+ * model sees nothing different and the report is what's new, and one
194
+ * that would show such a block to the model is asked to drop it instead.
195
+ *
196
+ * It's sent as `thinking.block_binding.prefix_mismatch_behavior:
197
+ * "drop_block"` with the `thinking-binding-controls-2026-08-01` beta,
198
+ * which membrane's Anthropic and Bedrock adapters carry (Bedrock's
199
+ * acceptance of the beta hasn't been tried). On any other adapter it does
200
+ * nothing, so a host should refuse it there. A thinking config the host
201
+ * sends itself, through `request.extra` or as `thinking` in
202
+ * `providerParams`, replaces the one membrane builds, control included.
203
+ *
204
+ * On a model whose thinking is always on (Fable, Mythos), membrane
205
+ * carries it in an adaptive thinking config whatever `thinking.enabled`
206
+ * says, with `thinking.display` when that's set, so such an agent's
207
+ * `display` takes effect only with this setting. On any other model, it
208
+ * goes only in the thinking config membrane sends while thinking is on.
209
+ * Membrane tells the first kind by its id, which names `fable` or
210
+ * `mythos`. Opus 5.5, Haiku 5.5, Sonnet 5.5, Sonnet 5, Fable 5 and Fable
211
+ * 5.1 accepted the config on 2026-10-18. Mythos hasn't been tried, and
212
+ * membrane notes that the family has refused thinking configs with a 400
213
+ * before, so for a Mythos model the setting may fail every request.
214
+ *
215
+ * On a framework turn, each call's report of the blocks the provider
216
+ * dropped goes to its `inference:usage` trace, and neither that call nor
217
+ * its stream's later calls feed the context strategy's calibration, since
218
+ * the provider doesn't bill a block it dropped and the strategy still
219
+ * counts it. After a fold, each block after the stretch it rewrote is
220
+ * bound to a conversation the request no longer holds. Where the context
221
+ * strategy still sends such a block, the provider drops it on every call
222
+ * until a later fold takes it out of the context, and while such blocks
223
+ * are sent, no stream gives a sample and the calibration keeps the value
224
+ * it had. A strategy that leaves that thinking out at the fold sends none
225
+ * to drop. The direct API carries the control too, but reads no report: it
226
+ * traces no usage and feeds no calibration.
227
+ *
228
+ * Default false: nothing is sent, and the account's default applies.
229
+ */
230
+ dropBlock?: boolean;
231
+ /**
232
+ * Whether this agent's model binds its signed thinking to the
233
+ * conversation before it, as the host knows from its own model records.
234
+ * A context manager that keeps a record of what each branch sent can
235
+ * then leave out thinking whose earlier conversation changed before the
236
+ * provider sees it. Set:
237
+ * - each compile the agent sends tells the context manager so
238
+ * (`thinkingBinding`: `binds`, `dropBlock` as set here, and the agent's
239
+ * name as the `participant` whose replies are its own), with digests
240
+ * of what the request carries ahead of its messages (`identity`: the
241
+ * system text with its system-position injections, the tools in the
242
+ * order sent, the model, and the thinking config, `maxTokens`,
243
+ * `providerParams` and `prefillUserMessage`);
244
+ * - each framework stream tells the context manager which stored rows
245
+ * its later rounds and its last reply carried as stored
246
+ * (`noteRequestSent`), naming the compile it was built from, so their
247
+ * thinking is kept at the next compile. The direct API
248
+ * (`runInference`) notes nothing, so each of its replies' thinking is
249
+ * left out at the compile after it's stored;
250
+ * - with `physicalWindowTokens` set too, `maxStreamTokens` no longer
251
+ * starts a new stream mid-turn, since the new stream's compile can take
252
+ * the turn's earlier reasoning out of the request;
253
+ * - with `dropBlock` set too, where a compile reports where the branch's
254
+ * record began (`thinkingRecordedAfter`), a block the provider drops
255
+ * that the record doesn't account for raises the
256
+ * `thinking-binding-loss` ops alert, once per incident and again if a
257
+ * call drops more. The provider reports drops only on a request that
258
+ * carries the drop control; without it, such a block is refused;
259
+ * - the agent is told, in a `[reasoning] <agent>:` system notice of kind
260
+ * `reasoning-loss` stored for it as the framework's other notices are,
261
+ * when a committing compile leaves out a stored reply's reasoning at a
262
+ * change of the request's head, at a branch's first compile, or in a
263
+ * fold or other change to an earlier message that takes a reply of the
264
+ * current turn, and, with `dropBlock` set too, when the provider drops
265
+ * blocks it can place as the agent's stored replies or the stream's
266
+ * rounds, once per incident and again when a call drops more. The
267
+ * framework hears compiles through `Agent.onThinkingStrip` from the
268
+ * agent's first stream on, unless a host has set its own, so an agent
269
+ * driven only through the direct API is never told.
270
+ * The record and the notes
271
+ * vouch for requests as agent-framework hands them to membrane, so a
272
+ * membrane `beforeRequest` hook that changes a request must change every
273
+ * request alike. Default false: compiles and streams are as they were.
274
+ */
275
+ binds?: boolean;
276
+ };
150
277
  /**
151
278
  * How to handle a model content-policy refusal (`stop_reason: refusal`).
152
279
  * When `autoRewind` is on, a refused turn triggers an automatic rewind: the
@@ -219,6 +346,34 @@ export interface AgentConfig {
219
346
  */
220
347
  toolWrapperProseGuard?: boolean;
221
348
 
349
+ /**
350
+ * Continue on the agent's own turn ending (off when left out): a turn the
351
+ * model ends itself (stop reason `end_turn` or `stop_sequence`), whether
352
+ * its last response is prose or empty, is followed by another turn,
353
+ * instead of a pause until the next event. A turn ended through
354
+ * `skip_reply` (or another tool that ends the turn, such as `sleep`), or
355
+ * whose last prose envelope is `>>skip_reply` (explicit) or `>>>skip_reply`
356
+ * (hybrid), pauses as usual. So does one whose closing prose bounced (the
357
+ * bounce and its cap answer it), and an agent offered no way to stop
358
+ * (locus or disabled mode without an offered `skip_reply`).
359
+ *
360
+ * As the next turn starts, a short `[continue]` system row naming the agent
361
+ * joins the window: another turn starts, how to stop, and that unmarked
362
+ * words are sent as usual; on the last continuation of a run, that the
363
+ * agent waits for the next event after it. It's written only when the
364
+ * continuation is that turn's whole cause: a message batched with it makes
365
+ * it that message's turn, with no row, in the message's channel. Otherwise
366
+ * the next turn keeps the turn's locus (locus and hybrid modes). At most
367
+ * `maxConsecutive` (default 3) continuations run in a row: the count
368
+ * starts again when a turn starts with a cause of its own (a message, a
369
+ * timer, a heartbeat that isn't a silent tick) or a tool ends one. Silent
370
+ * heartbeat ticks, refusals, `max_tokens` cut-offs, the stall guard's
371
+ * ends, ephemeral runs, conversation forks and a quiesce never continue. A
372
+ * ` !` continuation the turn asked for runs instead, and counts toward
373
+ * nothing. See docs/auto-continue.md.
374
+ */
375
+ autoContinue?: boolean | AutoContinueConfig;
376
+
222
377
  /**
223
378
  * Clock rows (off when left out): when a boundary of this interval on the
224
379
  * agent's local wall clock (counted from local midnight, in the
@@ -399,10 +554,22 @@ export interface InferenceRequest {
399
554
  * all of them without materializing content, the turn has no cause left
400
555
  * and does not run. */
401
556
  coalescingBatchSubjects?: string[];
402
- /** Host-owned: this wake's sole cause is reading this deferred write, a
403
- * coalesced render placed in its agent's queue (wakeToRead). Once the
404
- * agent has read the write, or it was removed, the wake starts no turn. */
557
+ /** Host-owned: this wake's sole cause is this write, deferred for its
558
+ * agent while a turn was alive: a coalesced render placed in its queue
559
+ * (wakeToRead), or a message, notice or event whose wake was queued with
560
+ * it. Once a request that carried the write was answered and, for a wake
561
+ * that carries a channel and isn't marked `ambient`, the agent has since
562
+ * published into that channel having read it, or once the write is in
563
+ * neither the agent's queue nor its store's current branch, the wake
564
+ * starts no turn. */
405
565
  readsDeferredWrite?: string;
566
+ /** Host-owned: this wake's sole cause is this message, stored in its
567
+ * agent's store as it arrived, not deferred (its row's id). Once a
568
+ * request that carried the message was answered and, for a wake that
569
+ * carries a channel and isn't marked `ambient`, the agent has since
570
+ * published into that channel having read it, or once the message isn't
571
+ * on its store's current branch, the wake starts no turn. */
572
+ readsStoredMessage?: string;
406
573
  agentName: string;
407
574
  reason: string;
408
575
  source: string;
@@ -418,6 +585,25 @@ export interface InferenceRequest {
418
585
  * ephemeral run's (a subagent's), which takes no global fallback.
419
586
  */
420
587
  channelId?: string;
588
+ /**
589
+ * The server of `channelId`'s channel. MCPL requires a channel id to be
590
+ * unique only within one server's connection (§14.2), so where two
591
+ * servers register the same id only the pair names one channel. The
592
+ * framework's own wakes set it beside `channelId`. A host's request that
593
+ * gives `channelId` alone names the one channel that id, or its
594
+ * server-qualified name (`serverId:channelId`), means; one that two
595
+ * servers' channels answer to names none, and the turn's speech has no
596
+ * channel of its own.
597
+ */
598
+ channelServerId?: string;
599
+ /**
600
+ * Framework-set: this wake carries an autoContinue continuation
601
+ * (AgentConfig.autoContinue), with what its `[continue]` row says. The
602
+ * scheduler keeps the mark on the turn's trigger only when the
603
+ * continuation is that turn's whole cause, and the turn writes the row as
604
+ * it starts. Hosts don't set it.
605
+ */
606
+ autoContinueRun?: AutoContinueRun;
421
607
  /**
422
608
  * True when the triggering message explicitly addressed the agent (mention,
423
609
  * reply-to-bot, DM — `chat:addressed` in MCPL RFC-001 terms). When a wake
@@ -426,6 +612,27 @@ export interface InferenceRequest {
426
612
  * not capture the agent's voice just by being newest.
427
613
  */
428
614
  addressed?: boolean;
615
+ /**
616
+ * Host-owned: true when the triggering message's server marked it ambient
617
+ * (`chat:ambient`). A coalesced push's wake carries it only to read a
618
+ * render, and only when every notice the render stands for was. Such a
619
+ * message asked nothing of the agent, so a wake for it that carries
620
+ * `readsDeferredWrite` or `readsStoredMessage` is dropped once a request
621
+ * that carried the message was answered, with no publish asked of the
622
+ * agent. A message with neither tag is in doubt, and is judged as an
623
+ * addressed one.
624
+ */
625
+ ambient?: true;
626
+ /**
627
+ * Host-owned: true when the triggering message's server marked it a
628
+ * `chat:system` notice (RFC-001 rev 3): an event about the place, such as
629
+ * a join or the weather changing, not something anyone said. Such a wake
630
+ * names no channel for its turn's plain speech, though it carries
631
+ * `channelId`: a turn it starts alone resolves its locus as a heartbeat's
632
+ * does. Like an ambient one, a wake to read it is done once read. Never
633
+ * set on a coalesced render's wake, which may fold messages too.
634
+ */
635
+ systemNotice?: true;
429
636
  /**
430
637
  * Who spoke the message that triggered this inference, as an adapter-
431
638
  * namespaced opaque id (`<serverId>:user:<authorId>`) — never a display
@@ -446,6 +653,12 @@ export interface InferenceRequest {
446
653
  wakeChannelId?: string;
447
654
  /** Timestamp of the event the wake provenance was taken from (ms). */
448
655
  wakeAt?: number;
656
+ /** Batched-wake lines the gate handed to this wake rather than wrote
657
+ * (WakeLine), decided by a fresh start of its turn as WakeLine says: each
658
+ * written once into the window it names, or left for a later fresh start
659
+ * of the same wake. A retry, or a start that resumes a logical turn,
660
+ * decides none. */
661
+ wakeLines?: WakeLine[];
449
662
  /** Suppress every automatic plain-prose delivery for this logical turn.
450
663
  * Explicit tool calls remain available. Used by authenticated silent wakes. */
451
664
  suppressProse?: boolean;
@@ -194,19 +194,34 @@ export interface ToolResult {
194
194
  * it reads the result's error text, if any.
195
195
  */
196
196
  data?: unknown;
197
+ /**
198
+ * Whether `data` is a protocol result's content: an array in which every
199
+ * element is a content block, of a type this host can show or not. The
200
+ * framework sets it on an MCPL tool's result, and a module that returns a
201
+ * content array can set it too. When it's set, each element reaches the
202
+ * model as itself, as a reference's stub, or as a marker saying what it was
203
+ * and why it isn't shown, never as JSON. When it isn't, an array counts as
204
+ * content only when every element is a block of one of MCP's types (text,
205
+ * image, audio, resource, resource_link), and any other array is data,
206
+ * written as JSON.
207
+ */
208
+ dataIsContent?: boolean;
197
209
  /** Error message (if failure) */
198
210
  error?: string;
199
211
  /** Whether this was an error (for LLM) */
200
212
  isError?: boolean;
201
213
  /**
202
- * The dispatcher refused the call before it opened, RFC-007's refusal, so
203
- * nothing ran and the call certainly had no effect. Only the dispatcher's
204
- * path, the model's calls and a script's, sets it: the caller may not use
205
- * the tool (allowedTools), a `skip_reply` wake was refused, the call's MCPL
206
- * server is absent or still connecting, the host's policy for that server
207
- * denies the tool, or a fork reached outside its channel. RFC-007's
208
- * lifecycle refuses the call from the same place, so observers see no
209
- * events for it. A check made after the call opened, such as a module's
214
+ * The call was refused before it opened, RFC-007's refusal, so nothing ran
215
+ * and the call certainly had no effect. The dispatcher's path, the model's
216
+ * calls and a script's, sets it: the caller may not use the tool
217
+ * (allowedTools), a `skip_reply` wake was refused, the call's MCPL server is
218
+ * absent or still connecting, the host's policy for that server denies the
219
+ * tool, or a fork reached outside its channel. RFC-007's lifecycle refuses
220
+ * the call from the same place, so observers see no events for it. The
221
+ * framework also sets it on the result it stores for each call in the last
222
+ * round of a response the output limit cut off: such a call was never
223
+ * dispatched or opened, and its result goes into the context with the reply,
224
+ * not through a tool-result event. A check made after the call opened, such as a module's
210
225
  * answer for a name it has no tool for or arguments that don't fit a
211
226
  * schema, is a failure whose text says nothing was done, as is an MCPL
212
227
  * request that couldn't be written. A programmatic call (`executeToolCall`,
@@ -258,6 +273,13 @@ export interface ToolCall {
258
273
  name: string;
259
274
  /** Tool input */
260
275
  input: unknown;
276
+ /**
277
+ * membrane's marker (ToolUseContent.unparseableInput), present when `input`
278
+ * isn't the model's arguments. The framework refuses such a call without
279
+ * running it, except one whose text is JSON `null`, which runs as a call
280
+ * with no arguments.
281
+ */
282
+ unparseableInput?: string;
261
283
  /** The agent that made this tool call. Set by the framework dispatch layer. */
262
284
  callerAgentName?: string;
263
285
  /**
@@ -311,7 +333,9 @@ export interface ToolCall {
311
333
  * read_image tool passes a model's call to the workspace without it; and a
312
334
  * utility run through `utils` carries what its `utils` call carried.
313
335
  * Without it, a module holds its answer to a bound of its own, if any: the
314
- * workspace's is the house default, 24,000.
336
+ * workspace's `edit` and `edit_many` answers hold to the house default,
337
+ * 24,000, and a `read` holds its page to its line limit alone, with every
338
+ * line whole, since such a caller takes the data itself.
315
339
  */
316
340
  resultMaxChars?: number;
317
341
  }