adam-agent-server 1.16.0 → 1.18.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (201) hide show
  1. package/dist/App-SIQUVFJY.js +14 -0
  2. package/dist/approval-handler-BWA7UIKN.js +1 -0
  3. package/dist/{artifacts-S2KD6W76.js → artifacts-MAYKOTA2.js} +1 -1
  4. package/dist/audit-diagnostics-K3LUWXTI.js +1 -0
  5. package/dist/audit-manager-6WL2V6JG.js +1 -0
  6. package/dist/bree-engine-KYD4GKQK.js +1 -0
  7. package/dist/channels-2TWTBE6Y.js +1 -0
  8. package/dist/channels-PWDSTYNR.js +1 -0
  9. package/dist/chat-tool-calls-WJDFQ54U.js +1 -0
  10. package/dist/chunk-2A2TXYT3.js +15 -0
  11. package/dist/chunk-2CE2WUUZ.js +1 -0
  12. package/dist/chunk-2JIQT2CI.js +1 -0
  13. package/dist/chunk-3MROEPGR.js +1 -0
  14. package/dist/chunk-3UFEOB6P.js +143 -0
  15. package/dist/{chunk-VKKDSXMR.js → chunk-47HJPIUA.js} +1 -1
  16. package/dist/{chunk-AQAHVNNG.js → chunk-4JHACUZY.js} +5 -5
  17. package/dist/{chunk-NUJSTEV4.js → chunk-4N5G7ND2.js} +1 -1
  18. package/dist/{chunk-TLMG5W3L.js → chunk-5G64P4KE.js} +1 -1
  19. package/dist/{chunk-245WE5AF.js → chunk-5M6IGE5G.js} +1 -1
  20. package/dist/chunk-5PELJRUQ.js +1 -0
  21. package/dist/{chunk-VVQ532U2.js → chunk-6WQFYV3N.js} +1 -1
  22. package/dist/{chunk-N2OLEUAQ.js → chunk-AUSR5JYV.js} +1 -1
  23. package/dist/{chunk-LVHLUAZW.js → chunk-BE653A45.js} +8 -7
  24. package/dist/{chunk-OXGWWSKT.js → chunk-BMCNQGUH.js} +1 -1
  25. package/dist/{chunk-BLCNUT53.js → chunk-EZLBMUQD.js} +1 -1
  26. package/dist/{chunk-NLTYJUQG.js → chunk-HL373H4P.js} +1 -1
  27. package/dist/{chunk-6Y2DN2UH.js → chunk-HRPMRWHD.js} +1 -1
  28. package/dist/{chunk-HJICGOD4.js → chunk-IEBAOZED.js} +2 -2
  29. package/dist/{chunk-SCUPWMI5.js → chunk-JROGEBP5.js} +1 -1
  30. package/dist/{chunk-LQVBWVLE.js → chunk-JYZTIE2J.js} +1 -1
  31. package/dist/{chunk-I44JKROJ.js → chunk-JZBXLN7M.js} +1 -1
  32. package/dist/{chunk-H4MMEULK.js → chunk-KS24764D.js} +2 -2
  33. package/dist/chunk-LCD5DVS6.js +1 -0
  34. package/dist/chunk-LKGYQJMS.js +6 -0
  35. package/dist/chunk-MTRLUW7Z.js +1 -0
  36. package/dist/{chunk-3UR2PN5N.js → chunk-NSUXJ2VA.js} +1 -1
  37. package/dist/{chunk-OGY42NUN.js → chunk-NUOTFUNF.js} +1 -1
  38. package/dist/chunk-NXGR3PRY.js +1 -0
  39. package/dist/{chunk-YNS5LQX5.js → chunk-O6L4UVLV.js} +1 -1
  40. package/dist/{chunk-FYULPPFR.js → chunk-OBD4245G.js} +1 -1
  41. package/dist/chunk-QTGAK62Z.js +14 -0
  42. package/dist/chunk-QYI44EP6.js +10 -0
  43. package/dist/{chunk-R24YRJRG.js → chunk-SGLZAIVL.js} +1 -1
  44. package/dist/chunk-SKHMWKJT.js +80 -0
  45. package/dist/chunk-T2Z2JDPY.js +2 -0
  46. package/dist/chunk-TA5PFK5C.js +5 -0
  47. package/dist/chunk-TWOJVEO7.js +32 -0
  48. package/dist/chunk-UCUELFCS.js +61 -0
  49. package/dist/{chunk-TJTH7LHX.js → chunk-V2MMQ3SH.js} +1 -1
  50. package/dist/{chunk-WBAPIPST.js → chunk-VO24C673.js} +1 -1
  51. package/dist/{chunk-HC34HJFF.js → chunk-VPMHZJS2.js} +1 -1
  52. package/dist/chunk-VWX2B6OM.js +6 -0
  53. package/dist/{chunk-QL2ZOLMC.js → chunk-WY5BOCQP.js} +180 -33
  54. package/dist/{chunk-TCBGUVVU.js → chunk-XAPJJAJQ.js} +1 -1
  55. package/dist/{chunk-HXDS4NWI.js → chunk-Z2APBKIT.js} +1 -1
  56. package/dist/chunk-ZJ3TS4FL.js +182 -0
  57. package/dist/{chunk-52FETPCI.js → chunk-ZQN6JZIJ.js} +1 -1
  58. package/dist/cli.js +2 -2
  59. package/dist/config-U624HJKI.js +1 -0
  60. package/dist/config-X7A6NA73.js +1 -0
  61. package/dist/db-XODNIJSJ.js +1 -0
  62. package/dist/{delivery-log-3O3OHKY4.js → delivery-log-QMQQHES4.js} +1 -1
  63. package/dist/engine-OQXDHA2R.js +1 -0
  64. package/dist/evolution-audit-XF4KZZMP.js +1 -0
  65. package/dist/execution-tools-BR4T4MMW.js +1 -0
  66. package/dist/{external-api-YMEFVZGG.js → external-api-435WH6V3.js} +1 -1
  67. package/dist/index.js +67 -47
  68. package/dist/learner-4CJ7BSCN.js +1 -0
  69. package/dist/logger-TEZSHFTZ.js +1 -0
  70. package/dist/{memories-2DY5G6ZN.js → memories-NJFKSOL5.js} +1 -1
  71. package/dist/memory-extractor-UQI75BBK.js +1 -0
  72. package/dist/memory-gc-NTZVUGJX.js +1 -0
  73. package/dist/memory-service-3RLVOF2C.js +1 -0
  74. package/dist/outbound-gateway-NJNSN2ZX.js +1 -0
  75. package/dist/presets-SUJRFRJC.js +1 -0
  76. package/dist/reflection-job-F4BZA2E3.js +23 -0
  77. package/dist/role-presets-VEYTGYA4.js +1 -0
  78. package/dist/role-workspace-AIVHPX5P.js +1 -0
  79. package/dist/roles-WDMUBWQP.js +1 -0
  80. package/dist/runtime-OMLPOMCA.js +1 -0
  81. package/dist/server-bus-6QGH2AVL.js +1 -0
  82. package/dist/session-manager-XFUKWEC7.js +1 -0
  83. package/dist/skill-registry-LARMNUT5.js +1 -0
  84. package/dist/target-resolution-RLNUCT6M.js +1 -0
  85. package/dist/{task-templates-4YPKFFKG.js → task-templates-BIVCRNXA.js} +1 -1
  86. package/dist/template-dispatch-6FPJQN6A.js +1 -0
  87. package/dist/trace-context-NVCN6UPC.js +1 -0
  88. package/package.json +2 -1
  89. package/web/dist/assets/{ArtifactDetail-9DJdEqCz.js → ArtifactDetail-DDTEAl2E.js} +2 -2
  90. package/web/dist/assets/{Artifacts-CQ6SAemH.js → Artifacts-BrhnC1Ef.js} +1 -1
  91. package/web/dist/assets/{Button-xVc-P0vm.js → Button-CRNb8sD3.js} +1 -1
  92. package/web/dist/assets/{Card-WUD1cwG6.js → Card-Cwvv0An8.js} +1 -1
  93. package/web/dist/assets/{ChannelDetail-B21nBQwi.js → ChannelDetail-D0FBZoAX.js} +1 -1
  94. package/web/dist/assets/{Channels-CAeGE1r7.js → Channels-Cztxvsa2.js} +2 -2
  95. package/web/dist/assets/{Chat-KpFWchPp.js → Chat-Ce72TtUi.js} +2 -2
  96. package/web/dist/assets/Cost-K8-4xqBe.js +4 -0
  97. package/web/dist/assets/{Dashboard-DkRwHNmr.js → Dashboard-BXqFb_Vr.js} +1 -1
  98. package/web/dist/assets/{EmptyState-BLB33cKG.js → EmptyState-BvQA1o5K.js} +1 -1
  99. package/web/dist/assets/{EnvVarEditor-BchUNrmz.js → EnvVarEditor-FiiJazzp.js} +1 -1
  100. package/web/dist/assets/{EventDefDetail-DnBwWWfT.js → EventDefDetail-C3S1G0K8.js} +1 -1
  101. package/web/dist/assets/{Events-ByIzPIs2.js → Events-BKxqZ9j6.js} +1 -1
  102. package/web/dist/assets/{Evolution-Vh9RKdma.js → Evolution-DFcSm6Rw.js} +1 -1
  103. package/web/dist/assets/{ExtensionDetail-0CtJh5rF.js → ExtensionDetail-C8aPpyLv.js} +1 -1
  104. package/web/dist/assets/Extensions-MLZk05j0.js +1 -0
  105. package/web/dist/assets/{FeatureRequests-XhQbGg_q.js → FeatureRequests-D_4XaQ7F.js} +1 -1
  106. package/web/dist/assets/{GoalDetail-DIOxf7ES.js → GoalDetail-DVU7c0aR.js} +1 -1
  107. package/web/dist/assets/{Goals-CZnHu9qC.js → Goals-D3h4WMjU.js} +1 -1
  108. package/web/dist/assets/LineChart-Ck1vfYHs.js +33 -0
  109. package/web/dist/assets/Logs-D5MQv6Yw.js +1 -0
  110. package/web/dist/assets/{Memories-D-EAODUg.js → Memories-Dls71I2i.js} +1 -1
  111. package/web/dist/assets/{Mistakes-wW78K3cP.js → Mistakes-BZcTg0vP.js} +1 -1
  112. package/web/dist/assets/{NotFound-BsxIP-Xm.js → NotFound-t66RIvqO.js} +1 -1
  113. package/web/dist/assets/{PageHeader-D8pqg_wk.js → PageHeader-acLQTYct.js} +1 -1
  114. package/web/dist/assets/Plugins-CwCHGzI6.js +1 -0
  115. package/web/dist/assets/RoleDetail-B2M6ALSl.js +3 -0
  116. package/web/dist/assets/Roles-FEHqm_Jf.js +1 -0
  117. package/web/dist/assets/{SectionHeader-DZo4QVWr.js → SectionHeader-NZWZgoOs.js} +1 -1
  118. package/web/dist/assets/Settings-rdVQMfqX.js +1 -0
  119. package/web/dist/assets/{Strategies-Bg4qlLei.js → Strategies-CwJ9JQ-X.js} +1 -1
  120. package/web/dist/assets/{Switch-WWPXnSOG.js → Switch-1JjR4Imr.js} +1 -1
  121. package/web/dist/assets/{Table-XjSmrOyn.js → Table-CvSmzzkm.js} +1 -1
  122. package/web/dist/assets/{Tabs-CSbcG_5T.js → Tabs-DWk9HyNd.js} +1 -1
  123. package/web/dist/assets/TaskDetail-h12WxjfG.js +2 -0
  124. package/web/dist/assets/Work-CfzFRSZX.js +1 -0
  125. package/web/dist/assets/api-BP4ZP9kk.js +1 -0
  126. package/web/dist/assets/{es2015-BgPT8VkR.js → es2015-BkFSNOYE.js} +1 -1
  127. package/web/dist/assets/index-CXEJd-0s.js +12 -0
  128. package/web/dist/assets/index-CarTGiGO.css +2 -0
  129. package/web/dist/assets/{useIsMobileLayout-DF2fEEM9.js → useIsMobileLayout-BogOiFTv.js} +1 -1
  130. package/web/dist/assets/{usePluginsWithUsage-CjU8Lkdn.js → usePluginsWithUsage-4iLJAPjH.js} +1 -1
  131. package/web/dist/assets/{vendor-icons-H7p0EuQJ.js → vendor-icons-Bc_e_XXa.js} +1 -1
  132. package/web/dist/assets/{vendor-react-C1yKjxEP.js → vendor-react-bQ_cvNuA.js} +1 -1
  133. package/web/dist/assets/{vendor-state-D0TNAbOY.js → vendor-state-BMVR_B0I.js} +1 -1
  134. package/web/dist/index.html +8 -8
  135. package/dist/App-Z2GJAMX3.js +0 -14
  136. package/dist/approval-handler-6NPN24UN.js +0 -1
  137. package/dist/audit-diagnostics-2MDM3IQT.js +0 -1
  138. package/dist/audit-manager-QG7CMBV2.js +0 -1
  139. package/dist/bree-engine-3QSLZF3W.js +0 -1
  140. package/dist/channels-S4AAOOTN.js +0 -1
  141. package/dist/channels-TYXSSI7D.js +0 -1
  142. package/dist/chat-tool-calls-2C7O4B2X.js +0 -1
  143. package/dist/chunk-32LOJEHE.js +0 -32
  144. package/dist/chunk-3UZIEE2D.js +0 -6
  145. package/dist/chunk-4234WJJD.js +0 -178
  146. package/dist/chunk-AG5SADAI.js +0 -5
  147. package/dist/chunk-ASPPM7TQ.js +0 -1
  148. package/dist/chunk-C2XFPUFV.js +0 -1
  149. package/dist/chunk-DRO3DG7X.js +0 -1
  150. package/dist/chunk-EWYXVBOG.js +0 -61
  151. package/dist/chunk-FCV2DPZQ.js +0 -1
  152. package/dist/chunk-FHESRUJY.js +0 -9
  153. package/dist/chunk-K2TZW4DU.js +0 -132
  154. package/dist/chunk-K4IE6DPX.js +0 -6
  155. package/dist/chunk-MNSZE3NV.js +0 -1
  156. package/dist/chunk-MTQI6B7T.js +0 -15
  157. package/dist/chunk-P5Q2UINT.js +0 -1
  158. package/dist/chunk-WVHN54MA.js +0 -14
  159. package/dist/chunk-XYZVMTNN.js +0 -1
  160. package/dist/chunk-Z6LHGA27.js +0 -1
  161. package/dist/config-HDAAV5FV.js +0 -1
  162. package/dist/config-VHWLMFIN.js +0 -1
  163. package/dist/db-HFBXO2O5.js +0 -1
  164. package/dist/dist-HCSYRPJU.js +0 -1
  165. package/dist/engine-J43ECCH7.js +0 -1
  166. package/dist/evolution-audit-BSGPFGFK.js +0 -1
  167. package/dist/execution-tools-HHUPWLCF.js +0 -1
  168. package/dist/learner-TQQZKRSB.js +0 -1
  169. package/dist/logger-PAMNFWI3.js +0 -1
  170. package/dist/memory-extractor-TUOOFST2.js +0 -1
  171. package/dist/memory-gc-MRO53MEY.js +0 -1
  172. package/dist/memory-service-23WVAW7T.js +0 -1
  173. package/dist/onnxruntime_binding-2BPLI7ZQ.node +0 -0
  174. package/dist/onnxruntime_binding-5J67DTMJ.node +0 -0
  175. package/dist/onnxruntime_binding-7ZZLEQ2F.node +0 -0
  176. package/dist/onnxruntime_binding-KDCXAPN5.node +0 -0
  177. package/dist/onnxruntime_binding-R73P2IQW.node +0 -0
  178. package/dist/outbound-gateway-VXODXSQR.js +0 -1
  179. package/dist/presets-KJV6SNNB.js +0 -1
  180. package/dist/reflection-job-EFFW3WOR.js +0 -23
  181. package/dist/role-presets-PHHL3OEN.js +0 -1
  182. package/dist/role-workspace-USY47ZPQ.js +0 -1
  183. package/dist/roles-3JXNHL7K.js +0 -1
  184. package/dist/runtime-TWLGJSL6.js +0 -1
  185. package/dist/server-bus-GEGVMSCA.js +0 -1
  186. package/dist/session-manager-PI3JEINK.js +0 -1
  187. package/dist/skill-registry-ROGU2WED.js +0 -1
  188. package/dist/target-resolution-PSSBM4LX.js +0 -1
  189. package/dist/template-dispatch-46TN534D.js +0 -1
  190. package/dist/trace-context-UR7DI5ME.js +0 -1
  191. package/web/dist/assets/Extensions--O1ulwlC.js +0 -1
  192. package/web/dist/assets/Logs-DdeG3GiY.js +0 -1
  193. package/web/dist/assets/Plugins-DDUdX51_.js +0 -1
  194. package/web/dist/assets/RoleDetail-CU3G9j_q.js +0 -35
  195. package/web/dist/assets/Roles-BCoSzDBg.js +0 -1
  196. package/web/dist/assets/Settings-K3usfV-2.js +0 -1
  197. package/web/dist/assets/TaskDetail-C5roukcV.js +0 -2
  198. package/web/dist/assets/Work-DGTWSgtc.js +0 -1
  199. package/web/dist/assets/api-BkdixMz9.js +0 -1
  200. package/web/dist/assets/index-KNUbHDLy.css +0 -2
  201. package/web/dist/assets/index-iD-HOtIu.js +0 -12
