nolo-cli 0.213.0 → 0.222.0-alpha.2

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 (262) hide show
  1. package/README.md +3 -2
  2. package/{_executeModel-CUJLCFWR.js → _executeModel-4GGQQHOB.js} +111 -82
  3. package/{accountResolver-4LKIHEKL.js → accountResolver-EK2S4PWF.js} +6 -6
  4. package/{action-DF5UYSJF.js → action-CK64LS6S.js} +12 -11
  5. package/{addContentAction-WERAONNY.js → addContentAction-GDHDOF4U.js} +18 -17
  6. package/{addDialogAgentAction-7VI7YRML.js → addDialogAgentAction-CAKRU3ZT.js} +21 -20
  7. package/{agentDeleteCommand-XJORXPGU.js → agentDeleteCommand-BPV2XZL7.js} +128 -119
  8. package/{agentEmailCommands-XTYYFR6Z.js → agentEmailCommands-EJOS75YL.js} +132 -124
  9. package/{agentFavoriteCommands-EDK743YA.js → agentFavoriteCommands-2LKGKSUD.js} +7 -8
  10. package/{agentGrantCommands-RQWK2TEV.js → agentGrantCommands-QQV4N4JW.js} +5 -5
  11. package/{agentListCommands-OBLRBLHS.js → agentListCommands-HIZODBF3.js} +155 -92
  12. package/{agentMachineCommands-5FMT3OT5.js → agentMachineCommands-ZMQ2CY7Y.js} +62 -54
  13. package/{agentProviderCommands-Q5O33MED.js → agentProviderCommands-WKJOAWBP.js} +5 -5
  14. package/{agentPullCommand-6EM3URVK.js → agentPullCommand-XN6ZPBUW.js} +7 -7
  15. package/agentRecordCommands-OMXVDLDX.js +176 -0
  16. package/agentRunCommand-CB34YWMV.js +206 -0
  17. package/{agentRunControl-TAMHJQSR.js → agentRunControl-JNONH3RP.js} +30 -15
  18. package/{agentRuntimeLocal-SOO2OPJG.js → agentRuntimeLocal-QZPFWMLG.js} +52 -45
  19. package/{agentSlice-CHR6KOZN.js → agentSlice-RD2CDU7T.js} +20 -19
  20. package/{appDeleteCommands-GUP6P5YE.js → appDeleteCommands-QCCFDIEQ.js} +61 -53
  21. package/{appDeployCommands-MH2FX4O5.js → appDeployCommands-V2T7TNMQ.js} +61 -53
  22. package/{appDeployStatusCommands-SUHN3HPJ.js → appDeployStatusCommands-6PGH7ZCG.js} +61 -53
  23. package/{appGetCommands-YWDEX6Z4.js → appGetCommands-3L7WWJA6.js} +61 -53
  24. package/{appListCommands-ZQVMLPAY.js → appListCommands-ENJCK4PO.js} +61 -53
  25. package/{authCommand-PWX2ZNUP.js → authCommand-6V47SYGK.js} +29 -28
  26. package/{authCommands-HV3EAU3V.js → authCommands-GAJ3NIXO.js} +14 -13
  27. package/{builtinSkillRegistry-2QETTQPM.js → builtinSkillRegistry-2ECA42FC.js} +11 -13
  28. package/{chromeCommands-REEAH4SX.js → chromeCommands-G5UDKVSV.js} +3 -3
  29. package/{chromeOpsCommands-DIVM2K3T.js → chromeOpsCommands-YKX2QX3A.js} +20 -10
  30. package/{chunk-CRHOO2ZR.js → chunk-27PCUMJI.js} +2 -2
  31. package/chunk-2CI3ZFWD.js +97 -0
  32. package/{chunk-NSAPDIN2.js → chunk-2GJKRKI6.js} +541 -31
  33. package/{chunk-SM3NSZJV.js → chunk-2UCBGYO4.js} +20 -1
  34. package/{chunk-PYRUW7XN.js → chunk-2VUZSVAS.js} +136 -54
  35. package/{chunk-YB3YZK56.js → chunk-2WZXXAQD.js} +1 -67
  36. package/chunk-2YGBI2XB.js +30 -0
  37. package/chunk-2ZKFCIJJ.js +13 -0
  38. package/{chunk-QG4AOSON.js → chunk-34J5K2YA.js} +13 -32
  39. package/{chunk-LOEO7LRC.js → chunk-3IK6ILVW.js} +4 -1
  40. package/{chunk-CTPXME7U.js → chunk-3LMUPOHG.js} +29 -6
  41. package/chunk-44X52WOJ.js +1621 -0
  42. package/{chunk-6VLJ6YA7.js → chunk-4DESLZTK.js} +9 -9
  43. package/{chunk-MYOH447Z.js → chunk-4JVNURX4.js} +1 -1
  44. package/chunk-5CHGAKRT.js +364 -0
  45. package/{chunk-YDH3FDFQ.js → chunk-5FUN7EG4.js} +1 -1
  46. package/{chunk-INUFILG6.js → chunk-5RKUPJYL.js} +1 -1
  47. package/{chunk-ZC3CMUKU.js → chunk-6OVNSQHN.js} +84 -2
  48. package/{chunk-MOIJOHA5.js → chunk-6WU5572L.js} +36 -25
  49. package/{chunk-IXNGOHV5.js → chunk-7EEZJ6BS.js} +11 -152
  50. package/{chunk-Y6ORVLSS.js → chunk-7ET2U67U.js} +1 -1
  51. package/{chunk-G7MLNNEX.js → chunk-7JLY4WYF.js} +5 -5
  52. package/{chunk-P5L7CXOC.js → chunk-7Z6EW7AH.js} +3 -2
  53. package/{chunk-NJLL224W.js → chunk-AD5EWDFD.js} +2 -2
  54. package/{chunk-J2NHJ7WX.js → chunk-AIHYNKGV.js} +4 -4
  55. package/{chunk-HPFCI4SK.js → chunk-AK5O76CC.js} +3 -3
  56. package/{chunk-Y63ZSOR6.js → chunk-AL3TYDIF.js} +1 -1
  57. package/{chunk-ALQ3657A.js → chunk-AMEOV5VZ.js} +32 -12
  58. package/chunk-AN74ON4G.js +675 -0
  59. package/{chunk-HRMJUN5J.js → chunk-AQZ6BMRK.js} +1 -1
  60. package/{chunk-XHQC4PXX.js → chunk-B4GOW4MT.js} +424 -194
  61. package/{chunk-4KB6WQUL.js → chunk-BGP2EDFG.js} +1 -1
  62. package/{chunk-NBTY7YJF.js → chunk-BR3GT6MR.js} +1 -0
  63. package/{chunk-7RFNTILS.js → chunk-BUDVRYES.js} +2 -2
  64. package/{chunk-SVYO6AO7.js → chunk-BV3FLP2L.js} +41 -1
  65. package/{chunk-RZOV7OMV.js → chunk-C4VAR65S.js} +83 -141
  66. package/{chunk-COFEN36Z.js → chunk-C4WTX5TU.js} +2 -2
  67. package/{chunk-ZL5RAEEB.js → chunk-CIRB724Q.js} +1 -1
  68. package/{chunk-F6UUQOG6.js → chunk-CKT6QUE2.js} +4 -4
  69. package/{chunk-X7SDOJUM.js → chunk-CMZ3Z5PT.js} +14 -14
  70. package/{secretCommands-LXDWOLZ6.js → chunk-D726I5AZ.js} +191 -16
  71. package/{chunk-TAKB25RM.js → chunk-DNKTQ3IN.js} +4 -4
  72. package/chunk-DVQH4BTR.js +1137 -0
  73. package/{chunk-WYDI6TGM.js → chunk-DWX2HEVC.js} +91 -132
  74. package/{chunk-5MQRBSMW.js → chunk-EIAI3PPH.js} +111 -113
  75. package/chunk-EUCFKKDM.js +247 -0
  76. package/chunk-EWQ3HGNZ.js +90 -0
  77. package/{chunk-RPQXPZZF.js → chunk-F3GRJO4Z.js} +908 -13
  78. package/{chunk-YTF4WH7J.js → chunk-FIYSMXHY.js} +1 -1
  79. package/{chunk-75XIDFBW.js → chunk-FJ23FZXF.js} +72 -28
  80. package/{chunk-INN4LTAJ.js → chunk-FJK526XH.js} +2 -2
  81. package/chunk-FS2XP5D7.js +142 -0
  82. package/{chunk-FUGMREBO.js → chunk-FYF2TONJ.js} +5 -5
  83. package/{chunk-PCLE46CE.js → chunk-GBWGPTA7.js} +2 -1
  84. package/{chunk-TX5EYMGT.js → chunk-GYVCJABP.js} +30 -254
  85. package/{chunk-3UKL3HPD.js → chunk-HOCHUZQ7.js} +8 -78
  86. package/{chunk-EHSZD5OI.js → chunk-HXER7YJF.js} +4 -4
  87. package/chunk-HYIETXA6.js +99 -0
  88. package/{chunk-H2TJUNCH.js → chunk-I4EADJ4P.js} +6 -6
  89. package/{chunk-TCZHTTUU.js → chunk-I7WBYGBP.js} +8 -8
  90. package/{chunk-6DWMYIUY.js → chunk-IILMY4W4.js} +14 -9
  91. package/chunk-JA3ICVJY.js +271 -0
  92. package/{chunk-ZRSNONOB.js → chunk-JWXITTQB.js} +8 -3
  93. package/{chunk-H4UOTUOX.js → chunk-KEN3N2TN.js} +148 -18
  94. package/{chunk-LEC5ALIN.js → chunk-KEPOVMF4.js} +1 -1
  95. package/{chunk-UHJGXRJ4.js → chunk-KQSYAIZR.js} +3 -3
  96. package/{chunk-4VJAC32I.js → chunk-L5I543VB.js} +3 -2
  97. package/chunk-LKA64WH4.js +227 -0
  98. package/{chunk-QHPRUL4O.js → chunk-LVL6GFCM.js} +4 -4
  99. package/{chunk-H5HF7TJA.js → chunk-MAIITKBT.js} +2 -2
  100. package/chunk-MBG66ZBH.js +226 -0
  101. package/{chunk-YUA6OAH5.js → chunk-MDLS23JK.js} +2 -2
  102. package/{chunk-VL5KOY2C.js → chunk-MK2Q7ZJD.js} +67 -5
  103. package/{chunk-MDB67IWP.js → chunk-MS4NZNKI.js} +10 -10
  104. package/{chunk-VO4WSAVP.js → chunk-MYHNBEXD.js} +3 -3
  105. package/{chunk-ZXOUUDCG.js → chunk-MZLE5HQ3.js} +3654 -231
  106. package/{chunk-AZMYUSVF.js → chunk-N5Z2V73W.js} +1 -1
  107. package/{chunk-V5Y3R6BT.js → chunk-NIZ2BXFD.js} +213 -210
  108. package/{chunk-KFLT5KAD.js → chunk-NWP2OYOX.js} +20 -20
  109. package/{chunk-G2BQWAVT.js → chunk-O6J3OTOP.js} +4 -4
  110. package/{chunk-VNYYOX3V.js → chunk-OB6DVWPF.js} +141 -48
  111. package/{chunk-YWSEPJ7C.js → chunk-OBWT45ZU.js} +3 -3
  112. package/{chunk-ZNWI6OVT.js → chunk-ODJ7BVSI.js} +80 -11
  113. package/{chunk-XJWWBO34.js → chunk-OJKUU3LP.js} +5 -7
  114. package/{chunk-HUBHAQK2.js → chunk-ON37YXGX.js} +29 -29
  115. package/{chunk-UYD5HQ6T.js → chunk-P5ZJRTCH.js} +5429 -1752
  116. package/{chunk-6XIE5ZGI.js → chunk-PDCV7P5W.js} +1 -1
  117. package/{chunk-WRYQ35LQ.js → chunk-PJCIP64Z.js} +859 -57
  118. package/{chunk-7QTZCMKL.js → chunk-PJVKMGPZ.js} +1089 -1639
  119. package/{chunk-A7TFUNZO.js → chunk-PPJYZRSQ.js} +6 -2
  120. package/chunk-QHEN7NZ7.js +46 -0
  121. package/{chunk-OQPKUBPB.js → chunk-QNWG52I4.js} +19 -7
  122. package/{chunk-YGILMZ7N.js → chunk-QVBXJNZ2.js} +1 -1
  123. package/{chunk-7BT37FK3.js → chunk-RDH5CQ4T.js} +648 -131
  124. package/{chunk-C6KNNXWU.js → chunk-RGQ4UUWZ.js} +25 -2
  125. package/{chunk-OWYYDMGJ.js → chunk-S2NTVGA2.js} +4 -2
  126. package/{chunk-KC4XDTT3.js → chunk-SOF4OWDM.js} +6 -4
  127. package/{chunk-RLBNLZVC.js → chunk-SQYIK6HO.js} +1 -1
  128. package/{chunk-YJAFKXMU.js → chunk-SVT62ULE.js} +50 -48
  129. package/{chunk-KIM6CLW5.js → chunk-SY3C4SQ7.js} +42 -15
  130. package/{chunk-JY5NGFFH.js → chunk-SYTHYBMI.js} +5 -5
  131. package/{chunk-WMTBPBMP.js → chunk-T6DXNI6Z.js} +52 -50
  132. package/chunk-TLE77UJ5.js +230 -0
  133. package/{chunk-4VNS5WPM.js → chunk-U67V476Y.js} +1 -8
  134. package/{chunk-F7CI2ZC5.js → chunk-UAIHKQIA.js} +2 -1
  135. package/{chunk-R5O4QAWG.js → chunk-UB3D4TRQ.js} +11 -77
  136. package/{chunk-WPORQFYN.js → chunk-UVLYNWIE.js} +2 -2
  137. package/{chunk-NOKUNJON.js → chunk-UYOICCYG.js} +29 -19
  138. package/{chunk-4I7ERB7F.js → chunk-VREDDN25.js} +1 -1
  139. package/{chunk-O2TZF4AI.js → chunk-WAE3GFCJ.js} +3 -3
  140. package/{chunk-H7PPIYWP.js → chunk-WI67URFP.js} +20 -20
  141. package/{chunk-7OCO4TDT.js → chunk-WJVYAO6P.js} +1 -1
  142. package/{chunk-T43B7LB2.js → chunk-WKGQSYTB.js} +1 -1
  143. package/{chunk-BBJ22CLB.js → chunk-WUUH4LWZ.js} +60 -30
  144. package/{chunk-4T2WNOY7.js → chunk-X7UF53VA.js} +33 -22
  145. package/{chunk-TY3TIUJK.js → chunk-XI2BWJM5.js} +65 -0
  146. package/{chunk-LLRPJECG.js → chunk-XWVCYUUU.js} +16 -159
  147. package/{chunk-J5JTMQIA.js → chunk-YFLVRVYK.js} +1 -1
  148. package/{chunk-EYLGAEB4.js → chunk-YGMBIXCF.js} +132 -0
  149. package/chunk-YL3EFYL3.js +199 -0
  150. package/{chunk-MMA3LZ3W.js → chunk-YNIYE47Z.js} +1 -1
  151. package/{chunk-W4S457LU.js → chunk-YU4ZPWVF.js} +41 -5
  152. package/{chunk-7Y4YTDQF.js → chunk-YWWDC3O7.js} +281 -159
  153. package/chunk-YZMNK53S.js +68 -0
  154. package/{chunk-RSHTSUEG.js → chunk-Z2PITYZN.js} +2060 -602
  155. package/{chunk-FY7F4Q6X.js → chunk-Z4PCXPUE.js} +2 -2
  156. package/{cliAgentConfigHelpers-WJBZQTLW.js → cliAgentConfigHelpers-TKYL43MT.js} +15 -16
  157. package/{cliAuthorityBrokerClient-PM3U6Q6J.js → cliAuthorityBrokerClient-XHH7MH2P.js} +1 -1
  158. package/{cliAuthorityStoreDriver-TKLXNNTG.js → cliAuthorityStoreDriver-6FE3BJNB.js} +1 -1
  159. package/{cliEnvHelpers-BVYTMUPJ.js → cliEnvHelpers-VPSJ4XWC.js} +3 -3
  160. package/{cliExecutor-BWBF2MTI.js → cliExecutor-4MAX3PZL.js} +2 -2
  161. package/cliLocalAgentRecordReader-MHHD4T7R.js +90 -0
  162. package/{commandRegistry-W63CYRZJ.js → commandRegistry-5DA5UP7S.js} +105 -97
  163. package/{contentThunks-U7PL5MQD.js → contentThunks-5GUQ7FWJ.js} +47 -43
  164. package/{cooldownCommands-TIGUHXTD.js → cooldownCommands-X7P5M2V5.js} +5 -4
  165. package/{createAgentAutomationAction-OLBQDD6R.js → createAgentAutomationAction-UCLTHQRI.js} +51 -49
  166. package/{createDialogAction-SVH6B3SB.js → createDialogAction-UPN774AF.js} +46 -48
  167. package/{createPageAction-F4DIWZ2Z.js → createPageAction-JRQ2TA4O.js} +50 -48
  168. package/{cursorProvider-YGGNMVWX.js → cursorProvider-2RACMEMF.js} +1 -1
  169. package/{db-HUCI5R4G.js → db-CS4ZJQKV.js} +1 -1
  170. package/{dbSlice-BVH2YZPQ.js → dbSlice-WNON7TOL.js} +17 -16
  171. package/{deleteFile-5YOEKV4U.js → deleteFile-Q3YDB4ML.js} +9 -9
  172. package/{desktopFolderProjects-SFY5EZS3.js → desktopFolderProjects-4POAMVJN.js} +2 -2
  173. package/{dialogCommands-KHIEPY3M.js → dialogCommands-VRI7VCXH.js} +64 -57
  174. package/dialogNotifyCommand-6TMCX4D2.js +36 -0
  175. package/{dialogSlice-ZCTDV2PZ.js → dialogSlice-LFNVUSAN.js} +42 -40
  176. package/{dialogUsageCommand-7KCPYGHG.js → dialogUsageCommand-HTVPR2CX.js} +11 -10
  177. package/{docCreateCommands-DPMZI7G5.js → docCreateCommands-AMPXMOX3.js} +61 -55
  178. package/{docDeleteCommands-IRQQLUBT.js → docDeleteCommands-I5WFAEHP.js} +63 -57
  179. package/{docReadCommands-LK37XH6L.js → docReadCommands-X53ELNIE.js} +61 -55
  180. package/{docStore-V2KECILA.js → docStore-2VAWVLWH.js} +21 -20
  181. package/{docUpdateCommands-O6T3HJHH.js → docUpdateCommands-6QPNDC7M.js} +64 -58
  182. package/{fetchMessages-NR4KNQLO.js → fetchMessages-TQEUZD7H.js} +8 -7
  183. package/{getPricing-2MNMXEVG.js → getPricing-MB2GBXOK.js} +6 -6
  184. package/{handleSendMessageAction-2PE25WM3.js → handleSendMessageAction-AAJOHXOB.js} +194 -302
  185. package/{hostCredentialCreate-S233UMAP.js → hostCredentialCreate-GLMJ22M6.js} +123 -114
  186. package/index.js +29 -29
  187. package/{keys-BEGDOTRL.js → keys-RWF7UCB4.js} +5 -4
  188. package/legacyMigration-TF4SYJCZ.js +19 -0
  189. package/{lib-5KKIBFIT.js → lib-OT5OTXRU.js} +7087 -6664
  190. package/{localDialogRead-7NNDVVF7.js → localDialogRead-SVTPA5GY.js} +3 -3
  191. package/{localFirstLog-DHNOY2NA.js → localFirstLog-OIETGK66.js} +1 -1
  192. package/localRecall-2J6QPOK2.js +15 -0
  193. package/{localRuntimeAdapter-KY6WXNBR.js → localRuntimeAdapter-BMP57P42.js} +119 -110
  194. package/{localRuntimeAuthority-OYH4AE4G.js → localRuntimeAuthority-IBJAT62G.js} +1 -1
  195. package/{localRuntimeDb-VBIMCWUC.js → localRuntimeDb-N7KHDXS2.js} +2 -2
  196. package/{machineCommands-Q6HA3IXF.js → machineCommands-3MLIAK5Q.js} +128 -119
  197. package/{machineInfo-UKPTZO5Y.js → machineInfo-LWHTEBHJ.js} +1 -1
  198. package/machineWsRunDispatch-FKIGROQF.js +191 -0
  199. package/{memberThunks-7EDJADWU.js → memberThunks-ZGLZ36PK.js} +29 -28
  200. package/{memoryCommands-ASCE5STX.js → memoryCommands-5WC3T66U.js} +4 -4
  201. package/models-ULVWLSQ6.js +9 -0
  202. package/{oauthTokenStore-OEERZFUC.js → oauthTokenStore-RUYNYALS.js} +1 -1
  203. package/{offlineMarxistsAgentCommand-2QTHJCHV.js → offlineMarxistsAgentCommand-4IC3Y4C6.js} +4 -4
  204. package/overlay-THLKYIWY.js +11 -0
  205. package/package.json +2 -2
  206. package/{pdf-U6KSUEZZ.js → pdf-KE3QI2V7.js} +1 -1
  207. package/{processSpawn-ZU5QFM43.js → processSpawn-6GEO77KV.js} +1 -1
  208. package/{profileConfig-KN3N2BLF.js → profileConfig-KOWK4HOG.js} +1 -1
  209. package/{projectArchive-DRTDIMEV.js → projectArchive-HK63GMF4.js} +52 -50
  210. package/{providerPresetApply-YXGV6NXB.js → providerPresetApply-OIFQ73LH.js} +19 -12
  211. package/{providerRegistry-S6UL6UNA.js → providerRegistry-KZ3SDZ3D.js} +10 -10
  212. package/{read-4V2RMG7N.js → read-MRQHJMJ2.js} +10 -10
  213. package/{readDocTool-BH6ATGQO.js → readDocTool-4BGTXTXA.js} +2 -2
  214. package/{readlineWorkspace-2W4WRCOU.js → readlineWorkspace-AKAHSCNY.js} +7982 -6274
  215. package/{removeDialogAgentAction-LYAZGNKW.js → removeDialogAgentAction-B6H7DXFM.js} +23 -22
  216. package/{runAgentClientLoop-J2VQBS2Z.js → runAgentClientLoop-UVAWGEON.js} +81 -79
  217. package/{runtimeDoctorCommands-QAI3MBKQ.js → runtimeDoctorCommands-FW6XKDUG.js} +12 -12
  218. package/{runtimeModeArgs-2Y7BALTO.js → runtimeModeArgs-X7DL7PUN.js} +1 -1
  219. package/secretCommands-LJXOOYA7.js +24 -0
  220. package/{setDialogExtraReferencesAction-OCRPGPYH.js → setDialogExtraReferencesAction-EVCY3TRW.js} +22 -21
  221. package/{setPrimaryDialogAgentAction-HFJDQIBU.js → setPrimaryDialogAgentAction-KPFVPHCJ.js} +23 -22
  222. package/{settingThunks-RAMHMTGM.js → settingThunks-ENOAK2WV.js} +97 -88
  223. package/{skillDiscovery-XKHROSH2.js → skillDiscovery-B5V23AXP.js} +4 -4
  224. package/{skillSummaryMarker-42HKSXYY.js → skillSummaryMarker-62UW7HI7.js} +1 -1
  225. package/{slateToRenderMarkdown-Y5IYN73U.js → slateToRenderMarkdown-R3X74MCX.js} +1 -1
  226. package/{slateUtils-NGV2NMKM.js → slateUtils-ESQAJ6RN.js} +1 -1
  227. package/{spaceCommands-KVJZVKVO.js → spaceCommands-DTTNAS2L.js} +61 -53
  228. package/store-JRVN62NM.js +46 -0
  229. package/{streamAgentChatTurn-GHBMJJ6S.js → streamAgentChatTurn-R5UY25VB.js} +875 -618
  230. package/{switchDialogAgentAction-EBRMW3RA.js → switchDialogAgentAction-SZ44XDRY.js} +21 -20
  231. package/{tableCommands-MP6VFSVT.js → tableCommands-HITDSLHS.js} +10 -10
  232. package/tombstones-FQQMEDOW.js +32 -0
  233. package/{toolApiClient-HGNO53TC.js → toolApiClient-OGQEBQVX.js} +4 -4
  234. package/{tools-EWKCPKMS.js → tools-HWFG6GMJ.js} +75 -74
  235. package/tuiSummaryLlmCaller-HQQZAMYF.js +44 -0
  236. package/{updateCommands-ZQYU6SCI.js → updateCommands-RJVCRSBP.js} +10 -8
  237. package/{updateDialogTitleAction-5GGMBTDF.js → updateDialogTitleAction-KNPOAMVS.js} +48 -46
  238. package/{usageCommand-F4IPVMIZ.js → usageCommand-FWZCB7AM.js} +11 -10
  239. package/{usageRebuildCommand-HAW2AD5N.js → usageRebuildCommand-SP2BLNJU.js} +12 -11
  240. package/userDataMerge-HT2ZVHBJ.js +13 -0
  241. package/{windowsSelfUpdate-257DV2T6.js → windowsSelfUpdate-KERHIAB4.js} +3 -3
  242. package/{workloadLifecycle-4C42SVBD.js → workloadLifecycle-DYNEYHV5.js} +6 -6
  243. package/agentRecordCommands-ZQ7SVYGG.js +0 -167
  244. package/agentRunCommand-WS7IGO2W.js +0 -196
  245. package/chunk-3CGG2PAL.js +0 -594
  246. package/chunk-5XBUWM6I.js +0 -89
  247. package/chunk-CJEIOP3E.js +0 -0
  248. package/chunk-EHGEOAHI.js +0 -636
  249. package/chunk-FW6YHHLI.js +0 -842
  250. package/chunk-GPVRUGGY.js +0 -115
  251. package/chunk-HSVBJRF4.js +0 -339
  252. package/chunk-WJZOQR2J.js +0 -151
  253. package/chunk-ZCWRMUWT.js +0 -89
  254. package/dist-M676ULYG.js +0 -7314
  255. package/machineWsRunDispatch-WWJQ6WR3.js +0 -182
  256. package/models-PJBE6JDV.js +0 -9
  257. package/tuiSummaryLlmCaller-ALQYUUWB.js +0 -189
  258. package/{chunk-WACI5I6V.js → chunk-2THCNKE4.js} +3 -3
  259. package/{chunk-2QHFH3DR.js → chunk-47ITIXO7.js} +6 -6
  260. package/{chunk-GOO6G4PY.js → chunk-CKG3PRZ7.js} +0 -0
  261. package/{chunk-OQHIVPG4.js → chunk-SNBZZPYH.js} +3 -3
  262. package/{chunk-AETZ7AD6.js → chunk-W6RFEDN4.js} +3 -3
