@animalabs/agent-framework 0.22.2 → 0.23.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 (997) hide show
  1. package/README.md +108 -4
  2. package/dist/src/agent.d.ts +108 -17
  3. package/dist/src/agent.d.ts.map +1 -1
  4. package/dist/src/agent.js +207 -67
  5. package/dist/src/agent.js.map +1 -1
  6. package/dist/src/api/mcp-server-core.js +1 -1
  7. package/dist/src/api/mcp-server-core.js.map +1 -1
  8. package/dist/src/api/server.d.ts.map +1 -1
  9. package/dist/src/api/server.js +5 -1
  10. package/dist/src/api/server.js.map +1 -1
  11. package/dist/src/api/types.d.ts +1 -1
  12. package/dist/src/api/types.d.ts.map +1 -1
  13. package/dist/src/branch-names.d.ts +14 -0
  14. package/dist/src/branch-names.d.ts.map +1 -0
  15. package/dist/src/branch-names.js +22 -0
  16. package/dist/src/branch-names.js.map +1 -0
  17. package/dist/src/closest-names.d.ts +28 -0
  18. package/dist/src/closest-names.d.ts.map +1 -0
  19. package/dist/src/closest-names.js +98 -0
  20. package/dist/src/closest-names.js.map +1 -0
  21. package/dist/src/code-execution/index.d.ts +1 -1
  22. package/dist/src/code-execution/index.d.ts.map +1 -1
  23. package/dist/src/code-execution/index.js.map +1 -1
  24. package/dist/src/code-execution/py-runner.d.ts +50 -7
  25. package/dist/src/code-execution/py-runner.d.ts.map +1 -1
  26. package/dist/src/code-execution/py-runner.js +258 -90
  27. package/dist/src/code-execution/py-runner.js.map +1 -1
  28. package/dist/src/code-execution/runtime-py.d.ts +3 -2
  29. package/dist/src/code-execution/runtime-py.d.ts.map +1 -1
  30. package/dist/src/code-execution/runtime-py.js +94 -8
  31. package/dist/src/code-execution/runtime-py.js.map +1 -1
  32. package/dist/src/code-execution/tool-definition.d.ts +17 -1
  33. package/dist/src/code-execution/tool-definition.d.ts.map +1 -1
  34. package/dist/src/code-execution/tool-definition.js +72 -6
  35. package/dist/src/code-execution/tool-definition.js.map +1 -1
  36. package/dist/src/config-checks.d.ts +28 -0
  37. package/dist/src/config-checks.d.ts.map +1 -0
  38. package/dist/src/config-checks.js +56 -0
  39. package/dist/src/config-checks.js.map +1 -0
  40. package/dist/src/deadline-timer.d.ts +21 -0
  41. package/dist/src/deadline-timer.d.ts.map +1 -0
  42. package/dist/src/deadline-timer.js +43 -0
  43. package/dist/src/deadline-timer.js.map +1 -0
  44. package/dist/src/error-message.d.ts +30 -0
  45. package/dist/src/error-message.d.ts.map +1 -0
  46. package/dist/src/error-message.js +50 -0
  47. package/dist/src/error-message.js.map +1 -0
  48. package/dist/src/framework.d.ts +1529 -165
  49. package/dist/src/framework.d.ts.map +1 -1
  50. package/dist/src/framework.js +8264 -1939
  51. package/dist/src/framework.js.map +1 -1
  52. package/dist/src/gate/event-gate.d.ts +8 -0
  53. package/dist/src/gate/event-gate.d.ts.map +1 -1
  54. package/dist/src/gate/event-gate.js +36 -5
  55. package/dist/src/gate/event-gate.js.map +1 -1
  56. package/dist/src/held-writes.d.ts +16 -0
  57. package/dist/src/held-writes.d.ts.map +1 -0
  58. package/dist/src/held-writes.js +56 -0
  59. package/dist/src/held-writes.js.map +1 -0
  60. package/dist/src/index.d.ts +10 -4
  61. package/dist/src/index.d.ts.map +1 -1
  62. package/dist/src/index.js +11 -5
  63. package/dist/src/index.js.map +1 -1
  64. package/dist/src/mcpl/capability-grant.d.ts +4 -0
  65. package/dist/src/mcpl/capability-grant.d.ts.map +1 -1
  66. package/dist/src/mcpl/capability-grant.js +1 -1
  67. package/dist/src/mcpl/capability-grant.js.map +1 -1
  68. package/dist/src/mcpl/channel-registry.d.ts +233 -18
  69. package/dist/src/mcpl/channel-registry.d.ts.map +1 -1
  70. package/dist/src/mcpl/channel-registry.js +975 -386
  71. package/dist/src/mcpl/channel-registry.js.map +1 -1
  72. package/dist/src/mcpl/checkpoint-manager.d.ts +21 -1
  73. package/dist/src/mcpl/checkpoint-manager.d.ts.map +1 -1
  74. package/dist/src/mcpl/checkpoint-manager.js +91 -30
  75. package/dist/src/mcpl/checkpoint-manager.js.map +1 -1
  76. package/dist/src/mcpl/conversation-router.d.ts +19 -3
  77. package/dist/src/mcpl/conversation-router.d.ts.map +1 -1
  78. package/dist/src/mcpl/conversation-router.js +23 -8
  79. package/dist/src/mcpl/conversation-router.js.map +1 -1
  80. package/dist/src/mcpl/convert-block.d.ts +20 -0
  81. package/dist/src/mcpl/convert-block.d.ts.map +1 -0
  82. package/dist/src/mcpl/convert-block.js +88 -0
  83. package/dist/src/mcpl/convert-block.js.map +1 -0
  84. package/dist/src/mcpl/errors.d.ts +13 -0
  85. package/dist/src/mcpl/errors.d.ts.map +1 -1
  86. package/dist/src/mcpl/errors.js +28 -0
  87. package/dist/src/mcpl/errors.js.map +1 -1
  88. package/dist/src/mcpl/hook-orchestrator.d.ts +23 -0
  89. package/dist/src/mcpl/hook-orchestrator.d.ts.map +1 -1
  90. package/dist/src/mcpl/hook-orchestrator.js +83 -72
  91. package/dist/src/mcpl/hook-orchestrator.js.map +1 -1
  92. package/dist/src/mcpl/inbound-source.d.ts +114 -0
  93. package/dist/src/mcpl/inbound-source.d.ts.map +1 -0
  94. package/dist/src/mcpl/inbound-source.js +83 -0
  95. package/dist/src/mcpl/inbound-source.js.map +1 -0
  96. package/dist/src/mcpl/index.d.ts +7 -1
  97. package/dist/src/mcpl/index.d.ts.map +1 -1
  98. package/dist/src/mcpl/index.js +5 -1
  99. package/dist/src/mcpl/index.js.map +1 -1
  100. package/dist/src/mcpl/inference-router.d.ts +19 -13
  101. package/dist/src/mcpl/inference-router.d.ts.map +1 -1
  102. package/dist/src/mcpl/inference-router.js +155 -87
  103. package/dist/src/mcpl/inference-router.js.map +1 -1
  104. package/dist/src/mcpl/log-value.d.ts +7 -0
  105. package/dist/src/mcpl/log-value.d.ts.map +1 -1
  106. package/dist/src/mcpl/log-value.js +9 -0
  107. package/dist/src/mcpl/log-value.js.map +1 -1
  108. package/dist/src/mcpl/modern-connection.d.ts +227 -0
  109. package/dist/src/mcpl/modern-connection.d.ts.map +1 -0
  110. package/dist/src/mcpl/modern-connection.js +1088 -0
  111. package/dist/src/mcpl/modern-connection.js.map +1 -0
  112. package/dist/src/mcpl/prefix-rule.d.ts +18 -0
  113. package/dist/src/mcpl/prefix-rule.d.ts.map +1 -0
  114. package/dist/src/mcpl/prefix-rule.js +25 -0
  115. package/dist/src/mcpl/prefix-rule.js.map +1 -0
  116. package/dist/src/mcpl/protocol-family.d.ts +179 -0
  117. package/dist/src/mcpl/protocol-family.d.ts.map +1 -0
  118. package/dist/src/mcpl/protocol-family.js +697 -0
  119. package/dist/src/mcpl/protocol-family.js.map +1 -0
  120. package/dist/src/mcpl/push-coalescer.d.ts +58 -17
  121. package/dist/src/mcpl/push-coalescer.d.ts.map +1 -1
  122. package/dist/src/mcpl/push-coalescer.js +93 -32
  123. package/dist/src/mcpl/push-coalescer.js.map +1 -1
  124. package/dist/src/mcpl/push-handler.d.ts +16 -9
  125. package/dist/src/mcpl/push-handler.d.ts.map +1 -1
  126. package/dist/src/mcpl/push-handler.js +18 -83
  127. package/dist/src/mcpl/push-handler.js.map +1 -1
  128. package/dist/src/mcpl/reference-fetcher.d.ts +76 -13
  129. package/dist/src/mcpl/reference-fetcher.d.ts.map +1 -1
  130. package/dist/src/mcpl/reference-fetcher.js +275 -66
  131. package/dist/src/mcpl/reference-fetcher.js.map +1 -1
  132. package/dist/src/mcpl/references.d.ts +98 -18
  133. package/dist/src/mcpl/references.d.ts.map +1 -1
  134. package/dist/src/mcpl/references.js +170 -32
  135. package/dist/src/mcpl/references.js.map +1 -1
  136. package/dist/src/mcpl/server-connection.d.ts +406 -31
  137. package/dist/src/mcpl/server-connection.d.ts.map +1 -1
  138. package/dist/src/mcpl/server-connection.js +1331 -272
  139. package/dist/src/mcpl/server-connection.js.map +1 -1
  140. package/dist/src/mcpl/server-registry.d.ts +35 -6
  141. package/dist/src/mcpl/server-registry.d.ts.map +1 -1
  142. package/dist/src/mcpl/server-registry.js +63 -13
  143. package/dist/src/mcpl/server-registry.js.map +1 -1
  144. package/dist/src/mcpl/skip-reply-wake.d.ts +36 -0
  145. package/dist/src/mcpl/skip-reply-wake.d.ts.map +1 -0
  146. package/dist/src/mcpl/skip-reply-wake.js +55 -0
  147. package/dist/src/mcpl/skip-reply-wake.js.map +1 -0
  148. package/dist/src/mcpl/tool-result-normalize.d.ts +54 -0
  149. package/dist/src/mcpl/tool-result-normalize.d.ts.map +1 -0
  150. package/dist/src/mcpl/tool-result-normalize.js +232 -0
  151. package/dist/src/mcpl/tool-result-normalize.js.map +1 -0
  152. package/dist/src/mcpl/transport.d.ts +104 -12
  153. package/dist/src/mcpl/transport.d.ts.map +1 -1
  154. package/dist/src/mcpl/transport.js +315 -85
  155. package/dist/src/mcpl/transport.js.map +1 -1
  156. package/dist/src/mcpl/types.d.ts +76 -19
  157. package/dist/src/mcpl/types.d.ts.map +1 -1
  158. package/dist/src/mcpl/types.js.map +1 -1
  159. package/dist/src/mcpl/visible-content.d.ts +16 -0
  160. package/dist/src/mcpl/visible-content.d.ts.map +1 -1
  161. package/dist/src/mcpl/visible-content.js +26 -0
  162. package/dist/src/mcpl/visible-content.js.map +1 -1
  163. package/dist/src/module-registry.d.ts +34 -6
  164. package/dist/src/module-registry.d.ts.map +1 -1
  165. package/dist/src/module-registry.js +119 -31
  166. package/dist/src/module-registry.js.map +1 -1
  167. package/dist/src/modules/api/index.d.ts +1 -1
  168. package/dist/src/modules/api/index.d.ts.map +1 -1
  169. package/dist/src/modules/api/index.js +3 -2
  170. package/dist/src/modules/api/index.js.map +1 -1
  171. package/dist/src/modules/discord/discord-js-client.d.ts +43 -2
  172. package/dist/src/modules/discord/discord-js-client.d.ts.map +1 -1
  173. package/dist/src/modules/discord/discord-js-client.js +286 -67
  174. package/dist/src/modules/discord/discord-js-client.js.map +1 -1
  175. package/dist/src/modules/discord/index.d.ts +53 -5
  176. package/dist/src/modules/discord/index.d.ts.map +1 -1
  177. package/dist/src/modules/discord/index.js +712 -186
  178. package/dist/src/modules/discord/index.js.map +1 -1
  179. package/dist/src/modules/discord/refusal.d.ts +14 -0
  180. package/dist/src/modules/discord/refusal.d.ts.map +1 -0
  181. package/dist/src/modules/discord/refusal.js +14 -0
  182. package/dist/src/modules/discord/refusal.js.map +1 -0
  183. package/dist/src/modules/discord/types.d.ts +27 -4
  184. package/dist/src/modules/discord/types.d.ts.map +1 -1
  185. package/dist/src/modules/health/index.d.ts.map +1 -1
  186. package/dist/src/modules/health/index.js +8 -3
  187. package/dist/src/modules/health/index.js.map +1 -1
  188. package/dist/src/modules/history/index.d.ts +3 -1
  189. package/dist/src/modules/history/index.d.ts.map +1 -1
  190. package/dist/src/modules/history/index.js +359 -127
  191. package/dist/src/modules/history/index.js.map +1 -1
  192. package/dist/src/modules/history/semantic.d.ts +28 -1
  193. package/dist/src/modules/history/semantic.d.ts.map +1 -1
  194. package/dist/src/modules/history/semantic.js +177 -32
  195. package/dist/src/modules/history/semantic.js.map +1 -1
  196. package/dist/src/modules/index.d.ts +1 -1
  197. package/dist/src/modules/index.d.ts.map +1 -1
  198. package/dist/src/modules/index.js +1 -1
  199. package/dist/src/modules/index.js.map +1 -1
  200. package/dist/src/modules/unknown-tool.d.ts +10 -0
  201. package/dist/src/modules/unknown-tool.d.ts.map +1 -0
  202. package/dist/src/modules/unknown-tool.js +17 -0
  203. package/dist/src/modules/unknown-tool.js.map +1 -0
  204. package/dist/src/modules/workspace/disk-agreement.d.ts +57 -4
  205. package/dist/src/modules/workspace/disk-agreement.d.ts.map +1 -1
  206. package/dist/src/modules/workspace/disk-agreement.js +75 -7
  207. package/dist/src/modules/workspace/disk-agreement.js.map +1 -1
  208. package/dist/src/modules/workspace/effects.d.ts +66 -7
  209. package/dist/src/modules/workspace/effects.d.ts.map +1 -1
  210. package/dist/src/modules/workspace/effects.js +303 -46
  211. package/dist/src/modules/workspace/effects.js.map +1 -1
  212. package/dist/src/modules/workspace/index.d.ts +313 -45
  213. package/dist/src/modules/workspace/index.d.ts.map +1 -1
  214. package/dist/src/modules/workspace/index.js +1404 -304
  215. package/dist/src/modules/workspace/index.js.map +1 -1
  216. package/dist/src/modules/workspace/observe.d.ts +315 -16
  217. package/dist/src/modules/workspace/observe.d.ts.map +1 -1
  218. package/dist/src/modules/workspace/observe.js +727 -37
  219. package/dist/src/modules/workspace/observe.js.map +1 -1
  220. package/dist/src/modules/workspace/reconcile.d.ts +58 -7
  221. package/dist/src/modules/workspace/reconcile.d.ts.map +1 -1
  222. package/dist/src/modules/workspace/reconcile.js +521 -56
  223. package/dist/src/modules/workspace/reconcile.js.map +1 -1
  224. package/dist/src/modules/workspace/types.d.ts +28 -5
  225. package/dist/src/modules/workspace/types.d.ts.map +1 -1
  226. package/dist/src/modules/workspace/types.js.map +1 -1
  227. package/dist/src/modules/workspace/watcher.d.ts +49 -2
  228. package/dist/src/modules/workspace/watcher.d.ts.map +1 -1
  229. package/dist/src/modules/workspace/watcher.js +158 -29
  230. package/dist/src/modules/workspace/watcher.js.map +1 -1
  231. package/dist/src/prose-drafts.d.ts +240 -0
  232. package/dist/src/prose-drafts.d.ts.map +1 -0
  233. package/dist/src/prose-drafts.js +362 -0
  234. package/dist/src/prose-drafts.js.map +1 -0
  235. package/dist/src/prose-segments.d.ts +21 -2
  236. package/dist/src/prose-segments.d.ts.map +1 -1
  237. package/dist/src/prose-segments.js +46 -9
  238. package/dist/src/prose-segments.js.map +1 -1
  239. package/dist/src/recovery/offline-branch.d.ts +1 -0
  240. package/dist/src/recovery/offline-branch.d.ts.map +1 -1
  241. package/dist/src/recovery/offline-branch.js +3 -1
  242. package/dist/src/recovery/offline-branch.js.map +1 -1
  243. package/dist/src/safe-slice.d.ts +5 -1
  244. package/dist/src/safe-slice.d.ts.map +1 -1
  245. package/dist/src/safe-slice.js +9 -1
  246. package/dist/src/safe-slice.js.map +1 -1
  247. package/dist/src/silent-heartbeat.d.ts +112 -39
  248. package/dist/src/silent-heartbeat.d.ts.map +1 -1
  249. package/dist/src/silent-heartbeat.js +100 -29
  250. package/dist/src/silent-heartbeat.js.map +1 -1
  251. package/dist/src/tool-args.d.ts +40 -0
  252. package/dist/src/tool-args.d.ts.map +1 -0
  253. package/dist/src/tool-args.js +207 -0
  254. package/dist/src/tool-args.js.map +1 -0
  255. package/dist/src/tool-image-ledger.d.ts +87 -19
  256. package/dist/src/tool-image-ledger.d.ts.map +1 -1
  257. package/dist/src/tool-image-ledger.js +135 -32
  258. package/dist/src/tool-image-ledger.js.map +1 -1
  259. package/dist/src/tool-presentation.d.ts +9 -0
  260. package/dist/src/tool-presentation.d.ts.map +1 -1
  261. package/dist/src/tool-presentation.js +266 -62
  262. package/dist/src/tool-presentation.js.map +1 -1
  263. package/dist/src/tool-result-guard.d.ts.map +1 -1
  264. package/dist/src/tool-result-guard.js +7 -10
  265. package/dist/src/tool-result-guard.js.map +1 -1
  266. package/dist/src/tool-result-history.d.ts +32 -3
  267. package/dist/src/tool-result-history.d.ts.map +1 -1
  268. package/dist/src/tool-result-history.js +106 -19
  269. package/dist/src/tool-result-history.js.map +1 -1
  270. package/dist/src/tune-out/coordinator.d.ts +25 -1
  271. package/dist/src/tune-out/coordinator.d.ts.map +1 -1
  272. package/dist/src/tune-out/coordinator.js +260 -65
  273. package/dist/src/tune-out/coordinator.js.map +1 -1
  274. package/dist/src/types/agent.d.ts +44 -22
  275. package/dist/src/types/agent.d.ts.map +1 -1
  276. package/dist/src/types/events.d.ts +25 -0
  277. package/dist/src/types/events.d.ts.map +1 -1
  278. package/dist/src/types/framework.d.ts +38 -7
  279. package/dist/src/types/framework.d.ts.map +1 -1
  280. package/dist/src/types/inference-log.d.ts +1 -1
  281. package/dist/src/types/inference-log.d.ts.map +1 -1
  282. package/dist/src/types/module.d.ts +77 -14
  283. package/dist/src/types/module.d.ts.map +1 -1
  284. package/dist/src/types/trace.d.ts +97 -8
  285. package/dist/src/types/trace.d.ts.map +1 -1
  286. package/dist/src/usage/usage-tracker.d.ts +5 -0
  287. package/dist/src/usage/usage-tracker.d.ts.map +1 -1
  288. package/dist/src/usage/usage-tracker.js +35 -8
  289. package/dist/src/usage/usage-tracker.js.map +1 -1
  290. package/package.json +5 -4
  291. package/src/agent.ts +257 -72
  292. package/src/api/mcp-server-core.ts +1 -1
  293. package/src/api/server.ts +4 -1
  294. package/src/api/types.ts +1 -1
  295. package/src/branch-names.ts +19 -0
  296. package/src/closest-names.ts +94 -0
  297. package/src/code-execution/index.ts +1 -0
  298. package/src/code-execution/py-runner.ts +304 -93
  299. package/src/code-execution/runtime-py.ts +94 -8
  300. package/src/code-execution/tool-definition.ts +85 -7
  301. package/src/config-checks.ts +50 -0
  302. package/src/deadline-timer.ts +44 -0
  303. package/src/error-message.ts +48 -0
  304. package/src/framework.ts +8625 -1984
  305. package/src/gate/event-gate.ts +38 -5
  306. package/src/held-writes.ts +59 -0
  307. package/src/index.ts +29 -5
  308. package/src/mcpl/capability-grant.ts +1 -1
  309. package/src/mcpl/channel-registry.ts +1095 -411
  310. package/src/mcpl/checkpoint-manager.ts +104 -29
  311. package/src/mcpl/conversation-router.ts +28 -8
  312. package/src/mcpl/convert-block.ts +105 -0
  313. package/src/mcpl/errors.ts +28 -0
  314. package/src/mcpl/hook-orchestrator.ts +84 -77
  315. package/src/mcpl/inbound-source.ts +156 -0
  316. package/src/mcpl/index.ts +23 -1
  317. package/src/mcpl/inference-router.ts +179 -103
  318. package/src/mcpl/log-value.ts +10 -0
  319. package/src/mcpl/modern-connection.ts +1182 -0
  320. package/src/mcpl/prefix-rule.ts +32 -0
  321. package/src/mcpl/protocol-family.ts +691 -0
  322. package/src/mcpl/push-coalescer.ts +110 -36
  323. package/src/mcpl/push-handler.ts +20 -90
  324. package/src/mcpl/reference-fetcher.ts +318 -67
  325. package/src/mcpl/references.ts +183 -34
  326. package/src/mcpl/server-connection.ts +1404 -280
  327. package/src/mcpl/server-registry.ts +63 -14
  328. package/src/mcpl/skip-reply-wake.ts +73 -0
  329. package/src/mcpl/tool-result-normalize.ts +294 -0
  330. package/src/mcpl/transport.ts +320 -76
  331. package/src/mcpl/types.ts +77 -19
  332. package/src/mcpl/visible-content.ts +28 -0
  333. package/src/module-registry.ts +126 -36
  334. package/src/modules/api/index.ts +3 -2
  335. package/src/modules/discord/discord-js-client.ts +306 -74
  336. package/src/modules/discord/index.ts +737 -201
  337. package/src/modules/discord/refusal.ts +13 -0
  338. package/src/modules/discord/types.ts +27 -6
  339. package/src/modules/health/index.ts +8 -3
  340. package/src/modules/history/index.ts +410 -120
  341. package/src/modules/history/semantic.ts +189 -32
  342. package/src/modules/index.ts +1 -1
  343. package/src/modules/unknown-tool.ts +16 -0
  344. package/src/modules/workspace/disk-agreement.ts +97 -8
  345. package/src/modules/workspace/effects.ts +291 -36
  346. package/src/modules/workspace/index.ts +1469 -321
  347. package/src/modules/workspace/observe.ts +784 -41
  348. package/src/modules/workspace/reconcile.ts +619 -64
  349. package/src/modules/workspace/types.ts +28 -5
  350. package/src/modules/workspace/watcher.ts +154 -30
  351. package/src/prose-drafts.ts +481 -0
  352. package/src/prose-segments.ts +51 -8
  353. package/src/recovery/offline-branch.ts +4 -1
  354. package/src/safe-slice.ts +9 -1
  355. package/src/silent-heartbeat.ts +184 -59
  356. package/src/tool-args.ts +213 -0
  357. package/src/tool-image-ledger.ts +153 -34
  358. package/src/tool-presentation.ts +233 -42
  359. package/src/tool-result-guard.ts +7 -8
  360. package/src/tool-result-history.ts +124 -20
  361. package/src/tune-out/coordinator.ts +259 -65
  362. package/src/types/agent.ts +44 -24
  363. package/src/types/events.ts +25 -0
  364. package/src/types/framework.ts +38 -7
  365. package/src/types/inference-log.ts +1 -1
  366. package/src/types/module.ts +79 -14
  367. package/src/types/trace.ts +103 -8
  368. package/src/usage/usage-tracker.ts +32 -8
  369. package/dist/test/activation-request-sanitize.test.d.ts +0 -2
  370. package/dist/test/activation-request-sanitize.test.d.ts.map +0 -1
  371. package/dist/test/activation-request-sanitize.test.js +0 -89
  372. package/dist/test/activation-request-sanitize.test.js.map +0 -1
  373. package/dist/test/agent-cache-ttl.test.d.ts +0 -2
  374. package/dist/test/agent-cache-ttl.test.d.ts.map +0 -1
  375. package/dist/test/agent-cache-ttl.test.js +0 -41
  376. package/dist/test/agent-cache-ttl.test.js.map +0 -1
  377. package/dist/test/agent-runtime-settings.test.d.ts +0 -2
  378. package/dist/test/agent-runtime-settings.test.d.ts.map +0 -1
  379. package/dist/test/agent-runtime-settings.test.js +0 -1598
  380. package/dist/test/agent-runtime-settings.test.js.map +0 -1
  381. package/dist/test/api-admin-gate.test.d.ts +0 -2
  382. package/dist/test/api-admin-gate.test.d.ts.map +0 -1
  383. package/dist/test/api-admin-gate.test.js +0 -116
  384. package/dist/test/api-admin-gate.test.js.map +0 -1
  385. package/dist/test/assistant-persist-refusal.test.d.ts +0 -2
  386. package/dist/test/assistant-persist-refusal.test.d.ts.map +0 -1
  387. package/dist/test/assistant-persist-refusal.test.js +0 -63
  388. package/dist/test/assistant-persist-refusal.test.js.map +0 -1
  389. package/dist/test/batched-wake-locus.test.d.ts +0 -2
  390. package/dist/test/batched-wake-locus.test.d.ts.map +0 -1
  391. package/dist/test/batched-wake-locus.test.js +0 -166
  392. package/dist/test/batched-wake-locus.test.js.map +0 -1
  393. package/dist/test/busy-agent-scheduler.test.d.ts +0 -2
  394. package/dist/test/busy-agent-scheduler.test.d.ts.map +0 -1
  395. package/dist/test/busy-agent-scheduler.test.js +0 -92
  396. package/dist/test/busy-agent-scheduler.test.js.map +0 -1
  397. package/dist/test/channel-incoming-targeting.test.d.ts +0 -2
  398. package/dist/test/channel-incoming-targeting.test.d.ts.map +0 -1
  399. package/dist/test/channel-incoming-targeting.test.js +0 -81
  400. package/dist/test/channel-incoming-targeting.test.js.map +0 -1
  401. package/dist/test/channel-label-history.test.d.ts +0 -2
  402. package/dist/test/channel-label-history.test.d.ts.map +0 -1
  403. package/dist/test/channel-label-history.test.js +0 -424
  404. package/dist/test/channel-label-history.test.js.map +0 -1
  405. package/dist/test/channel-lifecycle-provenance.test.d.ts +0 -2
  406. package/dist/test/channel-lifecycle-provenance.test.d.ts.map +0 -1
  407. package/dist/test/channel-lifecycle-provenance.test.js +0 -47
  408. package/dist/test/channel-lifecycle-provenance.test.js.map +0 -1
  409. package/dist/test/channel-registry-routing.test.d.ts +0 -2
  410. package/dist/test/channel-registry-routing.test.d.ts.map +0 -1
  411. package/dist/test/channel-registry-routing.test.js +0 -446
  412. package/dist/test/channel-registry-routing.test.js.map +0 -1
  413. package/dist/test/channel-registry-typing.test.d.ts +0 -2
  414. package/dist/test/channel-registry-typing.test.d.ts.map +0 -1
  415. package/dist/test/channel-registry-typing.test.js +0 -91
  416. package/dist/test/channel-registry-typing.test.js.map +0 -1
  417. package/dist/test/channels-changed-respond-first.test.d.ts +0 -2
  418. package/dist/test/channels-changed-respond-first.test.d.ts.map +0 -1
  419. package/dist/test/channels-changed-respond-first.test.js +0 -74
  420. package/dist/test/channels-changed-respond-first.test.js.map +0 -1
  421. package/dist/test/checkpoint-attribution.test.d.ts +0 -2
  422. package/dist/test/checkpoint-attribution.test.d.ts.map +0 -1
  423. package/dist/test/checkpoint-attribution.test.js +0 -200
  424. package/dist/test/checkpoint-attribution.test.js.map +0 -1
  425. package/dist/test/code-execution.test.d.ts +0 -11
  426. package/dist/test/code-execution.test.d.ts.map +0 -1
  427. package/dist/test/code-execution.test.js +0 -1272
  428. package/dist/test/code-execution.test.js.map +0 -1
  429. package/dist/test/component-defaults.test.d.ts +0 -2
  430. package/dist/test/component-defaults.test.d.ts.map +0 -1
  431. package/dist/test/component-defaults.test.js +0 -54
  432. package/dist/test/component-defaults.test.js.map +0 -1
  433. package/dist/test/conversation-fork-injection-scoping.test.d.ts +0 -2
  434. package/dist/test/conversation-fork-injection-scoping.test.d.ts.map +0 -1
  435. package/dist/test/conversation-fork-injection-scoping.test.js +0 -200
  436. package/dist/test/conversation-fork-injection-scoping.test.js.map +0 -1
  437. package/dist/test/conversation-router.test.d.ts +0 -2
  438. package/dist/test/conversation-router.test.d.ts.map +0 -1
  439. package/dist/test/conversation-router.test.js +0 -174
  440. package/dist/test/conversation-router.test.js.map +0 -1
  441. package/dist/test/conversation-routing.test.d.ts +0 -7
  442. package/dist/test/conversation-routing.test.d.ts.map +0 -1
  443. package/dist/test/conversation-routing.test.js +0 -621
  444. package/dist/test/conversation-routing.test.js.map +0 -1
  445. package/dist/test/deferred-wake-integrity.test.d.ts +0 -29
  446. package/dist/test/deferred-wake-integrity.test.d.ts.map +0 -1
  447. package/dist/test/deferred-wake-integrity.test.js +0 -320
  448. package/dist/test/deferred-wake-integrity.test.js.map +0 -1
  449. package/dist/test/discord-awareness-outbox.test.d.ts +0 -2
  450. package/dist/test/discord-awareness-outbox.test.d.ts.map +0 -1
  451. package/dist/test/discord-awareness-outbox.test.js +0 -371
  452. package/dist/test/discord-awareness-outbox.test.js.map +0 -1
  453. package/dist/test/discord-history-delete-window.test.d.ts +0 -2
  454. package/dist/test/discord-history-delete-window.test.d.ts.map +0 -1
  455. package/dist/test/discord-history-delete-window.test.js +0 -81
  456. package/dist/test/discord-history-delete-window.test.js.map +0 -1
  457. package/dist/test/discord-history-sync.test.d.ts +0 -2
  458. package/dist/test/discord-history-sync.test.d.ts.map +0 -1
  459. package/dist/test/discord-history-sync.test.js +0 -56
  460. package/dist/test/discord-history-sync.test.js.map +0 -1
  461. package/dist/test/discord-typing-keepalive.test.d.ts +0 -2
  462. package/dist/test/discord-typing-keepalive.test.d.ts.map +0 -1
  463. package/dist/test/discord-typing-keepalive.test.js +0 -77
  464. package/dist/test/discord-typing-keepalive.test.js.map +0 -1
  465. package/dist/test/ephemeral-settle.test.d.ts +0 -2
  466. package/dist/test/ephemeral-settle.test.d.ts.map +0 -1
  467. package/dist/test/ephemeral-settle.test.js +0 -354
  468. package/dist/test/ephemeral-settle.test.js.map +0 -1
  469. package/dist/test/event-gate-passthrough.test.d.ts +0 -15
  470. package/dist/test/event-gate-passthrough.test.d.ts.map +0 -1
  471. package/dist/test/event-gate-passthrough.test.js +0 -289
  472. package/dist/test/event-gate-passthrough.test.js.map +0 -1
  473. package/dist/test/event-gate-policy-mutation.test.d.ts +0 -2
  474. package/dist/test/event-gate-policy-mutation.test.d.ts.map +0 -1
  475. package/dist/test/event-gate-policy-mutation.test.js +0 -137
  476. package/dist/test/event-gate-policy-mutation.test.js.map +0 -1
  477. package/dist/test/event-gate-rate-limit.test.d.ts +0 -2
  478. package/dist/test/event-gate-rate-limit.test.d.ts.map +0 -1
  479. package/dist/test/event-gate-rate-limit.test.js +0 -627
  480. package/dist/test/event-gate-rate-limit.test.js.map +0 -1
  481. package/dist/test/event-gate-script.test.d.ts +0 -2
  482. package/dist/test/event-gate-script.test.d.ts.map +0 -1
  483. package/dist/test/event-gate-script.test.js +0 -95
  484. package/dist/test/event-gate-script.test.js.map +0 -1
  485. package/dist/test/event-gate-selfwake.test.d.ts +0 -15
  486. package/dist/test/event-gate-selfwake.test.d.ts.map +0 -1
  487. package/dist/test/event-gate-selfwake.test.js +0 -125
  488. package/dist/test/event-gate-selfwake.test.js.map +0 -1
  489. package/dist/test/event-gate-tags.test.d.ts +0 -2
  490. package/dist/test/event-gate-tags.test.d.ts.map +0 -1
  491. package/dist/test/event-gate-tags.test.js +0 -76
  492. package/dist/test/event-gate-tags.test.js.map +0 -1
  493. package/dist/test/event-gate.test.d.ts +0 -2
  494. package/dist/test/event-gate.test.d.ts.map +0 -1
  495. package/dist/test/event-gate.test.js +0 -919
  496. package/dist/test/event-gate.test.js.map +0 -1
  497. package/dist/test/explicit-prose-routing.test.d.ts +0 -11
  498. package/dist/test/explicit-prose-routing.test.d.ts.map +0 -1
  499. package/dist/test/explicit-prose-routing.test.js +0 -1715
  500. package/dist/test/explicit-prose-routing.test.js.map +0 -1
  501. package/dist/test/framework.test.d.ts +0 -5
  502. package/dist/test/framework.test.d.ts.map +0 -1
  503. package/dist/test/framework.test.js +0 -1048
  504. package/dist/test/framework.test.js.map +0 -1
  505. package/dist/test/gather-context-timeout.test.d.ts +0 -2
  506. package/dist/test/gather-context-timeout.test.d.ts.map +0 -1
  507. package/dist/test/gather-context-timeout.test.js +0 -120
  508. package/dist/test/gather-context-timeout.test.js.map +0 -1
  509. package/dist/test/health-snapshot.test.d.ts +0 -2
  510. package/dist/test/health-snapshot.test.d.ts.map +0 -1
  511. package/dist/test/health-snapshot.test.js +0 -74
  512. package/dist/test/health-snapshot.test.js.map +0 -1
  513. package/dist/test/helpers/coalescing-fixture.d.ts +0 -74
  514. package/dist/test/helpers/coalescing-fixture.d.ts.map +0 -1
  515. package/dist/test/helpers/coalescing-fixture.js +0 -152
  516. package/dist/test/helpers/coalescing-fixture.js.map +0 -1
  517. package/dist/test/helpers/coalescing-kill-child.d.ts +0 -2
  518. package/dist/test/helpers/coalescing-kill-child.d.ts.map +0 -1
  519. package/dist/test/helpers/coalescing-kill-child.js +0 -24
  520. package/dist/test/helpers/coalescing-kill-child.js.map +0 -1
  521. package/dist/test/helpers/mock-membrane.d.ts +0 -53
  522. package/dist/test/helpers/mock-membrane.d.ts.map +0 -1
  523. package/dist/test/helpers/mock-membrane.js +0 -168
  524. package/dist/test/helpers/mock-membrane.js.map +0 -1
  525. package/dist/test/helpers/pytc-stop-rows.d.ts +0 -11
  526. package/dist/test/helpers/pytc-stop-rows.d.ts.map +0 -1
  527. package/dist/test/helpers/pytc-stop-rows.js +0 -143
  528. package/dist/test/helpers/pytc-stop-rows.js.map +0 -1
  529. package/dist/test/helpers/quiesce-crash-child.d.ts +0 -2
  530. package/dist/test/helpers/quiesce-crash-child.d.ts.map +0 -1
  531. package/dist/test/helpers/quiesce-crash-child.js +0 -156
  532. package/dist/test/helpers/quiesce-crash-child.js.map +0 -1
  533. package/dist/test/hide-then-turn.test.d.ts +0 -2
  534. package/dist/test/hide-then-turn.test.d.ts.map +0 -1
  535. package/dist/test/hide-then-turn.test.js +0 -101
  536. package/dist/test/hide-then-turn.test.js.map +0 -1
  537. package/dist/test/history-module-overview.test.d.ts +0 -2
  538. package/dist/test/history-module-overview.test.d.ts.map +0 -1
  539. package/dist/test/history-module-overview.test.js +0 -711
  540. package/dist/test/history-module-overview.test.js.map +0 -1
  541. package/dist/test/history-module-realstore.test.d.ts +0 -2
  542. package/dist/test/history-module-realstore.test.d.ts.map +0 -1
  543. package/dist/test/history-module-realstore.test.js +0 -363
  544. package/dist/test/history-module-realstore.test.js.map +0 -1
  545. package/dist/test/history-module-semantic.test.d.ts +0 -2
  546. package/dist/test/history-module-semantic.test.d.ts.map +0 -1
  547. package/dist/test/history-module-semantic.test.js +0 -213
  548. package/dist/test/history-module-semantic.test.js.map +0 -1
  549. package/dist/test/history-module-ux.test.d.ts +0 -2
  550. package/dist/test/history-module-ux.test.d.ts.map +0 -1
  551. package/dist/test/history-module-ux.test.js +0 -304
  552. package/dist/test/history-module-ux.test.js.map +0 -1
  553. package/dist/test/history-module.test.d.ts +0 -2
  554. package/dist/test/history-module.test.d.ts.map +0 -1
  555. package/dist/test/history-module.test.js +0 -619
  556. package/dist/test/history-module.test.js.map +0 -1
  557. package/dist/test/history-semantic-review-findings.test.d.ts +0 -2
  558. package/dist/test/history-semantic-review-findings.test.d.ts.map +0 -1
  559. package/dist/test/history-semantic-review-findings.test.js +0 -338
  560. package/dist/test/history-semantic-review-findings.test.js.map +0 -1
  561. package/dist/test/history-semantic-sync-converges.test.d.ts +0 -2
  562. package/dist/test/history-semantic-sync-converges.test.d.ts.map +0 -1
  563. package/dist/test/history-semantic-sync-converges.test.js +0 -109
  564. package/dist/test/history-semantic-sync-converges.test.js.map +0 -1
  565. package/dist/test/host-quiesce.test.d.ts +0 -2
  566. package/dist/test/host-quiesce.test.d.ts.map +0 -1
  567. package/dist/test/host-quiesce.test.js +0 -988
  568. package/dist/test/host-quiesce.test.js.map +0 -1
  569. package/dist/test/inference-exhaustion-rewind.test.d.ts +0 -2
  570. package/dist/test/inference-exhaustion-rewind.test.d.ts.map +0 -1
  571. package/dist/test/inference-exhaustion-rewind.test.js +0 -387
  572. package/dist/test/inference-exhaustion-rewind.test.js.map +0 -1
  573. package/dist/test/inference-failure-bounds.test.d.ts +0 -2
  574. package/dist/test/inference-failure-bounds.test.d.ts.map +0 -1
  575. package/dist/test/inference-failure-bounds.test.js +0 -1202
  576. package/dist/test/inference-failure-bounds.test.js.map +0 -1
  577. package/dist/test/inference-failure-observability.test.d.ts +0 -2
  578. package/dist/test/inference-failure-observability.test.d.ts.map +0 -1
  579. package/dist/test/inference-failure-observability.test.js +0 -84
  580. package/dist/test/inference-failure-observability.test.js.map +0 -1
  581. package/dist/test/journal-tool.test.d.ts +0 -2
  582. package/dist/test/journal-tool.test.d.ts.map +0 -1
  583. package/dist/test/journal-tool.test.js +0 -33
  584. package/dist/test/journal-tool.test.js.map +0 -1
  585. package/dist/test/kv-unified-open-flight-retry.test.d.ts +0 -2
  586. package/dist/test/kv-unified-open-flight-retry.test.d.ts.map +0 -1
  587. package/dist/test/kv-unified-open-flight-retry.test.js +0 -189
  588. package/dist/test/kv-unified-open-flight-retry.test.js.map +0 -1
  589. package/dist/test/kv-unified-wiring.test.d.ts +0 -2
  590. package/dist/test/kv-unified-wiring.test.d.ts.map +0 -1
  591. package/dist/test/kv-unified-wiring.test.js +0 -95
  592. package/dist/test/kv-unified-wiring.test.js.map +0 -1
  593. package/dist/test/late-events-after-stop.test.d.ts +0 -2
  594. package/dist/test/late-events-after-stop.test.d.ts.map +0 -1
  595. package/dist/test/late-events-after-stop.test.js +0 -122
  596. package/dist/test/late-events-after-stop.test.js.map +0 -1
  597. package/dist/test/liveness-watchdog.test.d.ts +0 -2
  598. package/dist/test/liveness-watchdog.test.d.ts.map +0 -1
  599. package/dist/test/liveness-watchdog.test.js +0 -94
  600. package/dist/test/liveness-watchdog.test.js.map +0 -1
  601. package/dist/test/machine-close-provenance.test.d.ts +0 -2
  602. package/dist/test/machine-close-provenance.test.d.ts.map +0 -1
  603. package/dist/test/machine-close-provenance.test.js +0 -116
  604. package/dist/test/machine-close-provenance.test.js.map +0 -1
  605. package/dist/test/maintenance-timer.test.d.ts +0 -2
  606. package/dist/test/maintenance-timer.test.d.ts.map +0 -1
  607. package/dist/test/maintenance-timer.test.js +0 -1827
  608. package/dist/test/maintenance-timer.test.js.map +0 -1
  609. package/dist/test/mcp-server-bin.test.d.ts +0 -2
  610. package/dist/test/mcp-server-bin.test.d.ts.map +0 -1
  611. package/dist/test/mcp-server-bin.test.js +0 -142
  612. package/dist/test/mcp-server-bin.test.js.map +0 -1
  613. package/dist/test/mcpl-access-provider.test.d.ts +0 -2
  614. package/dist/test/mcpl-access-provider.test.d.ts.map +0 -1
  615. package/dist/test/mcpl-access-provider.test.js +0 -20
  616. package/dist/test/mcpl-access-provider.test.js.map +0 -1
  617. package/dist/test/mcpl-awareness-barrier.test.d.ts +0 -2
  618. package/dist/test/mcpl-awareness-barrier.test.d.ts.map +0 -1
  619. package/dist/test/mcpl-awareness-barrier.test.js +0 -769
  620. package/dist/test/mcpl-awareness-barrier.test.js.map +0 -1
  621. package/dist/test/mcpl-capability-grant.test.d.ts +0 -10
  622. package/dist/test/mcpl-capability-grant.test.d.ts.map +0 -1
  623. package/dist/test/mcpl-capability-grant.test.js +0 -111
  624. package/dist/test/mcpl-capability-grant.test.js.map +0 -1
  625. package/dist/test/mcpl-capability-scoping.test.d.ts +0 -2
  626. package/dist/test/mcpl-capability-scoping.test.d.ts.map +0 -1
  627. package/dist/test/mcpl-capability-scoping.test.js +0 -266
  628. package/dist/test/mcpl-capability-scoping.test.js.map +0 -1
  629. package/dist/test/mcpl-child-env.test.d.ts +0 -2
  630. package/dist/test/mcpl-child-env.test.d.ts.map +0 -1
  631. package/dist/test/mcpl-child-env.test.js +0 -158
  632. package/dist/test/mcpl-child-env.test.js.map +0 -1
  633. package/dist/test/mcpl-coalesced-content-parity.test.d.ts +0 -2
  634. package/dist/test/mcpl-coalesced-content-parity.test.d.ts.map +0 -1
  635. package/dist/test/mcpl-coalesced-content-parity.test.js +0 -532
  636. package/dist/test/mcpl-coalesced-content-parity.test.js.map +0 -1
  637. package/dist/test/mcpl-coalescing.test.d.ts +0 -2
  638. package/dist/test/mcpl-coalescing.test.d.ts.map +0 -1
  639. package/dist/test/mcpl-coalescing.test.js +0 -1125
  640. package/dist/test/mcpl-coalescing.test.js.map +0 -1
  641. package/dist/test/mcpl-config-diagnostics.test.d.ts +0 -2
  642. package/dist/test/mcpl-config-diagnostics.test.d.ts.map +0 -1
  643. package/dist/test/mcpl-config-diagnostics.test.js +0 -452
  644. package/dist/test/mcpl-config-diagnostics.test.js.map +0 -1
  645. package/dist/test/mcpl-empty-content.test.d.ts +0 -2
  646. package/dist/test/mcpl-empty-content.test.d.ts.map +0 -1
  647. package/dist/test/mcpl-empty-content.test.js +0 -368
  648. package/dist/test/mcpl-empty-content.test.js.map +0 -1
  649. package/dist/test/mcpl-gate-roundtrip.test.d.ts +0 -2
  650. package/dist/test/mcpl-gate-roundtrip.test.d.ts.map +0 -1
  651. package/dist/test/mcpl-gate-roundtrip.test.js +0 -285
  652. package/dist/test/mcpl-gate-roundtrip.test.js.map +0 -1
  653. package/dist/test/mcpl-list-status.test.d.ts +0 -2
  654. package/dist/test/mcpl-list-status.test.d.ts.map +0 -1
  655. package/dist/test/mcpl-list-status.test.js +0 -82
  656. package/dist/test/mcpl-list-status.test.js.map +0 -1
  657. package/dist/test/mcpl-manifest-changed.test.d.ts +0 -2
  658. package/dist/test/mcpl-manifest-changed.test.d.ts.map +0 -1
  659. package/dist/test/mcpl-manifest-changed.test.js +0 -178
  660. package/dist/test/mcpl-manifest-changed.test.js.map +0 -1
  661. package/dist/test/mcpl-push-convert.test.d.ts +0 -2
  662. package/dist/test/mcpl-push-convert.test.d.ts.map +0 -1
  663. package/dist/test/mcpl-push-convert.test.js +0 -42
  664. package/dist/test/mcpl-push-convert.test.js.map +0 -1
  665. package/dist/test/mcpl-reconnect-events.test.d.ts +0 -2
  666. package/dist/test/mcpl-reconnect-events.test.d.ts.map +0 -1
  667. package/dist/test/mcpl-reconnect-events.test.js +0 -144
  668. package/dist/test/mcpl-reconnect-events.test.js.map +0 -1
  669. package/dist/test/mcpl-reconnect-reregistration.test.d.ts +0 -2
  670. package/dist/test/mcpl-reconnect-reregistration.test.d.ts.map +0 -1
  671. package/dist/test/mcpl-reconnect-reregistration.test.js +0 -238
  672. package/dist/test/mcpl-reconnect-reregistration.test.js.map +0 -1
  673. package/dist/test/mcpl-reference-fetcher.test.d.ts +0 -2
  674. package/dist/test/mcpl-reference-fetcher.test.d.ts.map +0 -1
  675. package/dist/test/mcpl-reference-fetcher.test.js +0 -427
  676. package/dist/test/mcpl-reference-fetcher.test.js.map +0 -1
  677. package/dist/test/mcpl-reference-fields.test.d.ts +0 -2
  678. package/dist/test/mcpl-reference-fields.test.d.ts.map +0 -1
  679. package/dist/test/mcpl-reference-fields.test.js +0 -149
  680. package/dist/test/mcpl-reference-fields.test.js.map +0 -1
  681. package/dist/test/mcpl-rejection-log-lines.test.d.ts +0 -2
  682. package/dist/test/mcpl-rejection-log-lines.test.d.ts.map +0 -1
  683. package/dist/test/mcpl-rejection-log-lines.test.js +0 -349
  684. package/dist/test/mcpl-rejection-log-lines.test.js.map +0 -1
  685. package/dist/test/mcpl-request-timeout.test.d.ts +0 -2
  686. package/dist/test/mcpl-request-timeout.test.d.ts.map +0 -1
  687. package/dist/test/mcpl-request-timeout.test.js +0 -138
  688. package/dist/test/mcpl-request-timeout.test.js.map +0 -1
  689. package/dist/test/mcpl-runtime-lifecycle.test.d.ts +0 -7
  690. package/dist/test/mcpl-runtime-lifecycle.test.d.ts.map +0 -1
  691. package/dist/test/mcpl-runtime-lifecycle.test.js +0 -142
  692. package/dist/test/mcpl-runtime-lifecycle.test.js.map +0 -1
  693. package/dist/test/mcpl-stderr-tail.test.d.ts +0 -2
  694. package/dist/test/mcpl-stderr-tail.test.d.ts.map +0 -1
  695. package/dist/test/mcpl-stderr-tail.test.js +0 -210
  696. package/dist/test/mcpl-stderr-tail.test.js.map +0 -1
  697. package/dist/test/mcpl-tool-class-listing.test.d.ts +0 -2
  698. package/dist/test/mcpl-tool-class-listing.test.d.ts.map +0 -1
  699. package/dist/test/mcpl-tool-class-listing.test.js +0 -147
  700. package/dist/test/mcpl-tool-class-listing.test.js.map +0 -1
  701. package/dist/test/mcpl-tool-classes.test.d.ts +0 -7
  702. package/dist/test/mcpl-tool-classes.test.d.ts.map +0 -1
  703. package/dist/test/mcpl-tool-classes.test.js +0 -80
  704. package/dist/test/mcpl-tool-classes.test.js.map +0 -1
  705. package/dist/test/mcpl-tool-lifecycle-e2e.test.d.ts +0 -2
  706. package/dist/test/mcpl-tool-lifecycle-e2e.test.d.ts.map +0 -1
  707. package/dist/test/mcpl-tool-lifecycle-e2e.test.js +0 -237
  708. package/dist/test/mcpl-tool-lifecycle-e2e.test.js.map +0 -1
  709. package/dist/test/mcpl-tool-lifecycle-emitter.test.d.ts +0 -11
  710. package/dist/test/mcpl-tool-lifecycle-emitter.test.d.ts.map +0 -1
  711. package/dist/test/mcpl-tool-lifecycle-emitter.test.js +0 -412
  712. package/dist/test/mcpl-tool-lifecycle-emitter.test.js.map +0 -1
  713. package/dist/test/mcpl-tool-lifecycle-script.test.d.ts +0 -2
  714. package/dist/test/mcpl-tool-lifecycle-script.test.d.ts.map +0 -1
  715. package/dist/test/mcpl-tool-lifecycle-script.test.js +0 -288
  716. package/dist/test/mcpl-tool-lifecycle-script.test.js.map +0 -1
  717. package/dist/test/mcpl-tool-lifecycle.test.d.ts +0 -11
  718. package/dist/test/mcpl-tool-lifecycle.test.d.ts.map +0 -1
  719. package/dist/test/mcpl-tool-lifecycle.test.js +0 -270
  720. package/dist/test/mcpl-tool-lifecycle.test.js.map +0 -1
  721. package/dist/test/mcpl-transport-close.test.d.ts +0 -2
  722. package/dist/test/mcpl-transport-close.test.d.ts.map +0 -1
  723. package/dist/test/mcpl-transport-close.test.js +0 -373
  724. package/dist/test/mcpl-transport-close.test.js.map +0 -1
  725. package/dist/test/mcpl-transport-spawn.test.d.ts +0 -2
  726. package/dist/test/mcpl-transport-spawn.test.d.ts.map +0 -1
  727. package/dist/test/mcpl-transport-spawn.test.js +0 -58
  728. package/dist/test/mcpl-transport-spawn.test.js.map +0 -1
  729. package/dist/test/mcpl-ws-transport.test.d.ts +0 -2
  730. package/dist/test/mcpl-ws-transport.test.d.ts.map +0 -1
  731. package/dist/test/mcpl-ws-transport.test.js +0 -259
  732. package/dist/test/mcpl-ws-transport.test.js.map +0 -1
  733. package/dist/test/module-context-integration.test.d.ts +0 -18
  734. package/dist/test/module-context-integration.test.d.ts.map +0 -1
  735. package/dist/test/module-context-integration.test.js +0 -181
  736. package/dist/test/module-context-integration.test.js.map +0 -1
  737. package/dist/test/offline-recovery-branch.test.d.ts +0 -2
  738. package/dist/test/offline-recovery-branch.test.d.ts.map +0 -1
  739. package/dist/test/offline-recovery-branch.test.js +0 -570
  740. package/dist/test/offline-recovery-branch.test.js.map +0 -1
  741. package/dist/test/operator-surgery.test.d.ts +0 -2
  742. package/dist/test/operator-surgery.test.d.ts.map +0 -1
  743. package/dist/test/operator-surgery.test.js +0 -595
  744. package/dist/test/operator-surgery.test.js.map +0 -1
  745. package/dist/test/ops-alert.test.d.ts +0 -2
  746. package/dist/test/ops-alert.test.d.ts.map +0 -1
  747. package/dist/test/ops-alert.test.js +0 -153
  748. package/dist/test/ops-alert.test.js.map +0 -1
  749. package/dist/test/overbudget-drain-breaker.test.d.ts +0 -2
  750. package/dist/test/overbudget-drain-breaker.test.d.ts.map +0 -1
  751. package/dist/test/overbudget-drain-breaker.test.js +0 -198
  752. package/dist/test/overbudget-drain-breaker.test.js.map +0 -1
  753. package/dist/test/pack-installs-alone.test.d.ts +0 -2
  754. package/dist/test/pack-installs-alone.test.d.ts.map +0 -1
  755. package/dist/test/pack-installs-alone.test.js +0 -284
  756. package/dist/test/pack-installs-alone.test.js.map +0 -1
  757. package/dist/test/per-agent-delivery.test.d.ts +0 -2
  758. package/dist/test/per-agent-delivery.test.d.ts.map +0 -1
  759. package/dist/test/per-agent-delivery.test.js +0 -108
  760. package/dist/test/per-agent-delivery.test.js.map +0 -1
  761. package/dist/test/physical-window-restart.test.d.ts +0 -16
  762. package/dist/test/physical-window-restart.test.d.ts.map +0 -1
  763. package/dist/test/physical-window-restart.test.js +0 -487
  764. package/dist/test/physical-window-restart.test.js.map +0 -1
  765. package/dist/test/placed-reaction-baseline.test.d.ts +0 -2
  766. package/dist/test/placed-reaction-baseline.test.d.ts.map +0 -1
  767. package/dist/test/placed-reaction-baseline.test.js +0 -312
  768. package/dist/test/placed-reaction-baseline.test.js.map +0 -1
  769. package/dist/test/present-while-acting.test.d.ts +0 -19
  770. package/dist/test/present-while-acting.test.d.ts.map +0 -1
  771. package/dist/test/present-while-acting.test.js +0 -1649
  772. package/dist/test/present-while-acting.test.js.map +0 -1
  773. package/dist/test/prose-segments.test.d.ts +0 -2
  774. package/dist/test/prose-segments.test.d.ts.map +0 -1
  775. package/dist/test/prose-segments.test.js +0 -52
  776. package/dist/test/prose-segments.test.js.map +0 -1
  777. package/dist/test/prose-stream-router.test.d.ts +0 -2
  778. package/dist/test/prose-stream-router.test.d.ts.map +0 -1
  779. package/dist/test/prose-stream-router.test.js +0 -171
  780. package/dist/test/prose-stream-router.test.js.map +0 -1
  781. package/dist/test/provider-acceleration-cooldown.test.d.ts +0 -2
  782. package/dist/test/provider-acceleration-cooldown.test.d.ts.map +0 -1
  783. package/dist/test/provider-acceleration-cooldown.test.js +0 -435
  784. package/dist/test/provider-acceleration-cooldown.test.js.map +0 -1
  785. package/dist/test/provider-waits.test.d.ts +0 -2
  786. package/dist/test/provider-waits.test.d.ts.map +0 -1
  787. package/dist/test/provider-waits.test.js +0 -2259
  788. package/dist/test/provider-waits.test.js.map +0 -1
  789. package/dist/test/puppet-tool-call.test.d.ts +0 -2
  790. package/dist/test/puppet-tool-call.test.d.ts.map +0 -1
  791. package/dist/test/puppet-tool-call.test.js +0 -226
  792. package/dist/test/puppet-tool-call.test.js.map +0 -1
  793. package/dist/test/puppet-turn-reservation.test.d.ts +0 -2
  794. package/dist/test/puppet-turn-reservation.test.d.ts.map +0 -1
  795. package/dist/test/puppet-turn-reservation.test.js +0 -139
  796. package/dist/test/puppet-turn-reservation.test.js.map +0 -1
  797. package/dist/test/reaction-baseline-platform.test.d.ts +0 -2
  798. package/dist/test/reaction-baseline-platform.test.d.ts.map +0 -1
  799. package/dist/test/reaction-baseline-platform.test.js +0 -124
  800. package/dist/test/reaction-baseline-platform.test.js.map +0 -1
  801. package/dist/test/record-journal.test.d.ts +0 -6
  802. package/dist/test/record-journal.test.d.ts.map +0 -1
  803. package/dist/test/record-journal.test.js +0 -269
  804. package/dist/test/record-journal.test.js.map +0 -1
  805. package/dist/test/refusal-reaction-baseline.test.d.ts +0 -2
  806. package/dist/test/refusal-reaction-baseline.test.d.ts.map +0 -1
  807. package/dist/test/refusal-reaction-baseline.test.js +0 -81
  808. package/dist/test/refusal-reaction-baseline.test.js.map +0 -1
  809. package/dist/test/refusal-rewind.test.d.ts +0 -2
  810. package/dist/test/refusal-rewind.test.d.ts.map +0 -1
  811. package/dist/test/refusal-rewind.test.js +0 -117
  812. package/dist/test/refusal-rewind.test.js.map +0 -1
  813. package/dist/test/refusal-single-call.test.d.ts +0 -2
  814. package/dist/test/refusal-single-call.test.d.ts.map +0 -1
  815. package/dist/test/refusal-single-call.test.js +0 -177
  816. package/dist/test/refusal-single-call.test.js.map +0 -1
  817. package/dist/test/release-bump.test.d.ts +0 -2
  818. package/dist/test/release-bump.test.d.ts.map +0 -1
  819. package/dist/test/release-bump.test.js +0 -248
  820. package/dist/test/release-bump.test.js.map +0 -1
  821. package/dist/test/release-changelog.test.d.ts +0 -2
  822. package/dist/test/release-changelog.test.d.ts.map +0 -1
  823. package/dist/test/release-changelog.test.js +0 -159
  824. package/dist/test/release-changelog.test.js.map +0 -1
  825. package/dist/test/release-holds.test.d.ts +0 -2
  826. package/dist/test/release-holds.test.d.ts.map +0 -1
  827. package/dist/test/release-holds.test.js +0 -456
  828. package/dist/test/release-holds.test.js.map +0 -1
  829. package/dist/test/same-round-think-policy.test.d.ts +0 -2
  830. package/dist/test/same-round-think-policy.test.d.ts.map +0 -1
  831. package/dist/test/same-round-think-policy.test.js +0 -853
  832. package/dist/test/same-round-think-policy.test.js.map +0 -1
  833. package/dist/test/save-recent-image.test.d.ts +0 -26
  834. package/dist/test/save-recent-image.test.d.ts.map +0 -1
  835. package/dist/test/save-recent-image.test.js +0 -974
  836. package/dist/test/save-recent-image.test.js.map +0 -1
  837. package/dist/test/shutdown-errors.test.d.ts +0 -2
  838. package/dist/test/shutdown-errors.test.d.ts.map +0 -1
  839. package/dist/test/shutdown-errors.test.js +0 -662
  840. package/dist/test/shutdown-errors.test.js.map +0 -1
  841. package/dist/test/silent-heartbeat-rows.test.d.ts +0 -2
  842. package/dist/test/silent-heartbeat-rows.test.d.ts.map +0 -1
  843. package/dist/test/silent-heartbeat-rows.test.js +0 -451
  844. package/dist/test/silent-heartbeat-rows.test.js.map +0 -1
  845. package/dist/test/silent-heartbeat.test.d.ts +0 -2
  846. package/dist/test/silent-heartbeat.test.d.ts.map +0 -1
  847. package/dist/test/silent-heartbeat.test.js +0 -165
  848. package/dist/test/silent-heartbeat.test.js.map +0 -1
  849. package/dist/test/state-scaling-e2e.test.d.ts +0 -22
  850. package/dist/test/state-scaling-e2e.test.d.ts.map +0 -1
  851. package/dist/test/state-scaling-e2e.test.js +0 -206
  852. package/dist/test/state-scaling-e2e.test.js.map +0 -1
  853. package/dist/test/state-scaling.test.d.ts +0 -12
  854. package/dist/test/state-scaling.test.d.ts.map +0 -1
  855. package/dist/test/state-scaling.test.js +0 -251
  856. package/dist/test/state-scaling.test.js.map +0 -1
  857. package/dist/test/stop-with-host-operations.test.d.ts +0 -20
  858. package/dist/test/stop-with-host-operations.test.d.ts.map +0 -1
  859. package/dist/test/stop-with-host-operations.test.js +0 -1174
  860. package/dist/test/stop-with-host-operations.test.js.map +0 -1
  861. package/dist/test/stop-with-work-in-flight.test.d.ts +0 -23
  862. package/dist/test/stop-with-work-in-flight.test.d.ts.map +0 -1
  863. package/dist/test/stop-with-work-in-flight.test.js +0 -784
  864. package/dist/test/stop-with-work-in-flight.test.js.map +0 -1
  865. package/dist/test/surgery-marks-receipt.test.d.ts +0 -2
  866. package/dist/test/surgery-marks-receipt.test.d.ts.map +0 -1
  867. package/dist/test/surgery-marks-receipt.test.js +0 -540
  868. package/dist/test/surgery-marks-receipt.test.js.map +0 -1
  869. package/dist/test/thinking-token-stamp.test.d.ts +0 -12
  870. package/dist/test/thinking-token-stamp.test.d.ts.map +0 -1
  871. package/dist/test/thinking-token-stamp.test.js +0 -129
  872. package/dist/test/thinking-token-stamp.test.js.map +0 -1
  873. package/dist/test/timezone.test.d.ts +0 -2
  874. package/dist/test/timezone.test.d.ts.map +0 -1
  875. package/dist/test/timezone.test.js +0 -18
  876. package/dist/test/timezone.test.js.map +0 -1
  877. package/dist/test/tool-batch-hook.test.d.ts +0 -8
  878. package/dist/test/tool-batch-hook.test.d.ts.map +0 -1
  879. package/dist/test/tool-batch-hook.test.js +0 -275
  880. package/dist/test/tool-batch-hook.test.js.map +0 -1
  881. package/dist/test/tool-policy.test.d.ts +0 -2
  882. package/dist/test/tool-policy.test.d.ts.map +0 -1
  883. package/dist/test/tool-policy.test.js +0 -51
  884. package/dist/test/tool-policy.test.js.map +0 -1
  885. package/dist/test/tool-presentation.test.d.ts +0 -2
  886. package/dist/test/tool-presentation.test.d.ts.map +0 -1
  887. package/dist/test/tool-presentation.test.js +0 -268
  888. package/dist/test/tool-presentation.test.js.map +0 -1
  889. package/dist/test/tool-result-content.test.d.ts +0 -2
  890. package/dist/test/tool-result-content.test.d.ts.map +0 -1
  891. package/dist/test/tool-result-content.test.js +0 -37
  892. package/dist/test/tool-result-content.test.js.map +0 -1
  893. package/dist/test/tool-result-guard.test.d.ts +0 -2
  894. package/dist/test/tool-result-guard.test.d.ts.map +0 -1
  895. package/dist/test/tool-result-guard.test.js +0 -3729
  896. package/dist/test/tool-result-guard.test.js.map +0 -1
  897. package/dist/test/tool-result-history.test.d.ts +0 -7
  898. package/dist/test/tool-result-history.test.d.ts.map +0 -1
  899. package/dist/test/tool-result-history.test.js +0 -156
  900. package/dist/test/tool-result-history.test.js.map +0 -1
  901. package/dist/test/tool-result-spill.test.d.ts +0 -13
  902. package/dist/test/tool-result-spill.test.d.ts.map +0 -1
  903. package/dist/test/tool-result-spill.test.js +0 -586
  904. package/dist/test/tool-result-spill.test.js.map +0 -1
  905. package/dist/test/tool-wrapper-prose-guard-integration.test.d.ts +0 -2
  906. package/dist/test/tool-wrapper-prose-guard-integration.test.d.ts.map +0 -1
  907. package/dist/test/tool-wrapper-prose-guard-integration.test.js +0 -485
  908. package/dist/test/tool-wrapper-prose-guard-integration.test.js.map +0 -1
  909. package/dist/test/tool-wrapper-prose-guard.test.d.ts +0 -2
  910. package/dist/test/tool-wrapper-prose-guard.test.d.ts.map +0 -1
  911. package/dist/test/tool-wrapper-prose-guard.test.js +0 -34
  912. package/dist/test/tool-wrapper-prose-guard.test.js.map +0 -1
  913. package/dist/test/tools-observe-parser-conformance.test.d.ts +0 -2
  914. package/dist/test/tools-observe-parser-conformance.test.d.ts.map +0 -1
  915. package/dist/test/tools-observe-parser-conformance.test.js +0 -129
  916. package/dist/test/tools-observe-parser-conformance.test.js.map +0 -1
  917. package/dist/test/trunk-channel-routing.test.d.ts +0 -19
  918. package/dist/test/trunk-channel-routing.test.d.ts.map +0 -1
  919. package/dist/test/trunk-channel-routing.test.js +0 -652
  920. package/dist/test/trunk-channel-routing.test.js.map +0 -1
  921. package/dist/test/tune-out-e2e.test.d.ts +0 -2
  922. package/dist/test/tune-out-e2e.test.d.ts.map +0 -1
  923. package/dist/test/tune-out-e2e.test.js +0 -142
  924. package/dist/test/tune-out-e2e.test.js.map +0 -1
  925. package/dist/test/tune-out-gate-composition.test.d.ts +0 -2
  926. package/dist/test/tune-out-gate-composition.test.d.ts.map +0 -1
  927. package/dist/test/tune-out-gate-composition.test.js +0 -221
  928. package/dist/test/tune-out-gate-composition.test.js.map +0 -1
  929. package/dist/test/tune-out-lifecycle.test.d.ts +0 -2
  930. package/dist/test/tune-out-lifecycle.test.d.ts.map +0 -1
  931. package/dist/test/tune-out-lifecycle.test.js +0 -121
  932. package/dist/test/tune-out-lifecycle.test.js.map +0 -1
  933. package/dist/test/turn-trigger-provenance.test.d.ts +0 -2
  934. package/dist/test/turn-trigger-provenance.test.d.ts.map +0 -1
  935. package/dist/test/turn-trigger-provenance.test.js +0 -137
  936. package/dist/test/turn-trigger-provenance.test.js.map +0 -1
  937. package/dist/test/unconvertible-tool-result.test.d.ts +0 -2
  938. package/dist/test/unconvertible-tool-result.test.d.ts.map +0 -1
  939. package/dist/test/unconvertible-tool-result.test.js +0 -358
  940. package/dist/test/unconvertible-tool-result.test.js.map +0 -1
  941. package/dist/test/unsent-compiles.test.d.ts +0 -2
  942. package/dist/test/unsent-compiles.test.d.ts.map +0 -1
  943. package/dist/test/unsent-compiles.test.js +0 -139
  944. package/dist/test/unsent-compiles.test.js.map +0 -1
  945. package/dist/test/usage-accounting.test.d.ts +0 -2
  946. package/dist/test/usage-accounting.test.d.ts.map +0 -1
  947. package/dist/test/usage-accounting.test.js +0 -13
  948. package/dist/test/usage-accounting.test.js.map +0 -1
  949. package/dist/test/usage-tracker.test.d.ts +0 -2
  950. package/dist/test/usage-tracker.test.d.ts.map +0 -1
  951. package/dist/test/usage-tracker.test.js +0 -129
  952. package/dist/test/usage-tracker.test.js.map +0 -1
  953. package/dist/test/utils-surface.test.d.ts +0 -2
  954. package/dist/test/utils-surface.test.d.ts.map +0 -1
  955. package/dist/test/utils-surface.test.js +0 -145
  956. package/dist/test/utils-surface.test.js.map +0 -1
  957. package/dist/test/workspace-branch-continuation.test.d.ts +0 -15
  958. package/dist/test/workspace-branch-continuation.test.d.ts.map +0 -1
  959. package/dist/test/workspace-branch-continuation.test.js +0 -183
  960. package/dist/test/workspace-branch-continuation.test.js.map +0 -1
  961. package/dist/test/workspace-materialize-freshness.test.d.ts +0 -16
  962. package/dist/test/workspace-materialize-freshness.test.d.ts.map +0 -1
  963. package/dist/test/workspace-materialize-freshness.test.js +0 -252
  964. package/dist/test/workspace-materialize-freshness.test.js.map +0 -1
  965. package/dist/test/workspace-path-containment.test.d.ts +0 -19
  966. package/dist/test/workspace-path-containment.test.d.ts.map +0 -1
  967. package/dist/test/workspace-path-containment.test.js +0 -91
  968. package/dist/test/workspace-path-containment.test.js.map +0 -1
  969. package/dist/test/workspace-read-file-from-disk.test.d.ts +0 -17
  970. package/dist/test/workspace-read-file-from-disk.test.d.ts.map +0 -1
  971. package/dist/test/workspace-read-file-from-disk.test.js +0 -174
  972. package/dist/test/workspace-read-file-from-disk.test.js.map +0 -1
  973. package/dist/test/workspace-read-image.test.d.ts +0 -2
  974. package/dist/test/workspace-read-image.test.d.ts.map +0 -1
  975. package/dist/test/workspace-read-image.test.js +0 -597
  976. package/dist/test/workspace-read-image.test.js.map +0 -1
  977. package/dist/test/workspace-read-text.test.d.ts +0 -2
  978. package/dist/test/workspace-read-text.test.d.ts.map +0 -1
  979. package/dist/test/workspace-read-text.test.js +0 -101
  980. package/dist/test/workspace-read-text.test.js.map +0 -1
  981. package/dist/test/workspace-restore-order.test.d.ts +0 -16
  982. package/dist/test/workspace-restore-order.test.d.ts.map +0 -1
  983. package/dist/test/workspace-restore-order.test.js +0 -140
  984. package/dist/test/workspace-restore-order.test.js.map +0 -1
  985. package/dist/test/workspace-three-way.test.d.ts +0 -12
  986. package/dist/test/workspace-three-way.test.d.ts.map +0 -1
  987. package/dist/test/workspace-three-way.test.js +0 -4094
  988. package/dist/test/workspace-three-way.test.js.map +0 -1
  989. package/dist/test/workspace-watcher.test.d.ts +0 -2
  990. package/dist/test/workspace-watcher.test.d.ts.map +0 -1
  991. package/dist/test/workspace-watcher.test.js +0 -281
  992. package/dist/test/workspace-watcher.test.js.map +0 -1
  993. package/dist/test/xml-round-persist.test.d.ts +0 -19
  994. package/dist/test/xml-round-persist.test.d.ts.map +0 -1
  995. package/dist/test/xml-round-persist.test.js +0 -235
  996. package/dist/test/xml-round-persist.test.js.map +0 -1
  997. package/dist/tsconfig.tsbuildinfo +0 -1
