@moltzap/client 2026.528.0 → 2026.717.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 (367) hide show
  1. package/dist/agent-client.d.ts +2 -65
  2. package/dist/agent-client.d.ts.map +1 -1
  3. package/dist/agent-client.js +1 -286
  4. package/dist/agent-client.js.map +1 -1
  5. package/dist/app-client.d.ts +3 -0
  6. package/dist/app-client.d.ts.map +1 -0
  7. package/dist/app-client.js +2 -0
  8. package/dist/app-client.js.map +1 -0
  9. package/dist/auth.d.ts +6 -15
  10. package/dist/auth.d.ts.map +1 -1
  11. package/dist/auth.js +12 -16
  12. package/dist/auth.js.map +1 -1
  13. package/dist/channel-base/format-cross-conv.d.ts +10 -15
  14. package/dist/channel-base/format-cross-conv.d.ts.map +1 -1
  15. package/dist/channel-base/format-cross-conv.js +10 -15
  16. package/dist/channel-base/format-cross-conv.js.map +1 -1
  17. package/dist/channel-base/format-group-block.d.ts +8 -10
  18. package/dist/channel-base/format-group-block.d.ts.map +1 -1
  19. package/dist/channel-base/format-group-block.js +8 -10
  20. package/dist/channel-base/format-group-block.js.map +1 -1
  21. package/dist/channel-base/index.d.ts +3 -62
  22. package/dist/channel-base/index.d.ts.map +1 -1
  23. package/dist/channel-base/index.js +2 -65
  24. package/dist/channel-base/index.js.map +1 -1
  25. package/dist/channel-base/lease-guard.d.ts +0 -2
  26. package/dist/channel-base/lease-guard.d.ts.map +1 -1
  27. package/dist/channel-base/lease-guard.js +0 -2
  28. package/dist/channel-base/lease-guard.js.map +1 -1
  29. package/dist/channel-base/lease-store.d.ts +2 -3
  30. package/dist/channel-base/lease-store.d.ts.map +1 -1
  31. package/dist/channel-base/lease-store.js +2 -3
  32. package/dist/channel-base/lease-store.js.map +1 -1
  33. package/dist/channel-base/lease.d.ts +25 -31
  34. package/dist/channel-base/lease.d.ts.map +1 -1
  35. package/dist/channel-base/lease.js +29 -45
  36. package/dist/channel-base/lease.js.map +1 -1
  37. package/dist/channel-core-enrichment.d.ts +1 -1
  38. package/dist/channel-core-enrichment.d.ts.map +1 -1
  39. package/dist/channel-core-test-support.d.ts +17 -11
  40. package/dist/channel-core-test-support.d.ts.map +1 -1
  41. package/dist/channel-core-test-support.js +5 -6
  42. package/dist/channel-core-test-support.js.map +1 -1
  43. package/dist/channel-core.d.ts +24 -29
  44. package/dist/channel-core.d.ts.map +1 -1
  45. package/dist/channel-core.js +18 -42
  46. package/dist/channel-core.js.map +1 -1
  47. package/dist/cli/commands/agents.d.ts +3 -6
  48. package/dist/cli/commands/agents.d.ts.map +1 -1
  49. package/dist/cli/commands/agents.js +14 -50
  50. package/dist/cli/commands/agents.js.map +1 -1
  51. package/dist/cli/commands/contacts.d.ts +5 -6
  52. package/dist/cli/commands/contacts.d.ts.map +1 -1
  53. package/dist/cli/commands/contacts.js +15 -43
  54. package/dist/cli/commands/contacts.js.map +1 -1
  55. package/dist/cli/commands/conversations.d.ts +8 -18
  56. package/dist/cli/commands/conversations.d.ts.map +1 -1
  57. package/dist/cli/commands/conversations.js +14 -65
  58. package/dist/cli/commands/conversations.js.map +1 -1
  59. package/dist/cli/commands/messages.d.ts +13 -35
  60. package/dist/cli/commands/messages.d.ts.map +1 -1
  61. package/dist/cli/commands/messages.js +21 -46
  62. package/dist/cli/commands/messages.js.map +1 -1
  63. package/dist/cli/commands/register.d.ts +10 -12
  64. package/dist/cli/commands/register.d.ts.map +1 -1
  65. package/dist/cli/commands/register.js +47 -133
  66. package/dist/cli/commands/register.js.map +1 -1
  67. package/dist/cli/commands/send.d.ts +23 -36
  68. package/dist/cli/commands/send.d.ts.map +1 -1
  69. package/dist/cli/commands/send.js +25 -72
  70. package/dist/cli/commands/send.js.map +1 -1
  71. package/dist/cli/commands/start.d.ts +10 -124
  72. package/dist/cli/commands/start.d.ts.map +1 -1
  73. package/dist/cli/commands/start.js +28 -510
  74. package/dist/cli/commands/start.js.map +1 -1
  75. package/dist/cli/commands/status.d.ts +1 -1
  76. package/dist/cli/commands/status.d.ts.map +1 -1
  77. package/dist/cli/commands/status.js +8 -9
  78. package/dist/cli/commands/status.js.map +1 -1
  79. package/dist/cli/commands/test-transport.d.ts +12 -5
  80. package/dist/cli/commands/test-transport.d.ts.map +1 -1
  81. package/dist/cli/commands/test-transport.js +15 -15
  82. package/dist/cli/commands/test-transport.js.map +1 -1
  83. package/dist/cli/index.js +13 -38
  84. package/dist/cli/index.js.map +1 -1
  85. package/dist/cli/output.d.ts +4 -0
  86. package/dist/cli/output.d.ts.map +1 -0
  87. package/dist/cli/output.js +9 -0
  88. package/dist/cli/output.js.map +1 -0
  89. package/dist/cli/socket-client.d.ts +7 -14
  90. package/dist/cli/socket-client.d.ts.map +1 -1
  91. package/dist/cli/socket-client.js +15 -38
  92. package/dist/cli/socket-client.js.map +1 -1
  93. package/dist/cli/transport.d.ts +53 -116
  94. package/dist/cli/transport.d.ts.map +1 -1
  95. package/dist/cli/transport.js +45 -295
  96. package/dist/cli/transport.js.map +1 -1
  97. package/dist/config.d.ts +24 -0
  98. package/dist/config.d.ts.map +1 -0
  99. package/dist/config.js +35 -0
  100. package/dist/config.js.map +1 -0
  101. package/dist/config.test-utils.d.ts +13 -0
  102. package/dist/config.test-utils.d.ts.map +1 -0
  103. package/dist/config.test-utils.js +46 -0
  104. package/dist/config.test-utils.js.map +1 -0
  105. package/dist/index.d.ts +3 -8
  106. package/dist/index.d.ts.map +1 -1
  107. package/dist/index.js +2 -12
  108. package/dist/index.js.map +1 -1
  109. package/dist/local-daemon-rpc.d.ts +259 -8
  110. package/dist/local-daemon-rpc.d.ts.map +1 -1
  111. package/dist/local-daemon-rpc.js +189 -12
  112. package/dist/local-daemon-rpc.js.map +1 -1
  113. package/dist/{runtime/local-history.d.ts → local-history.d.ts} +16 -21
  114. package/dist/local-history.d.ts.map +1 -0
  115. package/dist/{runtime/local-history.js → local-history.js} +16 -21
  116. package/dist/local-history.js.map +1 -0
  117. package/dist/local-paths.d.ts +0 -2
  118. package/dist/local-paths.d.ts.map +1 -1
  119. package/dist/local-paths.js +0 -4
  120. package/dist/local-paths.js.map +1 -1
  121. package/dist/local-socket-server.d.ts +22 -0
  122. package/dist/local-socket-server.d.ts.map +1 -0
  123. package/dist/{runtime/local-socket-server.js → local-socket-server.js} +4 -9
  124. package/dist/local-socket-server.js.map +1 -0
  125. package/dist/message-rendering.d.ts +3 -0
  126. package/dist/message-rendering.d.ts.map +1 -0
  127. package/dist/message-rendering.js +7 -0
  128. package/dist/message-rendering.js.map +1 -0
  129. package/dist/notification/__tests__/{snapshot-semantics.types-check.d.ts → subscribe-signatures.types-check.d.ts} +1 -1
  130. package/dist/notification/__tests__/subscribe-signatures.types-check.d.ts.map +1 -0
  131. package/dist/notification/__tests__/subscribe-signatures.types-check.js +55 -0
  132. package/dist/notification/__tests__/subscribe-signatures.types-check.js.map +1 -0
  133. package/dist/notification/errors.d.ts +18 -6
  134. package/dist/notification/errors.d.ts.map +1 -1
  135. package/dist/notification/errors.js +13 -15
  136. package/dist/notification/errors.js.map +1 -1
  137. package/dist/notification/index.d.ts +5 -0
  138. package/dist/notification/index.d.ts.map +1 -0
  139. package/dist/notification/index.js +5 -0
  140. package/dist/notification/index.js.map +1 -0
  141. package/dist/notification/stream.d.ts +33 -49
  142. package/dist/notification/stream.d.ts.map +1 -1
  143. package/dist/notification/stream.js +33 -76
  144. package/dist/notification/stream.js.map +1 -1
  145. package/dist/pagination.d.ts +20 -10
  146. package/dist/pagination.d.ts.map +1 -1
  147. package/dist/pagination.js +8 -9
  148. package/dist/pagination.js.map +1 -1
  149. package/dist/profile.d.ts +92 -0
  150. package/dist/profile.d.ts.map +1 -0
  151. package/dist/profile.js +149 -0
  152. package/dist/profile.js.map +1 -0
  153. package/dist/refs.d.ts.map +1 -0
  154. package/dist/refs.js.map +1 -0
  155. package/dist/service-archive-purge.d.ts +2 -1
  156. package/dist/service-archive-purge.d.ts.map +1 -1
  157. package/dist/service-archive-purge.js.map +1 -1
  158. package/dist/{runtime/service-helpers.d.ts → service-helpers.d.ts} +5 -11
  159. package/dist/service-helpers.d.ts.map +1 -0
  160. package/dist/{runtime/service-helpers.js → service-helpers.js} +2 -9
  161. package/dist/service-helpers.js.map +1 -0
  162. package/dist/service-local-daemon.d.ts +22 -0
  163. package/dist/service-local-daemon.d.ts.map +1 -0
  164. package/dist/service-local-daemon.js +185 -0
  165. package/dist/service-local-daemon.js.map +1 -0
  166. package/dist/service.d.ts +65 -57
  167. package/dist/service.d.ts.map +1 -1
  168. package/dist/service.js +205 -156
  169. package/dist/service.js.map +1 -1
  170. package/dist/test-utils/channel-service-fixture.d.ts +3 -2
  171. package/dist/test-utils/channel-service-fixture.d.ts.map +1 -1
  172. package/dist/test-utils/channel-service-fixture.js.map +1 -1
  173. package/dist/test-utils/fake-service.d.ts +26 -18
  174. package/dist/test-utils/fake-service.d.ts.map +1 -1
  175. package/dist/test-utils/fake-service.js +28 -42
  176. package/dist/test-utils/fake-service.js.map +1 -1
  177. package/dist/test-utils/ids.d.ts +3 -1
  178. package/dist/test-utils/ids.d.ts.map +1 -1
  179. package/dist/test-utils/ids.js.map +1 -1
  180. package/dist/test-utils/index.d.ts +9 -2
  181. package/dist/test-utils/index.d.ts.map +1 -1
  182. package/dist/test-utils/index.js +8 -1
  183. package/dist/test-utils/index.js.map +1 -1
  184. package/dist/test-utils/standalone-provisioning.d.ts +17 -0
  185. package/dist/test-utils/standalone-provisioning.d.ts.map +1 -0
  186. package/dist/test-utils/standalone-provisioning.js +14 -0
  187. package/dist/test-utils/standalone-provisioning.js.map +1 -0
  188. package/dist/tsconfig.tsbuildinfo +1 -0
  189. package/package.json +39 -17
  190. package/dist/auth.test.d.ts +0 -2
  191. package/dist/auth.test.d.ts.map +0 -1
  192. package/dist/auth.test.js +0 -121
  193. package/dist/auth.test.js.map +0 -1
  194. package/dist/channel-core-context.test.d.ts +0 -2
  195. package/dist/channel-core-context.test.d.ts.map +0 -1
  196. package/dist/channel-core-context.test.js +0 -342
  197. package/dist/channel-core-context.test.js.map +0 -1
  198. package/dist/channel-core-dispatch.test.d.ts +0 -2
  199. package/dist/channel-core-dispatch.test.d.ts.map +0 -1
  200. package/dist/channel-core-dispatch.test.js +0 -557
  201. package/dist/channel-core-dispatch.test.js.map +0 -1
  202. package/dist/channel-core.test.d.ts +0 -2
  203. package/dist/channel-core.test.d.ts.map +0 -1
  204. package/dist/channel-core.test.js +0 -232
  205. package/dist/channel-core.test.js.map +0 -1
  206. package/dist/cli/__tests__/cli-multi-agent.int.test.d.ts +0 -2
  207. package/dist/cli/__tests__/cli-multi-agent.int.test.d.ts.map +0 -1
  208. package/dist/cli/__tests__/cli-multi-agent.int.test.js +0 -132
  209. package/dist/cli/__tests__/cli-multi-agent.int.test.js.map +0 -1
  210. package/dist/cli/commands/invite.d.ts +0 -7
  211. package/dist/cli/commands/invite.d.ts.map +0 -1
  212. package/dist/cli/commands/invite.js +0 -11
  213. package/dist/cli/commands/invite.js.map +0 -1
  214. package/dist/cli/commands/messages.test.d.ts +0 -2
  215. package/dist/cli/commands/messages.test.d.ts.map +0 -1
  216. package/dist/cli/commands/messages.test.js +0 -99
  217. package/dist/cli/commands/messages.test.js.map +0 -1
  218. package/dist/cli/commands/ping.d.ts +0 -7
  219. package/dist/cli/commands/ping.d.ts.map +0 -1
  220. package/dist/cli/commands/ping.js +0 -37
  221. package/dist/cli/commands/ping.js.map +0 -1
  222. package/dist/cli/commands/presence.d.ts +0 -11
  223. package/dist/cli/commands/presence.d.ts.map +0 -1
  224. package/dist/cli/commands/presence.js +0 -33
  225. package/dist/cli/commands/presence.js.map +0 -1
  226. package/dist/cli/commands/register.test.d.ts +0 -2
  227. package/dist/cli/commands/register.test.d.ts.map +0 -1
  228. package/dist/cli/commands/register.test.js +0 -91
  229. package/dist/cli/commands/register.test.js.map +0 -1
  230. package/dist/cli/commands/send.test.d.ts +0 -2
  231. package/dist/cli/commands/send.test.d.ts.map +0 -1
  232. package/dist/cli/commands/send.test.js +0 -59
  233. package/dist/cli/commands/send.test.js.map +0 -1
  234. package/dist/cli/commands/start.test.d.ts +0 -2
  235. package/dist/cli/commands/start.test.d.ts.map +0 -1
  236. package/dist/cli/commands/start.test.js +0 -624
  237. package/dist/cli/commands/start.test.js.map +0 -1
  238. package/dist/cli/commands/whoami.d.ts +0 -8
  239. package/dist/cli/commands/whoami.d.ts.map +0 -1
  240. package/dist/cli/commands/whoami.js +0 -28
  241. package/dist/cli/commands/whoami.js.map +0 -1
  242. package/dist/cli/config.d.ts +0 -66
  243. package/dist/cli/config.d.ts.map +0 -1
  244. package/dist/cli/config.js +0 -148
  245. package/dist/cli/config.js.map +0 -1
  246. package/dist/cli/config.test.d.ts +0 -2
  247. package/dist/cli/config.test.d.ts.map +0 -1
  248. package/dist/cli/config.test.js +0 -89
  249. package/dist/cli/config.test.js.map +0 -1
  250. package/dist/cli/http-client.d.ts +0 -17
  251. package/dist/cli/http-client.d.ts.map +0 -1
  252. package/dist/cli/http-client.js +0 -38
  253. package/dist/cli/http-client.js.map +0 -1
  254. package/dist/cli/profile.d.ts +0 -126
  255. package/dist/cli/profile.d.ts.map +0 -1
  256. package/dist/cli/profile.js +0 -231
  257. package/dist/cli/profile.js.map +0 -1
  258. package/dist/cli/profile.test.d.ts +0 -2
  259. package/dist/cli/profile.test.d.ts.map +0 -1
  260. package/dist/cli/profile.test.js +0 -369
  261. package/dist/cli/profile.test.js.map +0 -1
  262. package/dist/cli/transport.test.d.ts +0 -2
  263. package/dist/cli/transport.test.d.ts.map +0 -1
  264. package/dist/cli/transport.test.js +0 -312
  265. package/dist/cli/transport.test.js.map +0 -1
  266. package/dist/notification/__tests__/filter-equivalence.test.d.ts +0 -2
  267. package/dist/notification/__tests__/filter-equivalence.test.d.ts.map +0 -1
  268. package/dist/notification/__tests__/filter-equivalence.test.js +0 -123
  269. package/dist/notification/__tests__/filter-equivalence.test.js.map +0 -1
  270. package/dist/notification/__tests__/snapshot-semantics.test.d.ts +0 -2
  271. package/dist/notification/__tests__/snapshot-semantics.test.d.ts.map +0 -1
  272. package/dist/notification/__tests__/snapshot-semantics.test.js +0 -261
  273. package/dist/notification/__tests__/snapshot-semantics.test.js.map +0 -1
  274. package/dist/notification/__tests__/snapshot-semantics.types-check.d.ts.map +0 -1
  275. package/dist/notification/__tests__/snapshot-semantics.types-check.js +0 -62
  276. package/dist/notification/__tests__/snapshot-semantics.types-check.js.map +0 -1
  277. package/dist/pagination.test.d.ts +0 -2
  278. package/dist/pagination.test.d.ts.map +0 -1
  279. package/dist/pagination.test.js +0 -72
  280. package/dist/pagination.test.js.map +0 -1
  281. package/dist/runtime/close-info.d.ts +0 -84
  282. package/dist/runtime/close-info.d.ts.map +0 -1
  283. package/dist/runtime/close-info.js +0 -102
  284. package/dist/runtime/close-info.js.map +0 -1
  285. package/dist/runtime/close-info.test.d.ts +0 -2
  286. package/dist/runtime/close-info.test.d.ts.map +0 -1
  287. package/dist/runtime/close-info.test.js +0 -109
  288. package/dist/runtime/close-info.test.js.map +0 -1
  289. package/dist/runtime/errors.d.ts +0 -11
  290. package/dist/runtime/errors.d.ts.map +0 -1
  291. package/dist/runtime/errors.js +0 -41
  292. package/dist/runtime/errors.js.map +0 -1
  293. package/dist/runtime/errors.test.d.ts +0 -2
  294. package/dist/runtime/errors.test.d.ts.map +0 -1
  295. package/dist/runtime/errors.test.js +0 -79
  296. package/dist/runtime/errors.test.js.map +0 -1
  297. package/dist/runtime/frame.d.ts +0 -8
  298. package/dist/runtime/frame.d.ts.map +0 -1
  299. package/dist/runtime/frame.js +0 -12
  300. package/dist/runtime/frame.js.map +0 -1
  301. package/dist/runtime/frame.test.d.ts +0 -2
  302. package/dist/runtime/frame.test.d.ts.map +0 -1
  303. package/dist/runtime/frame.test.js +0 -59
  304. package/dist/runtime/frame.test.js.map +0 -1
  305. package/dist/runtime/index.d.ts +0 -10
  306. package/dist/runtime/index.d.ts.map +0 -1
  307. package/dist/runtime/index.js +0 -9
  308. package/dist/runtime/index.js.map +0 -1
  309. package/dist/runtime/local-history.d.ts.map +0 -1
  310. package/dist/runtime/local-history.js.map +0 -1
  311. package/dist/runtime/local-service-commands.d.ts +0 -26
  312. package/dist/runtime/local-service-commands.d.ts.map +0 -1
  313. package/dist/runtime/local-service-commands.js +0 -29
  314. package/dist/runtime/local-service-commands.js.map +0 -1
  315. package/dist/runtime/local-socket-server.d.ts +0 -20
  316. package/dist/runtime/local-socket-server.d.ts.map +0 -1
  317. package/dist/runtime/local-socket-server.js.map +0 -1
  318. package/dist/runtime/refs.d.ts.map +0 -1
  319. package/dist/runtime/refs.js.map +0 -1
  320. package/dist/runtime/runtime.test.d.ts +0 -2
  321. package/dist/runtime/runtime.test.d.ts.map +0 -1
  322. package/dist/runtime/runtime.test.js +0 -37
  323. package/dist/runtime/runtime.test.js.map +0 -1
  324. package/dist/runtime/service-helpers.d.ts.map +0 -1
  325. package/dist/runtime/service-helpers.js.map +0 -1
  326. package/dist/runtime/service-teardown.d.ts +0 -5
  327. package/dist/runtime/service-teardown.d.ts.map +0 -1
  328. package/dist/runtime/service-teardown.js +0 -36
  329. package/dist/runtime/service-teardown.js.map +0 -1
  330. package/dist/runtime/service-teardown.test.d.ts +0 -2
  331. package/dist/runtime/service-teardown.test.d.ts.map +0 -1
  332. package/dist/runtime/service-teardown.test.js +0 -80
  333. package/dist/runtime/service-teardown.test.js.map +0 -1
  334. package/dist/runtime/subscribers.d.ts +0 -152
  335. package/dist/runtime/subscribers.d.ts.map +0 -1
  336. package/dist/runtime/subscribers.js +0 -222
  337. package/dist/runtime/subscribers.js.map +0 -1
  338. package/dist/service-socket-path.test.d.ts +0 -2
  339. package/dist/service-socket-path.test.d.ts.map +0 -1
  340. package/dist/service-socket-path.test.js +0 -87
  341. package/dist/service-socket-path.test.js.map +0 -1
  342. package/dist/service.test.d.ts +0 -2
  343. package/dist/service.test.d.ts.map +0 -1
  344. package/dist/service.test.js +0 -796
  345. package/dist/service.test.js.map +0 -1
  346. package/dist/test/index.d.ts +0 -47
  347. package/dist/test/index.d.ts.map +0 -1
  348. package/dist/test/index.js +0 -39
  349. package/dist/test/index.js.map +0 -1
  350. package/dist/test-utils/conformance-adapter.d.ts +0 -40
  351. package/dist/test-utils/conformance-adapter.d.ts.map +0 -1
  352. package/dist/test-utils/conformance-adapter.js +0 -250
  353. package/dist/test-utils/conformance-adapter.js.map +0 -1
  354. package/dist/tm-client-test-support.d.ts +0 -184
  355. package/dist/tm-client-test-support.d.ts.map +0 -1
  356. package/dist/tm-client-test-support.js +0 -466
  357. package/dist/tm-client-test-support.js.map +0 -1
  358. package/dist/tm-client.d.ts +0 -269
  359. package/dist/tm-client.d.ts.map +0 -1
  360. package/dist/tm-client.js +0 -518
  361. package/dist/tm-client.js.map +0 -1
  362. package/dist/tm-client.test.d.ts +0 -2
  363. package/dist/tm-client.test.d.ts.map +0 -1
  364. package/dist/tm-client.test.js +0 -490
  365. package/dist/tm-client.test.js.map +0 -1
  366. /package/dist/{runtime/refs.d.ts → refs.d.ts} +0 -0
  367. /package/dist/{runtime/refs.js → refs.js} +0 -0