@@ -0,0 +1,1621 @@
1
+ import {
2
+ isMediaFile,
3
+ resolveFileCategory
4
+ } from "./chunk-3PVYUPXK.js";
5
+ import {
6
+ loadFileFromIndexedDb,
7
+ removeAction,
8
+ saveFileToIndexedDb
9
+ } from "./chunk-C4WTX5TU.js";
10
+ import {
11
+ readAction,
12
+ readRequestManager,
13
+ resolveAgentReadServers
14
+ } from "./chunk-WAE3GFCJ.js";
15
+ import {
16
+ beginWriteAck,
17
+ compareRemoteRecordsByComparableTime,
18
+ getRuntimeServerContext,
19
+ pickBestSettledRemoteRecord,
20
+ planAuthorityReadServers,
21
+ resolveAuthorityReplicationServers,
22
+ resolveRecordAuthority,
23
+ resolveUploadReplicationServers,
24
+ scheduleConfiguredPatchReplication,
25
+ scheduleExistingRecordReplication,
26
+ scheduleUploadReplication,
27
+ scheduleWriteReplication,
28
+ shouldPreferRemoteBodyOverLocalProjection,
29
+ shouldReplaceLocalWithRemoteRecord,
30
+ shouldReplicateLocalRecord,
31
+ uploadToCurrentServer
32
+ } from "./chunk-2VUZSVAS.js";
33
+ import {
34
+ asyncThunkCreator,
35
+ buildCreateSlice,
36
+ createEntityAdapter,
37
+ noloDeleteRequest
38
+ } from "./chunk-7Z6EW7AH.js";
39
+ import {
40
+ fetchFromClientDb,
41
+ fetchFromServer,
42
+ logger,
43
+ normalizeTimeFields
44
+ } from "./chunk-AGP3YSEC.js";
45
+ import {
46
+ isTombstoneRecord
47
+ } from "./chunk-BV3FLP2L.js";
48
+ import {
49
+ fileKey,
50
+ getFileIdFromKey
51
+ } from "./chunk-SYTHYBMI.js";
52
+ import {
53
+ ulid
54
+ } from "./chunk-OJKUU3LP.js";
55
+ import {
56
+ isRecord
57
+ } from "./chunk-KUG52IAP.js";
58
+ import {
59
+ API_ENDPOINTS
60
+ } from "./chunk-LCBAMY2M.js";
61
+
62
+ // packages/database/protectedRecordProtocol.ts
63
+ var PROTECTED_RECORD_PROTOCOL_VERSION = 1;
64
+ function assertJson(value, ancestors = /* @__PURE__ */ new Set()) {
65
+ if (value === null || typeof value === "string" || typeof value === "boolean") return;
66
+ if (typeof value === "number" && Number.isFinite(value)) return;
67
+ if (typeof value !== "object" || value === null || ancestors.has(value)) {
68
+ throw new TypeError("Invalid JSON value");
69
+ }
70
+ const array = Array.isArray(value);
71
+ const proto = Object.getPrototypeOf(value);
72
+ if (!array && proto !== Object.prototype && proto !== null) throw new TypeError("Invalid JSON object");
73
+ const keys = Reflect.ownKeys(value);
74
+ const descriptors = Object.getOwnPropertyDescriptors(value);
75
+ if (array && keys.length !== value.length + 1) throw new TypeError("Invalid JSON array");
76
+ ancestors.add(value);
77
+ try {
78
+ for (const key of keys) {
79
+ if (array && key === "length") continue;
80
+ if (typeof key !== "string") throw new TypeError("Invalid JSON key");
81
+ const descriptor = descriptors[key];
82
+ if (!descriptor.enumerable || !("value" in descriptor)) throw new TypeError("Invalid JSON property");
83
+ if (array && (!/^(0|[1-9][0-9]*)$/.test(key) || Number(key) >= value.length)) {
84
+ throw new TypeError("Invalid JSON array index");
85
+ }
86
+ assertJson(descriptor.value, ancestors);
87
+ }
88
+ } finally {
89
+ ancestors.delete(value);
90
+ }
91
+ }
92
+ function assertRecord(value) {
93
+ if (value === null || typeof value !== "object" || Array.isArray(value)) throw new TypeError("Expected JSON record");
94
+ assertJson(value);
95
+ }
96
+ function envelope(value, fields) {
97
+ assertRecord(value);
98
+ if (value.protocolVersion !== PROTECTED_RECORD_PROTOCOL_VERSION) throw new TypeError("Unsupported protocolVersion");
99
+ if (Object.keys(value).some((key) => !fields.includes(key))) throw new TypeError("Unknown protocol field");
100
+ for (const key of ["mutationId", "authorityServer", "authorityEpoch"]) nonEmpty(value[key], key);
101
+ return value;
102
+ }
103
+ function nonEmpty(value, field) {
104
+ if (typeof value !== "string" || value.trim().length === 0) throw new TypeError(`Invalid ${field}`);
105
+ }
106
+ var identityFields = ["protocolVersion", "mutationId", "authorityServer", "authorityEpoch"];
107
+ function assertProtectedMutation(input) {
108
+ const value = envelope(input, [...identityFields, "operation", "payload", "expectedRevision", "createOnly"]);
109
+ if (value.operation !== "replace" && value.operation !== "patch") throw new TypeError("Unsupported operation");
110
+ assertRecord(value.payload);
111
+ if (Object.hasOwn(value, "createOnly")) {
112
+ if (value.createOnly !== true || Object.hasOwn(value, "expectedRevision") || value.operation !== "replace") {
113
+ throw new TypeError("Invalid create-only baseline");
114
+ }
115
+ } else {
116
+ nonEmpty(value.expectedRevision, "expectedRevision");
117
+ }
118
+ }
119
+ function parseProtectedMutation(input) {
120
+ assertProtectedMutation(input);
121
+ return input;
122
+ }
123
+ function parseProtectedMutationAck(input) {
124
+ const value = envelope(input, [...identityFields, "revision", "record"]);
125
+ nonEmpty(value.revision, "revision");
126
+ assertRecord(value.record);
127
+ return value;
128
+ }
129
+
130
+ // packages/database/actions/protectedRecordSync.ts
131
+ var PROTECTED_SYNC_PREFIX = "\0protected-record-sync:v1:";
132
+ var ProtectedSyncError = class extends Error {
133
+ constructor(code, message) {
134
+ super(message ?? code);
135
+ this.code = code;
136
+ this.name = "ProtectedSyncError";
137
+ }
138
+ };
139
+ var protectedPageBaselineKey = (actorId, dbKey) => `\0page-read-baseline:v1:${encodeURIComponent(actorId)}:${encodeURIComponent(dbKey)}`;
140
+ var encodeSegment = (value) => encodeURIComponent(value);
141
+ var protectedSyncWorkingCopyKey = (actorId, dbKey) => `${PROTECTED_SYNC_PREFIX}working:${encodeSegment(actorId)}:${encodeSegment(dbKey)}`;
142
+ var protectedSyncStateKey = (actorId, dbKey) => `${PROTECTED_SYNC_PREFIX}state:${encodeSegment(actorId)}:${encodeSegment(dbKey)}`;
143
+ var protectedSyncLockName = (actorId, dbKey) => `protected-record-sync:${encodeSegment(actorId)}:${encodeSegment(dbKey)}`;
144
+ var protectedSyncSendLockName = (actorId, dbKey) => `protected-record-send:${encodeSegment(actorId)}:${encodeSegment(dbKey)}`;
145
+ var isNotFound = (error) => !!error && typeof error === "object" && error.notFound === true;
146
+ async function readOptional(db, key) {
147
+ try {
148
+ return await db.get(key);
149
+ } catch (error) {
150
+ if (isNotFound(error)) return void 0;
151
+ throw error;
152
+ }
153
+ }
154
+ function protectedSyncCopy(value) {
155
+ if (value === void 0) return value;
156
+ return JSON.parse(JSON.stringify(value));
157
+ }
158
+ function protectedSyncJsonEqual(left, right) {
159
+ if (left === right) return true;
160
+ if (typeof left !== typeof right) return false;
161
+ if (left === null || right === null) return false;
162
+ if (Array.isArray(left) || Array.isArray(right)) {
163
+ if (!Array.isArray(left) || !Array.isArray(right) || left.length !== right.length) return false;
164
+ return left.every((item, index) => protectedSyncJsonEqual(item, right[index]));
165
+ }
166
+ if (typeof left === "object") {
167
+ const leftKeys = Object.keys(left).sort();
168
+ const rightKeys = Object.keys(right).sort();
169
+ if (leftKeys.length !== rightKeys.length) return false;
170
+ if (leftKeys.some((key, index) => key !== rightKeys[index])) return false;
171
+ return leftKeys.every(
172
+ (key) => protectedSyncJsonEqual(left[key], right[key])
173
+ );
174
+ }
175
+ return false;
176
+ }
177
+ var requireNonEmptyString = (value, field) => {
178
+ if (typeof value !== "string" || value.length === 0) {
179
+ throw new ProtectedSyncError("INVALID_INPUT", `${field} \u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32`);
180
+ }
181
+ return value;
182
+ };
183
+ var requireJsonValue = (value, field) => {
184
+ if (value === void 0) {
185
+ throw new ProtectedSyncError("INVALID_INPUT", `${field} \u4E0D\u80FD\u662F undefined`);
186
+ }
187
+ try {
188
+ JSON.stringify(value);
189
+ } catch {
190
+ throw new ProtectedSyncError("INVALID_INPUT", `${field} \u5FC5\u987B\u662F\u53EF JSON \u5E8F\u5217\u5316\u7684\u6570\u636E`);
191
+ }
192
+ return value;
193
+ };
194
+ function createNavigatorLocksLock(namespace = "state") {
195
+ return async (scope, task) => {
196
+ const locks = globalThis.navigator?.locks;
197
+ if (!locks || typeof locks.request !== "function") {
198
+ throw new ProtectedSyncError(
199
+ "LOCK_UNAVAILABLE",
200
+ `navigator.locks \u4E0D\u53EF\u7528\uFF08${namespace} \u9501\uFF09\uFF1A\u6CA1\u6709\u53EF\u9760\u7684\u8DE8\u6807\u7B7E\u534F\u8C03\u5668\uFF0C\u62D2\u7EDD\u4EE5\u8FDB\u7A0B\u5185\u9501\u5192\u5145\u8DE8\u6807\u7B7E\u4E92\u65A5`
201
+ );
202
+ }
203
+ const name = (scope.namespace ?? namespace) === "send" ? protectedSyncSendLockName(scope.actorId, scope.dbKey) : protectedSyncLockName(scope.actorId, scope.dbKey);
204
+ const result = await locks.request(name, { mode: "exclusive" }, async () => task());
205
+ return result;
206
+ };
207
+ }
208
+ function createProtectedRecordSync(deps) {
209
+ const { db } = deps;
210
+ const stateLock = deps.lock ?? createNavigatorLocksLock("state");
211
+ const sendLock = deps.sendLock ?? createNavigatorLocksLock("send");
212
+ const withStateLock = (scope, task) => stateLock({ ...scope, namespace: "state" }, task);
213
+ const withSendLock = (scope, task) => sendLock({ ...scope, namespace: "send" }, task);
214
+ const loadState = async (actorId, dbKey) => {
215
+ const [workingRaw, stateRaw] = await Promise.all([
216
+ readOptional(db, protectedSyncWorkingCopyKey(actorId, dbKey)),
217
+ readOptional(db, protectedSyncStateKey(actorId, dbKey))
218
+ ]);
219
+ const working = workingRaw?.workingCopy ?? null;
220
+ const persisted = stateRaw ?? {};
221
+ const outbox = (Array.isArray(persisted.outbox) ? persisted.outbox : []).map((entry) => ({
222
+ ...entry,
223
+ // 旧版本持久化的认领标志不再解释为占用:重启后队列必须可继续。
224
+ inFlight: false
225
+ }));
226
+ return protectedSyncCopy({
227
+ actorId,
228
+ dbKey,
229
+ workingCopy: working,
230
+ outbox,
231
+ baselineRevision: persisted.baselineRevision ?? null,
232
+ lastAck: persisted.lastAck ?? null,
233
+ legacyCandidates: Array.isArray(persisted.legacyCandidates) ? persisted.legacyCandidates : [],
234
+ remoteCandidate: persisted.remoteCandidate ?? null,
235
+ blocked: persisted.blocked ?? null,
236
+ nextSeq: typeof persisted.nextSeq === "number" ? persisted.nextSeq : 1
237
+ });
238
+ };
239
+ const persist = async (state, extra, discovery) => {
240
+ const operations = [
241
+ {
242
+ type: "put",
243
+ key: protectedSyncWorkingCopyKey(state.actorId, state.dbKey),
244
+ value: { workingCopy: state.workingCopy }
245
+ },
246
+ {
247
+ type: "put",
248
+ key: protectedSyncStateKey(state.actorId, state.dbKey),
249
+ value: {
250
+ outbox: state.outbox,
251
+ baselineRevision: state.baselineRevision,
252
+ lastAck: state.lastAck,
253
+ legacyCandidates: state.legacyCandidates,
254
+ remoteCandidate: state.remoteCandidate,
255
+ blocked: state.blocked,
256
+ nextSeq: state.nextSeq
257
+ }
258
+ }
259
+ ];
260
+ if (extra) operations.push({ type: "put", key: extra.key, value: extra.value });
261
+ if (discovery) operations.push({ type: "put", key: discovery.key, value: discovery.value });
262
+ try {
263
+ await db.batch(operations);
264
+ } catch (error) {
265
+ throw new ProtectedSyncError(
266
+ "BATCH_FAILED",
267
+ `protected record sync \u843D\u76D8\u5931\u8D25\uFF1A${error instanceof Error ? error.message : String(error)}`
268
+ );
269
+ }
270
+ };
271
+ const validateScope = (actorId, dbKey) => {
272
+ const actor = requireNonEmptyString(actorId, "actorId");
273
+ const key = requireNonEmptyString(dbKey, "dbKey");
274
+ if (key.startsWith("\0")) {
275
+ throw new ProtectedSyncError("INVALID_INPUT", "dbKey \u4E0D\u80FD\u4F7F\u7528\u5185\u90E8\u4FDD\u7559\u524D\u7F00");
276
+ }
277
+ return { actorId: actor, dbKey: key };
278
+ };
279
+ const applyAckUnlocked = async (state, mutationId, revision, record) => {
280
+ state.outbox = state.outbox.slice(1);
281
+ state.baselineRevision = revision;
282
+ state.lastAck = { mutationId, revision, record };
283
+ state.outbox = state.outbox.map((entry) => ({ ...entry, baseRevision: revision }));
284
+ if (state.workingCopy) {
285
+ state.workingCopy = state.workingCopy.mutationId === mutationId ? null : { ...state.workingCopy, baseRevision: revision };
286
+ }
287
+ await persist(state, { key: state.dbKey, value: protectedSyncCopy(record) });
288
+ return state;
289
+ };
290
+ const saveLocalDraft = async (input) => {
291
+ const scope = validateScope(input?.actorId, input?.dbKey);
292
+ const authorityServer = requireNonEmptyString(input.authorityServer, "authorityServer");
293
+ const mutationId = requireNonEmptyString(input.mutationId, "mutationId");
294
+ const data = requireJsonValue(input.data, "data");
295
+ const baseRevision = input.baseRevision ?? null;
296
+ const intent = {};
297
+ if (input.operation !== void 0) {
298
+ const mutation = parseProtectedMutation({
299
+ protocolVersion: 1,
300
+ operation: input.operation,
301
+ payload: input.payload,
302
+ authorityEpoch: input.authorityEpoch,
303
+ authorityServer,
304
+ mutationId,
305
+ expectedRevision: baseRevision
306
+ });
307
+ intent.operation = "patch";
308
+ intent.payload = protectedSyncCopy(mutation.payload);
309
+ intent.authorityEpoch = mutation.authorityEpoch;
310
+ } else if (input.payload !== void 0 || input.authorityEpoch !== void 0) {
311
+ throw new ProtectedSyncError("INVALID_INPUT", "patch intent requires explicit operation");
312
+ }
313
+ return withStateLock(scope, async () => {
314
+ const state = await loadState(scope.actorId, scope.dbKey);
315
+ const existing = state.outbox.find((entry2) => entry2.mutationId === mutationId);
316
+ if (existing) {
317
+ if (!protectedSyncJsonEqual(existing.data, data) || existing.authorityServer !== authorityServer || existing.operation !== intent.operation || existing.authorityEpoch !== intent.authorityEpoch || !protectedSyncJsonEqual(existing.payload, intent.payload)) {
318
+ throw new ProtectedSyncError(
319
+ "MUTATION_ID_CONFLICT",
320
+ `mutationId ${mutationId} \u5DF2\u5B58\u5728\u4E14 payload \u4E0D\u540C\uFF1A\u62D2\u7EDD\u6539\u5199\u961F\u5217\u4E2D\u7684\u4E0D\u53EF\u53D8 payload`
321
+ );
322
+ }
323
+ return protectedSyncCopy(state);
324
+ }
325
+ const entry = {
326
+ ...intent,
327
+ mutationId,
328
+ data: protectedSyncCopy(data),
329
+ baseRevision: baseRevision ?? state.baselineRevision,
330
+ authorityServer,
331
+ seq: state.nextSeq
332
+ };
333
+ state.outbox = [...state.outbox, entry];
334
+ state.nextSeq = state.nextSeq + 1;
335
+ state.workingCopy = {
336
+ ...intent,
337
+ mutationId,
338
+ data: protectedSyncCopy(data),
339
+ baseRevision: entry.baseRevision,
340
+ authorityServer,
341
+ seq: entry.seq
342
+ };
343
+ await persist(state);
344
+ return protectedSyncCopy(state);
345
+ });
346
+ };
347
+ const ackMutation = async (input) => {
348
+ const scope = validateScope(input?.actorId, input?.dbKey);
349
+ const mutationId = requireNonEmptyString(input.mutationId, "mutationId");
350
+ const revision = requireNonEmptyString(input.revision, "revision");
351
+ const record = requireJsonValue(input.record, "record");
352
+ return withStateLock(scope, async () => {
353
+ const state = await loadState(scope.actorId, scope.dbKey);
354
+ if (state.lastAck?.mutationId === mutationId) return protectedSyncCopy(state);
355
+ const head = state.outbox[0];
356
+ if (!head) {
357
+ throw new ProtectedSyncError("MUTATION_NOT_FOUND", `\u672A\u627E\u5230\u5F85\u786E\u8BA4\u7684 mutation\uFF1A${mutationId}`);
358
+ }
359
+ if (head.mutationId !== mutationId) {
360
+ const known = state.outbox.some((entry) => entry.mutationId === mutationId);
361
+ throw new ProtectedSyncError(
362
+ known ? "OUT_OF_ORDER" : "MUTATION_NOT_FOUND",
363
+ known ? `\u53EA\u5141\u8BB8\u786E\u8BA4\u961F\u9996\uFF1A\u5F53\u524D\u961F\u9996\u662F ${head.mutationId}\uFF0C\u4E0D\u662F ${mutationId}` : `\u672A\u627E\u5230\u5F85\u786E\u8BA4\u7684 mutation\uFF1A${mutationId}`
364
+ );
365
+ }
366
+ const next = await applyAckUnlocked(state, mutationId, revision, protectedSyncCopy(record));
367
+ return protectedSyncCopy(next);
368
+ });
369
+ };
370
+ const readState = async (input) => {
371
+ const scope = validateScope(input?.actorId, input?.dbKey);
372
+ return withStateLock(scope, async () => protectedSyncCopy(await loadState(scope.actorId, scope.dbKey)));
373
+ };
374
+ const acceptRemote = async (input) => {
375
+ const scope = validateScope(input?.actorId, input?.dbKey);
376
+ const record = requireJsonValue(input.record, "record");
377
+ const discovery = input.authority ? {
378
+ key: protectedPageBaselineKey(scope.actorId, scope.dbKey),
379
+ value: {
380
+ authorityServer: requireNonEmptyString(input.authority.authorityServer, "authorityServer"),
381
+ authorityEpoch: requireNonEmptyString(input.authority.authorityEpoch, "authorityEpoch"),
382
+ revision: input.revision
383
+ }
384
+ } : void 0;
385
+ return withStateLock(scope, async () => {
386
+ const state = await loadState(scope.actorId, scope.dbKey);
387
+ if (Array.isArray(input.legacyCandidates) && input.legacyCandidates.length > 0) {
388
+ const merged = [...state.legacyCandidates];
389
+ for (const candidate of input.legacyCandidates) {
390
+ const position = merged.findIndex((item) => item.candidateId === candidate.candidateId);
391
+ if (position === -1) merged.push(protectedSyncCopy(candidate));
392
+ else merged[position] = { ...merged[position], ...protectedSyncCopy(candidate) };
393
+ }
394
+ state.legacyCandidates = merged;
395
+ }
396
+ const hasPending = state.outbox.length > 0;
397
+ const hasWorking = state.workingCopy !== null;
398
+ const hasLegacy = state.legacyCandidates.length > 0;
399
+ if (hasPending || hasWorking || hasLegacy) {
400
+ state.remoteCandidate = { revision: input.revision ?? null, record: protectedSyncCopy(record) };
401
+ input.assertCurrentAccess?.();
402
+ await persist(state, void 0, discovery);
403
+ return {
404
+ applied: false,
405
+ reason: hasPending ? "pending-mutations" : hasWorking ? "working-copy" : "legacy-candidates",
406
+ state: protectedSyncCopy(state)
407
+ };
408
+ }
409
+ state.baselineRevision = input.revision ?? state.baselineRevision;
410
+ state.remoteCandidate = null;
411
+ state.workingCopy = null;
412
+ input.assertCurrentAccess?.();
413
+ await persist(state, { key: scope.dbKey, value: protectedSyncCopy(record) }, discovery);
414
+ return { applied: true, reason: null, state: protectedSyncCopy(state) };
415
+ });
416
+ };
417
+ const markBlocked = async (input) => {
418
+ const scope = validateScope(input?.actorId, input?.dbKey);
419
+ const reason = requireNonEmptyString(input.reason, "reason");
420
+ return withStateLock(scope, async () => {
421
+ const state = await loadState(scope.actorId, scope.dbKey);
422
+ state.blocked = { reason, detail: input.detail ?? null, at: Date.now() };
423
+ await persist(state);
424
+ return protectedSyncCopy(state);
425
+ });
426
+ };
427
+ const clearBlocked = async (input) => {
428
+ const scope = validateScope(input?.actorId, input?.dbKey);
429
+ return withStateLock(scope, async () => {
430
+ const state = await loadState(scope.actorId, scope.dbKey);
431
+ state.blocked = null;
432
+ await persist(state);
433
+ return protectedSyncCopy(state);
434
+ });
435
+ };
436
+ const beginInFlight = async (input) => {
437
+ const scope = validateScope(input?.actorId, input?.dbKey);
438
+ return withStateLock(scope, async () => {
439
+ const state = await loadState(scope.actorId, scope.dbKey);
440
+ if (state.blocked) {
441
+ throw new ProtectedSyncError("BLOCKED", `\u8BB0\u5F55\u5904\u4E8E blocked \u72B6\u6001\uFF1A${state.blocked.reason}`);
442
+ }
443
+ const head = state.outbox[0];
444
+ if (!head) {
445
+ throw new ProtectedSyncError("MUTATION_NOT_FOUND", "\u5F85\u53D1\u961F\u5217\u4E3A\u7A7A");
446
+ }
447
+ if (input.mutationId !== void 0 && input.mutationId !== head.mutationId) {
448
+ throw new ProtectedSyncError(
449
+ "OUT_OF_ORDER",
450
+ `\u961F\u5217\u5FC5\u987B\u6309\u5E8F\u53D1\u9001\uFF1A\u5F53\u524D\u961F\u9996\u662F ${head.mutationId}\uFF0C\u4E0D\u662F ${input.mutationId}`
451
+ );
452
+ }
453
+ return protectedSyncCopy(state);
454
+ });
455
+ };
456
+ const releaseInFlight = async (input) => {
457
+ const scope = validateScope(input?.actorId, input?.dbKey);
458
+ requireNonEmptyString(input.mutationId, "mutationId");
459
+ return withStateLock(scope, async () => protectedSyncCopy(await loadState(scope.actorId, scope.dbKey)));
460
+ };
461
+ const withNextMutation = async (scopeInput, send) => {
462
+ const scope = validateScope(scopeInput?.actorId, scopeInput?.dbKey);
463
+ if (typeof send !== "function") {
464
+ throw new ProtectedSyncError("INVALID_INPUT", "send \u5FC5\u987B\u662F\u51FD\u6570");
465
+ }
466
+ const snapshot = await withStateLock(scope, async () => {
467
+ const state = await loadState(scope.actorId, scope.dbKey);
468
+ if (state.blocked) {
469
+ throw new ProtectedSyncError("BLOCKED", `\u8BB0\u5F55\u5904\u4E8E blocked \u72B6\u6001\uFF1A${state.blocked.reason}`);
470
+ }
471
+ const head = state.outbox[0];
472
+ return { state: protectedSyncCopy(state), entry: head ? protectedSyncCopy(head) : null };
473
+ });
474
+ if (!snapshot.entry) {
475
+ return { mutationId: null, outcome: "none", state: snapshot.state };
476
+ }
477
+ const entry = snapshot.entry;
478
+ return withSendLock(scope, async () => {
479
+ const ready = await withStateLock(scope, async () => {
480
+ const state = await loadState(scope.actorId, scope.dbKey);
481
+ const head = state.outbox[0];
482
+ const same = !!head && head.mutationId === entry.mutationId && head.baseRevision === entry.baseRevision;
483
+ return { state, same };
484
+ });
485
+ if (!ready.same) {
486
+ return {
487
+ mutationId: null,
488
+ outcome: "none",
489
+ skipped: true,
490
+ state: protectedSyncCopy(ready.state)
491
+ };
492
+ }
493
+ const result = await send(protectedSyncCopy(entry));
494
+ return withStateLock(scope, async () => {
495
+ const state = await loadState(scope.actorId, scope.dbKey);
496
+ if (result?.outcome === "acked") {
497
+ const revision = requireNonEmptyString(result.revision, "revision");
498
+ const record = requireJsonValue(result.record, "record");
499
+ if (state.lastAck?.mutationId === entry.mutationId) {
500
+ return { mutationId: entry.mutationId, outcome: "acked", state: protectedSyncCopy(state) };
501
+ }
502
+ const head = state.outbox[0];
503
+ if (!head || head.mutationId !== entry.mutationId) {
504
+ return {
505
+ mutationId: null,
506
+ outcome: "none",
507
+ skipped: true,
508
+ state: protectedSyncCopy(state)
509
+ };
510
+ }
511
+ const next = await applyAckUnlocked(state, entry.mutationId, revision, protectedSyncCopy(record));
512
+ return { mutationId: entry.mutationId, outcome: "acked", state: protectedSyncCopy(next) };
513
+ }
514
+ if (result?.outcome === "pending") {
515
+ return {
516
+ mutationId: entry.mutationId,
517
+ outcome: "pending",
518
+ reason: result.reason,
519
+ state: protectedSyncCopy(state)
520
+ };
521
+ }
522
+ if (result?.outcome === "conflict" || result?.outcome === "blocked") {
523
+ const reason = requireNonEmptyString(result.reason, "reason");
524
+ const stillPending = state.outbox.some((item) => item.mutationId === entry.mutationId);
525
+ if (stillPending) {
526
+ state.blocked = { reason, detail: result.detail ?? null, at: Date.now() };
527
+ await persist(state);
528
+ }
529
+ return {
530
+ mutationId: entry.mutationId,
531
+ outcome: result.outcome,
532
+ reason,
533
+ state: protectedSyncCopy(state)
534
+ };
535
+ }
536
+ throw new ProtectedSyncError("INVALID_INPUT", "send \u5FC5\u987B\u8FD4\u56DE acked/conflict/blocked/pending");
537
+ });
538
+ });
539
+ };
540
+ return {
541
+ saveLocalDraft,
542
+ ackMutation,
543
+ readState,
544
+ acceptRemote,
545
+ markBlocked,
546
+ clearBlocked,
547
+ beginInFlight,
548
+ releaseInFlight,
549
+ withNextMutation
550
+ };
551
+ }
552
+
553
+ // packages/database/actions/protectedRecordTransport.ts
554
+ function createProtectedRecordTransport(options) {
555
+ return {
556
+ sendNext(scope) {
557
+ return options.sync.withNextMutation(scope, async (entry) => {
558
+ const blocked = (reason) => ({ outcome: "blocked", reason });
559
+ if (entry.operation !== "patch") return blocked("PATCH_INTENT_REQUIRED");
560
+ if (!entry.authorityEpoch?.trim()) return blocked("AUTHORITY_EPOCH_REQUIRED");
561
+ if (!entry.baseRevision?.trim()) return blocked("BASE_REVISION_REQUIRED");
562
+ if (!/^page-[A-Za-z0-9_-]+$/.test(scope.dbKey)) return blocked("UNSUPPORTED_DB_KEY");
563
+ let mutation;
564
+ let origin;
565
+ try {
566
+ origin = new URL(entry.authorityServer);
567
+ if (!["http:", "https:"].includes(origin.protocol) || origin.username || origin.password || origin.search || origin.hash || origin.pathname !== "/") return blocked("INVALID_AUTHORITY");
568
+ mutation = parseProtectedMutation({
569
+ protocolVersion: 1,
570
+ operation: "patch",
571
+ payload: entry.payload,
572
+ expectedRevision: entry.baseRevision,
573
+ mutationId: entry.mutationId,
574
+ authorityServer: entry.authorityServer,
575
+ authorityEpoch: entry.authorityEpoch
576
+ });
577
+ } catch {
578
+ return blocked("INVALID_PATCH_INTENT");
579
+ }
580
+ let response;
581
+ try {
582
+ if (!await options.isAuthorityAllowed(origin.origin)) return blocked("AUTHORITY_NOT_CONFIGURED");
583
+ const token = await options.getToken({ actorId: scope.actorId, authorityServer: entry.authorityServer });
584
+ if (!token) return blocked("AUTH_REQUIRED");
585
+ response = await options.fetch(`${origin.origin}/api/v1/db/patch/${scope.dbKey}`, {
586
+ method: "PATCH",
587
+ redirect: "error",
588
+ credentials: "omit",
589
+ headers: { "Content-Type": "application/json", Authorization: `Bearer ${token}` },
590
+ body: JSON.stringify(mutation)
591
+ });
592
+ } catch {
593
+ return { outcome: "pending", reason: "NETWORK_OR_CREDENTIALS_UNAVAILABLE" };
594
+ }
595
+ if (response.status === 409) return { outcome: "conflict", reason: "HTTP_409" };
596
+ if (response.status === 401 || response.status === 403) return blocked(`HTTP_${response.status}`);
597
+ if (response.status === 503) return { outcome: "pending", reason: "PROTOCOL_UNAVAILABLE" };
598
+ if (!response.ok) return blocked(`HTTP_${response.status}`);
599
+ try {
600
+ const ack = parseProtectedMutationAck(await response.json());
601
+ if (ack.mutationId !== entry.mutationId || ack.authorityServer !== entry.authorityServer || ack.authorityEpoch !== entry.authorityEpoch) return blocked("ACK_IDENTITY_MISMATCH");
602
+ return { outcome: "acked", revision: ack.revision, record: ack.record };
603
+ } catch {
604
+ return blocked("INVALID_ACK");
605
+ }
606
+ });
607
+ }
608
+ };
609
+ }
610
+
611
+ // packages/database/actions/protectedPageRead.ts
612
+ var baselineKey = protectedPageBaselineKey;
613
+ var originOf = (value) => {
614
+ try {
615
+ const url = new URL(value ?? "");
616
+ return ["http:", "https:"].includes(url.protocol) && !url.username && !url.password && url.pathname === "/" && !url.search && !url.hash ? url.origin : null;
617
+ } catch {
618
+ return null;
619
+ }
620
+ };
621
+ async function getPageReadBaseline(db, actorId, dbKey) {
622
+ try {
623
+ const value = await db.get(baselineKey(actorId, dbKey));
624
+ if (!value) {
625
+ const state = await db.get(protectedSyncStateKey(actorId, dbKey));
626
+ if (state) throw Error("\u6587\u6863\u4FDD\u62A4\u72B6\u6001\u5B58\u5728\u4F46\u57FA\u7EBF\u7F3A\u5931\uFF0C\u5DF2\u963B\u6B62\u9000\u56DE\u65E7\u8BFB\u5199\u8DEF\u5F84");
627
+ }
628
+ return value ?? null;
629
+ } catch (error) {
630
+ if (error && typeof error === "object" && "notFound" in error && error.notFound === true) {
631
+ let state;
632
+ try {
633
+ state = await db.get(protectedSyncStateKey(actorId, dbKey));
634
+ } catch (stateError) {
635
+ if (!(stateError && typeof stateError === "object" && "notFound" in stateError && stateError.notFound === true)) throw stateError;
636
+ }
637
+ if (state) throw Error("\u6587\u6863\u4FDD\u62A4\u72B6\u6001\u5B58\u5728\u4F46\u57FA\u7EBF\u7F3A\u5931\uFF0C\u5DF2\u963B\u6B62\u9000\u56DE\u65E7\u8BFB\u5199\u8DEF\u5F84");
638
+ return null;
639
+ }
640
+ throw error;
641
+ }
642
+ }
643
+ async function readProtectedPage(options) {
644
+ const { db, actorId, dbKey } = options;
645
+ const assertAccess = (origin) => {
646
+ const access = options.getCurrentAccess?.() ?? options;
647
+ if (access.actorId !== actorId || !access.token?.trim()) {
648
+ throw Error("\u6587\u6863\u8BFB\u53D6\u8EAB\u4EFD\u5DF2\u53D8\u5316\u6216\u8BA4\u8BC1\u5DF2\u64A4\u9500\uFF0C\u5DF2\u505C\u6B62\u8BFB\u53D6");
649
+ }
650
+ if (origin && !access.servers.some((server) => originOf(server) === origin)) {
651
+ throw Error("\u6587\u6863\u5F52\u5C5E\u670D\u52A1\u5668\u4E0D\u5728\u5DF2\u914D\u7F6E\u670D\u52A1\u5668\u4E2D\u6216\u5DF2\u79FB\u9664\uFF0C\u672A\u53D1\u9001\u8BA4\u8BC1\u4FE1\u606F\uFF0C\u672A\u8F6C\u53D1\u8BA4\u8BC1\u4FE1\u606F");
652
+ }
653
+ return access.token;
654
+ };
655
+ assertAccess();
656
+ const sync = options.sync ?? createProtectedRecordSync({ db });
657
+ const saved = await getPageReadBaseline(db, actorId, dbKey);
658
+ assertAccess(saved?.authorityServer);
659
+ if (saved) {
660
+ const state = await sync.readState({ actorId, dbKey });
661
+ if (state.workingCopy) {
662
+ if (options.getCurrentAccess && !state.blocked && !state.legacyCandidates.length) {
663
+ const transport = createProtectedRecordTransport({
664
+ sync,
665
+ fetch: options.fetch,
666
+ isAuthorityAllowed: (origin) => {
667
+ const access = options.getCurrentAccess();
668
+ return access.actorId === actorId && access.servers.some((server) => originOf(server) === origin);
669
+ },
670
+ getToken: async () => {
671
+ const access = options.getCurrentAccess();
672
+ return access.actorId === actorId ? access.token ?? null : null;
673
+ }
674
+ });
675
+ for (let count = 0; count < state.outbox.length; count++) {
676
+ if ((await transport.sendNext({ actorId, dbKey })).outcome !== "acked") break;
677
+ }
678
+ const latest = await sync.readState({ actorId, dbKey });
679
+ assertAccess(saved.authorityServer);
680
+ return latest.workingCopy?.data ?? latest.lastAck?.record ?? state.workingCopy.data;
681
+ }
682
+ assertAccess(saved.authorityServer);
683
+ return state.workingCopy.data;
684
+ }
685
+ }
686
+ const servers = saved ? [saved.authorityServer] : options.servers;
687
+ for (const server of servers) {
688
+ const origin = originOf(server);
689
+ if (!origin) continue;
690
+ const token = assertAccess(origin);
691
+ let response;
692
+ try {
693
+ response = await options.fetch(`${origin}/api/v1/db/read/${encodeURIComponent(dbKey)}`, {
694
+ headers: { Authorization: `Bearer ${token}` },
695
+ redirect: "error",
696
+ credentials: "omit",
697
+ signal: AbortSignal.timeout(5e3)
698
+ });
699
+ } catch {
700
+ assertAccess(origin);
701
+ continue;
702
+ }
703
+ assertAccess(origin);
704
+ if (!response.ok) continue;
705
+ const authorityServer = originOf(response.headers.get("X-Nolo-Authority-Server"));
706
+ const authorityEpoch = response.headers.get("X-Nolo-Authority-Epoch");
707
+ if (!authorityServer || !authorityEpoch?.trim()) continue;
708
+ const authorityToken = assertAccess(authorityServer);
709
+ if (authorityServer !== origin) {
710
+ response = await options.fetch(`${authorityServer}/api/v1/db/read/${encodeURIComponent(dbKey)}`, {
711
+ headers: { Authorization: `Bearer ${authorityToken}` },
712
+ redirect: "error",
713
+ credentials: "omit",
714
+ signal: AbortSignal.timeout(5e3)
715
+ });
716
+ if (!response.ok || response.headers.get("X-Nolo-Authority-Server") !== authorityServer || response.headers.get("X-Nolo-Authority-Epoch") !== authorityEpoch) throw Error("\u6587\u6863\u5F52\u5C5E\u6821\u9A8C\u5931\u8D25\uFF0C\u672A\u91C7\u7528\u526F\u672C");
717
+ }
718
+ if (saved && (saved.authorityServer !== authorityServer || saved.authorityEpoch !== authorityEpoch)) {
719
+ throw Error("\u6587\u6863\u5F52\u5C5E\u5DF2\u5207\u6362\uFF0C\u4FDD\u7559\u672C\u5730\u5185\u5BB9\uFF0C\u9700\u91CD\u65B0\u786E\u8BA4\u5F52\u5C5E");
720
+ }
721
+ const etag = response.headers.get("ETag");
722
+ if (!etag || !/^"[^"\r\n]+"$/.test(etag)) throw Error("\u6587\u6863\u670D\u52A1\u5668\u672A\u8FD4\u56DE\u6709\u6548\u7248\u672C\u57FA\u7EBF");
723
+ const record = await response.json();
724
+ if (!record || record.type !== "page") throw Error("\u6587\u6863\u5F52\u5C5E\u670D\u52A1\u5668\u8FD4\u56DE\u4E86\u65E0\u6548\u8BB0\u5F55");
725
+ const local = await db.get(dbKey).catch((error) => {
726
+ if (error && typeof error === "object" && "notFound" in error && error.notFound === true) return void 0;
727
+ throw error;
728
+ });
729
+ const localIsProjection = shouldPreferRemoteBodyOverLocalProjection(local, record);
730
+ const candidates = !saved && local && !localIsProjection && JSON.stringify(local) !== JSON.stringify(record) ? [{ candidateId: "legacy-local", source: "local", record: local, revision: null, observedAt: null }] : void 0;
731
+ assertAccess(authorityServer);
732
+ const result = await sync.acceptRemote({
733
+ actorId,
734
+ dbKey,
735
+ record,
736
+ revision: etag.slice(1, -1),
737
+ authority: { authorityServer, authorityEpoch },
738
+ legacyCandidates: candidates,
739
+ assertCurrentAccess: () => {
740
+ assertAccess(authorityServer);
741
+ }
742
+ });
743
+ assertAccess(authorityServer);
744
+ return result.state.workingCopy?.data ?? (!result.applied && local ? local : record);
745
+ }
746
+ if (saved) {
747
+ const local = await db.get(dbKey);
748
+ assertAccess(saved.authorityServer);
749
+ if (local) return local;
750
+ throw Error("\u6587\u6863\u6743\u5A01\u670D\u52A1\u5668\u4E0D\u53EF\u7528\uFF0C\u4E14\u6CA1\u6709\u672C\u5730\u7F13\u5B58");
751
+ }
752
+ assertAccess();
753
+ return void 0;
754
+ }
755
+
756
+ // packages/database/actions/readAndWait.ts
757
+ var hashTokenScope = (currentToken) => {
758
+ const token = currentToken || "";
759
+ if (!token) return "anonymous";
760
+ let hash = 0;
761
+ for (let index = 0; index < token.length; index += 1) {
762
+ hash = (hash << 5) - hash + token.charCodeAt(index) | 0;
763
+ }
764
+ return `token:${Math.abs(hash).toString(36)}`;
765
+ };
766
+ var buildReadAndWaitRequestKey = (dbKey, currentToken) => `${dbKey}\0auth:${hashTokenScope(currentToken)}`;
767
+ var isRemoteDataNewer = (remoteData, localData) => {
768
+ return compareRemoteRecordsByComparableTime(remoteData, localData) > 0;
769
+ };
770
+ var syncLocalDataToServer = async (replicationContext, dbKey, localData) => {
771
+ try {
772
+ scheduleExistingRecordReplication({
773
+ currentServer: replicationContext.currentServer,
774
+ syncServers: replicationContext.syncServers,
775
+ dbKey,
776
+ localData,
777
+ state: replicationContext.state
778
+ });
779
+ } catch {
780
+ }
781
+ };
782
+ var processRemoteData = async (db, dbKey, remotePromises, localData, replicationContext) => {
783
+ try {
784
+ const settledResults = await Promise.allSettled(remotePromises);
785
+ const remoteResult = pickBestSettledRemoteRecord({
786
+ settledResults,
787
+ isBetterCandidate: (current, latest) => compareRemoteRecordsByComparableTime(current, latest) > 0
788
+ });
789
+ const validRemoteData = remoteResult ? remoteResult.data : null;
790
+ if (shouldReplaceLocalWithRemoteRecord({
791
+ localData,
792
+ remoteData: validRemoteData,
793
+ isRemoteNewer: isRemoteDataNewer
794
+ })) {
795
+ await db.put(dbKey, validRemoteData);
796
+ return validRemoteData;
797
+ }
798
+ if (localData) {
799
+ if (shouldReplicateLocalRecord({
800
+ localData,
801
+ remoteData: validRemoteData,
802
+ remoteTargetCount: remotePromises.length
803
+ })) {
804
+ void syncLocalDataToServer(replicationContext, dbKey, localData);
805
+ }
806
+ return localData;
807
+ }
808
+ throw new Error("Failed to fetch data from all sources");
809
+ } catch (err) {
810
+ if (localData) {
811
+ return localData;
812
+ }
813
+ throw err;
814
+ }
815
+ };
816
+ var readAndWaitAction = async (payload, thunkApi) => {
817
+ const dbKey = typeof payload === "string" ? payload : payload.dbKey;
818
+ const preferredServerOrigin = typeof payload === "string" ? void 0 : payload.preferredServerOrigin;
819
+ const { db } = thunkApi.extra;
820
+ if (!db) {
821
+ throw new Error(
822
+ "Database instance is not available in thunk extra argument."
823
+ );
824
+ }
825
+ const state = thunkApi.getState();
826
+ const {
827
+ currentToken,
828
+ remoteServers: configuredServers,
829
+ currentServer,
830
+ currentUserId,
831
+ syncServers,
832
+ userAuthorityRegistry
833
+ } = getRuntimeServerContext(state, preferredServerOrigin);
834
+ const allServers = resolveAgentReadServers({ dbKey, configuredServers });
835
+ const isLoggedIn = !!currentToken;
836
+ const executeReadAndWait = async () => {
837
+ if (dbKey.startsWith("page-") && currentUserId && currentToken && typeof db.batch === "function") {
838
+ const protectedData = await readProtectedPage({
839
+ db,
840
+ actorId: currentUserId,
841
+ dbKey,
842
+ servers: preferredServerOrigin ? [preferredServerOrigin, ...allServers] : allServers,
843
+ token: currentToken,
844
+ fetch,
845
+ getCurrentAccess: () => {
846
+ const context = getRuntimeServerContext(thunkApi.getState());
847
+ return { actorId: context.currentUserId, token: context.currentToken, servers: context.remoteServers };
848
+ }
849
+ });
850
+ if (protectedData !== void 0) return { ...protectedData, dbKey };
851
+ }
852
+ const localData = await fetchFromClientDb(db, dbKey);
853
+ const authority = resolveRecordAuthority({
854
+ dbKey,
855
+ record: localData,
856
+ currentUserId,
857
+ currentServer,
858
+ userAuthorityRegistry
859
+ });
860
+ const readServers = planAuthorityReadServers({
861
+ allServers,
862
+ authorityServer: preferredServerOrigin ?? authority.authorityServer,
863
+ serverOrigin: authority.serverOrigin
864
+ });
865
+ const hasPreferredAuthorityServer = !!preferredServerOrigin || !!authority.authorityServer;
866
+ const preferredAuthorityServer = hasPreferredAuthorityServer ? readServers[0] : null;
867
+ if (readServers.length === 0) {
868
+ if (localData) {
869
+ return { ...localData, dbKey };
870
+ }
871
+ throw new Error(
872
+ `Failed to fetch data for key "${dbKey}" because network is offline and no local data is available.`
873
+ );
874
+ }
875
+ if (preferredAuthorityServer) {
876
+ try {
877
+ const preferredRemoteData = await fetchFromServer(
878
+ preferredAuthorityServer,
879
+ dbKey,
880
+ isLoggedIn ? currentToken : void 0
881
+ );
882
+ if (preferredRemoteData) {
883
+ await db.put(dbKey, preferredRemoteData);
884
+ return { ...preferredRemoteData, dbKey };
885
+ }
886
+ } catch {
887
+ }
888
+ }
889
+ const remainingReadServers = preferredAuthorityServer ? readServers.filter((server) => server !== preferredAuthorityServer) : readServers;
890
+ const remotePromises = remainingReadServers.map(
891
+ (server) => fetchFromServer(server, dbKey, isLoggedIn ? currentToken : void 0)
892
+ );
893
+ const chosenData = await processRemoteData(
894
+ db,
895
+ dbKey,
896
+ remotePromises,
897
+ localData,
898
+ { currentServer, syncServers, state }
899
+ );
900
+ return { ...chosenData, dbKey };
901
+ };
902
+ const inFlightKey = buildReadAndWaitRequestKey(dbKey, currentToken);
903
+ const existing = readRequestManager.getInFlight(inFlightKey);
904
+ if (existing) return existing;
905
+ let inFlightPromise;
906
+ inFlightPromise = executeReadAndWait().finally(() => {
907
+ readRequestManager.clearInFlight(inFlightKey, inFlightPromise);
908
+ });
909
+ readRequestManager.setInFlight(inFlightKey, inFlightPromise);
910
+ return inFlightPromise;
911
+ };
912
+
913
+ // packages/database/actions/actionToast.ts
914
+ var registeredToast = null;
915
+ var actionToast = {
916
+ success: (message) => registeredToast?.success(message),
917
+ error: (message) => {
918
+ if (registeredToast) registeredToast.error(message);
919
+ else console.warn(message);
920
+ }
921
+ };
922
+
923
+ // packages/database/actions/write.ts
924
+ var SPACE_MEMBER_PREFIX = "space-member-";
925
+ var getMemberUserIdFromSpaceMemberKey = (dbKey) => {
926
+ if (!dbKey.startsWith(SPACE_MEMBER_PREFIX)) return null;
927
+ const rest = dbKey.slice(SPACE_MEMBER_PREFIX.length);
928
+ const lastDash = rest.lastIndexOf("-");
929
+ if (lastDash <= 0) return null;
930
+ return rest.slice(0, lastDash);
931
+ };
932
+ var saveToClientDb = async (clientDb, dbKey, data) => {
933
+ if (!clientDb) {
934
+ logger.error({ dbKey }, "Client database is undefined in saveToClientDb");
935
+ throw new Error("Client database instance is required");
936
+ }
937
+ try {
938
+ await clientDb.put(dbKey, data);
939
+ logger.debug({ dbKey }, "Data saved successfully to local database.");
940
+ } catch (err) {
941
+ logger.error({ err, dbKey }, "Failed to save data to local database");
942
+ throw new Error(`Local database put failed for ${dbKey}: ${err.message}`);
943
+ }
944
+ };
945
+ var writeAction = async (writeConfig, thunkApi) => {
946
+ const { db: clientDb } = thunkApi.extra;
947
+ if (!clientDb) {
948
+ throw new Error("Client database instance is required in writeAction");
949
+ }
950
+ const state = thunkApi.getState();
951
+ const { currentServer, syncServers, currentUserId } = getRuntimeServerContext(state);
952
+ const { data, customKey } = writeConfig;
953
+ const userId = writeConfig.userId || currentUserId;
954
+ const isSpaceMemberRecord = customKey.startsWith(SPACE_MEMBER_PREFIX);
955
+ const recordUserId = isSpaceMemberRecord ? data.userId || getMemberUserIdFromSpaceMemberKey(customKey) || userId : userId;
956
+ if (!data || !customKey) {
957
+ const errorMsg = "Invalid arguments for writeAction: data and customKey are required.";
958
+ logger.error({ writeConfig }, errorMsg);
959
+ actionToast.error(errorMsg);
960
+ throw new Error(errorMsg);
961
+ }
962
+ const VALID_TYPES = [
963
+ "msg" /* MSG */,
964
+ "page" /* DOC */,
965
+ "dialog" /* DIALOG */,
966
+ "notification" /* NOTIFICATION */,
967
+ "token" /* TOKEN */,
968
+ "transaction" /* TRANSACTION */,
969
+ "space" /* SPACE */,
970
+ "setting" /* SETTING */,
971
+ "table" /* TABLE */,
972
+ "table_row" /* TABLE_ROW */,
973
+ "email" /* EMAIL */,
974
+ "agent" /* AGENT */,
975
+ "agent-automation" /* AGENT_AUTOMATION */
976
+ ];
977
+ if (!data.type || !VALID_TYPES.includes(data.type)) {
978
+ logger.warn(
979
+ `Invalid data type "${data.type}" for writeAction with key ${customKey}. Proceeding anyway.`
980
+ );
981
+ }
982
+ let writeAck = null;
983
+ try {
984
+ const willSaveData = normalizeTimeFields({
985
+ ...data,
986
+ dbKey: customKey,
987
+ userId: recordUserId
988
+ });
989
+ writeAck = beginWriteAck(customKey);
990
+ await saveToClientDb(clientDb, customKey, willSaveData);
991
+ const servers = resolveAuthorityReplicationServers({
992
+ currentServer,
993
+ syncServers,
994
+ dbKey: customKey,
995
+ record: willSaveData,
996
+ state
997
+ });
998
+ const serverWriteConfig = {
999
+ data: willSaveData,
1000
+ customKey,
1001
+ userId: recordUserId
1002
+ };
1003
+ if (servers.length > 0) {
1004
+ logger.debug(
1005
+ `[writeAction] Initiating background sync for key: ${customKey} to ${servers.length} servers.`
1006
+ );
1007
+ const replication = scheduleWriteReplication(
1008
+ servers,
1009
+ serverWriteConfig,
1010
+ state
1011
+ );
1012
+ writeAck.settleWithReplication(replication);
1013
+ } else {
1014
+ writeAck.markNotReplicated();
1015
+ logger.warn(
1016
+ { customKey },
1017
+ "[writeAction] No available servers, data only saved locally."
1018
+ );
1019
+ }
1020
+ return willSaveData;
1021
+ } catch (error) {
1022
+ writeAck?.markAborted();
1023
+ const errorMessage = `Write action failed for ${customKey}: ${error?.message || "Unknown error"}`;
1024
+ logger.error({ error }, "[writeAction] Error");
1025
+ actionToast.error(`Failed to save data for ${customKey}.`);
1026
+ throw new Error(errorMessage);
1027
+ }
1028
+ };
1029
+
1030
+ // packages/database/actions/protectedPagePatch.ts
1031
+ async function patchProtectedPage(options) {
1032
+ const baseline = await getPageReadBaseline(options.db, options.actorId, options.dbKey);
1033
+ if (!baseline) return void 0;
1034
+ const sync = options.sync ?? createProtectedRecordSync({ db: options.db });
1035
+ const scope = { actorId: options.actorId, dbKey: options.dbKey };
1036
+ const state = await sync.readState(scope);
1037
+ if (state.legacyCandidates.length) throw Error("\u672C\u5730\u65E7\u526F\u672C\u5C1A\u672A\u786E\u8BA4\uFF0C\u672A\u8986\u76D6\u4E91\u7AEF\uFF1B\u8BF7\u5148\u5904\u7406\u7248\u672C\u5DEE\u5F02");
1038
+ const current = state.workingCopy?.data ?? await options.db.get(options.dbKey) ?? options.data;
1039
+ const data = options.buildData ? options.buildData(current) : options.data;
1040
+ const draft = await sync.saveLocalDraft({
1041
+ ...scope,
1042
+ ...baseline,
1043
+ baseRevision: state.baselineRevision ?? baseline.revision,
1044
+ mutationId: crypto.randomUUID(),
1045
+ data,
1046
+ operation: "patch",
1047
+ payload: options.changes
1048
+ });
1049
+ if (draft.blocked) throw Error("\u8349\u7A3F\u5DF2\u4FDD\u5B58\u5728\u672C\u5730\uFF0C\u4F46\u540C\u6B65\u53D7\u963B\uFF1B\u4E91\u7AEF\u5C1A\u672A\u786E\u8BA4");
1050
+ const transport = createProtectedRecordTransport({
1051
+ sync,
1052
+ fetch: options.fetch,
1053
+ isAuthorityAllowed: options.isAuthorityAllowed,
1054
+ getToken: async () => options.token()
1055
+ });
1056
+ let result;
1057
+ for (let count = 0; count < draft.outbox.length; count++) {
1058
+ result = await transport.sendNext(scope);
1059
+ if (result.outcome !== "acked") break;
1060
+ }
1061
+ if (result?.outcome === "conflict" || result?.outcome === "blocked") {
1062
+ throw Error("\u8349\u7A3F\u5DF2\u4FDD\u5B58\u5728\u672C\u5730\uFF0C\u4F46\u5B58\u5728\u7248\u672C\u51B2\u7A81\u6216\u6388\u6743\u95EE\u9898\uFF1B\u672A\u8986\u76D6\u4E91\u7AEF");
1063
+ }
1064
+ const latest = await sync.readState(scope);
1065
+ if (options.requireServerConfirmation && latest.outbox.length) {
1066
+ throw Error("\u8349\u7A3F\u5DF2\u4FDD\u5B58\u5728\u672C\u5730\uFF0C\u7B49\u5F85\u670D\u52A1\u5668\u786E\u8BA4\uFF1B\u8BF7\u8054\u7F51\u540E\u91CD\u8BD5\u4FDD\u5B58");
1067
+ }
1068
+ return latest.workingCopy?.data ?? latest.lastAck?.record ?? options.data;
1069
+ }
1070
+
1071
+ // packages/core/timestamp.ts
1072
+ function toTimestampMs(value) {
1073
+ if (typeof value === "number" && Number.isFinite(value)) return value;
1074
+ if (typeof value === "string") {
1075
+ const parsed = Date.parse(value);
1076
+ return Number.isFinite(parsed) ? parsed : 0;
1077
+ }
1078
+ return 0;
1079
+ }
1080
+
1081
+ // packages/database/actions/patch.ts
1082
+ var deepMerge = (target, source) => {
1083
+ const output = { ...target };
1084
+ for (const key in source) {
1085
+ if (Object.prototype.hasOwnProperty.call(source, key)) {
1086
+ if (source[key] === null && key in output) {
1087
+ delete output[key];
1088
+ } else if (isRecord(source[key])) {
1089
+ output[key] = deepMerge(output[key] || {}, source[key]);
1090
+ } else {
1091
+ output[key] = source[key];
1092
+ }
1093
+ }
1094
+ }
1095
+ return output;
1096
+ };
1097
+ var inferNextUpdatedAt = (currentData) => {
1098
+ const previousUpdatedAt = currentData?.updatedAt;
1099
+ const previousCreatedAt = currentData?.createdAt;
1100
+ const previousMetaCreatedAt = currentData?.meta?.createdAt;
1101
+ const previousTimestamp = Math.max(
1102
+ toTimestampMs(previousUpdatedAt),
1103
+ toTimestampMs(previousCreatedAt),
1104
+ toTimestampMs(previousMetaCreatedAt)
1105
+ );
1106
+ const nextTimestamp = Math.max(Date.now(), previousTimestamp + 1);
1107
+ if (typeof previousUpdatedAt === "number" || typeof previousCreatedAt === "number" || typeof previousMetaCreatedAt === "number") {
1108
+ return nextTimestamp;
1109
+ }
1110
+ if (typeof previousUpdatedAt === "string" || typeof previousCreatedAt === "string") {
1111
+ return new Date(nextTimestamp).toISOString();
1112
+ }
1113
+ return void 0;
1114
+ };
1115
+ var patchAction = async ({
1116
+ dbKey,
1117
+ changes,
1118
+ preferredServerOrigin,
1119
+ requireServerConfirmation
1120
+ }, thunkApi) => {
1121
+ const { db } = thunkApi.extra;
1122
+ if (!db) {
1123
+ const errorMsg = "Database instance is not available.";
1124
+ actionToast.error(errorMsg);
1125
+ throw new Error(errorMsg);
1126
+ }
1127
+ if (!dbKey || !changes || typeof changes !== "object") {
1128
+ const errorMsg = "Patch action requires a valid dbKey and changes object.";
1129
+ actionToast.error(errorMsg);
1130
+ throw new Error(errorMsg);
1131
+ }
1132
+ const state = thunkApi.getState();
1133
+ const { currentServer, syncServers: configuredSyncServers, currentToken, currentUserId } = getRuntimeServerContext(state);
1134
+ try {
1135
+ let currentData = await db.get(dbKey);
1136
+ if (!currentData) {
1137
+ const hydrateServer = preferredServerOrigin ?? currentServer;
1138
+ const remoteData = hydrateServer ? await fetchFromServer(hydrateServer, dbKey, currentToken) : null;
1139
+ if (!remoteData) {
1140
+ throw new Error(
1141
+ `Cannot apply patch: Data not found locally or on server for key: ${dbKey}.`
1142
+ );
1143
+ }
1144
+ const latestLocal = await db.get(dbKey);
1145
+ currentData = latestLocal ?? remoteData;
1146
+ }
1147
+ const patchChanges = Object.prototype.hasOwnProperty.call(changes, "updatedAt") ? changes : {
1148
+ ...changes,
1149
+ ...inferNextUpdatedAt(currentData) !== void 0 ? { updatedAt: inferNextUpdatedAt(currentData) } : {}
1150
+ };
1151
+ const newData = deepMerge(currentData, patchChanges);
1152
+ const persistedData = newData && typeof newData === "object" ? { ...newData, dbKey } : { dbKey };
1153
+ if (dbKey.startsWith("page-") && currentUserId && typeof db.batch === "function") {
1154
+ const protectedData = await patchProtectedPage({
1155
+ db,
1156
+ actorId: currentUserId,
1157
+ dbKey,
1158
+ data: persistedData,
1159
+ changes: patchChanges,
1160
+ requireServerConfirmation,
1161
+ buildData: (latest) => ({ ...deepMerge(latest, patchChanges), dbKey }),
1162
+ isAuthorityAllowed: (origin) => {
1163
+ const context = getRuntimeServerContext(thunkApi.getState());
1164
+ return context.currentUserId === currentUserId && context.remoteServers.some((server) => {
1165
+ try {
1166
+ return new URL(server).origin === origin;
1167
+ } catch {
1168
+ return false;
1169
+ }
1170
+ });
1171
+ },
1172
+ token: async () => {
1173
+ const context = getRuntimeServerContext(thunkApi.getState());
1174
+ return context.currentUserId === currentUserId ? context.currentToken ?? null : null;
1175
+ },
1176
+ fetch
1177
+ });
1178
+ if (protectedData !== void 0) return protectedData;
1179
+ }
1180
+ await db.put(dbKey, persistedData);
1181
+ scheduleConfiguredPatchReplication({
1182
+ currentServer,
1183
+ syncServers: configuredSyncServers,
1184
+ preferredServerOrigin,
1185
+ dbKey,
1186
+ changes: patchChanges,
1187
+ state
1188
+ });
1189
+ return persistedData;
1190
+ } catch (error) {
1191
+ const errorMessage = `Failed to update data for ${dbKey}.`;
1192
+ actionToast.error(errorMessage);
1193
+ throw new Error(error.message || errorMessage);
1194
+ }
1195
+ };
1196
+
1197
+ // packages/database/actions/purge.ts
1198
+ var purgeAction = async (payload, thunkApi) => {
1199
+ const { db: clientDb } = thunkApi.extra;
1200
+ const dbKey = typeof payload === "string" ? payload : payload.dbKey;
1201
+ const preferredServerOrigin = typeof payload === "string" ? void 0 : payload.preferredServerOrigin;
1202
+ if (!clientDb) {
1203
+ throw new Error("Client database is undefined in purgeAction");
1204
+ }
1205
+ const state = thunkApi.getState();
1206
+ const { currentServer, syncServers } = getRuntimeServerContext(state);
1207
+ const localData = await fetchFromClientDb(clientDb, dbKey);
1208
+ if (localData && !isTombstoneRecord(localData)) {
1209
+ throw new Error(
1210
+ `purgeAction refused: record ${dbKey} is not tombstoned. Use removeAction instead.`
1211
+ );
1212
+ }
1213
+ await clientDb.del(dbKey);
1214
+ const servers = resolveAuthorityReplicationServers({
1215
+ currentServer,
1216
+ syncServers,
1217
+ preferredServerOrigin,
1218
+ dbKey,
1219
+ state
1220
+ });
1221
+ await Promise.all(
1222
+ servers.map(async (server) => {
1223
+ const ok = await noloDeleteRequest(
1224
+ server,
1225
+ dbKey,
1226
+ { type: "single", force: true },
1227
+ state
1228
+ );
1229
+ if (!ok) {
1230
+ console.warn("[purgeAction] server force-delete failed", { dbKey, server });
1231
+ }
1232
+ })
1233
+ );
1234
+ return { dbKey, servers };
1235
+ };
1236
+
1237
+ // packages/database/actions/upsert.ts
1238
+ var upsertAction = async (upsertConfig, thunkApi) => {
1239
+ const { dbKey, data } = upsertConfig;
1240
+ if (!dbKey || !data || typeof data !== "object") {
1241
+ const errorMsg = "upsertAction \u53C2\u6570\u65E0\u6548\uFF1AdbKey \u548C data \u5BF9\u8C61\u662F\u5FC5\u9700\u7684\u3002";
1242
+ actionToast.error(errorMsg);
1243
+ throw new Error(errorMsg);
1244
+ }
1245
+ try {
1246
+ const existingData = await readAction({ dbKey }, thunkApi);
1247
+ let finalResult;
1248
+ if (existingData && Object.keys(existingData).length > 0) {
1249
+ finalResult = await patchAction({ dbKey, changes: data }, thunkApi);
1250
+ } else {
1251
+ finalResult = await writeAction({ data, customKey: dbKey }, thunkApi);
1252
+ }
1253
+ return finalResult;
1254
+ } catch (error) {
1255
+ const errorMessage = `Upsert \u534F\u8C03\u64CD\u4F5C\u5931\u8D25 (dbKey: ${dbKey}): ${error.message || "\u672A\u77E5\u9519\u8BEF"}`;
1256
+ actionToast.error("\u6570\u636E\u4FDD\u5B58\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002");
1257
+ throw new Error(errorMessage, { cause: error });
1258
+ }
1259
+ };
1260
+
1261
+ // packages/database/actions/upload.ts
1262
+ var saveToClientDb2 = async (clientDb, dbKey, metadata) => {
1263
+ if (!clientDb) {
1264
+ logger.error({ dbKey }, "Client database is undefined in saveToClientDb");
1265
+ throw new Error("Client database instance is required");
1266
+ }
1267
+ try {
1268
+ await clientDb.put(dbKey, metadata);
1269
+ logger.debug(
1270
+ { dbKey },
1271
+ "File metadata saved successfully to local database."
1272
+ );
1273
+ } catch (err) {
1274
+ logger.error(
1275
+ { err, dbKey },
1276
+ "Failed to save file metadata to local database"
1277
+ );
1278
+ throw new Error(`Local database put failed for ${dbKey}: ${err.message}`);
1279
+ }
1280
+ };
1281
+ var uploadFileAction = async (uploadConfig, thunkApi) => {
1282
+ const { db: clientDb } = thunkApi.extra;
1283
+ const state = thunkApi.getState();
1284
+ const { currentServer, syncServers, currentUserId } = getRuntimeServerContext(state);
1285
+ const { file, customKey, onProgress, signal } = uploadConfig;
1286
+ const userId = uploadConfig.userId || currentUserId;
1287
+ if (!file) {
1288
+ const errorMsg = "Invalid arguments for uploadFileAction: file is required.";
1289
+ logger.error({ uploadConfig }, errorMsg);
1290
+ throw new Error(errorMsg);
1291
+ }
1292
+ try {
1293
+ const fileId = ulid();
1294
+ const fileExtension = file.name.split(".").pop() || "";
1295
+ const fileName = `${fileId}${fileExtension ? "." + fileExtension : ""}`;
1296
+ let finalDbKey = customKey;
1297
+ if (!finalDbKey || !finalDbKey.startsWith("file-")) {
1298
+ const actualUserId = userId || "unknown";
1299
+ if (actualUserId === "unknown") {
1300
+ console.warn("[uploadFileAction] User ID is unknown during upload. Key will be file-unknown.");
1301
+ }
1302
+ finalDbKey = fileKey.single(actualUserId, fileId);
1303
+ }
1304
+ const fileMetadata = normalizeTimeFields({
1305
+ id: fileId,
1306
+ title: file.name,
1307
+ originalName: file.name,
1308
+ fileName,
1309
+ filePath: "",
1310
+ size: file.size,
1311
+ mimeType: file.type || "application/octet-stream",
1312
+ type: "file" /* FILE */,
1313
+ fileCategory: resolveFileCategory({
1314
+ mimeType: file.type,
1315
+ fileName: file.name
1316
+ }),
1317
+ dbKey: finalDbKey,
1318
+ userId
1319
+ });
1320
+ await saveToClientDb2(clientDb, finalDbKey, fileMetadata);
1321
+ const cacheLocally = async () => {
1322
+ try {
1323
+ await saveFileToIndexedDb(fileId, file);
1324
+ } catch (err) {
1325
+ logger.warn(
1326
+ { err, fileId },
1327
+ "[uploadFileAction] Failed to cache file locally."
1328
+ );
1329
+ }
1330
+ };
1331
+ const localCachePromise = isMediaFile(file) ? cacheLocally() : null;
1332
+ if (!localCachePromise) {
1333
+ await cacheLocally();
1334
+ }
1335
+ const tenantId = userId || "default";
1336
+ const uploadReplicationConfig = {
1337
+ file,
1338
+ metadata: fileMetadata,
1339
+ customKey: finalDbKey,
1340
+ userId
1341
+ };
1342
+ const uploadServers = resolveUploadReplicationServers({
1343
+ currentServer,
1344
+ syncServers,
1345
+ tenantId,
1346
+ uploadConfig: uploadReplicationConfig,
1347
+ state
1348
+ });
1349
+ const primaryUploadServer = uploadServers[0] ?? currentServer;
1350
+ const primaryUploadSucceeded = await uploadToCurrentServer({
1351
+ currentServer: primaryUploadServer,
1352
+ uploadConfig: uploadReplicationConfig,
1353
+ state,
1354
+ ...onProgress ? { onProgress } : {},
1355
+ ...signal ? { signal } : {}
1356
+ });
1357
+ if (localCachePromise) {
1358
+ await localCachePromise;
1359
+ }
1360
+ if (primaryUploadServer && !primaryUploadSucceeded) {
1361
+ throw new Error(`Primary upload failed on authority server ${primaryUploadServer}`);
1362
+ }
1363
+ const serversToUse = scheduleUploadReplication({
1364
+ currentServer,
1365
+ syncServers,
1366
+ tenantId,
1367
+ uploadConfig: uploadReplicationConfig,
1368
+ state,
1369
+ excludeServers: primaryUploadServer ? [primaryUploadServer] : []
1370
+ });
1371
+ if (!primaryUploadServer && !serversToUse.length) {
1372
+ logger.warn(
1373
+ { finalDbKey, fileName, tenantId },
1374
+ "[uploadFileAction] No replication servers available, file metadata only saved locally."
1375
+ );
1376
+ return fileMetadata;
1377
+ }
1378
+ logger.debug(
1379
+ { primaryUploadServer, currentServer, serversToUse, tenantId },
1380
+ `[uploadFileAction] Uploaded primary copy for ${fileName} and scheduled background sync to ${serversToUse.length} additional servers.`
1381
+ );
1382
+ return fileMetadata;
1383
+ } catch (error) {
1384
+ const errorMessage = `Upload action failed for ${customKey}: ${error?.message || "Unknown error"}`;
1385
+ logger.error({ error }, "[uploadFileAction] Error");
1386
+ throw new Error(errorMessage);
1387
+ }
1388
+ };
1389
+
1390
+ // packages/database/actions/fileContent.ts
1391
+ var resolveLocalFileId = (fileId) => {
1392
+ if (fileId.startsWith("file-")) {
1393
+ return getFileIdFromKey(fileId) || fileId;
1394
+ }
1395
+ return fileId;
1396
+ };
1397
+ var readFileContentAction = async ({
1398
+ fileId,
1399
+ useServerFallback = true
1400
+ }, thunkApi) => {
1401
+ if (!fileId || typeof fileId !== "string") {
1402
+ throw new Error("readFileContentAction requires a valid fileId string.");
1403
+ }
1404
+ const localId = resolveLocalFileId(fileId);
1405
+ const localRecord = await loadFileFromIndexedDb(localId);
1406
+ if (localRecord) {
1407
+ return {
1408
+ fileId: localId,
1409
+ blob: localRecord.blob,
1410
+ source: "local"
1411
+ };
1412
+ }
1413
+ if (!useServerFallback) {
1414
+ throw new Error(
1415
+ `Local file not found for id "${fileId}", and server fallback is disabled.`
1416
+ );
1417
+ }
1418
+ const state = thunkApi.getState();
1419
+ const { currentServer, remoteServers: serversToTry } = getRuntimeServerContext(state);
1420
+ if (!currentServer) {
1421
+ throw new Error(
1422
+ `No current server configured. Cannot fetch remote file for id "${fileId}".`
1423
+ );
1424
+ }
1425
+ let lastError = "";
1426
+ for (const server of serversToTry) {
1427
+ const url = `${server}${API_ENDPOINTS.DATABASE}/file/content/${fileId}`;
1428
+ console.debug("[readFileContentAction] trying server:", url);
1429
+ try {
1430
+ const res = await fetch(url);
1431
+ if (!res.ok) {
1432
+ lastError = `HTTP ${res.status} from ${server}`;
1433
+ console.debug("[readFileContentAction] server returned:", lastError);
1434
+ continue;
1435
+ }
1436
+ const blob = await res.blob();
1437
+ if (typeof indexedDB !== "undefined") {
1438
+ void saveFileToIndexedDb(localId, blob).catch((err) => {
1439
+ console.warn(
1440
+ "[readFileContentAction] Failed to cache remote file into IndexedDB:",
1441
+ err
1442
+ );
1443
+ });
1444
+ }
1445
+ return {
1446
+ fileId: localId,
1447
+ blob,
1448
+ source: "remote"
1449
+ };
1450
+ } catch (err) {
1451
+ lastError = err?.message || "Network error";
1452
+ console.debug(
1453
+ "[readFileContentAction] fetch error from",
1454
+ server,
1455
+ lastError
1456
+ );
1457
+ }
1458
+ }
1459
+ throw new Error(
1460
+ `Failed to fetch remote file content from all servers for id "${fileId}". Last error: ${lastError}`
1461
+ );
1462
+ };
1463
+
1464
+ // packages/database/dbSlice.ts
1465
+ var dbAdapter = createEntityAdapter({
1466
+ selectId: (entity) => entity.dbKey
1467
+ });
1468
+ var {
1469
+ selectById,
1470
+ selectEntities,
1471
+ selectAll,
1472
+ selectIds,
1473
+ selectTotal
1474
+ } = dbAdapter.getSelectors((state) => state.db);
1475
+ var initialState = dbAdapter.getInitialState({});
1476
+ var createSliceWithThunks = buildCreateSlice({
1477
+ creators: { asyncThunk: asyncThunkCreator }
1478
+ });
1479
+ var dbSlice = createSliceWithThunks({
1480
+ name: "db",
1481
+ initialState,
1482
+ reducers: (create) => ({
1483
+ // Async Thunks
1484
+ // 惰性加载 readAction:esbuild 把大型 read.ts 排到同 chunk 后部时,
1485
+ // `var readAction` 在 create.asyncThunk(readAction) 执行时仍是 undefined,
1486
+ // 之后所有 dispatch(read) 抛 "payloadCreator is not a function"。
1487
+ // 动态 import 在调用期解析,避开 TDZ/求值顺序问题(同下方 share)。
1488
+ read: create.asyncThunk(
1489
+ async (payload, thunkApi) => {
1490
+ const { readAction: readAction2 } = await import("./read-MRQHJMJ2.js");
1491
+ return readAction2(payload, thunkApi);
1492
+ },
1493
+ {
1494
+ fulfilled: (state, action) => {
1495
+ if (action.payload && Object.keys(action.payload).length > 0) {
1496
+ dbAdapter.upsertOne(state, action.payload);
1497
+ }
1498
+ }
1499
+ }
1500
+ ),
1501
+ readAndWait: create.asyncThunk(readAndWaitAction, {
1502
+ fulfilled: (state, action) => {
1503
+ if (action.payload && Object.keys(action.payload).length > 0) {
1504
+ dbAdapter.upsertOne(state, action.payload);
1505
+ }
1506
+ }
1507
+ }),
1508
+ remove: create.asyncThunk(removeAction, {
1509
+ fulfilled: (state, action) => {
1510
+ const { dbKey } = action.payload;
1511
+ if (dbKey) dbAdapter.removeOne(state, dbKey);
1512
+ }
1513
+ }),
1514
+ purge: create.asyncThunk(purgeAction, {
1515
+ fulfilled: (state, action) => {
1516
+ const { dbKey } = action.payload;
1517
+ if (dbKey) dbAdapter.removeOne(state, dbKey);
1518
+ }
1519
+ }),
1520
+ write: create.asyncThunk(writeAction, {
1521
+ fulfilled: (state, action) => {
1522
+ if (action.payload && action.payload.dbKey && Object.keys(action.payload).length > 0) {
1523
+ dbAdapter.upsertOne(state, action.payload);
1524
+ }
1525
+ }
1526
+ }),
1527
+ patch: create.asyncThunk(patchAction, {
1528
+ fulfilled: (state, action) => {
1529
+ const { payload } = action;
1530
+ if (payload && payload.dbKey && Object.keys(payload).length > 0) {
1531
+ dbAdapter.upsertOne(state, payload);
1532
+ }
1533
+ }
1534
+ }),
1535
+ upsert: create.asyncThunk(upsertAction, {
1536
+ fulfilled: (state, action) => {
1537
+ if (action.payload && action.payload.dbKey && Object.keys(action.payload).length > 0) {
1538
+ dbAdapter.upsertOne(state, action.payload);
1539
+ }
1540
+ }
1541
+ }),
1542
+ // 文件上传(avatar / Slate / Space 等统一走这里)
1543
+ upload: create.asyncThunk(uploadFileAction, {
1544
+ fulfilled: (state, action) => {
1545
+ const payload = action.payload;
1546
+ if (payload && payload.dbKey && Object.keys(payload).length > 0) {
1547
+ dbAdapter.upsertOne(state, payload);
1548
+ }
1549
+ }
1550
+ }),
1551
+ // 读取文件内容(优先本地 IndexedDB,无状态副作用)
1552
+ readFileContent: create.asyncThunk(readFileContentAction, {
1553
+ // fulfilled 时不修改 db state;由调用方通过 unwrap() 拿返回值使用
1554
+ }),
1555
+ // 惰性加载 shareResourceAction:静态 import 会形成
1556
+ // dbSlice -> share/action -> settings/settingSlice -> settingPersistence
1557
+ // -> settings/dbActionThunks -> database/dbActionThunks -> dbSlice 的循环依赖。
1558
+ // 分包后 chunk 求值顺序一旦从环内进入 dbSlice,上面的 `readAction` 等
1559
+ // `export const` 还处于未初始化状态,thunk 会以 undefined 作为 payloadCreator
1560
+ // 建成,之后 dispatch(read(...)) 抛 "payloadCreator is not a function"。
1561
+ // 这里改成动态 import,运行期才解析,彻底断开这条边。
1562
+ share: create.asyncThunk(
1563
+ async (config, thunkApi) => {
1564
+ const { shareResourceAction } = await import("./action-CK64LS6S.js");
1565
+ return shareResourceAction(config, thunkApi);
1566
+ }
1567
+ ),
1568
+ // SSR 预取:服务端直接注入实体到 db slice,供首屏 hydrate 使用
1569
+ upsertSSREntity: create.reducer((state, action) => {
1570
+ if (action.payload && action.payload.dbKey) {
1571
+ dbAdapter.upsertOne(state, action.payload);
1572
+ }
1573
+ }),
1574
+ // Undo an in-memory optimistic entity without writing a tombstone or
1575
+ // scheduling remote deletion. Durable deletes must continue to use remove.
1576
+ removeCachedEntity: create.reducer((state, action) => {
1577
+ if (action.payload) dbAdapter.removeOne(state, action.payload);
1578
+ })
1579
+ })
1580
+ });
1581
+ var {
1582
+ remove,
1583
+ purge,
1584
+ read,
1585
+ readAndWait,
1586
+ write,
1587
+ patch,
1588
+ upsert,
1589
+ upload,
1590
+ readFileContent,
1591
+ share,
1592
+ upsertSSREntity,
1593
+ removeCachedEntity
1594
+ } = dbSlice.actions;
1595
+ var dbSlice_default = dbSlice.reducer;
1596
+
1597
+ export {
1598
+ readAndWaitAction,
1599
+ toTimestampMs,
1600
+ uploadFileAction,
1601
+ readFileContentAction,
1602
+ dbAdapter,
1603
+ selectById,
1604
+ selectEntities,
1605
+ selectAll,
1606
+ selectIds,
1607
+ selectTotal,
1608
+ remove,
1609
+ purge,
1610
+ read,
1611
+ readAndWait,
1612
+ write,
1613
+ patch,
1614
+ upsert,
1615
+ upload,
1616
+ readFileContent,
1617
+ share,
1618
+ upsertSSREntity,
1619
+ removeCachedEntity,
1620
+ dbSlice_default
1621
+ };