@@ -0,0 +1,61 @@
1
+ import{d as V}from"./chunk-XAPJJAJQ.js";import{b as L}from"./chunk-Z2APBKIT.js";import{b as N,p as Z}from"./chunk-2A2TXYT3.js";import{n as d,p as k}from"./chunk-WY5BOCQP.js";import{c as F,h as X}from"./chunk-EZLBMUQD.js";Z();k();k();function Ee(e){d().prepare(`
2
+ INSERT INTO audit_violations
3
+ (id, step_task_id, execution_id, role_id, contract_field, layer, severity, message, metadata_json, created_at)
4
+ VALUES
5
+ (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
6
+ `).run(e.id,e.stepTaskId,e.executionId??null,e.roleId,e.contractField,e.layer,e.severity,e.message,e.metadata?JSON.stringify(e.metadata):null,e.createdAt)}function h(e){return{id:e.id,stepTaskId:e.step_task_id,executionId:e.execution_id??void 0,roleId:e.role_id,contractField:e.contract_field,layer:e.layer,severity:e.severity,message:e.message,metadata:e.metadata_json?JSON.parse(e.metadata_json):void 0,createdAt:e.created_at}}function D(e,s=50){return d().prepare("SELECT * FROM audit_violations WHERE role_id = ? ORDER BY created_at DESC LIMIT ?").all(e,s).map(h)}function H(e){return d().prepare("SELECT * FROM audit_violations WHERE step_task_id = ? ORDER BY created_at DESC").all(e).map(h)}function Te(e){return d().prepare("SELECT * FROM audit_violations WHERE execution_id = ? ORDER BY created_at DESC").all(e).map(h)}function P(e){return{id:e.id,roleId:e.role_id,taskId:e.task_id,scores:JSON.parse(e.score_json),emaScore:e.ema_score,createdAt:e.created_at,taskType:e.task_type??void 0}}function W(e){d().prepare(`
7
+ INSERT INTO role_scores (id, role_id, task_id, task_type, score_json, ema_score, created_at)
8
+ VALUES (?, ?, ?, ?, ?, ?, ?)
9
+ `).run(e.id,e.roleId,e.taskId,e.taskType??null,JSON.stringify(e.scores),e.emaScore,e.createdAt)}function ee(e,s=50){return d().prepare("SELECT * FROM role_scores WHERE role_id = ? ORDER BY created_at DESC LIMIT ?").all(e,s).map(P)}function B(e){return d().prepare("SELECT ema_score FROM role_scores WHERE role_id = ? ORDER BY created_at DESC LIMIT 1").get(e)?.ema_score}function U(e){let t=d().prepare(`
10
+ SELECT token_usage FROM tasks
11
+ WHERE role_id = ? AND status = 'completed' AND token_usage IS NOT NULL
12
+ ORDER BY completed_at DESC LIMIT 50
13
+ `).all(e);if(t.length===0)return 1e4;let n=t.map(r=>{let a=JSON.parse(r.token_usage);return(a.input??0)+(a.output??0)}).sort((r,a)=>r-a);return n[Math.floor(n.length/2)]}function Ie(e){let t=d().prepare("SELECT * FROM role_scores WHERE role_id = ? ORDER BY created_at DESC LIMIT 1").get(e);return t?P(t):void 0}function xe(e,s,t,n,r){let a=d(),o=a.prepare("SELECT id, role_id, score_json FROM role_scores WHERE task_id = ?").get(e);if(!o)return;let l=JSON.parse(o.score_json);l.intentFulfillment=s,l.intentFulfillmentFailed=t,l.weighted=n(l);let p=a.prepare("SELECT ema_score FROM role_scores WHERE role_id = ? AND created_at < (SELECT created_at FROM role_scores WHERE id = ?) ORDER BY created_at DESC LIMIT 1").get(o.role_id,o.id),u=p!==void 0?r*l.weighted+(1-r)*p.ema_score:l.weighted;return a.prepare("UPDATE role_scores SET score_json = ?, ema_score = ? WHERE id = ?").run(JSON.stringify(l),u,o.id),u}function Me(e,s){let n=d().prepare(`
14
+ SELECT rs.score_json, t.cost_usd, t.completed_at, rs.created_at
15
+ FROM role_scores rs
16
+ JOIN tasks t ON t.id = rs.task_id
17
+ WHERE rs.role_id = ? AND rs.task_type = ?
18
+ ORDER BY rs.created_at DESC
19
+ `).all(e,s);if(n.length===0)return{totalTasks:0,successRate:0,avgCostUsd:0,lastAttempt:null};let r=n.length,o=n.filter(f=>JSON.parse(f.score_json).taskSuccess===1).length/r,p=n.map(f=>f.cost_usd??0).reduce((f,E)=>f+E,0)/r,u=n[0]?.created_at??null;return{totalTasks:r,successRate:o,avgCostUsd:p,lastAttempt:u}}function he(e,s=50){let n=ee(e,s).map(o=>o.scores.contractCompliance).filter(o=>o!=null);return n.length===0?{emaScore:null,recentViolations:D(e,10),contractsCheckedRowCount:0}:{emaScore:[...n].reverse().reduce((o,l,p)=>p===0?l:A*l+(1-A)*o,0),recentViolations:D(e,10),contractsCheckedRowCount:n.length}}X();import{v4 as te}from"uuid";var se=F("audit"),O={taskSuccess:.25,planAccuracy:.2,permissionCompliance:.2,efficiency:.15,intentFulfillment:.2},M={taskSuccess:.3,planAccuracy:.25,permissionCompliance:.25,efficiency:.2},A=.3;function ne(e){return e.intentFulfillment===null||e.intentFulfillment===void 0?e.taskSuccess*M.taskSuccess+e.planAccuracy*M.planAccuracy+e.permissionCompliance*M.permissionCompliance+e.efficiency*M.efficiency:e.taskSuccess*O.taskSuccess+e.planAccuracy*O.planAccuracy+e.permissionCompliance*O.permissionCompliance+e.efficiency*O.efficiency+e.intentFulfillment*O.intentFulfillment}function re(e,s){let t=N(e),n=t?.status==="completed"?1:0,r=1,a=V(e);a?.deviationReport&&(r=a.deviationReport.overallAccuracy);let o=1,l=L(e,1e3),p=l.filter(_=>_.type==="tool_result"||_.type==="permission_denied").length,u=l.filter(_=>_.type==="permission_denied").length;p>0&&(o=1-u/p);let f=1;if(t?.tokenUsage){let _=t.tokenUsage.input+t.tokenUsage.output,c=s?U(s):1e4;_>c&&(f=Math.max(0,1-(_-c)/c))}let E=ne({taskSuccess:n,planAccuracy:r,permissionCompliance:o,efficiency:f,intentFulfillment:void 0}),T=t?.config?.outputContractCheckCount??0,x=null;if(T>0){let c=H(e).filter(i=>!(i.severity==="warning"&&i.layer==="C"));x=Math.max(0,Math.min(1,1-c.length/T))}return{taskSuccess:n,planAccuracy:r,permissionCompliance:o,efficiency:f,contractCompliance:x,contractsCheckedThisTask:T,weighted:E}}function He(e,s,t){let n=re(s,e),r=B(e),a=r!==void 0?A*n.weighted+(1-A)*r:n.weighted;return W({id:te(),roleId:e,taskId:s,scores:n,emaScore:a,createdAt:Date.now(),taskType:t}),se.debug({roleId:e,taskId:s,scores:{...n,weighted:n.weighted.toFixed(3)},ema:a.toFixed(3)},"Task score recorded"),a}k();function q(e){return{id:e.id,sourceSessionId:e.source_session_id??void 0,sourceMessageId:e.source_message_id??void 0,extractedAt:e.extracted_at,extractedByRoleId:e.extracted_by_role_id??void 0,content:e.content,summary:e.summary??void 0,status:e.status,tags:e.tags?JSON.parse(e.tags):void 0,evidenceQuote:e.evidence_quote??void 0,createdAt:e.created_at,updatedAt:e.updated_at}}var oe=`
20
+ INSERT INTO feature_requests
21
+ (id, source_session_id, source_message_id, extracted_at, extracted_by_role_id,
22
+ content, summary, status, tags, evidence_quote, created_at, updated_at)
23
+ VALUES
24
+ (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
25
+ `.trim(),ie=`
26
+ UPDATE feature_requests SET status = ?, updated_at = ? WHERE id = ?
27
+ `.trim();function J(e){d().prepare(oe).run(e.id,e.sourceSessionId??null,e.sourceMessageId??null,e.extractedAt,e.extractedByRoleId??null,e.content,e.summary??null,e.status,e.tags?JSON.stringify(e.tags):null,e.evidenceQuote??null,e.createdAt,e.updatedAt)}function Be(e,s=100,t=0){let n=d();return(e?n.prepare("SELECT * FROM feature_requests WHERE status = ? ORDER BY extracted_at DESC LIMIT ? OFFSET ?").all(e,s,t):n.prepare("SELECT * FROM feature_requests ORDER BY extracted_at DESC LIMIT ? OFFSET ?").all(s,t)).map(q)}function Ue(e){let t=d().prepare("SELECT * FROM feature_requests WHERE id = ?").get(e);return t?q(t):void 0}function qe(e,s){d().prepare(ie).run(s,Date.now(),e)}k();function v(e){return{id:e.id,dimensionType:e.dimension_type,dimensionValue:e.dimension_value,count:e.count,roleIds:JSON.parse(e.role_ids),sampleEvidenceIds:JSON.parse(e.sample_evidence_ids),status:e.status,firstSeen:e.first_seen,lastSeen:e.last_seen,createdAt:e.created_at,updatedAt:e.updated_at}}var ae=`
28
+ INSERT INTO mistake_patterns
29
+ (id, dimension_type, dimension_value, count, role_ids, sample_evidence_ids,
30
+ status, first_seen, last_seen, created_at, updated_at)
31
+ VALUES
32
+ (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
33
+ `.trim(),ce=`
34
+ UPDATE mistake_patterns SET status = ?, updated_at = ? WHERE id = ?
35
+ `.trim();function j(e){let s=d(),t=Date.now(),n=e.sampleEvidenceIds.slice(-10),r=s.prepare("SELECT * FROM mistake_patterns WHERE dimension_type = ? AND dimension_value = ?").get(e.dimensionType,e.dimensionValue);if(r){let o=JSON.parse(r.role_ids),l=Array.from(new Set([...o,...e.roleIds])),u=[...JSON.parse(r.sample_evidence_ids),...n].slice(-10);s.prepare(`
36
+ UPDATE mistake_patterns SET
37
+ count = count + 1,
38
+ role_ids = ?,
39
+ sample_evidence_ids = ?,
40
+ last_seen = ?,
41
+ updated_at = ?
42
+ WHERE dimension_type = ? AND dimension_value = ?
43
+ `).run(JSON.stringify(l),JSON.stringify(u),e.lastSeen,t,e.dimensionType,e.dimensionValue)}else s.prepare(ae).run(`mp-${Date.now()}-${Math.random().toString(36).slice(2,8)}`,e.dimensionType,e.dimensionValue,1,JSON.stringify(e.roleIds),JSON.stringify(n),"new",e.firstSeen,e.lastSeen,t,t);let a=s.prepare("SELECT * FROM mistake_patterns WHERE dimension_type = ? AND dimension_value = ?").get(e.dimensionType,e.dimensionValue);return v(a)}function Ye(e,s=100,t=0){let n=d();return(e?n.prepare("SELECT * FROM mistake_patterns WHERE status = ? ORDER BY last_seen DESC LIMIT ? OFFSET ?").all(e,s,t):n.prepare("SELECT * FROM mistake_patterns ORDER BY last_seen DESC LIMIT ? OFFSET ?").all(s,t)).map(v)}function Ke(e){let t=d().prepare("SELECT * FROM mistake_patterns WHERE id = ?").get(e);return t?v(t):void 0}function Qe(e,s){d().prepare(ce).run(s,Date.now(),e)}k();import{randomUUID as Y}from"crypto";function Xe(e,s){if(s.added.length===0&&s.modified.length===0&&s.deleted.length===0)return;let t=d(),n=t.prepare("INSERT INTO task_files (id, task_id, path, op, mtime_ns, size_bytes, inode, created_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?)");n.safeIntegers(!0);let r=Date.now();t.transaction(()=>{let a=(o,l)=>{n.run(Y(),e,o.path,l,o.mtime_ns,o.size,o.inode,r)};for(let o of s.added)a(o,"added");for(let o of s.modified)a(o,"modified");for(let o of s.deleted)n.run(Y(),e,o,"deleted",null,null,null,r)})()}function Ze(e){let t=d().prepare("SELECT * FROM task_files WHERE task_id = ? ORDER BY created_at, path");return t.safeIntegers(!0),t.all(e)}import{createSdkMcpServer as de,tool as le}from"@anthropic-ai/claude-agent-sdk";import{z as S}from"zod";import{v4 as ue}from"uuid";var K={content:S.string().min(1).max(5e3),summary:S.string().max(500).optional(),tags:S.array(S.string().max(50)).max(10).optional(),evidenceQuote:S.string().max(1e3).optional(),sourceSessionId:S.string().optional(),sourceMessageId:S.string().optional()};function me(e){return le("record_feature_request","Record a feature request extracted from chat sessions. Call this once per distinct feature request found in the provided chat data. Do not fabricate \u2014 only record requests that appear verbatim or clearly in the chat content.",K,async s=>{let t=S.object(K).safeParse(s);if(!t.success)return{content:[{type:"text",text:JSON.stringify({ok:!1,error:t.error.message})}]};let n=t.data,r=Date.now(),a=ue(),o={id:a,content:n.content,summary:n.summary,status:"new",tags:n.tags??[],evidenceQuote:n.evidenceQuote,sourceSessionId:n.sourceSessionId,sourceMessageId:n.sourceMessageId,extractedByRoleId:e,extractedAt:r,createdAt:r,updatedAt:r};try{J(o)}catch{return{content:[{type:"text",text:JSON.stringify({ok:!1,error:"failed to write feature request"})}]}}return{content:[{type:"text",text:JSON.stringify({success:!0,featureRequestId:a,summary:n.summary??n.content.slice(0,80)})}]}})}function Q(e){return de({name:"mining-tools",version:"1.0.0",tools:[me(e)]})}import{createSdkMcpServer as fe,tool as _e}from"@anthropic-ai/claude-agent-sdk";import{z as I}from"zod";k();var C=.5,w=.3;function pe(e,s,t,n){let r=e<t,a=s<n;return r&&a?"both":r?"low_ema":"low_task"}function z(e={}){let{windowDays:s=14,dimensions:t=["event_type","score_degradation","tool_call_pattern"],minOccurrences:n=3,minRoles:r=2,scoreThresholdEma:a=C,scoreThresholdTask:o=w}=e,l=d(),p=Date.now()-s*864e5,u=new Map;if(t.includes("event_type")){let c=l.prepare(`
44
+ SELECT id, role_id, source, timestamp
45
+ FROM evolution_audit
46
+ WHERE timestamp >= ? AND source IN ('audit','monitor','admin','manual')
47
+ ORDER BY timestamp ASC
48
+ `).all(p);for(let i of c){let g=i.source,R=`event_type|${g}`;u.has(R)||u.set(R,{dimensionType:"event_type",dimensionValue:g,count:0,roleIds:new Set,evidenceIds:[],firstSeen:1/0,lastSeen:0});let m=u.get(R);m.count++,i.role_id&&m.roleIds.add(i.role_id),m.evidenceIds.push({source:"evolution_audit",id:i.id}),i.timestamp<m.firstSeen&&(m.firstSeen=i.timestamp),i.timestamp>m.lastSeen&&(m.lastSeen=i.timestamp)}}if(t.includes("score_degradation")){let c=l.prepare(`
49
+ SELECT id, role_id, score_json, ema_score, created_at
50
+ FROM role_scores
51
+ WHERE created_at >= ?
52
+ ORDER BY created_at ASC
53
+ `).all(p);for(let i of c){let g=i.ema_score;try{let b=JSON.parse(i.score_json);typeof b.weighted=="number"?g=b.weighted:typeof b.task=="number"?g=b.task:typeof b.score=="number"&&(g=b.score)}catch{}let R=pe(i.ema_score,g,a,o),m=`score_degradation|${R}`;u.has(m)||u.set(m,{dimensionType:"score_degradation",dimensionValue:R,count:0,roleIds:new Set,evidenceIds:[],firstSeen:1/0,lastSeen:0});let y=u.get(m);y.count++,y.roleIds.add(i.role_id),y.evidenceIds.push({source:"role_scores",id:i.id}),i.created_at<y.firstSeen&&(y.firstSeen=i.created_at),i.created_at>y.lastSeen&&(y.lastSeen=i.created_at)}}if(t.includes("tool_call_pattern")){let c=l.prepare(`
54
+ SELECT dl.id, dl.task_id, dl.error, dl.created_at, t.role_id
55
+ FROM delivery_log dl
56
+ LEFT JOIN tasks t ON t.id = dl.task_id
57
+ WHERE dl.created_at >= ?
58
+ AND dl.message_type = 'sandbox_violation'
59
+ AND dl.source = 'audit'
60
+ ORDER BY dl.created_at ASC
61
+ `).all(p);for(let i of c){let g=(i.error??"").slice(0,60),R=`tool_call_pattern|${g}`;u.has(R)||u.set(R,{dimensionType:"tool_call_pattern",dimensionValue:g,count:0,roleIds:new Set,evidenceIds:[],firstSeen:1/0,lastSeen:0});let m=u.get(R);m.count++,i.role_id&&m.roleIds.add(i.role_id),m.evidenceIds.push({source:"delivery_log",id:i.id}),i.created_at<m.firstSeen&&(m.firstSeen=i.created_at),i.created_at>m.lastSeen&&(m.lastSeen=i.created_at)}}let f={};for(let c of u.keys()){let[i]=c.split("|");f[i]=(f[i]??0)+1}let E=Array.from(u.values()).filter(c=>c.count>=n&&c.roleIds.size>=r),T=0,x=l.transaction(()=>{for(let c of E)j({dimensionType:c.dimensionType,dimensionValue:c.dimensionValue,roleIds:Array.from(c.roleIds),sampleEvidenceIds:c.evidenceIds.slice(-10),firstSeen:c.firstSeen===1/0?Date.now():c.firstSeen,lastSeen:c.lastSeen}),T++});try{x()}catch(c){throw new Error(`aggregateMistakes: transaction failed: ${c}`)}let _=0;for(let c of u.values())_+=c.count;return{patternsUpserted:T,totalEventsScanned:_,dimensionCounts:f}}var $={windowDays:I.number().int().min(1).max(365).optional(),dimensions:I.enum(["event_type","score_degradation","tool_call_pattern"]).array().min(1).max(3).optional(),minOccurrences:I.number().int().min(1).max(100).optional(),minRoles:I.number().int().min(1).max(100).optional()};function ge(){return _e("aggregate_mistakes","Aggregate cross-role failure signals from the last N days into mistake patterns. Returns counts + dimensions; patterns are persisted to mistake_patterns for UI review. Notify-only: no role/permission/CAG mutation.",$,async e=>{let s=I.object($).safeParse(e);if(!s.success)return{content:[{type:"text",text:JSON.stringify({ok:!1,error:s.error.message})}]};let t=s.data,n={windowDays:t.windowDays??14,dimensions:t.dimensions??["event_type","score_degradation","tool_call_pattern"],minOccurrences:t.minOccurrences??3,minRoles:t.minRoles??2,scoreThresholdEma:C,scoreThresholdTask:w};try{let r=z(n);return{content:[{type:"text",text:JSON.stringify({ok:!0,...r})}]}}catch(r){return{content:[{type:"text",text:JSON.stringify({ok:!1,error:String(r)})}]}}})}var Re="audit-tools";function G(){return fe({name:Re,version:"1.0.0",tools:[ge()]})}var Se=new Set(["mcp__execution-tools__","mcp__mining-tools__","mcp__audit-tools__"]);function gt(e){if(!e)return!1;for(let s of Se)if(e.startsWith(s))return!0;return!1}function Rt(e){return e.presetId==="feature-miner"?{"mining-tools":Q(e.id)}:e.presetId==="mistake-digester"?{"audit-tools":G()}:{}}function yt(e,s){let t=e.toLowerCase(),n=e;return/\b401\b/.test(t)||/unauthorized/i.test(t)||/invalid.*(?:api.?)?key/i.test(t)||/auth.*fail/i.test(t)||/invalid.*token/i.test(t)||s?.httpStatus===401?{category:"AUTH",originalError:n,retryable:!1,userAction:"Update the API key or credentials in the Role configuration",sameRoleRetry:!1,differentRoleHelp:!1}:/\b429\b/.test(t)||/rate.?limit/i.test(t)||/too many requests/i.test(t)||/quota.?exhaust/i.test(t)||/rate.?limit.?exceed/i.test(t)||/too.?many.?calls/i.test(t)?{category:"RATE_LIMIT",originalError:n,retryable:!0,userAction:"Wait before retrying, or increase the rate limit quota",sameRoleRetry:!0,differentRoleHelp:!1}:/econnrefused/i.test(t)||/enotfound/i.test(t)||/dns/i.test(t)||/connection.?refused/i.test(t)||/connection.?reset/i.test(t)||/connection.?timed? ?out/i.test(t)||/fetch.?failed/i.test(t)||/network.?error/i.test(t)||/socket.?hang.?up/i.test(t)||/etimedout/i.test(t)?{category:"NETWORK",originalError:n,retryable:!0,userAction:"Check network connectivity and that the target service is reachable",sameRoleRetry:!0,differentRoleHelp:!1}:/prompt is too long/i.test(t)||/context.*exceed/i.test(t)||/context.*window/i.test(t)||/too many tokens/i.test(t)||/max.?tokens/i.test(t)||/token.?limit/i.test(t)?{category:"CONTEXT_OVERFLOW",originalError:n,retryable:!1,userAction:"Shorten the task prompt or simplify the request",sameRoleRetry:!1,differentRoleHelp:!1}:s?.sandboxViolation||/sandbox/i.test(t)||/not allowed.*sandbox/i.test(t)||/sandbox.*deny/i.test(t)||/operation.*denied.*sandbox/i.test(t)?{category:"SANDBOX_VIOLATION",originalError:n,retryable:!1,userAction:"Grant filesystem access in Role settings, or run without sandbox",sameRoleRetry:!1,differentRoleHelp:!0}:/tool.*not found/i.test(t)||/command not found/i.test(t)||/enoent/i.test(t)||/no such file/i.test(t)||/mcp.*error.*tool/i.test(t)||/tool.*blocked/i.test(t)||s?.toolName&&/not.*found/.test(t)&&/tool/.test(t)?{category:"TOOL_UNAVAILABLE",originalError:n,retryable:!1,userAction:"Install the required tool or plugin, or add it to the Role's allowed tools",sameRoleRetry:!1,differentRoleHelp:!0}:/timeout/i.test(t)||/timed out/i.test(t)||/exceeded.*seconds/i.test(t)?{category:"TIMEOUT",originalError:n,retryable:!0,userAction:"Increase the task timeout or simplify the task",sameRoleRetry:!0,differentRoleHelp:!1}:/invalid.*url/i.test(t)||/bad request/i.test(t)||/400\b/.test(t)||/wrong.*method/i.test(t)||/invalid.*param/i.test(t)||/missing.*param/i.test(t)?{category:"MALFORMED_REQUEST",originalError:n,retryable:!1,userAction:"Fix the task parameters and retry",sameRoleRetry:!1,differentRoleHelp:!1}:/internal.*error/i.test(t)||/unexpected.*error/i.test(t)||/500\b/.test(t)||/503\b/.test(t)?{category:"INTERNAL_ERROR",originalError:n,retryable:!0,userAction:"The service had an internal error. Retry may succeed.",sameRoleRetry:!0,differentRoleHelp:!1}:{category:"UNKNOWN",originalError:n,retryable:!1,userAction:void 0,sameRoleRetry:!1,differentRoleHelp:!1}}export{Ee as a,Te as b,A as c,ne as d,He as e,ee as f,B as g,Ie as h,xe as i,Me as j,he as k,J as l,Be as m,Ue as n,qe as o,Ye as p,Ke as q,Qe as r,Se as s,gt as t,Rt as u,yt as v,Xe as w,Ze as x};
@@ -1,4 +1,4 @@
1
- import{C as M,I as D}from"./chunk-MTQI6B7T.js";import{n as u,p as O}from"./chunk-QL2ZOLMC.js";O();D();function E(e){return{id:e.id,roleId:e.role_id,type:e.type,content:e.content,embedding:e.embedding?new Float32Array(e.embedding.buffer,e.embedding.byteOffset,e.embedding.byteLength/4):void 0,keywords:e.keywords?JSON.parse(e.keywords):[],importance:e.importance,sourceType:e.source_type,sourceTaskId:e.source_task_id??void 0,evidence:e.evidence?JSON.parse(e.evidence):void 0,createdAt:e.created_at,lastAccessed:e.last_accessed,retrievedCount:e.retrieved_count,tier:e.tier,supersededBy:e.superseded_by??void 0}}function _(e){return Buffer.from(e.buffer,e.byteOffset,e.byteLength)}function I(e){u().prepare(`
1
+ import{D as M,L as D}from"./chunk-2A2TXYT3.js";import{n as u,p as O}from"./chunk-WY5BOCQP.js";O();D();function E(e){return{id:e.id,roleId:e.role_id,type:e.type,content:e.content,embedding:e.embedding?new Float32Array(e.embedding.buffer,e.embedding.byteOffset,e.embedding.byteLength/4):void 0,keywords:e.keywords?JSON.parse(e.keywords):[],importance:e.importance,sourceType:e.source_type,sourceTaskId:e.source_task_id??void 0,evidence:e.evidence?JSON.parse(e.evidence):void 0,createdAt:e.created_at,lastAccessed:e.last_accessed,retrievedCount:e.retrieved_count,tier:e.tier,supersededBy:e.superseded_by??void 0}}function _(e){return Buffer.from(e.buffer,e.byteOffset,e.byteLength)}function I(e){u().prepare(`
2
2
  INSERT INTO memories (id, role_id, type, content, embedding, keywords,
3
3
  importance, source_type, source_task_id, evidence,
4
4
  created_at, last_accessed, retrieved_count, tier, superseded_by)
@@ -1 +1 @@
1
- import{c as s}from"./chunk-FCV2DPZQ.js";import{join as o}from"path";import{homedir as r}from"os";var c,e,A,t,p,E,a,S,D,P,T=s(()=>{"use strict";c=["Read","Write","Edit","Bash","Grep","Glob","WebSearch","WebFetch","LSP","NotebookEdit","Agent"],e=["~/.ssh","~/.aws","~/.gnupg","/etc/shadow"],A=e,t=o(r(),".adam"),p=o(t,"adam.db"),E=o(t,"adam.config.yaml"),a=o(t,".env"),S=o(t,"CLAUDE.md"),D=o(t,"logs"),P=10*1024});export{c as a,e as b,A as c,t as d,p as e,E as f,a as g,T as h};
1
+ import{b as s}from"./chunk-5PELJRUQ.js";import{join as o}from"path";import{homedir as r}from"os";var c,e,A,t,p,E,a,S,D,P,T=s(()=>{"use strict";c=["Read","Write","Edit","Bash","Grep","Glob","WebSearch","WebFetch","LSP","NotebookEdit","Agent"],e=["~/.ssh","~/.aws","~/.gnupg","/etc/shadow"],A=e,t=o(r(),".adam"),p=o(t,"adam.db"),E=o(t,"adam.config.yaml"),a=o(t,".env"),S=o(t,"CLAUDE.md"),D=o(t,"logs"),P=10*1024});export{c as a,e as b,A as c,t as d,p as e,E as f,a as g,T as h};
@@ -1 +1 @@
1
- import{g as Qe}from"./chunk-HJICGOD4.js";import{a as He,b as k,c as xe,d as B,e as Ke}from"./chunk-NNMQGISW.js";import{b as Xe,c as Je,f as se,g as re}from"./chunk-6Y2DN2UH.js";import{a as je,b as Ve,c as E,d as ne,e as F,f as Te,g as z,i as ze}from"./chunk-VVQ532U2.js";import{d as V}from"./chunk-Z6LHGA27.js";import{c as y,h as C}from"./chunk-BLCNUT53.js";import{z as g}from"zod/v4";import{v4 as Ms}from"uuid";import{randomUUID as st}from"crypto";import tn from"crypto";var Ye="2.1.7",ie="bot";function nn(t){let e=t.split(".").map(i=>parseInt(i,10)),n=e[0]??0,r=e[1]??0,s=e[2]??0;return(n&255)<<16|(r&255)<<8|s&255}var Me=nn(Ye),sn=35e3,Ze=15e3,rn=1e4;function ae(){return{channel_version:Ye}}function an(t){return t.endsWith("/")?t:`${t}/`}function on(){let t=tn.randomBytes(4).readUInt32BE(0);return Buffer.from(String(t),"utf-8").toString("base64")}function dn(t){let e={"Content-Type":"application/json",AuthorizationType:"ilink_bot_token","Content-Length":String(Buffer.byteLength(t.body,"utf-8")),"X-WECHAT-UIN":on(),"iLink-App-Id":ie,"iLink-App-ClientVersion":String(Me)};return t.token?.trim()&&(e.Authorization=`Bearer ${t.token.trim()}`),t.routeTag&&(e.SKRouteTag=t.routeTag),e}async function oe(t){let e=an(t.baseUrl),n=new URL(t.endpoint,e),r=dn({token:t.token,routeTag:t.routeTag,body:t.body}),s=new AbortController,i=setTimeout(()=>s.abort(),t.timeoutMs);try{let a=await fetch(n.toString(),{method:"POST",headers:r,body:t.body,signal:s.signal});clearTimeout(i);let o=await a.text();if(!a.ok)throw new Error(`${t.label} ${a.status}: ${o}`);return o}catch(a){throw clearTimeout(i),a}}async function et(t){let e=t.timeoutMs??sn;try{let n=await oe({baseUrl:t.baseUrl,endpoint:"ilink/bot/getupdates",body:JSON.stringify({get_updates_buf:t.get_updates_buf??"",base_info:ae()}),token:t.token,routeTag:t.routeTag,timeoutMs:e,label:"getUpdates"});return JSON.parse(n)}catch(n){if(n instanceof Error&&n.name==="AbortError")return{ret:0,msgs:[],get_updates_buf:t.get_updates_buf};throw n}}var un={[-2]:2,[-3]:3},cn=1e3;async function Q(t){let e=(await import("./logger-PAMNFWI3.js")).getLogger("channels"),n=new Map;for(;;){let r=await oe({baseUrl:t.baseUrl,endpoint:"ilink/bot/sendmessage",body:JSON.stringify({...t.body,base_info:ae()}),token:t.token,routeTag:t.routeTag,timeoutMs:t.timeoutMs??Ze,label:"sendMessage"});e.info({status:200,responseBody:r.slice(0,300)},"apiFetch sendMessage response");try{let s=JSON.parse(r);if(s.ret&&s.ret!==0){let i=un[s.ret],a=(n.get(s.ret)??0)+1;if(n.set(s.ret,a),i!==void 0&&a<i){e.warn({ret:s.ret,attempt:a,maxRetries:i},"sendMessage: retriable iLink error, retrying"),await new Promise(o=>setTimeout(o,cn*a));continue}throw e.error({ret:s.ret,errmsg:s.errmsg,attempt:a},"sendMessage: iLink API error, no more retries"),new Error(`sendMessage failed: iLink ret=${s.ret}${s.errmsg?` errmsg=${s.errmsg}`:""}`)}}catch(s){if(s instanceof SyntaxError)e.warn({rawText:r.slice(0,200)},"sendMessage: non-JSON response, treating as success");else throw s}return}}async function tt(t){await oe({baseUrl:t.baseUrl,endpoint:"ilink/bot/sendtyping",body:JSON.stringify({...t.body,base_info:ae()}),token:t.token,routeTag:t.routeTag,timeoutMs:t.timeoutMs??rn,label:"sendTyping"})}async function nt(t){let e=await oe({baseUrl:t.baseUrl,endpoint:"ilink/bot/getuploadurl",body:JSON.stringify({filekey:t.filekey,media_type:t.media_type,to_user_id:t.to_user_id,rawsize:t.rawsize,rawfilemd5:t.rawfilemd5,filesize:t.filesize,thumb_rawsize:t.thumb_rawsize,thumb_rawfilemd5:t.thumb_rawfilemd5,thumb_filesize:t.thumb_filesize,no_need_thumb:t.no_need_thumb,aeskey:t.aeskey,base_info:ae()}),token:t.token,routeTag:t.routeTag,timeoutMs:t.timeoutMs??Ze,label:"getUploadUrl"});return JSON.parse(e)}var ln=5*6e4,mn=35e3,rt="3",T=new Map;function Se(t){return Date.now()-t.startedAt<ln}function gn(){for(let[t,e]of T)Se(e)||T.delete(t)}async function it(t,e,n){let r=t.endsWith("/")?t:`${t}/`,s=new URL(`ilink/bot/get_bot_qrcode?bot_type=${encodeURIComponent(e)}`,r),i={"iLink-App-Id":ie};n&&(i.SKRouteTag=n);let a=await fetch(s.toString(),{headers:i});if(!a.ok){let o=await a.text().catch(()=>"(unreadable)");throw new Error(`Failed to fetch QR code: ${a.status} ${a.statusText} body=${o}`)}return await a.json()}async function pn(t,e,n){let r=t.endsWith("/")?t:`${t}/`,s=new URL(`ilink/bot/get_qrcode_status?qrcode=${encodeURIComponent(e)}`,r),i={"iLink-App-Id":ie,"iLink-App-ClientVersion":String(Me)};n&&(i.SKRouteTag=n);let a=new AbortController,o=setTimeout(()=>a.abort(),mn);try{let d=await fetch(s.toString(),{headers:i,signal:a.signal});clearTimeout(o);let c=await d.text();if(!d.ok)throw new Error(`Failed to poll QR status: ${d.status} ${d.statusText}`);return JSON.parse(c)}catch(d){if(clearTimeout(o),d instanceof Error&&d.name==="AbortError")return{status:"wait"};throw d}}async function at(t){let e=t.accountId||st();gn();let n=T.get(e);if(!t.force&&n&&Se(n)&&n.qrcodeUrl)return{qrcodeUrl:n.qrcodeUrl,message:"QR code ready. Scan with WeChat.",sessionKey:e};if(!t.apiBaseUrl)return{message:"No baseUrl configured for this WeChat channel.",sessionKey:e};try{let r=t.botType||rt,s=await it(t.apiBaseUrl,r,t.routeTag),i={sessionKey:e,id:st(),qrcode:s.qrcode,qrcodeUrl:s.qrcode_img_content,startedAt:Date.now()};return T.set(e,i),{qrcodeUrl:s.qrcode_img_content,message:"Scan the QR code with WeChat to connect.",sessionKey:e}}catch(r){return{message:`Failed to start login: ${String(r)}`,sessionKey:e}}}var fn=3;async function ot(t){let e=T.get(t.sessionKey);if(!e)return{connected:!1,message:"No active login session. Start QR login first."};if(!Se(e))return T.delete(t.sessionKey),{connected:!1,message:"QR code expired. Please start again."};let n=Math.max(t.timeoutMs??48e4,1e3),r=Date.now()+n,s=1;for(;Date.now()<r;){try{let i=await pn(t.apiBaseUrl,e.qrcode,t.routeTag);switch(e.status=i.status,i.status){case"wait":break;case"scaned":break;case"expired":{if(s++,s>fn)return T.delete(t.sessionKey),{connected:!1,message:"Login timeout: QR expired multiple times."};try{let a=t.botType||rt,o=await it(t.apiBaseUrl,a,t.routeTag);e.qrcode=o.qrcode,e.qrcodeUrl=o.qrcode_img_content,e.startedAt=Date.now()}catch(a){return T.delete(t.sessionKey),{connected:!1,message:`QR refresh failed: ${String(a)}`}}break}case"confirmed":return i.ilink_bot_id?(T.delete(t.sessionKey),{connected:!0,botToken:i.bot_token,accountId:i.ilink_bot_id,baseUrl:i.baseurl,userId:i.ilink_user_id,message:"Connected to WeChat successfully!"}):(T.delete(t.sessionKey),{connected:!1,message:"Login failed: server did not return bot ID."})}}catch(i){return T.delete(t.sessionKey),{connected:!1,message:`Login failed: ${String(i)}`}}await new Promise(i=>setTimeout(i,1e3))}return T.delete(t.sessionKey),{connected:!1,message:"Login timeout. Please try again."}}import A from"fs";import*as M from"fs/promises";import x from"path";import{homedir as pe}from"os";var de={IMAGE:1,VIDEO:2,FILE:3,VOICE:4},H={NONE:0,USER:1,BOT:2},_={NONE:0,TEXT:1,IMAGE:2,VOICE:3,FILE:4,VIDEO:5},K={NEW:0,GENERATING:1,FINISH:2},dt={TYPING:1,CANCEL:2};C();var hn=y("channels"),Ce=-14,ue=3600*1e3,$=new Map;function ut(t){let e=Date.now()+ue;$.set(t,e),hn.info({channelId:t},`Session paused until ${new Date(e).toISOString()} (${ue/1e3}s)`)}function ce(t){let e=$.get(t);return e===void 0?!1:Date.now()>=e?($.delete(t),!1):!0}function ct(t){let e=$.get(t);if(e===void 0)return 0;let n=e-Date.now();return n<=0?($.delete(t),0):n}function lt(t){$.delete(t)}C();import*as me from"fs/promises";import _t from"path";import{homedir as In}from"os";import{createCipheriv as yn,createDecipheriv as bn}from"crypto";function mt(t,e){let n=yn("aes-128-ecb",e,null);return Buffer.concat([n.update(t),n.final()])}function gt(t,e){let n=bn("aes-128-ecb",e,null);return Buffer.concat([n.update(t),n.final()])}function pt(t){return Math.ceil((t+1)/16)*16}function Ae(t,e){return`${e}/download?encrypted_query_param=${encodeURIComponent(t)}`}function ft(t){return`${t.cdnBaseUrl}/upload?encrypted_query_param=${encodeURIComponent(t.uploadParam)}&filekey=${encodeURIComponent(t.filekey)}`}C();var Ws=y("channels");function wn(t){let e=Buffer.from(t,"base64");if(e.length===16)return e;if(e.length===32&&/^[0-9a-fA-F]{32}$/.test(e.toString("ascii")))return Buffer.from(e.toString("ascii"),"hex");throw new Error(`aes_key must decode to 16 raw bytes or 32-char hex, got ${e.length} bytes`)}async function ht(t){let e=await fetch(t);if(!e.ok)throw new Error(`CDN download ${e.status} ${e.statusText}`);return Buffer.from(await e.arrayBuffer())}async function X(t){let{encryptQueryParam:e,aesKeyBase64:n,cdnBaseUrl:r,fullUrl:s}=t,i=wn(n),a=s?.trim()||(e?Ae(e,r):null);if(!a)throw new Error("CDN download: need full_url or encrypt_query_param");let o=await ht(a);return gt(o,i)}async function yt(t){let{encryptQueryParam:e,cdnBaseUrl:n,fullUrl:r}=t,s=r?.trim()||(e?Ae(e,n):null);if(!s)throw new Error("CDN download: need full_url or encrypt_query_param");return ht(s)}C();var le=y("channels"),bt=24e3;function _n(t,e){let n=t.byteLength,r=44+n,s=Buffer.allocUnsafe(r),i=0;return s.write("RIFF",i),i+=4,s.writeUInt32LE(r-8,i),i+=4,s.write("WAVE",i),i+=4,s.write("fmt ",i),i+=4,s.writeUInt32LE(16,i),i+=4,s.writeUInt16LE(1,i),i+=2,s.writeUInt16LE(1,i),i+=2,s.writeUInt32LE(e,i),i+=4,s.writeUInt32LE(e*2,i),i+=4,s.writeUInt16LE(2,i),i+=2,s.writeUInt16LE(16,i),i+=2,s.write("data",i),i+=4,s.writeUInt32LE(n,i),i+=4,Buffer.from(t.buffer,t.byteOffset,t.byteLength).copy(s,i),s}async function wt(t){try{let{decode:e}=await import("silk-wasm");le.debug(`silkToWav: decoding ${t.length} bytes of SILK`);let n=await e(t,bt);le.debug(`silkToWav: decoded duration=${n.duration}ms pcmBytes=${n.data.byteLength}`);let r=_n(n.data,bt);return le.debug(`silkToWav: WAV size=${r.length}`),r}catch(e){return le.warn(`silkToWav: transcode failed, will use raw silk err=${String(e)}`),null}}var N=y("channels"),It=100*1024*1024;function En(t){return re(t)??".bin"}async function J(t,e,n,r,s=It,i){if(t.length>s)throw new Error(`Media too large: ${t.length} bytes exceeds ${s} bytes`);let a=_t.join(In(),".adam","wechat","media",r,n);await me.mkdir(a,{recursive:!0});let o;if(i&&/^[a-zA-Z0-9._-]+$/.test(i))o=i;else{let c=e?En(e):".bin",u=Date.now(),p=Math.random().toString(36).slice(2,7);o=`${u}-${p}${c}`}let d=_t.join(a,o);return await me.writeFile(d,t),N.debug(`saveMedia: saved ${t.length} bytes to ${d}`),d}async function Et(t,e){let{cdnBaseUrl:n,channelId:r}=e;if(t.type===_.IMAGE){let s=t.image_item;if(!s?.media?.encrypt_query_param&&!s?.media?.full_url)return null;let i=s.aeskey?Buffer.from(s.aeskey,"hex").toString("base64"):s.media?.aes_key;try{let a=i?await X({encryptQueryParam:s.media?.encrypt_query_param,aesKeyBase64:i,cdnBaseUrl:n,fullUrl:s.media?.full_url}):await yt({encryptQueryParam:s.media?.encrypt_query_param,cdnBaseUrl:n,fullUrl:s.media?.full_url});return{path:await J(a,"image/png","inbound",r),mimeType:"image/png",type:"image"}}catch(a){return N.error({channelId:r},`Image download/decrypt failed: ${String(a)}`),null}}if(t.type===_.VOICE){let s=t.voice_item;if(!s?.media?.encrypt_query_param&&!s?.media?.full_url||!s?.media?.aes_key)return null;try{let i=await X({encryptQueryParam:s.media.encrypt_query_param,aesKeyBase64:s.media.aes_key,cdnBaseUrl:n,fullUrl:s.media.full_url}),a=await wt(i);if(a){let o=await J(a,"audio/wav","inbound",r);return N.debug(`Voice: saved WAV to ${o}`),{path:o,mimeType:"audio/wav",type:"audio"}}else{let o=await J(i,"audio/silk","inbound",r);return N.debug(`Voice: silk transcode unavailable, saved raw SILK to ${o}`),{path:o,mimeType:"audio/silk",type:"audio"}}}catch(i){return N.error({channelId:r},`Voice download/transcode failed: ${String(i)}`),null}}if(t.type===_.FILE){let s=t.file_item;if(!s?.media?.encrypt_query_param&&!s?.media?.full_url||!s?.media?.aes_key)return null;try{let i=await X({encryptQueryParam:s.media.encrypt_query_param,aesKeyBase64:s.media.aes_key,cdnBaseUrl:n,fullUrl:s.media.full_url}),a=se(s.file_name??"file.bin");return{path:await J(i,a,"inbound",r,It,s.file_name),mimeType:a,type:"file"}}catch(i){return N.error({channelId:r},`File download failed: ${String(i)}`),null}}if(t.type===_.VIDEO){let s=t.video_item;if(!s?.media?.encrypt_query_param&&!s?.media?.full_url||!s?.media?.aes_key)return null;try{let i=await X({encryptQueryParam:s.media.encrypt_query_param,aesKeyBase64:s.media.aes_key,cdnBaseUrl:n,fullUrl:s.media.full_url});return{path:await J(i,"video/mp4","inbound",r),mimeType:"video/mp4",type:"video"}}catch(i){return N.error({channelId:r},`Video download failed: ${String(i)}`),null}}return null}import Mt from"path";import Re from"crypto";import Tn from"fs/promises";C();var O=y("channels"),ge=3;async function xn(t){let{buf:e,uploadFullUrl:n,uploadParam:r,filekey:s,cdnBaseUrl:i,label:a,aeskey:o}=t,d=mt(e,o),c=n?.trim(),u;if(c)u=c;else if(r)u=ft({cdnBaseUrl:i,uploadParam:r,filekey:s});else throw new Error(`${a}: CDN upload URL missing (need upload_full_url or upload_param)`);O.debug(`${a}: CDN POST url=${u} ciphertextSize=${d.length}`);let p,f;for(let m=1;m<=ge;m++)try{let l=await fetch(u,{method:"POST",headers:{"Content-Type":"application/octet-stream"},body:new Uint8Array(d)});if(l.status>=400&&l.status<500){let b=l.headers.get("x-error-message")??await l.text();throw O.error(`${a}: CDN client error attempt=${m} status=${l.status} errMsg=${b}`),new Error(`CDN upload client error ${l.status}: ${b}`)}if(l.status!==200){let b=l.headers.get("x-error-message")??`status ${l.status}`;throw O.error(`${a}: CDN server error attempt=${m} status=${l.status} errMsg=${b}`),new Error(`CDN upload server error: ${b}`)}if(p=l.headers.get("x-encrypted-param")??void 0,!p)throw O.error(`${a}: CDN response missing x-encrypted-param header attempt=${m}`),new Error("CDN upload response missing x-encrypted-param header");O.debug(`${a}: CDN upload success attempt=${m}`);break}catch(l){if(f=l,l instanceof Error&&l.message.includes("client error"))throw l;m<ge?O.warn(`${a}: attempt ${m} failed, retrying... err=${String(l)}`):O.error(`${a}: all ${ge} attempts failed err=${String(l)}`)}if(!p)throw f instanceof Error?f:new Error(`CDN upload failed after ${ge} attempts`);return{downloadParam:p}}async function ke(t){let{filePath:e,toUserId:n,opts:r,cdnBaseUrl:s,mediaType:i,label:a}=t,o=await Tn.readFile(e),d=o.length,c=Re.createHash("md5").update(o).digest("hex"),u=pt(d),p=Re.randomBytes(16).toString("hex"),f=Re.randomBytes(16);O.debug(`${a}: file=${e} rawsize=${d} filesize=${u} md5=${c} filekey=${p}`);let m=await nt({...r,filekey:p,media_type:i,to_user_id:n,rawsize:d,rawfilemd5:c,filesize:u,no_need_thumb:!0,aeskey:f.toString("hex")}),l=m.upload_full_url?.trim(),b=m.upload_param;if(!l&&!b)throw new Error(`${a}: getUploadUrl returned no upload URL (need upload_full_url or upload_param)`);let{downloadParam:L}=await xn({buf:o,uploadFullUrl:l||void 0,uploadParam:b??void 0,filekey:p,cdnBaseUrl:s,aeskey:f,label:`${a}[orig filekey=${p}]`});return{filekey:p,downloadEncryptedQueryParam:L,aeskey:f.toString("hex"),fileSize:d,fileSizeCiphertext:u}}async function Tt(t){return ke({...t,mediaType:de.IMAGE,label:"uploadImageToWeixin"})}async function xt(t){return ke({...t,mediaType:de.VIDEO,label:"uploadVideoToWeixin"})}async function Pe(t){return ke({...t,mediaType:de.FILE,label:"uploadFileAttachmentToWeixin"})}C();var Y=y("channels");function Mn(){return`adam-wechat-${Date.now()}-${Math.random().toString(36).slice(2,7)}`}function Sn(t){let e=t;return e=e.replace(/```[^\n]*\n?([\s\S]*?)```/g,(n,r)=>r.trim()),e=e.replace(/!\[[^\]]*\]\([^)]*\)/g,""),e=e.replace(/\[([^\]]+)\]\([^)]*\)/g,"$1"),e=e.replace(/^\|[\s:|-]+\|$/gm,""),e=e.replace(/^\|(.+)\|$/gm,(n,r)=>r.split("|").map(s=>s.trim()).join(" ")),e}async function Ue(t){let{to:e,text:n,mediaItem:r,opts:s,label:i}=t,a=[],o=Sn(n);o&&a.push({type:_.TEXT,text_item:{text:o}}),a.push(r);let d="";for(let c of a){d=Mn();let u={msg:{from_user_id:"",to_user_id:e,client_id:d,message_type:H.BOT,message_state:K.FINISH,item_list:[c],context_token:s.contextToken}};await Q({baseUrl:s.baseUrl,token:s.token,routeTag:s.routeTag,body:u})}return Y.debug(`${i}: sent to=${e} messageId=${d}`),{messageId:d}}async function Cn(t){let{to:e,text:n,uploaded:r,opts:s}=t,i={type:_.IMAGE,image_item:{media:{encrypt_query_param:r.downloadEncryptedQueryParam,aes_key:Buffer.from(r.aeskey).toString("base64"),encrypt_type:1},mid_size:r.fileSizeCiphertext}};return Ue({to:e,text:n,mediaItem:i,opts:s,label:"sendImageMessage"})}async function An(t){let{to:e,text:n,uploaded:r,opts:s}=t,i={type:_.VIDEO,video_item:{media:{encrypt_query_param:r.downloadEncryptedQueryParam,aes_key:Buffer.from(r.aeskey).toString("base64"),encrypt_type:1},video_size:r.fileSizeCiphertext}};return Ue({to:e,text:n,mediaItem:i,opts:s,label:"sendVideoMessage"})}async function St(t){let{to:e,text:n,fileName:r,uploaded:s,opts:i}=t,a={type:_.FILE,file_item:{media:{encrypt_query_param:s.downloadEncryptedQueryParam,aes_key:Buffer.from(s.aeskey).toString("base64"),encrypt_type:1},file_name:r,len:String(s.fileSize)}};return Ue({to:e,text:n,mediaItem:a,opts:i,label:"sendFileMessage"})}async function Ct(t){let{filePath:e,to:n,text:r,opts:s,cdnBaseUrl:i}=t,a=se(e),o={baseUrl:s.baseUrl,token:s.token,routeTag:s.routeTag};if(a.startsWith("video/")){Y.debug(`sendWeixinMediaFile: uploading video filePath=${e} to=${n}`);let u=await xt({filePath:e,toUserId:n,opts:o,cdnBaseUrl:i});return An({to:n,text:r,uploaded:u,opts:s})}if(a.startsWith("image/")){Y.debug(`sendWeixinMediaFile: uploading image filePath=${e} to=${n}`);let u=await Tt({filePath:e,toUserId:n,opts:o,cdnBaseUrl:i});return Cn({to:n,text:r,uploaded:u,opts:s})}if(a.startsWith("audio/")){let u=Mt.basename(e);Y.debug(`sendWeixinMediaFile: uploading audio as file filePath=${e} name=${u} to=${n}`);let p=await Pe({filePath:e,fileName:u,toUserId:n,opts:o,cdnBaseUrl:i});return St({to:n,text:r,fileName:u,uploaded:p,opts:s})}let d=Mt.basename(e);Y.debug(`sendWeixinMediaFile: uploading file attachment filePath=${e} name=${d} to=${n}`);let c=await Pe({filePath:e,fileName:d,toUserId:n,opts:o,cdnBaseUrl:i});return St({to:n,text:r,fileName:d,uploaded:c,opts:s})}C();var h=y("channels"),At="https://novac2c.cdn.weixin.qq.com/c2c",Ne=new Map;function Pt(t){return x.join(pe(),".adam","wechat",`${t}.context-tokens.json`)}function Rn(t){let e=Pt(t);try{let n=A.readFileSync(e,"utf-8"),r=JSON.parse(n);for(let[s,i]of Object.entries(r))typeof i=="string"&&i&&Ne.set(`${t}:${s}`,i);h.debug({channelId:t,count:Object.keys(r).length},"Restored context tokens from disk")}catch{}}function kn(t,e,n){let r=Pt(t);try{let s={};try{let a=A.readFileSync(r,"utf-8");s=JSON.parse(a)}catch{}s[e]=n;let i=x.dirname(r);A.mkdirSync(i,{recursive:!0}),A.writeFileSync(r,JSON.stringify(s),"utf-8")}catch(s){h.warn({channelId:t,userId:e},`Failed to persist context token: ${String(s)}`)}}function Pn(t,e,n){Ne.set(`${t}:${e}`,n),kn(t,e,n)}function ve(t,e){return Ne.get(`${t}:${e}`)}function Ut(t){return x.join(pe(),".adam","wechat",`${t}.sync`)}function Un(t){try{return A.readFileSync(Ut(t),"utf-8")}catch{return""}}function vn(t,e){let n=Ut(t);A.mkdirSync(x.dirname(n),{recursive:!0}),A.writeFileSync(n,e,"utf-8")}var Oe=1440*60*1e3,Rt=10,On=20,kt=1440*60*1e3,Nn=1320*60*1e3,Dn=1,Ln=7200*1e3;function vt(t){return x.join(pe(),".adam","wechat",`${t}.session.json`)}function Fn(t){let e=new Map,n=vt(t);try{let r=A.readFileSync(n,"utf-8"),s=JSON.parse(r);for(let[i,a]of Object.entries(s))a&&typeof a.lastUserMessageAt=="number"&&e.set(i,a);h.debug({channelId:t,count:e.size},"Restored sessions from disk")}catch{}return e}function Z(t,e){let n=vt(t);try{let r={};for(let[i,a]of e)r[i]=a;let s=x.dirname(n);A.mkdirSync(s,{recursive:!0}),A.writeFileSync(n,JSON.stringify(r),"utf-8")}catch(r){h.warn({channelId:t},`Failed to persist sessions: ${String(r)}`)}}var Bn=0;function ee(){return`adam-wechat-${Date.now()}-${++Bn}`}var q=class{platform="wechat";id;config;status="disconnected";messageHandler=null;pollAbort=null;getUpdatesBuf="";sessions=new Map;pendingQueue=new Map;lastReminderAt=new Map;constructor(e,n){if(this.id=e,!n.baseUrl)throw new Error("WeChat adapter requires baseUrl");this.config=n}async connect(){if(!this.config.botToken)throw new Error("WeChat adapter requires botToken. Complete QR login first.");this.status="connecting",this.getUpdatesBuf=Un(this.id),Rn(this.id),this.sessions=Fn(this.id),this.pollAbort=new AbortController,this.status="connected",h.info({channelId:this.id},"WeChat adapter connected, starting long-poll"),this.startLongPoll()}async disconnect(){this.pollAbort&&(this.pollAbort.abort(),this.pollAbort=null),this.status="disconnected",h.info({channelId:this.id},"WeChat adapter disconnected")}getStatus(){if(this.status==="connected"&&ce(this.id))return"error";if(this.status==="connected"){for(let[,e]of this.sessions)if(this.isSessionActive(e)&&e.quotaRemaining<=0)return"degraded"}return this.status}getCapabilities(){return{canEdit:!1,canQuote:!0,canParseQuote:!0,canInlineButtons:!1,maxTextLength:4e3,supportsAttachments:!0,maxAttachmentsPerMessage:1}}async sendMessage(e,n){if(ce(this.id)){let c=Math.ceil(ct(this.id)/6e4);throw new Error(`WeChat session paused, ${c} min remaining. Re-scan QR to reconnect.`)}let r=this.getOrCreateSession(e),i=this.getSessionRemainingMs(r)/36e5;if(!this.isSessionActive(r))return h.warn({channelId:this.id,chatId:e.slice(0,12),lastUserMessageAt:r.lastUserMessageAt,sessionExpired:!0},"iLink session expired (>24h), message queued"),this.enqueueMessage(e,n),`queued-${ee()}`;if(r.quotaRemaining<=0)return h.warn({channelId:this.id,chatId:e.slice(0,12),quotaRemaining:0,remainingHours:i.toFixed(1)},"iLink quota exhausted, message queued"),this.enqueueMessage(e,n),`queued-${ee()}`;let a=ee(),o=ve(this.id,e),d=this.config.cdnBaseUrl??At;try{let c=n.attachments?.[0],u=c?.path??n.mediaUrl,p=c?.contentType,f=c?.filename,m=c?.mediaType??n.mediaType;if(u){let l=!u.includes("://")||u.startsWith("file://"),b=x.join(pe(),".adam","wechat","media","outbound-tmp");await M.mkdir(b,{recursive:!0});let L=this.getExtensionFromMediaType(m,p),R;if(l){let I=u.startsWith("file://")?new URL(u).pathname:x.isAbsolute(u)?u:x.resolve(u),v=await M.readFile(I);R=x.join(b,`${Date.now()}-${Math.random().toString(36).slice(2,7)}${L}`),await M.writeFile(R,v)}else{let I=await fetch(u);if(!I.ok)throw new Error(`Failed to fetch media: ${I.status}`);let v=Buffer.from(await I.arrayBuffer());R=x.join(b,`${Date.now()}-${Math.random().toString(36).slice(2,7)}${L}`),await M.writeFile(R,v)}let w=R;if(f){let I=f.replace(/[\\/]/g,"-").replace(/\.\./g,"-").replace(/[\x00-\x1f]/g,"");if(I.length>0&&I.length<200){let v=x.join(b,`${Date.now()}-${I}`);await M.copyFile(R,v),await M.unlink(R).catch(()=>{}),w=v}}let U=await Ct({filePath:w,to:e,text:n.content??"",opts:{baseUrl:this.config.baseUrl,token:this.config.botToken,routeTag:this.config.routeTag,contextToken:o},cdnBaseUrl:d});return await M.unlink(w).catch(()=>{}),r.quotaRemaining--,Z(this.id,this.sessions),h.info({channelId:this.id,chatId:e.slice(0,12),quotaRemaining:r.quotaRemaining,sessionRemainingHours:(this.getSessionRemainingMs(r)/36e5).toFixed(1)},"iLink send success: quota decremented"),this.checkAndSendReminder(e,r).catch(I=>{h.warn({channelId:this.id,chatId:e.slice(0,12)},`Reminder send failed: ${String(I)}`)}),U.messageId}return await Q({baseUrl:this.config.baseUrl,token:this.config.botToken,routeTag:this.config.routeTag,body:{msg:{from_user_id:"",to_user_id:e,client_id:a,message_type:H.BOT,message_state:K.FINISH,item_list:this.buildItemList(n),context_token:o}}}),r.quotaRemaining--,Z(this.id,this.sessions),h.info({channelId:this.id,chatId:e.slice(0,12),quotaRemaining:r.quotaRemaining,sessionRemainingHours:(this.getSessionRemainingMs(r)/36e5).toFixed(1)},"iLink send success: quota decremented"),this.checkAndSendReminder(e,r).catch(l=>{h.warn({channelId:this.id,chatId:e.slice(0,12)},`Reminder send failed: ${String(l)}`)}),a}catch(c){if(c instanceof Error&&c.message.includes("ret=-2"))return r.quotaRemaining=0,Z(this.id,this.sessions),h.warn({channelId:this.id,chatId:e.slice(0,12),quotaRemaining:0},"iLink quota exhausted (ret=-2 confirmed), message queued"),this.enqueueMessage(e,n),`queued-${ee()}`;throw c}}onMessage(e){this.messageHandler=e}async sendTypingIndicator(e){if(ce(this.id))return;let n=ve(this.id,e);try{await tt({baseUrl:this.config.baseUrl,token:this.config.botToken,routeTag:this.config.routeTag,body:{ilink_user_id:e,status:dt.TYPING}})}catch{}}updateConfig(e){Object.assign(this.config,e)}buildItemList(e){if(!e.content)return;let n={type:_.TEXT,text_item:{text:e.content}};if(e.replyToMessageId){let r=(e.quoteExcerpt??"").slice(0,80);n.ref_msg={message_item:{msg_id:e.replyToMessageId,text_item:{text:r}},title:e.quoteTitle}}return[n]}getOrCreateSession(e){let n=this.sessions.get(e);return n||(n={lastUserMessageAt:0,quotaRemaining:0},this.sessions.set(e,n)),n}isSessionActive(e){return e.lastUserMessageAt>0&&Date.now()-e.lastUserMessageAt<=Oe}getSessionRemainingMs(e){return e.lastUserMessageAt===0?0:Math.max(0,Oe-(Date.now()-e.lastUserMessageAt))}enqueueMessage(e,n){let r=this.pendingQueue.get(e);r||(r=[],this.pendingQueue.set(e,r));let s=Date.now();r=r.filter(i=>s-i.queuedAt<kt),r.length>=On&&(r.shift(),h.warn({channelId:this.id,chatId:e.slice(0,12)},"Queue full, dropping oldest message")),r.push({message:n,queuedAt:s}),this.pendingQueue.set(e,r),h.info({channelId:this.id,chatId:e.slice(0,12),queueDepth:r.length},"Message enqueued")}async flushQueue(e){let n=this.pendingQueue.get(e);if(!n||n.length===0)return;let r=this.getOrCreateSession(e),s=Math.min(n.length,Math.max(0,r.quotaRemaining-2));if(s<=0){h.info({channelId:this.id,chatId:e.slice(0,12),quotaRemaining:r.quotaRemaining},"Queue flush skipped: insufficient quota (reserving 2 for conversation)");return}h.info({channelId:this.id,chatId:e.slice(0,12),queueDepth:n.length,sending:s,quotaRemaining:r.quotaRemaining},"Flushing queued messages");let i=0;for(;i<s&&n.length>0;){let a=n[0];if(Date.now()-a.queuedAt>kt){n.shift();continue}try{if(await this.sendMessage(e,a.message),n.shift(),i++,r.quotaRemaining<=0)break}catch{h.warn({channelId:this.id,chatId:e.slice(0,12)},"Queue flush: send failed, stopping");break}}n.length===0&&this.pendingQueue.delete(e),h.info({channelId:this.id,chatId:e.slice(0,12),sent:i,remaining:n.length},"Queue flush complete")}async checkAndSendReminder(e,n){let r=Date.now(),s=this.lastReminderAt.get(e)??0;if(r-s<Ln)return;let i=this.getSessionRemainingMs(n),o=r-n.lastUserMessageAt>=Nn,d=n.quotaRemaining<=Dn;if(!o&&!d)return;let c=(i/36e5).toFixed(1),u;o&&d?u=`[\u7CFB\u7EDF\u63D0\u9192] \u6D88\u606F\u7A97\u53E3\u5373\u5C06\u5173\u95ED\uFF08\u5269\u4F59${c}\u5C0F\u65F6/${n.quotaRemaining}\u6761\u914D\u989D\uFF09\u3002\u8BF7\u56DE\u590D\u4EFB\u610F\u6D88\u606F\u4EE5\u4FDD\u6301\u8FDE\u63A5\u3002`:o?u=`[\u7CFB\u7EDF\u63D0\u9192] \u6D88\u606F\u7A97\u53E3\u5373\u5C06\u5173\u95ED\uFF08\u5269\u4F59${c}\u5C0F\u65F6\uFF09\u3002\u8BF7\u56DE\u590D\u4EFB\u610F\u6D88\u606F\u4EE5\u4FDD\u6301\u8FDE\u63A5\u3002`:u=`[\u7CFB\u7EDF\u63D0\u9192] \u6D88\u606F\u914D\u989D\u5373\u5C06\u7528\u5B8C\uFF08\u5269\u4F59${n.quotaRemaining}\u6761\uFF09\u3002\u8BF7\u56DE\u590D\u4EFB\u610F\u6D88\u606F\u4EE5\u91CD\u7F6E\u914D\u989D\u3002`;let p=ve(this.id,e);try{await Q({baseUrl:this.config.baseUrl,token:this.config.botToken,routeTag:this.config.routeTag,body:{msg:{from_user_id:"",to_user_id:e,client_id:ee(),message_type:H.BOT,message_state:K.FINISH,item_list:[{type:_.TEXT,text_item:{text:u}}],context_token:p}}}),n.quotaRemaining--,this.lastReminderAt.set(e,r),Z(this.id,this.sessions),h.info({channelId:this.id,chatId:e.slice(0,12),remainingHours:c,quotaRemaining:n.quotaRemaining,trigger:o?"time":"quota"},"iLink session reminder sent")}catch(f){h.warn({channelId:this.id,chatId:e.slice(0,12)},`Reminder send failed: ${String(f)}`)}}async startLongPoll(){let e=this.pollAbort?.signal,n=0,r=3,s=3e4,i=2e3;for(;!e?.aborted;)try{let a=await et({baseUrl:this.config.baseUrl,token:this.config.botToken,routeTag:this.config.routeTag,get_updates_buf:this.getUpdatesBuf});if(a.ret===Ce||a.errcode===Ce){ut(this.id),this.status="error",h.error({channelId:this.id},"Session expired (errcode=-14), pausing for 1 hour"),await this.sleep(ue,e),lt(this.id),this.status="connected";continue}if(a.ret!==void 0&&a.ret!==0||a.errcode!==void 0&&a.errcode!==0){n++,h.error({channelId:this.id,ret:a.ret,errcode:a.errcode},"getUpdates API error"),n>=r?(n=0,await this.sleep(s,e)):await this.sleep(i,e);continue}n=0,a.get_updates_buf&&(this.getUpdatesBuf=a.get_updates_buf,vn(this.id,a.get_updates_buf));for(let d of a.msgs??[])await this.processInbound(d)}catch(a){if(e?.aborted)return;n++,h.error({channelId:this.id,error:a},"getUpdates error"),n>=r?(n=0,await this.sleep(s,e)):await this.sleep(i,e)}}async processInbound(e){if(!this.messageHandler)return;let n=!!e.group_id,r=n?e.group_id:e.from_user_id??"",s=e.from_user_id??"";e.context_token&&r&&Pn(this.id,r,e.context_token);let i=this.getOrCreateSession(r),a=i.quotaRemaining;i.lastUserMessageAt=Date.now(),i.quotaRemaining=Rt,Z(this.id,this.sessions),h.info({channelId:this.id,chatId:r.slice(0,12),quotaReset:!0,prevQuota:a,newQuota:Rt,sessionWindowMs:Oe},"iLink session reset: user message received, quota restored"),this.flushQueue(r);let o="",d,c=[],u;for(let m of e.item_list??[]){let l=m.ref_msg?.message_item?.msg_id;if(l){u=l;break}}for(let m of e.item_list??[])m.type===_.TEXT&&m.text_item?.text&&(o+=m.text_item.text),m.type===_.IMAGE&&(d="image",c.push(m)),m.type===_.VOICE&&(d="audio",c.push(m),m.voice_item?.text&&!o&&(o=m.voice_item.text)),m.type===_.FILE&&(d="file",c.push(m)),m.type===_.VIDEO&&(d="video",c.push(m));if(!o&&!d)return;let p;if(c.length>0){let m=this.config.cdnBaseUrl??At;try{let l=await Et(c[0],{cdnBaseUrl:m,channelId:this.id});l&&(p=l.path,d=l.type)}catch(l){h.error({channelId:this.id},`Media download failed: ${String(l)}`)}}let f={channelId:this.id,platform:"wechat",chatId:r,senderId:s,content:o,mediaType:d,mediaPath:p,isGroup:n,timestamp:e.create_time_ms??Date.now(),raw:e,...u?{quotedPlatformMessageId:u}:{}};this.messageHandler(f)}getExtensionFromMediaType(e,n){if(n){let r=re(n);if(r&&r!==".bin")return r}switch(e){case"image":return".png";case"video":return".mp4";case"audio":return".mp3";default:return".bin"}}sleep(e,n){return new Promise((r,s)=>{let i=setTimeout(r,e);n?.addEventListener("abort",()=>{clearTimeout(i),s(new Error("aborted"))},{once:!0})})}};C();C();var $n=y("channels"),fe=class{platform="discord";id;config;status="disconnected";messageHandler=null;client=null;constructor(e,n){if(this.id=e,!n.botToken)throw new Error("Discord adapter requires botToken");this.config=n}async connect(){this.status="connecting";try{let{Client:e,GatewayIntentBits:n}=await import("discord.js");this.client=new e({intents:[n.Guilds,n.GuildMessages,n.MessageContent,n.DirectMessages]});let r=this.client;r.on("messageCreate",s=>{if(!this.messageHandler||s.author.bot||this.config.allowedGuildIds?.length&&s.guildId&&!this.config.allowedGuildIds.includes(s.guildId))return;let i={channelId:this.id,platform:"discord",chatId:s.channelId,senderId:s.author.id,senderName:s.author.displayName??s.author.username,content:s.content,isGroup:!!s.guildId,timestamp:s.createdTimestamp,raw:s};this.messageHandler(i)}),await r.login(this.config.botToken),this.status="connected",$n.info({channelId:this.id},"Discord bot connected")}catch(e){throw this.status="error",e}}async disconnect(){this.client&&await this.client.destroy(),this.client=null,this.status="disconnected"}getStatus(){return this.status}getCapabilities(){return{canEdit:!0,canQuote:!0,canParseQuote:!0,canInlineButtons:!0,maxTextLength:2e3,supportsAttachments:!0}}async sendMessage(e,n){if(!this.client)throw new Error("Discord client not connected");let s=await this.client.channels.fetch(e);if(!s||!("send"in s))throw new Error(`Channel ${e} not found or not text channel`);return(await s.send({content:n.content,reply:n.replyToMessageId?{messageReference:n.replyToMessageId}:void 0})).id}onMessage(e){this.messageHandler=e}async sendTypingIndicator(e){if(!this.client)return;let r=await this.client.channels.fetch(e);r&&"sendTyping"in r&&await r.sendTyping()}};import{statSync as es}from"fs";import{ImapFlow as ts}from"imapflow";import ns from"nodemailer";import{existsSync as qn,mkdirSync as Gn,readFileSync as Wn,writeFileSync as jn}from"fs";import{dirname as Vn,join as Ot}from"path";import{homedir as zn}from"os";var Qn={lastUid:0,seenMessageIds:[],sentMessageIds:[],updatedAt:0};function De(t=process.env.ADAM_TEST_DIR??Ot(zn(),".adam")){return Ot(t,"email-gateway","state.json")}function he(t=De()){if(!qn(t))return{...Qn};let e=JSON.parse(Wn(t,"utf-8"));return{uidValidity:e.uidValidity,lastUid:Number.isInteger(e.lastUid)?e.lastUid:0,seenMessageIds:Array.isArray(e.seenMessageIds)?e.seenMessageIds.filter(Nt):[],sentMessageIds:Array.isArray(e.sentMessageIds)?e.sentMessageIds.filter(Nt):[],updatedAt:typeof e.updatedAt=="number"?e.updatedAt:0}}function te(t,e=De()){Gn(Vn(e),{recursive:!0}),jn(e,JSON.stringify({...t,updatedAt:Date.now()},null,2),"utf-8")}function Dt(t,e){let n=G(e);return n?{...t,seenMessageIds:t.seenMessageIds.includes(n)?t.seenMessageIds:[...t.seenMessageIds,n]}:t}function Hn(t,e){let n=G(e);return n?{...t,sentMessageIds:t.sentMessageIds.includes(n)?t.sentMessageIds:[...t.sentMessageIds,n]}:t}function Lt(t,e=De()){let n=Hn(he(e),t);return te(n,e),n}function G(t){return typeof t=="string"?t.trim():""}function Nt(t){return typeof t=="string"}import{Readable as Kn}from"stream";import{MailParser as Xn}from"mailparser";import{convert as Jn}from"html-to-text";async function Bt(t){let e=new Xn({skipImageLinks:!0,skipTextToHtml:!0}),n={},r,s,i,a=[],o,d="",c="",u="",p,f=0,m;if(await new Promise((L,R)=>{e.on("headers",w=>{try{for(let[I,v]of w.entries())n[I.toLowerCase()]=Zn(v);r=Ft(w.get("message-id")),o=Ft(w.get("subject")),u=Gt(w.get("content-type"))??"";let U=w.get("date");U instanceof Date&&(p=U.getTime()),s=$t(w.get("from"),"from"),i=Yn(w.get("reply-to"),"reply-to"),a=qt(w.get("to"))}catch(U){m=U instanceof Error?U:new Error(String(U))}}),e.on("data",w=>{if(w.type==="attachment"){f+=1,w.release?.(),w.content?.resume?.();return}d=w.text??"",c=typeof w.html=="string"?w.html:""}),e.on("error",R),e.on("end",L),Kn.from([t]).pipe(e)}),m)throw m;if(!s)throw new Error("Inbound email must contain exactly one valid From address");let l=u.toLowerCase()==="text/html",b=d.trim();return(l||!b)&&c.trim()&&(b=Jn(c,{wordwrap:!1,selectors:[{selector:"h1",format:"heading",options:{uppercase:!1}},{selector:"h2",format:"heading",options:{uppercase:!1}},{selector:"h3",format:"heading",options:{uppercase:!1}},{selector:"h4",format:"heading",options:{uppercase:!1}},{selector:"h5",format:"heading",options:{uppercase:!1}},{selector:"h6",format:"heading",options:{uppercase:!1}}]}).trim()),!b&&o&&(b=o.trim()),{messageId:r,from:s,replyTo:i,to:a,subject:o,text:b,date:p,rawHeaders:n,attachmentCount:f}}function $t(t,e){let n=qt(t);if(n.length!==1){if(n.length===0)return;throw new Error(`Inbound email ${e} must contain exactly one mailbox address`)}return n[0]}function Yn(t,e){if(t)return $t(t,e)}function qt(t){return t?typeof t=="string"?[k(t)]:(t.value??[]).map(r=>r.address).filter(r=>typeof r=="string"&&r.trim().length>0).map(r=>k(r)):[]}function Ft(t){if(typeof t=="string")return t;if(Array.isArray(t))return t.map(String).join(", ")}function Zn(t){if(t instanceof Date)return t.toISOString();if(typeof t=="string")return t;if(Array.isArray(t))return t.map(String).join(", ");let e=Gt(t);return e||(t&&typeof t=="object"&&"text"in t?String(t.text??""):String(t??""))}function Gt(t){if(typeof t=="string")return t;if(t&&typeof t=="object"&&"value"in t){let e=t.value;if(typeof e=="string")return e}}var Wt=3e4,ss=5e3,rs=3e5,is=1.33,as=3e4;function os(t){if(!t||t.length===0)return Wt;let e=0;for(let r of t)try{e+=es(r.path).size}catch{}let n=e*is/(1024*1024);return Math.min(rs,Wt+Math.ceil(n*ss))}var Fe=class{imapClient;smtpTransporter;pollTimer;handlers=[];status={status:"stopped"};state=he();async start(e){if(await this.stop(),!e.enabled){this.status={status:"stopped",details:{reason:"disabled"}};return}this.status={status:"starting",lastStartedAt:Date.now()};try{this.imapClient=new ts({host:e.imap.host,port:e.imap.port,secure:e.imap.secure,auth:{user:e.imap.auth.user,pass:e.imap.auth.pass}}),await this.imapClient.connect();let n=await this.imapClient.mailboxOpen(e.imap.mailbox),r=n?.uidValidity?Number(n.uidValidity):void 0;r&&this.state.uidValidity&&r!==this.state.uidValidity?(this.state={...this.state,uidValidity:r,lastUid:0,seenMessageIds:[]},te(this.state)):r&&(this.state={...this.state,uidValidity:r},te(this.state)),this.smtpTransporter=ns.createTransport({host:e.smtp.host,port:e.smtp.port,secure:e.smtp.secure,auth:{user:e.smtp.auth.user,pass:e.smtp.auth.pass}}),await this.smtpTransporter.verify(),this.status={status:"connected",lastStartedAt:Date.now(),lastCheckedAt:Date.now()},this.schedulePoll(e)}catch(n){throw await this.cleanupResources(),this.status={status:"error",lastError:Be(n),details:{stage:this.smtpTransporter?"smtp":"imap"}},n}}async stop(){await this.cleanupResources(),this.status={status:"stopped"}}getStatus(){return{...this.status}}onInbound(e){this.handlers.push(e)}async send(e){if(!this.smtpTransporter)throw new Error("EmailGateway SMTP transporter is not started");let n=os(e.attachments),r=await ds(this.smtpTransporter.sendMail({from:e.from,to:e.to,subject:e.subject,text:e.text,html:e.html,attachments:e.attachments}),n,`SMTP send timed out after ${Math.round(n/1e3)}s`),s=G(r.messageId);if(!s)throw new Error("SMTP send returned no Message-ID");return this.state=Lt(s),s}isSentByAdam(e){let n=G(e);return n.length>0&&this.state.sentMessageIds.includes(n)}schedulePoll(e){this.pollTimer=setInterval(()=>{this.poll(e)},as)}async poll(e){if(this.imapClient)try{this.state=he();let n=`${this.state.lastUid+1}:*`,r=this.imapClient.fetch?.(n,{uid:!0,source:!0,envelope:!0},{uid:!0});if(!r||!r[Symbol.asyncIterator])return;let s=!1;for await(let i of r){let a=Number(i.uid);if(!Number.isInteger(a)||a<=this.state.lastUid)continue;if(!i.source){this.markDegraded(new Error(`IMAP fetch item ${a} is missing source`)),s=!0;break}let o;try{o=await Bt(i.source)}catch(u){this.markDegraded(u),s=!0;break}let d=o.rawHeaders["x-adam-probe-id"],c=G(o.messageId);if(d?.startsWith("adam-probe-")){this.advanceCursor(a);continue}if(c&&this.state.sentMessageIds.includes(c)){this.advanceCursor(a);continue}if(c&&this.state.seenMessageIds.includes(c)){this.advanceCursor(a);continue}try{await Promise.all(this.handlers.map(u=>u(o)))}catch(u){this.markDegraded(u),s=!0;break}this.state=Dt(this.state,c),this.advanceCursor(a)}s||(this.status={...this.status,status:"connected",lastCheckedAt:Date.now(),lastError:void 0})}catch(n){this.markDegraded(n)}}advanceCursor(e){this.state={...this.state,lastUid:e},te(this.state)}markDegraded(e){this.status={...this.status,status:"degraded",lastError:Be(e),lastCheckedAt:Date.now()}}async cleanupResources(){this.pollTimer&&(clearInterval(this.pollTimer),this.pollTimer=void 0);let e=this.imapClient,n=this.smtpTransporter;this.imapClient=void 0,this.smtpTransporter=void 0,e&&(await Le(e.logout?.()),await Le(e.close?.())),await Le(n?.close?.())}},jt;function S(){return jt??=new Fe,jt}async function ye(t){await S().start(t)}async function jr(t,e){await S().stop(),await S().start(t)}async function Vr(t){await S().stop()}async function ds(t,e,n){let r;try{return await Promise.race([t,new Promise((s,i)=>{r=setTimeout(()=>i(new Error(n)),e)})])}catch(s){throw new Error(Be(s))}finally{r&&clearTimeout(r)}}function Be(t){return t instanceof Error?t.message.replace(/pass(word)?=[^\s]+/gi,"password=****"):"Email gateway operation failed"}async function Le(t){t&&typeof t.then=="function"&&await t.catch(()=>{})}C();var ls=/\b55[234]\b/,ms=/(?:size|too large|exceeds|maximum|over.*?limit)/i,gs=/\b(\d{6,11})\b/,ps=/Final-Recipient:\s*rfc822;\s*([^\s>]+@([^\s>;]+))/i,fs=/To:[\s<]*([^\s>;]+@([^\s>;]+))/i;function Vt(t){let e=t.text??"",n=e.split(/\r?\n/).filter(a=>ls.test(a)&&ms.test(a));if(n.length===0)return null;let r=e.match(ps)??e.match(fs);if(!r)return null;let s=r[2].toLowerCase().trim();if(!je.test(s))return null;let i=null;for(let a of n){let o=a.match(gs);if(o){let d=parseInt(o[1],10);if(Number.isFinite(d)&&d>=1048576&&d<=209715200){i=d;break}}}return i===null?null:{recipientDomain:s,capBytes:i}}var be=y("channels"),zt=!1;function Qt(t){if(zt){be.debug("Bounce handler already registered; skipping duplicate registration");return}zt=!0,t.onInbound(async e=>{let n=Vt(e);if(!n){(/MAILER-DAEMON/i.test(e.from??"")||/Mail Delivery|Undeliverable|Returned mail|Delivery Status Notification/i.test(e.subject??""))&&be.warn({from:e.from,subject:e.subject},"Inbound looks like bounce but parser did not recognize a size-limit cap");return}let{recipientDomain:r,capBytes:s}=n;be.info({recipientDomain:r,capBytes:s},"Bounce-learning: detected SMTP size-limit bounce");let i=F().filter(a=>a.platform==="email");for(let a of i)try{ze(a.id,r,s)}catch(o){be.warn({channelId:a.id,recipientDomain:r,capBytes:s,err:o},"Bounce-learning: setRecipientCap failed (out of range or DB error); skipping")}})}C();var we=y("channels"),$e=class{constructor(e){this.gateway=e}gateway;adaptersByAddress=new Map;channelAddressById=new Map;registerAdapter(e,n){if(!He(e)||!e.enabled)return;let r=B(e);this.unregisterAdapter(e.id),this.adaptersByAddress.set(r,n),this.channelAddressById.set(e.id,r)}unregisterAdapter(e){let n=this.channelAddressById.get(e);n&&(this.adaptersByAddress.delete(n),this.channelAddressById.delete(e))}refreshFromChannels(e,n){this.adaptersByAddress.clear(),this.channelAddressById.clear();for(let r of e){let s=n.get(r.id);if(s)try{this.registerAdapter(r,s)}catch(i){we.warn({channelId:r.id,error:i},"Invalid email channel skipped during router refresh")}}}async handle(e){if(e.messageId&&this.gateway.isSentByAdam(e.messageId)){we.debug({messageId:e.messageId},"Skipping Adam-sent email");return}let n;try{n=k(e.from)}catch(s){we.warn({from:e.from,error:s},"Skipping email with invalid sender address");return}let r=this.adaptersByAddress.get(n);if(!r){we.info({from:n},"Skipping unmatched inbound email");return}await r.acceptInbound(e)}hasAddress(e){return this.adaptersByAddress.has(k(e))}},_e,Ht;function qe(t){return(!_e||Ht!==t)&&(_e=new $e(t),Ht=t,t.onInbound(e=>_e?.handle(e)??Promise.resolve())),_e}import{existsSync as hs}from"fs";import{basename as ys,isAbsolute as bs}from"path";function Kt(t){let e=[];return t.mediaUrl&&e.push({path:t.mediaUrl,mediaType:t.mediaType}),t.attachments&&e.push(...t.attachments),e.map(ws)}function ws(t){let e=t.path.startsWith("file://")?new URL(t.path).pathname:t.path;if(!bs(e)||e.includes("://"))throw new Error("Email attachment path must be an absolute local file path");if(!hs(e))throw new Error(`Email attachment file not found: ${e}`);return{filename:t.filename??ys(e),path:e,...t.contentType?{contentType:t.contentType}:t.mediaType?{contentType:_s(t.mediaType)}:{}}}function _s(t){return"application/octet-stream"}import Is from"markdown-it";var Es=new Is({html:!1,linkify:!0});function Xt(t){return{text:Xe(t),html:Es.render(t)}}function Jt(t){let e=t.prefix.trim()||"Adam";return t.messageType==="report"||t.messageType==="status_report"?`[${e} Report]`:t.messageType==="deliver"||t.messageType==="result_delivery"?`[${e} Deliver]`:`[${e}]`}var Ie=class{platform="email";id;channel;gateway;handler;inboundDispatchHandler;status="disconnected";identity;constructor(e,n,r={}){this.channel=e,this.gateway=n,this.id=e.id,this.identity=r}async connect(){let e=this.gateway.getStatus();this.status=Ee(e.status)}async disconnect(){this.status="disconnected"}getStatus(){return this.status}getCapabilities(){return{canEdit:!1,canQuote:!1,canParseQuote:!1,canInlineButtons:!1,maxTextLength:Number.POSITIVE_INFINITY,supportsAttachments:!0}}async sendMessage(e,n){let r=k(e),s=B(this.channel);if(r!==s)throw new Error("Email channel recipient does not match configured address");let i=Xt(n.content);return this.gateway.send({from:this.identity.from?Ke(this.identity.from,this.identity.displayName):void 0,to:r,subject:Jt({prefix:this.identity.subjectPrefix??"Adam",messageType:n.messageType??"reply"}),text:i.text,html:i.html,attachments:Kt(n)})}onMessage(e){this.handler=e}onInboundDispatch(e){this.inboundDispatchHandler=e}syncGatewayStatus(){this.status=Ee(this.gateway.getStatus().status)}async acceptInbound(e){let n=k(e.from),r={channelId:this.channel.id,platform:"email",chatId:n,senderId:n,senderName:e.from,content:e.text,replyToMessageId:e.messageId,isGroup:!1,timestamp:e.date??Date.now(),raw:{messageId:e.messageId,subject:e.subject,attachmentCount:e.attachmentCount,headers:e.rawHeaders}};this.handler?.(r),this.inboundDispatchHandler&&await this.inboundDispatchHandler(r)}};function Ee(t){switch(t){case"connected":return"connected";case"starting":return"connecting";case"degraded":case"error":return"degraded";case"stopped":return"disconnected";default:return"disconnected"}}var Yt=y("channels"),Ge=new Map;async function W(t,e){if(t.hasAdapter(e.id))return!0;if(e.platform==="wechat"){let n=e.config;return n.botToken?(await t.addChannel(e,new q(e.id,n)),!0):!1}if(e.platform==="discord"){let n=e.config;return n.botToken?(await t.addChannel(e,new fe(e.id,{botToken:n.botToken})),!0):!1}if(e.platform==="email"){B(e);let n=S(),r=V().emailGateway,s=new Ie(e,n,{from:r?.smtp?.from||r?.address,displayName:r?.displayName,subjectPrefix:r?.subjectPrefix??"Adam"});Ge.set(e.id,s),qe(n).registerAdapter(e,s);try{await Ts(),await t.addChannel(e,s)}catch(i){throw await j(t,e),i}return!0}return!1}async function Ei(t){for(let e of F(!0))try{await W(t,e)}catch(n){z(e.id,"error"),Yt.warn({channelId:e.id,platform:e.platform,error:n},"Failed to register built-in channel adapter")}}async function Zt(t,e){e.platform==="email"&&(await j(t,e),e.enabled&&await W(t,e))}async function en(t,e){await j(t,e)}async function j(t,e){e.platform==="email"&&(qe(S()).unregisterAdapter(e.id),Ge.delete(e.id),t?.hasAdapter(e.id)&&await t.removeChannel(e.id))}function Ti(t){for(let[e,n]of Ge.entries())n.syncGatewayStatus(),z(e,n.getStatus())}async function Ts(){let t=V().emailGateway;if(!t?.enabled)return;let e=S().getStatus().status;if(!(e!=="stopped"&&e!=="error"))try{await ye(t),Qt(S())}catch(n){Yt.warn({error:xs(n)},"EmailGateway start failed during built-in adapter registration")}}function xs(t){return t instanceof Error?t.message.replace(/pass(word)?=[^\s]+/gi,"password=****"):"Email gateway operation failed"}var P=g.object({id:g.string().uuid()}),Ss=g.object({name:g.string().min(1,"name is required"),platform:g.string().min(1,"platform is required"),config:g.record(g.string(),g.unknown()),enabled:g.boolean().optional().default(!0),linkedRoleId:g.string().optional(),allowedChatIds:g.array(g.string()).optional()}),Cs=g.object({name:g.string().min(1).optional(),enabled:g.boolean().optional(),config:g.record(g.string(),g.unknown()).optional(),linkedRoleId:g.string().optional(),allowedChatIds:g.array(g.string()).optional(),viewerKey:g.string().min(1).max(100).regex(/^[a-zA-Z0-9_.@:-]+$/,"viewerKey must be alphanumeric or one of _ . @ : -").optional(),defaultRecipientCapBytes:g.number().int().min(1048576).max(209715200).optional(),recipientCapMap:g.record(g.string().regex(/^[a-z0-9.-]+$/),g.number().int().min(1048576).max(209715200)).optional()}),We;function Li(t){We=t}function Fi(){return We}async function Bi(t){let e=We;async function n(r){Ve(r);try{return e&&r.enabled&&await W(e,r),r}catch(s){throw await j(e,r),Te(r.id),s}}t.get("/channels",{schema:{tags:["Channels"],summary:"List channels",querystring:{type:"object",properties:{enabled:{type:"boolean"}}}}},async(r,s)=>({channels:F(r.query.enabled)})),t.post("/channels",{schema:{tags:["Channels"],summary:"Create a channel",body:{type:"object",required:["name","platform","config"],properties:{name:{type:"string",minLength:1},platform:{type:"string",minLength:1},config:{type:"object"},enabled:{type:"boolean"},linkedRoleId:{type:"string"},allowedChatIds:{type:"array",items:{type:"string"}}}}}},async(r,s)=>{let i=Ss.safeParse(r.body);if(!i.success)return s.status(400).send({code:"VALIDATION_ERROR",message:g.prettifyError(i.error)});let{name:a,platform:o,config:d,enabled:c,linkedRoleId:u,allowedChatIds:p}=i.data,f=d;if(o==="email")try{f={...xe(d)}}catch(l){return s.status(400).send({code:"VALIDATION_ERROR",message:l instanceof Error?l.message:String(l)})}let m={id:Ms(),name:a,platform:o,enabled:c,status:"disconnected",config:f,linkedRoleId:u,allowedChatIds:p,viewerKey:Je(),createdAt:Date.now(),messageCount:0};try{await n(m)}catch(l){return s.status(400).send({code:"VALIDATION_ERROR",message:D(l)})}return s.status(201).send({channel:m})}),t.get("/channels/:id",{schema:{tags:["Channels"],summary:"Get channel by ID",params:{type:"object",required:["id"],properties:{id:{type:"string",format:"uuid"}}}}},async(r,s)=>{let i=P.safeParse(r.params);if(!i.success)return s.status(400).send({code:"VALIDATION_ERROR",message:g.prettifyError(i.error)});let a=E(i.data.id);return a?{channel:a}:s.status(404).send({code:"NOT_FOUND",message:"Channel not found"})}),t.patch("/channels/:id",{schema:{tags:["Channels"],summary:"Update channel",params:{type:"object",required:["id"],properties:{id:{type:"string",format:"uuid"}}},body:{type:"object",properties:{name:{type:"string"},enabled:{type:"boolean"},config:{type:"object"},linkedRoleId:{type:"string"},allowedChatIds:{type:"array",items:{type:"string"}},viewerKey:{type:"string",minLength:1,maxLength:100}}}}},async(r,s)=>{let i=P.safeParse(r.params);if(!i.success)return s.status(400).send({code:"VALIDATION_ERROR",message:g.prettifyError(i.error)});let a=E(i.data.id);if(!a)return s.status(404).send({code:"NOT_FOUND",message:"Channel not found"});let o=Cs.safeParse(r.body);if(!o.success)return s.status(400).send({code:"VALIDATION_ERROR",message:g.prettifyError(o.error)});let d={...o.data};if((a.platform==="email"||d.config)&&(d.config||a.config)){let p=d.config??a.config;if(a.platform==="email")try{d.config={...xe(p)}}catch(f){return s.status(400).send({code:"VALIDATION_ERROR",message:f instanceof Error?f.message:String(f)})}}let c=a.platform==="email"&&(d.enabled!==void 0||d.config!==void 0);ne(a.id,d);let u=E(a.id);if(e&&u&&c)try{await Zt(e,u)}catch(p){if(ne(a.id,{name:a.name,enabled:a.enabled,status:a.status,config:a.config,linkedRoleId:a.linkedRoleId,allowedChatIds:a.allowedChatIds,lastMessageAt:a.lastMessageAt,messageCount:a.messageCount}),await j(e,u),a.enabled)try{await W(e,a)}catch(f){return s.status(500).send({code:"RESTORE_FAILED",message:D(f)})}return s.status(400).send({code:"VALIDATION_ERROR",message:D(p)})}return{channel:u}}),t.delete("/channels/:id",{schema:{tags:["Channels"],summary:"Delete channel",params:{type:"object",required:["id"],properties:{id:{type:"string",format:"uuid"}}}}},async(r,s)=>{let i=P.safeParse(r.params);if(!i.success)return s.status(400).send({code:"VALIDATION_ERROR",message:g.prettifyError(i.error)});let a=E(i.data.id);if(!a)return s.status(404).send({code:"NOT_FOUND",message:"Channel not found"});if(Te(a.id),e)try{await en(e,a)}catch(o){t.log.warn({channelId:a.id,error:D(o)},"Failed to clean up built-in channel runtime")}return s.status(204).send()}),t.post("/channels/:id/connect",{schema:{tags:["Channels"],summary:"Connect channel",params:{type:"object",required:["id"],properties:{id:{type:"string",format:"uuid"}}}}},async(r,s)=>{let i=P.safeParse(r.params);if(!i.success)return s.status(400).send({code:"VALIDATION_ERROR",message:g.prettifyError(i.error)});if(!e)return s.status(501).send({code:"NOT_IMPLEMENTED",message:"Channel manager not initialized"});let a=E(i.data.id);if(!a)return s.status(404).send({code:"NOT_FOUND",message:"Channel not found"});if(a.platform==="email")try{await As()}catch(o){let d=S().getStatus();return z(a.id,Ee(d.status)),s.status(409).send({code:"EMAIL_GATEWAY_NOT_READY",message:D(o),gatewayStatus:d})}if(!e.hasAdapter(a.id))try{await W(e,a)}catch(o){return s.status(400).send({code:"VALIDATION_ERROR",message:D(o)})}if(!e.hasAdapter(a.id))return s.status(400).send({code:"NO_ADAPTER",message:"No adapter registered for this channel. Install the appropriate adapter first."});try{await e.connectChannel(a.id);let o=E(a.id)?.status??e.getChannelStatus(a.id);return o!=="connected"?s.status(409).send({code:"CONNECT_INCOMPLETE",message:`Channel connect finished with status "${o}"`,status:o}):{channelId:a.id,status:o}}catch(o){return s.status(500).send({code:"CONNECT_FAILED",message:D(o)})}}),t.post("/channels/:id/disconnect",{schema:{tags:["Channels"],summary:"Disconnect channel",params:{type:"object",required:["id"],properties:{id:{type:"string",format:"uuid"}}}}},async(r,s)=>{let i=P.safeParse(r.params);if(!i.success)return s.status(400).send({code:"VALIDATION_ERROR",message:g.prettifyError(i.error)});if(!e)return s.status(501).send({code:"NOT_IMPLEMENTED",message:"Channel manager not initialized"});let a=E(i.data.id);return a?(await e.disconnectChannel(a.id),{channelId:a.id,status:"disconnected"}):s.status(404).send({code:"NOT_FOUND",message:"Channel not found"})}),t.get("/channels/:id/capabilities",{schema:{tags:["Channels"],summary:"Get channel adapter capabilities",params:{type:"object",required:["id"],properties:{id:{type:"string",format:"uuid"}}}}},async(r,s)=>{let i=P.safeParse(r.params);if(!i.success)return s.status(400).send({code:"VALIDATION_ERROR",message:g.prettifyError(i.error)});if(!E(i.data.id))return s.status(404).send({code:"NOT_FOUND",message:"Channel not found"});if(!e)return s.status(503).send({code:"MANAGER_UNAVAILABLE",message:"ChannelManager not initialized"});let o=e.getCapabilities(i.data.id);return o?{capabilities:o}:s.status(404).send({code:"ADAPTER_NOT_REGISTERED",message:"Channel adapter not active"})}),t.get("/channels/:id/messages",{schema:{tags:["Channels"],summary:"Get channel message history",params:{type:"object",required:["id"],properties:{id:{type:"string",format:"uuid"}}},querystring:{type:"object",properties:{limit:{type:"integer",minimum:1,maximum:200,default:50},offset:{type:"integer",minimum:0,default:0}}}}},async(r,s)=>{let i=P.safeParse(r.params);if(!i.success)return s.status(400).send({code:"VALIDATION_ERROR",message:g.prettifyError(i.error)});let a=E(i.data.id);if(!a)return s.status(404).send({code:"NOT_FOUND",message:"Channel not found"});let{limit:o=50,offset:d=0}=r.query;return{messages:Qe(a.id,o,d)}}),t.post("/channels/:id/wechat/qr-start",{schema:{tags:["WeChat"],summary:"Start WeChat QR login",params:{type:"object",required:["id"],properties:{id:{type:"string",format:"uuid"}}}}},async(r,s)=>{let i=P.safeParse(r.params);if(!i.success)return s.status(400).send({code:"VALIDATION_ERROR",message:g.prettifyError(i.error)});let a=E(i.data.id);if(!a)return s.status(404).send({code:"NOT_FOUND",message:"Channel not found"});if(a.platform!=="wechat")return s.status(400).send({code:"INVALID_PLATFORM",message:"Channel is not a WeChat channel"});let o=a.config;return await at({apiBaseUrl:o.baseUrl,routeTag:o.routeTag})}),t.post("/channels/:id/wechat/qr-wait",{schema:{tags:["WeChat"],summary:"Wait for WeChat QR scan",params:{type:"object",required:["id"],properties:{id:{type:"string",format:"uuid"}}},body:{type:"object",properties:{sessionKey:{type:"string"},timeoutMs:{type:"number"}}}}},async(r,s)=>{let i=P.safeParse(r.params);if(!i.success)return s.status(400).send({code:"VALIDATION_ERROR",message:g.prettifyError(i.error)});let a=E(i.data.id);if(!a)return s.status(404).send({code:"NOT_FOUND",message:"Channel not found"});if(a.platform!=="wechat")return s.status(400).send({code:"INVALID_PLATFORM",message:"Channel is not a WeChat channel"});let o=a.config,{sessionKey:d,timeoutMs:c}=r.body??{},u=await ot({sessionKey:d??"",apiBaseUrl:o.baseUrl,timeoutMs:c??12e4,routeTag:o.routeTag});if(u.connected&&u.botToken){let p={...o,botToken:u.botToken,accountId:u.accountId,baseUrl:u.baseUrl??o.baseUrl,userId:u.userId};if(ne(a.id,{config:p}),e){let f=new q(a.id,p),m=E(a.id);m&&await e.addChannel(m,f)}}return{connected:u.connected,accountId:u.accountId,message:u.message}})}function D(t){return t instanceof Error?t.message.replace(/pass(word)?=[^\s]+/gi,"password=****"):String(t)}async function As(){let t=V().emailGateway;if(!t?.enabled)throw new Error("Email Gateway is disabled. Enable Email Gateway in Settings before connecting Mail channels.");let e=S();e.getStatus().status!=="connected"&&await ye(t);let n=e.getStatus();if(n.status!=="connected"){let r=n.lastError?`: ${n.lastError}`:"";throw new Error(`Email Gateway status is ${n.status}${r}`)}}export{Lt as a,G as b,Bt as c,S as d,jr as e,Vr as f,Ei as g,Ti as h,Li as i,Fi as j,Bi as k};
1
+ import{g as Qe}from"./chunk-IEBAOZED.js";import{a as He,b as k,c as xe,d as B,e as Ke}from"./chunk-NNMQGISW.js";import{b as Xe,c as Je,f as se,g as re}from"./chunk-HRPMRWHD.js";import{a as je,b as Ve,c as E,d as ne,e as F,f as Te,g as z,i as ze}from"./chunk-6WQFYV3N.js";import{e as V}from"./chunk-3MROEPGR.js";import{c as y,h as C}from"./chunk-EZLBMUQD.js";import{z as g}from"zod/v4";import{v4 as Ms}from"uuid";import{randomUUID as st}from"crypto";import tn from"crypto";var Ye="2.1.7",ie="bot";function nn(t){let e=t.split(".").map(i=>parseInt(i,10)),n=e[0]??0,r=e[1]??0,s=e[2]??0;return(n&255)<<16|(r&255)<<8|s&255}var Me=nn(Ye),sn=35e3,Ze=15e3,rn=1e4;function ae(){return{channel_version:Ye}}function an(t){return t.endsWith("/")?t:`${t}/`}function on(){let t=tn.randomBytes(4).readUInt32BE(0);return Buffer.from(String(t),"utf-8").toString("base64")}function dn(t){let e={"Content-Type":"application/json",AuthorizationType:"ilink_bot_token","Content-Length":String(Buffer.byteLength(t.body,"utf-8")),"X-WECHAT-UIN":on(),"iLink-App-Id":ie,"iLink-App-ClientVersion":String(Me)};return t.token?.trim()&&(e.Authorization=`Bearer ${t.token.trim()}`),t.routeTag&&(e.SKRouteTag=t.routeTag),e}async function oe(t){let e=an(t.baseUrl),n=new URL(t.endpoint,e),r=dn({token:t.token,routeTag:t.routeTag,body:t.body}),s=new AbortController,i=setTimeout(()=>s.abort(),t.timeoutMs);try{let a=await fetch(n.toString(),{method:"POST",headers:r,body:t.body,signal:s.signal});clearTimeout(i);let o=await a.text();if(!a.ok)throw new Error(`${t.label} ${a.status}: ${o}`);return o}catch(a){throw clearTimeout(i),a}}async function et(t){let e=t.timeoutMs??sn;try{let n=await oe({baseUrl:t.baseUrl,endpoint:"ilink/bot/getupdates",body:JSON.stringify({get_updates_buf:t.get_updates_buf??"",base_info:ae()}),token:t.token,routeTag:t.routeTag,timeoutMs:e,label:"getUpdates"});return JSON.parse(n)}catch(n){if(n instanceof Error&&n.name==="AbortError")return{ret:0,msgs:[],get_updates_buf:t.get_updates_buf};throw n}}var un={[-2]:2,[-3]:3},cn=1e3;async function Q(t){let e=(await import("./logger-TEZSHFTZ.js")).getLogger("channels"),n=new Map;for(;;){let r=await oe({baseUrl:t.baseUrl,endpoint:"ilink/bot/sendmessage",body:JSON.stringify({...t.body,base_info:ae()}),token:t.token,routeTag:t.routeTag,timeoutMs:t.timeoutMs??Ze,label:"sendMessage"});e.info({status:200,responseBody:r.slice(0,300)},"apiFetch sendMessage response");try{let s=JSON.parse(r);if(s.ret&&s.ret!==0){let i=un[s.ret],a=(n.get(s.ret)??0)+1;if(n.set(s.ret,a),i!==void 0&&a<i){e.warn({ret:s.ret,attempt:a,maxRetries:i},"sendMessage: retriable iLink error, retrying"),await new Promise(o=>setTimeout(o,cn*a));continue}throw e.error({ret:s.ret,errmsg:s.errmsg,attempt:a},"sendMessage: iLink API error, no more retries"),new Error(`sendMessage failed: iLink ret=${s.ret}${s.errmsg?` errmsg=${s.errmsg}`:""}`)}}catch(s){if(s instanceof SyntaxError)e.warn({rawText:r.slice(0,200)},"sendMessage: non-JSON response, treating as success");else throw s}return}}async function tt(t){await oe({baseUrl:t.baseUrl,endpoint:"ilink/bot/sendtyping",body:JSON.stringify({...t.body,base_info:ae()}),token:t.token,routeTag:t.routeTag,timeoutMs:t.timeoutMs??rn,label:"sendTyping"})}async function nt(t){let e=await oe({baseUrl:t.baseUrl,endpoint:"ilink/bot/getuploadurl",body:JSON.stringify({filekey:t.filekey,media_type:t.media_type,to_user_id:t.to_user_id,rawsize:t.rawsize,rawfilemd5:t.rawfilemd5,filesize:t.filesize,thumb_rawsize:t.thumb_rawsize,thumb_rawfilemd5:t.thumb_rawfilemd5,thumb_filesize:t.thumb_filesize,no_need_thumb:t.no_need_thumb,aeskey:t.aeskey,base_info:ae()}),token:t.token,routeTag:t.routeTag,timeoutMs:t.timeoutMs??Ze,label:"getUploadUrl"});return JSON.parse(e)}var ln=5*6e4,mn=35e3,rt="3",T=new Map;function Se(t){return Date.now()-t.startedAt<ln}function gn(){for(let[t,e]of T)Se(e)||T.delete(t)}async function it(t,e,n){let r=t.endsWith("/")?t:`${t}/`,s=new URL(`ilink/bot/get_bot_qrcode?bot_type=${encodeURIComponent(e)}`,r),i={"iLink-App-Id":ie};n&&(i.SKRouteTag=n);let a=await fetch(s.toString(),{headers:i});if(!a.ok){let o=await a.text().catch(()=>"(unreadable)");throw new Error(`Failed to fetch QR code: ${a.status} ${a.statusText} body=${o}`)}return await a.json()}async function pn(t,e,n){let r=t.endsWith("/")?t:`${t}/`,s=new URL(`ilink/bot/get_qrcode_status?qrcode=${encodeURIComponent(e)}`,r),i={"iLink-App-Id":ie,"iLink-App-ClientVersion":String(Me)};n&&(i.SKRouteTag=n);let a=new AbortController,o=setTimeout(()=>a.abort(),mn);try{let d=await fetch(s.toString(),{headers:i,signal:a.signal});clearTimeout(o);let c=await d.text();if(!d.ok)throw new Error(`Failed to poll QR status: ${d.status} ${d.statusText}`);return JSON.parse(c)}catch(d){if(clearTimeout(o),d instanceof Error&&d.name==="AbortError")return{status:"wait"};throw d}}async function at(t){let e=t.accountId||st();gn();let n=T.get(e);if(!t.force&&n&&Se(n)&&n.qrcodeUrl)return{qrcodeUrl:n.qrcodeUrl,message:"QR code ready. Scan with WeChat.",sessionKey:e};if(!t.apiBaseUrl)return{message:"No baseUrl configured for this WeChat channel.",sessionKey:e};try{let r=t.botType||rt,s=await it(t.apiBaseUrl,r,t.routeTag),i={sessionKey:e,id:st(),qrcode:s.qrcode,qrcodeUrl:s.qrcode_img_content,startedAt:Date.now()};return T.set(e,i),{qrcodeUrl:s.qrcode_img_content,message:"Scan the QR code with WeChat to connect.",sessionKey:e}}catch(r){return{message:`Failed to start login: ${String(r)}`,sessionKey:e}}}var fn=3;async function ot(t){let e=T.get(t.sessionKey);if(!e)return{connected:!1,message:"No active login session. Start QR login first."};if(!Se(e))return T.delete(t.sessionKey),{connected:!1,message:"QR code expired. Please start again."};let n=Math.max(t.timeoutMs??48e4,1e3),r=Date.now()+n,s=1;for(;Date.now()<r;){try{let i=await pn(t.apiBaseUrl,e.qrcode,t.routeTag);switch(e.status=i.status,i.status){case"wait":break;case"scaned":break;case"expired":{if(s++,s>fn)return T.delete(t.sessionKey),{connected:!1,message:"Login timeout: QR expired multiple times."};try{let a=t.botType||rt,o=await it(t.apiBaseUrl,a,t.routeTag);e.qrcode=o.qrcode,e.qrcodeUrl=o.qrcode_img_content,e.startedAt=Date.now()}catch(a){return T.delete(t.sessionKey),{connected:!1,message:`QR refresh failed: ${String(a)}`}}break}case"confirmed":return i.ilink_bot_id?(T.delete(t.sessionKey),{connected:!0,botToken:i.bot_token,accountId:i.ilink_bot_id,baseUrl:i.baseurl,userId:i.ilink_user_id,message:"Connected to WeChat successfully!"}):(T.delete(t.sessionKey),{connected:!1,message:"Login failed: server did not return bot ID."})}}catch(i){return T.delete(t.sessionKey),{connected:!1,message:`Login failed: ${String(i)}`}}await new Promise(i=>setTimeout(i,1e3))}return T.delete(t.sessionKey),{connected:!1,message:"Login timeout. Please try again."}}import A from"fs";import*as M from"fs/promises";import x from"path";import{homedir as pe}from"os";var de={IMAGE:1,VIDEO:2,FILE:3,VOICE:4},H={NONE:0,USER:1,BOT:2},_={NONE:0,TEXT:1,IMAGE:2,VOICE:3,FILE:4,VIDEO:5},K={NEW:0,GENERATING:1,FINISH:2},dt={TYPING:1,CANCEL:2};C();var hn=y("channels"),Ce=-14,ue=3600*1e3,$=new Map;function ut(t){let e=Date.now()+ue;$.set(t,e),hn.info({channelId:t},`Session paused until ${new Date(e).toISOString()} (${ue/1e3}s)`)}function ce(t){let e=$.get(t);return e===void 0?!1:Date.now()>=e?($.delete(t),!1):!0}function ct(t){let e=$.get(t);if(e===void 0)return 0;let n=e-Date.now();return n<=0?($.delete(t),0):n}function lt(t){$.delete(t)}C();import*as me from"fs/promises";import _t from"path";import{homedir as In}from"os";import{createCipheriv as yn,createDecipheriv as bn}from"crypto";function mt(t,e){let n=yn("aes-128-ecb",e,null);return Buffer.concat([n.update(t),n.final()])}function gt(t,e){let n=bn("aes-128-ecb",e,null);return Buffer.concat([n.update(t),n.final()])}function pt(t){return Math.ceil((t+1)/16)*16}function Ae(t,e){return`${e}/download?encrypted_query_param=${encodeURIComponent(t)}`}function ft(t){return`${t.cdnBaseUrl}/upload?encrypted_query_param=${encodeURIComponent(t.uploadParam)}&filekey=${encodeURIComponent(t.filekey)}`}C();var Ws=y("channels");function wn(t){let e=Buffer.from(t,"base64");if(e.length===16)return e;if(e.length===32&&/^[0-9a-fA-F]{32}$/.test(e.toString("ascii")))return Buffer.from(e.toString("ascii"),"hex");throw new Error(`aes_key must decode to 16 raw bytes or 32-char hex, got ${e.length} bytes`)}async function ht(t){let e=await fetch(t);if(!e.ok)throw new Error(`CDN download ${e.status} ${e.statusText}`);return Buffer.from(await e.arrayBuffer())}async function X(t){let{encryptQueryParam:e,aesKeyBase64:n,cdnBaseUrl:r,fullUrl:s}=t,i=wn(n),a=s?.trim()||(e?Ae(e,r):null);if(!a)throw new Error("CDN download: need full_url or encrypt_query_param");let o=await ht(a);return gt(o,i)}async function yt(t){let{encryptQueryParam:e,cdnBaseUrl:n,fullUrl:r}=t,s=r?.trim()||(e?Ae(e,n):null);if(!s)throw new Error("CDN download: need full_url or encrypt_query_param");return ht(s)}C();var le=y("channels"),bt=24e3;function _n(t,e){let n=t.byteLength,r=44+n,s=Buffer.allocUnsafe(r),i=0;return s.write("RIFF",i),i+=4,s.writeUInt32LE(r-8,i),i+=4,s.write("WAVE",i),i+=4,s.write("fmt ",i),i+=4,s.writeUInt32LE(16,i),i+=4,s.writeUInt16LE(1,i),i+=2,s.writeUInt16LE(1,i),i+=2,s.writeUInt32LE(e,i),i+=4,s.writeUInt32LE(e*2,i),i+=4,s.writeUInt16LE(2,i),i+=2,s.writeUInt16LE(16,i),i+=2,s.write("data",i),i+=4,s.writeUInt32LE(n,i),i+=4,Buffer.from(t.buffer,t.byteOffset,t.byteLength).copy(s,i),s}async function wt(t){try{let{decode:e}=await import("silk-wasm");le.debug(`silkToWav: decoding ${t.length} bytes of SILK`);let n=await e(t,bt);le.debug(`silkToWav: decoded duration=${n.duration}ms pcmBytes=${n.data.byteLength}`);let r=_n(n.data,bt);return le.debug(`silkToWav: WAV size=${r.length}`),r}catch(e){return le.warn(`silkToWav: transcode failed, will use raw silk err=${String(e)}`),null}}var N=y("channels"),It=100*1024*1024;function En(t){return re(t)??".bin"}async function J(t,e,n,r,s=It,i){if(t.length>s)throw new Error(`Media too large: ${t.length} bytes exceeds ${s} bytes`);let a=_t.join(In(),".adam","wechat","media",r,n);await me.mkdir(a,{recursive:!0});let o;if(i&&/^[a-zA-Z0-9._-]+$/.test(i))o=i;else{let c=e?En(e):".bin",u=Date.now(),p=Math.random().toString(36).slice(2,7);o=`${u}-${p}${c}`}let d=_t.join(a,o);return await me.writeFile(d,t),N.debug(`saveMedia: saved ${t.length} bytes to ${d}`),d}async function Et(t,e){let{cdnBaseUrl:n,channelId:r}=e;if(t.type===_.IMAGE){let s=t.image_item;if(!s?.media?.encrypt_query_param&&!s?.media?.full_url)return null;let i=s.aeskey?Buffer.from(s.aeskey,"hex").toString("base64"):s.media?.aes_key;try{let a=i?await X({encryptQueryParam:s.media?.encrypt_query_param,aesKeyBase64:i,cdnBaseUrl:n,fullUrl:s.media?.full_url}):await yt({encryptQueryParam:s.media?.encrypt_query_param,cdnBaseUrl:n,fullUrl:s.media?.full_url});return{path:await J(a,"image/png","inbound",r),mimeType:"image/png",type:"image"}}catch(a){return N.error({channelId:r},`Image download/decrypt failed: ${String(a)}`),null}}if(t.type===_.VOICE){let s=t.voice_item;if(!s?.media?.encrypt_query_param&&!s?.media?.full_url||!s?.media?.aes_key)return null;try{let i=await X({encryptQueryParam:s.media.encrypt_query_param,aesKeyBase64:s.media.aes_key,cdnBaseUrl:n,fullUrl:s.media.full_url}),a=await wt(i);if(a){let o=await J(a,"audio/wav","inbound",r);return N.debug(`Voice: saved WAV to ${o}`),{path:o,mimeType:"audio/wav",type:"audio"}}else{let o=await J(i,"audio/silk","inbound",r);return N.debug(`Voice: silk transcode unavailable, saved raw SILK to ${o}`),{path:o,mimeType:"audio/silk",type:"audio"}}}catch(i){return N.error({channelId:r},`Voice download/transcode failed: ${String(i)}`),null}}if(t.type===_.FILE){let s=t.file_item;if(!s?.media?.encrypt_query_param&&!s?.media?.full_url||!s?.media?.aes_key)return null;try{let i=await X({encryptQueryParam:s.media.encrypt_query_param,aesKeyBase64:s.media.aes_key,cdnBaseUrl:n,fullUrl:s.media.full_url}),a=se(s.file_name??"file.bin");return{path:await J(i,a,"inbound",r,It,s.file_name),mimeType:a,type:"file"}}catch(i){return N.error({channelId:r},`File download failed: ${String(i)}`),null}}if(t.type===_.VIDEO){let s=t.video_item;if(!s?.media?.encrypt_query_param&&!s?.media?.full_url||!s?.media?.aes_key)return null;try{let i=await X({encryptQueryParam:s.media.encrypt_query_param,aesKeyBase64:s.media.aes_key,cdnBaseUrl:n,fullUrl:s.media.full_url});return{path:await J(i,"video/mp4","inbound",r),mimeType:"video/mp4",type:"video"}}catch(i){return N.error({channelId:r},`Video download failed: ${String(i)}`),null}}return null}import Mt from"path";import Re from"crypto";import Tn from"fs/promises";C();var O=y("channels"),ge=3;async function xn(t){let{buf:e,uploadFullUrl:n,uploadParam:r,filekey:s,cdnBaseUrl:i,label:a,aeskey:o}=t,d=mt(e,o),c=n?.trim(),u;if(c)u=c;else if(r)u=ft({cdnBaseUrl:i,uploadParam:r,filekey:s});else throw new Error(`${a}: CDN upload URL missing (need upload_full_url or upload_param)`);O.debug(`${a}: CDN POST url=${u} ciphertextSize=${d.length}`);let p,f;for(let m=1;m<=ge;m++)try{let l=await fetch(u,{method:"POST",headers:{"Content-Type":"application/octet-stream"},body:new Uint8Array(d)});if(l.status>=400&&l.status<500){let b=l.headers.get("x-error-message")??await l.text();throw O.error(`${a}: CDN client error attempt=${m} status=${l.status} errMsg=${b}`),new Error(`CDN upload client error ${l.status}: ${b}`)}if(l.status!==200){let b=l.headers.get("x-error-message")??`status ${l.status}`;throw O.error(`${a}: CDN server error attempt=${m} status=${l.status} errMsg=${b}`),new Error(`CDN upload server error: ${b}`)}if(p=l.headers.get("x-encrypted-param")??void 0,!p)throw O.error(`${a}: CDN response missing x-encrypted-param header attempt=${m}`),new Error("CDN upload response missing x-encrypted-param header");O.debug(`${a}: CDN upload success attempt=${m}`);break}catch(l){if(f=l,l instanceof Error&&l.message.includes("client error"))throw l;m<ge?O.warn(`${a}: attempt ${m} failed, retrying... err=${String(l)}`):O.error(`${a}: all ${ge} attempts failed err=${String(l)}`)}if(!p)throw f instanceof Error?f:new Error(`CDN upload failed after ${ge} attempts`);return{downloadParam:p}}async function ke(t){let{filePath:e,toUserId:n,opts:r,cdnBaseUrl:s,mediaType:i,label:a}=t,o=await Tn.readFile(e),d=o.length,c=Re.createHash("md5").update(o).digest("hex"),u=pt(d),p=Re.randomBytes(16).toString("hex"),f=Re.randomBytes(16);O.debug(`${a}: file=${e} rawsize=${d} filesize=${u} md5=${c} filekey=${p}`);let m=await nt({...r,filekey:p,media_type:i,to_user_id:n,rawsize:d,rawfilemd5:c,filesize:u,no_need_thumb:!0,aeskey:f.toString("hex")}),l=m.upload_full_url?.trim(),b=m.upload_param;if(!l&&!b)throw new Error(`${a}: getUploadUrl returned no upload URL (need upload_full_url or upload_param)`);let{downloadParam:L}=await xn({buf:o,uploadFullUrl:l||void 0,uploadParam:b??void 0,filekey:p,cdnBaseUrl:s,aeskey:f,label:`${a}[orig filekey=${p}]`});return{filekey:p,downloadEncryptedQueryParam:L,aeskey:f.toString("hex"),fileSize:d,fileSizeCiphertext:u}}async function Tt(t){return ke({...t,mediaType:de.IMAGE,label:"uploadImageToWeixin"})}async function xt(t){return ke({...t,mediaType:de.VIDEO,label:"uploadVideoToWeixin"})}async function Pe(t){return ke({...t,mediaType:de.FILE,label:"uploadFileAttachmentToWeixin"})}C();var Y=y("channels");function Mn(){return`adam-wechat-${Date.now()}-${Math.random().toString(36).slice(2,7)}`}function Sn(t){let e=t;return e=e.replace(/```[^\n]*\n?([\s\S]*?)```/g,(n,r)=>r.trim()),e=e.replace(/!\[[^\]]*\]\([^)]*\)/g,""),e=e.replace(/\[([^\]]+)\]\([^)]*\)/g,"$1"),e=e.replace(/^\|[\s:|-]+\|$/gm,""),e=e.replace(/^\|(.+)\|$/gm,(n,r)=>r.split("|").map(s=>s.trim()).join(" ")),e}async function Ue(t){let{to:e,text:n,mediaItem:r,opts:s,label:i}=t,a=[],o=Sn(n);o&&a.push({type:_.TEXT,text_item:{text:o}}),a.push(r);let d="";for(let c of a){d=Mn();let u={msg:{from_user_id:"",to_user_id:e,client_id:d,message_type:H.BOT,message_state:K.FINISH,item_list:[c],context_token:s.contextToken}};await Q({baseUrl:s.baseUrl,token:s.token,routeTag:s.routeTag,body:u})}return Y.debug(`${i}: sent to=${e} messageId=${d}`),{messageId:d}}async function Cn(t){let{to:e,text:n,uploaded:r,opts:s}=t,i={type:_.IMAGE,image_item:{media:{encrypt_query_param:r.downloadEncryptedQueryParam,aes_key:Buffer.from(r.aeskey).toString("base64"),encrypt_type:1},mid_size:r.fileSizeCiphertext}};return Ue({to:e,text:n,mediaItem:i,opts:s,label:"sendImageMessage"})}async function An(t){let{to:e,text:n,uploaded:r,opts:s}=t,i={type:_.VIDEO,video_item:{media:{encrypt_query_param:r.downloadEncryptedQueryParam,aes_key:Buffer.from(r.aeskey).toString("base64"),encrypt_type:1},video_size:r.fileSizeCiphertext}};return Ue({to:e,text:n,mediaItem:i,opts:s,label:"sendVideoMessage"})}async function St(t){let{to:e,text:n,fileName:r,uploaded:s,opts:i}=t,a={type:_.FILE,file_item:{media:{encrypt_query_param:s.downloadEncryptedQueryParam,aes_key:Buffer.from(s.aeskey).toString("base64"),encrypt_type:1},file_name:r,len:String(s.fileSize)}};return Ue({to:e,text:n,mediaItem:a,opts:i,label:"sendFileMessage"})}async function Ct(t){let{filePath:e,to:n,text:r,opts:s,cdnBaseUrl:i}=t,a=se(e),o={baseUrl:s.baseUrl,token:s.token,routeTag:s.routeTag};if(a.startsWith("video/")){Y.debug(`sendWeixinMediaFile: uploading video filePath=${e} to=${n}`);let u=await xt({filePath:e,toUserId:n,opts:o,cdnBaseUrl:i});return An({to:n,text:r,uploaded:u,opts:s})}if(a.startsWith("image/")){Y.debug(`sendWeixinMediaFile: uploading image filePath=${e} to=${n}`);let u=await Tt({filePath:e,toUserId:n,opts:o,cdnBaseUrl:i});return Cn({to:n,text:r,uploaded:u,opts:s})}if(a.startsWith("audio/")){let u=Mt.basename(e);Y.debug(`sendWeixinMediaFile: uploading audio as file filePath=${e} name=${u} to=${n}`);let p=await Pe({filePath:e,fileName:u,toUserId:n,opts:o,cdnBaseUrl:i});return St({to:n,text:r,fileName:u,uploaded:p,opts:s})}let d=Mt.basename(e);Y.debug(`sendWeixinMediaFile: uploading file attachment filePath=${e} name=${d} to=${n}`);let c=await Pe({filePath:e,fileName:d,toUserId:n,opts:o,cdnBaseUrl:i});return St({to:n,text:r,fileName:d,uploaded:c,opts:s})}C();var h=y("channels"),At="https://novac2c.cdn.weixin.qq.com/c2c",Ne=new Map;function Pt(t){return x.join(pe(),".adam","wechat",`${t}.context-tokens.json`)}function Rn(t){let e=Pt(t);try{let n=A.readFileSync(e,"utf-8"),r=JSON.parse(n);for(let[s,i]of Object.entries(r))typeof i=="string"&&i&&Ne.set(`${t}:${s}`,i);h.debug({channelId:t,count:Object.keys(r).length},"Restored context tokens from disk")}catch{}}function kn(t,e,n){let r=Pt(t);try{let s={};try{let a=A.readFileSync(r,"utf-8");s=JSON.parse(a)}catch{}s[e]=n;let i=x.dirname(r);A.mkdirSync(i,{recursive:!0}),A.writeFileSync(r,JSON.stringify(s),"utf-8")}catch(s){h.warn({channelId:t,userId:e},`Failed to persist context token: ${String(s)}`)}}function Pn(t,e,n){Ne.set(`${t}:${e}`,n),kn(t,e,n)}function ve(t,e){return Ne.get(`${t}:${e}`)}function Ut(t){return x.join(pe(),".adam","wechat",`${t}.sync`)}function Un(t){try{return A.readFileSync(Ut(t),"utf-8")}catch{return""}}function vn(t,e){let n=Ut(t);A.mkdirSync(x.dirname(n),{recursive:!0}),A.writeFileSync(n,e,"utf-8")}var Oe=1440*60*1e3,Rt=10,On=20,kt=1440*60*1e3,Nn=1320*60*1e3,Dn=1,Ln=7200*1e3;function vt(t){return x.join(pe(),".adam","wechat",`${t}.session.json`)}function Fn(t){let e=new Map,n=vt(t);try{let r=A.readFileSync(n,"utf-8"),s=JSON.parse(r);for(let[i,a]of Object.entries(s))a&&typeof a.lastUserMessageAt=="number"&&e.set(i,a);h.debug({channelId:t,count:e.size},"Restored sessions from disk")}catch{}return e}function Z(t,e){let n=vt(t);try{let r={};for(let[i,a]of e)r[i]=a;let s=x.dirname(n);A.mkdirSync(s,{recursive:!0}),A.writeFileSync(n,JSON.stringify(r),"utf-8")}catch(r){h.warn({channelId:t},`Failed to persist sessions: ${String(r)}`)}}var Bn=0;function ee(){return`adam-wechat-${Date.now()}-${++Bn}`}var q=class{platform="wechat";id;config;status="disconnected";messageHandler=null;pollAbort=null;getUpdatesBuf="";sessions=new Map;pendingQueue=new Map;lastReminderAt=new Map;constructor(e,n){if(this.id=e,!n.baseUrl)throw new Error("WeChat adapter requires baseUrl");this.config=n}async connect(){if(!this.config.botToken)throw new Error("WeChat adapter requires botToken. Complete QR login first.");this.status="connecting",this.getUpdatesBuf=Un(this.id),Rn(this.id),this.sessions=Fn(this.id),this.pollAbort=new AbortController,this.status="connected",h.info({channelId:this.id},"WeChat adapter connected, starting long-poll"),this.startLongPoll()}async disconnect(){this.pollAbort&&(this.pollAbort.abort(),this.pollAbort=null),this.status="disconnected",h.info({channelId:this.id},"WeChat adapter disconnected")}getStatus(){if(this.status==="connected"&&ce(this.id))return"error";if(this.status==="connected"){for(let[,e]of this.sessions)if(this.isSessionActive(e)&&e.quotaRemaining<=0)return"degraded"}return this.status}getCapabilities(){return{canEdit:!1,canQuote:!0,canParseQuote:!0,canInlineButtons:!1,maxTextLength:4e3,supportsAttachments:!0,maxAttachmentsPerMessage:1}}async sendMessage(e,n){if(ce(this.id)){let c=Math.ceil(ct(this.id)/6e4);throw new Error(`WeChat session paused, ${c} min remaining. Re-scan QR to reconnect.`)}let r=this.getOrCreateSession(e),i=this.getSessionRemainingMs(r)/36e5;if(!this.isSessionActive(r))return h.warn({channelId:this.id,chatId:e.slice(0,12),lastUserMessageAt:r.lastUserMessageAt,sessionExpired:!0},"iLink session expired (>24h), message queued"),this.enqueueMessage(e,n),`queued-${ee()}`;if(r.quotaRemaining<=0)return h.warn({channelId:this.id,chatId:e.slice(0,12),quotaRemaining:0,remainingHours:i.toFixed(1)},"iLink quota exhausted, message queued"),this.enqueueMessage(e,n),`queued-${ee()}`;let a=ee(),o=ve(this.id,e),d=this.config.cdnBaseUrl??At;try{let c=n.attachments?.[0],u=c?.path??n.mediaUrl,p=c?.contentType,f=c?.filename,m=c?.mediaType??n.mediaType;if(u){let l=!u.includes("://")||u.startsWith("file://"),b=x.join(pe(),".adam","wechat","media","outbound-tmp");await M.mkdir(b,{recursive:!0});let L=this.getExtensionFromMediaType(m,p),R;if(l){let I=u.startsWith("file://")?new URL(u).pathname:x.isAbsolute(u)?u:x.resolve(u),v=await M.readFile(I);R=x.join(b,`${Date.now()}-${Math.random().toString(36).slice(2,7)}${L}`),await M.writeFile(R,v)}else{let I=await fetch(u);if(!I.ok)throw new Error(`Failed to fetch media: ${I.status}`);let v=Buffer.from(await I.arrayBuffer());R=x.join(b,`${Date.now()}-${Math.random().toString(36).slice(2,7)}${L}`),await M.writeFile(R,v)}let w=R;if(f){let I=f.replace(/[\\/]/g,"-").replace(/\.\./g,"-").replace(/[\x00-\x1f]/g,"");if(I.length>0&&I.length<200){let v=x.join(b,`${Date.now()}-${I}`);await M.copyFile(R,v),await M.unlink(R).catch(()=>{}),w=v}}let U=await Ct({filePath:w,to:e,text:n.content??"",opts:{baseUrl:this.config.baseUrl,token:this.config.botToken,routeTag:this.config.routeTag,contextToken:o},cdnBaseUrl:d});return await M.unlink(w).catch(()=>{}),r.quotaRemaining--,Z(this.id,this.sessions),h.info({channelId:this.id,chatId:e.slice(0,12),quotaRemaining:r.quotaRemaining,sessionRemainingHours:(this.getSessionRemainingMs(r)/36e5).toFixed(1)},"iLink send success: quota decremented"),this.checkAndSendReminder(e,r).catch(I=>{h.warn({channelId:this.id,chatId:e.slice(0,12)},`Reminder send failed: ${String(I)}`)}),U.messageId}return await Q({baseUrl:this.config.baseUrl,token:this.config.botToken,routeTag:this.config.routeTag,body:{msg:{from_user_id:"",to_user_id:e,client_id:a,message_type:H.BOT,message_state:K.FINISH,item_list:this.buildItemList(n),context_token:o}}}),r.quotaRemaining--,Z(this.id,this.sessions),h.info({channelId:this.id,chatId:e.slice(0,12),quotaRemaining:r.quotaRemaining,sessionRemainingHours:(this.getSessionRemainingMs(r)/36e5).toFixed(1)},"iLink send success: quota decremented"),this.checkAndSendReminder(e,r).catch(l=>{h.warn({channelId:this.id,chatId:e.slice(0,12)},`Reminder send failed: ${String(l)}`)}),a}catch(c){if(c instanceof Error&&c.message.includes("ret=-2"))return r.quotaRemaining=0,Z(this.id,this.sessions),h.warn({channelId:this.id,chatId:e.slice(0,12),quotaRemaining:0},"iLink quota exhausted (ret=-2 confirmed), message queued"),this.enqueueMessage(e,n),`queued-${ee()}`;throw c}}onMessage(e){this.messageHandler=e}async sendTypingIndicator(e){if(ce(this.id))return;let n=ve(this.id,e);try{await tt({baseUrl:this.config.baseUrl,token:this.config.botToken,routeTag:this.config.routeTag,body:{ilink_user_id:e,status:dt.TYPING}})}catch{}}updateConfig(e){Object.assign(this.config,e)}buildItemList(e){if(!e.content)return;let n={type:_.TEXT,text_item:{text:e.content}};if(e.replyToMessageId){let r=(e.quoteExcerpt??"").slice(0,80);n.ref_msg={message_item:{msg_id:e.replyToMessageId,text_item:{text:r}},title:e.quoteTitle}}return[n]}getOrCreateSession(e){let n=this.sessions.get(e);return n||(n={lastUserMessageAt:0,quotaRemaining:0},this.sessions.set(e,n)),n}isSessionActive(e){return e.lastUserMessageAt>0&&Date.now()-e.lastUserMessageAt<=Oe}getSessionRemainingMs(e){return e.lastUserMessageAt===0?0:Math.max(0,Oe-(Date.now()-e.lastUserMessageAt))}enqueueMessage(e,n){let r=this.pendingQueue.get(e);r||(r=[],this.pendingQueue.set(e,r));let s=Date.now();r=r.filter(i=>s-i.queuedAt<kt),r.length>=On&&(r.shift(),h.warn({channelId:this.id,chatId:e.slice(0,12)},"Queue full, dropping oldest message")),r.push({message:n,queuedAt:s}),this.pendingQueue.set(e,r),h.info({channelId:this.id,chatId:e.slice(0,12),queueDepth:r.length},"Message enqueued")}async flushQueue(e){let n=this.pendingQueue.get(e);if(!n||n.length===0)return;let r=this.getOrCreateSession(e),s=Math.min(n.length,Math.max(0,r.quotaRemaining-2));if(s<=0){h.info({channelId:this.id,chatId:e.slice(0,12),quotaRemaining:r.quotaRemaining},"Queue flush skipped: insufficient quota (reserving 2 for conversation)");return}h.info({channelId:this.id,chatId:e.slice(0,12),queueDepth:n.length,sending:s,quotaRemaining:r.quotaRemaining},"Flushing queued messages");let i=0;for(;i<s&&n.length>0;){let a=n[0];if(Date.now()-a.queuedAt>kt){n.shift();continue}try{if(await this.sendMessage(e,a.message),n.shift(),i++,r.quotaRemaining<=0)break}catch{h.warn({channelId:this.id,chatId:e.slice(0,12)},"Queue flush: send failed, stopping");break}}n.length===0&&this.pendingQueue.delete(e),h.info({channelId:this.id,chatId:e.slice(0,12),sent:i,remaining:n.length},"Queue flush complete")}async checkAndSendReminder(e,n){let r=Date.now(),s=this.lastReminderAt.get(e)??0;if(r-s<Ln)return;let i=this.getSessionRemainingMs(n),o=r-n.lastUserMessageAt>=Nn,d=n.quotaRemaining<=Dn;if(!o&&!d)return;let c=(i/36e5).toFixed(1),u;o&&d?u=`[\u7CFB\u7EDF\u63D0\u9192] \u6D88\u606F\u7A97\u53E3\u5373\u5C06\u5173\u95ED\uFF08\u5269\u4F59${c}\u5C0F\u65F6/${n.quotaRemaining}\u6761\u914D\u989D\uFF09\u3002\u8BF7\u56DE\u590D\u4EFB\u610F\u6D88\u606F\u4EE5\u4FDD\u6301\u8FDE\u63A5\u3002`:o?u=`[\u7CFB\u7EDF\u63D0\u9192] \u6D88\u606F\u7A97\u53E3\u5373\u5C06\u5173\u95ED\uFF08\u5269\u4F59${c}\u5C0F\u65F6\uFF09\u3002\u8BF7\u56DE\u590D\u4EFB\u610F\u6D88\u606F\u4EE5\u4FDD\u6301\u8FDE\u63A5\u3002`:u=`[\u7CFB\u7EDF\u63D0\u9192] \u6D88\u606F\u914D\u989D\u5373\u5C06\u7528\u5B8C\uFF08\u5269\u4F59${n.quotaRemaining}\u6761\uFF09\u3002\u8BF7\u56DE\u590D\u4EFB\u610F\u6D88\u606F\u4EE5\u91CD\u7F6E\u914D\u989D\u3002`;let p=ve(this.id,e);try{await Q({baseUrl:this.config.baseUrl,token:this.config.botToken,routeTag:this.config.routeTag,body:{msg:{from_user_id:"",to_user_id:e,client_id:ee(),message_type:H.BOT,message_state:K.FINISH,item_list:[{type:_.TEXT,text_item:{text:u}}],context_token:p}}}),n.quotaRemaining--,this.lastReminderAt.set(e,r),Z(this.id,this.sessions),h.info({channelId:this.id,chatId:e.slice(0,12),remainingHours:c,quotaRemaining:n.quotaRemaining,trigger:o?"time":"quota"},"iLink session reminder sent")}catch(f){h.warn({channelId:this.id,chatId:e.slice(0,12)},`Reminder send failed: ${String(f)}`)}}async startLongPoll(){let e=this.pollAbort?.signal,n=0,r=3,s=3e4,i=2e3;for(;!e?.aborted;)try{let a=await et({baseUrl:this.config.baseUrl,token:this.config.botToken,routeTag:this.config.routeTag,get_updates_buf:this.getUpdatesBuf});if(a.ret===Ce||a.errcode===Ce){ut(this.id),this.status="error",h.error({channelId:this.id},"Session expired (errcode=-14), pausing for 1 hour"),await this.sleep(ue,e),lt(this.id),this.status="connected";continue}if(a.ret!==void 0&&a.ret!==0||a.errcode!==void 0&&a.errcode!==0){n++,h.error({channelId:this.id,ret:a.ret,errcode:a.errcode},"getUpdates API error"),n>=r?(n=0,await this.sleep(s,e)):await this.sleep(i,e);continue}n=0,a.get_updates_buf&&(this.getUpdatesBuf=a.get_updates_buf,vn(this.id,a.get_updates_buf));for(let d of a.msgs??[])await this.processInbound(d)}catch(a){if(e?.aborted)return;n++,h.error({channelId:this.id,error:a},"getUpdates error"),n>=r?(n=0,await this.sleep(s,e)):await this.sleep(i,e)}}async processInbound(e){if(!this.messageHandler)return;let n=!!e.group_id,r=n?e.group_id:e.from_user_id??"",s=e.from_user_id??"";e.context_token&&r&&Pn(this.id,r,e.context_token);let i=this.getOrCreateSession(r),a=i.quotaRemaining;i.lastUserMessageAt=Date.now(),i.quotaRemaining=Rt,Z(this.id,this.sessions),h.info({channelId:this.id,chatId:r.slice(0,12),quotaReset:!0,prevQuota:a,newQuota:Rt,sessionWindowMs:Oe},"iLink session reset: user message received, quota restored"),this.flushQueue(r);let o="",d,c=[],u;for(let m of e.item_list??[]){let l=m.ref_msg?.message_item?.msg_id;if(l){u=l;break}}for(let m of e.item_list??[])m.type===_.TEXT&&m.text_item?.text&&(o+=m.text_item.text),m.type===_.IMAGE&&(d="image",c.push(m)),m.type===_.VOICE&&(d="audio",c.push(m),m.voice_item?.text&&!o&&(o=m.voice_item.text)),m.type===_.FILE&&(d="file",c.push(m)),m.type===_.VIDEO&&(d="video",c.push(m));if(!o&&!d)return;let p;if(c.length>0){let m=this.config.cdnBaseUrl??At;try{let l=await Et(c[0],{cdnBaseUrl:m,channelId:this.id});l&&(p=l.path,d=l.type)}catch(l){h.error({channelId:this.id},`Media download failed: ${String(l)}`)}}let f={channelId:this.id,platform:"wechat",chatId:r,senderId:s,content:o,mediaType:d,mediaPath:p,isGroup:n,timestamp:e.create_time_ms??Date.now(),raw:e,...u?{quotedPlatformMessageId:u}:{}};this.messageHandler(f)}getExtensionFromMediaType(e,n){if(n){let r=re(n);if(r&&r!==".bin")return r}switch(e){case"image":return".png";case"video":return".mp4";case"audio":return".mp3";default:return".bin"}}sleep(e,n){return new Promise((r,s)=>{let i=setTimeout(r,e);n?.addEventListener("abort",()=>{clearTimeout(i),s(new Error("aborted"))},{once:!0})})}};C();C();var $n=y("channels"),fe=class{platform="discord";id;config;status="disconnected";messageHandler=null;client=null;constructor(e,n){if(this.id=e,!n.botToken)throw new Error("Discord adapter requires botToken");this.config=n}async connect(){this.status="connecting";try{let{Client:e,GatewayIntentBits:n}=await import("discord.js");this.client=new e({intents:[n.Guilds,n.GuildMessages,n.MessageContent,n.DirectMessages]});let r=this.client;r.on("messageCreate",s=>{if(!this.messageHandler||s.author.bot||this.config.allowedGuildIds?.length&&s.guildId&&!this.config.allowedGuildIds.includes(s.guildId))return;let i={channelId:this.id,platform:"discord",chatId:s.channelId,senderId:s.author.id,senderName:s.author.displayName??s.author.username,content:s.content,isGroup:!!s.guildId,timestamp:s.createdTimestamp,raw:s};this.messageHandler(i)}),await r.login(this.config.botToken),this.status="connected",$n.info({channelId:this.id},"Discord bot connected")}catch(e){throw this.status="error",e}}async disconnect(){this.client&&await this.client.destroy(),this.client=null,this.status="disconnected"}getStatus(){return this.status}getCapabilities(){return{canEdit:!0,canQuote:!0,canParseQuote:!0,canInlineButtons:!0,maxTextLength:2e3,supportsAttachments:!0}}async sendMessage(e,n){if(!this.client)throw new Error("Discord client not connected");let s=await this.client.channels.fetch(e);if(!s||!("send"in s))throw new Error(`Channel ${e} not found or not text channel`);return(await s.send({content:n.content,reply:n.replyToMessageId?{messageReference:n.replyToMessageId}:void 0})).id}onMessage(e){this.messageHandler=e}async sendTypingIndicator(e){if(!this.client)return;let r=await this.client.channels.fetch(e);r&&"sendTyping"in r&&await r.sendTyping()}};import{statSync as es}from"fs";import{ImapFlow as ts}from"imapflow";import ns from"nodemailer";import{existsSync as qn,mkdirSync as Gn,readFileSync as Wn,writeFileSync as jn}from"fs";import{dirname as Vn,join as Ot}from"path";import{homedir as zn}from"os";var Qn={lastUid:0,seenMessageIds:[],sentMessageIds:[],updatedAt:0};function De(t=process.env.ADAM_TEST_DIR??Ot(zn(),".adam")){return Ot(t,"email-gateway","state.json")}function he(t=De()){if(!qn(t))return{...Qn};let e=JSON.parse(Wn(t,"utf-8"));return{uidValidity:e.uidValidity,lastUid:Number.isInteger(e.lastUid)?e.lastUid:0,seenMessageIds:Array.isArray(e.seenMessageIds)?e.seenMessageIds.filter(Nt):[],sentMessageIds:Array.isArray(e.sentMessageIds)?e.sentMessageIds.filter(Nt):[],updatedAt:typeof e.updatedAt=="number"?e.updatedAt:0}}function te(t,e=De()){Gn(Vn(e),{recursive:!0}),jn(e,JSON.stringify({...t,updatedAt:Date.now()},null,2),"utf-8")}function Dt(t,e){let n=G(e);return n?{...t,seenMessageIds:t.seenMessageIds.includes(n)?t.seenMessageIds:[...t.seenMessageIds,n]}:t}function Hn(t,e){let n=G(e);return n?{...t,sentMessageIds:t.sentMessageIds.includes(n)?t.sentMessageIds:[...t.sentMessageIds,n]}:t}function Lt(t,e=De()){let n=Hn(he(e),t);return te(n,e),n}function G(t){return typeof t=="string"?t.trim():""}function Nt(t){return typeof t=="string"}import{Readable as Kn}from"stream";import{MailParser as Xn}from"mailparser";import{convert as Jn}from"html-to-text";async function Bt(t){let e=new Xn({skipImageLinks:!0,skipTextToHtml:!0}),n={},r,s,i,a=[],o,d="",c="",u="",p,f=0,m;if(await new Promise((L,R)=>{e.on("headers",w=>{try{for(let[I,v]of w.entries())n[I.toLowerCase()]=Zn(v);r=Ft(w.get("message-id")),o=Ft(w.get("subject")),u=Gt(w.get("content-type"))??"";let U=w.get("date");U instanceof Date&&(p=U.getTime()),s=$t(w.get("from"),"from"),i=Yn(w.get("reply-to"),"reply-to"),a=qt(w.get("to"))}catch(U){m=U instanceof Error?U:new Error(String(U))}}),e.on("data",w=>{if(w.type==="attachment"){f+=1,w.release?.(),w.content?.resume?.();return}d=w.text??"",c=typeof w.html=="string"?w.html:""}),e.on("error",R),e.on("end",L),Kn.from([t]).pipe(e)}),m)throw m;if(!s)throw new Error("Inbound email must contain exactly one valid From address");let l=u.toLowerCase()==="text/html",b=d.trim();return(l||!b)&&c.trim()&&(b=Jn(c,{wordwrap:!1,selectors:[{selector:"h1",format:"heading",options:{uppercase:!1}},{selector:"h2",format:"heading",options:{uppercase:!1}},{selector:"h3",format:"heading",options:{uppercase:!1}},{selector:"h4",format:"heading",options:{uppercase:!1}},{selector:"h5",format:"heading",options:{uppercase:!1}},{selector:"h6",format:"heading",options:{uppercase:!1}}]}).trim()),!b&&o&&(b=o.trim()),{messageId:r,from:s,replyTo:i,to:a,subject:o,text:b,date:p,rawHeaders:n,attachmentCount:f}}function $t(t,e){let n=qt(t);if(n.length!==1){if(n.length===0)return;throw new Error(`Inbound email ${e} must contain exactly one mailbox address`)}return n[0]}function Yn(t,e){if(t)return $t(t,e)}function qt(t){return t?typeof t=="string"?[k(t)]:(t.value??[]).map(r=>r.address).filter(r=>typeof r=="string"&&r.trim().length>0).map(r=>k(r)):[]}function Ft(t){if(typeof t=="string")return t;if(Array.isArray(t))return t.map(String).join(", ")}function Zn(t){if(t instanceof Date)return t.toISOString();if(typeof t=="string")return t;if(Array.isArray(t))return t.map(String).join(", ");let e=Gt(t);return e||(t&&typeof t=="object"&&"text"in t?String(t.text??""):String(t??""))}function Gt(t){if(typeof t=="string")return t;if(t&&typeof t=="object"&&"value"in t){let e=t.value;if(typeof e=="string")return e}}var Wt=3e4,ss=5e3,rs=3e5,is=1.33,as=3e4;function os(t){if(!t||t.length===0)return Wt;let e=0;for(let r of t)try{e+=es(r.path).size}catch{}let n=e*is/(1024*1024);return Math.min(rs,Wt+Math.ceil(n*ss))}var Fe=class{imapClient;smtpTransporter;pollTimer;handlers=[];status={status:"stopped"};state=he();async start(e){if(await this.stop(),!e.enabled){this.status={status:"stopped",details:{reason:"disabled"}};return}this.status={status:"starting",lastStartedAt:Date.now()};try{this.imapClient=new ts({host:e.imap.host,port:e.imap.port,secure:e.imap.secure,auth:{user:e.imap.auth.user,pass:e.imap.auth.pass}}),await this.imapClient.connect();let n=await this.imapClient.mailboxOpen(e.imap.mailbox),r=n?.uidValidity?Number(n.uidValidity):void 0;r&&this.state.uidValidity&&r!==this.state.uidValidity?(this.state={...this.state,uidValidity:r,lastUid:0,seenMessageIds:[]},te(this.state)):r&&(this.state={...this.state,uidValidity:r},te(this.state)),this.smtpTransporter=ns.createTransport({host:e.smtp.host,port:e.smtp.port,secure:e.smtp.secure,auth:{user:e.smtp.auth.user,pass:e.smtp.auth.pass}}),await this.smtpTransporter.verify(),this.status={status:"connected",lastStartedAt:Date.now(),lastCheckedAt:Date.now()},this.schedulePoll(e)}catch(n){throw await this.cleanupResources(),this.status={status:"error",lastError:Be(n),details:{stage:this.smtpTransporter?"smtp":"imap"}},n}}async stop(){await this.cleanupResources(),this.status={status:"stopped"}}getStatus(){return{...this.status}}onInbound(e){this.handlers.push(e)}async send(e){if(!this.smtpTransporter)throw new Error("EmailGateway SMTP transporter is not started");let n=os(e.attachments),r=await ds(this.smtpTransporter.sendMail({from:e.from,to:e.to,subject:e.subject,text:e.text,html:e.html,attachments:e.attachments}),n,`SMTP send timed out after ${Math.round(n/1e3)}s`),s=G(r.messageId);if(!s)throw new Error("SMTP send returned no Message-ID");return this.state=Lt(s),s}isSentByAdam(e){let n=G(e);return n.length>0&&this.state.sentMessageIds.includes(n)}schedulePoll(e){this.pollTimer=setInterval(()=>{this.poll(e)},as)}async poll(e){if(this.imapClient)try{this.state=he();let n=`${this.state.lastUid+1}:*`,r=this.imapClient.fetch?.(n,{uid:!0,source:!0,envelope:!0},{uid:!0});if(!r||!r[Symbol.asyncIterator])return;let s=!1;for await(let i of r){let a=Number(i.uid);if(!Number.isInteger(a)||a<=this.state.lastUid)continue;if(!i.source){this.markDegraded(new Error(`IMAP fetch item ${a} is missing source`)),s=!0;break}let o;try{o=await Bt(i.source)}catch(u){this.markDegraded(u),s=!0;break}let d=o.rawHeaders["x-adam-probe-id"],c=G(o.messageId);if(d?.startsWith("adam-probe-")){this.advanceCursor(a);continue}if(c&&this.state.sentMessageIds.includes(c)){this.advanceCursor(a);continue}if(c&&this.state.seenMessageIds.includes(c)){this.advanceCursor(a);continue}try{await Promise.all(this.handlers.map(u=>u(o)))}catch(u){this.markDegraded(u),s=!0;break}this.state=Dt(this.state,c),this.advanceCursor(a)}s||(this.status={...this.status,status:"connected",lastCheckedAt:Date.now(),lastError:void 0})}catch(n){this.markDegraded(n)}}advanceCursor(e){this.state={...this.state,lastUid:e},te(this.state)}markDegraded(e){this.status={...this.status,status:"degraded",lastError:Be(e),lastCheckedAt:Date.now()}}async cleanupResources(){this.pollTimer&&(clearInterval(this.pollTimer),this.pollTimer=void 0);let e=this.imapClient,n=this.smtpTransporter;this.imapClient=void 0,this.smtpTransporter=void 0,e&&(await Le(e.logout?.()),await Le(e.close?.())),await Le(n?.close?.())}},jt;function S(){return jt??=new Fe,jt}async function ye(t){await S().start(t)}async function jr(t,e){await S().stop(),await S().start(t)}async function Vr(t){await S().stop()}async function ds(t,e,n){let r;try{return await Promise.race([t,new Promise((s,i)=>{r=setTimeout(()=>i(new Error(n)),e)})])}catch(s){throw new Error(Be(s))}finally{r&&clearTimeout(r)}}function Be(t){return t instanceof Error?t.message.replace(/pass(word)?=[^\s]+/gi,"password=****"):"Email gateway operation failed"}async function Le(t){t&&typeof t.then=="function"&&await t.catch(()=>{})}C();var ls=/\b55[234]\b/,ms=/(?:size|too large|exceeds|maximum|over.*?limit)/i,gs=/\b(\d{6,11})\b/,ps=/Final-Recipient:\s*rfc822;\s*([^\s>]+@([^\s>;]+))/i,fs=/To:[\s<]*([^\s>;]+@([^\s>;]+))/i;function Vt(t){let e=t.text??"",n=e.split(/\r?\n/).filter(a=>ls.test(a)&&ms.test(a));if(n.length===0)return null;let r=e.match(ps)??e.match(fs);if(!r)return null;let s=r[2].toLowerCase().trim();if(!je.test(s))return null;let i=null;for(let a of n){let o=a.match(gs);if(o){let d=parseInt(o[1],10);if(Number.isFinite(d)&&d>=1048576&&d<=209715200){i=d;break}}}return i===null?null:{recipientDomain:s,capBytes:i}}var be=y("channels"),zt=!1;function Qt(t){if(zt){be.debug("Bounce handler already registered; skipping duplicate registration");return}zt=!0,t.onInbound(async e=>{let n=Vt(e);if(!n){(/MAILER-DAEMON/i.test(e.from??"")||/^no-reply@mailsupport\.aliyun\.com$/i.test(e.from??"")||/Mail Delivery|Undeliverable|Returned mail|Delivery Status Notification|退信|无法投递|投递失败/i.test(e.subject??""))&&be.warn({from:e.from,subject:e.subject},"Inbound looks like bounce but parser did not recognize a size-limit cap");return}let{recipientDomain:r,capBytes:s}=n;be.info({recipientDomain:r,capBytes:s},"Bounce-learning: detected SMTP size-limit bounce");let i=F().filter(a=>a.platform==="email");for(let a of i)try{ze(a.id,r,s)}catch(o){be.warn({channelId:a.id,recipientDomain:r,capBytes:s,err:o},"Bounce-learning: setRecipientCap failed (out of range or DB error); skipping")}})}C();var we=y("channels"),$e=class{constructor(e){this.gateway=e}gateway;adaptersByAddress=new Map;channelAddressById=new Map;registerAdapter(e,n){if(!He(e)||!e.enabled)return;let r=B(e);this.unregisterAdapter(e.id),this.adaptersByAddress.set(r,n),this.channelAddressById.set(e.id,r)}unregisterAdapter(e){let n=this.channelAddressById.get(e);n&&(this.adaptersByAddress.delete(n),this.channelAddressById.delete(e))}refreshFromChannels(e,n){this.adaptersByAddress.clear(),this.channelAddressById.clear();for(let r of e){let s=n.get(r.id);if(s)try{this.registerAdapter(r,s)}catch(i){we.warn({channelId:r.id,error:i},"Invalid email channel skipped during router refresh")}}}async handle(e){if(e.messageId&&this.gateway.isSentByAdam(e.messageId)){we.debug({messageId:e.messageId},"Skipping Adam-sent email");return}let n;try{n=k(e.from)}catch(s){we.warn({from:e.from,error:s},"Skipping email with invalid sender address");return}let r=this.adaptersByAddress.get(n);if(!r){we.info({from:n},"Skipping unmatched inbound email");return}await r.acceptInbound(e)}hasAddress(e){return this.adaptersByAddress.has(k(e))}},_e,Ht;function qe(t){return(!_e||Ht!==t)&&(_e=new $e(t),Ht=t,t.onInbound(e=>_e?.handle(e)??Promise.resolve())),_e}import{existsSync as hs}from"fs";import{basename as ys,isAbsolute as bs}from"path";function Kt(t){let e=[];return t.mediaUrl&&e.push({path:t.mediaUrl,mediaType:t.mediaType}),t.attachments&&e.push(...t.attachments),e.map(ws)}function ws(t){let e=t.path.startsWith("file://")?new URL(t.path).pathname:t.path;if(!bs(e)||e.includes("://"))throw new Error("Email attachment path must be an absolute local file path");if(!hs(e))throw new Error(`Email attachment file not found: ${e}`);return{filename:t.filename??ys(e),path:e,...t.contentType?{contentType:t.contentType}:t.mediaType?{contentType:_s(t.mediaType)}:{}}}function _s(t){return"application/octet-stream"}import Is from"markdown-it";var Es=new Is({html:!1,linkify:!0});function Xt(t){return{text:Xe(t),html:Es.render(t)}}function Jt(t){let e=t.prefix.trim()||"Adam";return t.messageType==="report"||t.messageType==="status_report"?`[${e} Report]`:t.messageType==="deliver"||t.messageType==="result_delivery"?`[${e} Deliver]`:`[${e}]`}var Ie=class{platform="email";id;channel;gateway;handler;inboundDispatchHandler;status="disconnected";identity;constructor(e,n,r={}){this.channel=e,this.gateway=n,this.id=e.id,this.identity=r}async connect(){let e=this.gateway.getStatus();this.status=Ee(e.status)}async disconnect(){this.status="disconnected"}getStatus(){return this.status}getCapabilities(){return{canEdit:!1,canQuote:!1,canParseQuote:!1,canInlineButtons:!1,maxTextLength:Number.POSITIVE_INFINITY,supportsAttachments:!0}}async sendMessage(e,n){let r=k(e),s=B(this.channel);if(r!==s)throw new Error("Email channel recipient does not match configured address");let i=Xt(n.content);return this.gateway.send({from:this.identity.from?Ke(this.identity.from,this.identity.displayName):void 0,to:r,subject:Jt({prefix:this.identity.subjectPrefix??"Adam",messageType:n.messageType??"reply"}),text:i.text,html:i.html,attachments:Kt(n)})}onMessage(e){this.handler=e}onInboundDispatch(e){this.inboundDispatchHandler=e}syncGatewayStatus(){this.status=Ee(this.gateway.getStatus().status)}async acceptInbound(e){let n=k(e.from),r={channelId:this.channel.id,platform:"email",chatId:n,senderId:n,senderName:e.from,content:e.text,replyToMessageId:e.messageId,isGroup:!1,timestamp:e.date??Date.now(),raw:{messageId:e.messageId,subject:e.subject,attachmentCount:e.attachmentCount,headers:e.rawHeaders}};this.handler?.(r),this.inboundDispatchHandler&&await this.inboundDispatchHandler(r)}};function Ee(t){switch(t){case"connected":return"connected";case"starting":return"connecting";case"degraded":case"error":return"degraded";case"stopped":return"disconnected";default:return"disconnected"}}var Yt=y("channels"),Ge=new Map;async function W(t,e){if(t.hasAdapter(e.id))return!0;if(e.platform==="wechat"){let n=e.config;return n.botToken?(await t.addChannel(e,new q(e.id,n)),!0):!1}if(e.platform==="discord"){let n=e.config;return n.botToken?(await t.addChannel(e,new fe(e.id,{botToken:n.botToken})),!0):!1}if(e.platform==="email"){B(e);let n=S(),r=V().emailGateway,s=new Ie(e,n,{from:r?.smtp?.from||r?.address,displayName:r?.displayName,subjectPrefix:r?.subjectPrefix??"Adam"});Ge.set(e.id,s),qe(n).registerAdapter(e,s);try{await Ts(),await t.addChannel(e,s)}catch(i){throw await j(t,e),i}return!0}return!1}async function Ei(t){for(let e of F(!0))try{await W(t,e)}catch(n){z(e.id,"error"),Yt.warn({channelId:e.id,platform:e.platform,error:n},"Failed to register built-in channel adapter")}}async function Zt(t,e){e.platform==="email"&&(await j(t,e),e.enabled&&await W(t,e))}async function en(t,e){await j(t,e)}async function j(t,e){e.platform==="email"&&(qe(S()).unregisterAdapter(e.id),Ge.delete(e.id),t?.hasAdapter(e.id)&&await t.removeChannel(e.id))}function Ti(t){for(let[e,n]of Ge.entries())n.syncGatewayStatus(),z(e,n.getStatus())}async function Ts(){let t=V().emailGateway;if(!t?.enabled)return;let e=S().getStatus().status;if(!(e!=="stopped"&&e!=="error"))try{await ye(t),Qt(S())}catch(n){Yt.warn({error:xs(n)},"EmailGateway start failed during built-in adapter registration")}}function xs(t){return t instanceof Error?t.message.replace(/pass(word)?=[^\s]+/gi,"password=****"):"Email gateway operation failed"}var P=g.object({id:g.string().uuid()}),Ss=g.object({name:g.string().min(1,"name is required"),platform:g.string().min(1,"platform is required"),config:g.record(g.string(),g.unknown()),enabled:g.boolean().optional().default(!0),linkedRoleId:g.string().optional(),allowedChatIds:g.array(g.string()).optional()}),Cs=g.object({name:g.string().min(1).optional(),enabled:g.boolean().optional(),config:g.record(g.string(),g.unknown()).optional(),linkedRoleId:g.string().optional(),allowedChatIds:g.array(g.string()).optional(),viewerKey:g.string().min(1).max(100).regex(/^[a-zA-Z0-9_.@:-]+$/,"viewerKey must be alphanumeric or one of _ . @ : -").optional(),defaultRecipientCapBytes:g.number().int().min(1048576).max(209715200).optional(),recipientCapMap:g.record(g.string().regex(/^[a-z0-9.-]+$/),g.number().int().min(1048576).max(209715200)).optional()}),We;function Li(t){We=t}function Fi(){return We}async function Bi(t){let e=We;async function n(r){Ve(r);try{return e&&r.enabled&&await W(e,r),r}catch(s){throw await j(e,r),Te(r.id),s}}t.get("/channels",{schema:{tags:["Channels"],summary:"List channels",querystring:{type:"object",properties:{enabled:{type:"boolean"}}}}},async(r,s)=>({channels:F(r.query.enabled)})),t.post("/channels",{schema:{tags:["Channels"],summary:"Create a channel",body:{type:"object",required:["name","platform","config"],properties:{name:{type:"string",minLength:1},platform:{type:"string",minLength:1},config:{type:"object"},enabled:{type:"boolean"},linkedRoleId:{type:"string"},allowedChatIds:{type:"array",items:{type:"string"}}}}}},async(r,s)=>{let i=Ss.safeParse(r.body);if(!i.success)return s.status(400).send({code:"VALIDATION_ERROR",message:g.prettifyError(i.error)});let{name:a,platform:o,config:d,enabled:c,linkedRoleId:u,allowedChatIds:p}=i.data,f=d;if(o==="email")try{f={...xe(d)}}catch(l){return s.status(400).send({code:"VALIDATION_ERROR",message:l instanceof Error?l.message:String(l)})}let m={id:Ms(),name:a,platform:o,enabled:c,status:"disconnected",config:f,linkedRoleId:u,allowedChatIds:p,viewerKey:Je(),createdAt:Date.now(),messageCount:0};try{await n(m)}catch(l){return s.status(400).send({code:"VALIDATION_ERROR",message:D(l)})}return s.status(201).send({channel:m})}),t.get("/channels/:id",{schema:{tags:["Channels"],summary:"Get channel by ID",params:{type:"object",required:["id"],properties:{id:{type:"string",format:"uuid"}}}}},async(r,s)=>{let i=P.safeParse(r.params);if(!i.success)return s.status(400).send({code:"VALIDATION_ERROR",message:g.prettifyError(i.error)});let a=E(i.data.id);return a?{channel:a}:s.status(404).send({code:"NOT_FOUND",message:"Channel not found"})}),t.patch("/channels/:id",{schema:{tags:["Channels"],summary:"Update channel",params:{type:"object",required:["id"],properties:{id:{type:"string",format:"uuid"}}},body:{type:"object",properties:{name:{type:"string"},enabled:{type:"boolean"},config:{type:"object"},linkedRoleId:{type:"string"},allowedChatIds:{type:"array",items:{type:"string"}},viewerKey:{type:"string",minLength:1,maxLength:100}}}}},async(r,s)=>{let i=P.safeParse(r.params);if(!i.success)return s.status(400).send({code:"VALIDATION_ERROR",message:g.prettifyError(i.error)});let a=E(i.data.id);if(!a)return s.status(404).send({code:"NOT_FOUND",message:"Channel not found"});let o=Cs.safeParse(r.body);if(!o.success)return s.status(400).send({code:"VALIDATION_ERROR",message:g.prettifyError(o.error)});let d={...o.data};if((a.platform==="email"||d.config)&&(d.config||a.config)){let p=d.config??a.config;if(a.platform==="email")try{d.config={...xe(p)}}catch(f){return s.status(400).send({code:"VALIDATION_ERROR",message:f instanceof Error?f.message:String(f)})}}let c=a.platform==="email"&&(d.enabled!==void 0||d.config!==void 0);ne(a.id,d);let u=E(a.id);if(e&&u&&c)try{await Zt(e,u)}catch(p){if(ne(a.id,{name:a.name,enabled:a.enabled,status:a.status,config:a.config,linkedRoleId:a.linkedRoleId,allowedChatIds:a.allowedChatIds,lastMessageAt:a.lastMessageAt,messageCount:a.messageCount}),await j(e,u),a.enabled)try{await W(e,a)}catch(f){return s.status(500).send({code:"RESTORE_FAILED",message:D(f)})}return s.status(400).send({code:"VALIDATION_ERROR",message:D(p)})}return{channel:u}}),t.delete("/channels/:id",{schema:{tags:["Channels"],summary:"Delete channel",params:{type:"object",required:["id"],properties:{id:{type:"string",format:"uuid"}}}}},async(r,s)=>{let i=P.safeParse(r.params);if(!i.success)return s.status(400).send({code:"VALIDATION_ERROR",message:g.prettifyError(i.error)});let a=E(i.data.id);if(!a)return s.status(404).send({code:"NOT_FOUND",message:"Channel not found"});if(Te(a.id),e)try{await en(e,a)}catch(o){t.log.warn({channelId:a.id,error:D(o)},"Failed to clean up built-in channel runtime")}return s.status(204).send()}),t.post("/channels/:id/connect",{schema:{tags:["Channels"],summary:"Connect channel",params:{type:"object",required:["id"],properties:{id:{type:"string",format:"uuid"}}}}},async(r,s)=>{let i=P.safeParse(r.params);if(!i.success)return s.status(400).send({code:"VALIDATION_ERROR",message:g.prettifyError(i.error)});if(!e)return s.status(501).send({code:"NOT_IMPLEMENTED",message:"Channel manager not initialized"});let a=E(i.data.id);if(!a)return s.status(404).send({code:"NOT_FOUND",message:"Channel not found"});if(a.platform==="email")try{await As()}catch(o){let d=S().getStatus();return z(a.id,Ee(d.status)),s.status(409).send({code:"EMAIL_GATEWAY_NOT_READY",message:D(o),gatewayStatus:d})}if(!e.hasAdapter(a.id))try{await W(e,a)}catch(o){return s.status(400).send({code:"VALIDATION_ERROR",message:D(o)})}if(!e.hasAdapter(a.id))return s.status(400).send({code:"NO_ADAPTER",message:"No adapter registered for this channel. Install the appropriate adapter first."});try{await e.connectChannel(a.id);let o=E(a.id)?.status??e.getChannelStatus(a.id);return o!=="connected"?s.status(409).send({code:"CONNECT_INCOMPLETE",message:`Channel connect finished with status "${o}"`,status:o}):{channelId:a.id,status:o}}catch(o){return s.status(500).send({code:"CONNECT_FAILED",message:D(o)})}}),t.post("/channels/:id/disconnect",{schema:{tags:["Channels"],summary:"Disconnect channel",params:{type:"object",required:["id"],properties:{id:{type:"string",format:"uuid"}}}}},async(r,s)=>{let i=P.safeParse(r.params);if(!i.success)return s.status(400).send({code:"VALIDATION_ERROR",message:g.prettifyError(i.error)});if(!e)return s.status(501).send({code:"NOT_IMPLEMENTED",message:"Channel manager not initialized"});let a=E(i.data.id);return a?(await e.disconnectChannel(a.id),{channelId:a.id,status:"disconnected"}):s.status(404).send({code:"NOT_FOUND",message:"Channel not found"})}),t.get("/channels/:id/capabilities",{schema:{tags:["Channels"],summary:"Get channel adapter capabilities",params:{type:"object",required:["id"],properties:{id:{type:"string",format:"uuid"}}}}},async(r,s)=>{let i=P.safeParse(r.params);if(!i.success)return s.status(400).send({code:"VALIDATION_ERROR",message:g.prettifyError(i.error)});if(!E(i.data.id))return s.status(404).send({code:"NOT_FOUND",message:"Channel not found"});if(!e)return s.status(503).send({code:"MANAGER_UNAVAILABLE",message:"ChannelManager not initialized"});let o=e.getCapabilities(i.data.id);return o?{capabilities:o}:s.status(404).send({code:"ADAPTER_NOT_REGISTERED",message:"Channel adapter not active"})}),t.get("/channels/:id/messages",{schema:{tags:["Channels"],summary:"Get channel message history",params:{type:"object",required:["id"],properties:{id:{type:"string",format:"uuid"}}},querystring:{type:"object",properties:{limit:{type:"integer",minimum:1,maximum:200,default:50},offset:{type:"integer",minimum:0,default:0}}}}},async(r,s)=>{let i=P.safeParse(r.params);if(!i.success)return s.status(400).send({code:"VALIDATION_ERROR",message:g.prettifyError(i.error)});let a=E(i.data.id);if(!a)return s.status(404).send({code:"NOT_FOUND",message:"Channel not found"});let{limit:o=50,offset:d=0}=r.query;return{messages:Qe(a.id,o,d)}}),t.post("/channels/:id/wechat/qr-start",{schema:{tags:["WeChat"],summary:"Start WeChat QR login",params:{type:"object",required:["id"],properties:{id:{type:"string",format:"uuid"}}}}},async(r,s)=>{let i=P.safeParse(r.params);if(!i.success)return s.status(400).send({code:"VALIDATION_ERROR",message:g.prettifyError(i.error)});let a=E(i.data.id);if(!a)return s.status(404).send({code:"NOT_FOUND",message:"Channel not found"});if(a.platform!=="wechat")return s.status(400).send({code:"INVALID_PLATFORM",message:"Channel is not a WeChat channel"});let o=a.config;return await at({apiBaseUrl:o.baseUrl,routeTag:o.routeTag})}),t.post("/channels/:id/wechat/qr-wait",{schema:{tags:["WeChat"],summary:"Wait for WeChat QR scan",params:{type:"object",required:["id"],properties:{id:{type:"string",format:"uuid"}}},body:{type:"object",properties:{sessionKey:{type:"string"},timeoutMs:{type:"number"}}}}},async(r,s)=>{let i=P.safeParse(r.params);if(!i.success)return s.status(400).send({code:"VALIDATION_ERROR",message:g.prettifyError(i.error)});let a=E(i.data.id);if(!a)return s.status(404).send({code:"NOT_FOUND",message:"Channel not found"});if(a.platform!=="wechat")return s.status(400).send({code:"INVALID_PLATFORM",message:"Channel is not a WeChat channel"});let o=a.config,{sessionKey:d,timeoutMs:c}=r.body??{},u=await ot({sessionKey:d??"",apiBaseUrl:o.baseUrl,timeoutMs:c??12e4,routeTag:o.routeTag});if(u.connected&&u.botToken){let p={...o,botToken:u.botToken,accountId:u.accountId,baseUrl:u.baseUrl??o.baseUrl,userId:u.userId};if(ne(a.id,{config:p}),e){let f=new q(a.id,p),m=E(a.id);m&&await e.addChannel(m,f)}}return{connected:u.connected,accountId:u.accountId,message:u.message}})}function D(t){return t instanceof Error?t.message.replace(/pass(word)?=[^\s]+/gi,"password=****"):String(t)}async function As(){let t=V().emailGateway;if(!t?.enabled)throw new Error("Email Gateway is disabled. Enable Email Gateway in Settings before connecting Mail channels.");let e=S();e.getStatus().status!=="connected"&&await ye(t);let n=e.getStatus();if(n.status!=="connected"){let r=n.lastError?`: ${n.lastError}`:"";throw new Error(`Email Gateway status is ${n.status}${r}`)}}export{Lt as a,G as b,Bt as c,S as d,jr as e,Vr as f,Ei as g,Ti as h,Li as i,Fi as j,Bi as k};
@@ -0,0 +1,6 @@
1
+ import{D as m,L as b}from"./chunk-2A2TXYT3.js";import{g as I,l as N,n as g,p as y}from"./chunk-WY5BOCQP.js";y();b();import{z as a}from"zod";var u=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i,U=/^role-[a-z0-9][a-z0-9-]*$/,P=/^tmpl-[a-f0-9]+$/,R=/^workflow-[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i,x=/^[a-z][a-z0-9]+-[a-z][a-z0-9-]+$/,k=/^[a-zA-Z][\w-]*@[a-zA-Z][\w-]*$/,O=/^(?:\/|~\/)/,_=/^[\p{L}0-9._-]+$/u,F=a.string().regex(u,"taskId must be a UUID (e.g., 'a1b2c3d4-...'). Use list_tasks to find existing IDs.").describe("Task ID (UUID). Use list_tasks or read_task_status to find existing IDs."),J=a.string().refine(e=>u.test(e)||U.test(e),{message:"roleId must be a UUID or a system role ID like 'role-chat-manager'. Use list_roles to find IDs (do NOT pass the Role's display name)."}).describe("Role ID (UUID or 'role-<name>' for presets). Use list_roles to find IDs \u2014 NOT the human-readable name."),W=a.string().regex(u,"goalId must be a UUID. Use list_goals to find existing IDs.").describe("Goal ID (UUID). Use list_goals to find existing IDs."),H=a.string().regex(u,"channelId must be a UUID. Use list_channels to find IDs (do NOT pass the channel's display name).").describe("Channel ID (UUID). Use list_channels to find IDs \u2014 NOT the channel's display name."),G=a.string().regex(u,"sessionId must be a UUID.").describe("Chat session ID (UUID)."),V=a.string().refine(e=>u.test(e)||P.test(e)||R.test(e)||x.test(e),{message:"templateId must be a UUID, 'tmpl-<hex>', 'workflow-<uuid>', or a friendly ID (e.g., 'pkos-scan-and-sync'). Use list_templates to find IDs."}).describe("Task template ID. Use list_templates to find IDs."),Y=a.string().regex(k,"pluginId must be '<name>@<scope>' (e.g., 'github@anthropic'). Use list_available_plugins to discover.").describe("Plugin ID in '<name>@<scope>' format (e.g., 'github@anthropic'). Use list_available_plugins to discover."),j=a.string().regex(u,"eventDefId must be a UUID. Use list_event_defs to find IDs.").describe("Event definition ID (UUID). Use list_event_defs to find IDs."),z=a.string().regex(u,"ruleId must be a UUID. Use list_delivery_rules to find IDs.").describe("Delivery rule ID (UUID). Use list_delivery_rules to find IDs."),K=a.string().regex(u,"strategyId must be a UUID. Use list_strategies to find IDs.").describe("Strategy ID (UUID). Use list_strategies to find IDs."),q=a.string().regex(O,"Path must be absolute ('/Users/.../file' or '~/...'). Do NOT use relative paths or remote URLs.").describe("Absolute local file path (e.g., '/Users/me/file.txt' or '~/Documents/file.txt'). Remote URLs are NOT accepted \u2014 download files locally first."),Q=a.string().regex(/^[A-Za-z0-9_-]{1,64}$/,"executionId must be 1-64 chars: letters, digits, dashes, underscores. Use list_template_executions or query_execution_status to find existing IDs.").describe("TemplateExecution ID. Use list_template_executions or query_execution_status to find existing IDs."),X=a.string().min(1).max(128).regex(_,"stepId must be 1-128 chars: letters (any script), digits, dots, underscores, or dashes.").describe("Template step ID \u2014 a human-readable identifier for a template step.");N();function L(e){if(e)return e.startsWith("event:")?e.slice(6):void 0}var c=class extends Error{constructor(n,r,i=[]){super(r);this.code=n;this.failingStepIds=i;this.name="TemplateValidationError"}code;failingStepIds},f=class extends Error{constructor(n,r){super(A(n,r));this.code=n;this.failingStepIds=r;this.name="TemplateRoleConfigError"}code;failingStepIds};function A(e,t){return e==="STEP_AUTOSELECT_NEEDS_REQUIREMENTS"?`Template has ${t.length} step(s) with autoSelectRole=true but no requirements object. Failing step ids: ${t.join(", ")}`:e==="STEP_ROLE_NOT_FOUND"?`Template has ${t.length} step(s) with a roleId that does not resolve to an active role. Failing step ids: ${t.join(", ")}`:`Template has ${t.length} step(s) without executable role config. Set template.rolePreference, OR set each failing step's roleId, OR set autoSelectRole=true. Failing step ids: ${t.join(", ")}`}function v(e){let t=typeof e.roleId=="string"&&e.roleId.length>0,n=e.autoSelectRole===!0;return t||n}function C(e){if(typeof e.roleId=="string"&&e.roleId.length>0){let t=m(e.roleId);if(!t||t.status!=="active")return{code:"STEP_ROLE_NOT_FOUND",stepId:e.id}}return e.autoSelectRole===!0&&e.requirements==null?{code:"STEP_AUTOSELECT_NEEDS_REQUIREMENTS",stepId:e.id}:null}function M(e){if(!e.rolePreference){let n=[];for(let r of e.steps)v(r)||n.push(r.id);if(n.length>0)throw new f("TEMPLATE_INVALID_ROLE_CONFIG",n)}let t=e.steps.map(n=>C(n)).filter(n=>n!==null);if(t.length>0){let n=t[0].code,r=t.filter(i=>i.code===n).map(i=>i.stepId);throw new f(n,r)}}function D(e){if(!Array.isArray(e.steps)||e.steps.length<1)throw new c("TEMPLATE_STEPS_REQUIRED","Template must contain at least one step.");let t=new Set,n=[],r=[];for(let s of e.steps)(typeof s.id!="string"||s.id.length<1||s.id.length>128||!_.test(s.id))&&r.push(s.id),t.has(s.id)&&n.push(s.id),t.add(s.id);if(r.length>0)throw new c("TEMPLATE_STEP_ID_INVALID",`Template has invalid step id(s): ${r.join(", ")}. Step ids must be 1-128 chars: letters, digits, dots, underscores, or dashes.`,r);if(n.length>0)throw new c("TEMPLATE_STEP_ID_DUPLICATE",`Template has duplicate step id(s): ${n.join(", ")}.`,n);let i=new Map;for(let s of e.steps){let o=s.dependsOn??[];i.set(s.id,o);for(let l of o){if(l===s.id)throw new c("TEMPLATE_DEPENDENCY_SELF",`Template step "${s.id}" cannot depend on itself.`,[s.id]);if(!t.has(l))throw new c("TEMPLATE_DEPENDENCY_UNKNOWN",`Template step "${s.id}" depends on unknown step "${l}".`,[s.id])}if(s.minDependencies!==void 0){if(!Number.isInteger(s.minDependencies)||s.minDependencies<1)throw new c("TEMPLATE_MIN_DEPENDENCIES_INVALID",`Step "${s.id}": minDependencies must be a positive integer`,[s.id]);let l=s.dependsOn?.length??0;if(s.minDependencies>l)throw new c("TEMPLATE_MIN_DEPENDENCIES_EXCEEDS",`Step "${s.id}": minDependencies (${s.minDependencies}) exceeds dependsOn length (${l})`,[s.id])}}let d=new Set,p=new Set,E=(s,o)=>{if(p.has(s))return[...o,s];if(d.has(s))return null;p.add(s);for(let l of i.get(s)??[]){let T=E(l,[...o,s]);if(T)return T}return p.delete(s),d.add(s),null};for(let s of e.steps){let o=E(s.id,[]);if(o)throw new c("TEMPLATE_DEPENDENCY_CYCLE",`Template step dependencies contain a cycle: ${o.join(" -> ")}.`,[...new Set(o)])}M(e)}function h(e){if(e.type!=="cron"&&e.type!=="manual"&&e.type!=="once"&&e.type!=="template_complete"&&e.type!=="event")throw new c("TEMPLATE_TRIGGER_INVALID",`Template trigger type is not supported: ${String(e.type)}.`);if(e.type==="template_complete"&&!/^template_complete:[\w-]+$/.test(e.event??""))throw new c("TEMPLATE_TRIGGER_INVALID","Template completion trigger event must use 'template_complete:<templateId>'.")}function S(e){let t=e.trigger_type,n={type:t,cron:t==="event"?void 0:e.trigger_cron??void 0,event:t==="event"?void 0:e.trigger_event??void 0,eventDefId:t==="event"?L(e.trigger_event):void 0,runAt:t==="once"?e.trigger_cron??void 0:void 0};return{id:e.id,name:e.name,description:e.description??void 0,trigger:n,steps:JSON.parse(e.steps),rolePreference:e.role_preference??void 0,config:e.config?JSON.parse(e.config):void 0,tags:e.tags?JSON.parse(e.tags):void 0,enabled:e.enabled===1,createdAt:e.created_at,updatedAt:e.updated_at??void 0,sourceSessionId:e.source_session_id??void 0,deliverTo:e.deliver_to?JSON.parse(e.deliver_to):void 0,reportTo:e.report_to?JSON.parse(e.report_to):void 0,goalIds:e.goal_ids?JSON.parse(e.goal_ids):void 0,isPreset:e.is_preset===1?!0:void 0,presetId:e.preset_id??void 0,retryPolicy:e.retry_policy?JSON.parse(e.retry_policy):void 0}}function se(e){D(e),h(e.trigger);let n=g().prepare(`
2
+ INSERT OR IGNORE INTO task_templates (id, name, description, trigger_type, trigger_cron,
3
+ trigger_event, steps, role_preference, config, tags, enabled, created_at, updated_at,
4
+ source_session_id, deliver_to, report_to, goal_ids, is_preset, preset_id, retry_policy)
5
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
6
+ `).run(e.id,e.name,e.description??null,e.trigger.type,e.trigger.type==="once"?e.trigger.runAt??null:e.trigger.cron??null,e.trigger.type==="event"?`event:${e.trigger.eventDefId}`:e.trigger.event??null,JSON.stringify(e.steps),e.rolePreference??null,e.config?JSON.stringify(e.config):null,e.tags?JSON.stringify(e.tags):null,e.enabled?1:0,e.createdAt??Date.now(),e.updatedAt??null,e.sourceSessionId??null,e.deliverTo?JSON.stringify(e.deliverTo):null,e.reportTo?JSON.stringify(e.reportTo):null,e.goalIds?JSON.stringify(e.goalIds):null,e.presetId!=null?1:0,e.presetId??null,e.retryPolicy?JSON.stringify(e.retryPolicy):null);return{changes:Number(n.changes)}}function $(e){let n=g().prepare("SELECT * FROM task_templates WHERE id = ?").get(e);return n?S(n):void 0}function re(e,t){let n=g();if("steps"in t||"rolePreference"in t){let d=$(e);if(d){let p={rolePreference:"rolePreference"in t?t.rolePreference:d.rolePreference,steps:"steps"in t&&t.steps?t.steps:d.steps};D(p)}}"trigger"in t&&t.trigger&&h(t.trigger);let r=[],i=[];"name"in t&&(r.push("name = ?"),i.push(t.name)),"description"in t&&(r.push("description = ?"),i.push(t.description??null)),"trigger"in t&&t.trigger&&(r.push("trigger_type = ?"),i.push(t.trigger.type),r.push("trigger_cron = ?"),i.push(t.trigger.type==="once"?t.trigger.runAt??null:t.trigger.cron??null),r.push("trigger_event = ?"),i.push(t.trigger.type==="event"?`event:${t.trigger.eventDefId}`:t.trigger.event??null)),"steps"in t&&(r.push("steps = ?"),i.push(JSON.stringify(t.steps))),"rolePreference"in t&&(r.push("role_preference = ?"),i.push(t.rolePreference??null)),"config"in t&&(r.push("config = ?"),i.push(t.config?JSON.stringify(t.config):null)),"tags"in t&&(r.push("tags = ?"),i.push(t.tags?JSON.stringify(t.tags):null)),"enabled"in t&&(r.push("enabled = ?"),i.push(t.enabled?1:0)),"sourceSessionId"in t&&(r.push("source_session_id = ?"),i.push(t.sourceSessionId??null)),"deliverTo"in t&&(r.push("deliver_to = ?"),i.push(t.deliverTo?JSON.stringify(t.deliverTo):null)),"reportTo"in t&&(r.push("report_to = ?"),i.push(t.reportTo?JSON.stringify(t.reportTo):null)),"goalIds"in t&&(r.push("goal_ids = ?"),i.push(t.goalIds?JSON.stringify(t.goalIds):null)),"isPreset"in t&&(r.push("is_preset = ?"),i.push(t.isPreset?1:0)),"presetId"in t&&(r.push("preset_id = ?"),i.push(t.presetId??null)),"retryPolicy"in t&&(r.push("retry_policy = ?"),i.push(t.retryPolicy?JSON.stringify(t.retryPolicy):null)),r.length!==0&&(r.push("updated_at = ?"),i.push(Date.now()),i.push(e),n.prepare(`UPDATE task_templates SET ${r.join(", ")} WHERE id = ?`).run(...i))}function ie(e=!1,t,n=0){let r=g(),i="SELECT * FROM task_templates",d=[];return e&&(i+=" WHERE enabled = 1"),i+=" ORDER BY COALESCE(updated_at, created_at) DESC",typeof t=="number"&&(i+=" LIMIT ? OFFSET ?",d.push(t,n)),r.prepare(i).all(...d).map(S)}function oe(e){g().prepare("UPDATE task_templates SET enabled = 1, updated_at = ? WHERE id = ?").run(Date.now(),e)}function le(e){g().prepare("UPDATE task_templates SET enabled = 0, updated_at = ? WHERE id = ?").run(Date.now(),e)}function ae(e){let t=g(),n=t.prepare("SELECT COUNT(*) AS n FROM template_executions WHERE template_id = ?").get(e),r=t.prepare("SELECT COUNT(*) AS n FROM tasks WHERE template_id = ?").get(e);return{executionCount:n.n,taskCount:r.n}}function de(e,t="template_only"){let n=g(),r=n.prepare("SELECT id FROM template_executions WHERE template_id = ?").all(e);n.transaction(()=>{if(t==="with_tasks"){let p=n.prepare("SELECT id FROM tasks WHERE template_id = ?").all(e).map(E=>E.id);if(p.length>0)for(let s=0;s<p.length;s+=500){let o=p.slice(s,s+500),l=o.map(()=>"?").join(",");n.prepare(`DELETE FROM role_scores WHERE task_id IN (${l})`).run(...o),n.prepare(`DELETE FROM manager_decisions WHERE task_id IN (${l})`).run(...o),n.prepare(`UPDATE chat_messages SET task_id = NULL WHERE task_id IN (${l})`).run(...o),n.prepare(`UPDATE approval_rules SET created_by_task_id = NULL WHERE created_by_task_id IN (${l})`).run(...o),n.prepare(`DELETE FROM tasks WHERE id IN (${l})`).run(...o)}}n.prepare("DELETE FROM template_executions WHERE template_id = ?").run(e),n.prepare("DELETE FROM task_templates WHERE id = ?").run(e)})();for(let d of r)I(d.id)}export{F as a,J as b,W as c,H as d,G as e,V as f,Y as g,j as h,z as i,K as j,q as k,Q as l,X as m,c as n,f as o,M as p,D as q,se as r,$ as s,re as t,ie as u,oe as v,le as w,ae as x,de as y};