@@ -27,6 +27,7 @@
27
27
  */
28
28
 
29
29
  import { createHash, randomBytes } from 'node:crypto';
30
+ import { REFERENCE_STUB_MAX_CHARS, referenceTypeLabel } from './mcpl/references.js';
30
31
  import { safeSlice } from './safe-slice.js';
31
32
 
32
33
  export interface RetainedToolImage {
@@ -189,8 +190,9 @@ function mintLedgerNonce(): string {
189
190
  /** Grammar of a ref this module mints: `img_<ledger nonce>_<sequence>`. */
190
191
  export const TOOL_IMAGE_REF_RE = /^img_[0-9a-z]+_\d+$/;
191
192
 
192
- /** RFC 6838 type/subtype token characters (lowercased); no parameters. */
193
- const MEDIA_TYPE_ESSENCE_RE = /^[a-z0-9!#$&^_.+-]+\/[a-z0-9!#$&^_.+-]+$/;
193
+ /** RFC 6838 type/subtype token characters (lowercased), each name at most
194
+ * 127 characters (its section 4.2); no parameters. */
195
+ const MEDIA_TYPE_ESSENCE_RE = /^[a-z0-9!#$&^_.+-]{1,127}\/[a-z0-9!#$&^_.+-]{1,127}$/;
194
196
  export const FALLBACK_MEDIA_TYPE = 'application/octet-stream';
195
197
 
196
198
  /**
@@ -228,21 +230,32 @@ export type ParsedImagePlaceholder =
228
230
  /** The placeholder exactly as it appears in the text. */
229
231
  text: string;
230
232
  }
231
- /** An RFC-005 reference stub whose testimony says image — bytes live
233
+ /** An RFC-005 reference stub whose text shows an image type — bytes live
232
234
  * behind fetch_reference, never in this ledger. Occupies a slot so the
233
235
  * index cannot slide past it. */
234
236
  | {
235
237
  kind: 'reference';
236
238
  refId: string;
237
- /** Mime sniffed from the stub text; null when the stub names none. */
238
- mediaType: string | null;
239
+ /** The image type the stub shows, as a stub shows a type (sanitized and
240
+ * bounded), lowercased: the first `image/` token in its text, which can
241
+ * come from its name. */
242
+ mediaType: string;
239
243
  offset: number;
240
244
  /** The stub line exactly as it appears in the text. */
241
245
  text: string;
242
246
  };
243
247
 
244
- const PLACEHOLDER_RE = /\[image: ([a-z0-9!#$&^_.+-]+\/[a-z0-9!#$&^_.+-]+), (~?[\d.]+(?:B|KB|MB))(?:, ref (img_[0-9a-z]+_\d+))?\]/g;
245
- /** `[ref_1_ab3d] cam.png — image/png, 1.2MB claimed — from tool result — …` (one line). */
248
+ /**
249
+ * `[image: image/png, ~691KB, ref img_k7x3q2_7]`. Each part is bounded by
250
+ * what formatToolImagePlaceholder writes, so text shaped like a placeholder
251
+ * but longer is no slot: a type and a subtype name at RFC 6838's 127
252
+ * characters each (normalizeMediaType writes none longer), and a size's
253
+ * number, a ledger nonce and a sequence at 16 characters each, a safe
254
+ * integer's digits.
255
+ */
256
+ const PLACEHOLDER_RE = /\[image: ([a-z0-9!#$&^_.+-]{1,127}\/[a-z0-9!#$&^_.+-]{1,127}), (~?[\d.]{1,16}(?:B|KB|MB))(?:, ref (img_[0-9a-z]{1,16}_\d{1,16}))?\]/g;
257
+ /** `[ref_1_ab3d] cam.png — image/png, 1.2MB claimed — from tool result — …`
258
+ * (one line, at most REFERENCE_STUB_MAX_CHARS long: see parseImagePlaceholders). */
246
259
  const REFERENCE_STUB_RE = /^\[(ref_[0-9a-z]+_[0-9a-z]+)\] ([^\n]*)$/gm;
247
260
  const IMAGE_MIME_RE = /\bimage\/[a-z0-9!#$&^_.+-]+/i;
248
261
 
@@ -252,6 +265,13 @@ const IMAGE_MIME_RE = /\bimage\/[a-z0-9!#$&^_.+-]+/i;
252
265
  * untrusted — a tool result can quote someone else's placeholder verbatim —
253
266
  * so the caller MUST cross-check a resolved ref's provenance against the
254
267
  * tool_result block it was found in before handing out bytes.
268
+ *
269
+ * Decided from the text alone, so a stored result counts the same however
270
+ * long ago it was written, across restarts and registry evictions. A
271
+ * reference stub is a slot when its text shows an image type, and a
272
+ * non-image reference is no slot. A line shaped like a stub but longer than
273
+ * buildReferenceStub writes (REFERENCE_STUB_MAX_CHARS) is quoted text and no
274
+ * slot either, so a slot's text is bounded wherever it is kept.
255
275
  */
256
276
  export function parseImagePlaceholders(text: string): ParsedImagePlaceholder[] {
257
277
  const out: ParsedImagePlaceholder[] = [];
@@ -259,43 +279,142 @@ export function parseImagePlaceholders(text: string): ParsedImagePlaceholder[] {
259
279
  out.push({ kind: 'inline', mediaType: m[1]!, sizeLabel: m[2]!, ref: m[3] ?? null, offset: m.index ?? 0, text: m[0] });
260
280
  }
261
281
  for (const m of text.matchAll(REFERENCE_STUB_RE)) {
262
- const mime = m[2]!.match(IMAGE_MIME_RE);
263
- out.push({ kind: 'reference', refId: m[1]!, mediaType: mime ? mime[0].toLowerCase() : null, offset: m.index ?? 0, text: m[0] });
282
+ if (m[0].length > REFERENCE_STUB_MAX_CHARS) continue;
283
+ const shown = m[2]!.match(IMAGE_MIME_RE);
284
+ if (!shown) continue;
285
+ out.push({ kind: 'reference', refId: m[1]!, mediaType: referenceTypeLabel(shown[0]).toLowerCase(), offset: m.index ?? 0, text: m[0] });
264
286
  }
265
287
  out.sort((a, b) => a.offset - b.offset);
266
288
  return out;
267
289
  }
268
290
 
269
291
  /**
270
- * Cut `text` to at most `cap` chars WITHOUT losing or splitting an image
271
- * slot. The stored tool_result text is the only place the inventory
272
- * discovers tool images, while the live wire still delivers every image
273
- * regardless of text length — so a slot dropped by truncation is an image
274
- * the resident saw that the index silently slides past (the #104 failure,
275
- * one representation over). Returns the head to keep and the slots that
276
- * fell at or past the cut, to be re-appended verbatim after the truncation
277
- * notice. A slot straddling the cut moves the cut back to its start, so the
278
- * head never contains a partial slot (a partial reference-stub line would
279
- * otherwise still re-parse and be counted twice).
292
+ * The most image slots a stored copy keeps past its cut: a bound on what it
293
+ * carries there, set at the ledger's entry limit, the most images it holds
294
+ * bytes for. Serializing a result retains its images in order before their
295
+ * placeholders are written, and every agent's ledger is built with the
296
+ * defaults, so once a result is stored a save can reach bytes for at most
297
+ * its newest DEFAULT_TOOL_IMAGE_LEDGER_MAX_ENTRIES images, fewer when the
298
+ * ledger's limit on held characters binds first, and an inline image older
299
+ * than those can only fail. Image stubs and quoted placeholders count toward
300
+ * the bound too, so where they follow a result's images past the cut, the
301
+ * newest slots kept can leave out an image whose bytes the ledger still
302
+ * holds.
303
+ */
304
+ export const MAX_KEPT_IMAGE_SLOTS = DEFAULT_TOOL_IMAGE_LEDGER_MAX_ENTRIES;
305
+
306
+ /** The ranges `[start, end)` of a tool result's text that its live copy
307
+ * showed beside its images: each text block up to where the live copy cut it
308
+ * at the inline cap (toolResultCutAt), and every other block whole. They
309
+ * come in text order and never overlap, as the blocks do, and
310
+ * cutStoredToolResult relies on that. */
311
+ export type ShownRanges = ReadonlyArray<readonly [number, number]>;
312
+
313
+ /** A tool result's stored copy, cut at its inline cap. */
314
+ export interface StoredCut {
315
+ /** The text before the cut. */
316
+ head: string;
317
+ /** The image slots past the cut that the stored copy re-appends after its
318
+ * truncation notice, in text order: the newest MAX_KEPT_IMAGE_SLOTS of
319
+ * those the live copy showed. */
320
+ kept: string[];
321
+ /** How many image slots past the cut the live copy showed. */
322
+ fell: number;
323
+ }
324
+
325
+ /**
326
+ * Where a tool result's text longer than `cap` is cut: by its stored copy
327
+ * (cutStoredToolResult), by history's own truncation (truncateForHistory),
328
+ * and by its live copy, for each text block beside an image
329
+ * (tryNativeToolResultContent, framework.ts), so the stored copy and the live
330
+ * copy cut alike. The text's length when it isn't longer than `cap`.
331
+ *
332
+ * The cut is made at the cap, or before it when the cap would split a
333
+ * surrogate pair (safeSlice's rule), and that is where the moves back are
334
+ * measured from. It moves back to the start of a placeholder it would split,
335
+ * and then to the start of a stub-shaped line it would split when at most
336
+ * REFERENCE_STUB_MAX_CHARS of the line lie before it, since that part could
337
+ * still read as a slot. So no slot straddles the cut, and the text before it
338
+ * never ends in part of one. A longer part, which can't parse as a slot,
339
+ * stays before the cut. Each move back lands on a `[`, so it splits no pair.
280
340
  */
281
- export function splitPreservingImageSlots(text: string, cap: number): { head: string; tail: string[] } {
282
- const slots = parseImagePlaceholders(text);
283
- let cutAt = cap;
284
- for (const slot of slots) {
285
- if (slot.offset < cutAt && slot.offset + slot.text.length > cutAt) cutAt = slot.offset;
341
+ export function toolResultCutAt(text: string, cap: number): number {
342
+ if (text.length <= cap) return text.length;
343
+ let cutAt = safeSlice(text, 0, cap).length;
344
+ // Neither grammar crosses a newline, so only the line holding the cut can
345
+ // be split; it is read whole, as the parser reads it.
346
+ const lineStart = text.lastIndexOf('\n', cutAt - 1) + 1;
347
+ const newline = text.indexOf('\n', cutAt);
348
+ const line = text.slice(lineStart, newline === -1 ? text.length : newline);
349
+ for (const m of line.matchAll(PLACEHOLDER_RE)) {
350
+ const start = lineStart + (m.index ?? 0);
351
+ if (start < cutAt && start + m[0].length > cutAt) cutAt = start;
286
352
  }
287
- return {
288
- head: safeSlice(text, 0, cutAt),
289
- tail: slots.filter((slot) => slot.offset >= cutAt).map((slot) => slot.text),
290
- };
353
+ for (const m of line.matchAll(REFERENCE_STUB_RE)) {
354
+ const start = lineStart + (m.index ?? 0);
355
+ if (start < cutAt && start + m[0].length > cutAt && cutAt - start <= REFERENCE_STUB_MAX_CHARS) cutAt = start;
356
+ }
357
+ return cutAt;
291
358
  }
292
359
 
293
- /** Text to append after a truncation notice so the preserved slots stay
294
- * parseable (each reference stub on its own line). Empty when none. */
295
- export function formatPreservedImageSlots(tail: string[]): string {
296
- if (tail.length === 0) return '';
297
- return `\n[${tail.length} image slot(s) fell past the cut; kept here in order so save_recent_image still counts them:]\n`
298
- + tail.join('\n');
360
+ /**
361
+ * Cut a tool result's text at its inline `cap` as its stored copy keeps it
362
+ * (toolResultCutAt): the stored copy keeps what the live copy showed. A text
363
+ * within the cap is all head, with nothing kept after it.
364
+ *
365
+ * `shown` is what the live copy showed beside the stored text: null when the
366
+ * live copy was the text itself, as for every result that carried no inline
367
+ * image. Then what the cut keeps is exactly what the resident saw, and
368
+ * nothing past it is kept (#403). A result that carried an inline image went
369
+ * to the model as native blocks (tryNativeToolResultContent, framework.ts),
370
+ * every image whatever the text's length, so its stored text is the only
371
+ * place save_recent_image's inventory finds them, and a slot dropped by the
372
+ * cut would be an image the resident saw that the index slides past (#104).
373
+ * The image slots past the cut that lie wholly within what the live copy
374
+ * showed are kept, the newest MAX_KEPT_IMAGE_SLOTS of them, since the
375
+ * inventory counts from the end.
376
+ */
377
+ export function cutStoredToolResult(text: string, cap: number, shown: ShownRanges | null): StoredCut {
378
+ const cutAt = toolResultCutAt(text, cap);
379
+ const head = text.slice(0, cutAt);
380
+ if (shown === null) return { head, kept: [], fell: 0 };
381
+ // The slots and the ranges both come in text order, so one pass walks
382
+ // them together: a range that ends where a slot starts, or before, holds
383
+ // no later slot either.
384
+ const past: ParsedImagePlaceholder[] = [];
385
+ let r = 0;
386
+ for (const slot of parseImagePlaceholders(text)) {
387
+ if (slot.offset < cutAt) continue;
388
+ while (r < shown.length && shown[r]![1] <= slot.offset) r++;
389
+ const range = shown[r];
390
+ if (range && slot.offset >= range[0] && slot.offset + slot.text.length <= range[1]) past.push(slot);
391
+ }
392
+ return { head, kept: past.slice(-MAX_KEPT_IMAGE_SLOTS).map((slot) => slot.text), fell: past.length };
393
+ }
394
+
395
+ /** What a stored copy re-appends after its truncation notice: the kept
396
+ * slots, each on its own line so a reference stub stays parseable, under a
397
+ * note saying how many fell past the cut, and how many of those were left
398
+ * out and aren't counted. Empty when none fell past the cut. */
399
+ export function formatKeptImageSlots(cut: StoredCut): string {
400
+ if (cut.fell === 0) return '';
401
+ const leftOut = cut.fell - cut.kept.length;
402
+ const note = leftOut === 0
403
+ ? `${cut.fell} image slot(s) fell past the cut; kept here in order so save_recent_image still counts them:`
404
+ : `${cut.fell} image slot(s) fell past the cut. The last ${cut.kept.length} are kept here in order so `
405
+ + `save_recent_image still counts them; the ${leftOut} before them are left out, and it doesn't count them:`;
406
+ return `\n[${note}]\n${cut.kept.join('\n')}`;
407
+ }
408
+
409
+ /**
410
+ * The image slots a tool result's stored copy holds: its text's, or, when the
411
+ * text is longer than `cap`, those the cut keeps, in head and after the
412
+ * notice (cutStoredToolResult). The notice itself holds none. For counting a
413
+ * result before its stored copy is written, as it will count after.
414
+ */
415
+ export function storedImageSlots(text: string, cap: number, shown: ShownRanges | null): ParsedImagePlaceholder[] {
416
+ const cut = cutStoredToolResult(text, cap, shown);
417
+ return parseImagePlaceholders(cut.head + formatKeptImageSlots(cut));
299
418
  }
300
419
 
301
420
  export function sha256Hex(bytes: Buffer): string {
@@ -1,5 +1,7 @@
1
1
  import { createHash, randomUUID } from 'node:crypto';
2
- import { fchmodSync, closeSync, fstatSync, lstatSync, openSync, readSync, renameSync, unlinkSync, writeFileSync } from 'node:fs';
2
+ import { constants, fchmodSync, closeSync, fstatSync, lstatSync, openSync, readSync, renameSync, unlinkSync, writeFileSync } from 'node:fs';
3
+ import { closestNames } from './closest-names.js';
4
+ import { boundedErrorMessage, errorMessage } from './error-message.js';
3
5
  import type { ToolDefinition, ToolResult } from './types/events.js';
4
6
 
5
7
  export interface ToolPresentationConfig {
@@ -22,23 +24,145 @@ export interface PresentationSnapshot {
22
24
  entries: { name: string; source: string; visible: boolean; originalDescription: string; description: string; descriptionSource?: string; inputSchema: ToolDefinition['inputSchema'] }[];
23
25
  }
24
26
  const MAX_BYTES = 256 * 1024;
27
+ /**
28
+ * Opened with each read of a presentation file, as observe.ts opens workspace
29
+ * files: a FIFO at the operator's path opens at once and fails the regular-file
30
+ * check, where a blocking open would hold the whole process (it's synchronous)
31
+ * until something opened the FIFO for writing.
32
+ */
33
+ const NONBLOCK = typeof constants.O_NONBLOCK === 'number' ? constants.O_NONBLOCK : 0;
34
+ const MAX_DESCRIPTION_CHARS = 32768;
25
35
  const protectedNames = new Set(['set_tool_visibility', 'set_tool_description', 'workspace--read']);
26
36
  export const isPresentationTool = (name: string): boolean => name === 'set_tool_visibility' || name === 'set_tool_description';
27
37
  const hash = (value: string): string => createHash('sha256').update(value).digest('hex');
28
38
 
29
- export function parsePresentation(raw: string): PresentationDocument {
30
- const doc = JSON.parse(raw);
31
- if (!doc || doc.version !== 1 || !doc.tools || typeof doc.tools !== 'object' || Array.isArray(doc.tools)
32
- || Object.keys(doc).some(k => !['version', 'tools'].includes(k))) throw new Error('Expected {"version":1,"tools":{...}}');
33
- for (const [name, value] of Object.entries(doc.tools)) {
34
- if (!name || !value || typeof value !== 'object' || Array.isArray(value)) throw new Error(`Invalid override: ${name}`);
39
+ /**
40
+ * A presentation or defaults file this host can't use. Each problem is a
41
+ * clause about the file, such as `the entry for "x" has "visible": "no",
42
+ * which must be true or false`; whoever reports it names the file and says
43
+ * what follows from it.
44
+ */
45
+ class PresentationFileError extends Error {
46
+ constructor(problems: string[]) {
47
+ const more = problems.length - 10;
48
+ super((more > 0 ? [...problems.slice(0, 10), `${more} more problem${more === 1 ? '' : 's'}`] : problems).join('; '));
49
+ }
50
+ }
51
+
52
+ /** An edit refused, in words for the agent: its message is the whole result. */
53
+ class PresentationRefusal extends Error {}
54
+
55
+ const count = (n: number): string => n.toLocaleString('en-US');
56
+
57
+ /** A text's length in code points, so a character outside the Basic Multilingual Plane, such as 😀, counts once where UTF-16 counts it twice. */
58
+ const characters = (text: string): number => [...text].length;
59
+
60
+ /** A text's first `n` characters, never splitting a code point. */
61
+ const firstCharacters = (text: string, n: number): string => [...text].slice(0, n).join('');
62
+
63
+ /** A name as a message quotes it: whole up to 60 characters, and past that cut, with its length, since a file can hold a key of any size. */
64
+ function quoted(name: string): string {
65
+ return characters(name) <= 60 ? JSON.stringify(name) : `${JSON.stringify(firstCharacters(name, 57))}... (${count(characters(name))} characters)`;
66
+ }
67
+
68
+ /** A file's problem as a message quotes it: its own clauses whole, and anything else bounded, since nobody wrote that text for its reader. */
69
+ const problemText = (error: unknown): string => error instanceof PresentationFileError ? error.message : boundedErrorMessage(error);
70
+
71
+ /** A value as a message quotes it: short JSON for a scalar, the kind of anything bigger. */
72
+ function shown(value: unknown): string {
73
+ if (Array.isArray(value)) return 'an array';
74
+ if (value !== null && typeof value === 'object') return 'an object';
75
+ const json = JSON.stringify(value) ?? String(value);
76
+ return characters(json) > 40 ? `${firstCharacters(json, 37)}...` : json;
77
+ }
78
+
79
+ /** Names quoted and joined: "a", "a" and "b", "a", "b" and "c"; past ten, the first ten and how many more, since a file can hold any number of keys. Each is quoted by `quote`: quoted() by default, which cuts a file's long keys, or JSON.stringify for names the agent should copy whole. */
80
+ function quotedList(names: string[], conjunction: 'and' | 'or' = 'and', quote: (name: string) => string = quoted): string {
81
+ const each = names.slice(0, 10).map((name) => quote(name));
82
+ if (names.length > 10) return `${each.join(', ')} ${conjunction} ${count(names.length - 10)} more`;
83
+ return each.length > 1 ? `${each.slice(0, -1).join(', ')} ${conjunction} ${each[each.length - 1]}` : each.join('');
84
+ }
85
+
86
+ /**
87
+ * Every problem that keeps a document from being used, each by where it is;
88
+ * none for a usable one. A defaults file (`descriptionsOnly`) may set
89
+ * descriptions only, since visibility is the resident's to choose.
90
+ */
91
+ function documentProblems(doc: unknown, descriptionsOnly: boolean): string[] {
92
+ if (!doc || typeof doc !== 'object' || Array.isArray(doc)) return [`its top level is ${shown(doc)}, not an object like {"version":1,"tools":{}}`];
93
+ const top = doc as Record<string, unknown>;
94
+ const problems: string[] = [];
95
+ if (top.version !== 1) problems.push(`"version" must be 1, and ${Object.hasOwn(top, 'version') ? `it is ${shown(top.version)}` : "it's missing"}`);
96
+ const extra = Object.keys(top).filter((key) => key !== 'version' && key !== 'tools');
97
+ if (extra.length) problems.push(`only "version" and "tools" belong at the top level, not ${quotedList(extra)}`);
98
+ const tools = top.tools;
99
+ if (!tools || typeof tools !== 'object' || Array.isArray(tools)) {
100
+ problems.push(`"tools" must be an object of tool names, and ${Object.hasOwn(top, 'tools') ? `it is ${shown(tools)}` : "it's missing"}`);
101
+ return problems;
102
+ }
103
+ const setsVisibility: string[] = [];
104
+ for (const [name, value] of Object.entries(tools)) {
105
+ if (!name) { problems.push('"tools" has an entry with an empty name'); continue; }
106
+ const entry = `the entry for ${quoted(name)}`;
107
+ if (!value || typeof value !== 'object' || Array.isArray(value)) { problems.push(`${entry} is ${shown(value)}, not an object such as {"visible":false}`); continue; }
35
108
  const item = value as Record<string, unknown>;
36
- if (Object.keys(item).some(k => !['description', 'visible'].includes(k))
37
- || ('description' in item && (typeof item.description !== 'string' || item.description.length > 32768))
38
- || ('visible' in item && typeof item.visible !== 'boolean')) throw new Error(`Invalid description/visibility for ${name}`);
39
- if (protectedNames.has(name) && item.visible === false) throw new Error(`Cannot hide recovery tool ${name}`);
109
+ const unknown = Object.keys(item).filter((key) => key !== 'description' && key !== 'visible');
110
+ if (unknown.length) problems.push(`${entry} has ${quotedList(unknown)}, and an entry may have only ${descriptionsOnly ? '"description"' : '"description" and "visible"'}`);
111
+ if (Object.hasOwn(item, 'description')) {
112
+ if (typeof item.description !== 'string') problems.push(`${entry} has a "description" that is ${shown(item.description)}, not a string`);
113
+ else if (characters(item.description) > MAX_DESCRIPTION_CHARS) problems.push(`${entry} has a "description" of ${count(characters(item.description))} characters, over the ${count(MAX_DESCRIPTION_CHARS)} allowed`);
114
+ }
115
+ if (!Object.hasOwn(item, 'visible')) continue;
116
+ if (descriptionsOnly) setsVisibility.push(name);
117
+ else if (typeof item.visible !== 'boolean') problems.push(`${entry} has "visible": ${shown(item.visible)}, which must be true or false`);
118
+ else if (!item.visible && protectedNames.has(name)) problems.push(`${entry} hides it, which isn't allowed, since workspace--read, set_tool_visibility and set_tool_description are how the catalogue is read and how these settings are undone`);
40
119
  }
41
- return doc;
120
+ if (setsVisibility.length) problems.push(`it sets "visible" for ${quotedList(setsVisibility)}, and a defaults file may set only descriptions, since visibility is yours to choose`);
121
+ return problems;
122
+ }
123
+
124
+ function parseDocument(raw: string, descriptionsOnly: boolean): PresentationDocument {
125
+ let doc: unknown;
126
+ try { doc = JSON.parse(raw); }
127
+ catch (error) { throw new PresentationFileError([`it isn't valid JSON: ${errorMessage(error)}`]); }
128
+ const problems = documentProblems(doc, descriptionsOnly);
129
+ if (problems.length) throw new PresentationFileError(problems);
130
+ return doc as PresentationDocument;
131
+ }
132
+
133
+ /** A resident's presentation document, or an error naming every problem that keeps it from being used. */
134
+ export function parsePresentation(raw: string): PresentationDocument {
135
+ return parseDocument(raw, false);
136
+ }
137
+
138
+ /**
139
+ * What an agent is told when an edit fails. Every throw in `edit()` comes
140
+ * before its rename, and the cleanup after it never throws, so nothing was
141
+ * changed: a refusal says so in its own words, a file this host can't use is
142
+ * the host's to repair, and anything else is reported as the error it is.
143
+ */
144
+ function editFailure(error: unknown): string {
145
+ if (error instanceof PresentationRefusal) return error.message;
146
+ if (error instanceof PresentationFileError) return `Nothing was changed: your tool presentation file can't be used (${error.message}), and these tools won't write over it until it's repaired. Ask whoever runs this host to repair it.`;
147
+ const code = (error as NodeJS.ErrnoException | null)?.code;
148
+ return `Nothing was changed: the edit failed (${typeof code === 'string' ? code : boundedErrorMessage(error)}). Ask whoever runs this host to check your tool presentation file and its directory.`;
149
+ }
150
+
151
+ /** Whether a path is a symbolic link, so an open that found nothing can tell a dangling link from no file. */
152
+ function isLink(path: string): boolean {
153
+ try { return lstatSync(path).isSymbolicLink(); } catch { return false; }
154
+ }
155
+
156
+ /** Runs one step of an edit's cleanup, which must not throw: it returns what the step threw, if it did. */
157
+ function tidy(step: () => void): { error: unknown } | undefined {
158
+ try { step(); return undefined; } catch (error) { return { error }; }
159
+ }
160
+
161
+ /** What an edit says when its lock couldn't be removed afterwards, since every later edit will meet that lock. */
162
+ function lockLeftBehind(error: unknown): string {
163
+ const code = (error as NodeJS.ErrnoException | undefined)?.code;
164
+ return `This edit couldn't remove its lock afterwards, the presentation file's name with .lock added${typeof code === 'string' ? ` (${code})` : ''}. `
165
+ + 'Until whoever runs this host removes it, set_tool_visibility and set_tool_description will be refused, saying an edit left its lock behind.';
42
166
  }
43
167
 
44
168
  export function presentationTools(path: string): ToolDefinition[] {
@@ -56,44 +180,51 @@ export class ToolPresentation {
56
180
  constructor(readonly config: ToolPresentationConfig) {}
57
181
  private read(path = this.config.path, allowMissing = true): string {
58
182
  let fd: number;
59
- try { fd = openSync(path, 'r'); }
60
- catch (error) { if (allowMissing && (error as NodeJS.ErrnoException).code === 'ENOENT') return '{"version":1,"tools":{}}'; throw error; }
183
+ try { fd = openSync(path, constants.O_RDONLY | NONBLOCK); }
184
+ catch (error) {
185
+ const code = (error as NodeJS.ErrnoException).code;
186
+ if (code === 'ENOENT') {
187
+ if (isLink(path)) throw new PresentationFileError(["it's a symbolic link to a file that doesn't exist"]);
188
+ if (allowMissing) return '{"version":1,"tools":{}}';
189
+ throw new PresentationFileError(["it doesn't exist"]);
190
+ }
191
+ throw new PresentationFileError([`it couldn't be opened: ${code ?? boundedErrorMessage(error)}`]);
192
+ }
61
193
  try {
62
194
  const stat = fstatSync(fd);
63
- if (!stat.isFile() || stat.size > MAX_BYTES) throw new Error('Presentation must be a regular file under 256 KiB');
195
+ if (!stat.isFile()) throw new PresentationFileError(["it isn't a regular file"]);
196
+ if (stat.size > MAX_BYTES) throw new PresentationFileError([`it's ${count(stat.size)} bytes, over the ${count(MAX_BYTES)} (256 KiB) this host reads`]);
64
197
  const data = Buffer.alloc(MAX_BYTES + 1);
65
- let size = 0, count = 0;
66
- while (size < data.length && (count = readSync(fd, data, size, data.length - size, null)) > 0) size += count;
67
- if (size > MAX_BYTES) throw new Error('Presentation exceeds 256 KiB');
198
+ let size = 0, bytesRead = 0;
199
+ while (size < data.length && (bytesRead = readSync(fd, data, size, data.length - size, null)) > 0) size += bytesRead;
200
+ if (size > MAX_BYTES) throw new PresentationFileError([`it grew past ${count(MAX_BYTES)} bytes (256 KiB) while it was being read`]);
68
201
  return data.subarray(0,size).toString('utf8');
69
202
  } finally { closeSync(fd); }
70
203
  }
71
204
  resolve(tools: ToolDefinition[], sources: ReadonlyMap<string, string> = new Map()): PresentationSnapshot {
72
205
  let raw = '', doc: PresentationDocument = {version:1,tools:{}}, diagnostics: string[] = [];
73
206
  try { raw = this.read(); doc = parsePresentation(raw); }
74
- catch (error) { diagnostics.push(`Overrides not applied: ${String(error)}. Default visibility and component descriptions retained.`); }
207
+ catch (error) { diagnostics.push(`Your tool presentation file can't be used (${problemText(error)}), so none of its settings apply: every tool is visible and shows its configured default description, or its installed one where none is configured. set_tool_visibility and set_tool_description won't change the file until it's repaired; ask whoever runs this host to repair it.`); }
75
208
  const defaults = new Map<string, {description: string; path: string}>();
76
209
  const configuredSources = new Set<string>();
77
210
  for (const profile of this.config.defaults ?? []) {
78
211
  if (configuredSources.has(profile.source)) {
79
- diagnostics.push(`Duplicate defaults source ignored: ${profile.source}`); continue;
212
+ diagnostics.push(`The description defaults for ${JSON.stringify(profile.source)} are configured twice; only the first is read, and the other is ignored. Ask whoever runs this host to remove the duplicate.`); continue;
80
213
  }
81
214
  configuredSources.add(profile.source);
82
215
  // Absent components contribute neither tools nor missing-file errors.
83
216
  if (!tools.some(t => (sources.get(t.name) ?? 'Unattributed') === profile.source)) continue;
84
217
  try {
85
- const profileDoc = parsePresentation(this.read(profile.path, false));
86
- if (Object.values(profileDoc.tools).some(item => Object.keys(item).some(k => k !== 'description')))
87
- throw new Error('Component defaults may contain descriptions only; visibility belongs to the resident');
218
+ const profileDoc = parseDocument(this.read(profile.path, false), true);
88
219
  for (const tool of tools) {
89
220
  if ((sources.get(tool.name) ?? 'Unattributed') !== profile.source) continue;
90
221
  const item = Object.hasOwn(profileDoc.tools, tool.name) ? profileDoc.tools[tool.name] : undefined;
91
222
  if (item?.description !== undefined) defaults.set(tool.name, {description:item.description,path:profile.path});
92
223
  }
93
- } catch (error) { diagnostics.push(`Component defaults not applied (${profile.source}): ${String(error)}`); }
224
+ } catch (error) { diagnostics.push(`The description defaults for ${JSON.stringify(profile.source)} can't be used (${problemText(error)}), so its tools show their installed descriptions, or yours where you set one. Ask whoever runs this host to fix that defaults file.`); }
94
225
  }
95
226
  const names = new Set(tools.map(t => t.name));
96
- for (const name of Object.keys(doc.tools)) if (!names.has(name)) diagnostics.push(`Not currently available: ${name}`);
227
+ for (const name of Object.keys(doc.tools)) if (!names.has(name)) diagnostics.push(`Not currently available: ${quoted(name)}`);
97
228
  const entries = tools.map(tool => {
98
229
  const override = Object.hasOwn(doc.tools, tool.name) ? doc.tools[tool.name] : undefined;
99
230
  // Always retain a usable discovery signpost, even when its wording is overridden.
@@ -111,39 +242,98 @@ export class ToolPresentation {
111
242
  edit(tool: string, input: unknown, available: ToolDefinition[]): ToolResult {
112
243
  const lock = this.config.path + '.lock';
113
244
  let fd: number | undefined, tempFd: number | undefined, temp: string | undefined;
245
+ let result: ToolResult, lockLeft: { error: unknown } | undefined;
114
246
  try {
115
- if (!isPresentationTool(tool)) throw new Error('Unknown editing tool');
116
- const value = input as Record<string, unknown>;
247
+ if (!isPresentationTool(tool)) throw new Error(`${tool} isn't a tool presentation editing tool`);
117
248
  const field = tool === 'set_tool_visibility' ? 'visible' : 'description';
118
- if (!value || typeof value !== 'object' || Array.isArray(value) || typeof value.name !== 'string'
119
- || Object.keys(value).some(k=> !['name',field].includes(k)) || !Object.hasOwn(value,field)) throw new Error('Invalid editing arguments');
120
- if (!available.some(t=>t.name===value.name)) throw new Error('Tool is not currently available to this agent');
121
- if (field === 'visible' ? typeof value.visible !== 'boolean' : value.description !== null && typeof value.description !== 'string') throw new Error(`Invalid ${field}`);
122
- fd = openSync(lock, 'wx', 0o600);
249
+ const name = this.editedName(tool, field, input, available);
250
+ const value = input as Record<string, unknown>;
251
+ try { fd = openSync(lock, 'wx', 0o600); }
252
+ catch (error) {
253
+ if ((error as NodeJS.ErrnoException).code !== 'EEXIST') throw error;
254
+ throw new PresentationRefusal("Nothing was changed: an earlier edit of your tool presentation file left its lock behind, or another edit is in progress. Call this again in a few seconds. If it fails the same way, ask whoever runs this host to remove the stale lock, the presentation file's name with .lock added, once nothing is editing the file.");
255
+ }
123
256
  let mode = 0o600;
124
- try { const stat = lstatSync(this.config.path); if (stat.isSymbolicLink()) throw new Error('Edit the target file directly; tool editing refuses symlinks'); mode = stat.mode & 0o777; }
257
+ try {
258
+ const stat = lstatSync(this.config.path);
259
+ if (stat.isSymbolicLink()) throw new PresentationRefusal("Nothing was changed: your tool presentation file is a symbolic link, and these tools don't write through links. Ask whoever runs this host to make the change in the file it points to, or to replace the link with that file.");
260
+ mode = stat.mode & 0o777;
261
+ }
125
262
  catch (error) { if ((error as NodeJS.ErrnoException).code !== 'ENOENT') throw error; }
126
263
  const before = this.read(), doc = parsePresentation(before);
127
- const old = Object.hasOwn(doc.tools,value.name) ? doc.tools[value.name] : {};
264
+ const old = Object.hasOwn(doc.tools,name) ? doc.tools[name] : {};
128
265
  const updated = {...old};
129
266
  if (field === 'description' && value.description === null) delete updated.description;
130
267
  else Object.assign(updated,{[field]:value[field]});
131
- Object.defineProperty(doc.tools,value.name,{value:updated,enumerable:true,writable:true,configurable:true});
268
+ Object.defineProperty(doc.tools,name,{value:updated,enumerable:true,writable:true,configurable:true});
132
269
  const next = JSON.stringify(doc,null,2)+'\n';
270
+ // editedName has checked what this adds, so this can't fail on the agent's input;
271
+ // it keeps a gap in those checks from writing a file the host would then ignore.
133
272
  parsePresentation(next);
134
- if (Buffer.byteLength(next)>MAX_BYTES) throw new Error('Presentation exceeds 256 KiB');
273
+ const size = Buffer.byteLength(next);
274
+ if (size>MAX_BYTES) throw new PresentationRefusal(`Nothing was changed: with this change your tool presentation file would be ${count(size)} bytes, ${count(size - MAX_BYTES)} over its limit of ${count(MAX_BYTES)} (256 KiB). `
275
+ + (field === 'description' ? 'Use a shorter description, or make room by restoring descriptions you no longer need with "description": null.' : 'Make room by restoring descriptions you no longer need with set_tool_description and "description": null.')
276
+ + ' Entries for tools no longer available to you can be removed only by whoever runs this host.');
135
277
  temp = this.config.path + '.' + randomUUID() + '.tmp';
136
278
  tempFd = openSync(temp,'wx',0o600);
137
279
  writeFileSync(tempFd,next);
138
280
  fchmodSync(tempFd,mode); // preserve permissions on the opened inode, never a replacement path
139
- if (this.read() !== before) throw new Error('File changed concurrently; retry after reading it');
281
+ if (this.read() !== before) throw new PresentationRefusal('Nothing was changed: your tool presentation file changed while this edit was being made. Call this again; it applies to the file as it is now.');
140
282
  const opened = fstatSync(tempFd), named = lstatSync(temp);
141
283
  if (!named.isFile() || named.dev !== opened.dev || named.ino !== opened.ino)
142
- throw new Error('Temporary file changed concurrently; retry after checking the directory');
284
+ throw new PresentationRefusal('Nothing was changed: the temporary copy this edit was writing was replaced while it was written. Call this again; if it fails the same way, ask whoever runs this host to check what else writes beside your tool presentation file.');
143
285
  renameSync(temp,this.config.path); temp=undefined;
144
- return {success:true,data:{name:value.name,[field]:value[field],effective:'next newly compiled request',catalogue:this.config.cataloguePath}};
145
- } catch (error) { return {success:false,isError:true,error:String(error)}; }
146
- finally { if(tempFd!==undefined) closeSync(tempFd); if(temp) try{unlinkSync(temp);}catch{} if(fd!==undefined){closeSync(fd);unlinkSync(lock);} }
286
+ result = {success:true,data:{name,[field]:value[field],effective:'next newly compiled request',catalogue:this.config.cataloguePath}};
287
+ } catch (error) { result = {success:false,isError:true,error:editFailure(error)}; }
288
+ finally {
289
+ // After the rename the edit's result must stand, so no cleanup step may throw.
290
+ const tempFdToClose = tempFd, tempToRemove = temp, lockFd = fd;
291
+ if (tempFdToClose !== undefined) tidy(() => closeSync(tempFdToClose));
292
+ if (tempToRemove) tidy(() => unlinkSync(tempToRemove));
293
+ if (lockFd !== undefined) {
294
+ tidy(() => closeSync(lockFd));
295
+ lockLeft = tidy(() => unlinkSync(lock));
296
+ // A lock already gone was removed by something else, so none is left.
297
+ if ((lockLeft?.error as NodeJS.ErrnoException | undefined)?.code === 'ENOENT') lockLeft = undefined;
298
+ }
299
+ }
300
+ if (!lockLeft) return result;
301
+ return result.success
302
+ ? {...result,data:{...(result.data as Record<string, unknown>),note:lockLeftBehind(lockLeft.error)}}
303
+ : {...result,error:`${result.error} ${lockLeftBehind(lockLeft.error)}`};
304
+ }
305
+ /**
306
+ * The name of the tool an edit is for, once the agent's arguments hold up;
307
+ * otherwise a refusal naming every problem with them and the call to make.
308
+ * The limits a file would refuse (a description's length, the tools that
309
+ * can't be hidden) are checked here too, so they read as the agent's input
310
+ * rather than as a problem with the file.
311
+ */
312
+ private editedName(tool: string, field: 'visible' | 'description', input: unknown, available: ToolDefinition[]): string {
313
+ const usage = field === 'visible'
314
+ ? `set_tool_visibility takes {"name": a tool's exact name, "visible": true or false}.`
315
+ : `set_tool_description takes {"name": a tool's exact name, "description": the new text, or null to restore the default}.`;
316
+ if (!input || typeof input !== 'object' || Array.isArray(input)) throw new PresentationRefusal(`Nothing was changed: the arguments were ${shown(input)}, not an object. ${usage}`);
317
+ const args = input as Record<string, unknown>, problems: string[] = [];
318
+ if (!Object.hasOwn(args, 'name')) problems.push('"name" is missing');
319
+ else if (typeof args.name !== 'string') problems.push(`"name" is ${shown(args.name)}, not a string`);
320
+ if (!Object.hasOwn(args, field)) problems.push(`"${field}" is missing`);
321
+ else if (field === 'visible' ? typeof args.visible !== 'boolean' : args.description !== null && typeof args.description !== 'string')
322
+ problems.push(`"${field}" is ${shown(args[field])}, not ${field === 'visible' ? 'true or false' : 'a string or null'}`);
323
+ const extra = Object.keys(args).filter((key) => key !== 'name' && key !== field);
324
+ if (extra.length) problems.push(`${quotedList(extra)} ${extra.length > 1 ? "aren't arguments" : "isn't an argument"} of ${tool}`);
325
+ if (problems.length) throw new PresentationRefusal(`Nothing was changed: ${problems.join('; ')}. ${usage}`);
326
+ const name = args.name as string;
327
+ if (!available.some((t) => t.name === name)) {
328
+ const near = closestNames(name, available.map((t) => t.name));
329
+ throw new PresentationRefusal(`Nothing was changed: no tool named ${quoted(name)} is available to you.${near.length ? ` Did you mean ${quotedList(near, 'or', JSON.stringify)}?` : ''}`
330
+ + ` Copy the exact name from your tool catalogue's index, workspace--read {"path":${JSON.stringify(this.config.cataloguePath)},"limit":140}, reading on with "offset" if the index runs past that.`);
331
+ }
332
+ if (field === 'description' && typeof args.description === 'string' && characters(args.description) > MAX_DESCRIPTION_CHARS)
333
+ throw new PresentationRefusal(`Nothing was changed: the description is ${count(characters(args.description))} characters, over the ${count(MAX_DESCRIPTION_CHARS)} allowed. Shorten it and call set_tool_description again.`);
334
+ if (field === 'visible' && args.visible === false && protectedNames.has(name))
335
+ throw new PresentationRefusal(`Nothing was changed: ${name} can't be hidden, since workspace--read, set_tool_visibility and set_tool_description are how you read the catalogue and undo these changes. Calling this again won't change that.`);
336
+ return name;
147
337
  }
148
338
  }
149
339
  export function renderCatalogue(snapshot: PresentationSnapshot): string {
@@ -164,7 +354,8 @@ export function renderCatalogue(snapshot: PresentationSnapshot): string {
164
354
  `Read details: workspace--read {"path":${JSON.stringify(snapshot.cataloguePath)},"offset":LINE,"limit":LINES}.`,
165
355
  'Line references below belong to this revision; reread the index after changes.', '',
166
356
  ];
167
- for (const diagnostic of snapshot.diagnostics) lines.push('Diagnostic: '+diagnostic);
357
+ // One line each: a quoted parse error can hold the file's own line breaks.
358
+ for (const diagnostic of snapshot.diagnostics) lines.push('Diagnostic: '+diagnostic.replace(/\r\n|\r|\n/g, '\\n'));
168
359
  lines.push('## Index by source', '');
169
360
  const index = new Map<string, number>();
170
361
  for (const [source, entries] of groups) {