package/dist/service.js CHANGED
@@ -1,24 +1,34 @@
1
- /* eslint-disable jsdoc/text-escaping -- mermaid sequenceDiagram blocks need literal `<br>` (HTML5) for renderer compatibility; the escape would render as literal text. */
2
1
  import { FileSystem, Path } from "@effect/platform";
3
2
  import { NodeContext } from "@effect/platform-node";
4
- import { AgentsLookup, AgentsLookupByName, DispatchRequest, DispatchRelease, DispatchesConsumed, DispatchesExpired, DispatchesGet, MessageReceivedNotificationDefinition, TaskConversationCreatedNotificationDefinition, TaskConversationArchivedNotificationDefinition, TaskConversationUnarchivedNotificationDefinition, ConversationArchivedError, DEFAULT_APP_ID, MessagesList, MessagesSend, TaskRequest, TaskConversationList, NotConnectedError, serverRpcMethods, RpcServerError, RpcTimeoutError, } from "@moltzap/protocol";
5
- import { Config, ConfigProvider, Effect, HashMap, Option, Ref, Scope, Stream, } from "effect";
3
+ import { AgentId as AgentIdSchema, AgentNotFoundError, AgentsList, } from "@moltzap/protocol/identity";
4
+ import { DispatchRequest, DispatchRelease, DispatchLeaseConsumed, DispatchLeaseExpired, } from "@moltzap/protocol/message/dispatch";
5
+ import { ConversationCreatedNotificationDefinition, ConversationArchivedNotificationDefinition, ConversationUnarchivedNotificationDefinition, ConversationList, } from "@moltzap/protocol/conversation";
6
+ import { DEFAULT_APP_ID, TaskRequest } from "@moltzap/protocol/task";
7
+ import { ConversationArchivedError, } from "@moltzap/protocol/conversation";
8
+ import { MessageReceivedNotificationDefinition, MessagesList, MessagesSend, } from "@moltzap/protocol/message";
9
+ import { NotConnectedError, RpcTimeoutError, isNotificationDeliveryFor, } from "@moltzap/protocol/rpc";
10
+ import { AgentCallableGroup } from "@moltzap/protocol/socket/catalog";
11
+ import { Config, ConfigProvider, Effect, Exit, HashMap, Option, Ref, Schema, Scope, Stream, } from "effect";
6
12
  import { MoltZapAgentClient } from "./agent-client.js";
