@tangle-network/agent-app 0.43.56 → 0.43.57

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 (352) hide show
  1. package/dist/DesignCanvas-UNL34LS2.js +12 -0
  2. package/dist/DesignCanvasEditor-FJIVYOA2.js +13 -0
  3. package/dist/IntakeInterview-3ZIQMZS6.js +8 -0
  4. package/dist/InvitationsPanel-CJ7DR4F7.js +8 -0
  5. package/dist/MembersPanel-BB4OD2KB.js +8 -0
  6. package/dist/{TimelineEditor-I35SJJAJ.js → TimelineEditor-2ECKSU6P.js} +3 -3
  7. package/dist/{VaultPane-DrQ_tH6c.d.ts → VaultPane-BDP6SB_K.d.ts} +1 -0
  8. package/dist/{access-BZ81Btt5.d.ts → access-490O6aOU.d.ts} +16 -1
  9. package/dist/app-auth/index.d.ts +6 -1
  10. package/dist/app-auth/index.js +3 -3
  11. package/dist/app-auth/index.js.map +1 -1
  12. package/dist/{apply-Gk4raT2j.d.ts → apply-6wlMOLf8.d.ts} +30 -1
  13. package/dist/assets/index.d.ts +41 -0
  14. package/dist/assets/index.js +1 -1
  15. package/dist/assistant/index.d.ts +26 -6
  16. package/dist/assistant/index.js +9 -9
  17. package/dist/assistant/index.js.map +1 -1
  18. package/dist/{attachment-validation-D0csjCvz.d.ts → attachment-validation-tPRp-PP1.d.ts} +7 -1
  19. package/dist/{auth-DuptSkWh.d.ts → auth-_FU8w01b.d.ts} +4 -1
  20. package/dist/billing/index.d.ts +8 -0
  21. package/dist/billing/index.js +1 -1
  22. package/dist/brand/index.d.ts +2 -0
  23. package/dist/brand/index.js.map +1 -1
  24. package/dist/brand-extraction/index.d.ts +3 -0
  25. package/dist/brand-extraction/index.js.map +1 -1
  26. package/dist/catalog/index.d.ts +2 -0
  27. package/dist/catalog/index.js +1 -1
  28. package/dist/chat-routes/index.d.ts +41 -10
  29. package/dist/chat-routes/index.js +15 -15
  30. package/dist/chat-routes/index.js.map +1 -1
  31. package/dist/chat-store/index.d.ts +18 -4
  32. package/dist/chat-store/index.js +4 -4
  33. package/dist/chat-store/index.js.map +1 -1
  34. package/dist/{chunk-H5FM75MR.js → chunk-22GLESKE.js} +3 -3
  35. package/dist/chunk-22GLESKE.js.map +1 -0
  36. package/dist/{chunk-WEBBJBDH.js → chunk-2DRYTJHI.js} +1 -1
  37. package/dist/chunk-2DRYTJHI.js.map +1 -0
  38. package/dist/{chunk-7EVZUIHW.js → chunk-3EJ6SFJI.js} +1 -1
  39. package/dist/chunk-3EJ6SFJI.js.map +1 -0
  40. package/dist/{chunk-HRJJH3RX.js → chunk-3OFQFW5K.js} +4 -4
  41. package/dist/chunk-3OFQFW5K.js.map +1 -0
  42. package/dist/{chunk-7SUPA2YT.js → chunk-4KKXZQPT.js} +2 -2
  43. package/dist/chunk-4KKXZQPT.js.map +1 -0
  44. package/dist/{chunk-5PTGEJZL.js → chunk-5SD6HT2V.js} +1 -1
  45. package/dist/chunk-5SD6HT2V.js.map +1 -0
  46. package/dist/{chunk-7C64WKAH.js → chunk-5SXS3YAB.js} +2 -2
  47. package/dist/{chunk-L2TG5DBW.js → chunk-5TESA4SN.js} +1 -1
  48. package/dist/chunk-5TESA4SN.js.map +1 -0
  49. package/dist/{chunk-63CE7FEZ.js → chunk-6XIAPIW6.js} +1 -1
  50. package/dist/chunk-6XIAPIW6.js.map +1 -0
  51. package/dist/{chunk-MFRCM32T.js → chunk-7CTIUCQ4.js} +1 -1
  52. package/dist/chunk-7CTIUCQ4.js.map +1 -0
  53. package/dist/{chunk-6KVH5SP5.js → chunk-7YW6EBDX.js} +2 -2
  54. package/dist/chunk-7YW6EBDX.js.map +1 -0
  55. package/dist/{chunk-ZXNXAQAH.js → chunk-AP2UXKUK.js} +1 -1
  56. package/dist/chunk-AP2UXKUK.js.map +1 -0
  57. package/dist/{chunk-K63OWUDJ.js → chunk-BPSV5AA2.js} +2 -2
  58. package/dist/chunk-BPSV5AA2.js.map +1 -0
  59. package/dist/{chunk-MFI4ZM7W.js → chunk-BT4QFCTB.js} +1 -1
  60. package/dist/chunk-BT4QFCTB.js.map +1 -0
  61. package/dist/{chunk-ZYBWGSAZ.js → chunk-BVKQKGRK.js} +1 -1
  62. package/dist/chunk-BVKQKGRK.js.map +1 -0
  63. package/dist/{chunk-RVUISYUE.js → chunk-C3NSB66C.js} +7 -7
  64. package/dist/chunk-C3NSB66C.js.map +1 -0
  65. package/dist/{chunk-BQV42AFK.js → chunk-CCVWR33L.js} +1 -1
  66. package/dist/chunk-CCVWR33L.js.map +1 -0
  67. package/dist/{chunk-MCJSS6SM.js → chunk-CQZSAR77.js} +1 -1
  68. package/dist/chunk-CQZSAR77.js.map +1 -0
  69. package/dist/{chunk-3SVAA3MA.js → chunk-DJ4VJIH5.js} +1 -1
  70. package/dist/chunk-DJ4VJIH5.js.map +1 -0
  71. package/dist/{chunk-XKBIYSSM.js → chunk-DTSPS2HV.js} +3 -3
  72. package/dist/chunk-DTSPS2HV.js.map +1 -0
  73. package/dist/{chunk-4QN75UHX.js → chunk-E7N67FYI.js} +8 -8
  74. package/dist/chunk-E7N67FYI.js.map +1 -0
  75. package/dist/{chunk-2QI7XV2T.js → chunk-FBVLEGEG.js} +1 -1
  76. package/dist/{chunk-2QI7XV2T.js.map → chunk-FBVLEGEG.js.map} +1 -1
  77. package/dist/{chunk-5RMIUJDI.js → chunk-FKCB5FTD.js} +1 -1
  78. package/dist/chunk-FKCB5FTD.js.map +1 -0
  79. package/dist/{chunk-EEPJGZJW.js → chunk-GPBRL2XR.js} +1 -1
  80. package/dist/chunk-GPBRL2XR.js.map +1 -0
  81. package/dist/{chunk-G3HCU7TA.js → chunk-GXE6KHTS.js} +1 -1
  82. package/dist/chunk-GXE6KHTS.js.map +1 -0
  83. package/dist/{chunk-65P3HJY3.js → chunk-HCOROIRT.js} +1 -1
  84. package/dist/chunk-HCOROIRT.js.map +1 -0
  85. package/dist/{chunk-54GSK2KK.js → chunk-HYTIHYNV.js} +2 -2
  86. package/dist/chunk-HYTIHYNV.js.map +1 -0
  87. package/dist/{chunk-5MG74GVQ.js → chunk-IG46XCZM.js} +3 -3
  88. package/dist/chunk-IG46XCZM.js.map +1 -0
  89. package/dist/{chunk-ND3XEGBE.js → chunk-JDEGS53O.js} +1 -1
  90. package/dist/chunk-JDEGS53O.js.map +1 -0
  91. package/dist/{chunk-7W5XSTUF.js → chunk-JML7WKWU.js} +1 -1
  92. package/dist/chunk-JML7WKWU.js.map +1 -0
  93. package/dist/{chunk-Q4TKVF3L.js → chunk-JTLYXUEV.js} +1 -1
  94. package/dist/chunk-JTLYXUEV.js.map +1 -0
  95. package/dist/{chunk-CCRVDLV3.js → chunk-JWBZ74TW.js} +2 -2
  96. package/dist/chunk-JWBZ74TW.js.map +1 -0
  97. package/dist/{chunk-ZU5GNSOJ.js → chunk-K3LIPKFV.js} +3 -3
  98. package/dist/chunk-K3LIPKFV.js.map +1 -0
  99. package/dist/{chunk-GQRL6VNU.js → chunk-LGBO24FL.js} +1 -1
  100. package/dist/chunk-LGBO24FL.js.map +1 -0
  101. package/dist/{chunk-SWUVTGMR.js → chunk-MEUNTJL5.js} +3 -3
  102. package/dist/{chunk-SWUVTGMR.js.map → chunk-MEUNTJL5.js.map} +1 -1
  103. package/dist/{chunk-YNALYIQ3.js → chunk-NLSSFLLS.js} +1 -1
  104. package/dist/chunk-NLSSFLLS.js.map +1 -0
  105. package/dist/{chunk-HFC4BTWJ.js → chunk-PTUMBMVH.js} +1 -1
  106. package/dist/chunk-PTUMBMVH.js.map +1 -0
  107. package/dist/{chunk-R4NOKZMD.js → chunk-ROLFDOMJ.js} +3 -3
  108. package/dist/{chunk-NYATNLRK.js → chunk-RT5RKAFX.js} +1 -1
  109. package/dist/chunk-RT5RKAFX.js.map +1 -0
  110. package/dist/{chunk-GNL3MG5J.js → chunk-S564OFTL.js} +2 -2
  111. package/dist/{chunk-GUSCYE3S.js → chunk-TQOFR6XY.js} +1 -1
  112. package/dist/chunk-TQOFR6XY.js.map +1 -0
  113. package/dist/{chunk-47C6PJCW.js → chunk-TZO3SOUL.js} +1 -1
  114. package/dist/chunk-TZO3SOUL.js.map +1 -0
  115. package/dist/{chunk-YGUNTIT5.js → chunk-UKTYKG57.js} +1 -1
  116. package/dist/chunk-UKTYKG57.js.map +1 -0
  117. package/dist/{chunk-23LUHHHN.js → chunk-VCOD5AOR.js} +1 -1
  118. package/dist/chunk-VCOD5AOR.js.map +1 -0
  119. package/dist/{chunk-5I72FRZY.js → chunk-VOJB7MVG.js} +2 -2
  120. package/dist/{chunk-XWJXZ6WE.js → chunk-VTWKH4YU.js} +2 -2
  121. package/dist/chunk-VTWKH4YU.js.map +1 -0
  122. package/dist/{chunk-4K7BZYO7.js → chunk-VWAEWOWK.js} +3 -3
  123. package/dist/chunk-VWAEWOWK.js.map +1 -0
  124. package/dist/{chunk-M2EBUDZ7.js → chunk-VWOPOLVO.js} +2 -2
  125. package/dist/chunk-VWOPOLVO.js.map +1 -0
  126. package/dist/{chunk-BN2USWIR.js → chunk-VYECQAGM.js} +2 -2
  127. package/dist/chunk-VYECQAGM.js.map +1 -0
  128. package/dist/{chunk-SIXYZ2FB.js → chunk-YJMCRXQQ.js} +1 -1
  129. package/dist/chunk-YJMCRXQQ.js.map +1 -0
  130. package/dist/{chunk-PJC4NXPA.js → chunk-YKBDH2UY.js} +3 -3
  131. package/dist/chunk-YKBDH2UY.js.map +1 -0
  132. package/dist/{chunk-XAWFPMAR.js → chunk-YKOM4ZLQ.js} +1 -1
  133. package/dist/chunk-YKOM4ZLQ.js.map +1 -0
  134. package/dist/{chunk-TKVJE63N.js → chunk-YRMLYFVR.js} +3 -3
  135. package/dist/chunk-YRMLYFVR.js.map +1 -0
  136. package/dist/{chunk-USYXHDKE.js → chunk-YZ6KQULN.js} +2 -2
  137. package/dist/{command-stack-B_-WNfZU.d.ts → command-stack-TNPWJCzW.d.ts} +14 -2
  138. package/dist/{completion-Kaqp_tWk.d.ts → completion-CvcNUz07.d.ts} +1 -1
  139. package/dist/config/index.d.ts +1 -1
  140. package/dist/{contract-KfqJh_au.d.ts → contract-TjB68uqA.d.ts} +17 -0
  141. package/dist/design-canvas/drizzle.d.ts +10 -2
  142. package/dist/design-canvas/drizzle.js.map +1 -1
  143. package/dist/design-canvas/index.d.ts +29 -11
  144. package/dist/design-canvas/index.js +1070 -17
  145. package/dist/design-canvas/index.js.map +1 -1
  146. package/dist/design-canvas-react/engine.d.ts +42 -6
  147. package/dist/design-canvas-react/engine.js +4 -4
  148. package/dist/design-canvas-react/index.d.ts +12 -7
  149. package/dist/design-canvas-react/index.js +11 -11
  150. package/dist/design-canvas-react/index.js.map +1 -1
  151. package/dist/design-canvas-react/lazy.d.ts +4 -4
  152. package/dist/design-canvas-react/lazy.js +1 -1
  153. package/dist/durable-chat/index.d.ts +46 -1
  154. package/dist/durable-chat/index.js +3 -3
  155. package/dist/eval/index.d.ts +1 -1
  156. package/dist/{export-presets-DAsU5Wal.d.ts → export-presets-mgVulRaV.d.ts} +10 -1
  157. package/dist/{flow-types-Cb_AblZs.d.ts → flow-types-CqomVAUN.d.ts} +1 -0
  158. package/dist/harness/index.d.ts +5 -0
  159. package/dist/harness/index.js +1 -1
  160. package/dist/index.d.ts +10 -18
  161. package/dist/index.js +30 -231
  162. package/dist/intakes/api.d.ts +3 -2
  163. package/dist/intakes/api.js +3 -3
  164. package/dist/intakes/api.js.map +1 -1
  165. package/dist/intakes/drizzle.d.ts +10 -2
  166. package/dist/intakes/drizzle.js +3 -3
  167. package/dist/intakes/drizzle.js.map +1 -1
  168. package/dist/intakes/index.d.ts +2 -2
  169. package/dist/intakes/index.js +2 -2
  170. package/dist/intakes-react/index.d.ts +2 -1
  171. package/dist/intakes-react/index.js +2 -2
  172. package/dist/intakes-react/lazy.d.ts +2 -1
  173. package/dist/intakes-react/lazy.js +1 -1
  174. package/dist/intakes-react/lazy.js.map +1 -1
  175. package/dist/integrations/index.d.ts +4 -0
  176. package/dist/integrations/index.js +1 -1
  177. package/dist/interactions/index.d.ts +13 -2
  178. package/dist/interactions/index.js +2 -2
  179. package/dist/{invitations-CZ5G2tIn.d.ts → invitations-DoYMvXea.d.ts} +11 -1
  180. package/dist/{invitations-schema-DaMO4hZE.d.ts → invitations-schema-_fI7HkJP.d.ts} +5 -1
  181. package/dist/knowledge/index.d.ts +2 -0
  182. package/dist/knowledge/index.js +1 -1
  183. package/dist/knowledge-loop/index.d.ts +4 -1
  184. package/dist/knowledge-loop/index.js +1 -1
  185. package/dist/{lazy-C7LiVeFt.d.ts → lazy-DrkVyDpe.d.ts} +2 -2
  186. package/dist/{mcp-BHfIoGLW.d.ts → mcp-BjPqQ-3C.d.ts} +4 -2
  187. package/dist/{mcp-rpc-DLw_r9PQ.d.ts → mcp-rpc-BfUOsalw.d.ts} +3 -0
  188. package/dist/missions/index.d.ts +25 -0
  189. package/dist/missions/index.js +1 -1
  190. package/dist/{model-Bzi5i63l.d.ts → model-C8U0HZxL.d.ts} +1 -0
  191. package/dist/{model-dF2h4xT9.d.ts → model-DmdkIteM.d.ts} +19 -0
  192. package/dist/{model-BBwyOuWG.d.ts → model-DnfO_PdJ.d.ts} +25 -1
  193. package/dist/model-resolution/index.d.ts +10 -0
  194. package/dist/model-resolution/index.js.map +1 -1
  195. package/dist/{operations-DLIvvD00.d.ts → operations-ByJ6yXOW.d.ts} +20 -2
  196. package/dist/{parts-1sRYSPjF.d.ts → parts-n9XUon0a.d.ts} +29 -1
  197. package/dist/plans/index.d.ts +6 -0
  198. package/dist/plans/index.js +1 -1
  199. package/dist/platform/index.d.ts +24 -2
  200. package/dist/platform/index.js +3 -3
  201. package/dist/platform/index.js.map +1 -1
  202. package/dist/preflight/index.d.ts +3 -0
  203. package/dist/preflight/index.js +1 -1
  204. package/dist/preset-cloudflare/index.d.ts +4 -1
  205. package/dist/preset-cloudflare/index.js +2 -2
  206. package/dist/redact/index.d.ts +5 -0
  207. package/dist/redact/index.js +1 -1
  208. package/dist/{roles-BC1n4t37.d.ts → roles-B4nU3jDi.d.ts} +12 -0
  209. package/dist/run/index.d.ts +3 -0
  210. package/dist/run/index.js +1 -1
  211. package/dist/run/index.js.map +1 -1
  212. package/dist/runtime/index.d.ts +11 -4
  213. package/dist/runtime/index.js +4 -4
  214. package/dist/sandbox/index.d.ts +96 -3
  215. package/dist/sandbox/index.js +6 -6
  216. package/dist/{sandbox-terminal-BIIC__CP.d.ts → sandbox-terminal-ChNEdHF8.d.ts} +5 -0
  217. package/dist/sequences/drizzle.d.ts +11 -1
  218. package/dist/sequences/drizzle.js +1 -1
  219. package/dist/sequences/drizzle.js.map +1 -1
  220. package/dist/sequences/index.d.ts +32 -7
  221. package/dist/sequences/index.js +1562 -47
  222. package/dist/sequences/index.js.map +1 -1
  223. package/dist/sequences-react/index.d.ts +32 -2
  224. package/dist/sequences-react/index.js +3 -3
  225. package/dist/sequences-react/index.js.map +1 -1
  226. package/dist/{sso-CNOsARMJ.d.ts → sso-Cm00S61u.d.ts} +13 -0
  227. package/dist/{stale-turn-lock-C8Na1cFZ.d.ts → stale-turn-lock-DucQzvXu.d.ts} +2 -0
  228. package/dist/store/index.d.ts +5 -0
  229. package/dist/store/index.js.map +1 -1
  230. package/dist/{store-gckrNq-g.d.ts → store-B7LLlk9p.d.ts} +22 -1
  231. package/dist/{store-CFyxgTlD.d.ts → store-CqfDtnPQ.d.ts} +8 -2
  232. package/dist/stream/index.d.ts +10 -4
  233. package/dist/stream/index.js +4 -4
  234. package/dist/{stream-normalizer-DWvtmY6F.d.ts → stream-normalizer-C3M--r6y.d.ts} +17 -1
  235. package/dist/studio/index.d.ts +37 -0
  236. package/dist/studio/index.js +1 -1
  237. package/dist/studio-react/index.d.ts +3 -0
  238. package/dist/studio-react/index.js +1 -1
  239. package/dist/studio-react/index.js.map +1 -1
  240. package/dist/tangle/index.d.ts +3 -0
  241. package/dist/tangle/index.js +1 -1
  242. package/dist/teams/drizzle.d.ts +8 -4
  243. package/dist/teams/drizzle.js +1 -1
  244. package/dist/teams/drizzle.js.map +1 -1
  245. package/dist/teams/index.d.ts +4 -2
  246. package/dist/teams/index.js +3 -3
  247. package/dist/teams/invitations-api.d.ts +10 -4
  248. package/dist/teams/invitations-api.js +4 -4
  249. package/dist/teams/invitations-api.js.map +1 -1
  250. package/dist/teams/members-api.d.ts +4 -2
  251. package/dist/teams/members-api.js +3 -3
  252. package/dist/teams/resend.d.ts +5 -4
  253. package/dist/teams/resend.js +1 -1
  254. package/dist/teams/resend.js.map +1 -1
  255. package/dist/teams-react/index.d.ts +7 -2
  256. package/dist/teams-react/index.js +3 -3
  257. package/dist/teams-react/lazy.d.ts +5 -2
  258. package/dist/teams-react/lazy.js +2 -2
  259. package/dist/teams-react/lazy.js.map +1 -1
  260. package/dist/theme/index.d.ts +2 -0
  261. package/dist/theme/index.js +1 -1
  262. package/dist/theme/tailwind-preset.d.ts +1 -0
  263. package/dist/theme/tailwind-preset.js.map +1 -1
  264. package/dist/theme-contract/cli.js +1 -1
  265. package/dist/theme-contract/index.d.ts +3 -0
  266. package/dist/theme-contract/index.js +1 -1
  267. package/dist/tools/index.d.ts +13 -6
  268. package/dist/tools/index.js +3 -3
  269. package/dist/trace/index.d.ts +6 -1
  270. package/dist/trace/index.js +2 -2
  271. package/dist/{turn-buffer-C9mEgoop.d.ts → turn-buffer-DGnAPKwa.d.ts} +6 -0
  272. package/dist/turn-stream/index.d.ts +28 -2
  273. package/dist/turn-stream/index.js +1 -1
  274. package/dist/turn-stream/index.js.map +1 -1
  275. package/dist/{types-BEOvc_ue.d.ts → types-CBRyqijY.d.ts} +10 -0
  276. package/dist/vault/index.d.ts +1 -1
  277. package/dist/vault/lazy.d.ts +3 -2
  278. package/dist/vault/lazy.js.map +1 -1
  279. package/dist/web/index.d.ts +4 -0
  280. package/dist/web/index.js +1 -1
  281. package/dist/web-react/index.d.ts +51 -8
  282. package/dist/web-react/index.js +9 -9
  283. package/dist/web-react/terminal.d.ts +2 -2
  284. package/dist/web-react/terminal.js +1 -1
  285. package/package.json +3 -2
  286. package/dist/DesignCanvas-5DJAFDNC.js +0 -12
  287. package/dist/DesignCanvasEditor-XUJZARSN.js +0 -13
  288. package/dist/IntakeInterview-WHVKMNQW.js +0 -8
  289. package/dist/InvitationsPanel-XUUWZBPV.js +0 -8
  290. package/dist/MembersPanel-FOVHWUQ3.js +0 -8
  291. package/dist/chunk-23LUHHHN.js.map +0 -1
  292. package/dist/chunk-3SVAA3MA.js.map +0 -1
  293. package/dist/chunk-47C6PJCW.js.map +0 -1
  294. package/dist/chunk-4K7BZYO7.js.map +0 -1
  295. package/dist/chunk-4QN75UHX.js.map +0 -1
  296. package/dist/chunk-54GSK2KK.js.map +0 -1
  297. package/dist/chunk-5MG74GVQ.js.map +0 -1
  298. package/dist/chunk-5PTGEJZL.js.map +0 -1
  299. package/dist/chunk-5RMIUJDI.js.map +0 -1
  300. package/dist/chunk-63CE7FEZ.js.map +0 -1
  301. package/dist/chunk-65P3HJY3.js.map +0 -1
  302. package/dist/chunk-6KVH5SP5.js.map +0 -1
  303. package/dist/chunk-7EVZUIHW.js.map +0 -1
  304. package/dist/chunk-7SUPA2YT.js.map +0 -1
  305. package/dist/chunk-7W5XSTUF.js.map +0 -1
  306. package/dist/chunk-BN2USWIR.js.map +0 -1
  307. package/dist/chunk-BQV42AFK.js.map +0 -1
  308. package/dist/chunk-CCRVDLV3.js.map +0 -1
  309. package/dist/chunk-EEPJGZJW.js.map +0 -1
  310. package/dist/chunk-G3HCU7TA.js.map +0 -1
  311. package/dist/chunk-GQRL6VNU.js.map +0 -1
  312. package/dist/chunk-GUSCYE3S.js.map +0 -1
  313. package/dist/chunk-H5FM75MR.js.map +0 -1
  314. package/dist/chunk-HFC4BTWJ.js.map +0 -1
  315. package/dist/chunk-HRJJH3RX.js.map +0 -1
  316. package/dist/chunk-K63OWUDJ.js.map +0 -1
  317. package/dist/chunk-L2TG5DBW.js.map +0 -1
  318. package/dist/chunk-M2EBUDZ7.js.map +0 -1
  319. package/dist/chunk-MCJSS6SM.js.map +0 -1
  320. package/dist/chunk-MFI4ZM7W.js.map +0 -1
  321. package/dist/chunk-MFRCM32T.js.map +0 -1
  322. package/dist/chunk-ND3XEGBE.js.map +0 -1
  323. package/dist/chunk-NEOV2NQ3.js +0 -1617
  324. package/dist/chunk-NEOV2NQ3.js.map +0 -1
  325. package/dist/chunk-NYATNLRK.js.map +0 -1
  326. package/dist/chunk-PJC4NXPA.js.map +0 -1
  327. package/dist/chunk-Q4TKVF3L.js.map +0 -1
  328. package/dist/chunk-RVUISYUE.js.map +0 -1
  329. package/dist/chunk-SIXYZ2FB.js.map +0 -1
  330. package/dist/chunk-TKVJE63N.js.map +0 -1
  331. package/dist/chunk-WEBBJBDH.js.map +0 -1
  332. package/dist/chunk-WFMUDX5J.js +0 -1092
  333. package/dist/chunk-WFMUDX5J.js.map +0 -1
  334. package/dist/chunk-XAWFPMAR.js.map +0 -1
  335. package/dist/chunk-XKBIYSSM.js.map +0 -1
  336. package/dist/chunk-XWJXZ6WE.js.map +0 -1
  337. package/dist/chunk-YGUNTIT5.js.map +0 -1
  338. package/dist/chunk-YNALYIQ3.js.map +0 -1
  339. package/dist/chunk-ZU5GNSOJ.js.map +0 -1
  340. package/dist/chunk-ZXNXAQAH.js.map +0 -1
  341. package/dist/chunk-ZYBWGSAZ.js.map +0 -1
  342. /package/dist/{DesignCanvas-5DJAFDNC.js.map → DesignCanvas-UNL34LS2.js.map} +0 -0
  343. /package/dist/{DesignCanvasEditor-XUJZARSN.js.map → DesignCanvasEditor-FJIVYOA2.js.map} +0 -0
  344. /package/dist/{IntakeInterview-WHVKMNQW.js.map → IntakeInterview-3ZIQMZS6.js.map} +0 -0
  345. /package/dist/{InvitationsPanel-XUUWZBPV.js.map → InvitationsPanel-CJ7DR4F7.js.map} +0 -0
  346. /package/dist/{MembersPanel-FOVHWUQ3.js.map → MembersPanel-BB4OD2KB.js.map} +0 -0
  347. /package/dist/{TimelineEditor-I35SJJAJ.js.map → TimelineEditor-2ECKSU6P.js.map} +0 -0
  348. /package/dist/{chunk-7C64WKAH.js.map → chunk-5SXS3YAB.js.map} +0 -0
  349. /package/dist/{chunk-R4NOKZMD.js.map → chunk-ROLFDOMJ.js.map} +0 -0
  350. /package/dist/{chunk-GNL3MG5J.js.map → chunk-S564OFTL.js.map} +0 -0
  351. /package/dist/{chunk-5I72FRZY.js.map → chunk-VOJB7MVG.js.map} +0 -0
  352. /package/dist/{chunk-USYXHDKE.js.map → chunk-YZ6KQULN.js.map} +0 -0
