@animalabs/agent-framework 0.27.0 → 0.29.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 (344) hide show
  1. package/README.md +145 -41
  2. package/dist/src/agent.d.ts +29 -2
  3. package/dist/src/agent.d.ts.map +1 -1
  4. package/dist/src/agent.js +73 -12
  5. package/dist/src/agent.js.map +1 -1
  6. package/dist/src/api/mcp-server-core.d.ts.map +1 -1
  7. package/dist/src/api/mcp-server-core.js +3 -12
  8. package/dist/src/api/mcp-server-core.js.map +1 -1
  9. package/dist/src/api/server.d.ts.map +1 -1
  10. package/dist/src/api/server.js +11 -5
  11. package/dist/src/api/server.js.map +1 -1
  12. package/dist/src/auto-continue.d.ts +5 -2
  13. package/dist/src/auto-continue.d.ts.map +1 -1
  14. package/dist/src/auto-continue.js +9 -5
  15. package/dist/src/auto-continue.js.map +1 -1
  16. package/dist/src/code-execution/isolate/runner.d.ts +7 -5
  17. package/dist/src/code-execution/isolate/runner.d.ts.map +1 -1
  18. package/dist/src/code-execution/isolate/runner.js +7 -5
  19. package/dist/src/code-execution/isolate/runner.js.map +1 -1
  20. package/dist/src/code-execution/isolate/scripts.d.ts.map +1 -1
  21. package/dist/src/code-execution/isolate/scripts.js +3 -2
  22. package/dist/src/code-execution/isolate/scripts.js.map +1 -1
  23. package/dist/src/cut-off-round.d.ts +24 -0
  24. package/dist/src/cut-off-round.d.ts.map +1 -0
  25. package/dist/src/cut-off-round.js +87 -0
  26. package/dist/src/cut-off-round.js.map +1 -0
  27. package/dist/src/framework.d.ts +468 -125
  28. package/dist/src/framework.d.ts.map +1 -1
  29. package/dist/src/framework.js +3651 -1111
  30. package/dist/src/framework.js.map +1 -1
  31. package/dist/src/gate/event-gate.d.ts +133 -13
  32. package/dist/src/gate/event-gate.d.ts.map +1 -1
  33. package/dist/src/gate/event-gate.js +654 -59
  34. package/dist/src/gate/event-gate.js.map +1 -1
  35. package/dist/src/gate/index.d.ts +3 -2
  36. package/dist/src/gate/index.d.ts.map +1 -1
  37. package/dist/src/gate/index.js +2 -1
  38. package/dist/src/gate/index.js.map +1 -1
  39. package/dist/src/gate/reply-judge.d.ts +116 -0
  40. package/dist/src/gate/reply-judge.d.ts.map +1 -0
  41. package/dist/src/gate/reply-judge.js +467 -0
  42. package/dist/src/gate/reply-judge.js.map +1 -0
  43. package/dist/src/gate/types.d.ts +173 -2
  44. package/dist/src/gate/types.d.ts.map +1 -1
  45. package/dist/src/heartbeat/heartbeat.d.ts +202 -0
  46. package/dist/src/heartbeat/heartbeat.d.ts.map +1 -0
  47. package/dist/src/heartbeat/heartbeat.js +778 -0
  48. package/dist/src/heartbeat/heartbeat.js.map +1 -0
  49. package/dist/src/heartbeat/reminder-time.d.ts +5 -0
  50. package/dist/src/heartbeat/reminder-time.d.ts.map +1 -0
  51. package/dist/src/heartbeat/reminder-time.js +107 -0
  52. package/dist/src/heartbeat/reminder-time.js.map +1 -0
  53. package/dist/src/held-writes.d.ts +3 -3
  54. package/dist/src/held-writes.js +3 -3
  55. package/dist/src/host-presentation.d.ts +170 -0
  56. package/dist/src/host-presentation.d.ts.map +1 -0
  57. package/dist/src/host-presentation.js +561 -0
  58. package/dist/src/host-presentation.js.map +1 -0
  59. package/dist/src/index.d.ts +5 -1
  60. package/dist/src/index.d.ts.map +1 -1
  61. package/dist/src/index.js +3 -1
  62. package/dist/src/index.js.map +1 -1
  63. package/dist/src/line-reader.d.ts +4 -0
  64. package/dist/src/line-reader.d.ts.map +1 -0
  65. package/dist/src/line-reader.js +59 -0
  66. package/dist/src/line-reader.js.map +1 -0
  67. package/dist/src/mcpl/capability-mask.d.ts.map +1 -1
  68. package/dist/src/mcpl/capability-mask.js +3 -2
  69. package/dist/src/mcpl/capability-mask.js.map +1 -1
  70. package/dist/src/mcpl/channel-registry.d.ts +34 -6
  71. package/dist/src/mcpl/channel-registry.d.ts.map +1 -1
  72. package/dist/src/mcpl/channel-registry.js +133 -54
  73. package/dist/src/mcpl/channel-registry.js.map +1 -1
  74. package/dist/src/mcpl/conversation-router.d.ts.map +1 -1
  75. package/dist/src/mcpl/conversation-router.js +2 -1
  76. package/dist/src/mcpl/conversation-router.js.map +1 -1
  77. package/dist/src/mcpl/convert-block.d.ts +1 -0
  78. package/dist/src/mcpl/convert-block.d.ts.map +1 -1
  79. package/dist/src/mcpl/convert-block.js +16 -4
  80. package/dist/src/mcpl/convert-block.js.map +1 -1
  81. package/dist/src/mcpl/hook-orchestrator.d.ts.map +1 -1
  82. package/dist/src/mcpl/hook-orchestrator.js +4 -3
  83. package/dist/src/mcpl/hook-orchestrator.js.map +1 -1
  84. package/dist/src/mcpl/inbound-source.d.ts +29 -11
  85. package/dist/src/mcpl/inbound-source.d.ts.map +1 -1
  86. package/dist/src/mcpl/inbound-source.js +43 -70
  87. package/dist/src/mcpl/inbound-source.js.map +1 -1
  88. package/dist/src/mcpl/modern-connection.d.ts.map +1 -1
  89. package/dist/src/mcpl/modern-connection.js +11 -7
  90. package/dist/src/mcpl/modern-connection.js.map +1 -1
  91. package/dist/src/mcpl/protocol-family.d.ts +3 -2
  92. package/dist/src/mcpl/protocol-family.d.ts.map +1 -1
  93. package/dist/src/mcpl/protocol-family.js +25 -3
  94. package/dist/src/mcpl/protocol-family.js.map +1 -1
  95. package/dist/src/mcpl/push-handler.js +2 -2
  96. package/dist/src/mcpl/push-handler.js.map +1 -1
  97. package/dist/src/mcpl/references.d.ts +12 -40
  98. package/dist/src/mcpl/references.d.ts.map +1 -1
  99. package/dist/src/mcpl/references.js +29 -23
  100. package/dist/src/mcpl/references.js.map +1 -1
  101. package/dist/src/mcpl/server-connection.d.ts +18 -8
  102. package/dist/src/mcpl/server-connection.d.ts.map +1 -1
  103. package/dist/src/mcpl/server-connection.js +70 -30
  104. package/dist/src/mcpl/server-connection.js.map +1 -1
  105. package/dist/src/mcpl/skip-reply-wake.d.ts +25 -0
  106. package/dist/src/mcpl/skip-reply-wake.d.ts.map +1 -1
  107. package/dist/src/mcpl/skip-reply-wake.js +25 -0
  108. package/dist/src/mcpl/skip-reply-wake.js.map +1 -1
  109. package/dist/src/mcpl/tags.d.ts +9 -2
  110. package/dist/src/mcpl/tags.d.ts.map +1 -1
  111. package/dist/src/mcpl/tags.js +12 -2
  112. package/dist/src/mcpl/tags.js.map +1 -1
  113. package/dist/src/mcpl/tool-presence.d.ts +66 -14
  114. package/dist/src/mcpl/tool-presence.d.ts.map +1 -1
  115. package/dist/src/mcpl/tool-presence.js +150 -80
  116. package/dist/src/mcpl/tool-presence.js.map +1 -1
  117. package/dist/src/mcpl/tool-signature.d.ts +10 -3
  118. package/dist/src/mcpl/tool-signature.d.ts.map +1 -1
  119. package/dist/src/mcpl/tool-signature.js +60 -30
  120. package/dist/src/mcpl/tool-signature.js.map +1 -1
  121. package/dist/src/mcpl/toolset-host.d.ts +88 -55
  122. package/dist/src/mcpl/toolset-host.d.ts.map +1 -1
  123. package/dist/src/mcpl/toolset-host.js +220 -111
  124. package/dist/src/mcpl/toolset-host.js.map +1 -1
  125. package/dist/src/mcpl/toolsets-module.d.ts +27 -35
  126. package/dist/src/mcpl/toolsets-module.d.ts.map +1 -1
  127. package/dist/src/mcpl/toolsets-module.js +313 -91
  128. package/dist/src/mcpl/toolsets-module.js.map +1 -1
  129. package/dist/src/mcpl/transport.d.ts +1 -1
  130. package/dist/src/mcpl/transport.d.ts.map +1 -1
  131. package/dist/src/mcpl/transport.js +16 -16
  132. package/dist/src/mcpl/transport.js.map +1 -1
  133. package/dist/src/mcpl/types.d.ts +31 -13
  134. package/dist/src/mcpl/types.d.ts.map +1 -1
  135. package/dist/src/mcpl/types.js.map +1 -1
  136. package/dist/src/module-registry.d.ts +10 -8
  137. package/dist/src/module-registry.d.ts.map +1 -1
  138. package/dist/src/module-registry.js +15 -9
  139. package/dist/src/module-registry.js.map +1 -1
  140. package/dist/src/modules/api/index.d.ts.map +1 -1
  141. package/dist/src/modules/api/index.js +4 -2
  142. package/dist/src/modules/api/index.js.map +1 -1
  143. package/dist/src/modules/discord/index.d.ts.map +1 -1
  144. package/dist/src/modules/discord/index.js +33 -25
  145. package/dist/src/modules/discord/index.js.map +1 -1
  146. package/dist/src/modules/history/index.d.ts.map +1 -1
  147. package/dist/src/modules/history/index.js +30 -17
  148. package/dist/src/modules/history/index.js.map +1 -1
  149. package/dist/src/modules/sender-name.d.ts +7 -0
  150. package/dist/src/modules/sender-name.d.ts.map +1 -0
  151. package/dist/src/modules/sender-name.js +10 -0
  152. package/dist/src/modules/sender-name.js.map +1 -0
  153. package/dist/src/modules/workspace/answers.d.ts +26 -0
  154. package/dist/src/modules/workspace/answers.d.ts.map +1 -0
  155. package/dist/src/modules/workspace/answers.js +138 -0
  156. package/dist/src/modules/workspace/answers.js.map +1 -0
  157. package/dist/src/modules/workspace/branch-intent.d.ts +5 -3
  158. package/dist/src/modules/workspace/branch-intent.d.ts.map +1 -1
  159. package/dist/src/modules/workspace/branch-intent.js +6 -2
  160. package/dist/src/modules/workspace/branch-intent.js.map +1 -1
  161. package/dist/src/modules/workspace/direct-write.d.ts +3 -0
  162. package/dist/src/modules/workspace/direct-write.d.ts.map +1 -1
  163. package/dist/src/modules/workspace/direct-write.js +59 -24
  164. package/dist/src/modules/workspace/direct-write.js.map +1 -1
  165. package/dist/src/modules/workspace/disk-agreement.d.ts +33 -11
  166. package/dist/src/modules/workspace/disk-agreement.d.ts.map +1 -1
  167. package/dist/src/modules/workspace/disk-agreement.js +48 -17
  168. package/dist/src/modules/workspace/disk-agreement.js.map +1 -1
  169. package/dist/src/modules/workspace/edit-text.d.ts +2 -1
  170. package/dist/src/modules/workspace/edit-text.d.ts.map +1 -1
  171. package/dist/src/modules/workspace/edit-text.js +4 -2
  172. package/dist/src/modules/workspace/edit-text.js.map +1 -1
  173. package/dist/src/modules/workspace/effects.d.ts +4 -2
  174. package/dist/src/modules/workspace/effects.d.ts.map +1 -1
  175. package/dist/src/modules/workspace/effects.js +67 -50
  176. package/dist/src/modules/workspace/effects.js.map +1 -1
  177. package/dist/src/modules/workspace/index.d.ts +63 -51
  178. package/dist/src/modules/workspace/index.d.ts.map +1 -1
  179. package/dist/src/modules/workspace/index.js +980 -547
  180. package/dist/src/modules/workspace/index.js.map +1 -1
  181. package/dist/src/modules/workspace/observe.d.ts +125 -82
  182. package/dist/src/modules/workspace/observe.d.ts.map +1 -1
  183. package/dist/src/modules/workspace/observe.js +465 -241
  184. package/dist/src/modules/workspace/observe.js.map +1 -1
  185. package/dist/src/modules/workspace/read-page.d.ts.map +1 -1
  186. package/dist/src/modules/workspace/read-page.js +7 -1
  187. package/dist/src/modules/workspace/read-page.js.map +1 -1
  188. package/dist/src/modules/workspace/reconcile.d.ts +7 -1
  189. package/dist/src/modules/workspace/reconcile.d.ts.map +1 -1
  190. package/dist/src/modules/workspace/reconcile.js +156 -50
  191. package/dist/src/modules/workspace/reconcile.js.map +1 -1
  192. package/dist/src/modules/workspace/result-text.d.ts +1 -0
  193. package/dist/src/modules/workspace/result-text.d.ts.map +1 -1
  194. package/dist/src/modules/workspace/result-text.js.map +1 -1
  195. package/dist/src/modules/workspace/sync.d.ts +9 -0
  196. package/dist/src/modules/workspace/sync.d.ts.map +1 -1
  197. package/dist/src/modules/workspace/sync.js +14 -0
  198. package/dist/src/modules/workspace/sync.js.map +1 -1
  199. package/dist/src/modules/workspace/types.d.ts +96 -43
  200. package/dist/src/modules/workspace/types.d.ts.map +1 -1
  201. package/dist/src/modules/workspace/types.js.map +1 -1
  202. package/dist/src/modules/workspace/watcher.d.ts.map +1 -1
  203. package/dist/src/modules/workspace/watcher.js +8 -3
  204. package/dist/src/modules/workspace/watcher.js.map +1 -1
  205. package/dist/src/notice-tags.d.ts +79 -0
  206. package/dist/src/notice-tags.d.ts.map +1 -0
  207. package/dist/src/notice-tags.js +83 -0
  208. package/dist/src/notice-tags.js.map +1 -0
  209. package/dist/src/prose-drafts.d.ts +4 -3
  210. package/dist/src/prose-drafts.d.ts.map +1 -1
  211. package/dist/src/prose-drafts.js +3 -2
  212. package/dist/src/prose-drafts.js.map +1 -1
  213. package/dist/src/reasoning-loss-notice.d.ts +23 -0
  214. package/dist/src/reasoning-loss-notice.d.ts.map +1 -0
  215. package/dist/src/reasoning-loss-notice.js +52 -0
  216. package/dist/src/reasoning-loss-notice.js.map +1 -0
  217. package/dist/src/reasoning-loss.d.ts +24 -0
  218. package/dist/src/reasoning-loss.d.ts.map +1 -0
  219. package/dist/src/reasoning-loss.js +102 -0
  220. package/dist/src/reasoning-loss.js.map +1 -0
  221. package/dist/src/send-tools.d.ts +3 -2
  222. package/dist/src/send-tools.d.ts.map +1 -1
  223. package/dist/src/send-tools.js +3 -2
  224. package/dist/src/send-tools.js.map +1 -1
  225. package/dist/src/sent-rows.js +1 -1
  226. package/dist/src/silent-heartbeat.d.ts +1 -53
  227. package/dist/src/silent-heartbeat.d.ts.map +1 -1
  228. package/dist/src/silent-heartbeat.js +56 -3
  229. package/dist/src/silent-heartbeat.js.map +1 -1
  230. package/dist/src/supplied-text.d.ts +35 -0
  231. package/dist/src/supplied-text.d.ts.map +1 -0
  232. package/dist/src/supplied-text.js +141 -0
  233. package/dist/src/supplied-text.js.map +1 -0
  234. package/dist/src/thinking-drops.d.ts +4 -11
  235. package/dist/src/thinking-drops.d.ts.map +1 -1
  236. package/dist/src/thinking-drops.js +7 -14
  237. package/dist/src/thinking-drops.js.map +1 -1
  238. package/dist/src/tool-args.d.ts +12 -0
  239. package/dist/src/tool-args.d.ts.map +1 -1
  240. package/dist/src/tool-args.js +39 -4
  241. package/dist/src/tool-args.js.map +1 -1
  242. package/dist/src/tool-image-ledger.d.ts.map +1 -1
  243. package/dist/src/tool-image-ledger.js +2 -1
  244. package/dist/src/tool-image-ledger.js.map +1 -1
  245. package/dist/src/tool-presentation.d.ts.map +1 -1
  246. package/dist/src/tool-presentation.js +5 -4
  247. package/dist/src/tool-presentation.js.map +1 -1
  248. package/dist/src/tool-result-guard.d.ts +8 -4
  249. package/dist/src/tool-result-guard.d.ts.map +1 -1
  250. package/dist/src/tool-result-guard.js +23 -11
  251. package/dist/src/tool-result-guard.js.map +1 -1
  252. package/dist/src/tune-out/coordinator.d.ts +3 -2
  253. package/dist/src/tune-out/coordinator.d.ts.map +1 -1
  254. package/dist/src/tune-out/coordinator.js +24 -26
  255. package/dist/src/tune-out/coordinator.js.map +1 -1
  256. package/dist/src/tune-out/tools.d.ts +4 -1
  257. package/dist/src/tune-out/tools.d.ts.map +1 -1
  258. package/dist/src/types/agent.d.ts +63 -18
  259. package/dist/src/types/agent.d.ts.map +1 -1
  260. package/dist/src/types/events.d.ts +18 -8
  261. package/dist/src/types/events.d.ts.map +1 -1
  262. package/dist/src/types/framework.d.ts +58 -0
  263. package/dist/src/types/framework.d.ts.map +1 -1
  264. package/dist/src/types/module.d.ts +27 -13
  265. package/dist/src/types/module.d.ts.map +1 -1
  266. package/dist/src/types/trace.d.ts +34 -1
  267. package/dist/src/types/trace.d.ts.map +1 -1
  268. package/package.json +3 -3
  269. package/src/agent.ts +76 -12
  270. package/src/api/mcp-server-core.ts +3 -14
  271. package/src/api/server.ts +11 -5
  272. package/src/auto-continue.ts +12 -5
  273. package/src/code-execution/isolate/runner.ts +7 -5
  274. package/src/code-execution/isolate/scripts.ts +3 -2
  275. package/src/cut-off-round.ts +98 -0
  276. package/src/framework.ts +3772 -1138
  277. package/src/gate/event-gate.ts +705 -60
  278. package/src/gate/index.ts +9 -1
  279. package/src/gate/reply-judge.ts +512 -0
  280. package/src/gate/types.ts +176 -3
  281. package/src/heartbeat/heartbeat.ts +843 -0
  282. package/src/heartbeat/reminder-time.ts +107 -0
  283. package/src/held-writes.ts +3 -3
  284. package/src/host-presentation.ts +605 -0
  285. package/src/index.ts +5 -1
  286. package/src/line-reader.ts +58 -0
  287. package/src/mcpl/capability-mask.ts +3 -2
  288. package/src/mcpl/channel-registry.ts +139 -53
  289. package/src/mcpl/conversation-router.ts +2 -1
  290. package/src/mcpl/convert-block.ts +17 -4
  291. package/src/mcpl/hook-orchestrator.ts +4 -3
  292. package/src/mcpl/inbound-source.ts +45 -70
  293. package/src/mcpl/modern-connection.ts +11 -7
  294. package/src/mcpl/protocol-family.ts +24 -3
  295. package/src/mcpl/push-handler.ts +2 -2
  296. package/src/mcpl/references.ts +31 -23
  297. package/src/mcpl/server-connection.ts +76 -34
  298. package/src/mcpl/skip-reply-wake.ts +35 -0
  299. package/src/mcpl/tags.ts +13 -2
  300. package/src/mcpl/tool-presence.ts +149 -82
  301. package/src/mcpl/tool-signature.ts +64 -32
  302. package/src/mcpl/toolset-host.ts +212 -110
  303. package/src/mcpl/toolsets-module.ts +277 -91
  304. package/src/mcpl/transport.ts +18 -14
  305. package/src/mcpl/types.ts +32 -13
  306. package/src/module-registry.ts +14 -9
  307. package/src/modules/api/index.ts +4 -2
  308. package/src/modules/discord/index.ts +37 -25
  309. package/src/modules/history/index.ts +30 -18
  310. package/src/modules/sender-name.ts +9 -0
  311. package/src/modules/workspace/answers.ts +151 -0
  312. package/src/modules/workspace/branch-intent.ts +10 -5
  313. package/src/modules/workspace/direct-write.ts +59 -23
  314. package/src/modules/workspace/disk-agreement.ts +52 -21
  315. package/src/modules/workspace/edit-text.ts +7 -5
  316. package/src/modules/workspace/effects.ts +69 -50
  317. package/src/modules/workspace/index.ts +966 -556
  318. package/src/modules/workspace/observe.ts +497 -242
  319. package/src/modules/workspace/read-page.ts +7 -1
  320. package/src/modules/workspace/reconcile.ts +184 -49
  321. package/src/modules/workspace/result-text.ts +2 -0
  322. package/src/modules/workspace/sync.ts +16 -0
  323. package/src/modules/workspace/types.ts +96 -43
  324. package/src/modules/workspace/watcher.ts +8 -3
  325. package/src/notice-tags.ts +84 -0
  326. package/src/prose-drafts.ts +4 -3
  327. package/src/reasoning-loss-notice.ts +64 -0
  328. package/src/reasoning-loss.ts +120 -0
  329. package/src/send-tools.ts +3 -2
  330. package/src/sent-rows.ts +1 -1
  331. package/src/silent-heartbeat.ts +4 -3
  332. package/src/supplied-text.ts +154 -0
  333. package/src/thinking-drops.ts +10 -16
  334. package/src/tool-args.ts +38 -4
  335. package/src/tool-image-ledger.ts +2 -1
  336. package/src/tool-presentation.ts +5 -4
  337. package/src/tool-result-guard.ts +26 -11
  338. package/src/tune-out/coordinator.ts +25 -27
  339. package/src/tune-out/tools.ts +4 -1
  340. package/src/types/agent.ts +63 -18
  341. package/src/types/events.ts +18 -8
  342. package/src/types/framework.ts +59 -0
  343. package/src/types/module.ts +28 -13
  344. package/src/types/trace.ts +36 -1