7
- import { AgentNotFoundError } from "./runtime/errors.js";
8
- import { getOr, snapshot } from "./runtime/refs.js";
9
- import { LocalServiceCommands } from "./runtime/local-service-commands.js";
13
+ import { loadServiceConfig, } from "./config.js";
14
+ import { getOr, snapshot } from "./refs.js";
10
15
  import { getMoltZapAgentServiceSocketPath, getMoltZapServiceSocketPath, } from "./local-paths.js";
11
- import { startLocalSocketServer, stopLocalSocketServer, } from "./runtime/local-socket-server.js";
12
- import { buildContextEntries, makeContextCandidate, newMessagesForConversation, notificationTraceRecord, renderPart, ServiceInputError, } from "./runtime/service-helpers.js";
13
- import { decodeHistoryRequest, formatHistoryMessage, lastReadIdsForSession, } from "./runtime/local-history.js";
14
- import { composeServiceTeardown } from "./runtime/service-teardown.js";
16
+ import {} from "./local-daemon-rpc.js";
17
+ import { makeLocalDaemonHandlers } from "./service-local-daemon.js";
18
+ import { startLocalSocketServer, stopLocalSocketServer, } from "./local-socket-server.js";
19
+ import { buildContextEntries, makeContextCandidate, newMessagesForConversation, notificationTraceRecord, } from "./service-helpers.js";
20
+ import { renderPart } from "./message-rendering.js";
21
+ import { formatHistoryMessage, lastReadIdsForSession, } from "./local-history.js";
15
22
  import { purgeAgentCacheEntries, purgeLastNotified, purgeLastRead, } from "./service-archive-purge.js";