@@ -7,14 +7,14 @@ import {
7
7
  parseInteractionCancel,
8
8
  parseInteractionRequest,
9
9
  questionInteractionContentSignature
10
- } from "./chunk-XAWFPMAR.js";
10
+ } from "./chunk-YKOM4ZLQ.js";
11
11
  import {
12
12
  canTransitionPlanStatus,
13
13
  parsePlanSubmittedEvent,
14
14
  persistedPartToPlan,
15
15
  planFollowUpTurnId,
16
16
  planToPersistedPart
17
- } from "./chunk-SIXYZ2FB.js";
17
+ } from "./chunk-YJMCRXQQ.js";
18
18
 
19
19
  // src/durable-chat/errors.ts
20
20
  var DurableChatError = class extends Error {
@@ -917,4 +917,4 @@ export {
917
917
  createDurableInteractionRoutePersistence,
918
918
  createDurablePlanRoutes
919
919
  };
920
- //# sourceMappingURL=chunk-ZU5GNSOJ.js.map
920
+ //# sourceMappingURL=chunk-K3LIPKFV.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/durable-chat/errors.ts","../src/durable-chat/types.ts","../src/durable-chat/memory.ts","../src/durable-chat/interactions.ts","../src/durable-chat/adapters.ts","../src/durable-chat/plan-routes.ts"],"sourcesContent":["/** Define error codes representing possible Durable Chat failure scenarios */\nexport type DurableChatErrorCode =\n | 'DURABLE_CHAT_BAD_REQUEST'\n | 'DURABLE_CHAT_UNAUTHORIZED'\n | 'DURABLE_CHAT_CONFLICT'\n | 'DURABLE_CHAT_UNAVAILABLE'\n | 'DURABLE_CHAT_GONE'\n | 'DURABLE_CHAT_NOT_FOUND'\n\n/** Typed, fail-loud errors for adapters and route seams. */\nexport class DurableChatError extends Error {\n readonly code: DurableChatErrorCode\n readonly status: number\n readonly details?: unknown\n\n constructor(code: DurableChatErrorCode, message: string, status: number, details?: unknown) {\n super(message)\n this.name = 'DurableChatError'\n this.code = code\n this.status = status\n this.details = details\n }\n}\n\n/** Represent conflict errors occurring in durable chat state management */\nexport class DurableChatConflictError extends DurableChatError {\n constructor(message = 'durable chat state conflict', details?: unknown) {\n super('DURABLE_CHAT_CONFLICT', message, 409, details)\n this.name = 'DurableChatConflictError'\n }\n}\n\n/** Represent unavailable durable chat authority errors with status code 503 */\nexport class DurableChatUnavailableError extends DurableChatError {\n constructor(message = 'durable chat authority unavailable', details?: unknown) {\n super('DURABLE_CHAT_UNAVAILABLE', message, 503, details)\n this.name = 'DurableChatUnavailableError'\n }\n}\n\n/** Represent durable chat errors indicating the chat plan is no longer available */\nexport class DurableChatGoneError extends DurableChatError {\n constructor(message = 'durable chat plan is gone', details?: unknown) {\n super('DURABLE_CHAT_GONE', message, 410, details)\n this.name = 'DurableChatGoneError'\n }\n}\n","import type {\n ChatInteraction,\n ChatInteractionField,\n ChatInteractionStatus,\n InteractionAnswerValue,\n InteractionAnswers,\n} from '../interactions/contract'\nimport type { ChatPlan, ChatPlanStatus } from '../plans/index'\n\n/** An authorization-derived tenant/thread scope. Consumers should only\n * create this value after authenticating the request; the route never accepts\n * an identity or scope from the request body. */\nexport type DurableChatScope = string & { readonly __durableChatScope: unique symbol }\n\n/** Create a durable chat scope from a non-empty string value */\nexport function createDurableChatScope(value: string): DurableChatScope {\n if (typeof value !== 'string' || value.trim() === '') throw new TypeError('durable chat scope must be a non-empty string')\n return value as DurableChatScope\n}\n\n/** Resolve a valid durable chat scope key from the given scope input */\nexport function durableChatScopeKey(scope: DurableChatScope): string {\n if (typeof scope !== 'string' || scope.length === 0) throw new TypeError('durable chat scope is required')\n return scope\n}\n\n/** Represent durable plan outcomes as either approved or rejected */\nexport type DurablePlanDecision = 'approved' | 'rejected'\n/** Resolve durable plan authority decisions including approval, rejection, or predefined durable decisions */\nexport type DurablePlanAuthorityDecision = DurablePlanDecision | 'approve' | 'reject'\n\n/** Projection retained by a durable store. It is intentionally compatible\n * with the browser `/plans` projection and adds no product-specific fields. */\nexport type DurablePlanProjection = ChatPlan & {\n metadata?: Record<string, unknown>\n decidedBy?: string\n}\n\n/** Represent a unique identifier key for durable plan commands */\nexport type DurablePlanCommandKey = string\n\n/** Define possible states for a durable plan command in its lifecycle */\nexport type DurablePlanCommandState =\n | 'claimed'\n | 'authority_committed'\n | 'finalized'\n | 'conflicted'\n\n/** Define the structure for recording durable plan commands with associated metadata and state information */\nexport interface DurablePlanCommandRecord {\n scope: DurableChatScope\n planId: string\n revision: number\n decision: DurablePlanDecision\n commandKey: DurablePlanCommandKey\n authorityIdempotencyKey: string\n state: DurablePlanCommandState\n claimedAt: string\n authorityResult?: DurablePlanAuthorityResult\n receipt?: DurableFollowUpReceipt\n conflict?: string\n}\n\n/** Represent the current authoritative state and optional receipt of a durable plan authority */\nexport interface DurablePlanAuthorityCurrentResult {\n /** Authoritative state. `null` means the authority has forgotten the plan. */\n plan: DurablePlanProjection | null\n receipt?: DurableFollowUpReceipt\n}\n\n/** Define a durable receipt capturing stable identifiers and state for follow-up decisions */\nexport interface DurableFollowUpReceipt {\n /** Stable for a scope + plan + revision + decision. */\n receiptId: string\n planId: string\n revision: number\n decision: DurablePlanDecision\n turnId: string\n state: string\n /** Authority's stable idempotency key, useful when reconciling. */\n authorityIdempotencyKey: string\n}\n\n/** Describe the outcome of an authority's durable plan decision including follow-up and metadata */\nexport interface DurablePlanAuthorityResult {\n /** Authority's final plan projection. */\n plan: DurablePlanProjection\n /** Sandbox-style follow-up result. */\n followUp: { turnId: string; state: string }\n /** True when the authority served a previously committed decision. */\n idempotent?: boolean\n /** Stable authority operation id, if the provider has one. */\n authorityId?: string\n receipt?: DurableFollowUpReceipt\n}\n\n/** Structural port to Sandbox (or another durable plan authority). */\nexport interface DurablePlanAuthority {\n current(args: {\n scope: DurableChatScope\n planId: string\n revision?: number\n }): Promise<DurablePlanAuthorityCurrentResult | DurablePlanProjection | null>\n decide(args: {\n scope: DurableChatScope\n planId: string\n revision: number\n decision: DurablePlanDecision\n feedback?: string\n idempotencyKey: string\n }): Promise<DurablePlanAuthorityResult>\n}\n\n/** Define the structure for recording the state and metadata of a durable plan effect */\nexport interface DurablePlanEffectRecord {\n effectKey: string\n scope: DurableChatScope\n planId: string\n revision: number\n decision: DurablePlanDecision\n state: 'claimed' | 'completed' | 'error'\n claimedAt: string\n completedAt?: string\n error?: string\n}\n\n/** Manage durable storage and retrieval of plan projections, commands, and effects within a scoped context */\nexport interface DurablePlanStore {\n getPlanProjection(scope: DurableChatScope, planId: string, revision?: number): Promise<DurablePlanProjection | null>\n putPlanProjection(scope: DurableChatScope, projection: DurablePlanProjection): Promise<void>\n listPlanProjections?(scope: DurableChatScope, planId?: string): Promise<DurablePlanProjection[]>\n getPlanCommand(scope: DurableChatScope, commandKey: DurablePlanCommandKey): Promise<DurablePlanCommandRecord | null>\n claimPlanCommand(scope: DurableChatScope, command: DurablePlanCommandRecord): Promise<\n | { status: 'claimed'; record: DurablePlanCommandRecord }\n | { status: 'existing'; record: DurablePlanCommandRecord }\n | { status: 'conflict'; record?: DurablePlanCommandRecord; reason: string }\n >\n recordPlanAuthorityResult(scope: DurableChatScope, commandKey: DurablePlanCommandKey, result: DurablePlanAuthorityResult, receipt: DurableFollowUpReceipt): Promise<void>\n finalizePlanCommand(scope: DurableChatScope, commandKey: DurablePlanCommandKey): Promise<void>\n getPlanEffect(scope: DurableChatScope, effectKey: string): Promise<DurablePlanEffectRecord | null>\n claimPlanEffect(scope: DurableChatScope, effect: DurablePlanEffectRecord): Promise<\n | { status: 'claimed'; record: DurablePlanEffectRecord }\n | { status: 'existing'; record: DurablePlanEffectRecord }\n >\n completePlanEffect(scope: DurableChatScope, effectKey: string): Promise<void>\n failPlanEffect(scope: DurableChatScope, effectKey: string, error: string): Promise<void>\n\n getInteractionProjection(scope: DurableChatScope, interactionId: string): Promise<DurableInteractionProjection | null>\n upsertInteractionProjection(scope: DurableChatScope, projection: DurableInteractionProjection): Promise<DurableInteractionProjection>\n listInteractionProjections?(scope: DurableChatScope): Promise<DurableInteractionProjection[]>\n getAnswerIntent(scope: DurableChatScope, intentKey: string): Promise<DurableAnswerIntentRecord | null>\n claimAnswerIntent(scope: DurableChatScope, intent: DurableAnswerIntentRecord): Promise<\n | { status: 'claimed'; record: DurableAnswerIntentRecord }\n | { status: 'existing'; record: DurableAnswerIntentRecord }\n | { status: 'conflict'; record?: DurableAnswerIntentRecord; reason: string }\n >\n acknowledgeAnswerIntent(scope: DurableChatScope, intentKey: string, acknowledgement: DurableInteractionAcknowledgement): Promise<void>\n /** Atomically settle the interaction projection (including semantic aliases)\n * from the acknowledged intent and mark the intent finalized. */\n finalizeAnswerIntent(scope: DurableChatScope, intentKey: string, guarantee?: DurableInteractionGuarantee): Promise<void>\n abortAnswerIntent(scope: DurableChatScope, intentKey: string, error: string): Promise<void>\n}\n\n/** Alias used by adapters that store all durable chat state in one port. */\nexport type DurableChatStateStore = DurablePlanStore\n/** Represent durable storage for plan state management with persistence and reliability guarantees */\nexport type DurablePlanStateStore = DurablePlanStore\n/** Pick essential methods to manage and record durable plan command operations */\nexport type DurablePlanCommandJournal = Pick<DurablePlanStore, 'getPlanCommand' | 'claimPlanCommand' | 'recordPlanAuthorityResult' | 'finalizePlanCommand'>\n/** Provide durable methods to manage the lifecycle of answer intents in a plan store */\nexport type DurableAnswerIntentJournal = Pick<DurablePlanStore, 'getAnswerIntent' | 'claimAnswerIntent' | 'acknowledgeAnswerIntent' | 'finalizeAnswerIntent' | 'abortAnswerIntent'>\n\n/** Define a durable chat interaction projection with idempotent event tracking and optional tombstone flag */\nexport interface DurableInteractionProjection extends ChatInteraction {\n /** Sequence/event identity used to make ask replays idempotent. */\n eventId?: string\n semanticKey?: string\n /** A cancel-before-ask row is a terminal tombstone. */\n tombstone?: boolean\n updatedAt?: string\n}\n\n/** Define possible states for a durable answer intent lifecycle */\nexport type DurableAnswerIntentState = 'prepared' | 'acknowledged' | 'finalized' | 'aborted'\n\n/** Define the structure for recording durable answer intent details and their states */\nexport interface DurableAnswerIntentRecord {\n scope: DurableChatScope\n interactionId: string\n attemptKey: string\n intentKey: string\n outcome: 'accepted' | 'declined'\n data?: Record<string, InteractionAnswerValue>\n state: DurableAnswerIntentState\n guarantee?: DurableInteractionGuarantee\n acknowledgement?: DurableInteractionAcknowledgement\n createdAt: string\n finalizedAt?: string\n error?: string\n}\n\n/** Represent durable acknowledgement of an interaction with optional authority, status, and timestamp fields */\nexport interface DurableInteractionAcknowledgement {\n acknowledged: true\n authorityId?: string\n status?: string\n at?: string\n}\n\n/** Define interaction durability levels to specify reconciliation or best-effort guarantees */\nexport type DurableInteractionGuarantee = 'reconciled' | 'best-effort'\n\n/** Define options for durable interaction settlement including attempt key, guarantee, and timestamp provider */\nexport interface DurableInteractionSettlementOptions {\n /** Caller-created and stable across retries/reconnects. */\n attemptKey: string\n guarantee?: DurableInteractionGuarantee\n now?: () => string\n}\n\n/** Manage durable interaction lifecycles by preparing, acknowledging, finalizing, aborting, and reconciling intents */\nexport interface DurableInteractionSettlement {\n prepare(scope: DurableChatScope, interactionId: string, outcome: 'accepted' | 'declined', data?: Record<string, InteractionAnswerValue>): Promise<DurableAnswerIntentRecord>\n acknowledge(scope: DurableChatScope, intentKey: string, acknowledgement?: Omit<DurableInteractionAcknowledgement, 'acknowledged'>): Promise<DurableAnswerIntentRecord>\n finalize(scope: DurableChatScope, intentKey: string): Promise<DurableAnswerIntentRecord>\n abort(scope: DurableChatScope, intentKey: string, error: string): Promise<DurableAnswerIntentRecord>\n reconcile(scope: DurableChatScope, intentKey: string): Promise<DurableAnswerIntentRecord | null>\n}\n\n/** Normalize input value to a standardized DurablePlanDecision or return null for invalid inputs */\nexport function normalizePlanDecision(value: unknown): DurablePlanDecision | null {\n if (value === 'approved' || value === 'approve') return 'approved'\n if (value === 'rejected' || value === 'reject') return 'rejected'\n return null\n}\n\n/** Generate a unique key string for a plan command using plan ID, revision, and decision */\nexport function planCommandKey(planId: string, revision: number, decision: DurablePlanDecision): string {\n return `plan:${encodeURIComponent(planId)}:${revision}:${decision}`\n}\n\n/** Generate a unique idempotency key for a plan authority based on scope, plan, revision, and decision */\nexport function planAuthorityIdempotencyKey(scope: DurableChatScope, planId: string, revision: number, decision: DurablePlanDecision): string {\n return `durable-plan:${encodeURIComponent(durableChatScopeKey(scope))}:${encodeURIComponent(planId)}:${revision}:${decision}`\n}\n\n/** Generate a unique string key representing the effect of a plan decision within a given scope and revision */\nexport function planEffectKey(scope: DurableChatScope, planId: string, revision: number, decision: DurablePlanDecision): string {\n return `after-decision:${encodeURIComponent(durableChatScopeKey(scope))}:${encodeURIComponent(planId)}:${revision}:${decision}`\n}\n\n/** Resolve a durable follow-up receipt ensuring idempotency for a given plan decision and revision */\nexport function stablePlanReceipt(\n scope: DurableChatScope,\n planId: string,\n revision: number,\n decision: DurablePlanDecision,\n result: Pick<DurablePlanAuthorityResult, 'followUp'>,\n): DurableFollowUpReceipt {\n const authorityIdempotencyKey = planAuthorityIdempotencyKey(scope, planId, revision, decision)\n return {\n receiptId: `receipt:${authorityIdempotencyKey}`,\n planId,\n revision,\n decision,\n turnId: result.followUp.turnId,\n state: result.followUp.state,\n authorityIdempotencyKey,\n }\n}\n","import {\n durableChatScopeKey,\n type DurableAnswerIntentRecord,\n type DurableChatScope,\n type DurableInteractionProjection,\n type DurablePlanAuthorityResult,\n type DurablePlanCommandRecord,\n type DurablePlanCommandKey,\n type DurablePlanEffectRecord,\n type DurablePlanProjection,\n type DurablePlanStore,\n} from './types'\nimport { DurableChatConflictError } from './errors'\nimport { canTransitionPlanStatus } from '../plans/index'\n\n/**\n * Reference adapter for tests and local development. It is intentionally\n * process-local and non-production: there is no locking across processes,\n * transaction, or crash recovery. Production adapters should implement the\n * same port with a database/Workflow primitive and CAS at every claim.\n */\nexport class InMemoryDurableChatStateStore implements DurablePlanStore {\n private readonly plans = new Map<string, DurablePlanProjection>()\n private readonly currentPlans = new Map<string, string>()\n private readonly commands = new Map<string, DurablePlanCommandRecord>()\n private readonly effects = new Map<string, DurablePlanEffectRecord>()\n private readonly interactions = new Map<string, DurableInteractionProjection>()\n private readonly interactionSemantic = new Map<string, string>()\n /** Duplicate event ids point at the canonical semantic interaction so all\n * duplicate asks settle through one terminal row/attempt. */\n private readonly interactionAliases = new Map<string, string>()\n private readonly answerIntents = new Map<string, DurableAnswerIntentRecord>()\n\n private scopePrefix(scope: DurableChatScope): string {\n return `${encodeURIComponent(durableChatScopeKey(scope))}\\u0000`\n }\n private scopedKey(scope: DurableChatScope, ...parts: Array<string | number>): string {\n return `${this.scopePrefix(scope)}${parts.map((part) => encodeURIComponent(String(part))).join('\\u0000')}`\n }\n private planKey(scope: DurableChatScope, planId: string, revision: number): string {\n return this.scopedKey(scope, planId, revision)\n }\n private currentKey(scope: DurableChatScope, planId: string): string {\n return this.scopedKey(scope, planId)\n }\n private commandKey(scope: DurableChatScope, key: string): string {\n return this.scopedKey(scope, key)\n }\n private interactionKey(scope: DurableChatScope, id: string): string {\n return this.scopedKey(scope, id)\n }\n private intentKey(scope: DurableChatScope, key: string): string {\n return this.scopedKey(scope, key)\n }\n private effectKey(scope: DurableChatScope, key: string): string {\n return this.scopedKey(scope, key)\n }\n\n async getPlanProjection(scope: DurableChatScope, planId: string, revision?: number): Promise<DurablePlanProjection | null> {\n const current = revision === undefined ? this.currentPlans.get(this.currentKey(scope, planId)) : undefined\n const key = revision === undefined\n ? current\n : this.planKey(scope, planId, revision)\n return key ? this.plans.get(key) ?? null : null\n }\n\n async listPlanProjections(scope: DurableChatScope, planId?: string): Promise<DurablePlanProjection[]> {\n const prefix = this.scopePrefix(scope)\n return [...this.plans.entries()]\n .filter(([key, projection]) => key.startsWith(prefix) && (!planId || projection.planId === planId))\n .map(([, projection]) => projection)\n .sort((a, b) => a.revision - b.revision)\n }\n\n async putPlanProjection(scope: DurableChatScope, projection: DurablePlanProjection): Promise<void> {\n if (!projection.planId || !Number.isInteger(projection.revision) || projection.revision < 1) {\n throw new TypeError('plan projection requires planId and positive integer revision')\n }\n const key = this.planKey(scope, projection.planId, projection.revision)\n const prior = this.plans.get(key)\n if (prior && JSON.stringify(prior) !== JSON.stringify(projection)) {\n if (\n prior.body !== projection.body ||\n prior.title !== projection.title ||\n prior.submittedAt !== projection.submittedAt\n ) {\n throw new DurableChatConflictError('plan content changed without a new revision')\n }\n if (prior.status === projection.status && !['preparing', 'pending'].includes(prior.status)) {\n throw new DurableChatConflictError('terminal plan projection cannot be rewritten')\n }\n if (!canTransitionPlanStatus(prior.status, projection.status)) {\n throw new DurableChatConflictError('conflicting plan projection for the same revision')\n }\n }\n this.plans.set(key, projection)\n const currentKey = this.currentKey(scope, projection.planId)\n const currentKeyValue = this.currentPlans.get(currentKey)\n const current = currentKeyValue ? this.plans.get(currentKeyValue) : undefined\n if (!current || projection.revision > current.revision) this.currentPlans.set(currentKey, key)\n }\n\n async getPlanCommand(scope: DurableChatScope, commandKey: DurablePlanCommandKey): Promise<DurablePlanCommandRecord | null> {\n return this.commands.get(this.commandKey(scope, commandKey)) ?? null\n }\n\n async claimPlanCommand(scope: DurableChatScope, command: DurablePlanCommandRecord) {\n const key = this.commandKey(scope, command.commandKey)\n const existing = this.commands.get(key)\n if (!existing) {\n const prefix = this.scopePrefix(scope)\n const competing = [...this.commands.entries()].find(([storedKey, candidate]) =>\n storedKey.startsWith(prefix) && candidate.planId === command.planId &&\n candidate.revision === command.revision && candidate.decision !== command.decision,\n )\n if (competing) {\n return { status: 'conflict' as const, record: competing[1], reason: 'competing decision for plan revision' }\n }\n this.commands.set(key, command)\n return { status: 'claimed' as const, record: command }\n }\n if (\n existing.planId === command.planId && existing.revision === command.revision &&\n existing.decision === command.decision\n ) return { status: 'existing' as const, record: existing }\n return { status: 'conflict' as const, record: existing, reason: 'command key is already used by another decision' }\n }\n\n async recordPlanAuthorityResult(scope: DurableChatScope, commandKey: string, result: DurablePlanAuthorityResult, receipt: DurablePlanCommandRecord['receipt']): Promise<void> {\n const key = this.commandKey(scope, commandKey)\n const command = this.commands.get(key)\n if (!command) throw new DurableChatConflictError('cannot record authority result before claiming command')\n command.authorityResult = result\n command.receipt = receipt\n command.state = 'authority_committed'\n }\n\n async finalizePlanCommand(scope: DurableChatScope, commandKey: string): Promise<void> {\n const command = this.commands.get(this.commandKey(scope, commandKey))\n if (!command) throw new DurableChatConflictError('cannot finalize unknown plan command')\n command.state = 'finalized'\n }\n\n async getPlanEffect(scope: DurableChatScope, effectKey: string): Promise<DurablePlanEffectRecord | null> {\n return this.effects.get(this.effectKey(scope, effectKey)) ?? null\n }\n async claimPlanEffect(scope: DurableChatScope, effect: DurablePlanEffectRecord) {\n const key = this.effectKey(scope, effect.effectKey)\n const existing = this.effects.get(key)\n if (existing) return { status: 'existing' as const, record: existing }\n this.effects.set(key, effect)\n return { status: 'claimed' as const, record: effect }\n }\n async completePlanEffect(scope: DurableChatScope, effectKey: string): Promise<void> {\n const effect = this.effects.get(this.effectKey(scope, effectKey))\n if (!effect) throw new DurableChatConflictError('cannot complete unknown plan effect')\n effect.state = 'completed'\n effect.completedAt = new Date().toISOString()\n }\n async failPlanEffect(scope: DurableChatScope, effectKey: string, error: string): Promise<void> {\n const effect = this.effects.get(this.effectKey(scope, effectKey))\n if (!effect) throw new DurableChatConflictError('cannot fail unknown plan effect')\n effect.state = 'error'\n effect.error = error\n }\n\n async getInteractionProjection(scope: DurableChatScope, interactionId: string): Promise<DurableInteractionProjection | null> {\n const directKey = this.interactionKey(scope, interactionId)\n const alias = this.interactionAliases.get(directKey)\n return this.interactions.get(alias ?? directKey) ?? null\n }\n\n async listInteractionProjections(scope: DurableChatScope): Promise<DurableInteractionProjection[]> {\n const prefix = this.scopePrefix(scope)\n return [...this.interactions.entries()]\n .filter(([key]) => key.startsWith(prefix))\n .map(([, value]) => value)\n }\n\n async upsertInteractionProjection(scope: DurableChatScope, projection: DurableInteractionProjection): Promise<DurableInteractionProjection> {\n if (!projection.id) throw new TypeError('interaction projection requires id')\n const key = this.interactionKey(scope, projection.id)\n const prior = this.interactions.get(key)\n const resolvedPrior = prior ?? (() => {\n const alias = this.interactionAliases.get(key)\n return alias ? this.interactions.get(alias) : undefined\n })()\n if (!prior && resolvedPrior) {\n this.interactionAliases.set(key, this.interactionKey(scope, resolvedPrior.id))\n }\n if (resolvedPrior) {\n if (projection.eventId && resolvedPrior.eventId === projection.eventId) return resolvedPrior\n if (resolvedPrior.status !== 'pending') {\n if (\n resolvedPrior.tombstone && resolvedPrior.kind === 'unknown' &&\n projection.status === resolvedPrior.status\n ) {\n const enriched = {\n ...projection,\n id: resolvedPrior.id,\n status: resolvedPrior.status,\n tombstone: true,\n ...(resolvedPrior.cancelReason ? { cancelReason: resolvedPrior.cancelReason } : {}),\n }\n this.interactions.set(this.interactionKey(scope, resolvedPrior.id), enriched)\n return enriched\n }\n if (resolvedPrior.status === projection.status && JSON.stringify(resolvedPrior.answers) === JSON.stringify(projection.answers)) return resolvedPrior\n throw new DurableChatConflictError('interaction already has a conflicting terminal outcome')\n }\n // A terminal event wins over pending. A second terminal event is caught\n // above; this is the accepted-answer/cancel ordering rule.\n if (projection.status !== 'pending') {\n const canonical = resolvedPrior.id === projection.id ? projection : { ...projection, id: resolvedPrior.id }\n this.interactions.set(this.interactionKey(scope, canonical.id), canonical)\n if (resolvedPrior.semanticKey) {\n this.interactionSemantic.delete(this.scopedKey(scope, resolvedPrior.semanticKey))\n }\n return canonical\n }\n return resolvedPrior\n }\n if (projection.semanticKey) {\n const semantic = this.scopedKey(scope, projection.semanticKey)\n const priorId = this.interactionSemantic.get(semantic)\n if (priorId) {\n const canonicalKey = this.interactionKey(scope, priorId)\n this.interactionAliases.set(this.interactionKey(scope, projection.id), canonicalKey)\n return this.interactions.get(canonicalKey) ?? projection\n }\n this.interactionSemantic.set(semantic, projection.id)\n }\n this.interactions.set(key, projection)\n return projection\n }\n\n async getAnswerIntent(scope: DurableChatScope, intentKey: string): Promise<DurableAnswerIntentRecord | null> {\n return this.answerIntents.get(this.intentKey(scope, intentKey)) ?? null\n }\n async claimAnswerIntent(scope: DurableChatScope, intent: DurableAnswerIntentRecord) {\n const key = this.intentKey(scope, intent.intentKey)\n const existing = this.answerIntents.get(key)\n if (!existing) {\n this.answerIntents.set(key, intent)\n return { status: 'claimed' as const, record: intent }\n }\n if (existing.interactionId === intent.interactionId && existing.attemptKey === intent.attemptKey && existing.outcome === intent.outcome && JSON.stringify(existing.data) === JSON.stringify(intent.data)) {\n return { status: 'existing' as const, record: existing }\n }\n return { status: 'conflict' as const, record: existing, reason: 'answer intent key is already used by another answer' }\n }\n async acknowledgeAnswerIntent(scope: DurableChatScope, intentKey: string, acknowledgement: DurableAnswerIntentRecord['acknowledgement']): Promise<void> {\n const intent = this.answerIntents.get(this.intentKey(scope, intentKey))\n if (!intent) throw new DurableChatConflictError('cannot acknowledge unknown answer intent')\n if (intent.state === 'finalized') return\n intent.acknowledgement = acknowledgement\n intent.state = 'acknowledged'\n }\n async finalizeAnswerIntent(scope: DurableChatScope, intentKey: string, guarantee: DurableAnswerIntentRecord['guarantee'] = 'reconciled'): Promise<void> {\n const intent = this.answerIntents.get(this.intentKey(scope, intentKey))\n if (!intent) throw new DurableChatConflictError('cannot finalize unknown answer intent')\n if (intent.state === 'finalized') return\n if (!intent.acknowledgement?.acknowledged) {\n throw new DurableChatConflictError('cannot finalize an answer before authority acknowledgement')\n }\n const projection = await this.getInteractionProjection(scope, intent.interactionId)\n if (!projection) throw new DurableChatConflictError('cannot finalize an answer before its ask projection')\n const status = intent.outcome === 'accepted' ? 'answered' : 'declined'\n await this.upsertInteractionProjection(scope, {\n ...projection,\n status,\n ...(intent.data ? { answers: intent.data } : {}),\n updatedAt: intent.acknowledgement.at ?? new Date().toISOString(),\n })\n intent.state = 'finalized'\n intent.guarantee = guarantee\n intent.finalizedAt = new Date().toISOString()\n }\n async abortAnswerIntent(scope: DurableChatScope, intentKey: string, error: string): Promise<void> {\n const intent = this.answerIntents.get(this.intentKey(scope, intentKey))\n if (!intent) throw new DurableChatConflictError('cannot abort unknown answer intent')\n if (intent.state === 'finalized') return\n intent.state = 'aborted'\n intent.error = error\n }\n}\n\n/** Short aliases retained for adapter authors who call this a durable chat\n * store rather than a state store. Both names refer to the same non-production\n * reference implementation. */\nexport const InMemoryDurableChatStore = InMemoryDurableChatStateStore\n/** Create an in-memory durable chat state store for managing chat session data efficiently */\nexport function createInMemoryDurableChatStateStore(): InMemoryDurableChatStateStore {\n return new InMemoryDurableChatStateStore()\n}\n","import {\n cancelStatusFor,\n interactionFromWireRequest,\n isSafeInteractionFieldKey,\n parseInteractionAnswers,\n questionInteractionContentSignature,\n type InteractionAnswerValue,\n type InteractionAnswers,\n type InteractionRequestWire,\n} from '../interactions/contract'\nimport { DurableChatConflictError } from './errors'\nimport type {\n DurableAnswerIntentRecord,\n DurableChatScope,\n DurableInteractionAcknowledgement,\n DurableInteractionGuarantee,\n DurableInteractionProjection,\n DurableInteractionSettlement,\n DurableInteractionSettlementOptions,\n DurablePlanStore,\n} from './types'\n\nfunction nowIso(now?: () => string): string {\n return (now ?? (() => new Date().toISOString()))()\n}\n\nfunction intentKey(scope: DurableChatScope, interactionId: string, attemptKey: string): string {\n return `interaction-answer:${encodeURIComponent(scope)}:${encodeURIComponent(interactionId)}:${encodeURIComponent(attemptKey)}`\n}\n\nfunction ensureAttemptKey(attemptKey: string): void {\n if (!attemptKey || typeof attemptKey !== 'string' || attemptKey.length > 512) throw new TypeError('attemptKey must be a non-empty string')\n}\n\nfunction safeAnswers(data: Record<string, InteractionAnswerValue> | undefined): InteractionAnswers | undefined {\n if (data === undefined) return undefined\n for (const key of Object.keys(data)) {\n if (!isSafeInteractionFieldKey(key)) throw new TypeError(`unsafe interaction answer key: ${key}`)\n }\n const parsed = parseInteractionAnswers(data)\n if (!parsed.succeeded) throw new TypeError(parsed.error)\n return parsed.value\n}\n\n/** Apply an ask event. Event ids and semantic signatures make replays safe;\n * a prior cancel creates a tombstone and cannot be resurrected by a late ask. */\nexport async function upsertDurableInteractionAsk(\n store: DurablePlanStore,\n scope: DurableChatScope,\n request: InteractionRequestWire,\n options: { eventId?: string; semanticKey?: string; now?: () => string } = {},\n): Promise<DurableInteractionProjection> {\n const semanticKey = options.semanticKey ?? questionInteractionContentSignature(interactionFromWireRequest(request)) ?? undefined\n const incoming: DurableInteractionProjection = {\n ...interactionFromWireRequest(request),\n ...(options.eventId ? { eventId: options.eventId } : {}),\n ...(semanticKey ? { semanticKey } : {}),\n updatedAt: nowIso(options.now),\n }\n const prior = await store.getInteractionProjection(scope, request.id)\n if (prior?.tombstone) {\n return store.upsertInteractionProjection(scope, {\n ...incoming,\n status: prior.status,\n tombstone: true,\n ...(prior.cancelReason ? { cancelReason: prior.cancelReason } : {}),\n })\n }\n if (prior && prior.status !== 'pending') return prior\n return store.upsertInteractionProjection(scope, incoming)\n}\n\n/** Apply a cancel event. It is valid before the ask arrives and leaves a\n * terminal tombstone so a delayed ask cannot re-open the card. */\nexport async function recordDurableInteractionCancel(\n store: DurablePlanStore,\n scope: DurableChatScope,\n interactionId: string,\n reason?: string,\n options: { eventId?: string; now?: () => string } = {},\n): Promise<DurableInteractionProjection> {\n if (!interactionId) throw new TypeError('interaction id is required')\n const status = cancelStatusFor(reason)\n const prior = await store.getInteractionProjection(scope, interactionId)\n if (prior) {\n if (prior.status === status) return prior\n if (prior.status !== 'pending') throw new DurableChatConflictError('interaction already has a conflicting terminal outcome')\n return store.upsertInteractionProjection(scope, {\n ...prior, status, tombstone: true, ...(reason ? { cancelReason: reason } : {}),\n ...(options.eventId ? { eventId: options.eventId } : {}), updatedAt: nowIso(options.now),\n })\n }\n return store.upsertInteractionProjection(scope, {\n id: interactionId, kind: 'unknown', title: '', fields: [], status,\n tombstone: true, ...(reason ? { cancelReason: reason } : {}),\n ...(options.eventId ? { eventId: options.eventId } : {}), updatedAt: nowIso(options.now),\n })\n}\n\n/** Record an accepted/declined answer in the projection. The terminal\n * transition is intentionally separate from answer-intent acknowledgement so\n * callers can choose reconciled or best-effort delivery. */\nexport async function recordDurableInteractionAnswer(\n store: DurablePlanStore,\n scope: DurableChatScope,\n interactionId: string,\n outcome: 'accepted' | 'declined',\n answers?: Record<string, InteractionAnswerValue>,\n options: { eventId?: string; now?: () => string } = {},\n): Promise<DurableInteractionProjection> {\n const prior = await store.getInteractionProjection(scope, interactionId)\n if (!prior) throw new DurableChatConflictError('cannot answer an interaction before its ask projection')\n const status = outcome === 'accepted' ? 'answered' : 'declined'\n const parsed = safeAnswers(answers)\n if (prior.status === status && JSON.stringify(prior.answers) === JSON.stringify(parsed)) return prior\n if (prior.status !== 'pending') throw new DurableChatConflictError('interaction already has a conflicting terminal outcome')\n return store.upsertInteractionProjection(scope, {\n ...prior, status, ...(parsed ? { answers: parsed } : {}),\n ...(options.eventId ? { eventId: options.eventId } : {}), updatedAt: nowIso(options.now),\n })\n}\n\n/** Define options for creating durable interaction settlement factories including store and optional reconcile authority */\nexport interface DurableInteractionSettlementFactoryOptions extends DurableInteractionSettlementOptions {\n store: DurablePlanStore\n /** Optional authority lookup used by `reconcile`; returning null leaves the\n * intent prepared for a later durable retry. */\n reconcileAuthority?: (args: {\n scope: DurableChatScope\n intent: DurableAnswerIntentRecord\n }) => Promise<DurableInteractionAcknowledgement | null>\n}\n\n/** Additive answer settlement primitive for wiring into `/interactions`.\n * `attemptKey` belongs to the caller and is never generated from user data. */\nexport function createDurableInteractionSettlement(\n options: DurableInteractionSettlementFactoryOptions,\n): DurableInteractionSettlement {\n const now = options.now ?? (() => new Date().toISOString())\n return {\n async prepare(scope, interactionId, outcome, data) {\n ensureAttemptKey(options.attemptKey)\n const parsed = safeAnswers(data)\n const record: DurableAnswerIntentRecord = {\n scope, interactionId, attemptKey: options.attemptKey,\n intentKey: intentKey(scope, interactionId, options.attemptKey),\n outcome, ...(parsed ? { data: parsed } : {}), state: 'prepared',\n guarantee: options.guarantee ?? 'reconciled', createdAt: now(),\n }\n const result = await options.store.claimAnswerIntent(scope, record)\n if (result.status === 'conflict') throw new DurableChatConflictError(result.reason)\n return result.record\n },\n async acknowledge(scope, key, acknowledgement = {}) {\n const existing = await options.store.getAnswerIntent(scope, key)\n if (!existing) throw new DurableChatConflictError('unknown answer intent')\n const value: DurableInteractionAcknowledgement = {\n acknowledged: true,\n ...(acknowledgement.authorityId ? { authorityId: acknowledgement.authorityId } : {}),\n ...(acknowledgement.status ? { status: acknowledgement.status } : {}),\n at: acknowledgement.at ?? now(),\n }\n await options.store.acknowledgeAnswerIntent(scope, key, value)\n return (await options.store.getAnswerIntent(scope, key))!\n },\n async finalize(scope, key) {\n const existing = await options.store.getAnswerIntent(scope, key)\n if (!existing) throw new DurableChatConflictError('unknown answer intent')\n await options.store.finalizeAnswerIntent(scope, key, options.guarantee ?? 'reconciled')\n return (await options.store.getAnswerIntent(scope, key))!\n },\n async abort(scope, key, error) {\n const existing = await options.store.getAnswerIntent(scope, key)\n if (!existing) throw new DurableChatConflictError('unknown answer intent')\n await options.store.abortAnswerIntent(scope, key, error)\n return (await options.store.getAnswerIntent(scope, key))!\n },\n async reconcile(scope, key) {\n const existing = await options.store.getAnswerIntent(scope, key)\n if (!existing || !options.reconcileAuthority) return existing\n if (existing.state === 'finalized') return existing\n const acknowledgement = await options.reconcileAuthority({ scope, intent: existing })\n if (!acknowledgement) return existing\n await options.store.acknowledgeAnswerIntent(scope, key, {\n acknowledged: true,\n ...(acknowledgement.authorityId ? { authorityId: acknowledgement.authorityId } : {}),\n ...(acknowledgement.status ? { status: acknowledgement.status } : {}),\n ...(acknowledgement.at ? { at: acknowledgement.at } : {}),\n })\n await options.store.finalizeAnswerIntent(scope, key, options.guarantee ?? 'reconciled')\n return (await options.store.getAnswerIntent(scope, key))!\n },\n }\n}\n\n/** Stable key helper exported for products implementing their own settlement\n * loop. */\nexport function durableInteractionIntentKey(scope: DurableChatScope, interactionId: string, attemptKey: string): string {\n ensureAttemptKey(attemptKey)\n return intentKey(scope, interactionId, attemptKey)\n}\n\n/** Resolve and upsert a durable interaction ask in the store with optional event and timing parameters */\nexport const applyDurableInteractionAsk = upsertDurableInteractionAsk\n/** Resolve cancellation of a durable interaction with optional reason and event details */\nexport const applyDurableInteractionCancel = recordDurableInteractionCancel\n/** Resolve and record the outcome and answers of a durable interaction within the given store and scope */\nexport const applyDurableInteractionAnswer = recordDurableInteractionAnswer\n","import {\n interactionToPersistedPart,\n parseInteractionCancel,\n parseInteractionRequest,\n type InteractionCancelData,\n type InteractionPersistedPart,\n type InteractionRequestWire,\n} from '../interactions/contract'\nimport { DurableChatConflictError } from './errors'\nimport type {\n DurableInteractionRouteArgs,\n DurableInteractionRoutePersistence,\n} from '../interactions/route'\nimport {\n createDurableInteractionSettlement,\n recordDurableInteractionCancel,\n upsertDurableInteractionAsk,\n} from './interactions'\nimport type {\n DurableAnswerIntentRecord,\n DurableChatScope,\n DurableInteractionAcknowledgement,\n DurableInteractionGuarantee,\n DurableInteractionSettlement,\n DurablePlanStore,\n} from './types'\nimport {\n parsePlanSubmittedEvent,\n persistedPartToPlan,\n planToPersistedPart,\n} from '../plans/index'\n\n/** Define methods to manage durable interaction projections including upsert, cancel, and materialize operations */\nexport interface DurableInteractionProjectionAdapter {\n upsertAsk(request: InteractionRequestWire): Promise<void>\n cancel(cancel: InteractionCancelData): Promise<void>\n materialize(): Promise<InteractionPersistedPart[]>\n}\n\n/** Binds an authorized durable scope/store to interaction lifecycle events. */\nexport function createDurableInteractionProjectionAdapter(options: {\n store: DurablePlanStore\n scope: DurableChatScope\n now?: () => string\n}): DurableInteractionProjectionAdapter {\n const observed = new Set<string>()\n return {\n async upsertAsk(request) {\n observed.add(request.id)\n await upsertDurableInteractionAsk(options.store, options.scope, request, { now: options.now })\n },\n async cancel(cancel) {\n observed.add(cancel.id)\n await recordDurableInteractionCancel(\n options.store,\n options.scope,\n cancel.id,\n cancel.reason,\n { now: options.now },\n )\n },\n async materialize() {\n const projections = await Promise.all(\n [...observed].map((id) => options.store.getInteractionProjection(options.scope, id)),\n )\n const canonical = new Map(projections.filter((item) => item !== null).map((item) => [item.id, item]))\n return [...canonical.values()]\n .filter((projection) => projection.kind !== 'unknown')\n .map((projection) => interactionToPersistedPart(\n {\n id: projection.id,\n kind: projection.kind,\n title: projection.title,\n ...(projection.body ? { body: projection.body } : {}),\n answerSpec: { fields: projection.fields },\n },\n projection.status,\n projection.cancelReason,\n projection.answers,\n ))\n },\n }\n}\n\n/** Resolve chat events and materialize their state into durable records */\nexport interface DurableChatEventProjection {\n observe(event: unknown): void | Promise<void>\n materialize(): Array<Record<string, unknown>> | Promise<Array<Record<string, unknown>>>\n}\n\nfunction eventRecord(value: unknown): Record<string, unknown> | null {\n if (!value || typeof value !== 'object' || Array.isArray(value)) return null\n const record = value as Record<string, unknown>\n if (record.kind === 'event' && record.event && typeof record.event === 'object') {\n return record.event as Record<string, unknown>\n }\n return record\n}\n\n/** Event projector usable with any `ChatTurnRouteProducer` through\n * `withDurableChatProjection`. It tracks this turn's identities so older\n * thread state is not copied into every assistant message. */\nexport function createDurableChatEventProjection(options: {\n store: DurablePlanStore\n scope: DurableChatScope\n now?: () => string\n}): DurableChatEventProjection {\n const interactions = createDurableInteractionProjectionAdapter(options)\n const plans = new Set<string>()\n return {\n async observe(value) {\n const event = eventRecord(value)\n if (!event || typeof event.type !== 'string') return\n const data = eventRecord(event.data)\n if (event.type === 'interaction') {\n const parsed = parseInteractionRequest(data ?? undefined)\n if (parsed.succeeded) await interactions.upsertAsk(parsed.value)\n return\n }\n if (event.type === 'interaction.cancel') {\n const parsed = parseInteractionCancel(data ?? undefined)\n if (parsed.succeeded) {\n try {\n await interactions.cancel(parsed.value)\n } catch (error) {\n if (!(error instanceof DurableChatConflictError)) throw error\n }\n }\n return\n }\n if (!event.type.startsWith('plan.')) return\n const submitted = parsePlanSubmittedEvent(event)\n const planRecord = eventRecord(data?.plan) ?? eventRecord(eventRecord(event.properties)?.plan)\n const plan = submitted.succeeded\n ? submitted.value\n : planRecord ? persistedPartToPlan({ type: 'plan', ...planRecord }) : null\n if (!plan) return\n plans.add(`${plan.planId}\\u0000${plan.revision}`)\n try {\n await options.store.putPlanProjection(options.scope, plan)\n } catch (error) {\n if (!(error instanceof DurableChatConflictError)) throw error\n }\n },\n async materialize() {\n const interactionParts = await interactions.materialize()\n const planParts = await Promise.all([...plans].map(async (key) => {\n const [planId, rawRevision] = key.split('\\u0000')\n const plan = await options.store.getPlanProjection(options.scope, planId!, Number(rawRevision))\n return plan ? planToPersistedPart(plan) : null\n }))\n return [...interactionParts, ...planParts.filter((part) => part !== null)]\n },\n }\n}\n\n/** Define a structured response containing scope, settlement, and intent for durable interactions */\nexport interface PreparedDurableInteractionAnswer {\n scope: DurableChatScope\n settlement: DurableInteractionSettlement\n intent: DurableAnswerIntentRecord\n}\n\ninterface DurableInteractionRoutePersistenceBase {\n store: DurablePlanStore\n scope(args: DurableInteractionRouteArgs): DurableChatScope | Promise<DurableChatScope>\n now?: () => string\n}\n\n/** Define options for durable interaction route persistence with reconciliation guarantees and authority functions */\nexport type CreateDurableInteractionRoutePersistenceOptions =\n | (DurableInteractionRoutePersistenceBase & {\n guarantee: 'reconciled'\n reconcileAuthority(args: {\n scope: DurableChatScope\n intent: DurableAnswerIntentRecord\n route: DurableInteractionRouteArgs\n }): Promise<DurableInteractionAcknowledgement | null>\n })\n | (DurableInteractionRoutePersistenceBase & {\n guarantee: 'best-effort'\n reconcileAuthority?: (args: {\n scope: DurableChatScope\n intent: DurableAnswerIntentRecord\n route: DurableInteractionRouteArgs\n }) => Promise<DurableInteractionAcknowledgement | null>\n })\n\n/** Ready-to-use bridge from `/interactions` to the durable state port. Only\n * the reconciled variant may claim crash-safe behavior; best-effort is\n * explicit in both its type and persisted intent. */\nexport function createDurableInteractionRoutePersistence(\n options: CreateDurableInteractionRoutePersistenceOptions,\n): DurableInteractionRoutePersistence<PreparedDurableInteractionAnswer> {\n const guarantee: DurableInteractionGuarantee = options.guarantee\n return {\n guarantee,\n async prepare(args) {\n const scope = await options.scope(args)\n const settlement = createDurableInteractionSettlement({\n store: options.store,\n attemptKey: args.attemptKey,\n guarantee,\n now: options.now,\n ...(options.reconcileAuthority\n ? { reconcileAuthority: ({ intent }) => options.reconcileAuthority!({ scope, intent, route: args }) }\n : {}),\n })\n const intent = await settlement.prepare(\n scope,\n args.answer.id,\n args.answer.outcome,\n args.answer.data,\n )\n return { scope, settlement, intent }\n },\n async reconcile({ prepared }) {\n let intent = await prepared.settlement.reconcile(prepared.scope, prepared.intent.intentKey)\n if (intent?.state === 'acknowledged') {\n intent = await prepared.settlement.finalize(prepared.scope, prepared.intent.intentKey)\n }\n return { settled: intent?.state === 'finalized' }\n },\n async acknowledge({ prepared }) {\n await prepared.settlement.acknowledge(prepared.scope, prepared.intent.intentKey, {\n status: prepared.intent.outcome,\n })\n },\n async finalize({ prepared }) {\n await prepared.settlement.finalize(prepared.scope, prepared.intent.intentKey)\n },\n async fail({ prepared, error }) {\n await prepared.settlement.abort(\n prepared.scope,\n prepared.intent.intentKey,\n error instanceof Error ? error.message : String(error),\n )\n },\n }\n}\n","import {\n DurableChatConflictError,\n DurableChatGoneError,\n DurableChatUnavailableError,\n} from './errors'\nimport {\n durableChatScopeKey,\n normalizePlanDecision,\n planAuthorityIdempotencyKey,\n planCommandKey,\n planEffectKey,\n stablePlanReceipt,\n type DurableChatScope,\n type DurableFollowUpReceipt,\n type DurablePlanAuthority,\n type DurablePlanAuthorityCurrentResult,\n type DurablePlanAuthorityResult,\n type DurablePlanCommandRecord,\n type DurablePlanProjection,\n type DurablePlanStore,\n} from './types'\nimport { canTransitionPlanStatus, planFollowUpTurnId } from '../plans/index'\n\n/** Resolve authorization status for durable plans using scopes, responses, or nullish values */\nexport type DurablePlanAuthorization =\n | DurableChatScope\n | { scope: DurableChatScope }\n | Response\n | null\n | undefined\n\n/** Define arguments for authorizing durable plan route requests with operation and optional plan ID */\nexport interface DurablePlanRouteAuthorizeArgs {\n request: Request\n operation: 'current' | 'decide'\n planId?: string\n}\n\n/** Define options for durable plan routing including store, authority, authorization, and idempotent side effect handling */\nexport interface DurablePlanRouteOptions {\n store: DurablePlanStore\n authority: DurablePlanAuthority\n /** Authentication and resource authorization. Scope must be derived by the\n * caller from trusted credentials, never from client JSON. */\n authorize: (args: DurablePlanRouteAuthorizeArgs) => Promise<DurablePlanAuthorization> | DurablePlanAuthorization\n /** Required idempotent side effect seam. The route claims `effectKey` before\n * calling it; a product must make the callback safe to retry by that key. */\n afterDecision: (args: {\n scope: DurableChatScope\n plan: DurablePlanProjection\n receipt: DurableFollowUpReceipt\n effectKey: string\n }) => Promise<void> | void\n now?: () => string\n logger?: Pick<Console, 'warn' | 'error'>\n}\n\n/** Define routes handling durable plan requests with current and decide methods */\nexport interface DurablePlanRoutes {\n current(request: Request): Promise<Response>\n decide(request: Request): Promise<Response>\n}\n\ntype ParsedDecision = {\n planId: string\n revision: number\n decision: 'approved' | 'rejected'\n feedback?: string\n}\n\nfunction errorResponse(error: unknown, fallbackCode: string, fallbackStatus: number, fallbackMessage: string): Response {\n if (error instanceof Response) return error\n if (error && typeof error === 'object' && 'status' in error && typeof error.status === 'number') {\n const typed = error as { code?: unknown; message?: unknown; status: number }\n return Response.json(\n { code: typeof typed.code === 'string' ? typed.code : fallbackCode, error: typeof typed.message === 'string' ? typed.message : fallbackMessage },\n { status: typed.status },\n )\n }\n return Response.json({ code: fallbackCode, error: fallbackMessage }, { status: fallbackStatus })\n}\n\nfunction scopeFromAuthorization(value: DurablePlanAuthorization): DurableChatScope | Response {\n if (value instanceof Response) return value\n if (typeof value === 'string' && value) return value\n if (value && typeof value === 'object' && 'scope' in value && value.scope) return value.scope\n return Response.json({ code: 'DURABLE_CHAT_UNAUTHORIZED', error: 'not authorized' }, { status: 401 })\n}\n\nfunction planIdFromUrl(request: Request): string | null {\n const url = new URL(request.url)\n const query = url.searchParams.get('planId') ?? url.searchParams.get('id')\n if (query) return query\n const segments = url.pathname.split('/').filter(Boolean)\n return segments.length > 0 ? decodeURIComponent(segments[segments.length - 1]!) : null\n}\n\nfunction asCurrent(value: DurablePlanAuthorityCurrentResult | DurablePlanProjection | null): DurablePlanAuthorityCurrentResult {\n if (value === null) return { plan: null }\n if ('plan' in value) return value\n return { plan: value }\n}\n\nfunction terminalDecision(plan: DurablePlanProjection | null): 'approved' | 'rejected' | null {\n if (!plan) return null\n return plan.status === 'approved' || plan.status === 'rejected' ? plan.status : null\n}\n\nfunction parseDecisionBody(body: unknown): ParsedDecision | { error: string } {\n if (!body || typeof body !== 'object' || Array.isArray(body)) return { error: 'Invalid JSON body' }\n const record = body as Record<string, unknown>\n const planId = typeof record.planId === 'string' && record.planId\n ? record.planId\n : typeof record.id === 'string' && record.id ? record.id : null\n const revision = record.revision\n const decision = normalizePlanDecision(record.decision ?? record.outcome ?? record.status)\n if (!planId) return { error: 'Missing planId' }\n if (typeof revision !== 'number' || !Number.isInteger(revision) || revision < 1) return { error: 'revision must be a positive integer' }\n if (!decision) return { error: 'decision must be approved or rejected' }\n if (record.feedback !== undefined && typeof record.feedback !== 'string') return { error: 'feedback must be a string' }\n return { planId, revision, decision, ...(typeof record.feedback === 'string' ? { feedback: record.feedback } : {}) }\n}\n\nfunction withReceipt(result: DurablePlanAuthorityResult, scope: DurableChatScope, parsed: ParsedDecision): DurablePlanAuthorityResult & { receipt: DurableFollowUpReceipt } {\n const receipt = result.receipt ?? stablePlanReceipt(scope, parsed.planId, parsed.revision, parsed.decision, result)\n return { ...result, receipt }\n}\n\nfunction recoverReceipt(\n scope: DurableChatScope,\n plan: DurablePlanProjection,\n decision: 'approved' | 'rejected',\n): DurableFollowUpReceipt {\n return stablePlanReceipt(scope, plan.planId, plan.revision, decision, {\n followUp: { turnId: planFollowUpTurnId(plan.planId, decision), state: 'unknown' },\n })\n}\n\n/** Build durable plan routes with authorization and effect handling based on provided options */\nexport function createDurablePlanRoutes(options: DurablePlanRouteOptions): DurablePlanRoutes {\n const now = options.now ?? (() => new Date().toISOString())\n const logger = options.logger ?? console\n\n async function authorize(request: Request, operation: 'current' | 'decide', planId?: string): Promise<DurableChatScope | Response> {\n try {\n return scopeFromAuthorization(await options.authorize({ request, operation, ...(planId ? { planId } : {}) }))\n } catch (error) {\n return errorResponse(error, 'DURABLE_CHAT_UNAUTHORIZED', 401, 'not authorized')\n }\n }\n\n async function runEffect(\n scope: DurableChatScope,\n plan: DurablePlanProjection,\n receipt: DurableFollowUpReceipt,\n ): Promise<boolean> {\n const effectKey = planEffectKey(scope, plan.planId, plan.revision, receipt.decision)\n try {\n const existing = await options.store.getPlanEffect(scope, effectKey)\n if (existing?.state === 'completed') return true\n const claim = await options.store.claimPlanEffect(scope, {\n effectKey, scope, planId: plan.planId, revision: plan.revision,\n decision: receipt.decision, state: 'claimed', claimedAt: now(),\n })\n if (claim.status === 'existing' && claim.record.state === 'completed') return true\n await options.afterDecision({ scope, plan, receipt, effectKey })\n await options.store.completePlanEffect(scope, effectKey)\n return true\n } catch (error) {\n await options.store.failPlanEffect(scope, effectKey, error instanceof Error ? error.message : String(error)).catch(() => undefined)\n logger.warn('[durable-chat] afterDecision failed:', error)\n return false\n }\n }\n\n async function current(request: Request): Promise<Response> {\n const planId = planIdFromUrl(request)\n if (!planId) return Response.json({ code: 'DURABLE_CHAT_BAD_REQUEST', error: 'Missing planId' }, { status: 400 })\n const scope = await authorize(request, 'current', planId)\n if (scope instanceof Response) return scope\n const local = await options.store.getPlanProjection(scope, planId)\n let authoritative: DurablePlanAuthorityCurrentResult\n try {\n authoritative = asCurrent(await options.authority.current({ scope, planId }))\n } catch (error) {\n // A known terminal local record is safe to replay while authority is\n // temporarily down; pending records must not pretend to be committed.\n const decision = terminalDecision(local)\n if (decision) {\n const command = await options.store.getPlanCommand(scope, planCommandKey(planId, local!.revision, decision))\n if (command?.receipt) {\n const effectComplete = await runEffect(scope, command.authorityResult?.plan ?? local!, command.receipt)\n return Response.json({\n plan: command.authorityResult?.plan ?? local,\n receipt: command.receipt,\n replayed: true,\n ...(!effectComplete ? { effectPending: true } : {}),\n })\n }\n }\n return errorResponse(error, 'DURABLE_CHAT_UNAVAILABLE', 503, 'plan authority unavailable')\n }\n if (!authoritative.plan) {\n return Response.json({ code: 'DURABLE_CHAT_GONE', error: 'plan is no longer available' }, { status: 410 })\n }\n const authorityPlan = authoritative.plan\n const localWins = Boolean(local && (\n local.revision > authorityPlan.revision ||\n (local.revision === authorityPlan.revision && !canTransitionPlanStatus(local.status, authorityPlan.status))\n ))\n const plan = localWins ? local! : authorityPlan\n let projectionPending = false\n if (!localWins) {\n try {\n await options.store.putPlanProjection(scope, plan)\n } catch (error) {\n projectionPending = true\n logger.warn('[durable-chat] failed to heal plan projection:', error)\n }\n }\n const decision = terminalDecision(plan)\n let receipt = localWins ? undefined : authoritative.receipt\n if (!receipt && decision) {\n const command = await options.store.getPlanCommand(scope, planCommandKey(plan.planId, plan.revision, decision))\n receipt = command?.receipt\n if (!receipt) receipt = recoverReceipt(scope, plan, decision)\n }\n const effectComplete = decision && receipt ? await runEffect(scope, plan, receipt) : true\n return Response.json({\n plan,\n ...(receipt ? { receipt } : {}),\n ...(projectionPending ? { projectionPending: true } : {}),\n ...(!effectComplete ? { effectPending: true } : {}),\n })\n }\n\n async function decide(request: Request): Promise<Response> {\n const body = await request.json().catch(() => null)\n const parsed = parseDecisionBody(body)\n if ('error' in parsed) return Response.json({ code: 'DURABLE_CHAT_BAD_REQUEST', error: parsed.error }, { status: 400 })\n const scope = await authorize(request, 'decide', parsed.planId)\n if (scope instanceof Response) return scope\n const local = await options.store.getPlanProjection(scope, parsed.planId, parsed.revision)\n const current = await options.store.getPlanProjection(scope, parsed.planId)\n if (!local) {\n return Response.json({ code: 'DURABLE_CHAT_UNAVAILABLE', error: 'submitted plan projection is required before deciding' }, { status: 503 })\n }\n if (current && parsed.revision < current.revision) {\n return Response.json({ code: 'DURABLE_CHAT_CONFLICT', error: 'stale plan revision' }, { status: 409 })\n }\n if (local.status !== 'pending') {\n const existingTerminal = terminalDecision(local)\n if (existingTerminal === parsed.decision) {\n const existing = await options.store.getPlanCommand(scope, planCommandKey(parsed.planId, parsed.revision, parsed.decision))\n const receipt = existing?.receipt ?? recoverReceipt(scope, local, parsed.decision)\n const effectComplete = await runEffect(scope, existing?.authorityResult?.plan ?? local, receipt)\n return Response.json({\n plan: existing?.authorityResult?.plan ?? local,\n receipt,\n replayed: true,\n ...(!effectComplete ? { effectPending: true } : {}),\n })\n }\n return Response.json({\n code: 'DURABLE_CHAT_CONFLICT',\n error: 'plan is not pending',\n plan: local,\n }, { status: 409 })\n }\n const opposite = parsed.decision === 'approved' ? 'rejected' : 'approved'\n const oppositeCommand = await options.store.getPlanCommand(scope, planCommandKey(parsed.planId, parsed.revision, opposite))\n if (oppositeCommand) return Response.json({ code: 'DURABLE_CHAT_CONFLICT', error: 'competing decision for plan revision' }, { status: 409 })\n const commandKey = planCommandKey(parsed.planId, parsed.revision, parsed.decision)\n const authorityIdempotencyKey = planAuthorityIdempotencyKey(scope, parsed.planId, parsed.revision, parsed.decision)\n const command: DurablePlanCommandRecord = {\n scope, planId: parsed.planId, revision: parsed.revision, decision: parsed.decision,\n commandKey, authorityIdempotencyKey, state: 'claimed', claimedAt: now(),\n }\n const claimed = await options.store.claimPlanCommand(scope, command)\n if (claimed.status === 'conflict') return Response.json({ code: 'DURABLE_CHAT_CONFLICT', error: claimed.reason }, { status: 409 })\n if (claimed.status === 'existing' && claimed.record.receipt) {\n // Effect errors are intentionally retried on a known committed command.\n const effectComplete = await runEffect(scope, claimed.record.authorityResult?.plan ?? local, claimed.record.receipt)\n return Response.json({\n plan: claimed.record.authorityResult?.plan ?? local,\n receipt: claimed.record.receipt,\n replayed: true,\n ...(!effectComplete ? { effectPending: true } : {}),\n })\n }\n let authorityResult: DurablePlanAuthorityResult & { receipt: DurableFollowUpReceipt }\n try {\n authorityResult = withReceipt(await options.authority.decide({\n scope, planId: parsed.planId, revision: parsed.revision, decision: parsed.decision,\n ...(parsed.feedback ? { feedback: parsed.feedback } : {}), idempotencyKey: authorityIdempotencyKey,\n }), scope, parsed)\n } catch (error) {\n try {\n const reconciled = asCurrent(await options.authority.current({\n scope,\n planId: parsed.planId,\n revision: parsed.revision,\n }))\n const terminal = terminalDecision(reconciled.plan)\n if (reconciled.plan && terminal === parsed.decision) {\n const receipt = reconciled.receipt ?? recoverReceipt(scope, reconciled.plan, terminal)\n authorityResult = {\n plan: reconciled.plan,\n followUp: { turnId: receipt.turnId, state: receipt.state },\n idempotent: true,\n receipt,\n }\n } else if (reconciled.plan && reconciled.plan.status !== 'pending') {\n // The authority has already moved this revision out of its pending\n // state, but not to the decision this request asked for. Surface the\n // authoritative snapshot so the client can converge instead of\n // retrying an already-lost decision as if the authority were down.\n let projectionPending = false\n try {\n await options.store.putPlanProjection(scope, reconciled.plan)\n } catch (projectionError) {\n projectionPending = true\n logger.warn('[durable-chat] failed to reconcile conflicting plan projection:', projectionError)\n }\n return Response.json({\n code: 'DURABLE_CHAT_CONFLICT',\n error: 'plan is not pending',\n plan: reconciled.plan,\n ...(reconciled.receipt ? { receipt: reconciled.receipt } : {}),\n ...(projectionPending ? { projectionPending: true } : {}),\n }, { status: 409 })\n } else {\n return errorResponse(error, 'DURABLE_CHAT_UNAVAILABLE', 503, 'plan authority unavailable')\n }\n } catch {\n return errorResponse(error, 'DURABLE_CHAT_UNAVAILABLE', 503, 'plan authority unavailable')\n }\n }\n let projectionPending = false\n try {\n await options.store.recordPlanAuthorityResult(scope, commandKey, authorityResult, authorityResult.receipt)\n } catch (error) {\n projectionPending = true\n // The authority has committed; the receipt remains safe to return and\n // GET can reconcile from the authority on the next request.\n logger.warn('[durable-chat] failed to record authority result:', error)\n }\n try {\n await options.store.putPlanProjection(scope, authorityResult.plan)\n await options.store.finalizePlanCommand(scope, commandKey)\n } catch (error) {\n projectionPending = true\n logger.warn('[durable-chat] failed to finalize plan projection:', error)\n }\n const effectComplete = await runEffect(scope, authorityResult.plan, authorityResult.receipt)\n return Response.json({\n plan: authorityResult.plan,\n receipt: authorityResult.receipt,\n ...(projectionPending ? { projectionPending: true } : {}),\n ...(!effectComplete ? { effectPending: true } : {}),\n })\n }\n\n return { current, decide }\n}\n"],"mappings":"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","names":["intentKey","intent","decision","effectComplete","current","projectionPending"]}
@@ -187,4 +187,4 @@ export {
187
187
  summarize,
188
188
  renderHistogram
189
189
  };
190
- //# sourceMappingURL=chunk-GQRL6VNU.js.map
190
+ //# sourceMappingURL=chunk-LGBO24FL.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/trace/mission-trace.ts","../src/trace/index.ts"],"sourcesContent":["/**\n * Mission trace context — mint + thread the trace ids that join a mission's\n * step attempts and its delegated agent runs into ONE trace tree.\n *\n * ID formats are byte-compatible with agent-runtime's trace propagation\n * (`readTraceContextFromEnv` / OTLP export): 32 lowercase hex chars for a\n * trace id (16 bytes), 16 for a span id (8 bytes). The env pair from\n * {@link traceEnv} is exactly what agent-runtime's MCP subprocess reads at\n * startup (`TRACE_ID` + `PARENT_SPAN_ID`), so a delegation dispatched with it\n * parents its loop→round→iteration spans under the mission's step span.\n *\n * Pure functions, no deps. Ids are DETERMINISTIC when a key is supplied\n * (missionId / step-attempt seed) so a crashed driver re-mints the identical\n * context on re-dispatch and the re-run joins the same trace instead of\n * forking a new one; without a key they are random.\n */\n\nexport interface MissionTraceContext {\n /** 32-hex trace id shared by every span in the mission's tree. */\n traceId: string\n /** 16-hex span id of the mission root — the parent of every step span. */\n rootSpanId: string\n}\n\n/** Define context information for a step span including trace, span, and parent span identifiers */\nexport interface StepSpanContext {\n traceId: string\n /** 16-hex span id of this step attempt (or any nested unit of work). */\n spanId: string\n /** The span this one nests under. */\n parentSpanId: string\n}\n\n/**\n * Mint a mission's trace context. With `missionId` the ids are a pure\n * function of it; omitted, both ids are random.\n */\nexport function createMissionTraceContext(missionId?: string): MissionTraceContext {\n if (missionId !== undefined && missionId !== '') {\n return {\n traceId: hex64(fnv1a64(`mission-trace:${missionId}`)) + hex64(fnv1a64(`mission-trace:2:${missionId}`)),\n rootSpanId: hex64(fnv1a64(`mission-root-span:${missionId}`)),\n }\n }\n return { traceId: randomHex(16), rootSpanId: randomHex(8) }\n}\n\n/**\n * Derive a child span context under `parent` — one per step attempt (seed\n * e.g. `\"${stepId}#${attempt}\"`), or nested under another step span. With a\n * seed the span id is deterministic for the same parent + seed; omitted, it\n * is random.\n */\nexport function childSpanContext(\n parent: MissionTraceContext | StepSpanContext,\n seed?: string,\n): StepSpanContext {\n const parentSpanId = 'rootSpanId' in parent ? parent.rootSpanId : parent.spanId\n const spanId =\n seed !== undefined && seed !== ''\n ? hex64(fnv1a64(`span:${parent.traceId}:${parentSpanId}:${seed}`))\n : randomHex(8)\n return { traceId: parent.traceId, spanId, parentSpanId }\n}\n\n/**\n * The env pair a delegation subprocess inherits — agent-runtime's\n * `readTraceContextFromEnv` reads exactly these names. `PARENT_SPAN_ID` is\n * the span the dispatched work nests under: the root for a mission context,\n * the step-attempt span for a step context.\n */\nexport function traceEnv(ctx: MissionTraceContext | StepSpanContext): {\n TRACE_ID: string\n PARENT_SPAN_ID: string\n} {\n return {\n TRACE_ID: ctx.traceId,\n PARENT_SPAN_ID: 'rootSpanId' in ctx ? ctx.rootSpanId : ctx.spanId,\n }\n}\n\n// FNV-1a 64-bit over UTF-16 code units — a stable, dependency-free digest for\n// deterministic ids. Not cryptographic; trace ids only need uniqueness within\n// a tenant's missions, not unforgeability.\nconst FNV_OFFSET = 0xcbf29ce484222325n\nconst FNV_PRIME = 0x100000001b3n\nconst MASK_64 = 0xffffffffffffffffn\n\nfunction fnv1a64(input: string): bigint {\n let hash = FNV_OFFSET\n for (let i = 0; i < input.length; i++) {\n hash ^= BigInt(input.charCodeAt(i))\n hash = (hash * FNV_PRIME) & MASK_64\n }\n return hash\n}\n\nfunction hex64(value: bigint): string {\n return value.toString(16).padStart(16, '0')\n}\n\nfunction randomHex(byteLength: number): string {\n const bytes = new Uint8Array(byteLength)\n globalThis.crypto.getRandomValues(bytes)\n return Array.from(bytes)\n .map((b) => b.toString(16).padStart(2, '0'))\n .join('')\n}\n","/**\n * `@tangle-network/agent-app/trace` — flow observability for agent turns.\n *\n * The turn buffer stamps `_t` (ms since turn start) on every event, so any\n * live stream OR any historical turn replayed from a TurnEventStore can be\n * reconstructed into a span trace: pipeline overhead, model segments (with\n * thinking TTFT), tool executions, token usage, and cost. Renderers turn\n * traces and multi-run samples into ASCII waterfalls and histograms — the\n * default artifact for \"how did this run actually behave\" questions across\n * evals, hill-climbs, and production debugging.\n *\n * Span boundaries derived from a buffered stream are quantized by the\n * pump's flush window and the reader's poll cadence (~100–400ms); spans\n * carry `approx: true` to keep reports honest about that.\n */\n\nexport * from './mission-trace'\nexport * from './flow-types'\nexport * from './mission-flow'\n\nimport type { FlowSpan, FlowTrace } from './flow-types'\n\n/** Represent a timed event with a timestamp and associated event data */\nexport interface TimedEvent {\n /** ms since turn start (`_t` stamped by pumpBufferedTurn). */\n t: number\n event: Record<string, unknown>\n}\n\n/** Parse stored turn-event lines (JSON strings with `_t`) into TimedEvents. */\nexport function timedEventsFromLines(lines: string[]): TimedEvent[] {\n const out: TimedEvent[] = []\n for (const line of lines) {\n try {\n const parsed = JSON.parse(line) as Record<string, unknown>\n if (typeof parsed._t === 'number') out.push({ t: parsed._t, event: parsed })\n } catch {\n /* skip torn lines */\n }\n }\n return out.sort((a, b) => a.t - b.t)\n}\n\nfunction innerOf(e: Record<string, unknown>): Record<string, unknown> {\n return (e.kind === 'event' ? (e.event as Record<string, unknown>) : e) ?? {}\n}\n\n/**\n * Derive a span trace from timestamped turn events. Model segments are runs\n * of text/reasoning deltas; a tool span opens at the last delta before its\n * tool_call emission and closes at the matching tool_result.\n */\nexport function buildFlowTrace(\n events: TimedEvent[],\n opts?: { pricing?: { prompt?: string | number; completion?: string | number } },\n): FlowTrace {\n const spans: FlowSpan[] = []\n let promptTokens = 0\n let completionTokens = 0\n let toolCalls = 0\n\n const first = events[0]?.t ?? 0\n if (first > 0) {\n spans.push({ kind: 'pipeline', name: 'dispatch → first event', startMs: 0, endMs: first })\n }\n\n let segStart: number | null = null\n let segEnd = 0\n let segKinds = new Set<string>()\n let lastDeltaT = first\n const openCalls = new Map<string, { name: string; emitT: number; lastDeltaT: number }>()\n\n const closeSegment = () => {\n if (segStart !== null) {\n spans.push({\n kind: 'model',\n name: segKinds.has('reasoning') ? 'model turn (reasoning + text)' : 'model turn',\n startMs: segStart,\n endMs: segEnd,\n approx: true,\n })\n segStart = null\n segKinds = new Set()\n }\n }\n\n for (const { t, event } of events) {\n const inner = innerOf(event)\n const type = String(event.kind === 'tool_result' ? 'tool_result' : (inner.type ?? ''))\n\n if (type === 'text' || type === 'reasoning') {\n if (segStart === null) segStart = t\n segEnd = t\n segKinds.add(type)\n lastDeltaT = t\n } else if (type === 'tool_call') {\n closeSegment()\n toolCalls++\n const call = (inner.call ?? inner) as Record<string, unknown>\n const id = String(call.toolCallId ?? `call_${toolCalls}`)\n openCalls.set(id, { name: String(call.toolName ?? 'tool'), emitT: t, lastDeltaT })\n } else if (type === 'tool_result') {\n const id = String(event.toolCallId ?? inner.toolCallId ?? '')\n const open = openCalls.get(id)\n if (open) {\n spans.push({\n kind: 'tool',\n name: open.name,\n // Execution happens between the end of the model turn that emitted\n // the call and the result landing in the buffer.\n startMs: open.lastDeltaT,\n endMs: t,\n approx: true,\n meta: { ok: ((event.outcome ?? inner.outcome) as { ok?: boolean } | undefined)?.ok },\n })\n openCalls.delete(id)\n }\n } else if (type === 'usage') {\n const u = (inner.usage ?? {}) as { promptTokens?: number; completionTokens?: number }\n promptTokens += u.promptTokens ?? 0\n completionTokens += u.completionTokens ?? 0\n }\n }\n closeSegment()\n\n const totalMs = events.length ? events[events.length - 1]!.t : 0\n const trace: FlowTrace = { spans, totalMs, promptTokens, completionTokens, toolCalls }\n const p = opts?.pricing\n if (p && (p.prompt != null || p.completion != null)) {\n trace.costUsd = promptTokens * Number(p.prompt ?? 0) + completionTokens * Number(p.completion ?? 0)\n }\n return trace\n}\n\nconst fmtS = (ms: number) => `${(ms / 1000).toFixed(1)}s`\n\n/** ASCII waterfall cascade — the default artifact for explaining a flow. */\nexport function renderWaterfall(trace: FlowTrace, opts?: { width?: number }): string {\n const width = opts?.width ?? 40\n const scale = trace.totalMs > 0 ? width / trace.totalMs : 0\n const lines: string[] = []\n const spans = [...trace.spans].sort((a, b) => a.startMs - b.startMs)\n for (let i = 0; i < spans.length; i++) {\n const s = spans[i]!\n const offset = Math.round(s.startMs * scale)\n const len = Math.max(1, Math.round((s.endMs - s.startMs) * scale))\n const bar = ' '.repeat(offset) + (s.kind === 'tool' ? '▓' : s.kind === 'pipeline' ? '░' : '█').repeat(len)\n const branch = i === spans.length - 1 ? '└─' : '├─'\n const dur = `${fmtS(s.endMs - s.startMs)}${s.approx ? '~' : ''}`\n lines.push(`${fmtS(s.startMs).padStart(7)} ${branch} ${bar.padEnd(width + 2)} ${s.name} (${dur})`)\n }\n const cost = trace.costUsd != null ? ` $${trace.costUsd.toFixed(trace.costUsd < 0.01 ? 6 : 4)}` : ''\n lines.push(\n `${fmtS(trace.totalMs).padStart(7)} ── total · ${trace.promptTokens}p + ${trace.completionTokens}c tok · ${trace.toolCalls} tool calls${cost}`,\n )\n return lines.join('\\n')\n}\n\n/** Summarize key statistics of a numerical distribution including count, min, percentiles, and max */\nexport interface DistributionSummary {\n n: number\n min: number\n p50: number\n p90: number\n max: number\n}\n\n/** Summarize numeric values into a distribution summary including count, min, median, 90th percentile, and max */\nexport function summarize(values: number[]): DistributionSummary {\n const sorted = [...values].sort((a, b) => a - b)\n const q = (p: number) => sorted[Math.min(sorted.length - 1, Math.floor(p * sorted.length))] ?? 0\n return { n: sorted.length, min: sorted[0] ?? 0, p50: q(0.5), p90: q(0.9), max: sorted[sorted.length - 1] ?? 0 }\n}\n\n/** ASCII histogram for multi-run samples (eval latencies, costs, scores). */\nexport function renderHistogram(\n values: number[],\n opts?: { buckets?: number; width?: number; unit?: string; format?: (v: number) => string },\n): string {\n if (!values.length) return '(no samples)'\n const buckets = opts?.buckets ?? 6\n const width = opts?.width ?? 24\n const fmt = opts?.format ?? ((v: number) => `${Math.round(v)}${opts?.unit ?? ''}`)\n const s = summarize(values)\n const lo = s.min\n const hi = s.max === s.min ? s.min + 1 : s.max\n const counts = new Array<number>(buckets).fill(0)\n for (const v of values) {\n counts[Math.min(buckets - 1, Math.floor(((v - lo) / (hi - lo)) * buckets))]!++\n }\n const maxCount = Math.max(...counts)\n const lines = [\n `n=${s.n} min=${fmt(s.min)} p50=${fmt(s.p50)} p90=${fmt(s.p90)} max=${fmt(s.max)}`,\n ]\n for (let i = 0; i < buckets; i++) {\n const a = lo + ((hi - lo) * i) / buckets\n const b = lo + ((hi - lo) * (i + 1)) / buckets\n const bar = '█'.repeat(Math.max(counts[i]! > 0 ? 1 : 0, Math.round((counts[i]! / maxCount) * width)))\n lines.push(`${fmt(a).padStart(8)}-${fmt(b).padEnd(8)} ${bar} ${counts[i]}`)\n }\n return lines.join('\\n')\n}\n"],"mappings":"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","names":[]}
@@ -1,12 +1,12 @@
1
1
  import {
2
2
  generateInviteToken
3
- } from "./chunk-3SVAA3MA.js";
3
+ } from "./chunk-DJ4VJIH5.js";
4
4
  import {
5
5
  canManageWorkspaceMemberRole,
6
6
  hasWorkspaceRole,
7
7
  isAssignableWorkspaceRole,
8
8
  organizationRoleGrantsWorkspaceOwner
9
- } from "./chunk-63CE7FEZ.js";
9
+ } from "./chunk-6XIAPIW6.js";
10
10
 
