@openclaw/crabline 0.1.9 → 0.1.10

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 (189) hide show
  1. package/README.md +47 -22
  2. package/assets/crabline-banner.svg +20 -0
  3. package/dist/src/bin/crabline.js.map +1 -1
  4. package/dist/src/cli/program.d.ts +25 -1
  5. package/dist/src/cli/program.js +579 -82
  6. package/dist/src/cli/program.js.map +1 -1
  7. package/dist/src/config/load.js +59 -6
  8. package/dist/src/config/load.js.map +1 -1
  9. package/dist/src/config/schema.d.ts +116 -92
  10. package/dist/src/config/schema.js +179 -73
  11. package/dist/src/config/schema.js.map +1 -1
  12. package/dist/src/core/errors.js +9 -2
  13. package/dist/src/core/errors.js.map +1 -1
  14. package/dist/src/core/exit-codes.js.map +1 -1
  15. package/dist/src/core/matcher.js +7 -6
  16. package/dist/src/core/matcher.js.map +1 -1
  17. package/dist/src/core/message-template.js.map +1 -1
  18. package/dist/src/core/nonces.d.ts +1 -0
  19. package/dist/src/core/nonces.js +4 -2
  20. package/dist/src/core/nonces.js.map +1 -1
  21. package/dist/src/core/reporters.d.ts +1 -0
  22. package/dist/src/core/reporters.js +42 -4
  23. package/dist/src/core/reporters.js.map +1 -1
  24. package/dist/src/core/run.d.ts +3 -0
  25. package/dist/src/core/run.js +415 -107
  26. package/dist/src/core/run.js.map +1 -1
  27. package/dist/src/core/safe-regex.d.ts +3 -0
  28. package/dist/src/core/safe-regex.js +21 -0
  29. package/dist/src/core/safe-regex.js.map +1 -0
  30. package/dist/src/index.d.ts +2 -2
  31. package/dist/src/index.js +1 -1
  32. package/dist/src/index.js.map +1 -1
  33. package/dist/src/openclaw/artifact-generation.d.ts +38 -0
  34. package/dist/src/openclaw/artifact-generation.js +314 -0
  35. package/dist/src/openclaw/artifact-generation.js.map +1 -0
  36. package/dist/src/openclaw/bridges/matrix.js +97 -12
  37. package/dist/src/openclaw/bridges/matrix.js.map +1 -1
  38. package/dist/src/openclaw/bridges/mattermost.js +32 -10
  39. package/dist/src/openclaw/bridges/mattermost.js.map +1 -1
  40. package/dist/src/openclaw/bridges/signal.js +55 -18
  41. package/dist/src/openclaw/bridges/signal.js.map +1 -1
  42. package/dist/src/openclaw/bridges/slack.js +85 -7
  43. package/dist/src/openclaw/bridges/slack.js.map +1 -1
  44. package/dist/src/openclaw/bridges/telegram.js +124 -30
  45. package/dist/src/openclaw/bridges/telegram.js.map +1 -1
  46. package/dist/src/openclaw/bridges/whatsapp.js +78 -17
  47. package/dist/src/openclaw/bridges/whatsapp.js.map +1 -1
  48. package/dist/src/openclaw/bridges/zalo.js +14 -5
  49. package/dist/src/openclaw/bridges/zalo.js.map +1 -1
  50. package/dist/src/openclaw/outbound-contract.d.ts +5 -0
  51. package/dist/src/openclaw/outbound-contract.js +40 -0
  52. package/dist/src/openclaw/outbound-contract.js.map +1 -0
  53. package/dist/src/openclaw/private-file.d.ts +26 -0
  54. package/dist/src/openclaw/private-file.js +411 -0
  55. package/dist/src/openclaw/private-file.js.map +1 -0
  56. package/dist/src/openclaw/shared.d.ts +21 -2
  57. package/dist/src/openclaw/shared.js +115 -18
  58. package/dist/src/openclaw/shared.js.map +1 -1
  59. package/dist/src/openclaw/smoke-lock.d.ts +63 -0
  60. package/dist/src/openclaw/smoke-lock.js +949 -0
  61. package/dist/src/openclaw/smoke-lock.js.map +1 -0
  62. package/dist/src/openclaw.d.ts +16 -8
  63. package/dist/src/openclaw.js +194 -52
  64. package/dist/src/openclaw.js.map +1 -1
  65. package/dist/src/providers/builtin/discord.d.ts +10 -1
  66. package/dist/src/providers/builtin/discord.js +144 -18
  67. package/dist/src/providers/builtin/discord.js.map +1 -1
  68. package/dist/src/providers/builtin/external-webhook-auth.d.ts +11 -0
  69. package/dist/src/providers/builtin/external-webhook-auth.js +10 -0
  70. package/dist/src/providers/builtin/external-webhook-auth.js.map +1 -0
  71. package/dist/src/providers/builtin/feishu.d.ts +19 -2
  72. package/dist/src/providers/builtin/feishu.js +307 -25
  73. package/dist/src/providers/builtin/feishu.js.map +1 -1
  74. package/dist/src/providers/builtin/googlechat.d.ts +20 -1
  75. package/dist/src/providers/builtin/googlechat.js +178 -19
  76. package/dist/src/providers/builtin/googlechat.js.map +1 -1
  77. package/dist/src/providers/builtin/imessage.d.ts +4 -0
  78. package/dist/src/providers/builtin/imessage.js +26 -11
  79. package/dist/src/providers/builtin/imessage.js.map +1 -1
  80. package/dist/src/providers/builtin/loopback.js +92 -30
  81. package/dist/src/providers/builtin/loopback.js.map +1 -1
  82. package/dist/src/providers/builtin/matrix.d.ts +11 -1
  83. package/dist/src/providers/builtin/matrix.js +53 -29
  84. package/dist/src/providers/builtin/matrix.js.map +1 -1
  85. package/dist/src/providers/builtin/mattermost.d.ts +10 -0
  86. package/dist/src/providers/builtin/mattermost.js +38 -15
  87. package/dist/src/providers/builtin/mattermost.js.map +1 -1
  88. package/dist/src/providers/builtin/msteams.d.ts +17 -1
  89. package/dist/src/providers/builtin/msteams.js +113 -14
  90. package/dist/src/providers/builtin/msteams.js.map +1 -1
  91. package/dist/src/providers/builtin/native-local-mock.d.ts +2 -9
  92. package/dist/src/providers/builtin/native-local-mock.js +12 -35
  93. package/dist/src/providers/builtin/native-local-mock.js.map +1 -1
  94. package/dist/src/providers/builtin/script.d.ts +11 -15
  95. package/dist/src/providers/builtin/script.js +566 -104
  96. package/dist/src/providers/builtin/script.js.map +1 -1
  97. package/dist/src/providers/builtin/slack.d.ts +6 -0
  98. package/dist/src/providers/builtin/slack.js +99 -40
  99. package/dist/src/providers/builtin/slack.js.map +1 -1
  100. package/dist/src/providers/builtin/telegram.d.ts +6 -0
  101. package/dist/src/providers/builtin/telegram.js +64 -43
  102. package/dist/src/providers/builtin/telegram.js.map +1 -1
  103. package/dist/src/providers/builtin/whatsapp.d.ts +28 -8
  104. package/dist/src/providers/builtin/whatsapp.js +567 -30
  105. package/dist/src/providers/builtin/whatsapp.js.map +1 -1
  106. package/dist/src/providers/builtin/zalo.js +30 -19
  107. package/dist/src/providers/builtin/zalo.js.map +1 -1
  108. package/dist/src/providers/catalog.d.ts +3 -3
  109. package/dist/src/providers/catalog.js +3 -3
  110. package/dist/src/providers/catalog.js.map +1 -1
  111. package/dist/src/providers/local-mock.d.ts +11 -2
  112. package/dist/src/providers/local-mock.js +322 -96
  113. package/dist/src/providers/local-mock.js.map +1 -1
  114. package/dist/src/providers/native-ids.d.ts +1 -0
  115. package/dist/src/providers/native-ids.js +6 -1
  116. package/dist/src/providers/native-ids.js.map +1 -1
  117. package/dist/src/providers/recorder.d.ts +30 -2
  118. package/dist/src/providers/recorder.js +539 -70
  119. package/dist/src/providers/recorder.js.map +1 -1
  120. package/dist/src/providers/registry.d.ts +25 -1
  121. package/dist/src/providers/registry.js +280 -40
  122. package/dist/src/providers/registry.js.map +1 -1
  123. package/dist/src/providers/signed-jwt.d.ts +29 -0
  124. package/dist/src/providers/signed-jwt.js +202 -0
  125. package/dist/src/providers/signed-jwt.js.map +1 -0
  126. package/dist/src/providers/slack-ids.js.map +1 -1
  127. package/dist/src/providers/target-normalizers.d.ts +26 -0
  128. package/dist/src/providers/target-normalizers.js +276 -0
  129. package/dist/src/providers/target-normalizers.js.map +1 -0
  130. package/dist/src/providers/types.d.ts +5 -0
  131. package/dist/src/providers/types.js.map +1 -1
  132. package/dist/src/providers/webhook-server.d.ts +2 -0
  133. package/dist/src/providers/webhook-server.js +72 -25
  134. package/dist/src/providers/webhook-server.js.map +1 -1
  135. package/dist/src/servers/http.d.ts +23 -3
  136. package/dist/src/servers/http.js +213 -20
  137. package/dist/src/servers/http.js.map +1 -1
  138. package/dist/src/servers/index.js +20 -21
  139. package/dist/src/servers/index.js.map +1 -1
  140. package/dist/src/servers/matrix.js +465 -51
  141. package/dist/src/servers/matrix.js.map +1 -1
  142. package/dist/src/servers/mattermost.d.ts +5 -0
  143. package/dist/src/servers/mattermost.js +306 -58
  144. package/dist/src/servers/mattermost.js.map +1 -1
  145. package/dist/src/servers/pending-events.d.ts +2 -0
  146. package/dist/src/servers/pending-events.js +11 -0
  147. package/dist/src/servers/pending-events.js.map +1 -0
  148. package/dist/src/servers/recorder.d.ts +5 -0
  149. package/dist/src/servers/recorder.js +46 -3
  150. package/dist/src/servers/recorder.js.map +1 -1
  151. package/dist/src/servers/signal.d.ts +2 -0
  152. package/dist/src/servers/signal.js +444 -56
  153. package/dist/src/servers/signal.js.map +1 -1
  154. package/dist/src/servers/slack.d.ts +5 -0
  155. package/dist/src/servers/slack.js +515 -49
  156. package/dist/src/servers/slack.js.map +1 -1
  157. package/dist/src/servers/telegram.d.ts +111 -0
  158. package/dist/src/servers/telegram.js +811 -152
  159. package/dist/src/servers/telegram.js.map +1 -1
  160. package/dist/src/servers/webhook-target.d.ts +40 -0
  161. package/dist/src/servers/webhook-target.js +349 -0
  162. package/dist/src/servers/webhook-target.js.map +1 -0
  163. package/dist/src/servers/websocket.d.ts +2 -0
  164. package/dist/src/servers/websocket.js +29 -0
  165. package/dist/src/servers/websocket.js.map +1 -0
  166. package/dist/src/servers/whatsapp-baileys-websocket.d.ts +65 -1
  167. package/dist/src/servers/whatsapp-baileys-websocket.js +723 -99
  168. package/dist/src/servers/whatsapp-baileys-websocket.js.map +1 -1
  169. package/dist/src/servers/whatsapp-jid.d.ts +5 -0
  170. package/dist/src/servers/whatsapp-jid.js +32 -0
  171. package/dist/src/servers/whatsapp-jid.js.map +1 -0
  172. package/dist/src/servers/whatsapp-wire/binary-node.d.ts +5 -0
  173. package/dist/src/servers/whatsapp-wire/binary-node.js +87 -20
  174. package/dist/src/servers/whatsapp-wire/binary-node.js.map +1 -1
  175. package/dist/src/servers/whatsapp-wire/crypto.d.ts +6 -1
  176. package/dist/src/servers/whatsapp-wire/crypto.js +99 -45
  177. package/dist/src/servers/whatsapp-wire/crypto.js.map +1 -1
  178. package/dist/src/servers/whatsapp-wire/handshake.js +39 -4
  179. package/dist/src/servers/whatsapp-wire/handshake.js.map +1 -1
  180. package/dist/src/servers/whatsapp-wire/signal.js.map +1 -1
  181. package/dist/src/servers/whatsapp.d.ts +12 -7
  182. package/dist/src/servers/whatsapp.js +269 -107
  183. package/dist/src/servers/whatsapp.js.map +1 -1
  184. package/dist/src/servers/zalo.d.ts +14 -0
  185. package/dist/src/servers/zalo.js +521 -88
  186. package/dist/src/servers/zalo.js.map +1 -1
  187. package/docs/channel-setup.md +197 -19
  188. package/fixtures/examples/crabline.example.yaml +10 -0
  189. package/package.json +20 -15