16
23
  const CROSS_CONTEXT_TEXT_LIMIT = 120;
17
24
  const DEFAULT_MAX_CONTEXT_CONVERSATIONS = 5;
18
25
  const DEFAULT_MAX_MESSAGES_PER_CONVERSATION = 3;
19
26
  const HISTORY_LOOKUP_CONCURRENCY = 2;
20
- const SEND_TO_AGENT_LOOKUP_PAGE_SIZE = 50;
21
- const SEND_TO_AGENT_LOOKUP_MAX_PAGES = 20;
27
+ const AGENT_LOOKUP_PAGE_SIZE = 100;
28
+ const AGENT_LOOKUP_MAX_PAGES = 20;
29
+ const REUSABLE_CONVERSATION_LOOKUP_PAGE_SIZE = 50;
30
+ const REUSABLE_CONVERSATION_LOOKUP_MAX_PAGES = 20;
31
+ const decodeAgentId = Schema.decodeUnknownOption(AgentIdSchema);
22
32
  const ClientEventLogDir = Config.option(Config.string("MOLTZAP_CLIENT_EVENT_LOG_DIR"));
23
33
  const getClientEventLogDir = () => Option.getOrUndefined(Effect.runSync(ClientEventLogDir.pipe(Effect.withConfigProvider(ConfigProvider.fromEnv()))));