@@ -12,7 +12,9 @@
12
12
  * - Expose synthesized tools: channel_list, channel_open, channel_close, channel_publish
13
13
  * - Build channel context for beforeInference params
14
14
  */
15
- import { convertBlock } from './convert-block.js';
15
+ import { NOTICE_TAG } from '../notice-tags.js';
16
+ import { convertBlocks } from './convert-block.js';
17
+ import { cutToFit, markedText, markNoticeOpenings, nameToTypeBack, quotedValue, showsAsItself, suppliedValue } from '../supplied-text.js';
16
18
  import { isDeepStrictEqual } from 'node:util';
17
19
  import { ensureStateRegistered } from '../module-registry.js';
18
20
  import { expandCoreTags, isMarkerTagged } from './tags.js';
@@ -22,7 +24,7 @@ import { logDetail, logValue } from './log-value.js';
22
24
  import { RefusalLines } from './refusal-lines.js';
23
25
  import { CapabilityGrant } from './capability-grant.js';
24
26
  import { McplRequestError } from './server-connection.js';
25
- import { readSkipReplyWake } from './skip-reply-wake.js';
27
+ import { readSkipReplyWake, skipReplyNote } from './skip-reply-wake.js';
26
28
  import { isProseTargetToken } from './prose-grammar.js';