@@ -0,0 +1 @@
1
+ {"version":3,"file":"private-file.js","sourceRoot":"","sources":["../../../src/openclaw/private-file.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,EAAE,EAAmB,MAAM,kBAAkB,CAAC;AACvD,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAEtC,MAAM,aAAa,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAC;AAE1C,MAAM,6BAA6B,GAAG,MAAM,CAAC,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAyD/C,CAAC;AAEF,MAAM,uCAAuC,GAAG,MAAM,CAAC,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAoEzD,CAAC;AAWF,MAAM,oBAAoB,GAAqB,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE;IAC9E,MAAM,aAAa,CAAC,OAAO,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;AAC9C,CAAC,CAAC;AAEF,MAAM,UAAU,4BAA4B,CAAC,UAAqC;IAChF,MAAM,cAAc,GAAG,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAChG,IAAI,CAAC,cAAc,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,cAAc,CAAC,EAAE,CAAC;QAC5D,MAAM,IAAI,KAAK,CAAC,oDAAoD,CAAC,CAAC;IACxE,CAAC;IACD,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,cAAc,EAAE,UAAU,EAAE,mBAAmB,EAAE,MAAM,EAAE,gBAAgB,CAAC,CAAC;AACpG,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAC5C,QAAgB,EAChB,GAAG,GAAqB,oBAAoB,EAC5C,UAAU,GAA8B,OAAO,CAAC,GAAG,CAAC,UAAU;IAE9D,IAAI,CAAC;QACH,MAAM,cAAc,GAAG,4BAA4B,CAAC,UAAU,CAAC,CAAC;QAChE,MAAM,GAAG,CACP,cAAc,EACd,CAAC,SAAS,EAAE,YAAY,EAAE,iBAAiB,EAAE,UAAU,EAAE,6BAA6B,CAAC,EACvF;YACE,GAAG,EAAE;gBACH,GAAG,OAAO,CAAC,GAAG;gBACd,0BAA0B,EAAE,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC;aACnD;YACD,WAAW,EAAE,IAAI;SAClB,CACF,CAAC;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CACb,gGAAgG,EAChG,EAAE,KAAK,EAAE,KAAK,EAAE,CACjB,CAAC;IACJ,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,iCAAiC,CACrD,aAAqB,EACrB,GAAG,GAAqB,oBAAoB,EAC5C,UAAU,GAA8B,OAAO,CAAC,GAAG,CAAC,UAAU;IAE9D,IAAI,CAAC;QACH,MAAM,cAAc,GAAG,4BAA4B,CAAC,UAAU,CAAC,CAAC;QAChE,MAAM,GAAG,CACP,cAAc,EACd;YACE,SAAS;YACT,YAAY;YACZ,iBAAiB;YACjB,UAAU;YACV,uCAAuC;SACxC,EACD;YACE,GAAG,EAAE;gBACH,GAAG,OAAO,CAAC,GAAG;gBACd,+BAA+B,EAAE,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC;aAC7D;YACD,WAAW,EAAE,IAAI;SAClB,CACF,CAAC;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CACb,0GAA0G,EAC1G,EAAE,KAAK,EAAE,KAAK,EAAE,CACjB,CAAC;IACJ,CAAC;AACH,CAAC;AAOD,KAAK,UAAU,kBAAkB,CAAC,MAAkB;IAClD,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;IAClD,IAAI,KAAK,CAAC,GAAG,IAAI,EAAE,EAAE,CAAC;QACpB,MAAM,IAAI,KAAK,CAAC,gEAAgE,CAAC,CAAC;IACpF,CAAC;IACD,OAAO;QACL,MAAM,EAAE,KAAK,CAAC,GAAG;QACjB,KAAK,EAAE,KAAK,CAAC,GAAG;KACjB,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,kBAAkB,CAAC,QAAgB,EAAE,QAAsB;IACxE,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,MAAM,EAAE,CAAC,KAAK,CAAC,QAAQ,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;QACzD,IACE,KAAK,CAAC,MAAM,EAAE;YACd,KAAK,CAAC,KAAK,KAAK,EAAE;YAClB,KAAK,CAAC,GAAG,KAAK,QAAQ,CAAC,MAAM;YAC7B,KAAK,CAAC,GAAG,KAAK,QAAQ,CAAC,KAAK,EAC5B,CAAC;YACD,OAAO;QACT,CAAC;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CAAC,wDAAwD,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;IAC9F,CAAC;IACD,MAAM,IAAI,KAAK,CAAC,wDAAwD,CAAC,CAAC;AAC5E,CAAC;AAOD,KAAK,UAAU,2BAA2B,CAAC,MAAkB;IAC3D,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;IAClD,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE,IAAI,KAAK,CAAC,GAAG,IAAI,EAAE,EAAE,CAAC;QAC5C,MAAM,IAAI,KAAK,CAAC,qEAAqE,CAAC,CAAC;IACzF,CAAC;IACD,OAAO;QACL,MAAM,EAAE,KAAK,CAAC,GAAG;QACjB,KAAK,EAAE,KAAK,CAAC,GAAG;KACjB,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,2BAA2B,CACxC,aAAqB,EACrB,QAA2B;IAE3B,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,MAAM,EAAE,CAAC,KAAK,CAAC,aAAa,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;QAC9D,IAAI,KAAK,CAAC,WAAW,EAAE,IAAI,KAAK,CAAC,GAAG,KAAK,QAAQ,CAAC,MAAM,IAAI,KAAK,CAAC,GAAG,KAAK,QAAQ,CAAC,KAAK,EAAE,CAAC;YACzF,OAAO;QACT,CAAC;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CAAC,6DAA6D,EAAE;YAC7E,KAAK,EAAE,KAAK;SACb,CAAC,CAAC;IACL,CAAC;IACD,MAAM,IAAI,KAAK,CAAC,6DAA6D,CAAC,CAAC;AACjF,CAAC;AAOD,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAC5C,aAAqB;IAErB,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,aAAa,EAAE,GAAG,CAAC,CAAC;IACjD,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,2BAA2B,CAAC,MAAM,CAAC,CAAC;QAC3D,MAAM,OAAO,GAA4B;YACvC,KAAK,CAAC,gBAAgB,CAAC,WAAW,GAAG,aAAa;gBAChD,MAAM,2BAA2B,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;YAC3D,CAAC;YACD,aAAa;SACd,CAAC;QACF,MAAM,OAAO,CAAC,gBAAgB,EAAE,CAAC;QACjC,OAAO,OAAO,CAAC;IACjB,CAAC;YAAS,CAAC;QACT,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;IACvB,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,QAAgB,EAChB,QAAQ,GAAoB,OAAO,CAAC,QAAQ;IAE5C,IAAI,QAAQ,KAAK,OAAO,EAAE,CAAC;QACzB,OAAO;IACT,CAAC;IACD,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,GAAG,CAAC,CAAC;IAC1D,IAAI,CAAC;QACH,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;IACtB,CAAC;YAAS,CAAC;QACT,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;IACvB,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,6BAA6B,CACjD,OAAgC,EAChC,WAAW,GAAG,OAAO,CAAC,aAAa;IAEnC,MAAM,cAAc,GAAG,IAAI,CAAC,IAAI,CAC9B,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,EACzB,IAAI,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,OAAO,CAAC,GAAG,IAAI,UAAU,EAAE,SAAS,CACvE,CAAC;IACF,MAAM,OAAO,CAAC,gBAAgB,CAAC,WAAW,CAAC,CAAC;IAC5C,MAAM,EAAE,CAAC,MAAM,CAAC,WAAW,EAAE,cAAc,CAAC,CAAC;IAC7C,MAAM,OAAO,CAAC,gBAAgB,CAAC,cAAc,CAAC,CAAC;IAC/C,MAAM,mBAAmB,CAAC,cAAc,CAAC,CAAC;IAC1C,MAAM,EAAE,CAAC,EAAE,CAAC,cAAc,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC9D,MAAM,mBAAmB,CAAC,cAAc,CAAC,CAAC;AAC5C,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAC1C,aAAqB,EACrB,OAAO,GAGH,EAAE;IAEN,IAAI,OAAO,GAAG,KAAK,CAAC;IACpB,IAAI,CAAC;QACH,MAAM,EAAE,CAAC,KAAK,CAAC,aAAa,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;QAC/C,OAAO,GAAG,IAAI,CAAC;IACjB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAK,KAA+B,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YACvD,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,aAAa,EAAE,GAAG,CAAC,CAAC;IACjD,IAAI,UAAU,GAAG,IAAI,CAAC;IACtB,MAAM,WAAW,GAAG,KAAK,IAAI,EAAE;QAC7B,IAAI,CAAC,UAAU,EAAE,CAAC;YAChB,OAAO;QACT,CAAC;QACD,UAAU,GAAG,KAAK,CAAC;QACnB,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;IACvB,CAAC,CAAC;IACF,IAAI,QAA2B,CAAC;IAChC,IAAI,CAAC;QACH,QAAQ,GAAG,MAAM,2BAA2B,CAAC,MAAM,CAAC,CAAC;IACvD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,CAAC;YACH,MAAM,WAAW,EAAE,CAAC;QACtB,CAAC;QAAC,OAAO,UAAU,EAAE,CAAC;YACpB,MAAM,cAAc,GAAG,IAAI,cAAc,CACvC,CAAC,KAAK,EAAE,UAAU,CAAC,EACnB,oFAAoF,CACrF,CAAC;YACF,cAAc,CAAC,KAAK,GAAG,KAAK,CAAC;YAC7B,MAAM,cAAc,CAAC;QACvB,CAAC;QACD,MAAM,KAAK,CAAC;IACd,CAAC;IACD,MAAM,OAAO,GAA4B;QACvC,KAAK,CAAC,gBAAgB,CAAC,WAAW,GAAG,aAAa;YAChD,MAAM,2BAA2B,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;QAC3D,CAAC;QACD,aAAa;KACd,CAAC;IACF,IAAI,CAAC;QACH,MAAM,OAAO,CAAC,gBAAgB,EAAE,CAAC;QACjC,IAAI,CAAC,OAAO,CAAC,QAAQ,IAAI,OAAO,CAAC,QAAQ,CAAC,KAAK,OAAO,EAAE,CAAC;YACvD,MAAM,CAAC,OAAO,CAAC,sBAAsB,IAAI,iCAAiC,CAAC,CAAC,aAAa,CAAC,CAAC;QAC7F,CAAC;aAAM,CAAC;YACN,MAAM,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAC5B,CAAC;QACD,MAAM,OAAO,CAAC,gBAAgB,EAAE,CAAC;IACnC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,YAAY,GAAG,KAAK,CAAC;QACzB,IAAI,CAAC;YACH,MAAM,WAAW,EAAE,CAAC;QACtB,CAAC;QAAC,OAAO,UAAU,EAAE,CAAC;YACpB,MAAM,cAAc,GAAG,IAAI,cAAc,CACvC,CAAC,KAAK,EAAE,UAAU,CAAC,EACnB,oFAAoF,CACrF,CAAC;YACF,cAAc,CAAC,KAAK,GAAG,KAAK,CAAC;YAC7B,YAAY,GAAG,cAAc,CAAC;QAChC,CAAC;QACD,IAAI,OAAO,EAAE,CAAC;YACZ,IAAI,CAAC;gBACH,MAAM,6BAA6B,CAAC,OAAO,CAAC,CAAC;YAC/C,CAAC;YAAC,OAAO,YAAY,EAAE,CAAC;gBACtB,MAAM,cAAc,GAAG,IAAI,cAAc,CACvC,CAAC,YAAY,EAAE,YAAY,CAAC,EAC5B,uEACE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CACvD,EAAE,CACH,CAAC;gBACF,cAAc,CAAC,KAAK,GAAG,YAAY,CAAC;gBACpC,MAAM,cAAc,CAAC;YACvB,CAAC;QACH,CAAC;QACD,MAAM,YAAY,CAAC;IACrB,CAAC;YAAS,CAAC;QACT,MAAM,WAAW,EAAE,CAAC;IACtB,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,4BAA4B,CAChD,QAAgB,EAChB,QAAgB,EAChB,OAAO,GAOH,EAAE;IAEN,MAAM,aAAa,GAAG,IAAI,CAAC,IAAI,CAC7B,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,EACtB,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,OAAO,CAAC,GAAG,IAAI,UAAU,EAAE,MAAM,CACjE,CAAC;IACF,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC5D,IAAI,MAA8B,CAAC;IACnC,IAAI,iBAAiB,GAAG,KAAK,CAAC;IAC9B,IAAI,YAAqB,CAAC;IAC1B,IAAI,CAAC;QACH,MAAM,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,aAAa,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;QACpD,MAAM,QAAQ,GAAG,MAAM,kBAAkB,CAAC,MAAM,CAAC,CAAC;QAClD,IAAI,CAAC,OAAO,CAAC,QAAQ,IAAI,OAAO,CAAC,QAAQ,CAAC,KAAK,OAAO,EAAE,CAAC;YACvD,MAAM,CAAC,OAAO,CAAC,iBAAiB,IAAI,wBAAwB,CAAC,CAAC,aAAa,CAAC,CAAC;QAC/E,CAAC;aAAM,CAAC;YACN,MAAM,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAC5B,CAAC;QAED,MAAM,kBAAkB,CAAC,aAAa,EAAE,QAAQ,CAAC,CAAC;QAClD,MAAM,MAAM,CAAC,SAAS,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QACzC,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;QACpB,MAAM,kBAAkB,CAAC,aAAa,EAAE,QAAQ,CAAC,CAAC;QAClD,MAAM,OAAO,CAAC,YAAY,EAAE,CAAC,aAAa,CAAC,CAAC;QAC5C,MAAM,kBAAkB,CAAC,aAAa,EAAE,QAAQ,CAAC,CAAC;QAClD,MAAM,EAAE,CAAC,MAAM,CAAC,aAAa,EAAE,QAAQ,CAAC,CAAC;QACzC,MAAM,CAAC,OAAO,CAAC,UAAU,IAAI,mBAAmB,CAAC,CAAC,QAAQ,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC;QAC9E,MAAM,OAAO,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,CAAC;QACtC,MAAM,kBAAkB,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;IAC/C,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,iBAAiB,GAAG,IAAI,CAAC;QACzB,YAAY,GAAG,KAAK,CAAC;IACvB,CAAC;IAED,MAAM,aAAa,GAAc,EAAE,CAAC;IACpC,IAAI,CAAC;QACH,MAAM,MAAM,EAAE,KAAK,EAAE,CAAC;IACxB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC5B,CAAC;IACD,IAAI,CAAC;QACH,MAAM,CACJ,OAAO,CAAC,mBAAmB;YAC3B,CAAC,CAAC,aAAqB,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,aAAa,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CACnE,CAAC,aAAa,CAAC,CAAC;IACnB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC5B,CAAC;IAED,IAAI,iBAAiB,EAAE,CAAC;QACtB,IAAI,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC7B,MAAM,cAAc,GAClB,YAAY,YAAY,KAAK,CAAC,CAAC,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;YAC9E,MAAM,cAAc,GAAG,IAAI,cAAc,CACvC,CAAC,YAAY,EAAE,GAAG,aAAa,CAAC,EAChC,GAAG,cAAc,8CAA8C,CAChE,CAAC;YACF,cAAc,CAAC,KAAK,GAAG,YAAY,CAAC;YACpC,MAAM,WAAW,GACf,OAAO,YAAY,KAAK,QAAQ,IAAI,YAAY,KAAK,IAAI;gBACvD,CAAC,CAAE,YAAsC,CAAC,IAAI;gBAC9C,CAAC,CAAC,SAAS,CAAC;YAChB,IAAI,WAAW,EAAE,CAAC;gBAChB,MAAM,CAAC,MAAM,CAAC,cAAc,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC,CAAC;YACvD,CAAC;YACD,MAAM,cAAc,CAAC;QACvB,CAAC;QACD,MAAM,YAAY,CAAC;IACrB,CAAC;IACD,IAAI,aAAa,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC/B,MAAM,aAAa,CAAC,CAAC,CAAC,CAAC;IACzB,CAAC;IACD,IAAI,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC7B,MAAM,IAAI,cAAc,CAAC,aAAa,EAAE,oDAAoD,CAAC,CAAC;IAChG,CAAC;AACH,CAAC","sourcesContent":["import { execFile } from \"node:child_process\";\nimport { randomUUID } from \"node:crypto\";\nimport fs, { type FileHandle } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { promisify } from \"node:util\";\n\nconst execFileAsync = promisify(execFile);\n\nconst WINDOWS_OWNER_ONLY_ACL_SCRIPT = String.raw`\n$ErrorActionPreference = \"Stop\"\n$filePath = $env:CRABLINE_PRIVATE_FILE_PATH\nif ([string]::IsNullOrWhiteSpace($filePath)) {\n throw \"CRABLINE_PRIVATE_FILE_PATH is required.\"\n}\n\n$identity = [System.Security.Principal.WindowsIdentity]::GetCurrent()\n$sid = $identity.User\nif ($null -eq $sid) {\n throw \"Could not resolve the current Windows user SID.\"\n}\n\n$acl = Get-Acl -LiteralPath $filePath\n$acl.SetOwner($sid)\n$acl.SetAccessRuleProtection($true, $false)\n$existingRules = @($acl.GetAccessRules(\n $true,\n $false,\n [System.Security.Principal.SecurityIdentifier]\n))\nforeach ($existingRule in $existingRules) {\n [void]$acl.RemoveAccessRuleSpecific($existingRule)\n}\n$rule = [System.Security.AccessControl.FileSystemAccessRule]::new(\n $sid,\n [System.Security.AccessControl.FileSystemRights]::FullControl,\n [System.Security.AccessControl.AccessControlType]::Allow\n)\n$acl.SetAccessRule($rule)\nSet-Acl -LiteralPath $filePath -AclObject $acl\n\n$actual = Get-Acl -LiteralPath $filePath\n$ownerSid = $actual.GetOwner([System.Security.Principal.SecurityIdentifier])\n$rules = @($actual.GetAccessRules(\n $true,\n $true,\n [System.Security.Principal.SecurityIdentifier]\n))\nif (-not $actual.AreAccessRulesProtected) {\n throw \"Private file DACL still inherits permissions.\"\n}\nif ($ownerSid.Value -ne $sid.Value) {\n throw \"Private file owner SID does not match the current user.\"\n}\nif ($rules.Count -ne 1) {\n throw \"Private file DACL must contain exactly one access rule.\"\n}\n$actualRule = $rules[0]\nif (\n $actualRule.IsInherited -or\n $actualRule.IdentityReference.Value -ne $sid.Value -or\n $actualRule.AccessControlType -ne [System.Security.AccessControl.AccessControlType]::Allow -or\n (($actualRule.FileSystemRights -band [System.Security.AccessControl.FileSystemRights]::FullControl) -ne [System.Security.AccessControl.FileSystemRights]::FullControl)\n) {\n throw \"Private file DACL is not owner-only full control.\"\n}\n`;\n\nconst WINDOWS_OWNER_ONLY_DIRECTORY_ACL_SCRIPT = String.raw`\n$ErrorActionPreference = \"Stop\"\n$directoryPath = $env:CRABLINE_PRIVATE_DIRECTORY_PATH\nif ([string]::IsNullOrWhiteSpace($directoryPath)) {\n throw \"CRABLINE_PRIVATE_DIRECTORY_PATH is required.\"\n}\n\n$identity = [System.Security.Principal.WindowsIdentity]::GetCurrent()\n$sid = $identity.User\nif ($null -eq $sid) {\n throw \"Could not resolve the current Windows user SID.\"\n}\n\n$acl = Get-Acl -LiteralPath $directoryPath\n$acl.SetOwner($sid)\n$acl.SetAccessRuleProtection($true, $false)\n$existingRules = @($acl.GetAccessRules(\n $true,\n $false,\n [System.Security.Principal.SecurityIdentifier]\n))\nforeach ($existingRule in $existingRules) {\n [void]$acl.RemoveAccessRuleSpecific($existingRule)\n}\n$inheritance = (\n [System.Security.AccessControl.InheritanceFlags]::ContainerInherit -bor\n [System.Security.AccessControl.InheritanceFlags]::ObjectInherit\n)\n$rule = [System.Security.AccessControl.FileSystemAccessRule]::new(\n $sid,\n [System.Security.AccessControl.FileSystemRights]::FullControl,\n $inheritance,\n [System.Security.AccessControl.PropagationFlags]::None,\n [System.Security.AccessControl.AccessControlType]::Allow\n)\n$acl.SetAccessRule($rule)\nSet-Acl -LiteralPath $directoryPath -AclObject $acl\n\n$actual = Get-Acl -LiteralPath $directoryPath\n$ownerSid = $actual.GetOwner([System.Security.Principal.SecurityIdentifier])\n$rules = @($actual.GetAccessRules(\n $true,\n $true,\n [System.Security.Principal.SecurityIdentifier]\n))\nif (-not $actual.AreAccessRulesProtected) {\n throw \"Private directory DACL still inherits permissions.\"\n}\nif ($ownerSid.Value -ne $sid.Value) {\n throw \"Private directory owner SID does not match the current user.\"\n}\nif ($rules.Count -ne 1) {\n throw \"Private directory DACL must contain exactly one access rule.\"\n}\n$actualRule = $rules[0]\n$requiredInheritance = (\n [System.Security.AccessControl.InheritanceFlags]::ContainerInherit -bor\n [System.Security.AccessControl.InheritanceFlags]::ObjectInherit\n)\nif (\n $actualRule.IsInherited -or\n $actualRule.IdentityReference.Value -ne $sid.Value -or\n $actualRule.AccessControlType -ne [System.Security.AccessControl.AccessControlType]::Allow -or\n (($actualRule.FileSystemRights -band [System.Security.AccessControl.FileSystemRights]::FullControl) -ne [System.Security.AccessControl.FileSystemRights]::FullControl) -or\n (($actualRule.InheritanceFlags -band $requiredInheritance) -ne $requiredInheritance)\n) {\n throw \"Private directory DACL is not owner-only inheritable full control.\"\n}\n`;\n\nexport type WindowsAclRunner = (\n command: string,\n args: string[],\n options: {\n env: NodeJS.ProcessEnv;\n windowsHide: boolean;\n },\n) => Promise<void>;\n\nconst runWindowsAclCommand: WindowsAclRunner = async (command, args, options) => {\n await execFileAsync(command, args, options);\n};\n\nexport function resolveWindowsPowerShellPath(systemRoot: string | null | undefined): string {\n const normalizedRoot = systemRoot?.trim() ? path.win32.normalize(systemRoot.trim()) : undefined;\n if (!normalizedRoot || !/^[A-Za-z]:\\\\/.test(normalizedRoot)) {\n throw new Error(\"SystemRoot must be an absolute local Windows path.\");\n }\n return path.win32.join(normalizedRoot, \"System32\", \"WindowsPowerShell\", \"v1.0\", \"powershell.exe\");\n}\n\nexport async function applyOwnerOnlyWindowsAcl(\n filePath: string,\n run: WindowsAclRunner = runWindowsAclCommand,\n systemRoot: string | null | undefined = process.env.SystemRoot,\n): Promise<void> {\n try {\n const powershellPath = resolveWindowsPowerShellPath(systemRoot);\n await run(\n powershellPath,\n [\"-NoLogo\", \"-NoProfile\", \"-NonInteractive\", \"-Command\", WINDOWS_OWNER_ONLY_ACL_SCRIPT],\n {\n env: {\n ...process.env,\n CRABLINE_PRIVATE_FILE_PATH: path.resolve(filePath),\n },\n windowsHide: true,\n },\n );\n } catch (error) {\n throw new Error(\n \"Could not apply and verify an owner-only Windows ACL; powershell.exe with Set-Acl is required.\",\n { cause: error },\n );\n }\n}\n\nexport async function applyOwnerOnlyWindowsDirectoryAcl(\n directoryPath: string,\n run: WindowsAclRunner = runWindowsAclCommand,\n systemRoot: string | null | undefined = process.env.SystemRoot,\n): Promise<void> {\n try {\n const powershellPath = resolveWindowsPowerShellPath(systemRoot);\n await run(\n powershellPath,\n [\n \"-NoLogo\",\n \"-NoProfile\",\n \"-NonInteractive\",\n \"-Command\",\n WINDOWS_OWNER_ONLY_DIRECTORY_ACL_SCRIPT,\n ],\n {\n env: {\n ...process.env,\n CRABLINE_PRIVATE_DIRECTORY_PATH: path.resolve(directoryPath),\n },\n windowsHide: true,\n },\n );\n } catch (error) {\n throw new Error(\n \"Could not apply and verify an owner-only Windows directory ACL; powershell.exe with Set-Acl is required.\",\n { cause: error },\n );\n }\n}\n\ntype FileIdentity = {\n device: bigint;\n inode: bigint;\n};\n\nasync function readHandleIdentity(handle: FileHandle): Promise<FileIdentity> {\n const stats = await handle.stat({ bigint: true });\n if (stats.ino <= 0n) {\n throw new Error(\"The filesystem did not provide a stable private file identity.\");\n }\n return {\n device: stats.dev,\n inode: stats.ino,\n };\n}\n\nasync function assertPathIdentity(filePath: string, expected: FileIdentity): Promise<void> {\n try {\n const stats = await fs.lstat(filePath, { bigint: true });\n if (\n stats.isFile() &&\n stats.nlink === 1n &&\n stats.dev === expected.device &&\n stats.ino === expected.inode\n ) {\n return;\n }\n } catch (error) {\n throw new Error(\"Private file path identity changed during publication.\", { cause: error });\n }\n throw new Error(\"Private file path identity changed during publication.\");\n}\n\ntype DirectoryIdentity = {\n device: bigint;\n inode: bigint;\n};\n\nasync function readDirectoryHandleIdentity(handle: FileHandle): Promise<DirectoryIdentity> {\n const stats = await handle.stat({ bigint: true });\n if (!stats.isDirectory() || stats.ino <= 0n) {\n throw new Error(\"The filesystem did not provide a stable private directory identity.\");\n }\n return {\n device: stats.dev,\n inode: stats.ino,\n };\n}\n\nasync function assertDirectoryPathIdentity(\n directoryPath: string,\n expected: DirectoryIdentity,\n): Promise<void> {\n try {\n const stats = await fs.lstat(directoryPath, { bigint: true });\n if (stats.isDirectory() && stats.dev === expected.device && stats.ino === expected.inode) {\n return;\n }\n } catch (error) {\n throw new Error(\"Private directory path identity changed during publication.\", {\n cause: error,\n });\n }\n throw new Error(\"Private directory path identity changed during publication.\");\n}\n\nexport type SecuredPrivateDirectory = {\n assertIdentityAt(directoryPath?: string): Promise<void>;\n directoryPath: string;\n};\n\nexport async function captureDirectoryIdentity(\n directoryPath: string,\n): Promise<SecuredPrivateDirectory> {\n const handle = await fs.open(directoryPath, \"r\");\n try {\n const identity = await readDirectoryHandleIdentity(handle);\n const secured: SecuredPrivateDirectory = {\n async assertIdentityAt(currentPath = directoryPath) {\n await assertDirectoryPathIdentity(currentPath, identity);\n },\n directoryPath,\n };\n await secured.assertIdentityAt();\n return secured;\n } finally {\n await handle.close();\n }\n}\n\nexport async function syncParentDirectory(\n filePath: string,\n platform: NodeJS.Platform = process.platform,\n): Promise<void> {\n if (platform === \"win32\") {\n return;\n }\n const handle = await fs.open(path.dirname(filePath), \"r\");\n try {\n await handle.sync();\n } finally {\n await handle.close();\n }\n}\n\nexport async function removeSecuredPrivateDirectory(\n secured: SecuredPrivateDirectory,\n currentPath = secured.directoryPath,\n): Promise<void> {\n const quarantinePath = path.join(\n path.dirname(currentPath),\n `.${path.basename(currentPath)}.${process.pid}.${randomUUID()}.remove`,\n );\n await secured.assertIdentityAt(currentPath);\n await fs.rename(currentPath, quarantinePath);\n await secured.assertIdentityAt(quarantinePath);\n await syncParentDirectory(quarantinePath);\n await fs.rm(quarantinePath, { force: true, recursive: true });\n await syncParentDirectory(quarantinePath);\n}\n\nexport async function securePrivateDirectory(\n directoryPath: string,\n options: {\n platform?: NodeJS.Platform;\n secureWindowsDirectory?: (directoryPath: string) => Promise<void>;\n } = {},\n): Promise<SecuredPrivateDirectory> {\n let created = false;\n try {\n await fs.mkdir(directoryPath, { mode: 0o700 });\n created = true;\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== \"EEXIST\") {\n throw error;\n }\n }\n\n const handle = await fs.open(directoryPath, \"r\");\n let handleOpen = true;\n const closeHandle = async () => {\n if (!handleOpen) {\n return;\n }\n handleOpen = false;\n await handle.close();\n };\n let identity: DirectoryIdentity;\n try {\n identity = await readDirectoryHandleIdentity(handle);\n } catch (error) {\n try {\n await closeHandle();\n } catch (closeError) {\n const aggregateError = new AggregateError(\n [error, closeError],\n \"Private directory identity verification failed and its handle could not be closed.\",\n );\n aggregateError.cause = error;\n throw aggregateError;\n }\n throw error;\n }\n const secured: SecuredPrivateDirectory = {\n async assertIdentityAt(currentPath = directoryPath) {\n await assertDirectoryPathIdentity(currentPath, identity);\n },\n directoryPath,\n };\n try {\n await secured.assertIdentityAt();\n if ((options.platform ?? process.platform) === \"win32\") {\n await (options.secureWindowsDirectory ?? applyOwnerOnlyWindowsDirectoryAcl)(directoryPath);\n } else {\n await handle.chmod(0o700);\n }\n await secured.assertIdentityAt();\n } catch (error) {\n let primaryError = error;\n try {\n await closeHandle();\n } catch (closeError) {\n const aggregateError = new AggregateError(\n [error, closeError],\n \"Private directory securing failed and its verification handle could not be closed.\",\n );\n aggregateError.cause = error;\n primaryError = aggregateError;\n }\n if (created) {\n try {\n await removeSecuredPrivateDirectory(secured);\n } catch (cleanupError) {\n const aggregateError = new AggregateError(\n [primaryError, cleanupError],\n `Private directory securing failed and rollback cleanup also failed: ${\n error instanceof Error ? error.message : String(error)\n }`,\n );\n aggregateError.cause = primaryError;\n throw aggregateError;\n }\n }\n throw primaryError;\n } finally {\n await closeHandle();\n }\n\n return secured;\n}\n\nexport async function publishPrivateFileAtomically(\n filePath: string,\n contents: string,\n options: {\n afterRename?: (filePath: string) => Promise<void>;\n beforeRename?: (temporaryPath: string) => Promise<void>;\n platform?: NodeJS.Platform;\n removeTemporaryFile?: (temporaryPath: string) => Promise<void>;\n secureWindowsFile?: (temporaryPath: string) => Promise<void>;\n syncParent?: (filePath: string, platform?: NodeJS.Platform) => Promise<void>;\n } = {},\n): Promise<void> {\n const temporaryPath = path.join(\n path.dirname(filePath),\n `.${path.basename(filePath)}.${process.pid}.${randomUUID()}.tmp`,\n );\n await fs.mkdir(path.dirname(filePath), { recursive: true });\n let handle: FileHandle | undefined;\n let publicationFailed = false;\n let primaryError: unknown;\n try {\n handle = await fs.open(temporaryPath, \"wx+\", 0o600);\n const identity = await readHandleIdentity(handle);\n if ((options.platform ?? process.platform) === \"win32\") {\n await (options.secureWindowsFile ?? applyOwnerOnlyWindowsAcl)(temporaryPath);\n } else {\n await handle.chmod(0o600);\n }\n\n await assertPathIdentity(temporaryPath, identity);\n await handle.writeFile(contents, \"utf8\");\n await handle.sync();\n await assertPathIdentity(temporaryPath, identity);\n await options.beforeRename?.(temporaryPath);\n await assertPathIdentity(temporaryPath, identity);\n await fs.rename(temporaryPath, filePath);\n await (options.syncParent ?? syncParentDirectory)(filePath, options.platform);\n await options.afterRename?.(filePath);\n await assertPathIdentity(filePath, identity);\n } catch (error) {\n publicationFailed = true;\n primaryError = error;\n }\n\n const cleanupErrors: unknown[] = [];\n try {\n await handle?.close();\n } catch (error) {\n cleanupErrors.push(error);\n }\n try {\n await (\n options.removeTemporaryFile ??\n ((candidatePath: string) => fs.rm(candidatePath, { force: true }))\n )(temporaryPath);\n } catch (error) {\n cleanupErrors.push(error);\n }\n\n if (publicationFailed) {\n if (cleanupErrors.length > 0) {\n const primaryMessage =\n primaryError instanceof Error ? primaryError.message : String(primaryError);\n const aggregateError = new AggregateError(\n [primaryError, ...cleanupErrors],\n `${primaryMessage} Private temporary file cleanup also failed.`,\n );\n aggregateError.cause = primaryError;\n const primaryCode =\n typeof primaryError === \"object\" && primaryError !== null\n ? (primaryError as NodeJS.ErrnoException).code\n : undefined;\n if (primaryCode) {\n Object.assign(aggregateError, { code: primaryCode });\n }\n throw aggregateError;\n }\n throw primaryError;\n }\n if (cleanupErrors.length === 1) {\n throw cleanupErrors[0];\n }\n if (cleanupErrors.length > 1) {\n throw new AggregateError(cleanupErrors, \"Private temporary file publication cleanup failed.\");\n }\n}\n"]}
@@ -2,19 +2,34 @@ import type { CrablineServerChannel, CrablineServerManifest } from "../servers/i
2
2
  import type { ServerEventObserver } from "../servers/recorder.js";
3
3
  export declare const DEFAULT_ACCOUNT_ID = "default";
4
4
  export declare const OPENCLAW_CRABLINE_CHANNEL_CAPABILITY_MATRIX_PATH = "crabline-fake-provider-capabilities.json";
5
+ export declare const OPENCLAW_CRABLINE_PROVIDER_READINESS_PATH = "crabline-fake-provider-smoke.json";
6
+ /** @deprecated Use OPENCLAW_CRABLINE_PROVIDER_READINESS_PATH. */
5
7
  export declare const OPENCLAW_CRABLINE_CHANNEL_SMOKE_PATH = "crabline-fake-provider-smoke.json";
6
8
  export declare const OPENCLAW_CRABLINE_MANIFEST_PATH = "crabline-fake-provider-server.json";
9
+ export declare const OPENCLAW_CRABLINE_ARTIFACT_STORE_DIRECTORY = ".crabline-smoke-artifacts";
10
+ export declare const OPENCLAW_CRABLINE_ARTIFACT_POINTER_PATH = ".crabline-smoke-artifacts/current.json";
7
11
  export declare const OPENCLAW_CRABLINE_DEFAULT_CHANNEL = "telegram";
8
12
  export type OpenClawCrablineChannelDriverSelection = {
9
13
  channel: CrablineServerChannel;
10
14
  channelDriver: "crabline";
11
15
  capabilityMatrixPath: typeof OPENCLAW_CRABLINE_CHANNEL_CAPABILITY_MATRIX_PATH;
16
+ providerReadinessArtifactPath?: typeof OPENCLAW_CRABLINE_PROVIDER_READINESS_PATH;
12
17
  smokeArtifactPath: typeof OPENCLAW_CRABLINE_CHANNEL_SMOKE_PATH;
13
18
  };
19
+ /** @deprecated Use OpenClawCrablineProviderReadinessResult. */
14
20
  export type OpenClawCrablineChannelDriverSmokeResult = {
21
+ artifactPointerPath: string;
15
22
  capabilityReport: unknown;
23
+ capabilityMatrixPath: string;
24
+ generation: string;
16
25
  manifestPath: string;
17
26
  smoke: unknown;
27
+ smokeArtifactPath: string;
28
+ warnings?: string[];
29
+ };
30
+ export type OpenClawCrablineProviderReadinessResult = OpenClawCrablineChannelDriverSmokeResult & {
31
+ providerReadiness: unknown;
32
+ providerReadinessArtifactPath: string;
18
33
  };
19
34
  export type OpenClawCrablineConversation = {
20
35
  id: string;
@@ -36,7 +51,7 @@ export type OpenClawCrablineAgentDelivery = {
36
51
  export type OpenClawCrablineInboundInput = {
37
52
  conversation: {
38
53
  id: string;
39
- kind: string;
54
+ kind: "direct" | "group";
40
55
  };
41
56
  senderId: string;
42
57
  senderName?: string | undefined;
@@ -86,6 +101,7 @@ export type StartedOpenClawCrablineAdapter = OpenClawCrablineGatewayBinding & {
86
101
  export type ParsedQaTarget = {
87
102
  kind: "direct" | "group";
88
103
  id: string;
104
+ native: boolean;
89
105
  threadId?: string;
90
106
  };
91
107
  export type OpenClawCrablineProviderAdapter = {
@@ -96,7 +112,7 @@ export type OpenClawCrablineProviderAdapter = {
96
112
  event: unknown;
97
113
  targetByProviderTarget: ReadonlyMap<string, string>;
98
114
  }): OpenClawCrablineOutboundMessage | null;
99
- probe(): Promise<unknown>;
115
+ probe(signal?: AbortSignal): Promise<unknown>;
100
116
  };
101
117
  export type OpenClawCrablineProviderBridge<TManifest extends CrablineServerManifest = CrablineServerManifest> = {
102
118
  createAdapter(manifest: TManifest): OpenClawCrablineProviderAdapter;
@@ -116,10 +132,13 @@ export declare function createOpenClawCrablineProviderBridge<TProvider extends C
116
132
  }): OpenClawCrablineProviderBridge<Extract<CrablineServerManifest, {
117
133
  provider: TProvider;
118
134
  }>>;
135
+ export declare function runOpenClawCrablineProviderProbe<T>(provider: CrablineServerManifest["provider"], probe: (signal: AbortSignal) => Promise<T>): Promise<T>;
119
136
  export declare function readString(value: unknown): string | undefined;
137
+ export declare function readNonBlankString(value: unknown): string | undefined;
120
138
  export declare function isRecord(value: unknown): value is Record<string, unknown>;
121
139
  export declare function readInteger(value: unknown): number | undefined;
122
140
  export declare function parseQaTarget(target: string): ParsedQaTarget;
141
+ export declare function canonicalConversationIdForInbound(input: OpenClawCrablineInboundInput): string;
123
142
  export declare function qaTargetForInbound(input: OpenClawCrablineInboundInput): string;
124
143
  export declare function createAdminInboundRequest(manifest: CrablineServerManifest): {
125
144
  providerHeaders: {
@@ -1,22 +1,80 @@
1
1
  import { ADMIN_TOKEN_HEADER } from "../servers/http.js";
2
2
  export const DEFAULT_ACCOUNT_ID = "default";
3
3
  export const OPENCLAW_CRABLINE_CHANNEL_CAPABILITY_MATRIX_PATH = "crabline-fake-provider-capabilities.json";
4
- export const OPENCLAW_CRABLINE_CHANNEL_SMOKE_PATH = "crabline-fake-provider-smoke.json";
4
+ export const OPENCLAW_CRABLINE_PROVIDER_READINESS_PATH = "crabline-fake-provider-smoke.json";
5
+ /** @deprecated Use OPENCLAW_CRABLINE_PROVIDER_READINESS_PATH. */
6
+ export const OPENCLAW_CRABLINE_CHANNEL_SMOKE_PATH = OPENCLAW_CRABLINE_PROVIDER_READINESS_PATH;
5
7
  export const OPENCLAW_CRABLINE_MANIFEST_PATH = "crabline-fake-provider-server.json";
8
+ export const OPENCLAW_CRABLINE_ARTIFACT_STORE_DIRECTORY = ".crabline-smoke-artifacts";
9
+ export const OPENCLAW_CRABLINE_ARTIFACT_POINTER_PATH = `${OPENCLAW_CRABLINE_ARTIFACT_STORE_DIRECTORY}/current.json`;
6
10
  export const OPENCLAW_CRABLINE_DEFAULT_CHANNEL = "telegram";
11
+ const OPENCLAW_CRABLINE_PROVIDER_PROBE_TIMEOUT_MS = 5_000;
12
+ const OPENCLAW_CRABLINE_PROVIDER_PROBE_LABELS = {
13
+ mattermost: "Mattermost users.me",
14
+ matrix: "Matrix whoami",
15
+ signal: "Signal check",
16
+ slack: "Slack auth.test",
17
+ telegram: "Telegram getMe",
18
+ whatsapp: "WhatsApp phone number",
19
+ zalo: "Zalo getMe",
20
+ };
7
21
  export function createOpenClawCrablineProviderBridge(params) {
22
+ const createAdapter = (manifest) => {
23
+ const adapter = params.createAdapter(manifest);
24
+ return {
25
+ ...adapter,
26
+ createInbound(input) {
27
+ if (!readNonBlankString(input.text)) {
28
+ throw new Error("OpenClaw Crabline inbound message text is required.");
29
+ }
30
+ if (input.conversation.kind !== "direct" && input.conversation.kind !== "group") {
31
+ throw new Error("OpenClaw Crabline inbound conversation kind must be direct or group.");
32
+ }
33
+ return adapter.createInbound(input);
34
+ },
35
+ };
36
+ };
8
37
  const bridge = {
9
- createAdapter: params.createAdapter,
38
+ createAdapter,
10
39
  createAdapterFromManifest(manifest) {
11
40
  if (manifest.provider !== params.provider) {
12
41
  throw new Error(`Unsupported OpenClaw provider binding: expected ${params.provider}, got ${manifest.provider}.`);
13
42
  }
14
- return params.createAdapter(manifest);
43
+ return createAdapter(manifest);
15
44
  },
16
45
  provider: params.provider,
17
46
  };
18
47
  return bridge;
19
48
  }
49
+ export async function runOpenClawCrablineProviderProbe(provider, probe) {
50
+ const signal = AbortSignal.timeout(OPENCLAW_CRABLINE_PROVIDER_PROBE_TIMEOUT_MS);
51
+ const timeoutError = (cause) => new Error(`Crabline ${OPENCLAW_CRABLINE_PROVIDER_PROBE_LABELS[provider]} probe timed out after ${OPENCLAW_CRABLINE_PROVIDER_PROBE_TIMEOUT_MS} ms.`, { cause });
52
+ let onAbort;
53
+ const timeout = new Promise((_, reject) => {
54
+ onAbort = () => reject(timeoutError(signal.reason));
55
+ if (signal.aborted) {
56
+ onAbort();
57
+ return;
58
+ }
59
+ signal.addEventListener("abort", onAbort, { once: true });
60
+ });
61
+ const probeResult = Promise.resolve()
62
+ .then(() => probe(signal))
63
+ .catch((error) => {
64
+ if (signal.aborted) {
65
+ throw timeoutError(error);
66
+ }
67
+ throw error;
68
+ });
69
+ try {
70
+ return await Promise.race([probeResult, timeout]);
71
+ }
72
+ finally {
73
+ if (onAbort) {
74
+ signal.removeEventListener("abort", onAbort);
75
+ }
76
+ }
77
+ }
20
78
  export function readString(value) {
21
79
  if (typeof value === "string" && value.trim()) {
22
80
  return value.trim();
@@ -26,6 +84,9 @@ export function readString(value) {
26
84
  }
27
85
  return undefined;
28
86
  }
87
+ export function readNonBlankString(value) {
88
+ return typeof value === "string" && value.trim() ? value : undefined;
89
+ }
29
90
  export function isRecord(value) {
30
91
  return typeof value === "object" && value !== null && !Array.isArray(value);
31
92
  }
@@ -38,33 +99,69 @@ export function readInteger(value) {
38
99
  }
39
100
  export function parseQaTarget(target) {
40
101
  const trimmed = target.trim();
102
+ const invalidTarget = () => {
103
+ throw new Error("OpenClaw Crabline target must be a non-blank native id or a valid dm:<id>, group:<id>, channel:<id>, or thread:<id>/<thread-id> target.");
104
+ };
105
+ if (!trimmed) {
106
+ return invalidTarget();
107
+ }
41
108
  if (trimmed.startsWith("thread:")) {
42
- const rest = trimmed.slice("thread:".length);
109
+ const encoded = trimmed.startsWith("thread:/v1/");
110
+ const rest = trimmed.slice(encoded ? "thread:/v1/".length : "thread:".length);
43
111
  const slash = rest.indexOf("/");
44
- if (slash > 0) {
45
- return { kind: "group", id: rest.slice(0, slash), threadId: rest.slice(slash + 1) };
112
+ if (slash <= 0 || slash !== rest.lastIndexOf("/")) {
113
+ return invalidTarget();
114
+ }
115
+ let id = rest.slice(0, slash).trim();
116
+ let threadId = rest.slice(slash + 1).trim();
117
+ if (encoded) {
118
+ try {
119
+ id = decodeURIComponent(id).trim();
120
+ threadId = decodeURIComponent(threadId).trim();
121
+ }
122
+ catch {
123
+ return invalidTarget();
124
+ }
125
+ }
126
+ if (!id || !threadId) {
127
+ return invalidTarget();
46
128
  }
129
+ return { kind: "group", id, native: false, threadId };
47
130
  }
48
131
  if (trimmed.startsWith("channel:")) {
49
- return { kind: "group", id: trimmed.slice("channel:".length) };
132
+ const id = trimmed.slice("channel:".length).trim();
133
+ return id ? { kind: "group", id, native: false } : invalidTarget();
50
134
  }
51
135
  if (trimmed.startsWith("group:")) {
52
- return { kind: "group", id: trimmed.slice("group:".length) };
136
+ const id = trimmed.slice("group:".length).trim();
137
+ return id ? { kind: "group", id, native: false } : invalidTarget();
53
138
  }
54
139
  if (trimmed.startsWith("dm:")) {
55
- return { kind: "direct", id: trimmed.slice("dm:".length) };
140
+ const id = trimmed.slice("dm:".length).trim();
141
+ return id ? { kind: "direct", id, native: false } : invalidTarget();
56
142
  }
57
- return { kind: "direct", id: trimmed };
143
+ if (/^(?:dm|group|channel|thread)(?=\s*:|$)/iu.test(trimmed)) {
144
+ return invalidTarget();
145
+ }
146
+ return { kind: "direct", id: trimmed, native: true };
147
+ }
148
+ export function canonicalConversationIdForInbound(input) {
149
+ const conversationId = readNonBlankString(input.conversation.id);
150
+ if (!conversationId) {
151
+ throw new Error("OpenClaw Crabline inbound conversation id is required.");
152
+ }
153
+ return conversationId.trim();
154
+ }
155
+ function encodeQaThreadComponent(value) {
156
+ return value.replaceAll("%", "%25").replaceAll("/", "%2F");
58
157
  }
59
158
  export function qaTargetForInbound(input) {
60
- const prefix = input.conversation.kind === "direct"
61
- ? "dm"
62
- : input.conversation.kind === "channel"
63
- ? "channel"
64
- : "group";
65
- return input.threadId
66
- ? `thread:${input.conversation.id}/${input.threadId}`
67
- : `${prefix}:${input.conversation.id}`;
159
+ const conversationId = canonicalConversationIdForInbound(input);
160
+ const threadId = input.threadId?.trim();
161
+ const prefix = input.conversation.kind === "direct" ? "dm" : "group";
162
+ return threadId
163
+ ? `thread:/v1/${encodeQaThreadComponent(conversationId)}/${encodeQaThreadComponent(threadId)}`
164
+ : `${prefix}:${conversationId}`;
68
165
  }
69
166
  export function createAdminInboundRequest(manifest) {
70
167
  return {
@@ -1 +1 @@
1
- {"version":3,"file":"shared.js","sourceRoot":"","sources":["../../../src/openclaw/shared.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"shared.js","sourceRoot":"","sources":["../../../src/openclaw/shared.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAIxD,MAAM,CAAC,MAAM,kBAAkB,GAAG,SAAS,CAAC;AAC5C,MAAM,CAAC,MAAM,gDAAgD,GAC3D,0CAA0C,CAAC;AAC7C,MAAM,CAAC,MAAM,yCAAyC,GAAG,mCAAmC,CAAC;AAC7F,iEAAiE;AACjE,MAAM,CAAC,MAAM,oCAAoC,GAAG,yCAAyC,CAAC;AAC9F,MAAM,CAAC,MAAM,+BAA+B,GAAG,oCAAoC,CAAC;AACpF,MAAM,CAAC,MAAM,0CAA0C,GAAG,2BAA2B,CAAC;AACtF,MAAM,CAAC,MAAM,uCAAuC,GAAG,GAAG,0CAA0C,eAAe,CAAC;AACpH,MAAM,CAAC,MAAM,iCAAiC,GAAG,UAAU,CAAC;AAE5D,MAAM,2CAA2C,GAAG,KAAK,CAAC;AAC1D,MAAM,uCAAuC,GAAG;IAC9C,UAAU,EAAE,qBAAqB;IACjC,MAAM,EAAE,eAAe;IACvB,MAAM,EAAE,cAAc;IACtB,KAAK,EAAE,iBAAiB;IACxB,QAAQ,EAAE,gBAAgB;IAC1B,QAAQ,EAAE,uBAAuB;IACjC,IAAI,EAAE,YAAY;CAC0C,CAAC;AA+H/D,MAAM,UAAU,oCAAoC,CAElD,MAKD;IAEC,MAAM,aAAa,GAAG,CAAC,QAA0B,EAAmC,EAAE;QACpF,MAAM,OAAO,GAAG,MAAM,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;QAC/C,OAAO;YACL,GAAG,OAAO;YACV,aAAa,CAAC,KAAK;gBACjB,IAAI,CAAC,kBAAkB,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;oBACpC,MAAM,IAAI,KAAK,CAAC,qDAAqD,CAAC,CAAC;gBACzE,CAAC;gBACD,IAAI,KAAK,CAAC,YAAY,CAAC,IAAI,KAAK,QAAQ,IAAI,KAAK,CAAC,YAAY,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;oBAChF,MAAM,IAAI,KAAK,CAAC,sEAAsE,CAAC,CAAC;gBAC1F,CAAC;gBACD,OAAO,OAAO,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;YACtC,CAAC;SACF,CAAC;IACJ,CAAC,CAAC;IACF,MAAM,MAAM,GAAqD;QAC/D,aAAa;QACb,yBAAyB,CAAC,QAAQ;YAChC,IAAI,QAAQ,CAAC,QAAQ,KAAK,MAAM,CAAC,QAAQ,EAAE,CAAC;gBAC1C,MAAM,IAAI,KAAK,CACb,mDAAmD,MAAM,CAAC,QAAQ,SAAS,QAAQ,CAAC,QAAQ,GAAG,CAChG,CAAC;YACJ,CAAC;YACD,OAAO,aAAa,CAAC,QAA4B,CAAC,CAAC;QACrD,CAAC;QACD,QAAQ,EAAE,MAAM,CAAC,QAAwC;KAC1D,CAAC;IACF,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,gCAAgC,CACpD,QAA4C,EAC5C,KAA0C;IAE1C,MAAM,MAAM,GAAG,WAAW,CAAC,OAAO,CAAC,2CAA2C,CAAC,CAAC;IAChF,MAAM,YAAY,GAAG,CAAC,KAAc,EAAE,EAAE,CACtC,IAAI,KAAK,CACP,YAAY,uCAAuC,CAAC,QAAQ,CAAC,0BAA0B,2CAA2C,MAAM,EACxI,EAAE,KAAK,EAAE,CACV,CAAC;IACJ,IAAI,OAAiC,CAAC;IACtC,MAAM,OAAO,GAAG,IAAI,OAAO,CAAQ,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE;QAC/C,OAAO,GAAG,GAAG,EAAE,CAAC,MAAM,CAAC,YAAY,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;QACpD,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;YACnB,OAAO,EAAE,CAAC;YACV,OAAO;QACT,CAAC;QACD,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;IAC5D,CAAC,CAAC,CAAC;IACH,MAAM,WAAW,GAAG,OAAO,CAAC,OAAO,EAAE;SAClC,IAAI,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;SACzB,KAAK,CAAC,CAAC,KAAc,EAAE,EAAE;QACxB,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;YACnB,MAAM,YAAY,CAAC,KAAK,CAAC,CAAC;QAC5B,CAAC;QACD,MAAM,KAAK,CAAC;IACd,CAAC,CAAC,CAAC;IACL,IAAI,CAAC;QACH,OAAO,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC,CAAC;IACpD,CAAC;YAAS,CAAC;QACT,IAAI,OAAO,EAAE,CAAC;YACZ,MAAM,CAAC,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAC/C,CAAC;IACH,CAAC;AACH,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,KAAc;IACvC,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,IAAI,EAAE,EAAE,CAAC;QAC9C,OAAO,KAAK,CAAC,IAAI,EAAE,CAAC;IACtB,CAAC;IACD,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC3D,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;IACvB,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,KAAc;IAC/C,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;AACvE,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,KAAc;IACrC,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;AAC9E,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,KAAc;IACxC,MAAM,WAAW,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC;IACtC,IAAI,CAAC,WAAW,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC;QAClD,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,OAAO,MAAM,CAAC,WAAW,CAAC,CAAC;AAC7B,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,MAAc;IAC1C,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC;IAC9B,MAAM,aAAa,GAAG,GAAG,EAAE;QACzB,MAAM,IAAI,KAAK,CACb,yIAAyI,CAC1I,CAAC;IACJ,CAAC,CAAC;IACF,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,aAAa,EAAE,CAAC;IACzB,CAAC;IACD,IAAI,OAAO,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;QAClC,MAAM,OAAO,GAAG,OAAO,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;QAClD,MAAM,IAAI,GAAG,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;QAC9E,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QAChC,IAAI,KAAK,IAAI,CAAC,IAAI,KAAK,KAAK,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC;YAClD,OAAO,aAAa,EAAE,CAAC;QACzB,CAAC;QACD,IAAI,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC;QACrC,IAAI,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QAC5C,IAAI,OAAO,EAAE,CAAC;YACZ,IAAI,CAAC;gBACH,EAAE,GAAG,kBAAkB,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;gBACnC,QAAQ,GAAG,kBAAkB,CAAC,QAAQ,CAAC,CAAC,IAAI,EAAE,CAAC;YACjD,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,aAAa,EAAE,CAAC;YACzB,CAAC;QACH,CAAC;QACD,IAAI,CAAC,EAAE,IAAI,CAAC,QAAQ,EAAE,CAAC;YACrB,OAAO,aAAa,EAAE,CAAC;QACzB,CAAC;QACD,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC;IACxD,CAAC;IACD,IAAI,OAAO,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QACnC,MAAM,EAAE,GAAG,OAAO,CAAC,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC;QACnD,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,aAAa,EAAE,CAAC;IACrE,CAAC;IACD,IAAI,OAAO,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QACjC,MAAM,EAAE,GAAG,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC;QACjD,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,aAAa,EAAE,CAAC;IACrE,CAAC;IACD,IAAI,OAAO,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;QAC9B,MAAM,EAAE,GAAG,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC;QAC9C,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,aAAa,EAAE,CAAC;IACtE,CAAC;IACD,IAAI,0CAA0C,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;QAC7D,OAAO,aAAa,EAAE,CAAC;IACzB,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;AACvD,CAAC;AAED,MAAM,UAAU,iCAAiC,CAAC,KAAmC;IACnF,MAAM,cAAc,GAAG,kBAAkB,CAAC,KAAK,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC;IACjE,IAAI,CAAC,cAAc,EAAE,CAAC;QACpB,MAAM,IAAI,KAAK,CAAC,wDAAwD,CAAC,CAAC;IAC5E,CAAC;IACD,OAAO,cAAc,CAAC,IAAI,EAAE,CAAC;AAC/B,CAAC;AAED,SAAS,uBAAuB,CAAC,KAAa;IAC5C,OAAO,KAAK,CAAC,UAAU,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC,UAAU,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;AAC7D,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,KAAmC;IACpE,MAAM,cAAc,GAAG,iCAAiC,CAAC,KAAK,CAAC,CAAC;IAChE,MAAM,QAAQ,GAAG,KAAK,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC;IACxC,MAAM,MAAM,GAAG,KAAK,CAAC,YAAY,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC;IACrE,OAAO,QAAQ;QACb,CAAC,CAAC,cAAc,uBAAuB,CAAC,cAAc,CAAC,IAAI,uBAAuB,CAAC,QAAQ,CAAC,EAAE;QAC9F,CAAC,CAAC,GAAG,MAAM,IAAI,cAAc,EAAE,CAAC;AACpC,CAAC;AAED,MAAM,UAAU,yBAAyB,CAAC,QAAgC;IACxE,OAAO;QACL,eAAe,EAAE;YACf,cAAc,EAAE,kBAAkB;YAClC,CAAC,kBAAkB,CAAC,EAAE,QAAQ,CAAC,UAAU;SAC1C;QACD,WAAW,EAAE,QAAQ,CAAC,SAAS,CAAC,eAAe;KAChD,CAAC;AACJ,CAAC","sourcesContent":["import { ADMIN_TOKEN_HEADER } from \"../servers/http.js\";\nimport type { CrablineServerChannel, CrablineServerManifest } from \"../servers/index.js\";\nimport type { ServerEventObserver } from \"../servers/recorder.js\";\n\nexport const DEFAULT_ACCOUNT_ID = \"default\";\nexport const OPENCLAW_CRABLINE_CHANNEL_CAPABILITY_MATRIX_PATH =\n \"crabline-fake-provider-capabilities.json\";\nexport const OPENCLAW_CRABLINE_PROVIDER_READINESS_PATH = \"crabline-fake-provider-smoke.json\";\n/** @deprecated Use OPENCLAW_CRABLINE_PROVIDER_READINESS_PATH. */\nexport const OPENCLAW_CRABLINE_CHANNEL_SMOKE_PATH = OPENCLAW_CRABLINE_PROVIDER_READINESS_PATH;\nexport const OPENCLAW_CRABLINE_MANIFEST_PATH = \"crabline-fake-provider-server.json\";\nexport const OPENCLAW_CRABLINE_ARTIFACT_STORE_DIRECTORY = \".crabline-smoke-artifacts\";\nexport const OPENCLAW_CRABLINE_ARTIFACT_POINTER_PATH = `${OPENCLAW_CRABLINE_ARTIFACT_STORE_DIRECTORY}/current.json`;\nexport const OPENCLAW_CRABLINE_DEFAULT_CHANNEL = \"telegram\";\n\nconst OPENCLAW_CRABLINE_PROVIDER_PROBE_TIMEOUT_MS = 5_000;\nconst OPENCLAW_CRABLINE_PROVIDER_PROBE_LABELS = {\n mattermost: \"Mattermost users.me\",\n matrix: \"Matrix whoami\",\n signal: \"Signal check\",\n slack: \"Slack auth.test\",\n telegram: \"Telegram getMe\",\n whatsapp: \"WhatsApp phone number\",\n zalo: \"Zalo getMe\",\n} satisfies Record<CrablineServerManifest[\"provider\"], string>;\n\nexport type OpenClawCrablineChannelDriverSelection = {\n channel: CrablineServerChannel;\n channelDriver: \"crabline\";\n capabilityMatrixPath: typeof OPENCLAW_CRABLINE_CHANNEL_CAPABILITY_MATRIX_PATH;\n providerReadinessArtifactPath?: typeof OPENCLAW_CRABLINE_PROVIDER_READINESS_PATH;\n smokeArtifactPath: typeof OPENCLAW_CRABLINE_CHANNEL_SMOKE_PATH;\n};\n\n/** @deprecated Use OpenClawCrablineProviderReadinessResult. */\nexport type OpenClawCrablineChannelDriverSmokeResult = {\n artifactPointerPath: string;\n capabilityReport: unknown;\n capabilityMatrixPath: string;\n generation: string;\n manifestPath: string;\n smoke: unknown;\n smokeArtifactPath: string;\n warnings?: string[];\n};\n\nexport type OpenClawCrablineProviderReadinessResult = OpenClawCrablineChannelDriverSmokeResult & {\n providerReadiness: unknown;\n providerReadinessArtifactPath: string;\n};\nexport type OpenClawCrablineConversation = {\n id: string;\n kind: \"direct\" | \"group\";\n};\n\nexport type OpenClawCrablineGatewayBinding = {\n accountId: string;\n channel: string;\n createChannelDriverSmokeEnv(env: NodeJS.ProcessEnv): NodeJS.ProcessEnv;\n createGatewayConfig(openclawConfig?: Record<string, unknown>): Record<string, unknown>;\n requiredPluginIds: string[];\n};\n\nexport type OpenClawCrablineAgentDelivery = {\n channel: string;\n replyChannel: string;\n replyTo: string;\n to: string;\n};\n\nexport type OpenClawCrablineInboundInput = {\n conversation: {\n id: string;\n kind: \"direct\" | \"group\";\n };\n senderId: string;\n senderName?: string | undefined;\n text: string;\n threadId?: string | undefined;\n nativeCommand?: { name: string } | undefined;\n};\n\nexport type OpenClawCrablineInbound = {\n providerBody: Record<string, unknown>;\n providerHeaders: Record<string, string>;\n providerTargetKey: string;\n providerUrl: string;\n qaTarget: string;\n stateConversation: OpenClawCrablineConversation;\n threadId?: string | undefined;\n};\n\nexport type OpenClawCrablineOutboundMessage = {\n accountId: string;\n senderId: string;\n senderName: string;\n text: string;\n to: string;\n};\n\nexport type StartOpenClawCrablineAdapterParams = {\n channel: CrablineServerChannel;\n onEvent?: ServerEventObserver | undefined;\n openclawConfig?: Record<string, unknown> | undefined;\n recorderPath?: string | undefined;\n};\n\nexport type StartedOpenClawCrablineAdapter = OpenClawCrablineGatewayBinding & {\n close(): Promise<void>;\n createAgentDelivery(params: { target: string }): OpenClawCrablineAgentDelivery;\n createInbound(params: { input: OpenClawCrablineInboundInput }): OpenClawCrablineInbound;\n createOutboundFromRecorderEvent(params: {\n event: unknown;\n targetByProviderTarget: ReadonlyMap<string, string>;\n }): OpenClawCrablineOutboundMessage | null;\n manifest: CrablineServerManifest;\n probe(): Promise<unknown>;\n};\n\nexport type ParsedQaTarget = {\n kind: \"direct\" | \"group\";\n id: string;\n native: boolean;\n threadId?: string;\n};\n\nexport type OpenClawCrablineProviderAdapter = {\n createAgentDelivery(parsed: ParsedQaTarget): OpenClawCrablineAgentDelivery;\n createBinding(): OpenClawCrablineGatewayBinding;\n createInbound(input: OpenClawCrablineInboundInput): OpenClawCrablineInbound;\n createOutboundFromRecorderEvent(params: {\n event: unknown;\n targetByProviderTarget: ReadonlyMap<string, string>;\n }): OpenClawCrablineOutboundMessage | null;\n probe(signal?: AbortSignal): Promise<unknown>;\n};\n\nexport type OpenClawCrablineProviderBridge<\n TManifest extends CrablineServerManifest = CrablineServerManifest,\n> = {\n createAdapter(manifest: TManifest): OpenClawCrablineProviderAdapter;\n createAdapterFromManifest(manifest: CrablineServerManifest): OpenClawCrablineProviderAdapter;\n provider: TManifest[\"provider\"];\n};\n\nexport type OpenClawCrablineProviderBridgeRegistry = {\n [Provider in CrablineServerManifest[\"provider\"]]: OpenClawCrablineProviderBridge<\n Extract<CrablineServerManifest, { provider: Provider }>\n >;\n};\n\nexport function createOpenClawCrablineProviderBridge<\n TProvider extends CrablineServerManifest[\"provider\"],\n>(params: {\n createAdapter(\n manifest: Extract<CrablineServerManifest, { provider: TProvider }>,\n ): OpenClawCrablineProviderAdapter;\n provider: TProvider;\n}): OpenClawCrablineProviderBridge<Extract<CrablineServerManifest, { provider: TProvider }>> {\n type ProviderManifest = Extract<CrablineServerManifest, { provider: TProvider }>;\n const createAdapter = (manifest: ProviderManifest): OpenClawCrablineProviderAdapter => {\n const adapter = params.createAdapter(manifest);\n return {\n ...adapter,\n createInbound(input) {\n if (!readNonBlankString(input.text)) {\n throw new Error(\"OpenClaw Crabline inbound message text is required.\");\n }\n if (input.conversation.kind !== \"direct\" && input.conversation.kind !== \"group\") {\n throw new Error(\"OpenClaw Crabline inbound conversation kind must be direct or group.\");\n }\n return adapter.createInbound(input);\n },\n };\n };\n const bridge: OpenClawCrablineProviderBridge<ProviderManifest> = {\n createAdapter,\n createAdapterFromManifest(manifest) {\n if (manifest.provider !== params.provider) {\n throw new Error(\n `Unsupported OpenClaw provider binding: expected ${params.provider}, got ${manifest.provider}.`,\n );\n }\n return createAdapter(manifest as ProviderManifest);\n },\n provider: params.provider as ProviderManifest[\"provider\"],\n };\n return bridge;\n}\n\nexport async function runOpenClawCrablineProviderProbe<T>(\n provider: CrablineServerManifest[\"provider\"],\n probe: (signal: AbortSignal) => Promise<T>,\n): Promise<T> {\n const signal = AbortSignal.timeout(OPENCLAW_CRABLINE_PROVIDER_PROBE_TIMEOUT_MS);\n const timeoutError = (cause: unknown) =>\n new Error(\n `Crabline ${OPENCLAW_CRABLINE_PROVIDER_PROBE_LABELS[provider]} probe timed out after ${OPENCLAW_CRABLINE_PROVIDER_PROBE_TIMEOUT_MS} ms.`,\n { cause },\n );\n let onAbort: (() => void) | undefined;\n const timeout = new Promise<never>((_, reject) => {\n onAbort = () => reject(timeoutError(signal.reason));\n if (signal.aborted) {\n onAbort();\n return;\n }\n signal.addEventListener(\"abort\", onAbort, { once: true });\n });\n const probeResult = Promise.resolve()\n .then(() => probe(signal))\n .catch((error: unknown) => {\n if (signal.aborted) {\n throw timeoutError(error);\n }\n throw error;\n });\n try {\n return await Promise.race([probeResult, timeout]);\n } finally {\n if (onAbort) {\n signal.removeEventListener(\"abort\", onAbort);\n }\n }\n}\n\nexport function readString(value: unknown): string | undefined {\n if (typeof value === \"string\" && value.trim()) {\n return value.trim();\n }\n if (typeof value === \"number\" || typeof value === \"bigint\") {\n return String(value);\n }\n return undefined;\n}\n\nexport function readNonBlankString(value: unknown): string | undefined {\n return typeof value === \"string\" && value.trim() ? value : undefined;\n}\n\nexport function isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nexport function readInteger(value: unknown): number | undefined {\n const stringValue = readString(value);\n if (!stringValue || !/^-?\\d+$/u.test(stringValue)) {\n return undefined;\n }\n return Number(stringValue);\n}\n\nexport function parseQaTarget(target: string): ParsedQaTarget {\n const trimmed = target.trim();\n const invalidTarget = () => {\n throw new Error(\n \"OpenClaw Crabline target must be a non-blank native id or a valid dm:<id>, group:<id>, channel:<id>, or thread:<id>/<thread-id> target.\",\n );\n };\n if (!trimmed) {\n return invalidTarget();\n }\n if (trimmed.startsWith(\"thread:\")) {\n const encoded = trimmed.startsWith(\"thread:/v1/\");\n const rest = trimmed.slice(encoded ? \"thread:/v1/\".length : \"thread:\".length);\n const slash = rest.indexOf(\"/\");\n if (slash <= 0 || slash !== rest.lastIndexOf(\"/\")) {\n return invalidTarget();\n }\n let id = rest.slice(0, slash).trim();\n let threadId = rest.slice(slash + 1).trim();\n if (encoded) {\n try {\n id = decodeURIComponent(id).trim();\n threadId = decodeURIComponent(threadId).trim();\n } catch {\n return invalidTarget();\n }\n }\n if (!id || !threadId) {\n return invalidTarget();\n }\n return { kind: \"group\", id, native: false, threadId };\n }\n if (trimmed.startsWith(\"channel:\")) {\n const id = trimmed.slice(\"channel:\".length).trim();\n return id ? { kind: \"group\", id, native: false } : invalidTarget();\n }\n if (trimmed.startsWith(\"group:\")) {\n const id = trimmed.slice(\"group:\".length).trim();\n return id ? { kind: \"group\", id, native: false } : invalidTarget();\n }\n if (trimmed.startsWith(\"dm:\")) {\n const id = trimmed.slice(\"dm:\".length).trim();\n return id ? { kind: \"direct\", id, native: false } : invalidTarget();\n }\n if (/^(?:dm|group|channel|thread)(?=\\s*:|$)/iu.test(trimmed)) {\n return invalidTarget();\n }\n return { kind: \"direct\", id: trimmed, native: true };\n}\n\nexport function canonicalConversationIdForInbound(input: OpenClawCrablineInboundInput) {\n const conversationId = readNonBlankString(input.conversation.id);\n if (!conversationId) {\n throw new Error(\"OpenClaw Crabline inbound conversation id is required.\");\n }\n return conversationId.trim();\n}\n\nfunction encodeQaThreadComponent(value: string): string {\n return value.replaceAll(\"%\", \"%25\").replaceAll(\"/\", \"%2F\");\n}\n\nexport function qaTargetForInbound(input: OpenClawCrablineInboundInput) {\n const conversationId = canonicalConversationIdForInbound(input);\n const threadId = input.threadId?.trim();\n const prefix = input.conversation.kind === \"direct\" ? \"dm\" : \"group\";\n return threadId\n ? `thread:/v1/${encodeQaThreadComponent(conversationId)}/${encodeQaThreadComponent(threadId)}`\n : `${prefix}:${conversationId}`;\n}\n\nexport function createAdminInboundRequest(manifest: CrablineServerManifest) {\n return {\n providerHeaders: {\n \"content-type\": \"application/json\",\n [ADMIN_TOKEN_HEADER]: manifest.adminToken,\n },\n providerUrl: manifest.endpoints.adminInboundUrl,\n };\n}\n"]}
@@ -0,0 +1,63 @@
1
+ import { type CrablineServerChannel } from "../servers/index.js";
2
+ export type OpenClawCrablineSmokeRunLock = {
3
+ assertOwned(): Promise<void>;
4
+ commitFileAtomically(params: {
5
+ contents: string;
6
+ destinationPath: string;
7
+ stageDirectory?: string;
8
+ stageFile(filePath: string, contents: string): Promise<void>;
9
+ }): Promise<void>;
10
+ release(): Promise<void>;
11
+ };
12
+ type HeartbeatController = {
13
+ assertHealthy(): void;
14
+ settle(): Promise<void>;
15
+ stop(): Promise<void>;
16
+ };
17
+ type RemoveLockDirectory = (lockDirectory: string) => Promise<void>;
18
+ type Sleep = (delayMs: number) => Promise<void>;
19
+ type IsProcessAlive = (pid: number) => boolean;
20
+ type GetProcessIdentity = (pid: number) => string | null;
21
+ type StartHeartbeat = (renew: () => Promise<void>, intervalMs: number) => HeartbeatController;
22
+ type BeforeRecoveryClaim = () => Promise<void>;
23
+ type BeforeRecoveryDeleteClaim = () => Promise<void>;
24
+ type BeforeReleaseClaim = () => Promise<void>;
25
+ type BeforeCommitClaim = () => Promise<void>;
26
+ type BeforeCommitFileRename = () => Promise<void>;
27
+ type BeforeCommitRename = () => Promise<void>;
28
+ type SecureWindowsDirectory = (directoryPath: string) => Promise<void>;
29
+ type AfterLockDirectoryWrite = (directoryPath: string) => Promise<void>;
30
+ export declare function processStartedAtMsFromTimeOrigin(timeOrigin: number): number;
31
+ export declare const isProcessAlive: IsProcessAlive;
32
+ export declare function processIdentityFromLinuxStat(value: string, bootId: string): string | null;
33
+ export declare function processIdentityFromDarwin(processStartedAt: string, bootTime: string): string | null;
34
+ export declare function darwinProcessIdentityEnvironment(environment: NodeJS.ProcessEnv): NodeJS.ProcessEnv;
35
+ export declare function acquireOpenClawCrablineSmokeRunLock(params: {
36
+ channel: CrablineServerChannel;
37
+ outputDir: string;
38
+ }, dependencies?: {
39
+ afterLockCandidateInstall?: AfterLockDirectoryWrite;
40
+ afterLockOwnerWrite?: AfterLockDirectoryWrite;
41
+ getProcessIdentity?: GetProcessIdentity;
42
+ isProcessAlive?: IsProcessAlive;
43
+ leaseMs?: number;
44
+ now?: () => number;
45
+ pid?: number;
46
+ processIdentity?: string | null;
47
+ processStartedAtMs?: number;
48
+ platform?: NodeJS.Platform;
49
+ secureWindowsDirectory?: SecureWindowsDirectory;
50
+ beforeCommitClaim?: BeforeCommitClaim;
51
+ beforeCommitFileRename?: BeforeCommitFileRename;
52
+ beforeCommitRename?: BeforeCommitRename;
53
+ beforeRecoveryDeleteClaim?: BeforeRecoveryDeleteClaim;
54
+ beforeRecoveryClaim?: BeforeRecoveryClaim;
55
+ beforeReleaseClaim?: BeforeReleaseClaim;
56
+ removeDirectory?: RemoveLockDirectory;
57
+ sleep?: Sleep;
58
+ startHeartbeat?: StartHeartbeat;
59
+ }): Promise<OpenClawCrablineSmokeRunLock>;
60
+ export declare function releaseOpenClawCrablineSmokeRunLock(lock: Pick<OpenClawCrablineSmokeRunLock, "release">, dependencies?: {
61
+ sleep?: Sleep;
62
+ }): Promise<void>;
63
+ export {};