24
34
  function appendClientEventTrace(record) {
@@ -33,6 +43,10 @@ function appendClientEventTrace(record) {
33
43
  yield* Effect.zipRight(fileSystem.makeDirectory(dir, { recursive: true }), fileSystem.writeFileString(path.join(dir, `client-events-${safeAgentId}.jsonl`), JSON.stringify(record) + "\n", { flag: "a" }));
34
44
  }).pipe(Effect.withSpan("appendClientEventTrace"), Effect.provide(NodeContext.layer), Effect.catchAll((err) => Effect.logWarning("moltzap client event trace write failed", err)));
35
45
  }
46
+ const agentNotFound = (agentName) => new AgentNotFoundError({
47
+ message: `Agent not found: ${agentName}`,
48
+ data: { agentName },
49
+ });
36
50
  /** Escape `&lt;`, `>`, `&amp;` so sender content can't escape a `&lt;system-reminder>` block. */
37
51
  export function sanitizeForSystemReminder(s) {
38
52
  return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
@@ -42,7 +56,7 @@ export function sanitizeForSystemReminder(s) {
42
56
  * that inline context into prompt text (nanoclaw) and `MoltZapService.getContext`
43
57
  * share this formatter so sanitization and line shape stay in one place.
44
58
  */
45
- export function formatCrossConversationBlock(entries, opts) {
59
+ function formatCrossConversationBlock(entries, opts) {
46
60
  if (entries.length === 0)
47
61
  return null;
48
62
  const lines = entries.map((e) => {
@@ -91,19 +105,16 @@ function fanout(handlers, arg) {
91
105
  * API contract: **every fallible method returns `Effect`.** No `*Async`
92
106
  * Promise siblings — async/await consumers run the Effect at the edge
93
107
  * with `Effect.runPromise`. Keep this class Effect-only so downstream
94
- * callers compose failures and cancellation explicitly. (Phase -1
95
- * vendored the legacy `@moltzap/app-sdk` Promise-shaped wrapper out
96
- * to arena; consumers wanting Promise wrappers maintain their own.)
108
+ * callers compose failures and cancellation explicitly.
97
109
  */
98
110
  export class MoltZapService {
99
111
  opts;
100
112
  client = null;
101
113
  _connected = false;
102
114
  /**
103
- * Service-owned scope (spec #596 / Spec B §"4.2 service.ts" lifecycle
104
- * reshape). Opened in `connect()`, owns the `subscribeAll → Stream.runForEach`
105
- * fan-out fiber. Closed in `close()` so the fiber terminates with the
106
- * service.
115
+ * Service-owned scope. Opened in `connect()`, owns the
116
+ * `subscribeAll → Stream.runForEach` fan-out fiber. Closed in `close()` so
117
+ * the fiber terminates with the service.
107
118
  *
108
119
  * Held off the public `connect()` signature so callers do not need to
109
120
  * thread a `Scope` requirement.
@@ -134,42 +145,29 @@ export class MoltZapService {
134
145
  conversationArchived: [],
135
146
  conversationUnarchived: [],
136
147
  dispatchRelease: [],
137
- dispatchesConsumed: [],
138
- dispatchesExpired: [],
148
+ dispatchLeaseConsumed: [],
149
+ dispatchLeaseExpired: [],
139
150
  };
140
- notificationDispatchers = new Map([
141
- [
142
- MessageReceivedNotificationDefinition,
143
- (notification) => this.handleMessageReceivedNotification(notification.params),
144
- ],
145
- [
146
- TaskConversationCreatedNotificationDefinition,
147
- (notification) => this.handleConversationCreatedNotification(notification.params),
148
- ],
149
- [
150
- TaskConversationArchivedNotificationDefinition,
151
- (notification) => this.handleConversationArchivedNotification(notification.params),
152
- ],
153
- [
154
- TaskConversationUnarchivedNotificationDefinition,
155
- (notification) => this.handleConversationUnarchivedNotification(notification.params),
156
- ],
157
- [
158
- DispatchRelease,
159
- (notification) => fanout(this.handlers.dispatchRelease, notification.params),
160
- ],
161
- [
162
- DispatchesConsumed,
163
- (notification) => fanout(this.handlers.dispatchesConsumed, notification.params),
164
- ],
165
- [
166
- DispatchesExpired,
167
- (notification) => fanout(this.handlers.dispatchesExpired, notification.params),
168
- ],
169
- ]);
170
151
  _ownAgentId;
171
152
  constructor(opts) {
172
153
  this.opts = opts;
154
+ // The empty HelloOk carries no identity; `ownAgentId` is the client's
155
+ // registered/stored id, available before the handshake.
156
+ this._ownAgentId = opts.agentId;
157
+ }
158
+ static fromConfig(config) {
159
+ return new MoltZapService(config);
160
+ }
161
+ static make(profileName) {
162
+ return loadServiceConfig(profileName).pipe(Effect.map(MoltZapService.fromConfig));
163
+ }
164
+ static startDaemon(profileName) {
165
+ return Effect.gen(function* () {
166
+ const service = yield* MoltZapService.make(profileName);
167
+ yield* service.connect();
168
+ yield* service.startSocketServer();
169
+ return service;
170
+ }).pipe(Effect.withSpan("MoltZapService.startDaemon"));
173
171
  }
174
172
  get connected() {
175
173
  return this._connected;
@@ -183,9 +181,9 @@ export class MoltZapService {
183
181
  const client = new MoltZapAgentClient({
184
182
  serverUrl: this.opts.serverUrl,
185
183
  agentKey: this.opts.agentKey,
186
- // Spec #222 OQ-6: arg required. The body doesn't branch on
187
- // close metadata today; signature kept explicit so a future
188
- // disconnect-handler chain can plumb code/reason through.
184
+ // The body doesn't branch on close metadata today; the signature is
185
+ // kept explicit so a future disconnect-handler chain can plumb
186
+ // code/reason through.
189
187
  onDisconnect: () => {
190
188
  this._connected = false;
191
189
  fanout(this.handlers.disconnect, undefined);
@@ -196,11 +194,10 @@ export class MoltZapService {
196
194
  },
197
195
  });
198
196
  this.client = client;
199
- // Spec #596 / Spec B Goal #8: the legacy `subscribe({}, handler)` site
200
- // is replaced by `subscribeAll().pipe(Stream.runForEach, …)` forked
201
- // into a service-owned scope. The Stream is materialized BEFORE
202
- // `connect()` so subscriptions are registered with the registry
203
- // pre-handshake (pre-connect legality, preserved invariant).
197
+ // `subscribeAll().pipe(Stream.runForEach, …)` is forked into a
198
+ // service-owned scope. The Stream is materialized BEFORE `connect()` so
199
+ // subscriptions are registered with the registry pre-handshake (a
200
+ // pre-connect-legal operation).
204
201
  //
205
202
  // Stream errors of type `NotConnectedError` are surfaced on the
206
203
  // fiber's failure channel only when the client transitions to
@@ -213,7 +210,6 @@ export class MoltZapService {
213
210
  yield* Effect.forkIn(fanoutEffect, serviceScope);
214
211
  const helloOk = yield* client.connect();
215
212
  this._connected = true;
216
- this._ownAgentId = helloOk.agentId;
217
213
  return helloOk;
218
214
  });
219
215
  }
@@ -226,22 +222,15 @@ export class MoltZapService {
226
222
  close() {
227
223
  this._connected = false;
228
224
  Effect.runFork(this.stopSocketServer());
229
- // Spec #596 / Spec B §"4.2 service.ts": close the service-owned scope
230
- // BEFORE the client. Closing the scope interrupts the
231
- // `subscribeAll().pipe(Stream.runForEach, …)` fiber; the client's
232
- // `close()` then closes the registry which fires `onClose` on every
233
- // live subscription's Stream — but since our consumer fiber has
234
- // already been interrupted, the typed-error delivery is to a
235
- // terminated consumer (no-op, idempotent).
236
- // Order: close the service-scope FIRST (interrupting the
237
- // `subscribeAll → runForEach` fiber), THEN close the ws-client.
238
- // zipRight chains the two Effects sequentially inside a single
239
- // fork so the ordering is honoured deterministically.
240
225
  const scopeToClose = this.serviceScope;
241
226
  const clientToClose = this.client;
242
227
  this.serviceScope = null;
243
228
  this.client = null;
244
- Effect.runFork(composeServiceTeardown(scopeToClose, clientToClose));
229
+ const closeScope = scopeToClose === null
230
+ ? Effect.void
231
+ : Scope.close(scopeToClose, Exit.void);
232
+ const closeClient = clientToClose === null ? Effect.void : clientToClose.close();
233
+ Effect.runFork(closeScope.pipe(Effect.zipRight(closeClient)));
245
234
  Effect.runSync(Effect.all([
246
235
  Ref.set(this.conversationsRef, HashMap.empty()),
247
236
  Ref.set(this.messagesRef, HashMap.empty()),
@@ -287,7 +276,7 @@ export class MoltZapService {
287
276
  const running = yield* startLocalSocketServer({
288
277
  socketPath: this.socketPath,
289
278
  defaultSocketPath: MoltZapService.SOCKET_PATH,
290
- handleRequest: (method, params) => this.handleSocketRequestEffect(method, params),
279
+ handlers: this.localDaemonHandlers(),
291
280
  });
292
281
  this.socketServerScope = running.socketScope;
293
282
  this.activeSocketPath = running.socketPath;
@@ -308,36 +297,18 @@ export class MoltZapService {
308
297
  defaultSocketPath: MoltZapService.SOCKET_PATH,
309
298
  }).pipe(Effect.withSpan("MoltZapService.stopSocketServer"));
310
299
  }
311
- handleSocketRequestEffect(method, params) {
312
- return Effect.suspend(() => {
313
- switch (method) {
314
- case LocalServiceCommands.Ping:
315
- return Effect.succeed({ ok: true, agentId: this.ownAgentId });
316
- case LocalServiceCommands.Status:
317
- return Effect.succeed({
318
- agentId: this.ownAgentId,
319
- connected: this._connected,
320
- conversations: this.getConversations().length,
321
- });
322
- case LocalServiceCommands.History:
323
- return this.handleHistoryRequest(params);
324
- default: {
325
- const definition = serverRpcMethods.find((d) => d.name === method);
326
- if (definition === undefined ||
327
- !definition.validateParams(params)) {
328
- return Effect.fail(new ServiceInputError({
329
- message: `unknown or invalid RPC method: ${method}`,
330
- }));
331
- }
332
- return this.sendRpc(definition, params);
333
- }
334
- }
300
+ localDaemonHandlers() {
301
+ return makeLocalDaemonHandlers({
302
+ ownAgentId: this._ownAgentId,
303
+ connected: this._connected,
304
+ conversationCount: () => this.getConversations().length,
305
+ call: this.call.bind(this),
306
+ handleHistoryRequest: (request) => this.handleHistoryRequest(request),
335
307
  });
336
308
  }
337
- handleHistoryRequest(params) {
309
+ handleHistoryRequest(request) {
338
310
  return Effect.gen(this, function* () {
339
- const request = yield* decodeHistoryRequest(params);
340
- const result = yield* this.sendRpc(MessagesList, {
311
+ const result = yield* this.call(MessagesList.name, {
341
312
  taskId: request.taskId,
342
313
  conversationId: request.conversationId,
343
314
  limit: request.limit,
@@ -380,19 +351,13 @@ export class MoltZapService {
380
351
  ].filter((id) => !HashMap.has(knownNames, id));
381
352
  if (unknownAgentIds.length === 0)
382
353
  return;
383
- yield* this.sendRpc(AgentsLookup, { agentIds: unknownAgentIds }).pipe(Effect.tap((result) => Ref.update(this.agentNamesRef, (names) => {
384
- let next = names;
385
- for (const agent of result.agents) {
386
- next = HashMap.set(next, agent.id, agent.name);
387
- }
388
- return next;
389
- })), Effect.asVoid, Effect.catchAll(() => Effect.void));
354
+ yield* this.cacheVisibleAgentNamesForIds(new Set(unknownAgentIds)).pipe(Effect.asVoid, Effect.catchAll(() => Effect.void));
390
355
  });
391
356
  }
392
357
  fetchHistoryConversationMeta(convId) {
393
- // Spec D3 D10: ConversationsGet retires; client filters
394
- // TaskConversationList output for the matching conversation id.
395
- return this.sendRpc(TaskConversationList, {}).pipe(Effect.map((result) => {
358
+ // The client filters `ConversationList` output for the matching
359
+ // conversation id (there is no per-conversation get RPC).
360
+ return this.call(ConversationList.name, {}).pipe(Effect.map((result) => {
396
361
  const hit = result.items.find((item) => item.conversation.id === convId);
397
362
  return hit?.conversation;
398
363
  }), Effect.catchAll(() => Effect.succeed(undefined)));
@@ -441,17 +406,16 @@ export class MoltZapService {
441
406
  */
442
407
  resolveAgentName(agentId) {
443
408
  return Effect.gen(this, function* () {
409
+ const decodedAgentId = Option.getOrUndefined(decodeAgentId(agentId));
410
+ if (decodedAgentId === undefined)
411
+ return agentId;
444
412
  const cached = Option.getOrUndefined(HashMap.get(snapshot(this.agentNamesRef), agentId));
445
413
  if (cached !== undefined)
446
414
  return cached;
447
- return yield* this.sendRpc(AgentsLookup, {
448
- agentIds: [agentId],
449
- }).pipe(Effect.flatMap((result) => {
450
- const agent = result.agents[0];
451
- if (!agent)
452
- return Effect.succeed(agentId);
453
- return Ref.update(this.agentNamesRef, (names) => HashMap.set(names, agentId, agent.name)).pipe(Effect.as(agent.name));
454
- }), Effect.catchAll((err) => Effect.logWarning("agents/lookup failed; falling back to agentId").pipe(Effect.annotateLogs({ agentId, err: String(err) }), Effect.as(agentId))));
415
+ return yield* this.cacheVisibleAgentNamesForIds(new Set([decodedAgentId])).pipe(Effect.map(() => {
416
+ const resolved = Option.getOrUndefined(HashMap.get(snapshot(this.agentNamesRef), agentId));
417
+ return resolved ?? agentId;
418
+ }), Effect.catchAll((err) => Effect.logWarning("agent/identity/agents/list failed; falling back to agentId").pipe(Effect.annotateLogs({ agentId, err: String(err) }), Effect.as(agentId))));
455
419
  });
456
420
  }
457
421
  // --- Messaging ---
@@ -470,8 +434,8 @@ export class MoltZapService {
470
434
  * svc-->>caller: fail(RpcServerError ConversationArchived)
471
435
  * else
472
436
  * svc->>ws: sendRpc(MessagesSend, params)
473
- * Note over ws: stateRef None → fail NotConnectedError<br>otherwise allocate JsonRpcId, encode frame
474
- * ws->>server: {jsonrpc, method messages/send, id, params}
437
+ * Note over ws: stateRef None → fail NotConnectedError; otherwise allocate request id, encode frame
438
+ * ws->>server: {jsonrpc, method agent/message/send, id, params}
475
439
  * Note over ws: Deferred raced against 30s timeout
476
440
  * server-->>ws: {result, id} or {error, id}
477
441
  * Note over ws: reader fiber decodes, resolves the Deferred
@@ -482,17 +446,14 @@ export class MoltZapService {
482
446
  *
483
447
  * `opts.dispatchLeaseId` (when set) is forwarded verbatim in the
484
448
  * params frame. The server marks the lease consumed, blocking the
485
- * TM's timeout sweep. `MoltZapChannelCore.sendReply` forwards
449
+ * app authorization timeout sweep. `MoltZapChannelCore.sendReply` forwards
486
450
  * `leaseIdInFlight` automatically when the caller omits it.
487
451
  */
488
452
  send(taskId, conversationId, text, opts) {
489
453
  if (this.isConversationArchived(conversationId)) {
490
- return Effect.fail(new RpcServerError({
491
- code: ConversationArchivedError.code,
492
- message: "Conversation is archived",
493
- }));
454
+ return Effect.fail(new ConversationArchivedError({ message: "Conversation is archived" }));
494
455
  }
495
- return Effect.asVoid(this.sendRpc(MessagesSend, {
456
+ return Effect.asVoid(this.call(MessagesSend.name, {
496
457
  taskId,
497
458
  conversationId,
498
459
  parts: [{ type: "text", text }],
@@ -503,34 +464,23 @@ export class MoltZapService {
503
464
  }));
504
465
  }
505
466
  /**
506
- * Issue `dispatch/request`. The server returns the ack
467
+ * Issue `agent/dispatch/request`. The server returns the ack
507
468
  * `{leaseId, dispatchId}` immediately; the recipient observes the
508
469
  * verdict asynchronously via the `dispatchRelease` event.
509
470
  */
510
471
  requestDispatch(params) {
511
- return this.sendRpc(DispatchRequest, params);
512
- }
513
- /**
514
- * Issue `dispatches/get`. Moderator-only — calls from non-moderator
515
- * connections fail with a typed wire error. The server enforces the
516
- * binding tuple recorded at lease-mint time.
517
- */
518
- dispatchesGet(params) {
519
- return this.sendRpc(DispatchesGet, params);
472
+ return this.call(DispatchRequest.name, params);
520
473
  }
521
474
  sendToAgent(agentName, text, opts) {
522
475
  return Effect.gen(this, function* () {
523
476
  const cache = yield* Ref.get(this.agentConversationCacheRef);
524
477
  let entry = Option.getOrUndefined(HashMap.get(cache, agentName));
525
478
  if (entry === undefined) {
526
- const lookupResult = yield* this.sendRpc(AgentsLookupByName, {
527
- names: [agentName],
528
- });
529
- const agent = lookupResult.agents[0];
479
+ const agent = yield* this.findVisibleAgentByName(agentName);
530
480
  if (!agent) {
531
- return yield* Effect.fail(new AgentNotFoundError({ agentName }));
481
+ return yield* Effect.fail(agentNotFound(agentName));
532
482
  }
533
- const createResult = yield* this.sendRpc(TaskRequest, {
483
+ const createResult = yield* this.call(TaskRequest.name, {
534
484
  appId: DEFAULT_APP_ID,
535
485
  invitedAgentIds: [agent.id],
536
486
  initialConversation: { participants: [agent.id] },
@@ -552,13 +502,13 @@ export class MoltZapService {
552
502
  resolveReusableConversationId(taskId, agentName) {
553
503
  return Effect.gen(this, function* () {
554
504
  let cursor = undefined;
555
- for (let page = 0; page < SEND_TO_AGENT_LOOKUP_MAX_PAGES; page++) {
505
+ for (let page = 0; page < REUSABLE_CONVERSATION_LOOKUP_MAX_PAGES; page++) {
556
506
  const params = {
557
- limit: SEND_TO_AGENT_LOOKUP_PAGE_SIZE,
507
+ limit: REUSABLE_CONVERSATION_LOOKUP_PAGE_SIZE,
558
508
  };
559
509
  if (cursor !== undefined)
560
510
  params.cursor = cursor;
561
- const result = yield* this.sendRpc(TaskConversationList, params);
511
+ const result = yield* this.call(ConversationList.name, params);
562
512
  const hit = result.items.find((item) => item.taskId === taskId &&
563
513
  item.conversation.archivedAt === undefined);
564
514
  if (hit !== undefined)
@@ -567,7 +517,54 @@ export class MoltZapService {
567
517
  break;
568
518
  cursor = result.nextCursor;
569
519
  }
570
- return yield* Effect.fail(new AgentNotFoundError({ agentName }));
520
+ return yield* Effect.fail(agentNotFound(agentName));
521
+ });
522
+ }
523
+ cacheAgentNames(agents) {
524
+ if (agents.length === 0)
525
+ return Effect.void;
526
+ return Ref.update(this.agentNamesRef, (names) => {
527
+ let next = names;
528
+ for (const agent of agents) {
529
+ next = HashMap.set(next, agent.id, agent.name);
530
+ }
531
+ return next;
532
+ });
533
+ }
534
+ agentListParams(cursor) {
535
+ return cursor === undefined
536
+ ? { limit: AGENT_LOOKUP_PAGE_SIZE }
537
+ : { limit: AGENT_LOOKUP_PAGE_SIZE, cursor };
538
+ }
539
+ cacheVisibleAgentNamesForIds(agentIds) {
540
+ return Effect.gen(this, function* () {
541
+ const missing = new Set(agentIds);
542
+ let cursor = undefined;
543
+ for (let page = 0; page < AGENT_LOOKUP_MAX_PAGES; page++) {
544
+ const params = this.agentListParams(cursor);
545
+ const result = yield* this.call(AgentsList.name, params);
546
+ yield* this.cacheAgentNames(result.agents);
547
+ for (const agent of result.agents)
548
+ missing.delete(agent.id);
549
+ if (missing.size === 0 || result.nextCursor === undefined)
550
+ return;
551
+ cursor = result.nextCursor;
552
+ }
553
+ });
554
+ }
555
+ findVisibleAgentByName(agentName) {
556
+ return Effect.gen(this, function* () {
557
+ let cursor = undefined;
558
+ for (let page = 0; page < AGENT_LOOKUP_MAX_PAGES; page++) {
559
+ const params = this.agentListParams(cursor);
560
+ const result = yield* this.call(AgentsList.name, params);
561
+ yield* this.cacheAgentNames(result.agents);
562
+ const hit = result.agents.find((agent) => agent.name === agentName);
563
+ if (hit !== undefined || result.nextCursor === undefined)
564
+ return hit;
565
+ cursor = result.nextCursor;
566
+ }
567
+ return undefined;
571
568
  });
572
569
  }
573
570
  // --- Cross-Conversation Context ---
@@ -672,12 +669,27 @@ export class MoltZapService {
672
669
  this.handlers[notification].push(handler);
673
670
  }
674
671
  // --- RPC passthrough ---
675
- sendRpc(definition, params, opts) {
672
+ /**
673
+ * Outbound RPC, typed per method — delegates to the agent client's typed
674
+ * `call`. `call("agent/identity/agents/list", payload)` recovers the result and that
675
+ * method's tagged-error union; an app-only method does not typecheck.
676
+ */
677
+ call(tag, payload, opts) {
678
+ return Effect.suspend(() => {
679
+ const client = this.client;
680
+ if (!client) {
681
+ return Effect.fail(new NotConnectedError({ message: "Not connected" }));
682
+ }
683
+ return client.call(tag, payload, opts);
684
+ });
685
+ }
686
+ callDefinition(definition, payload, opts) {
676
687
  return Effect.suspend(() => {
677
- if (!this.client) {
688
+ const client = this.client;
689
+ if (!client) {
678
690
  return Effect.fail(new NotConnectedError({ message: "Not connected" }));
679
691
  }
680
- return this.client.sendRpc(definition, params, opts);
692
+ return client.callDefinition(definition, payload, opts);
681
693
  });
682
694
  }
683
695
  // --- Internals ---
@@ -690,11 +702,46 @@ export class MoltZapService {
690
702
  Effect.runFork(appendClientEventTrace(notificationTraceRecord(notification, this._ownAgentId)));
691
703
  }
692
704
  dispatchTypedNotification(notification) {
693
- const dispatch = this.notificationDispatchers.get(notification.definition);
694
- if (dispatch === undefined) {
705
+ if (this.dispatchMessageNotification(notification))
695
706
  return;
707
+ if (this.dispatchConversationNotification(notification))
708
+ return;
709
+ this.dispatchAppNotification(notification);
710
+ }
711
+ dispatchMessageNotification(notification) {
712
+ if (isNotificationDeliveryFor(notification, MessageReceivedNotificationDefinition)) {
713
+ this.handleMessageReceivedNotification(notification.params);
714
+ return true;
715
+ }
716
+ return false;
717
+ }
718
+ dispatchConversationNotification(notification) {
719
+ if (isNotificationDeliveryFor(notification, ConversationCreatedNotificationDefinition)) {
720
+ this.handleConversationCreatedNotification(notification.params);
721
+ return true;
722
+ }
723
+ if (isNotificationDeliveryFor(notification, ConversationArchivedNotificationDefinition)) {
724
+ this.handleConversationArchivedNotification(notification.params);
725
+ return true;
726
+ }
727
+ if (isNotificationDeliveryFor(notification, ConversationUnarchivedNotificationDefinition)) {
728
+ this.handleConversationUnarchivedNotification(notification.params);
729
+ return true;
730
+ }
731
+ return false;
732
+ }
733
+ dispatchAppNotification(notification) {
734
+ if (isNotificationDeliveryFor(notification, DispatchRelease)) {
735
+ fanout(this.handlers.dispatchRelease, notification.params);
736
+ return;
737
+ }
738
+ if (isNotificationDeliveryFor(notification, DispatchLeaseConsumed)) {
739
+ fanout(this.handlers.dispatchLeaseConsumed, notification.params);
740
+ return;
741
+ }
742
+ if (isNotificationDeliveryFor(notification, DispatchLeaseExpired)) {
743
+ fanout(this.handlers.dispatchLeaseExpired, notification.params);
696
744
  }
697
- dispatch(notification);
698
745
  }
699
746
  /**
700
747
  * Record `messageId` in the per-conversation dedup window. Returns
@@ -702,10 +749,10 @@ export class MoltZapService {
702
749
  * a duplicate within the window (caller drops). On a new id, evicts
703
750
  * the oldest entry if the window is full.
704
751
  *
705
- * Bound to the live `messages/received` notification path: a single
752
+ * Bound to the live `agent/message/received` notification path: a single
706
753
  * server-side broadcast that surfaces the same id twice (network
707
754
  * replay, dual subscription) is suppressed to one
708
- * `on("message", ...)` event. `messages/list` returns raw history
755
+ * `on("message", ...)` event. `agent/message/list` returns raw history
709
756
  * unfiltered; consumers that combine both feeds dedup themselves.
710
757
  */
711
758
  recordMessageIdIfNew(convId, msgId) {
@@ -719,7 +766,9 @@ export class MoltZapService {
719
766
  }
720
767
  if (dedupSet.size >= DEDUP_WINDOW_PER_CONV) {
721
768
  // size >= 1 guaranteed by the guard above; next().value is defined.
722
- dedupSet.delete(dedupSet.keys().next().value);
769
+ const oldest = dedupSet.keys().next();
770
+ if (!oldest.done)
771
+ dedupSet.delete(oldest.value);
723
772
  }
724
773
  dedupSet.add(msgId);
725
774
  return true;