11
11
  // src/teams/members-api.ts
12
12
  import { and, eq, isNull } from "drizzle-orm";
@@ -259,4 +259,4 @@ export {
259
259
  SeatLimitError,
260
260
  createMembersApi
261
261
  };
262
- //# sourceMappingURL=chunk-SWUVTGMR.js.map
262
+ //# sourceMappingURL=chunk-MEUNTJL5.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/teams/members-api.ts"],"sourcesContent":["/**\n * Framework-neutral members API for the teams module: the invite / list /\n * update-role / remove / accept-invite logic, lifted out of any one app's route\n * file. Each app mounts these in its own route with its own auth — the handlers\n * take an already-authenticated `actor`, the parsed inputs, the `db` + `tables`\n * from `createTeamTables`, the product's user + workspace tables, and the\n * workspace-access API from `createWorkspaceAccess`. They return web-standard\n * `Response`s (available in Workers, Node 18+, Deno, browsers), so\n * \"framework-neutral\" is literal: no Remix/React-Router/Express import anywhere.\n *\n * Two OPTIONAL seams an app wires only if it needs them:\n * - `enforceSeat` — billing/seat-limit gate, called at invite time only when\n * the invite would consume a NEW billable seat. An app without seat billing\n * passes nothing and seats are never checked.\n * - `memberSyncSeam` — fire-and-forget propagation of membership changes to a\n * sandbox/external system (add on accept, role on update, remove on\n * delete). An app without sandbox sync passes nothing. Fail-soft by\n * contract: a thrown sync is caught and never blocks the DB mutation.\n *\n * Imports `drizzle-orm`, so this is a subpath, never re-exported from root.\n */\n\nimport { and, eq, isNull } from 'drizzle-orm'\nimport {\n type AssignableWorkspaceRole,\n type WorkspaceRole,\n canManageWorkspaceMemberRole,\n hasWorkspaceRole,\n isAssignableWorkspaceRole,\n organizationRoleGrantsWorkspaceOwner,\n} from './roles'\nimport { generateInviteToken } from './invite'\nimport type { TeamDatabase, WorkspaceAccessApi } from './drizzle/access'\nimport type { TeamParentTable, TeamTables } from './drizzle/schema'\n\n/** The authenticated caller — apps resolve this from their own session layer. */\nexport interface MembersApiActor {\n id: string\n email?: string | null\n}\n\n/**\n * The product's user table, narrowed to the columns the member queries read.\n * Adopters pass their real drizzle user table.\n */\nexport interface UserLookupTable {\n id: any\n name: any\n email: any\n}\n\n/**\n * The product's workspace table, narrowed to the columns the member queries\n * read. The handlers join it to resolve a workspace's organization (the same\n * table passed to createTeamTables as workspaceTable).\n */\nexport interface WorkspaceLookupTable {\n id: any\n organizationId: any\n}\n\n/**\n * Optional billing seat gate. The seam resolves the count input itself (it\n * owns the plan/seat model) and throws when over the limit; the handler turns a\n * thrown `SeatLimitError` into a 402. Called only when an invite would consume\n * a NEW seat (invitee is not already an org member and has no pending org\n * invite) — the same guard gtm uses, so the seam never fires on a no-op invite.\n */\nexport interface EnforceSeatSeam {\n (input: { actorId: string; organizationId: string }): Promise<void> | void\n}\n\n/** Thrown by an `enforceSeat` seam to deny an invite; serialized to a 402. */\nexport class SeatLimitError extends Error {\n readonly status: number\n readonly capability?: string\n readonly requiredPlan?: string\n constructor(message: string, opts: { status?: number; capability?: string; requiredPlan?: string } = {}) {\n super(message)\n this.name = 'SeatLimitError'\n this.status = opts.status ?? 402\n this.capability = opts.capability\n this.requiredPlan = opts.requiredPlan\n }\n}\n\n/**\n * Optional membership-change propagation to an external system (e.g. sandbox).\n * Every method is fire-and-forget and fail-soft: the handler awaits nothing and\n * swallows rejections, so an unavailable downstream never blocks the mutation.\n * Each fires only for members with a real `userId` (never email-only invites).\n */\nexport interface MemberSyncSeam {\n add?(input: { workspaceId: string; userId: string; role: WorkspaceRole }): Promise<void> | void\n role?(input: { workspaceId: string; userId: string; role: WorkspaceRole }): Promise<void> | void\n remove?(input: { workspaceId: string; userId: string }): Promise<void> | void\n}\n\nexport interface MembersApiOptions {\n db: TeamDatabase\n tables: TeamTables\n /** The product's user table (FK target passed to createTeamTables). */\n userTable: TeamParentTable & UserLookupTable\n /** The product's workspace table (FK target passed to createTeamTables). */\n workspaceTable: TeamParentTable & WorkspaceLookupTable\n /** Workspace-access API from createWorkspaceAccess — RBAC stays one source. */\n access: Pick<WorkspaceAccessApi, 'getWorkspaceAccess'>\n enforceSeat?: EnforceSeatSeam\n memberSyncSeam?: MemberSyncSeam\n}\n\nexport interface MemberListEntry {\n id: string\n userId: string | null\n organizationMemberId: string | null\n role: WorkspaceRole\n name: string | null\n email: string | null\n invitedAt: Date | number | null\n acceptedAt: Date | number | null\n inherited: boolean\n}\n\n/**\n * Build the members API bound to one product's db/tables/access. Returns five\n * handlers; an app maps its route methods onto them (GET→list, POST→invite,\n * PATCH→updateRole, DELETE→remove; accept on its own route).\n */\nexport function createMembersApi(opts: MembersApiOptions) {\n const { db, tables, userTable, workspaceTable, access, enforceSeat, memberSyncSeam } = opts\n const { organizations, organizationMembers, workspaceMembers } = tables\n const users = userTable\n const workspaces = workspaceTable\n\n function fireSync(op: () => Promise<void> | void) {\n try {\n Promise.resolve(op()).catch(() => {})\n } catch {\n // seam threw synchronously — swallow; sync is best-effort by contract.\n }\n }\n\n async function listMembers(input: { workspaceId: string; actor: MembersApiActor }): Promise<Response> {\n const accessRow = await access.getWorkspaceAccess(input.workspaceId, input.actor.id)\n if (!accessRow) return Response.json({ error: 'Workspace not found' }, { status: 404 })\n\n const organizationId = (accessRow.workspace as { organizationId: string }).organizationId\n\n const [projectMembers, orgAdmins] = await Promise.all([\n db\n .select({\n id: workspaceMembers.id,\n organizationMemberId: workspaceMembers.organizationMemberId,\n userId: workspaceMembers.userId,\n role: workspaceMembers.role,\n invitedAt: workspaceMembers.invitedAt,\n acceptedAt: workspaceMembers.acceptedAt,\n inviteEmail: workspaceMembers.inviteEmail,\n userName: users.name,\n userEmail: users.email,\n })\n .from(workspaceMembers)\n .leftJoin(users, eq(users.id, workspaceMembers.userId))\n .where(eq(workspaceMembers.workspaceId, input.workspaceId)),\n db\n .select({\n id: organizationMembers.id,\n userId: organizationMembers.userId,\n orgRole: organizationMembers.role,\n userName: users.name,\n userEmail: users.email,\n createdAt: organizationMembers.createdAt,\n })\n .from(organizationMembers)\n .innerJoin(users, eq(users.id, organizationMembers.userId))\n .where(eq(organizationMembers.organizationId, organizationId)),\n ])\n\n const explicitOrgMemberIds = new Set(\n projectMembers.map((m: any) => m.organizationMemberId).filter(Boolean),\n )\n const members: MemberListEntry[] = [\n ...orgAdmins\n .filter((m: any) => organizationRoleGrantsWorkspaceOwner(m.orgRole) && !explicitOrgMemberIds.has(m.id))\n .map((m: any) => ({\n id: `org:${m.id}`,\n userId: m.userId,\n organizationMemberId: m.id,\n role: 'owner' as WorkspaceRole,\n name: m.userName,\n email: m.userEmail,\n invitedAt: m.createdAt,\n acceptedAt: m.createdAt,\n inherited: true,\n })),\n ...projectMembers.map((m: any) => ({\n id: m.id,\n userId: m.userId,\n organizationMemberId: m.organizationMemberId,\n role: m.role as WorkspaceRole,\n name: m.userName,\n email: m.userEmail ?? m.inviteEmail,\n invitedAt: m.invitedAt,\n acceptedAt: m.acceptedAt,\n inherited: false,\n })),\n ]\n\n return Response.json({ members, currentRole: accessRow.role, organizationId })\n }\n\n async function inviteMember(input: {\n workspaceId: string\n actor: MembersApiActor\n email?: string\n role?: string\n }): Promise<Response> {\n if (!input.email) return Response.json({ error: 'Missing email' }, { status: 400 })\n const requestedRole = input.role ?? 'editor'\n if (!isAssignableWorkspaceRole(requestedRole)) {\n return Response.json({ error: 'Invalid role. Must be viewer, editor, or admin.' }, { status: 400 })\n }\n const assignRole: AssignableWorkspaceRole = requestedRole\n const accessRow = await access.getWorkspaceAccess(input.workspaceId, input.actor.id, 'admin')\n if (!accessRow) return Response.json({ error: 'Workspace not found' }, { status: 404 })\n if (!hasWorkspaceRole(accessRow.role, assignRole)) {\n return Response.json({ error: 'Cannot assign a role higher than your own' }, { status: 403 })\n }\n\n const organizationId = (accessRow.workspace as { organizationId: string }).organizationId\n const normalizedEmail = input.email.toLowerCase().trim()\n const invitee = await getUserByEmail(normalizedEmail)\n const existingOrgMember = invitee ? await getOrganizationMember(organizationId, invitee.id) : null\n\n if (organizationRoleGrantsWorkspaceOwner(existingOrgMember?.role)) {\n return Response.json({ error: 'Organization admins already have project access' }, { status: 409 })\n }\n\n const existingInvite = await findExistingProjectInvite(input.workspaceId, normalizedEmail, invitee?.id)\n if (existingInvite) {\n return Response.json({ error: 'This collaborator is already invited to this project' }, { status: 409 })\n }\n\n if (enforceSeat && !existingOrgMember && !(await hasPendingOrgInvite(organizationId, normalizedEmail))) {\n try {\n await enforceSeat({ actorId: input.actor.id, organizationId })\n } catch (err) {\n if (err instanceof SeatLimitError) {\n return Response.json(\n { error: err.message, capability: err.capability, requiredPlan: err.requiredPlan },\n { status: err.status },\n )\n }\n throw err\n }\n }\n\n const token = generateInviteToken()\n const [member] = await db\n .insert(workspaceMembers)\n .values({\n workspaceId: input.workspaceId,\n organizationMemberId: existingOrgMember?.id ?? null,\n userId: invitee?.id ?? null,\n role: assignRole,\n invitedBy: input.actor.id,\n inviteEmail: normalizedEmail,\n inviteToken: token,\n })\n .returning()\n\n return Response.json({ member, inviteToken: token })\n }\n\n async function updateMemberRole(input: {\n workspaceId: string\n actor: MembersApiActor\n memberId?: string\n role?: string\n }): Promise<Response> {\n if (!input.memberId || !input.role) {\n return Response.json({ error: 'Missing memberId or role' }, { status: 400 })\n }\n if (input.memberId.startsWith('org:')) {\n return Response.json({ error: 'Organization owner/admin project access is managed at the organization level' }, { status: 403 })\n }\n if (!isAssignableWorkspaceRole(input.role)) {\n return Response.json({ error: 'Invalid role' }, { status: 400 })\n }\n\n const accessRow = await access.getWorkspaceAccess(input.workspaceId, input.actor.id, 'admin')\n if (!accessRow) return Response.json({ error: 'Workspace not found' }, { status: 404 })\n if (!hasWorkspaceRole(accessRow.role, input.role)) {\n return Response.json({ error: 'Cannot assign a role higher than your own' }, { status: 403 })\n }\n\n const [target] = await db\n .select({ id: workspaceMembers.id, role: workspaceMembers.role, userId: workspaceMembers.userId })\n .from(workspaceMembers)\n .where(and(eq(workspaceMembers.id, input.memberId), eq(workspaceMembers.workspaceId, input.workspaceId)))\n .limit(1)\n\n if (!target) return Response.json({ error: 'Member not found' }, { status: 404 })\n if (target.userId === input.actor.id) return Response.json({ error: 'Cannot change your own role' }, { status: 403 })\n if (!canManageWorkspaceMemberRole(accessRow.role, target.role as WorkspaceRole)) {\n return Response.json({ error: 'Cannot modify a member with equal or higher role' }, { status: 403 })\n }\n\n await db.update(workspaceMembers).set({ role: input.role }).where(eq(workspaceMembers.id, input.memberId))\n if (target.userId && memberSyncSeam?.role) {\n const userId = target.userId\n const nextRole = input.role as WorkspaceRole\n fireSync(() => memberSyncSeam.role!({ workspaceId: input.workspaceId, userId, role: nextRole }))\n }\n return Response.json({ success: true })\n }\n\n async function removeMember(input: {\n workspaceId: string\n actor: MembersApiActor\n memberId?: string\n }): Promise<Response> {\n if (!input.memberId) return Response.json({ error: 'Missing memberId' }, { status: 400 })\n if (input.memberId.startsWith('org:')) {\n return Response.json({ error: 'Organization owner/admin project access is managed at the organization level' }, { status: 403 })\n }\n\n const accessRow = await access.getWorkspaceAccess(input.workspaceId, input.actor.id, 'admin')\n if (!accessRow) return Response.json({ error: 'Workspace not found' }, { status: 404 })\n\n const [target] = await db\n .select({ id: workspaceMembers.id, role: workspaceMembers.role, userId: workspaceMembers.userId })\n .from(workspaceMembers)\n .where(and(eq(workspaceMembers.id, input.memberId), eq(workspaceMembers.workspaceId, input.workspaceId)))\n .limit(1)\n\n if (!target) return Response.json({ error: 'Member not found' }, { status: 404 })\n if (target.userId === input.actor.id) return Response.json({ error: 'Cannot remove yourself from this project' }, { status: 403 })\n if (!canManageWorkspaceMemberRole(accessRow.role, target.role as WorkspaceRole)) {\n return Response.json({ error: 'Cannot remove a member with equal or higher role' }, { status: 403 })\n }\n\n await db.delete(workspaceMembers).where(eq(workspaceMembers.id, input.memberId))\n if (target.userId && memberSyncSeam?.remove) {\n const userId = target.userId\n fireSync(() => memberSyncSeam.remove!({ workspaceId: input.workspaceId, userId }))\n }\n return Response.json({ success: true })\n }\n\n async function acceptInvite(input: { token?: string; actor: MembersApiActor }): Promise<Response> {\n if (!input.token || typeof input.token !== 'string') {\n return Response.json({ error: 'Missing invite token' }, { status: 400 })\n }\n\n const [invite] = await db\n .select()\n .from(workspaceMembers)\n .where(eq(workspaceMembers.inviteToken, input.token))\n .limit(1)\n\n if (!invite) return Response.json({ error: 'Invalid or expired invite' }, { status: 404 })\n if (invite.acceptedAt) return Response.json({ error: 'Invite already accepted' }, { status: 409 })\n\n if (invite.inviteEmail && invite.inviteEmail.toLowerCase() !== input.actor.email?.toLowerCase()) {\n return Response.json(\n { error: `This invite was sent to ${invite.inviteEmail}. Please sign in with that email.` },\n { status: 403 },\n )\n }\n\n const [workspace] = await db\n .select({ id: workspaces.id, organizationId: workspaces.organizationId })\n .from(workspaces)\n .where(eq(workspaces.id, invite.workspaceId))\n .limit(1)\n\n if (!workspace) return Response.json({ error: 'Project not found' }, { status: 404 })\n const organizationId = (workspace as { organizationId: string }).organizationId\n\n // Atomic accept: only succeeds if the token still exists and is unaccepted,\n // so two concurrent accepts can't both win.\n const updated = await db\n .update(workspaceMembers)\n .set({\n userId: input.actor.id,\n acceptedAt: new Date(),\n inviteToken: null,\n })\n .where(and(\n eq(workspaceMembers.inviteToken, input.token),\n isNull(workspaceMembers.acceptedAt),\n ))\n .returning({ id: workspaceMembers.id })\n\n if (updated.length === 0) return Response.json({ error: 'Invite already accepted' }, { status: 409 })\n\n const [orgMember] = await db\n .insert(organizationMembers)\n .values({\n organizationId,\n userId: input.actor.id,\n role: 'member',\n })\n .onConflictDoUpdate({\n target: [organizationMembers.organizationId, organizationMembers.userId],\n set: { updatedAt: new Date() },\n })\n .returning()\n\n await db\n .update(workspaceMembers)\n .set({ organizationMemberId: invite.organizationMemberId ?? orgMember!.id })\n .where(eq(workspaceMembers.id, updated[0]!.id))\n\n if (memberSyncSeam?.add) {\n const role = invite.role as WorkspaceRole\n fireSync(() => memberSyncSeam.add!({ workspaceId: invite.workspaceId, userId: input.actor.id, role }))\n }\n\n return Response.json({\n success: true,\n workspaceId: invite.workspaceId,\n role: invite.role,\n })\n }\n\n // ── internal query helpers ──\n\n async function getUserByEmail(email: string) {\n const [user] = await db\n .select({ id: users.id, email: users.email })\n .from(users)\n .where(eq(users.email, email))\n .limit(1)\n return user ?? null\n }\n\n async function getOrganizationMember(organizationId: string, userId: string) {\n const [member] = await db\n .select()\n .from(organizationMembers)\n .where(and(eq(organizationMembers.organizationId, organizationId), eq(organizationMembers.userId, userId)))\n .limit(1)\n return member ?? null\n }\n\n async function findExistingProjectInvite(workspaceId: string, email: string, userId?: string) {\n const byEmail = await db\n .select({ id: workspaceMembers.id })\n .from(workspaceMembers)\n .where(and(eq(workspaceMembers.workspaceId, workspaceId), eq(workspaceMembers.inviteEmail, email)))\n .limit(1)\n if (byEmail[0]) return byEmail[0]\n if (!userId) return null\n const byUser = await db\n .select({ id: workspaceMembers.id })\n .from(workspaceMembers)\n .where(and(eq(workspaceMembers.workspaceId, workspaceId), eq(workspaceMembers.userId, userId)))\n .limit(1)\n return byUser[0] ?? null\n }\n\n async function hasPendingOrgInvite(organizationId: string, email: string): Promise<boolean> {\n const [row] = await db\n .select({ id: workspaceMembers.id })\n .from(workspaceMembers)\n .innerJoin(workspaces, eq(workspaces.id, workspaceMembers.workspaceId))\n .where(and(\n eq(workspaces.organizationId, organizationId),\n eq(workspaceMembers.inviteEmail, email),\n isNull(workspaceMembers.acceptedAt),\n ))\n .limit(1)\n return Boolean(row)\n }\n\n return { listMembers, inviteMember, updateMemberRole, removeMember, acceptInvite }\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/teams/members-api.ts"],"sourcesContent":["/**\n * Framework-neutral members API for the teams module: the invite / list /\n * update-role / remove / accept-invite logic, lifted out of any one app's route\n * file. Each app mounts these in its own route with its own auth — the handlers\n * take an already-authenticated `actor`, the parsed inputs, the `db` + `tables`\n * from `createTeamTables`, the product's user + workspace tables, and the\n * workspace-access API from `createWorkspaceAccess`. They return web-standard\n * `Response`s (available in Workers, Node 18+, Deno, browsers), so\n * \"framework-neutral\" is literal: no Remix/React-Router/Express import anywhere.\n *\n * Two OPTIONAL seams an app wires only if it needs them:\n * - `enforceSeat` — billing/seat-limit gate, called at invite time only when\n * the invite would consume a NEW billable seat. An app without seat billing\n * passes nothing and seats are never checked.\n * - `memberSyncSeam` — fire-and-forget propagation of membership changes to a\n * sandbox/external system (add on accept, role on update, remove on\n * delete). An app without sandbox sync passes nothing. Fail-soft by\n * contract: a thrown sync is caught and never blocks the DB mutation.\n *\n * Imports `drizzle-orm`, so this is a subpath, never re-exported from root.\n */\n\nimport { and, eq, isNull } from 'drizzle-orm'\nimport {\n type AssignableWorkspaceRole,\n type WorkspaceRole,\n canManageWorkspaceMemberRole,\n hasWorkspaceRole,\n isAssignableWorkspaceRole,\n organizationRoleGrantsWorkspaceOwner,\n} from './roles'\nimport { generateInviteToken } from './invite'\nimport type { TeamDatabase, WorkspaceAccessApi } from './drizzle/access'\nimport type { TeamParentTable, TeamTables } from './drizzle/schema'\n\n/** The authenticated caller — apps resolve this from their own session layer. */\nexport interface MembersApiActor {\n id: string\n email?: string | null\n}\n\n/**\n * The product's user table, narrowed to the columns the member queries read.\n * Adopters pass their real drizzle user table.\n */\nexport interface UserLookupTable {\n id: any\n name: any\n email: any\n}\n\n/**\n * The product's workspace table, narrowed to the columns the member queries\n * read. The handlers join it to resolve a workspace's organization (the same\n * table passed to createTeamTables as workspaceTable).\n */\nexport interface WorkspaceLookupTable {\n id: any\n organizationId: any\n}\n\n/**\n * Optional billing seat gate. The seam resolves the count input itself (it\n * owns the plan/seat model) and throws when over the limit; the handler turns a\n * thrown `SeatLimitError` into a 402. Called only when an invite would consume\n * a NEW seat (invitee is not already an org member and has no pending org\n * invite) — the same guard gtm uses, so the seam never fires on a no-op invite.\n */\nexport interface EnforceSeatSeam {\n (input: { actorId: string; organizationId: string }): Promise<void> | void\n}\n\n/** Thrown by an `enforceSeat` seam to deny an invite; serialized to a 402. */\nexport class SeatLimitError extends Error {\n readonly status: number\n readonly capability?: string\n readonly requiredPlan?: string\n constructor(message: string, opts: { status?: number; capability?: string; requiredPlan?: string } = {}) {\n super(message)\n this.name = 'SeatLimitError'\n this.status = opts.status ?? 402\n this.capability = opts.capability\n this.requiredPlan = opts.requiredPlan\n }\n}\n\n/**\n * Optional membership-change propagation to an external system (e.g. sandbox).\n * Every method is fire-and-forget and fail-soft: the handler awaits nothing and\n * swallows rejections, so an unavailable downstream never blocks the mutation.\n * Each fires only for members with a real `userId` (never email-only invites).\n */\nexport interface MemberSyncSeam {\n add?(input: { workspaceId: string; userId: string; role: WorkspaceRole }): Promise<void> | void\n role?(input: { workspaceId: string; userId: string; role: WorkspaceRole }): Promise<void> | void\n remove?(input: { workspaceId: string; userId: string }): Promise<void> | void\n}\n\n/** Define configuration options for managing team members and workspace access APIs */\nexport interface MembersApiOptions {\n db: TeamDatabase\n tables: TeamTables\n /** The product's user table (FK target passed to createTeamTables). */\n userTable: TeamParentTable & UserLookupTable\n /** The product's workspace table (FK target passed to createTeamTables). */\n workspaceTable: TeamParentTable & WorkspaceLookupTable\n /** Workspace-access API from createWorkspaceAccess — RBAC stays one source. */\n access: Pick<WorkspaceAccessApi, 'getWorkspaceAccess'>\n enforceSeat?: EnforceSeatSeam\n memberSyncSeam?: MemberSyncSeam\n}\n\n/** Define the structure of a workspace member entry with identification, role, and status details */\nexport interface MemberListEntry {\n id: string\n userId: string | null\n organizationMemberId: string | null\n role: WorkspaceRole\n name: string | null\n email: string | null\n invitedAt: Date | number | null\n acceptedAt: Date | number | null\n inherited: boolean\n}\n\n/**\n * Build the members API bound to one product's db/tables/access. Returns five\n * handlers; an app maps its route methods onto them (GET→list, POST→invite,\n * PATCH→updateRole, DELETE→remove; accept on its own route).\n */\nexport function createMembersApi(opts: MembersApiOptions) {\n const { db, tables, userTable, workspaceTable, access, enforceSeat, memberSyncSeam } = opts\n const { organizations, organizationMembers, workspaceMembers } = tables\n const users = userTable\n const workspaces = workspaceTable\n\n function fireSync(op: () => Promise<void> | void) {\n try {\n Promise.resolve(op()).catch(() => {})\n } catch {\n // seam threw synchronously — swallow; sync is best-effort by contract.\n }\n }\n\n async function listMembers(input: { workspaceId: string; actor: MembersApiActor }): Promise<Response> {\n const accessRow = await access.getWorkspaceAccess(input.workspaceId, input.actor.id)\n if (!accessRow) return Response.json({ error: 'Workspace not found' }, { status: 404 })\n\n const organizationId = (accessRow.workspace as { organizationId: string }).organizationId\n\n const [projectMembers, orgAdmins] = await Promise.all([\n db\n .select({\n id: workspaceMembers.id,\n organizationMemberId: workspaceMembers.organizationMemberId,\n userId: workspaceMembers.userId,\n role: workspaceMembers.role,\n invitedAt: workspaceMembers.invitedAt,\n acceptedAt: workspaceMembers.acceptedAt,\n inviteEmail: workspaceMembers.inviteEmail,\n userName: users.name,\n userEmail: users.email,\n })\n .from(workspaceMembers)\n .leftJoin(users, eq(users.id, workspaceMembers.userId))\n .where(eq(workspaceMembers.workspaceId, input.workspaceId)),\n db\n .select({\n id: organizationMembers.id,\n userId: organizationMembers.userId,\n orgRole: organizationMembers.role,\n userName: users.name,\n userEmail: users.email,\n createdAt: organizationMembers.createdAt,\n })\n .from(organizationMembers)\n .innerJoin(users, eq(users.id, organizationMembers.userId))\n .where(eq(organizationMembers.organizationId, organizationId)),\n ])\n\n const explicitOrgMemberIds = new Set(\n projectMembers.map((m: any) => m.organizationMemberId).filter(Boolean),\n )\n const members: MemberListEntry[] = [\n ...orgAdmins\n .filter((m: any) => organizationRoleGrantsWorkspaceOwner(m.orgRole) && !explicitOrgMemberIds.has(m.id))\n .map((m: any) => ({\n id: `org:${m.id}`,\n userId: m.userId,\n organizationMemberId: m.id,\n role: 'owner' as WorkspaceRole,\n name: m.userName,\n email: m.userEmail,\n invitedAt: m.createdAt,\n acceptedAt: m.createdAt,\n inherited: true,\n })),\n ...projectMembers.map((m: any) => ({\n id: m.id,\n userId: m.userId,\n organizationMemberId: m.organizationMemberId,\n role: m.role as WorkspaceRole,\n name: m.userName,\n email: m.userEmail ?? m.inviteEmail,\n invitedAt: m.invitedAt,\n acceptedAt: m.acceptedAt,\n inherited: false,\n })),\n ]\n\n return Response.json({ members, currentRole: accessRow.role, organizationId })\n }\n\n async function inviteMember(input: {\n workspaceId: string\n actor: MembersApiActor\n email?: string\n role?: string\n }): Promise<Response> {\n if (!input.email) return Response.json({ error: 'Missing email' }, { status: 400 })\n const requestedRole = input.role ?? 'editor'\n if (!isAssignableWorkspaceRole(requestedRole)) {\n return Response.json({ error: 'Invalid role. Must be viewer, editor, or admin.' }, { status: 400 })\n }\n const assignRole: AssignableWorkspaceRole = requestedRole\n const accessRow = await access.getWorkspaceAccess(input.workspaceId, input.actor.id, 'admin')\n if (!accessRow) return Response.json({ error: 'Workspace not found' }, { status: 404 })\n if (!hasWorkspaceRole(accessRow.role, assignRole)) {\n return Response.json({ error: 'Cannot assign a role higher than your own' }, { status: 403 })\n }\n\n const organizationId = (accessRow.workspace as { organizationId: string }).organizationId\n const normalizedEmail = input.email.toLowerCase().trim()\n const invitee = await getUserByEmail(normalizedEmail)\n const existingOrgMember = invitee ? await getOrganizationMember(organizationId, invitee.id) : null\n\n if (organizationRoleGrantsWorkspaceOwner(existingOrgMember?.role)) {\n return Response.json({ error: 'Organization admins already have project access' }, { status: 409 })\n }\n\n const existingInvite = await findExistingProjectInvite(input.workspaceId, normalizedEmail, invitee?.id)\n if (existingInvite) {\n return Response.json({ error: 'This collaborator is already invited to this project' }, { status: 409 })\n }\n\n if (enforceSeat && !existingOrgMember && !(await hasPendingOrgInvite(organizationId, normalizedEmail))) {\n try {\n await enforceSeat({ actorId: input.actor.id, organizationId })\n } catch (err) {\n if (err instanceof SeatLimitError) {\n return Response.json(\n { error: err.message, capability: err.capability, requiredPlan: err.requiredPlan },\n { status: err.status },\n )\n }\n throw err\n }\n }\n\n const token = generateInviteToken()\n const [member] = await db\n .insert(workspaceMembers)\n .values({\n workspaceId: input.workspaceId,\n organizationMemberId: existingOrgMember?.id ?? null,\n userId: invitee?.id ?? null,\n role: assignRole,\n invitedBy: input.actor.id,\n inviteEmail: normalizedEmail,\n inviteToken: token,\n })\n .returning()\n\n return Response.json({ member, inviteToken: token })\n }\n\n async function updateMemberRole(input: {\n workspaceId: string\n actor: MembersApiActor\n memberId?: string\n role?: string\n }): Promise<Response> {\n if (!input.memberId || !input.role) {\n return Response.json({ error: 'Missing memberId or role' }, { status: 400 })\n }\n if (input.memberId.startsWith('org:')) {\n return Response.json({ error: 'Organization owner/admin project access is managed at the organization level' }, { status: 403 })\n }\n if (!isAssignableWorkspaceRole(input.role)) {\n return Response.json({ error: 'Invalid role' }, { status: 400 })\n }\n\n const accessRow = await access.getWorkspaceAccess(input.workspaceId, input.actor.id, 'admin')\n if (!accessRow) return Response.json({ error: 'Workspace not found' }, { status: 404 })\n if (!hasWorkspaceRole(accessRow.role, input.role)) {\n return Response.json({ error: 'Cannot assign a role higher than your own' }, { status: 403 })\n }\n\n const [target] = await db\n .select({ id: workspaceMembers.id, role: workspaceMembers.role, userId: workspaceMembers.userId })\n .from(workspaceMembers)\n .where(and(eq(workspaceMembers.id, input.memberId), eq(workspaceMembers.workspaceId, input.workspaceId)))\n .limit(1)\n\n if (!target) return Response.json({ error: 'Member not found' }, { status: 404 })\n if (target.userId === input.actor.id) return Response.json({ error: 'Cannot change your own role' }, { status: 403 })\n if (!canManageWorkspaceMemberRole(accessRow.role, target.role as WorkspaceRole)) {\n return Response.json({ error: 'Cannot modify a member with equal or higher role' }, { status: 403 })\n }\n\n await db.update(workspaceMembers).set({ role: input.role }).where(eq(workspaceMembers.id, input.memberId))\n if (target.userId && memberSyncSeam?.role) {\n const userId = target.userId\n const nextRole = input.role as WorkspaceRole\n fireSync(() => memberSyncSeam.role!({ workspaceId: input.workspaceId, userId, role: nextRole }))\n }\n return Response.json({ success: true })\n }\n\n async function removeMember(input: {\n workspaceId: string\n actor: MembersApiActor\n memberId?: string\n }): Promise<Response> {\n if (!input.memberId) return Response.json({ error: 'Missing memberId' }, { status: 400 })\n if (input.memberId.startsWith('org:')) {\n return Response.json({ error: 'Organization owner/admin project access is managed at the organization level' }, { status: 403 })\n }\n\n const accessRow = await access.getWorkspaceAccess(input.workspaceId, input.actor.id, 'admin')\n if (!accessRow) return Response.json({ error: 'Workspace not found' }, { status: 404 })\n\n const [target] = await db\n .select({ id: workspaceMembers.id, role: workspaceMembers.role, userId: workspaceMembers.userId })\n .from(workspaceMembers)\n .where(and(eq(workspaceMembers.id, input.memberId), eq(workspaceMembers.workspaceId, input.workspaceId)))\n .limit(1)\n\n if (!target) return Response.json({ error: 'Member not found' }, { status: 404 })\n if (target.userId === input.actor.id) return Response.json({ error: 'Cannot remove yourself from this project' }, { status: 403 })\n if (!canManageWorkspaceMemberRole(accessRow.role, target.role as WorkspaceRole)) {\n return Response.json({ error: 'Cannot remove a member with equal or higher role' }, { status: 403 })\n }\n\n await db.delete(workspaceMembers).where(eq(workspaceMembers.id, input.memberId))\n if (target.userId && memberSyncSeam?.remove) {\n const userId = target.userId\n fireSync(() => memberSyncSeam.remove!({ workspaceId: input.workspaceId, userId }))\n }\n return Response.json({ success: true })\n }\n\n async function acceptInvite(input: { token?: string; actor: MembersApiActor }): Promise<Response> {\n if (!input.token || typeof input.token !== 'string') {\n return Response.json({ error: 'Missing invite token' }, { status: 400 })\n }\n\n const [invite] = await db\n .select()\n .from(workspaceMembers)\n .where(eq(workspaceMembers.inviteToken, input.token))\n .limit(1)\n\n if (!invite) return Response.json({ error: 'Invalid or expired invite' }, { status: 404 })\n if (invite.acceptedAt) return Response.json({ error: 'Invite already accepted' }, { status: 409 })\n\n if (invite.inviteEmail && invite.inviteEmail.toLowerCase() !== input.actor.email?.toLowerCase()) {\n return Response.json(\n { error: `This invite was sent to ${invite.inviteEmail}. Please sign in with that email.` },\n { status: 403 },\n )\n }\n\n const [workspace] = await db\n .select({ id: workspaces.id, organizationId: workspaces.organizationId })\n .from(workspaces)\n .where(eq(workspaces.id, invite.workspaceId))\n .limit(1)\n\n if (!workspace) return Response.json({ error: 'Project not found' }, { status: 404 })\n const organizationId = (workspace as { organizationId: string }).organizationId\n\n // Atomic accept: only succeeds if the token still exists and is unaccepted,\n // so two concurrent accepts can't both win.\n const updated = await db\n .update(workspaceMembers)\n .set({\n userId: input.actor.id,\n acceptedAt: new Date(),\n inviteToken: null,\n })\n .where(and(\n eq(workspaceMembers.inviteToken, input.token),\n isNull(workspaceMembers.acceptedAt),\n ))\n .returning({ id: workspaceMembers.id })\n\n if (updated.length === 0) return Response.json({ error: 'Invite already accepted' }, { status: 409 })\n\n const [orgMember] = await db\n .insert(organizationMembers)\n .values({\n organizationId,\n userId: input.actor.id,\n role: 'member',\n })\n .onConflictDoUpdate({\n target: [organizationMembers.organizationId, organizationMembers.userId],\n set: { updatedAt: new Date() },\n })\n .returning()\n\n await db\n .update(workspaceMembers)\n .set({ organizationMemberId: invite.organizationMemberId ?? orgMember!.id })\n .where(eq(workspaceMembers.id, updated[0]!.id))\n\n if (memberSyncSeam?.add) {\n const role = invite.role as WorkspaceRole\n fireSync(() => memberSyncSeam.add!({ workspaceId: invite.workspaceId, userId: input.actor.id, role }))\n }\n\n return Response.json({\n success: true,\n workspaceId: invite.workspaceId,\n role: invite.role,\n })\n }\n\n // ── internal query helpers ──\n\n async function getUserByEmail(email: string) {\n const [user] = await db\n .select({ id: users.id, email: users.email })\n .from(users)\n .where(eq(users.email, email))\n .limit(1)\n return user ?? null\n }\n\n async function getOrganizationMember(organizationId: string, userId: string) {\n const [member] = await db\n .select()\n .from(organizationMembers)\n .where(and(eq(organizationMembers.organizationId, organizationId), eq(organizationMembers.userId, userId)))\n .limit(1)\n return member ?? null\n }\n\n async function findExistingProjectInvite(workspaceId: string, email: string, userId?: string) {\n const byEmail = await db\n .select({ id: workspaceMembers.id })\n .from(workspaceMembers)\n .where(and(eq(workspaceMembers.workspaceId, workspaceId), eq(workspaceMembers.inviteEmail, email)))\n .limit(1)\n if (byEmail[0]) return byEmail[0]\n if (!userId) return null\n const byUser = await db\n .select({ id: workspaceMembers.id })\n .from(workspaceMembers)\n .where(and(eq(workspaceMembers.workspaceId, workspaceId), eq(workspaceMembers.userId, userId)))\n .limit(1)\n return byUser[0] ?? null\n }\n\n async function hasPendingOrgInvite(organizationId: string, email: string): Promise<boolean> {\n const [row] = await db\n .select({ id: workspaceMembers.id })\n .from(workspaceMembers)\n .innerJoin(workspaces, eq(workspaces.id, workspaceMembers.workspaceId))\n .where(and(\n eq(workspaces.organizationId, organizationId),\n eq(workspaceMembers.inviteEmail, email),\n isNull(workspaceMembers.acceptedAt),\n ))\n .limit(1)\n return Boolean(row)\n }\n\n return { listMembers, inviteMember, updateMemberRole, removeMember, acceptInvite }\n}\n"],"mappings":"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","names":[]}
@@ -1165,4 +1165,4 @@ export {
1165
1165
  buildAgentMissionPlan,
1166
1166
  stepAgentActivity
1167
1167
  };
1168
- //# sourceMappingURL=chunk-YNALYIQ3.js.map
1168
+ //# sourceMappingURL=chunk-NLSSFLLS.js.map