27
29
  // ============================================================================
28
30
  // Typing indicator interval (Discord typing lasts ~10s, so 7s keeps it alive)
@@ -410,20 +412,22 @@ const CHANNEL_TOOL_DEFINITIONS = [
410
412
  // ============================================================================
411
413
  // Constructor Options
412
414
  // ============================================================================
413
- /** Bound connector values for notices, logs and an outcome's reason. A
414
- * PublishOutcome keeps the connector's structured data (`detail`) as the
415
- * connection gives it, its strings redacted (redactedData). */
415
+ /** Bound connector values for notices, logs and an outcome's reason, on one
416
+ * line with their notice openings marked (suppliedValue). A PublishOutcome
417
+ * keeps the connector's structured data (`detail`) as the connection gives
418
+ * it, its strings redacted (redactedData). */
416
419
  export function connectorText(value) {
417
420
  let text;
418
421
  try {
419
422
  text = typeof value === 'string' ? value : JSON.stringify(value) ?? String(value);
420
423
  }
421
424
  catch {
422
- return '[unserializable connector value]';
425
+ return `[${NOTICE_TAG.unserializableConnectorValue}]`;
423
426
  }
424
427
  const limit = 2000;
425
- const suffix = '… [truncated]';
426
- return text.length > limit ? text.slice(0, limit - suffix.length) + suffix : text;
428
+ const suffix = `… [${NOTICE_TAG.truncated}]`;
429
+ const shown = suppliedValue(text);
430
+ return shown.length > limit ? cutToFit(shown, limit - suffix.length) + suffix : shown;
427
431
  }
428
432
  /** One key per channel, its server and id: unlike joining the two with a
429
433
  * separator, no two channels share one, whatever their ids hold. */
@@ -437,6 +441,8 @@ export function sameChannel(a, b) {
437
441
  return !a && !b;
438
442
  return a.serverId === b.serverId && a.channelId === b.channelId;
439
443
  }
444
+ export const NO_CHANNEL_EXAMPLE = '#<channel>';
445
+ export const NO_PERSON_EXAMPLE = '@<person>';
440
446
  /**
441
447
  * A channel's server-qualified name, `serverId:channelId`. A name given as a
442
448
  * string (a tool's channelId, a `>>` target, a host's call) may take this
@@ -447,11 +453,32 @@ export function sameChannel(a, b) {
447
453
  export function qualifiedChannelName(ref) {
448
454
  return `${ref.serverId}:${ref.channelId}`;
449
455
  }
456
+ function markedHistory(history) {
457
+ return history.map((item) => {
458
+ if (item === null || typeof item !== 'object' || Array.isArray(item) || !('content' in item))
459
+ return item;
460
+ const { content } = item;
461
+ if (Array.isArray(content))
462
+ return { ...item, content: markNoticeOpenings(content.map(withEmbeddedTextMarked)) };
463
+ return typeof content === 'string' ? { ...item, content: markedText(content) } : item;
464
+ });
465
+ }
466
+ function withEmbeddedTextMarked(block) {
467
+ if (block === null || typeof block !== 'object' || block.type !== 'resource')
468
+ return block;
469
+ const { resource } = block;
470
+ if (resource === null || typeof resource !== 'object' || typeof resource.text !== 'string')
471
+ return block;
472
+ return { ...block, resource: { ...resource, text: markedText(resource.text) } };
473
+ }
450
474
  /** A channel told apart by its id and its server, for one no string picks
451
- * alone: `"b:room" on server "a"`. No input takes it for a name. */
475
+ * alone or whose name wouldn't show as itself: `"b:room" on server "a"`,
476
+ * each a JSON literal a channel tool's channelId and serverId take back
477
+ * (quotedValue). No input takes the whole form for a name. */
452
478
  function channelOnServer(ref) {
453
- return `${JSON.stringify(ref.channelId)} on server ${JSON.stringify(ref.serverId)}`;
479
+ return `${quotedValue(ref.channelId)} on server ${quotedValue(ref.serverId)}`;
454
480
  }
481
+ const CHANNEL_ON_SERVER_AT_END = /("(?:[^"\\]|\\.)*") on server ("(?:[^"\\]|\\.)*")$/;
455
482
  /**
456
483
  * A failed request's words, bounded, for a reason that a caller composes.
457
484
  * This host's own words, for a request that wasn't sent or wasn't answered
@@ -1328,7 +1355,7 @@ export class ChannelRegistry {
1328
1355
  }
1329
1356
  if (message.tags)
1330
1357
  message.tags = expandCoreTags(message.tags);
1331
- const convertedContent = message.content.map((block) => convertBlock(block, 'attachment on channel message', serverId));
1358
+ const convertedContent = convertBlocks(message.content, 'attachment on channel message', serverId);
1332
1359
  if (!emptyAllowed && isVisiblyEmptyConversion(message.content, convertedContent)) {
1333
1360
  rejectEmpty();
1334
1361
  continue;
@@ -1342,7 +1369,8 @@ export class ChannelRegistry {
1342
1369
  const incomingEntry = this.channels.get(incomingKey);
1343
1370
  const markAccepted = (firstView = false) => {
1344
1371
  // Non-conversational markers (a reaction added or removed, an edit, a
1345
- // deletion) are ABOUT a message, not one the agent replies to: they
1372
+ // deletion, and a chat:system notice such as a join or the weather)
1373
+ // are ABOUT a message or the place, not one the agent replies to: they
1346
1374
  // must not retarget the default publish locus or become
1347
1375
  // `context.incoming`'s reply anchor. An edit the coalescer delivered
1348
1376
  // as the agent's first view counts as the message it replaced.
@@ -1763,7 +1791,7 @@ export class ChannelRegistry {
1763
1791
  case 'journal':
1764
1792
  return this.handleToolJournal(input);
1765
1793
  case 'skip_reply':
1766
- return this.handleToolSkipReply(input);
1794
+ return this.handleToolSkipReply(input, origin?.kind === 'agent' ? origin.earlierWake : undefined);
1767
1795
  default:
1768
1796
  // Not every agent is given every channel tool, so the refusal points
1769
1797
  // to the ones this agent has rather than listing them all.
@@ -1816,7 +1844,8 @@ export class ChannelRegistry {
1816
1844
  // declared it inbound-only, since speech isn't posted there): a conversation
1817
1845
  // fork's home channel, else this turn's channel (single trunk agent — item-3
1818
1846
  // redux: its locus, else its triggering channel), else the global default
1819
- // (heartbeats). Without this, a fork
1847
+ // (a no-trigger turn's, but not a heartbeat's, whose turn takes none).
1848
+ // Without this, a fork
1820
1849
  // was advertised the global locus but published somewhere else; and a trunk
1821
1850
  // agent was told the wrong channel under concurrency.
1822
1851
  // Each lookup is keyed on whether a name was given, not its truthiness:
@@ -3214,13 +3243,20 @@ export class ChannelRegistry {
3214
3243
  * name, only where no registered channel takes that name, as a channel
3215
3244
  * tool reads it or a `>>` target does (by label or raw id too), so the
3216
3245
  * name can't send anything to another channel; else by its id and server.
3246
+ * A name that wouldn't show as itself (showsAsItself: one holding a line
3247
+ * break, a notice opening, a quote, a backslash or a lone surrogate, or
3248
+ * whitespace at its edges) is shown by its id and its server too, which
3249
+ * the channel tools take exactly and the prose resolver doesn't, so no name
3250
+ * shown can be another channel's.
3217
3251
  */
3218
3252
  nameShown(ref) {
3219
3253
  const entry = this.entryAt(ref);
3220
- if (entry)
3221
- return this.nameFor(entry) ?? channelOnServer(ref);
3254
+ if (entry) {
3255
+ const name = this.nameFor(entry);
3256
+ return name !== undefined && showsAsItself(name) ? name : channelOnServer(ref);
3257
+ }
3222
3258
  for (const name of [ref.channelId, qualifiedChannelName(ref)]) {
3223
- if (this.entriesNamed(name).length === 0 && !('channelId' in this.resolveProseTarget(name)))
3259
+ if (showsAsItself(name) && this.entriesNamed(name).length === 0 && !('channelId' in this.resolveProseTarget(name)))
3224
3260
  return name;
3225
3261
  }
3226
3262
  return channelOnServer(ref);
@@ -3257,7 +3293,7 @@ export class ChannelRegistry {
3257
3293
  tuneOutEndText(entry, tool) {
3258
3294
  const close = tool === 'channel_close';
3259
3295
  return this.nameFor(entry) !== undefined
3260
- ? `Call tune_out with channelId ${this.quotedShown(refOf(entry))} and mode "cancel" for it to resume normal ` +
3296
+ ? `Call tune_out with channelId ${quotedValue(this.nameFor(entry))} and mode "cancel" for it to resume normal ` +
3261
3297
  `attention; cancelling delivers the diverted backlog${close ? ', and channel_close closes it after that.' : '.'}`
3262
3298
  : 'No channelId names it alone, so tune_out can\'t cancel it: its tune-out ends by itself when its duration ' +
3263
3299
  'runs out, or at the first wake past its wake budget, and its backlog is delivered then.' +
@@ -3269,7 +3305,7 @@ export class ChannelRegistry {
3269
3305
  */
3270
3306
  quotedShown(ref) {
3271
3307
  const shown = this.nameShown(ref);
3272
- return shown === channelOnServer(ref) ? shown : JSON.stringify(shown);
3308
+ return shown === channelOnServer(ref) ? shown : quotedValue(shown);
3273
3309
  }
3274
3310
  /**
3275
3311
  * The string that names exactly this entry by entriesNamed: its id when no
@@ -3302,7 +3338,7 @@ export class ChannelRegistry {
3302
3338
  const nothing = opts.nothing ?? 'nothing ran';
3303
3339
  const names = entries.map((e) => this.nameFor(e));
3304
3340
  if (names.every((n) => n !== undefined)) {
3305
- const listed = names.map((n) => JSON.stringify(n)).join(', ');
3341
+ const listed = names.map((n) => quotedValue(n)).join(', ');
3306
3342
  const servers = [...new Set(entries.map((e) => JSON.stringify(e.serverId)))];
3307
3343
  // One server's two channels can answer to one name too, as `s`'s
3308
3344
  // `s:room` and `room` both do to `s:room`; its server picks neither.
@@ -3324,8 +3360,8 @@ export class ChannelRegistry {
3324
3360
  if (own === undefined && !opts.takesServerId)
3325
3361
  return `- ${where}: no channelId reaches it alone.`;
3326
3362
  return own !== undefined
3327
- ? `- ${where}: call again with channelId ${JSON.stringify(own)}.`
3328
- : `- ${where}: call again with channelId ${JSON.stringify(e.descriptor.id)} and serverId ${JSON.stringify(e.serverId)}.`;
3363
+ ? `- ${where}: call again with channelId ${quotedValue(own)}.`
3364
+ : `- ${where}: call again with channelId ${quotedValue(e.descriptor.id)} and serverId ${JSON.stringify(e.serverId)}.`;
3329
3365
  });
3330
3366
  const count = entries.length === 2 ? 'either of two channels' : `any of ${entries.length} channels`;
3331
3367
  return `Channel ${JSON.stringify(name)} could mean ${count}, so ${nothing}:\n${lines.join('\n')}`;
@@ -3363,7 +3399,7 @@ export class ChannelRegistry {
3363
3399
  if (!alone)
3364
3400
  return 'channel_list shows the channels and their servers.';
3365
3401
  const one = named[0];
3366
- const names = `${JSON.stringify(channelId)} alone names channel ${JSON.stringify(one.descriptor.id)} on server `
3402
+ const names = `${JSON.stringify(channelId)} alone names channel ${quotedValue(one.descriptor.id)} on server `
3367
3403
  + JSON.stringify(one.serverId);
3368
3404
  return takesServerId ? `${names}: for that one, call again with serverId left out.` : `${names}.`;
3369
3405
  }
@@ -3375,7 +3411,7 @@ export class ChannelRegistry {
3375
3411
  const places = elsewhere.map((e) => {
3376
3412
  const at = `on server ${JSON.stringify(e.serverId)}`;
3377
3413
  const name = this.nameFor(e);
3378
- return name === undefined ? `${at} (no channelId reaches it alone)` : `${at} as ${JSON.stringify(name)}`;
3414
+ return name === undefined ? `${at} (no channelId reaches it alone)` : `${at} as ${quotedValue(name)}`;
3379
3415
  });
3380
3416
  return `It's ${places.length === 1 ? places[0] : `${places.slice(0, -1).join(', ')} and ${places.at(-1)}`}.`;
3381
3417
  }
@@ -3638,19 +3674,22 @@ export class ChannelRegistry {
3638
3674
  * before any other spelling (ownChannelNamed).
3639
3675
  */
3640
3676
  resolveProseTarget(spec, opts) {
3641
- const own = this.ownChannelNamed(spec.trim(), opts?.own);
3677
+ const name = spec.trim();
3678
+ if (name === NO_CHANNEL_EXAMPLE || name === NO_PERSON_EXAMPLE)
3679
+ return { error: `${name} is the example's placeholder: write the name it stands for in its place` };
3680
+ const own = this.ownChannelNamed(name, opts?.own);
3642
3681
  let resolved;
3643
3682
  if (own === undefined) {
3644
- resolved = this.resolveTargetByName(spec);
3683
+ resolved = this.resolveTargetByName(name);
3645
3684
  }
3646
3685
  else if ('neither' in own) {
3647
- resolved = { error: `"${spec.trim()}" is the id of this turn's channels on more than one server`, candidates: this.ownCandidates(own.neither).map((c) => c.text) };
3686
+ resolved = { error: `"${name}" is the id of this turn's channels on more than one server`, candidates: this.ownCandidates(own.neither).map((c) => c.prose) };
3648
3687
  }
3649
3688
  else {
3650
3689
  const entry = this.entryAt(own.channel);
3651
3690
  resolved = entry
3652
3691
  ? { channelId: entry.descriptor.id, serverId: entry.serverId, label: entry.descriptor.label }
3653
- : { error: `${this.ownChannelGoneText(spec.trim(), own.channel)}, and nothing can be sent there until that server registers it again` };
3692
+ : { error: `${this.ownChannelGoneText(name, own.channel)}, and nothing can be sent there until that server registers it again` };
3654
3693
  }
3655
3694
  if (!opts?.forSpeech || 'error' in resolved)
3656
3695
  return resolved;
@@ -3703,7 +3742,7 @@ export class ChannelRegistry {
3703
3742
  return undefined;
3704
3743
  if ('neither' in mine) {
3705
3744
  const done = tool === 'publish' ? 'was posted' : tool === 'deliver' ? 'was delivered' : 'ran';
3706
- return { error: this.ownNeitherRefusal(name, mine.neither, done) };
3745
+ return { error: this.ownNeitherRefusal(name, mine.neither, done, false) };
3707
3746
  }
3708
3747
  return this.entryAt(mine.channel) ? { channel: mine.channel } : { error: this.ownChannelGoneRefusal(name, mine.channel, tool) };
3709
3748
  }
@@ -3720,32 +3759,73 @@ export class ChannelRegistry {
3720
3759
  /**
3721
3760
  * The turn's channels a name means neither of (ownChannelNamed), each by a
3722
3761
  * string that reaches it outside the turn's rule: its server-qualified
3723
- * name, where that picks it alone, since its id is the name refused. One
3724
- * no string picks alone, and one its server no longer registers, is named
3725
- * by its id and server, saying so; `reaches` says which a name reaches.
3762
+ * name, where that picks it alone, since its id is the name refused. `text`
3763
+ * is that name, which a refusal writes as JSON; `prose`, which a `>>`
3764
+ * target reads, is that name where it shows as itself, else its id and
3765
+ * server. One no string picks alone, and one its server no longer
3766
+ * registers, are named by id and server in both, saying so. `reaches` says
3767
+ * which a name reaches.
3726
3768
  */
3727
3769
  ownCandidates(channels) {
3728
3770
  return channels.map((c) => {
3729
3771
  const entry = this.entryAt(c);
3730
- if (!entry)
3731
- return { text: `${channelOnServer(c)} (its server no longer registers it)`, reaches: false };
3772
+ if (!entry) {
3773
+ const text = `${channelOnServer(c)} (its server no longer registers it)`;
3774
+ return { text, prose: text, reaches: false, byServer: false };
3775
+ }
3732
3776
  const qualified = qualifiedChannelName(c);
3733
3777
  const picked = this.entriesNamed(qualified);
3734
- return picked.length === 1 && picked[0] === entry
3735
- ? { text: qualified, reaches: true }
3736
- : { text: `${channelOnServer(c)} (no channelId reaches it alone)`, reaches: false };
3778
+ if (picked.length !== 1 || picked[0] !== entry) {
3779
+ const text = `${channelOnServer(c)} (no channelId reaches it alone)`;
3780
+ return { text, prose: text, reaches: false, byServer: true };
3781
+ }
3782
+ return { text: qualified, prose: showsAsItself(qualified) ? qualified : channelOnServer(c), reaches: true, byServer: false };
3737
3783
  });
3738
3784
  }
3785
+ /**
3786
+ * What a refusal listing these candidates says of each one that is a
3787
+ * channel shown by its id and server: the channelId channel_publish reaches
3788
+ * it by, or that no channelId reaches it alone. That is its server-qualified
3789
+ * name where that picks it alone, since a bare id is what a turn's own
3790
+ * channels answer to first, whether or not their server still registers
3791
+ * them (ownChannelNamed), and else its id where that picks it alone and
3792
+ * isn't empty (channel_publish refuses an empty one). It leaves out a channel no
3793
+ * longer registered and a candidate that already says no channelId reaches
3794
+ * it alone, and is empty when nothing is left.
3795
+ */
3796
+ publishRouteFor(candidates) {
3797
+ const parts = new Set();
3798
+ for (const candidate of candidates) {
3799
+ const shown = CHANNEL_ON_SERVER_AT_END.exec(candidate);
3800
+ if (!shown)
3801
+ continue;
3802
+ const ref = { channelId: JSON.parse(shown[1]), serverId: JSON.parse(shown[2]) };
3803
+ const entry = this.entryAt(ref);
3804
+ if (!entry)
3805
+ continue;
3806
+ const name = [qualifiedChannelName(ref), ref.channelId].find((n) => {
3807
+ const named = n === '' ? [] : this.entriesNamed(n);
3808
+ return named.length === 1 && named[0] === entry;
3809
+ });
3810
+ parts.add(name !== undefined
3811
+ ? `channel_publish reaches ${channelOnServer(ref)} with channelId ${quotedValue(name)}`
3812
+ : `no channelId reaches ${channelOnServer(ref)} alone`);
3813
+ }
3814
+ return parts.size ? ` For a channel shown by its id and server: ${[...parts].join('; ')}.` : '';
3815
+ }
3739
3816
  /** A tool's refusal of a name the turn's channels on more than one server
3740
3817
  * answer to by their id (ownChannelNamed's neither). */
3741
- ownNeitherRefusal(name, channels, done) {
3818
+ ownNeitherRefusal(name, channels, done, takesServer = true) {
3742
3819
  const candidates = this.ownCandidates(channels);
3743
- const named = candidates.filter((c) => c.reaches).map((c) => JSON.stringify(c.text));
3820
+ const named = candidates.filter((c) => c.reaches).map((c) => quotedValue(c.text));
3744
3821
  const pick = named.length === candidates.length ? ' Call again with channelId set to one of them.'
3745
3822
  : named.length === 1 ? ` Call again with channelId ${named[0]}.`
3746
3823
  : named.length > 1 ? ` Call again with channelId set to one of ${named.join(', ')}.` : '';
3747
- const listed = candidates.map((c) => (c.reaches ? JSON.stringify(c.text) : c.text)).join(', ');
3748
- return `"${name}" is the id of this turn's channels on more than one server (${listed}), so nothing ${done}.${pick}`;
3824
+ const listed = candidates.map((c) => (c.reaches ? quotedValue(c.text) : c.text)).join(', ');
3825
+ const byServer = takesServer && candidates.some((c) => c.byServer)
3826
+ ? ' For a channel shown by its id and server, call again with that channelId and that serverId.'
3827
+ : '';
3828
+ return `"${name}" is the id of this turn's channels on more than one server (${listed}), so nothing ${done}.${pick}${byServer}`;
3749
3829
  }
3750
3830
  resolveTargetByName(spec) {
3751
3831
  const entries = [...this.channels.values()];
@@ -3756,7 +3836,7 @@ export class ChannelRegistry {
3756
3836
  // A candidate is named by the token that picks it alone (nameFor), so
3757
3837
  // two servers' channels with one id or one label can be told apart, or,
3758
3838
  // where no string picks it alone, by its id and its server.
3759
- const token = (e) => this.nameFor(e) ?? channelOnServer(refOf(e));
3839
+ const token = (e) => this.nameShown(refOf(e));
3760
3840
  // A DM is shown by its label, the person, where that label, given as a
3761
3841
  // target, picks that DM. It doesn't where another channel answers to that
3762
3842
  // label too, as two servers' DMs with one person do (a label is matched
@@ -3773,7 +3853,7 @@ export class ChannelRegistry {
3773
3853
  };
3774
3854
  const dmShown = (list) => list.map((e) => {
3775
3855
  const label = e.descriptor.label ?? e.descriptor.id;
3776
- return labelPicks(e, label) ? label : token(e);
3856
+ return showsAsItself(label) && labelPicks(e, label) ? label : token(e);
3777
3857
  });
3778
3858
  // A channel id, or its server-qualified name (entriesNamed).
3779
3859
  const exact = this.entriesNamed(trimmed);
@@ -3878,7 +3958,7 @@ export class ChannelRegistry {
3878
3958
  if (byName.length > 1) {
3879
3959
  return {
3880
3960
  error: `"${trimmed}" matches several channels`,
3881
- candidates: byName.map((e) => `${e.descriptor.label} = ${token(e)}`),
3961
+ candidates: byName.map((e) => `${nameToTypeBack(e.descriptor.label ?? '')} = ${token(e)}`),
3882
3962
  };
3883
3963
  }
3884
3964
  // No match: offer near-candidates (labels containing the name) so the
@@ -3886,7 +3966,7 @@ export class ChannelRegistry {
3886
3966
  const near = entries
3887
3967
  .filter((e) => norm(e.descriptor.label ?? '').includes(norm(trimmed)))
3888
3968
  .slice(0, 5)
3889
- .map((e) => `${e.descriptor.label} = ${token(e)}`);
3969
+ .map((e) => `${nameToTypeBack(e.descriptor.label ?? '')} = ${token(e)}`);
3890
3970
  return { error: `no channel matches "${trimmed}"`, ...(near.length ? { candidates: near } : {}) };
3891
3971
  }
3892
3972
  /**
@@ -3923,7 +4003,7 @@ export class ChannelRegistry {
3923
4003
  qualifiedChannelName(ref),
3924
4004
  ];
3925
4005
  for (const c of candidates) {
3926
- if (!isProseTargetToken(c) || c === '#')
4006
+ if (!isProseTargetToken(c) || c === '#' || !showsAsItself(c))
3927
4007
  continue;
3928
4008
  const r = this.resolveProseTarget(c, { forSpeech: true });
3929
4009
  if ('channelId' in r && sameChannel(r, ref))
@@ -4191,7 +4271,7 @@ export class ChannelRegistry {
4191
4271
  channelId: input.channelId,
4192
4272
  serverId: entry.serverId,
4193
4273
  status: alreadyDesiredOpen ? 'reconciled' : 'opened',
4194
- ...(result.history ? { history: result.history } : {}),
4274
+ ...(result.history ? { history: markedHistory(result.history) } : {}),
4195
4275
  ...(result.historyTruncated ? { historyTruncated: true } : {}),
4196
4276
  },
4197
4277
  };
@@ -4648,13 +4728,14 @@ export class ChannelRegistry {
4648
4728
  * tool, so any trailing prose this turn is NOT posted. Replaces the old
4649
4729
  * overloaded use of `think` for staying silent.
4650
4730
  */
4651
- handleToolSkipReply(input) {
4731
+ handleToolSkipReply(input, earlierWake) {
4652
4732
  // The self-wake itself is armed by the framework (which owns the
4653
4733
  // EventGate) BEFORE its dispatch reaches this handler, from the same
4654
4734
  // reading, and the framework refuses a wake the host can't set before
4655
4735
  // dispatching. A caller of this registry's handleChannelToolCall
4656
4736
  // (AgentFramework.channels) goes past both, so its note names a wake
4657
- // nothing armed.
4737
+ // nothing armed. The framework, which also owns the heartbeat, says
4738
+ // which of its wakes is due before the self-wake (`earlierWake`).
4658
4739
  const wake = readSkipReplyWake(input);
4659
4740
  const selfWake = wake.kind === 'wake' ? wake.seconds : undefined;
4660
4741
  return {
@@ -4670,9 +4751,7 @@ export class ChannelRegistry {
4670
4751
  // on Fable: ~60% of skip_reply result bytes were verbatim input echo).
4671
4752
  data: {
4672
4753
  skipped: true,
4673
- note: selfWake !== undefined
4674
- ? `Turn ended; nothing sent. Self-wake in ~${selfWake}s unless something wakes you first.`
4675
- : 'Turn ended; nothing sent.',
4754
+ note: skipReplyNote(selfWake, selfWake !== undefined ? earlierWake : undefined),
4676
4755
  },
4677
4756
  };
4678
4757
  }
@@ -5227,7 +5306,7 @@ export class ChannelRegistry {
5227
5306
  else if (own && 'neither' in own) {
5228
5307
  if (seen)
5229
5308
  seen.refusal = 'shared-id';
5230
- return { success: false, error: this.ownNeitherRefusal(input.channelId, own.neither, 'was posted'), isError: true };
5309
+ return { success: false, error: this.ownNeitherRefusal(input.channelId, own.neither, 'was posted', false), isError: true };
5231
5310
  }
5232
5311
  else if (own) {
5233
5312
  entry = this.entryAt(own.channel);
@@ -5264,7 +5343,7 @@ export class ChannelRegistry {
5264
5343
  // channel with its id isn't where its message came from.
5265
5344
  error: input.channelId === undefined
5266
5345
  ? serverGiven
5267
- ? `Server "${input.serverId}" has no channel "${fallback.channelId}", the id of the channel this call would default to, so nothing was posted.`
5346
+ ? `Server "${input.serverId}" has no channel ${quotedValue(fallback.channelId)}, the id of the channel this call would default to, so nothing was posted.`
5268
5347
  : `The channel this would default to, ${this.quotedShown(fallback)}, isn't registered now, so nothing was posted.`
5269
5348
  // This tool's schema has no serverId, so one given here is a host's
5270
5349
  // ref (publishForAgent), or one an agent added unasked, and the