adam-agent-server 1.5.0 → 1.6.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 (127) hide show
  1. package/dist/App-WJMHK5EO.js +13 -0
  2. package/dist/adam-automator-skills-UFW5TXCC.js +18 -0
  3. package/dist/adam-tools-IAZSLWYB.js +1 -0
  4. package/dist/approval-handler-HQO62WK2.js +1 -0
  5. package/dist/audit-manager-LC5EQXCI.js +1 -0
  6. package/dist/bree-engine-M5CZ6A62.js +1 -0
  7. package/dist/channels-5TFYQN5Z.js +1 -0
  8. package/dist/{channels-HYSB2EEK.js → channels-J4STJ4X2.js} +1 -1
  9. package/dist/{chunk-BR2JY5X2.js → chunk-2H7UOW4P.js} +1 -1
  10. package/dist/{chunk-VRJ7R766.js → chunk-3LY6PD6A.js} +1 -1
  11. package/dist/{chunk-YVS565QY.js → chunk-4C5ITATX.js} +1 -1
  12. package/dist/{chunk-R4GIIQ7G.js → chunk-52PR7XTN.js} +1 -1
  13. package/dist/chunk-5OQZPUBV.js +79 -0
  14. package/dist/{chunk-Y3AMO6WC.js → chunk-7446ZS6D.js} +1 -1
  15. package/dist/{chunk-GBTG5B5R.js → chunk-7ZGSJCX5.js} +1 -1
  16. package/dist/{chunk-QWCRZDZS.js → chunk-DBP7GPWG.js} +2 -2
  17. package/dist/{chunk-5XUR3M23.js → chunk-DWRYIN5N.js} +1 -1
  18. package/dist/{chunk-RAW263MQ.js → chunk-FIN36WAP.js} +4 -4
  19. package/dist/{chunk-2DLVAKH7.js → chunk-FXQAUQTI.js} +1 -1
  20. package/dist/{chunk-6FXNB7NE.js → chunk-FZCNYKNT.js} +1 -1
  21. package/dist/{chunk-7L2WQM7N.js → chunk-G5ESQEXN.js} +1 -1
  22. package/dist/chunk-GGIHDFRW.js +6 -0
  23. package/dist/{chunk-HDP7A4XY.js → chunk-GMMWA5EG.js} +1 -1
  24. package/dist/chunk-HWLSHTVX.js +27 -0
  25. package/dist/{chunk-ISZJV72D.js → chunk-I7ZZKPHE.js} +1 -1
  26. package/dist/{chunk-5V36ACKZ.js → chunk-IZNEOYRP.js} +1 -1
  27. package/dist/{chunk-6775OYXA.js → chunk-MDBVKBC7.js} +1 -1
  28. package/dist/chunk-MJSSCKMB.js +23 -0
  29. package/dist/{chunk-INNDBLZE.js → chunk-MRTJFYPR.js} +1 -1
  30. package/dist/{chunk-YHVFZB6Q.js → chunk-N4ES7TCL.js} +1 -1
  31. package/dist/{chunk-JAS3TUZX.js → chunk-NCFVJCNQ.js} +26 -7
  32. package/dist/{chunk-H7VDC6FY.js → chunk-P5ZXNBNV.js} +1 -1
  33. package/dist/{chunk-7K4AQBDD.js → chunk-PG6LMSX6.js} +1 -1
  34. package/dist/{chunk-QVKI7H7W.js → chunk-RLJYEEQC.js} +1 -1
  35. package/dist/{chunk-2CMR5AG7.js → chunk-SWP2JC54.js} +1 -1
  36. package/dist/{chunk-H54ZXA26.js → chunk-TNL2LZB7.js} +1 -1
  37. package/dist/{chunk-5S6BMWD2.js → chunk-TSPQ44HT.js} +1 -1
  38. package/dist/{chunk-Z4D3L2HR.js → chunk-V32YF3J5.js} +1 -1
  39. package/dist/{chunk-XL46AGRZ.js → chunk-VVSZZK5T.js} +2 -2
  40. package/dist/{chunk-HTPUEIFT.js → chunk-WAG3MNMC.js} +5 -5
  41. package/dist/{chunk-VRP4LTHY.js → chunk-YDVTWPNA.js} +1 -1
  42. package/dist/{chunk-C6BOQJJF.js → chunk-YHVYX3F4.js} +1 -1
  43. package/dist/{chunk-23VZKIB6.js → chunk-YXYIA24D.js} +1 -1
  44. package/dist/chunk-ZL5JXLAX.js +49 -0
  45. package/dist/cli.js +2 -2
  46. package/dist/{config-EMNKHR3W.js → config-KFPS7IEH.js} +1 -1
  47. package/dist/config-ZBNGRASI.js +1 -0
  48. package/dist/db-PZ2V7UCK.js +1 -0
  49. package/dist/delivery-log-ACNJ66RD.js +1 -0
  50. package/dist/engine-5DHYHDAP.js +1 -0
  51. package/dist/{evolution-audit-LZSQPDHH.js → evolution-audit-OQDGPKYI.js} +1 -1
  52. package/dist/{external-api-7XV2PXPC.js → external-api-V74YTLBY.js} +1 -1
  53. package/dist/index.js +16 -13
  54. package/dist/{learner-IJN6B7KV.js → learner-QCD6BH2J.js} +1 -1
  55. package/dist/{logger-QCJUU7GV.js → logger-WEXZORHP.js} +1 -1
  56. package/dist/{memories-ZII5QSTJ.js → memories-QGMRSBJJ.js} +1 -1
  57. package/dist/{memory-extractor-DIYJFBCI.js → memory-extractor-3MRK43A2.js} +2 -2
  58. package/dist/memory-service-M5ADGITG.js +1 -0
  59. package/dist/outbound-gateway-QRL36F7K.js +1 -0
  60. package/dist/role-presets-DLO3XS54.js +1 -0
  61. package/dist/role-workspace-URSOBCDH.js +1 -0
  62. package/dist/roles-KYXNMO5H.js +1 -0
  63. package/dist/session-manager-LZ77OT7A.js +1 -0
  64. package/dist/task-templates-YPNWJOVV.js +1 -0
  65. package/dist/workflow-executor-3WMS2WV3.js +1 -0
  66. package/package.json +1 -1
  67. package/web/dist/assets/{AlertDialog-r3y6IhpW.js → AlertDialog-CfeiyMrc.js} +1 -1
  68. package/web/dist/assets/{Button-BjXgrQ95.js → Button-DuQctNms.js} +1 -1
  69. package/web/dist/assets/{Card-C153tGfJ.js → Card-rKfViPS2.js} +1 -1
  70. package/web/dist/assets/{ChannelDetail-C2uAZv1u.js → ChannelDetail-DHT8fW0C.js} +1 -1
  71. package/web/dist/assets/{Channels-C62Qrg-n.js → Channels-YHGNXcRu.js} +2 -2
  72. package/web/dist/assets/{Chat-kH2owmB_.js → Chat-Dv_Izjx3.js} +1 -1
  73. package/web/dist/assets/{Dashboard-BhD8SpFb.js → Dashboard-DsHC5W4C.js} +1 -1
  74. package/web/dist/assets/{EmptyState-CXwJFCDQ.js → EmptyState-CIdIlMbn.js} +1 -1
  75. package/web/dist/assets/{EnvVarEditor-GSapLD96.js → EnvVarEditor-Dxy1Kz1Z.js} +1 -1
  76. package/web/dist/assets/EventDefDetail-CwprP2ch.js +1 -0
  77. package/web/dist/assets/Events-B19a8cEG.js +1 -0
  78. package/web/dist/assets/{Evolution-BO5hysLD.js → Evolution-DT6iZvil.js} +1 -1
  79. package/web/dist/assets/{GoalDetail-cxa8OvEi.js → GoalDetail-BALsnPQl.js} +1 -1
  80. package/web/dist/assets/{Goals-Dz3qqp_l.js → Goals-BJIsKgfH.js} +1 -1
  81. package/web/dist/assets/{Logs-Ckp3-hYV.js → Logs-Cv15aV3l.js} +1 -1
  82. package/web/dist/assets/{Memories-DEuSRoP3.js → Memories-CKAXhAso.js} +1 -1
  83. package/web/dist/assets/{NotFound-Bvn39vSk.js → NotFound-DitXhq_y.js} +1 -1
  84. package/web/dist/assets/{PageHeader-BMvN0xiB.js → PageHeader-CHSgtxPw.js} +1 -1
  85. package/web/dist/assets/Plugins-NO0S2spH.js +1 -0
  86. package/web/dist/assets/{RoleDetail-BWMjP9aZ.js → RoleDetail-1FNyCD4u.js} +2 -2
  87. package/web/dist/assets/{Roles-DD7NBDku.js → Roles-grfjw2zy.js} +1 -1
  88. package/web/dist/assets/{SectionHeader-CiCj3Is0.js → SectionHeader-C2WpiwJ5.js} +1 -1
  89. package/web/dist/assets/{Settings-BlU19KuR.js → Settings-9LRLfa_4.js} +1 -1
  90. package/web/dist/assets/{Strategies-CJ_q94-v.js → Strategies-BMyd_7_5.js} +1 -1
  91. package/web/dist/assets/{Switch-CoUUy5jr.js → Switch-CULsD-kC.js} +1 -1
  92. package/web/dist/assets/{Table-CaFJieh_.js → Table-DuOLbyJQ.js} +1 -1
  93. package/web/dist/assets/{TaskDetail-DVrjU-E6.js → TaskDetail-C2yXy8gE.js} +2 -2
  94. package/web/dist/assets/Work-dftf35Me.js +1 -0
  95. package/web/dist/assets/index-D4IubNPI.css +2 -0
  96. package/web/dist/assets/index-qYKJGoIB.js +2 -0
  97. package/web/dist/assets/{useIsMobileLayout-Bwrm84kJ.js → useIsMobileLayout-C6KIQjuh.js} +1 -1
  98. package/web/dist/assets/{vendor-icons-BlMaTTx3.js → vendor-icons-Dk0hMuJz.js} +1 -1
  99. package/web/dist/assets/{vendor-react-7e01TWy7.js → vendor-react-C6faO6LO.js} +1 -1
  100. package/web/dist/assets/{vendor-state-Bj70wnRm.js → vendor-state-DahK0J-G.js} +1 -1
  101. package/web/dist/index.html +7 -7
  102. package/dist/App-JGH6G5US.js +0 -13
  103. package/dist/adam-tools-W5AOIGEQ.js +0 -1
  104. package/dist/approval-handler-ORD4MUVM.js +0 -1
  105. package/dist/audit-manager-YCJT2WP5.js +0 -1
  106. package/dist/bree-engine-R5YLSDCL.js +0 -1
  107. package/dist/channels-JCMPPQED.js +0 -1
  108. package/dist/chunk-2YAP4YJV.js +0 -57
  109. package/dist/chunk-DZEVMYPB.js +0 -19
  110. package/dist/chunk-GY52JA5I.js +0 -10
  111. package/dist/chunk-MTWLLE26.js +0 -49
  112. package/dist/chunk-S3BAIZ4Q.js +0 -6
  113. package/dist/config-XMQS2NPT.js +0 -1
  114. package/dist/db-YUYXVV3A.js +0 -1
  115. package/dist/delivery-log-VKONLSVD.js +0 -1
  116. package/dist/engine-BM5BMPIC.js +0 -1
  117. package/dist/memory-service-QMYJPBAE.js +0 -1
  118. package/dist/outbound-gateway-6K6P2BEH.js +0 -1
  119. package/dist/role-presets-K2BDRZBS.js +0 -1
  120. package/dist/roles-L34L5MK3.js +0 -1
  121. package/dist/session-manager-GRJ3FV3L.js +0 -1
  122. package/dist/task-templates-23YOAF3E.js +0 -1
  123. package/dist/workflow-executor-JTUWX5DC.js +0 -1
  124. package/web/dist/assets/Plugins-CRym22JF.js +0 -1
  125. package/web/dist/assets/Work-BMl61RRi.js +0 -1
  126. package/web/dist/assets/index-DcXMQByM.css +0 -2
  127. package/web/dist/assets/index-pF--tN9F.js +0 -2
@@ -1 +1 @@
1
- import{a as le,b as x,c as J,d as ge,e as me}from"./chunk-23VZKIB6.js";import{f as ue}from"./chunk-HDP7A4XY.js";import{c as _,h as M}from"./chunk-INNDBLZE.js";import{z as g}from"zod/v4";import{v4 as Dt}from"uuid";import{randomUUID as be}from"crypto";import Ye from"crypto";var pe="2.1.7",F="bot";function Ze(t){let e=t.split(".").map(r=>parseInt(r,10)),s=e[0]??0,i=e[1]??0,n=e[2]??0;return(s&255)<<16|(i&255)<<8|n&255}var Y=Ze(pe),et=35e3,fe=15e3,tt=1e4;function L(){return{channel_version:pe}}function nt(t){return t.endsWith("/")?t:`${t}/`}function st(){let t=Ye.randomBytes(4).readUInt32BE(0);return Buffer.from(String(t),"utf-8").toString("base64")}function it(t){let e={"Content-Type":"application/json",AuthorizationType:"ilink_bot_token","Content-Length":String(Buffer.byteLength(t.body,"utf-8")),"X-WECHAT-UIN":st(),"iLink-App-Id":F,"iLink-App-ClientVersion":String(Y)};return t.token?.trim()&&(e.Authorization=`Bearer ${t.token.trim()}`),t.routeTag&&(e.SKRouteTag=t.routeTag),e}async function D(t){let e=nt(t.baseUrl),s=new URL(t.endpoint,e),i=it({token:t.token,routeTag:t.routeTag,body:t.body}),n=new AbortController,r=setTimeout(()=>n.abort(),t.timeoutMs);try{let o=await fetch(s.toString(),{method:"POST",headers:i,body:t.body,signal:n.signal});clearTimeout(r);let a=await o.text();if(!o.ok)throw new Error(`${t.label} ${o.status}: ${a}`);return a}catch(o){throw clearTimeout(r),o}}async function he(t){let e=t.timeoutMs??et;try{let s=await D({baseUrl:t.baseUrl,endpoint:"ilink/bot/getupdates",body:JSON.stringify({get_updates_buf:t.get_updates_buf??"",base_info:L()}),token:t.token,routeTag:t.routeTag,timeoutMs:e,label:"getUpdates"});return JSON.parse(s)}catch(s){if(s instanceof Error&&s.name==="AbortError")return{ret:0,msgs:[],get_updates_buf:t.get_updates_buf};throw s}}var rt={[-2]:2,[-3]:3},ot=1e3;async function E(t){let e=(await import("./logger-QCJUU7GV.js")).getLogger("channels"),s=new Map;for(;;){let i=await D({baseUrl:t.baseUrl,endpoint:"ilink/bot/sendmessage",body:JSON.stringify({...t.body,base_info:L()}),token:t.token,routeTag:t.routeTag,timeoutMs:t.timeoutMs??fe,label:"sendMessage"});e.info({status:200,responseBody:i.slice(0,300)},"apiFetch sendMessage response");try{let n=JSON.parse(i);if(n.ret&&n.ret!==0){let r=rt[n.ret],o=(s.get(n.ret)??0)+1;if(s.set(n.ret,o),r!==void 0&&o<r){e.warn({ret:n.ret,attempt:o,maxRetries:r},"sendMessage: retriable iLink error, retrying"),await new Promise(a=>setTimeout(a,ot*o));continue}throw e.error({ret:n.ret,errmsg:n.errmsg,attempt:o},"sendMessage: iLink API error, no more retries"),new Error(`sendMessage failed: iLink ret=${n.ret}${n.errmsg?` errmsg=${n.errmsg}`:""}`)}}catch(n){if(n instanceof SyntaxError)e.warn({rawText:i.slice(0,200)},"sendMessage: non-JSON response, treating as success");else throw n}return}}async function ye(t){await D({baseUrl:t.baseUrl,endpoint:"ilink/bot/sendtyping",body:JSON.stringify({...t.body,base_info:L()}),token:t.token,routeTag:t.routeTag,timeoutMs:t.timeoutMs??tt,label:"sendTyping"})}async function _e(t){let e=await D({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:L()}),token:t.token,routeTag:t.routeTag,timeoutMs:t.timeoutMs??fe,label:"getUploadUrl"});return JSON.parse(e)}var at=5*6e4,dt=35e3,we="3",w=new Map;function Z(t){return Date.now()-t.startedAt<at}function ct(){for(let[t,e]of w)Z(e)||w.delete(t)}async function xe(t,e,s){let i=t.endsWith("/")?t:`${t}/`,n=new URL(`ilink/bot/get_bot_qrcode?bot_type=${encodeURIComponent(e)}`,i),r={"iLink-App-Id":F};s&&(r.SKRouteTag=s);let o=await fetch(n.toString(),{headers:r});if(!o.ok){let a=await o.text().catch(()=>"(unreadable)");throw new Error(`Failed to fetch QR code: ${o.status} ${o.statusText} body=${a}`)}return await o.json()}async function ut(t,e,s){let i=t.endsWith("/")?t:`${t}/`,n=new URL(`ilink/bot/get_qrcode_status?qrcode=${encodeURIComponent(e)}`,i),r={"iLink-App-Id":F,"iLink-App-ClientVersion":String(Y)};s&&(r.SKRouteTag=s);let o=new AbortController,a=setTimeout(()=>o.abort(),dt);try{let d=await fetch(n.toString(),{headers:r,signal:o.signal});clearTimeout(a);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(a),d instanceof Error&&d.name==="AbortError")return{status:"wait"};throw d}}async function Ie(t){let e=t.accountId||be();ct();let s=w.get(e);if(!t.force&&s&&Z(s)&&s.qrcodeUrl)return{qrcodeUrl:s.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 i=t.botType||we,n=await xe(t.apiBaseUrl,i,t.routeTag),r={sessionKey:e,id:be(),qrcode:n.qrcode,qrcodeUrl:n.qrcode_img_content,startedAt:Date.now()};return w.set(e,r),{qrcodeUrl:n.qrcode_img_content,message:"Scan the QR code with WeChat to connect.",sessionKey:e}}catch(i){return{message:`Failed to start login: ${String(i)}`,sessionKey:e}}}var lt=3;async function Te(t){let e=w.get(t.sessionKey);if(!e)return{connected:!1,message:"No active login session. Start QR login first."};if(!Z(e))return w.delete(t.sessionKey),{connected:!1,message:"QR code expired. Please start again."};let s=Math.max(t.timeoutMs??48e4,1e3),i=Date.now()+s,n=1;for(;Date.now()<i;){try{let r=await ut(t.apiBaseUrl,e.qrcode,t.routeTag);switch(e.status=r.status,r.status){case"wait":break;case"scaned":break;case"expired":{if(n++,n>lt)return w.delete(t.sessionKey),{connected:!1,message:"Login timeout: QR expired multiple times."};try{let o=t.botType||we,a=await xe(t.apiBaseUrl,o,t.routeTag);e.qrcode=a.qrcode,e.qrcodeUrl=a.qrcode_img_content,e.startedAt=Date.now()}catch(o){return w.delete(t.sessionKey),{connected:!1,message:`QR refresh failed: ${String(o)}`}}break}case"confirmed":return r.ilink_bot_id?(w.delete(t.sessionKey),{connected:!0,botToken:r.bot_token,accountId:r.ilink_bot_id,baseUrl:r.baseurl,userId:r.ilink_user_id,message:"Connected to WeChat successfully!"}):(w.delete(t.sessionKey),{connected:!1,message:"Login failed: server did not return bot ID."})}}catch(r){return w.delete(t.sessionKey),{connected:!1,message:`Login failed: ${String(r)}`}}await new Promise(r=>setTimeout(r,1e3))}return w.delete(t.sessionKey),{connected:!1,message:"Login timeout. Please try again."}}import T from"fs";import*as R from"fs/promises";import I from"path";import{homedir as H}from"os";var W={IMAGE:1,VIDEO:2,FILE:3,VOICE:4},A={NONE:0,USER:1,BOT:2},y={NONE:0,TEXT:1,IMAGE:2,VOICE:3,FILE:4,VIDEO:5},P={NEW:0,GENERATING:1,FINISH:2},Re={TYPING:1,CANCEL:2};M();var gt=_("channels"),ee=-14,B=3600*1e3,C=new Map;function Me(t){let e=Date.now()+B;C.set(t,e),gt.info({channelId:t},`Session paused until ${new Date(e).toISOString()} (${B/1e3}s)`)}function j(t){let e=C.get(t);return e===void 0?!1:Date.now()>=e?(C.delete(t),!1):!0}function Ue(t){let e=C.get(t);if(e===void 0)return 0;let s=e-Date.now();return s<=0?(C.delete(t),0):s}function ke(t){C.delete(t)}M();import*as z from"fs/promises";import $e from"path";import{homedir as wt}from"os";import{createCipheriv as mt,createDecipheriv as pt}from"crypto";function Se(t,e){let s=mt("aes-128-ecb",e,null);return Buffer.concat([s.update(t),s.final()])}function Ce(t,e){let s=pt("aes-128-ecb",e,null);return Buffer.concat([s.update(t),s.final()])}function Ee(t){return Math.ceil((t+1)/16)*16}function te(t,e){return`${e}/download?encrypted_query_param=${encodeURIComponent(t)}`}function Ae(t){return`${t.cdnBaseUrl}/upload?encrypted_query_param=${encodeURIComponent(t.uploadParam)}&filekey=${encodeURIComponent(t.filekey)}`}M();var sn=_("channels");function ft(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 Pe(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 v(t){let{encryptQueryParam:e,aesKeyBase64:s,cdnBaseUrl:i,fullUrl:n}=t,r=ft(s),o=n?.trim()||(e?te(e,i):null);if(!o)throw new Error("CDN download: need full_url or encrypt_query_param");let a=await Pe(o);return Ce(a,r)}async function ve(t){let{encryptQueryParam:e,cdnBaseUrl:s,fullUrl:i}=t,n=i?.trim()||(e?te(e,s):null);if(!n)throw new Error("CDN download: need full_url or encrypt_query_param");return Pe(n)}M();var Q=_("channels"),Oe=24e3;function ht(t,e){let s=t.byteLength,i=44+s,n=Buffer.allocUnsafe(i),r=0;return n.write("RIFF",r),r+=4,n.writeUInt32LE(i-8,r),r+=4,n.write("WAVE",r),r+=4,n.write("fmt ",r),r+=4,n.writeUInt32LE(16,r),r+=4,n.writeUInt16LE(1,r),r+=2,n.writeUInt16LE(1,r),r+=2,n.writeUInt32LE(e,r),r+=4,n.writeUInt32LE(e*2,r),r+=4,n.writeUInt16LE(2,r),r+=2,n.writeUInt16LE(16,r),r+=2,n.write("data",r),r+=4,n.writeUInt32LE(s,r),r+=4,Buffer.from(t.buffer,t.byteOffset,t.byteLength).copy(n,r),n}async function qe(t){try{let{decode:e}=await import("silk-wasm");Q.debug(`silkToWav: decoding ${t.length} bytes of SILK`);let s=await e(t,Oe);Q.debug(`silkToWav: decoded duration=${s.duration}ms pcmBytes=${s.data.byteLength}`);let i=ht(s.data,Oe);return Q.debug(`silkToWav: WAV size=${i.length}`),i}catch(e){return Q.warn(`silkToWav: transcode failed, will use raw silk err=${String(e)}`),null}}import yt from"path";var _t={".pdf":"application/pdf",".doc":"application/msword",".docx":"application/vnd.openxmlformats-officedocument.wordprocessingml.document",".xls":"application/vnd.ms-excel",".xlsx":"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",".ppt":"application/vnd.ms-powerpoint",".pptx":"application/vnd.openxmlformats-officedocument.presentationml.presentation",".txt":"text/plain",".csv":"text/csv",".zip":"application/zip",".tar":"application/x-tar",".gz":"application/gzip",".mp3":"audio/mpeg",".ogg":"audio/ogg",".wav":"audio/wav",".amr":"audio/amr",".silk":"audio/x-silk",".mp4":"video/mp4",".mov":"video/quicktime",".webm":"video/webm",".mkv":"video/x-matroska",".avi":"video/x-msvideo",".png":"image/png",".jpg":"image/jpeg",".jpeg":"image/jpeg",".gif":"image/gif",".webp":"image/webp",".bmp":"image/bmp"},bt={"image/jpeg":".jpg","image/jpg":".jpg","image/png":".png","image/gif":".gif","image/webp":".webp","image/bmp":".bmp","video/mp4":".mp4","video/quicktime":".mov","video/webm":".webm","video/x-matroska":".mkv","video/x-msvideo":".avi","audio/mpeg":".mp3","audio/ogg":".ogg","audio/wav":".wav","audio/amr":".amr","audio/x-silk":".silk","application/pdf":".pdf","application/zip":".zip","application/x-tar":".tar","application/gzip":".gz","text/plain":".txt","text/csv":".csv"};function V(t){let e=yt.extname(t).toLowerCase();return _t[e]??"application/octet-stream"}function Ne(t){let e=t.split(";")[0].trim().toLowerCase();return bt[e]??".bin"}var S=_("channels"),Fe=100*1024*1024;function xt(t){return Ne(t)??".bin"}async function O(t,e,s,i,n=Fe,r){if(t.length>n)throw new Error(`Media too large: ${t.length} bytes exceeds ${n} bytes`);let o=$e.join(wt(),".adam","wechat","media",i,s);await z.mkdir(o,{recursive:!0});let a;if(r&&/^[a-zA-Z0-9._-]+$/.test(r))a=r;else{let c=e?xt(e):".bin",u=Date.now(),p=Math.random().toString(36).slice(2,7);a=`${u}-${p}${c}`}let d=$e.join(o,a);return await z.writeFile(d,t),S.debug(`saveMedia: saved ${t.length} bytes to ${d}`),d}async function Le(t,e){let{cdnBaseUrl:s,channelId:i}=e;if(t.type===y.IMAGE){let n=t.image_item;if(!n?.media?.encrypt_query_param&&!n?.media?.full_url)return null;let r=n.aeskey?Buffer.from(n.aeskey,"hex").toString("base64"):n.media?.aes_key;try{let o=r?await v({encryptQueryParam:n.media?.encrypt_query_param,aesKeyBase64:r,cdnBaseUrl:s,fullUrl:n.media?.full_url}):await ve({encryptQueryParam:n.media?.encrypt_query_param,cdnBaseUrl:s,fullUrl:n.media?.full_url});return{path:await O(o,"image/png","inbound",i),mimeType:"image/png",type:"image"}}catch(o){return S.error({channelId:i},`Image download/decrypt failed: ${String(o)}`),null}}if(t.type===y.VOICE){let n=t.voice_item;if(!n?.media?.encrypt_query_param&&!n?.media?.full_url||!n?.media?.aes_key)return null;try{let r=await v({encryptQueryParam:n.media.encrypt_query_param,aesKeyBase64:n.media.aes_key,cdnBaseUrl:s,fullUrl:n.media.full_url}),o=await qe(r);if(o){let a=await O(o,"audio/wav","inbound",i);return S.debug(`Voice: saved WAV to ${a}`),{path:a,mimeType:"audio/wav",type:"audio"}}else{let a=await O(r,"audio/silk","inbound",i);return S.debug(`Voice: silk transcode unavailable, saved raw SILK to ${a}`),{path:a,mimeType:"audio/silk",type:"audio"}}}catch(r){return S.error({channelId:i},`Voice download/transcode failed: ${String(r)}`),null}}if(t.type===y.FILE){let n=t.file_item;if(!n?.media?.encrypt_query_param&&!n?.media?.full_url||!n?.media?.aes_key)return null;try{let r=await v({encryptQueryParam:n.media.encrypt_query_param,aesKeyBase64:n.media.aes_key,cdnBaseUrl:s,fullUrl:n.media.full_url}),o=V(n.file_name??"file.bin");return{path:await O(r,o,"inbound",i,Fe,n.file_name),mimeType:o,type:"file"}}catch(r){return S.error({channelId:i},`File download failed: ${String(r)}`),null}}if(t.type===y.VIDEO){let n=t.video_item;if(!n?.media?.encrypt_query_param&&!n?.media?.full_url||!n?.media?.aes_key)return null;try{let r=await v({encryptQueryParam:n.media.encrypt_query_param,aesKeyBase64:n.media.aes_key,cdnBaseUrl:s,fullUrl:n.media.full_url});return{path:await O(r,"video/mp4","inbound",i),mimeType:"video/mp4",type:"video"}}catch(r){return S.error({channelId:i},`Video download failed: ${String(r)}`),null}}return null}import Be from"path";import ne from"crypto";import It from"fs/promises";M();var U=_("channels"),G=3;async function Tt(t){let{buf:e,uploadFullUrl:s,uploadParam:i,filekey:n,cdnBaseUrl:r,label:o,aeskey:a}=t,d=Se(e,a),c=s?.trim(),u;if(c)u=c;else if(i)u=Ae({cdnBaseUrl:r,uploadParam:i,filekey:n});else throw new Error(`${o}: CDN upload URL missing (need upload_full_url or upload_param)`);U.debug(`${o}: CDN POST url=${u} ciphertextSize=${d.length}`);let p,l;for(let h=1;h<=G;h++)try{let m=await fetch(u,{method:"POST",headers:{"Content-Type":"application/octet-stream"},body:new Uint8Array(d)});if(m.status>=400&&m.status<500){let b=m.headers.get("x-error-message")??await m.text();throw U.error(`${o}: CDN client error attempt=${h} status=${m.status} errMsg=${b}`),new Error(`CDN upload client error ${m.status}: ${b}`)}if(m.status!==200){let b=m.headers.get("x-error-message")??`status ${m.status}`;throw U.error(`${o}: CDN server error attempt=${h} status=${m.status} errMsg=${b}`),new Error(`CDN upload server error: ${b}`)}if(p=m.headers.get("x-encrypted-param")??void 0,!p)throw U.error(`${o}: CDN response missing x-encrypted-param header attempt=${h}`),new Error("CDN upload response missing x-encrypted-param header");U.debug(`${o}: CDN upload success attempt=${h}`);break}catch(m){if(l=m,m instanceof Error&&m.message.includes("client error"))throw m;h<G?U.warn(`${o}: attempt ${h} failed, retrying... err=${String(m)}`):U.error(`${o}: all ${G} attempts failed err=${String(m)}`)}if(!p)throw l instanceof Error?l:new Error(`CDN upload failed after ${G} attempts`);return{downloadParam:p}}async function se(t){let{filePath:e,toUserId:s,opts:i,cdnBaseUrl:n,mediaType:r,label:o}=t,a=await It.readFile(e),d=a.length,c=ne.createHash("md5").update(a).digest("hex"),u=Ee(d),p=ne.randomBytes(16).toString("hex"),l=ne.randomBytes(16);U.debug(`${o}: file=${e} rawsize=${d} filesize=${u} md5=${c} filekey=${p}`);let h=await _e({...i,filekey:p,media_type:r,to_user_id:s,rawsize:d,rawfilemd5:c,filesize:u,no_need_thumb:!0,aeskey:l.toString("hex")}),m=h.upload_full_url?.trim(),b=h.upload_param;if(!m&&!b)throw new Error(`${o}: getUploadUrl returned no upload URL (need upload_full_url or upload_param)`);let{downloadParam:Je}=await Tt({buf:a,uploadFullUrl:m||void 0,uploadParam:b??void 0,filekey:p,cdnBaseUrl:n,aeskey:l,label:`${o}[orig filekey=${p}]`});return{filekey:p,downloadEncryptedQueryParam:Je,aeskey:l.toString("hex"),fileSize:d,fileSizeCiphertext:u}}async function De(t){return se({...t,mediaType:W.IMAGE,label:"uploadImageToWeixin"})}async function We(t){return se({...t,mediaType:W.VIDEO,label:"uploadVideoToWeixin"})}async function ie(t){return se({...t,mediaType:W.FILE,label:"uploadFileAttachmentToWeixin"})}M();var q=_("channels");function Rt(){return`adam-wechat-${Date.now()}-${Math.random().toString(36).slice(2,7)}`}function Mt(t){let e=t;return e=e.replace(/```[^\n]*\n?([\s\S]*?)```/g,(s,i)=>i.trim()),e=e.replace(/!\[[^\]]*\]\([^)]*\)/g,""),e=e.replace(/\[([^\]]+)\]\([^)]*\)/g,"$1"),e=e.replace(/^\|[\s:|-]+\|$/gm,""),e=e.replace(/^\|(.+)\|$/gm,(s,i)=>i.split("|").map(n=>n.trim()).join(" ")),e}async function re(t){let{to:e,text:s,mediaItem:i,opts:n,label:r}=t,o=[],a=Mt(s);a&&o.push({type:y.TEXT,text_item:{text:a}}),o.push(i);let d="";for(let c of o){d=Rt();let u={msg:{from_user_id:"",to_user_id:e,client_id:d,message_type:A.BOT,message_state:P.FINISH,item_list:[c],context_token:n.contextToken}};await E({baseUrl:n.baseUrl,token:n.token,routeTag:n.routeTag,body:u})}return q.debug(`${r}: sent to=${e} messageId=${d}`),{messageId:d}}async function Ut(t){let{to:e,text:s,uploaded:i,opts:n}=t,r={type:y.IMAGE,image_item:{media:{encrypt_query_param:i.downloadEncryptedQueryParam,aes_key:Buffer.from(i.aeskey).toString("base64"),encrypt_type:1},mid_size:i.fileSizeCiphertext}};return re({to:e,text:s,mediaItem:r,opts:n,label:"sendImageMessage"})}async function kt(t){let{to:e,text:s,uploaded:i,opts:n}=t,r={type:y.VIDEO,video_item:{media:{encrypt_query_param:i.downloadEncryptedQueryParam,aes_key:Buffer.from(i.aeskey).toString("base64"),encrypt_type:1},video_size:i.fileSizeCiphertext}};return re({to:e,text:s,mediaItem:r,opts:n,label:"sendVideoMessage"})}async function je(t){let{to:e,text:s,fileName:i,uploaded:n,opts:r}=t,o={type:y.FILE,file_item:{media:{encrypt_query_param:n.downloadEncryptedQueryParam,aes_key:Buffer.from(n.aeskey).toString("base64"),encrypt_type:1},file_name:i,len:String(n.fileSize)}};return re({to:e,text:s,mediaItem:o,opts:r,label:"sendFileMessage"})}async function Qe(t){let{filePath:e,to:s,text:i,opts:n,cdnBaseUrl:r}=t,o=V(e),a={baseUrl:n.baseUrl,token:n.token,routeTag:n.routeTag};if(o.startsWith("video/")){q.debug(`sendWeixinMediaFile: uploading video filePath=${e} to=${s}`);let u=await We({filePath:e,toUserId:s,opts:a,cdnBaseUrl:r});return kt({to:s,text:i,uploaded:u,opts:n})}if(o.startsWith("image/")){q.debug(`sendWeixinMediaFile: uploading image filePath=${e} to=${s}`);let u=await De({filePath:e,toUserId:s,opts:a,cdnBaseUrl:r});return Ut({to:s,text:i,uploaded:u,opts:n})}if(o.startsWith("audio/")){let u=Be.basename(e);q.debug(`sendWeixinMediaFile: uploading audio as file filePath=${e} name=${u} to=${s}`);let p=await ie({filePath:e,fileName:u,toUserId:s,opts:a,cdnBaseUrl:r});return je({to:s,text:i,fileName:u,uploaded:p,opts:n})}let d=Be.basename(e);q.debug(`sendWeixinMediaFile: uploading file attachment filePath=${e} name=${d} to=${s}`);let c=await ie({filePath:e,fileName:d,toUserId:s,opts:a,cdnBaseUrl:r});return je({to:s,text:i,fileName:d,uploaded:c,opts:n})}M();var f=_("channels"),Ve="https://novac2c.cdn.weixin.qq.com/c2c",de=new Map;function Ke(t){return I.join(H(),".adam","wechat",`${t}.context-tokens.json`)}function St(t){let e=Ke(t);try{let s=T.readFileSync(e,"utf-8"),i=JSON.parse(s);for(let[n,r]of Object.entries(i))typeof r=="string"&&r&&de.set(`${t}:${n}`,r);f.debug({channelId:t,count:Object.keys(i).length},"Restored context tokens from disk")}catch{}}function Ct(t,e,s){let i=Ke(t);try{let n={};try{let o=T.readFileSync(i,"utf-8");n=JSON.parse(o)}catch{}n[e]=s;let r=I.dirname(i);T.mkdirSync(r,{recursive:!0}),T.writeFileSync(i,JSON.stringify(n),"utf-8")}catch(n){f.warn({channelId:t,userId:e},`Failed to persist context token: ${String(n)}`)}}function Et(t,e,s){de.set(`${t}:${e}`,s),Ct(t,e,s)}function oe(t,e){return de.get(`${t}:${e}`)}function He(t){return I.join(H(),".adam","wechat",`${t}.sync`)}function At(t){try{return T.readFileSync(He(t),"utf-8")}catch{return""}}function Pt(t,e){let s=He(t);T.mkdirSync(I.dirname(s),{recursive:!0}),T.writeFileSync(s,e,"utf-8")}var ae=1440*60*1e3,ze=10,vt=20,Ge=1440*60*1e3,Ot=1320*60*1e3,qt=1,Nt=7200*1e3;function Xe(t){return I.join(H(),".adam","wechat",`${t}.session.json`)}function $t(t){let e=new Map,s=Xe(t);try{let i=T.readFileSync(s,"utf-8"),n=JSON.parse(i);for(let[r,o]of Object.entries(n))o&&typeof o.lastUserMessageAt=="number"&&e.set(r,o);f.debug({channelId:t,count:e.size},"Restored sessions from disk")}catch{}return e}function N(t,e){let s=Xe(t);try{let i={};for(let[r,o]of e)i[r]=o;let n=I.dirname(s);T.mkdirSync(n,{recursive:!0}),T.writeFileSync(s,JSON.stringify(i),"utf-8")}catch(i){f.warn({channelId:t},`Failed to persist sessions: ${String(i)}`)}}var Ft=0;function $(){return`adam-wechat-${Date.now()}-${++Ft}`}var K=class{platform="wechat";id;config;status="disconnected";messageHandler=null;pollAbort=null;getUpdatesBuf="";sessions=new Map;pendingQueue=new Map;lastReminderAt=new Map;constructor(e,s){if(this.id=e,!s.baseUrl)throw new Error("WeChat adapter requires baseUrl");this.config=s}async connect(){if(!this.config.botToken)throw new Error("WeChat adapter requires botToken. Complete QR login first.");this.status="connecting",this.getUpdatesBuf=At(this.id),St(this.id),this.sessions=$t(this.id),this.pollAbort=new AbortController,this.status="connected",f.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",f.info({channelId:this.id},"WeChat adapter disconnected")}getStatus(){if(this.status==="connected"&&j(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}async sendMessage(e,s){if(j(this.id)){let c=Math.ceil(Ue(this.id)/6e4);throw new Error(`WeChat session paused, ${c} min remaining. Re-scan QR to reconnect.`)}let i=this.getOrCreateSession(e),r=this.getSessionRemainingMs(i)/36e5;if(!this.isSessionActive(i))return f.warn({channelId:this.id,chatId:e.slice(0,12),lastUserMessageAt:i.lastUserMessageAt,sessionExpired:!0},"iLink session expired (>24h), message queued"),this.enqueueMessage(e,s),`queued-${$()}`;if(i.quotaRemaining<=0)return f.warn({channelId:this.id,chatId:e.slice(0,12),quotaRemaining:0,remainingHours:r.toFixed(1)},"iLink quota exhausted, message queued"),this.enqueueMessage(e,s),`queued-${$()}`;let o=$(),a=oe(this.id,e),d=this.config.cdnBaseUrl??Ve;try{if(s.mediaUrl){let c=!s.mediaUrl.includes("://")||s.mediaUrl.startsWith("file://"),u=I.join(H(),".adam","wechat","media","outbound-tmp");await R.mkdir(u,{recursive:!0});let p=this.getExtensionFromMediaType(s.mediaType),l;if(c){let m=s.mediaUrl.startsWith("file://")?new URL(s.mediaUrl).pathname:I.isAbsolute(s.mediaUrl)?s.mediaUrl:I.resolve(s.mediaUrl),b=await R.readFile(m);l=I.join(u,`${Date.now()}-${Math.random().toString(36).slice(2,7)}${p}`),await R.writeFile(l,b)}else{let m=await fetch(s.mediaUrl);if(!m.ok)throw new Error(`Failed to fetch media: ${m.status}`);let b=Buffer.from(await m.arrayBuffer());l=I.join(u,`${Date.now()}-${Math.random().toString(36).slice(2,7)}${p}`),await R.writeFile(l,b)}let h=await Qe({filePath:l,to:e,text:s.content??"",opts:{baseUrl:this.config.baseUrl,token:this.config.botToken,routeTag:this.config.routeTag,contextToken:a},cdnBaseUrl:d});return await R.unlink(l).catch(()=>{}),i.quotaRemaining--,N(this.id,this.sessions),f.info({channelId:this.id,chatId:e.slice(0,12),quotaRemaining:i.quotaRemaining,sessionRemainingHours:(this.getSessionRemainingMs(i)/36e5).toFixed(1)},"iLink send success: quota decremented"),this.checkAndSendReminder(e,i).catch(m=>{f.warn({channelId:this.id,chatId:e.slice(0,12)},`Reminder send failed: ${String(m)}`)}),h.messageId}return await E({baseUrl:this.config.baseUrl,token:this.config.botToken,routeTag:this.config.routeTag,body:{msg:{from_user_id:"",to_user_id:e,client_id:o,message_type:A.BOT,message_state:P.FINISH,item_list:s.content?[{type:y.TEXT,text_item:{text:s.content}}]:void 0,context_token:a}}}),i.quotaRemaining--,N(this.id,this.sessions),f.info({channelId:this.id,chatId:e.slice(0,12),quotaRemaining:i.quotaRemaining,sessionRemainingHours:(this.getSessionRemainingMs(i)/36e5).toFixed(1)},"iLink send success: quota decremented"),this.checkAndSendReminder(e,i).catch(c=>{f.warn({channelId:this.id,chatId:e.slice(0,12)},`Reminder send failed: ${String(c)}`)}),o}catch(c){if(c instanceof Error&&c.message.includes("ret=-2"))return i.quotaRemaining=0,N(this.id,this.sessions),f.warn({channelId:this.id,chatId:e.slice(0,12),quotaRemaining:0},"iLink quota exhausted (ret=-2 confirmed), message queued"),this.enqueueMessage(e,s),`queued-${$()}`;throw c}}onMessage(e){this.messageHandler=e}async sendTypingIndicator(e){if(j(this.id))return;let s=oe(this.id,e);try{await ye({baseUrl:this.config.baseUrl,token:this.config.botToken,routeTag:this.config.routeTag,body:{ilink_user_id:e,status:Re.TYPING}})}catch{}}updateConfig(e){Object.assign(this.config,e)}getOrCreateSession(e){let s=this.sessions.get(e);return s||(s={lastUserMessageAt:0,quotaRemaining:0},this.sessions.set(e,s)),s}isSessionActive(e){return e.lastUserMessageAt>0&&Date.now()-e.lastUserMessageAt<=ae}getSessionRemainingMs(e){return e.lastUserMessageAt===0?0:Math.max(0,ae-(Date.now()-e.lastUserMessageAt))}enqueueMessage(e,s){let i=this.pendingQueue.get(e);i||(i=[],this.pendingQueue.set(e,i));let n=Date.now();i=i.filter(r=>n-r.queuedAt<Ge),i.length>=vt&&(i.shift(),f.warn({channelId:this.id,chatId:e.slice(0,12)},"Queue full, dropping oldest message")),i.push({message:s,queuedAt:n}),this.pendingQueue.set(e,i),f.info({channelId:this.id,chatId:e.slice(0,12),queueDepth:i.length},"Message enqueued")}async flushQueue(e){let s=this.pendingQueue.get(e);if(!s||s.length===0)return;let i=this.getOrCreateSession(e),n=Math.min(s.length,Math.max(0,i.quotaRemaining-2));if(n<=0){f.info({channelId:this.id,chatId:e.slice(0,12),quotaRemaining:i.quotaRemaining},"Queue flush skipped: insufficient quota (reserving 2 for conversation)");return}f.info({channelId:this.id,chatId:e.slice(0,12),queueDepth:s.length,sending:n,quotaRemaining:i.quotaRemaining},"Flushing queued messages");let r=0;for(;r<n&&s.length>0;){let o=s[0];if(Date.now()-o.queuedAt>Ge){s.shift();continue}try{if(await this.sendMessage(e,o.message),s.shift(),r++,i.quotaRemaining<=0)break}catch{f.warn({channelId:this.id,chatId:e.slice(0,12)},"Queue flush: send failed, stopping");break}}s.length===0&&this.pendingQueue.delete(e),f.info({channelId:this.id,chatId:e.slice(0,12),sent:r,remaining:s.length},"Queue flush complete")}async checkAndSendReminder(e,s){let i=Date.now(),n=this.lastReminderAt.get(e)??0;if(i-n<Nt)return;let r=this.getSessionRemainingMs(s),a=i-s.lastUserMessageAt>=Ot,d=s.quotaRemaining<=qt;if(!a&&!d)return;let c=(r/36e5).toFixed(1),u;a&&d?u=`[\u7CFB\u7EDF\u63D0\u9192] \u6D88\u606F\u7A97\u53E3\u5373\u5C06\u5173\u95ED\uFF08\u5269\u4F59${c}\u5C0F\u65F6/${s.quotaRemaining}\u6761\u914D\u989D\uFF09\u3002\u8BF7\u56DE\u590D\u4EFB\u610F\u6D88\u606F\u4EE5\u4FDD\u6301\u8FDE\u63A5\u3002`:a?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${s.quotaRemaining}\u6761\uFF09\u3002\u8BF7\u56DE\u590D\u4EFB\u610F\u6D88\u606F\u4EE5\u91CD\u7F6E\u914D\u989D\u3002`;let p=oe(this.id,e);try{await E({baseUrl:this.config.baseUrl,token:this.config.botToken,routeTag:this.config.routeTag,body:{msg:{from_user_id:"",to_user_id:e,client_id:$(),message_type:A.BOT,message_state:P.FINISH,item_list:[{type:y.TEXT,text_item:{text:u}}],context_token:p}}}),s.quotaRemaining--,this.lastReminderAt.set(e,i),N(this.id,this.sessions),f.info({channelId:this.id,chatId:e.slice(0,12),remainingHours:c,quotaRemaining:s.quotaRemaining,trigger:a?"time":"quota"},"iLink session reminder sent")}catch(l){f.warn({channelId:this.id,chatId:e.slice(0,12)},`Reminder send failed: ${String(l)}`)}}async startLongPoll(){let e=this.pollAbort?.signal,s=0,i=3,n=3e4,r=2e3;for(;!e?.aborted;)try{let o=await he({baseUrl:this.config.baseUrl,token:this.config.botToken,routeTag:this.config.routeTag,get_updates_buf:this.getUpdatesBuf});if(o.ret===ee||o.errcode===ee){Me(this.id),this.status="error",f.error({channelId:this.id},"Session expired (errcode=-14), pausing for 1 hour"),await this.sleep(B,e),ke(this.id),this.status="connected";continue}if(o.ret!==void 0&&o.ret!==0||o.errcode!==void 0&&o.errcode!==0){s++,f.error({channelId:this.id,ret:o.ret,errcode:o.errcode},"getUpdates API error"),s>=i?(s=0,await this.sleep(n,e)):await this.sleep(r,e);continue}s=0,o.get_updates_buf&&(this.getUpdatesBuf=o.get_updates_buf,Pt(this.id,o.get_updates_buf));for(let d of o.msgs??[])await this.processInbound(d)}catch(o){if(e?.aborted)return;s++,f.error({channelId:this.id,error:o},"getUpdates error"),s>=i?(s=0,await this.sleep(n,e)):await this.sleep(r,e)}}async processInbound(e){if(!this.messageHandler)return;let s=!!e.group_id,i=s?e.group_id:e.from_user_id??"",n=e.from_user_id??"";e.context_token&&i&&Et(this.id,i,e.context_token);let r=this.getOrCreateSession(i),o=r.quotaRemaining;r.lastUserMessageAt=Date.now(),r.quotaRemaining=ze,N(this.id,this.sessions),f.info({channelId:this.id,chatId:i.slice(0,12),quotaReset:!0,prevQuota:o,newQuota:ze,sessionWindowMs:ae},"iLink session reset: user message received, quota restored"),this.flushQueue(i);let a="",d,c=[];for(let l of e.item_list??[])l.type===y.TEXT&&l.text_item?.text&&(a+=l.text_item.text),l.type===y.IMAGE&&(d="image",c.push(l)),l.type===y.VOICE&&(d="audio",c.push(l),l.voice_item?.text&&!a&&(a=l.voice_item.text)),l.type===y.FILE&&(d="file",c.push(l)),l.type===y.VIDEO&&(d="video",c.push(l));if(!a&&!d)return;let u;if(c.length>0){let l=this.config.cdnBaseUrl??Ve;try{let h=await Le(c[0],{cdnBaseUrl:l,channelId:this.id});h&&(u=h.path,d=h.type)}catch(h){f.error({channelId:this.id},`Media download failed: ${String(h)}`)}}let p={channelId:this.id,platform:"wechat",chatId:i,senderId:n,content:a,mediaType:d,mediaPath:u,isGroup:s,timestamp:e.create_time_ms??Date.now(),raw:e};this.messageHandler(p)}getExtensionFromMediaType(e){switch(e){case"image":return".png";case"video":return".mp4";case"audio":return".mp3";default:return".bin"}}sleep(e,s){return new Promise((i,n)=>{let r=setTimeout(i,e);s?.addEventListener("abort",()=>{clearTimeout(r),n(new Error("aborted"))},{once:!0})})}};M();var Lt=_("channels"),X=class{platform="discord";id;config;status="disconnected";messageHandler=null;client=null;constructor(e,s){if(this.id=e,!s.botToken)throw new Error("Discord adapter requires botToken");this.config=s}async connect(){this.status="connecting";try{let{Client:e,GatewayIntentBits:s}=await import("discord.js");this.client=new e({intents:[s.Guilds,s.GuildMessages,s.MessageContent,s.DirectMessages]});let i=this.client;i.on("messageCreate",n=>{if(!this.messageHandler||n.author.bot||this.config.allowedGuildIds?.length&&n.guildId&&!this.config.allowedGuildIds.includes(n.guildId))return;let r={channelId:this.id,platform:"discord",chatId:n.channelId,senderId:n.author.id,senderName:n.author.displayName??n.author.username,content:n.content,isGroup:!!n.guildId,timestamp:n.createdTimestamp,raw:n};this.messageHandler(r)}),await i.login(this.config.botToken),this.status="connected",Lt.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}async sendMessage(e,s){if(!this.client)throw new Error("Discord client not connected");let n=await this.client.channels.fetch(e);if(!n||!("send"in n))throw new Error(`Channel ${e} not found or not text channel`);return(await n.send({content:s.content,reply:s.replyToMessageId?{messageReference:s.replyToMessageId}:void 0})).id}onMessage(e){this.messageHandler=e}async sendTypingIndicator(e){if(!this.client)return;let i=await this.client.channels.fetch(e);i&&"sendTyping"in i&&await i.sendTyping()}};var k=g.object({id:g.string().uuid()}),Wt=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()}),Bt=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()}),ce;function Zn(t){ce=t}function es(){return ce}async function ts(t){let e=ce;t.get("/channels",{schema:{tags:["Channels"],summary:"List channels",querystring:{type:"object",properties:{enabled:{type:"boolean"}}}}},async(s,i)=>({channels:ge(s.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(s,i)=>{let n=Wt.safeParse(s.body);if(!n.success)return i.status(400).send({code:"VALIDATION_ERROR",message:g.prettifyError(n.error)});let{name:r,platform:o,config:a,enabled:d,linkedRoleId:c,allowedChatIds:u}=n.data,p={id:Dt(),name:r,platform:o,enabled:d,status:"disconnected",config:a,linkedRoleId:c,allowedChatIds:u,createdAt:Date.now(),messageCount:0};return le(p),i.status(201).send({channel:p})}),t.get("/channels/:id",{schema:{tags:["Channels"],summary:"Get channel by ID",params:{type:"object",required:["id"],properties:{id:{type:"string",format:"uuid"}}}}},async(s,i)=>{let n=k.safeParse(s.params);if(!n.success)return i.status(400).send({code:"VALIDATION_ERROR",message:g.prettifyError(n.error)});let r=x(n.data.id);return r?{channel:r}:i.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"}}}}}},async(s,i)=>{let n=k.safeParse(s.params);if(!n.success)return i.status(400).send({code:"VALIDATION_ERROR",message:g.prettifyError(n.error)});let r=x(n.data.id);if(!r)return i.status(404).send({code:"NOT_FOUND",message:"Channel not found"});let o=Bt.safeParse(s.body);return o.success?(J(r.id,o.data),{channel:x(r.id)}):i.status(400).send({code:"VALIDATION_ERROR",message:g.prettifyError(o.error)})}),t.delete("/channels/:id",{schema:{tags:["Channels"],summary:"Delete channel",params:{type:"object",required:["id"],properties:{id:{type:"string",format:"uuid"}}}}},async(s,i)=>{let n=k.safeParse(s.params);if(!n.success)return i.status(400).send({code:"VALIDATION_ERROR",message:g.prettifyError(n.error)});let r=x(n.data.id);return r?(me(r.id),i.status(204).send()):i.status(404).send({code:"NOT_FOUND",message:"Channel not found"})}),t.post("/channels/:id/connect",{schema:{tags:["Channels"],summary:"Connect channel",params:{type:"object",required:["id"],properties:{id:{type:"string",format:"uuid"}}}}},async(s,i)=>{let n=k.safeParse(s.params);if(!n.success)return i.status(400).send({code:"VALIDATION_ERROR",message:g.prettifyError(n.error)});if(!e)return i.status(501).send({code:"NOT_IMPLEMENTED",message:"Channel manager not initialized"});let r=x(n.data.id);if(!r)return i.status(404).send({code:"NOT_FOUND",message:"Channel not found"});if(!e.hasAdapter(r.id)&&r.platform==="discord"){let o=r.config;if(!o.botToken)return i.status(400).send({code:"MISSING_CONFIG",message:"Discord channel requires botToken in config"});let a=new X(r.id,{botToken:o.botToken});await e.addChannel(r,a)}if(!e.hasAdapter(r.id))return i.status(400).send({code:"NO_ADAPTER",message:"No adapter registered for this channel. Install the appropriate adapter first."});try{return await e.connectChannel(r.id),{channelId:r.id,status:"connected"}}catch(o){return i.status(500).send({code:"CONNECT_FAILED",message:String(o)})}}),t.post("/channels/:id/disconnect",{schema:{tags:["Channels"],summary:"Disconnect channel",params:{type:"object",required:["id"],properties:{id:{type:"string",format:"uuid"}}}}},async(s,i)=>{let n=k.safeParse(s.params);if(!n.success)return i.status(400).send({code:"VALIDATION_ERROR",message:g.prettifyError(n.error)});if(!e)return i.status(501).send({code:"NOT_IMPLEMENTED",message:"Channel manager not initialized"});let r=x(n.data.id);return r?(await e.disconnectChannel(r.id),{channelId:r.id,status:"disconnected"}):i.status(404).send({code:"NOT_FOUND",message:"Channel not found"})}),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(s,i)=>{let n=k.safeParse(s.params);if(!n.success)return i.status(400).send({code:"VALIDATION_ERROR",message:g.prettifyError(n.error)});let r=x(n.data.id);if(!r)return i.status(404).send({code:"NOT_FOUND",message:"Channel not found"});let{limit:o=50,offset:a=0}=s.query;return{messages:ue(r.id,o,a)}}),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(s,i)=>{let n=k.safeParse(s.params);if(!n.success)return i.status(400).send({code:"VALIDATION_ERROR",message:g.prettifyError(n.error)});let r=x(n.data.id);if(!r)return i.status(404).send({code:"NOT_FOUND",message:"Channel not found"});if(r.platform!=="wechat")return i.status(400).send({code:"INVALID_PLATFORM",message:"Channel is not a WeChat channel"});let o=r.config;return await Ie({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(s,i)=>{let n=k.safeParse(s.params);if(!n.success)return i.status(400).send({code:"VALIDATION_ERROR",message:g.prettifyError(n.error)});let r=x(n.data.id);if(!r)return i.status(404).send({code:"NOT_FOUND",message:"Channel not found"});if(r.platform!=="wechat")return i.status(400).send({code:"INVALID_PLATFORM",message:"Channel is not a WeChat channel"});let o=r.config,{sessionKey:a,timeoutMs:d}=s.body??{},c=await Te({sessionKey:a??"",apiBaseUrl:o.baseUrl,timeoutMs:d??12e4,routeTag:o.routeTag});if(c.connected&&c.botToken){let u={...o,botToken:c.botToken,accountId:c.accountId,baseUrl:c.baseUrl??o.baseUrl,userId:c.userId};if(J(r.id,{config:u}),e){let p=new K(r.id,u),l=x(r.id);l&&await e.addChannel(l,p)}}return{connected:c.connected,accountId:c.accountId,message:c.message}})}export{K as a,X as b,Zn as c,es as d,ts as e};
1
+ import{f as ue}from"./chunk-GMMWA5EG.js";import{a as le,b as x,c as J,d as ge,e as me}from"./chunk-YXYIA24D.js";import{c as _,h as M}from"./chunk-MRTJFYPR.js";import{z as g}from"zod/v4";import{v4 as Dt}from"uuid";import{randomUUID as be}from"crypto";import Ye from"crypto";var pe="2.1.7",F="bot";function Ze(t){let e=t.split(".").map(r=>parseInt(r,10)),s=e[0]??0,i=e[1]??0,n=e[2]??0;return(s&255)<<16|(i&255)<<8|n&255}var Y=Ze(pe),et=35e3,fe=15e3,tt=1e4;function L(){return{channel_version:pe}}function nt(t){return t.endsWith("/")?t:`${t}/`}function st(){let t=Ye.randomBytes(4).readUInt32BE(0);return Buffer.from(String(t),"utf-8").toString("base64")}function it(t){let e={"Content-Type":"application/json",AuthorizationType:"ilink_bot_token","Content-Length":String(Buffer.byteLength(t.body,"utf-8")),"X-WECHAT-UIN":st(),"iLink-App-Id":F,"iLink-App-ClientVersion":String(Y)};return t.token?.trim()&&(e.Authorization=`Bearer ${t.token.trim()}`),t.routeTag&&(e.SKRouteTag=t.routeTag),e}async function D(t){let e=nt(t.baseUrl),s=new URL(t.endpoint,e),i=it({token:t.token,routeTag:t.routeTag,body:t.body}),n=new AbortController,r=setTimeout(()=>n.abort(),t.timeoutMs);try{let o=await fetch(s.toString(),{method:"POST",headers:i,body:t.body,signal:n.signal});clearTimeout(r);let a=await o.text();if(!o.ok)throw new Error(`${t.label} ${o.status}: ${a}`);return a}catch(o){throw clearTimeout(r),o}}async function he(t){let e=t.timeoutMs??et;try{let s=await D({baseUrl:t.baseUrl,endpoint:"ilink/bot/getupdates",body:JSON.stringify({get_updates_buf:t.get_updates_buf??"",base_info:L()}),token:t.token,routeTag:t.routeTag,timeoutMs:e,label:"getUpdates"});return JSON.parse(s)}catch(s){if(s instanceof Error&&s.name==="AbortError")return{ret:0,msgs:[],get_updates_buf:t.get_updates_buf};throw s}}var rt={[-2]:2,[-3]:3},ot=1e3;async function E(t){let e=(await import("./logger-WEXZORHP.js")).getLogger("channels"),s=new Map;for(;;){let i=await D({baseUrl:t.baseUrl,endpoint:"ilink/bot/sendmessage",body:JSON.stringify({...t.body,base_info:L()}),token:t.token,routeTag:t.routeTag,timeoutMs:t.timeoutMs??fe,label:"sendMessage"});e.info({status:200,responseBody:i.slice(0,300)},"apiFetch sendMessage response");try{let n=JSON.parse(i);if(n.ret&&n.ret!==0){let r=rt[n.ret],o=(s.get(n.ret)??0)+1;if(s.set(n.ret,o),r!==void 0&&o<r){e.warn({ret:n.ret,attempt:o,maxRetries:r},"sendMessage: retriable iLink error, retrying"),await new Promise(a=>setTimeout(a,ot*o));continue}throw e.error({ret:n.ret,errmsg:n.errmsg,attempt:o},"sendMessage: iLink API error, no more retries"),new Error(`sendMessage failed: iLink ret=${n.ret}${n.errmsg?` errmsg=${n.errmsg}`:""}`)}}catch(n){if(n instanceof SyntaxError)e.warn({rawText:i.slice(0,200)},"sendMessage: non-JSON response, treating as success");else throw n}return}}async function ye(t){await D({baseUrl:t.baseUrl,endpoint:"ilink/bot/sendtyping",body:JSON.stringify({...t.body,base_info:L()}),token:t.token,routeTag:t.routeTag,timeoutMs:t.timeoutMs??tt,label:"sendTyping"})}async function _e(t){let e=await D({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:L()}),token:t.token,routeTag:t.routeTag,timeoutMs:t.timeoutMs??fe,label:"getUploadUrl"});return JSON.parse(e)}var at=5*6e4,dt=35e3,we="3",w=new Map;function Z(t){return Date.now()-t.startedAt<at}function ct(){for(let[t,e]of w)Z(e)||w.delete(t)}async function xe(t,e,s){let i=t.endsWith("/")?t:`${t}/`,n=new URL(`ilink/bot/get_bot_qrcode?bot_type=${encodeURIComponent(e)}`,i),r={"iLink-App-Id":F};s&&(r.SKRouteTag=s);let o=await fetch(n.toString(),{headers:r});if(!o.ok){let a=await o.text().catch(()=>"(unreadable)");throw new Error(`Failed to fetch QR code: ${o.status} ${o.statusText} body=${a}`)}return await o.json()}async function ut(t,e,s){let i=t.endsWith("/")?t:`${t}/`,n=new URL(`ilink/bot/get_qrcode_status?qrcode=${encodeURIComponent(e)}`,i),r={"iLink-App-Id":F,"iLink-App-ClientVersion":String(Y)};s&&(r.SKRouteTag=s);let o=new AbortController,a=setTimeout(()=>o.abort(),dt);try{let d=await fetch(n.toString(),{headers:r,signal:o.signal});clearTimeout(a);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(a),d instanceof Error&&d.name==="AbortError")return{status:"wait"};throw d}}async function Ie(t){let e=t.accountId||be();ct();let s=w.get(e);if(!t.force&&s&&Z(s)&&s.qrcodeUrl)return{qrcodeUrl:s.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 i=t.botType||we,n=await xe(t.apiBaseUrl,i,t.routeTag),r={sessionKey:e,id:be(),qrcode:n.qrcode,qrcodeUrl:n.qrcode_img_content,startedAt:Date.now()};return w.set(e,r),{qrcodeUrl:n.qrcode_img_content,message:"Scan the QR code with WeChat to connect.",sessionKey:e}}catch(i){return{message:`Failed to start login: ${String(i)}`,sessionKey:e}}}var lt=3;async function Te(t){let e=w.get(t.sessionKey);if(!e)return{connected:!1,message:"No active login session. Start QR login first."};if(!Z(e))return w.delete(t.sessionKey),{connected:!1,message:"QR code expired. Please start again."};let s=Math.max(t.timeoutMs??48e4,1e3),i=Date.now()+s,n=1;for(;Date.now()<i;){try{let r=await ut(t.apiBaseUrl,e.qrcode,t.routeTag);switch(e.status=r.status,r.status){case"wait":break;case"scaned":break;case"expired":{if(n++,n>lt)return w.delete(t.sessionKey),{connected:!1,message:"Login timeout: QR expired multiple times."};try{let o=t.botType||we,a=await xe(t.apiBaseUrl,o,t.routeTag);e.qrcode=a.qrcode,e.qrcodeUrl=a.qrcode_img_content,e.startedAt=Date.now()}catch(o){return w.delete(t.sessionKey),{connected:!1,message:`QR refresh failed: ${String(o)}`}}break}case"confirmed":return r.ilink_bot_id?(w.delete(t.sessionKey),{connected:!0,botToken:r.bot_token,accountId:r.ilink_bot_id,baseUrl:r.baseurl,userId:r.ilink_user_id,message:"Connected to WeChat successfully!"}):(w.delete(t.sessionKey),{connected:!1,message:"Login failed: server did not return bot ID."})}}catch(r){return w.delete(t.sessionKey),{connected:!1,message:`Login failed: ${String(r)}`}}await new Promise(r=>setTimeout(r,1e3))}return w.delete(t.sessionKey),{connected:!1,message:"Login timeout. Please try again."}}import T from"fs";import*as R from"fs/promises";import I from"path";import{homedir as H}from"os";var W={IMAGE:1,VIDEO:2,FILE:3,VOICE:4},A={NONE:0,USER:1,BOT:2},y={NONE:0,TEXT:1,IMAGE:2,VOICE:3,FILE:4,VIDEO:5},P={NEW:0,GENERATING:1,FINISH:2},Re={TYPING:1,CANCEL:2};M();var gt=_("channels"),ee=-14,B=3600*1e3,C=new Map;function Me(t){let e=Date.now()+B;C.set(t,e),gt.info({channelId:t},`Session paused until ${new Date(e).toISOString()} (${B/1e3}s)`)}function j(t){let e=C.get(t);return e===void 0?!1:Date.now()>=e?(C.delete(t),!1):!0}function Ue(t){let e=C.get(t);if(e===void 0)return 0;let s=e-Date.now();return s<=0?(C.delete(t),0):s}function ke(t){C.delete(t)}M();import*as z from"fs/promises";import $e from"path";import{homedir as wt}from"os";import{createCipheriv as mt,createDecipheriv as pt}from"crypto";function Se(t,e){let s=mt("aes-128-ecb",e,null);return Buffer.concat([s.update(t),s.final()])}function Ce(t,e){let s=pt("aes-128-ecb",e,null);return Buffer.concat([s.update(t),s.final()])}function Ee(t){return Math.ceil((t+1)/16)*16}function te(t,e){return`${e}/download?encrypted_query_param=${encodeURIComponent(t)}`}function Ae(t){return`${t.cdnBaseUrl}/upload?encrypted_query_param=${encodeURIComponent(t.uploadParam)}&filekey=${encodeURIComponent(t.filekey)}`}M();var sn=_("channels");function ft(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 Pe(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 v(t){let{encryptQueryParam:e,aesKeyBase64:s,cdnBaseUrl:i,fullUrl:n}=t,r=ft(s),o=n?.trim()||(e?te(e,i):null);if(!o)throw new Error("CDN download: need full_url or encrypt_query_param");let a=await Pe(o);return Ce(a,r)}async function ve(t){let{encryptQueryParam:e,cdnBaseUrl:s,fullUrl:i}=t,n=i?.trim()||(e?te(e,s):null);if(!n)throw new Error("CDN download: need full_url or encrypt_query_param");return Pe(n)}M();var Q=_("channels"),Oe=24e3;function ht(t,e){let s=t.byteLength,i=44+s,n=Buffer.allocUnsafe(i),r=0;return n.write("RIFF",r),r+=4,n.writeUInt32LE(i-8,r),r+=4,n.write("WAVE",r),r+=4,n.write("fmt ",r),r+=4,n.writeUInt32LE(16,r),r+=4,n.writeUInt16LE(1,r),r+=2,n.writeUInt16LE(1,r),r+=2,n.writeUInt32LE(e,r),r+=4,n.writeUInt32LE(e*2,r),r+=4,n.writeUInt16LE(2,r),r+=2,n.writeUInt16LE(16,r),r+=2,n.write("data",r),r+=4,n.writeUInt32LE(s,r),r+=4,Buffer.from(t.buffer,t.byteOffset,t.byteLength).copy(n,r),n}async function qe(t){try{let{decode:e}=await import("silk-wasm");Q.debug(`silkToWav: decoding ${t.length} bytes of SILK`);let s=await e(t,Oe);Q.debug(`silkToWav: decoded duration=${s.duration}ms pcmBytes=${s.data.byteLength}`);let i=ht(s.data,Oe);return Q.debug(`silkToWav: WAV size=${i.length}`),i}catch(e){return Q.warn(`silkToWav: transcode failed, will use raw silk err=${String(e)}`),null}}import yt from"path";var _t={".pdf":"application/pdf",".doc":"application/msword",".docx":"application/vnd.openxmlformats-officedocument.wordprocessingml.document",".xls":"application/vnd.ms-excel",".xlsx":"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",".ppt":"application/vnd.ms-powerpoint",".pptx":"application/vnd.openxmlformats-officedocument.presentationml.presentation",".txt":"text/plain",".csv":"text/csv",".zip":"application/zip",".tar":"application/x-tar",".gz":"application/gzip",".mp3":"audio/mpeg",".ogg":"audio/ogg",".wav":"audio/wav",".amr":"audio/amr",".silk":"audio/x-silk",".mp4":"video/mp4",".mov":"video/quicktime",".webm":"video/webm",".mkv":"video/x-matroska",".avi":"video/x-msvideo",".png":"image/png",".jpg":"image/jpeg",".jpeg":"image/jpeg",".gif":"image/gif",".webp":"image/webp",".bmp":"image/bmp"},bt={"image/jpeg":".jpg","image/jpg":".jpg","image/png":".png","image/gif":".gif","image/webp":".webp","image/bmp":".bmp","video/mp4":".mp4","video/quicktime":".mov","video/webm":".webm","video/x-matroska":".mkv","video/x-msvideo":".avi","audio/mpeg":".mp3","audio/ogg":".ogg","audio/wav":".wav","audio/amr":".amr","audio/x-silk":".silk","application/pdf":".pdf","application/zip":".zip","application/x-tar":".tar","application/gzip":".gz","text/plain":".txt","text/csv":".csv"};function V(t){let e=yt.extname(t).toLowerCase();return _t[e]??"application/octet-stream"}function Ne(t){let e=t.split(";")[0].trim().toLowerCase();return bt[e]??".bin"}var S=_("channels"),Fe=100*1024*1024;function xt(t){return Ne(t)??".bin"}async function O(t,e,s,i,n=Fe,r){if(t.length>n)throw new Error(`Media too large: ${t.length} bytes exceeds ${n} bytes`);let o=$e.join(wt(),".adam","wechat","media",i,s);await z.mkdir(o,{recursive:!0});let a;if(r&&/^[a-zA-Z0-9._-]+$/.test(r))a=r;else{let c=e?xt(e):".bin",u=Date.now(),p=Math.random().toString(36).slice(2,7);a=`${u}-${p}${c}`}let d=$e.join(o,a);return await z.writeFile(d,t),S.debug(`saveMedia: saved ${t.length} bytes to ${d}`),d}async function Le(t,e){let{cdnBaseUrl:s,channelId:i}=e;if(t.type===y.IMAGE){let n=t.image_item;if(!n?.media?.encrypt_query_param&&!n?.media?.full_url)return null;let r=n.aeskey?Buffer.from(n.aeskey,"hex").toString("base64"):n.media?.aes_key;try{let o=r?await v({encryptQueryParam:n.media?.encrypt_query_param,aesKeyBase64:r,cdnBaseUrl:s,fullUrl:n.media?.full_url}):await ve({encryptQueryParam:n.media?.encrypt_query_param,cdnBaseUrl:s,fullUrl:n.media?.full_url});return{path:await O(o,"image/png","inbound",i),mimeType:"image/png",type:"image"}}catch(o){return S.error({channelId:i},`Image download/decrypt failed: ${String(o)}`),null}}if(t.type===y.VOICE){let n=t.voice_item;if(!n?.media?.encrypt_query_param&&!n?.media?.full_url||!n?.media?.aes_key)return null;try{let r=await v({encryptQueryParam:n.media.encrypt_query_param,aesKeyBase64:n.media.aes_key,cdnBaseUrl:s,fullUrl:n.media.full_url}),o=await qe(r);if(o){let a=await O(o,"audio/wav","inbound",i);return S.debug(`Voice: saved WAV to ${a}`),{path:a,mimeType:"audio/wav",type:"audio"}}else{let a=await O(r,"audio/silk","inbound",i);return S.debug(`Voice: silk transcode unavailable, saved raw SILK to ${a}`),{path:a,mimeType:"audio/silk",type:"audio"}}}catch(r){return S.error({channelId:i},`Voice download/transcode failed: ${String(r)}`),null}}if(t.type===y.FILE){let n=t.file_item;if(!n?.media?.encrypt_query_param&&!n?.media?.full_url||!n?.media?.aes_key)return null;try{let r=await v({encryptQueryParam:n.media.encrypt_query_param,aesKeyBase64:n.media.aes_key,cdnBaseUrl:s,fullUrl:n.media.full_url}),o=V(n.file_name??"file.bin");return{path:await O(r,o,"inbound",i,Fe,n.file_name),mimeType:o,type:"file"}}catch(r){return S.error({channelId:i},`File download failed: ${String(r)}`),null}}if(t.type===y.VIDEO){let n=t.video_item;if(!n?.media?.encrypt_query_param&&!n?.media?.full_url||!n?.media?.aes_key)return null;try{let r=await v({encryptQueryParam:n.media.encrypt_query_param,aesKeyBase64:n.media.aes_key,cdnBaseUrl:s,fullUrl:n.media.full_url});return{path:await O(r,"video/mp4","inbound",i),mimeType:"video/mp4",type:"video"}}catch(r){return S.error({channelId:i},`Video download failed: ${String(r)}`),null}}return null}import Be from"path";import ne from"crypto";import It from"fs/promises";M();var U=_("channels"),G=3;async function Tt(t){let{buf:e,uploadFullUrl:s,uploadParam:i,filekey:n,cdnBaseUrl:r,label:o,aeskey:a}=t,d=Se(e,a),c=s?.trim(),u;if(c)u=c;else if(i)u=Ae({cdnBaseUrl:r,uploadParam:i,filekey:n});else throw new Error(`${o}: CDN upload URL missing (need upload_full_url or upload_param)`);U.debug(`${o}: CDN POST url=${u} ciphertextSize=${d.length}`);let p,l;for(let h=1;h<=G;h++)try{let m=await fetch(u,{method:"POST",headers:{"Content-Type":"application/octet-stream"},body:new Uint8Array(d)});if(m.status>=400&&m.status<500){let b=m.headers.get("x-error-message")??await m.text();throw U.error(`${o}: CDN client error attempt=${h} status=${m.status} errMsg=${b}`),new Error(`CDN upload client error ${m.status}: ${b}`)}if(m.status!==200){let b=m.headers.get("x-error-message")??`status ${m.status}`;throw U.error(`${o}: CDN server error attempt=${h} status=${m.status} errMsg=${b}`),new Error(`CDN upload server error: ${b}`)}if(p=m.headers.get("x-encrypted-param")??void 0,!p)throw U.error(`${o}: CDN response missing x-encrypted-param header attempt=${h}`),new Error("CDN upload response missing x-encrypted-param header");U.debug(`${o}: CDN upload success attempt=${h}`);break}catch(m){if(l=m,m instanceof Error&&m.message.includes("client error"))throw m;h<G?U.warn(`${o}: attempt ${h} failed, retrying... err=${String(m)}`):U.error(`${o}: all ${G} attempts failed err=${String(m)}`)}if(!p)throw l instanceof Error?l:new Error(`CDN upload failed after ${G} attempts`);return{downloadParam:p}}async function se(t){let{filePath:e,toUserId:s,opts:i,cdnBaseUrl:n,mediaType:r,label:o}=t,a=await It.readFile(e),d=a.length,c=ne.createHash("md5").update(a).digest("hex"),u=Ee(d),p=ne.randomBytes(16).toString("hex"),l=ne.randomBytes(16);U.debug(`${o}: file=${e} rawsize=${d} filesize=${u} md5=${c} filekey=${p}`);let h=await _e({...i,filekey:p,media_type:r,to_user_id:s,rawsize:d,rawfilemd5:c,filesize:u,no_need_thumb:!0,aeskey:l.toString("hex")}),m=h.upload_full_url?.trim(),b=h.upload_param;if(!m&&!b)throw new Error(`${o}: getUploadUrl returned no upload URL (need upload_full_url or upload_param)`);let{downloadParam:Je}=await Tt({buf:a,uploadFullUrl:m||void 0,uploadParam:b??void 0,filekey:p,cdnBaseUrl:n,aeskey:l,label:`${o}[orig filekey=${p}]`});return{filekey:p,downloadEncryptedQueryParam:Je,aeskey:l.toString("hex"),fileSize:d,fileSizeCiphertext:u}}async function De(t){return se({...t,mediaType:W.IMAGE,label:"uploadImageToWeixin"})}async function We(t){return se({...t,mediaType:W.VIDEO,label:"uploadVideoToWeixin"})}async function ie(t){return se({...t,mediaType:W.FILE,label:"uploadFileAttachmentToWeixin"})}M();var q=_("channels");function Rt(){return`adam-wechat-${Date.now()}-${Math.random().toString(36).slice(2,7)}`}function Mt(t){let e=t;return e=e.replace(/```[^\n]*\n?([\s\S]*?)```/g,(s,i)=>i.trim()),e=e.replace(/!\[[^\]]*\]\([^)]*\)/g,""),e=e.replace(/\[([^\]]+)\]\([^)]*\)/g,"$1"),e=e.replace(/^\|[\s:|-]+\|$/gm,""),e=e.replace(/^\|(.+)\|$/gm,(s,i)=>i.split("|").map(n=>n.trim()).join(" ")),e}async function re(t){let{to:e,text:s,mediaItem:i,opts:n,label:r}=t,o=[],a=Mt(s);a&&o.push({type:y.TEXT,text_item:{text:a}}),o.push(i);let d="";for(let c of o){d=Rt();let u={msg:{from_user_id:"",to_user_id:e,client_id:d,message_type:A.BOT,message_state:P.FINISH,item_list:[c],context_token:n.contextToken}};await E({baseUrl:n.baseUrl,token:n.token,routeTag:n.routeTag,body:u})}return q.debug(`${r}: sent to=${e} messageId=${d}`),{messageId:d}}async function Ut(t){let{to:e,text:s,uploaded:i,opts:n}=t,r={type:y.IMAGE,image_item:{media:{encrypt_query_param:i.downloadEncryptedQueryParam,aes_key:Buffer.from(i.aeskey).toString("base64"),encrypt_type:1},mid_size:i.fileSizeCiphertext}};return re({to:e,text:s,mediaItem:r,opts:n,label:"sendImageMessage"})}async function kt(t){let{to:e,text:s,uploaded:i,opts:n}=t,r={type:y.VIDEO,video_item:{media:{encrypt_query_param:i.downloadEncryptedQueryParam,aes_key:Buffer.from(i.aeskey).toString("base64"),encrypt_type:1},video_size:i.fileSizeCiphertext}};return re({to:e,text:s,mediaItem:r,opts:n,label:"sendVideoMessage"})}async function je(t){let{to:e,text:s,fileName:i,uploaded:n,opts:r}=t,o={type:y.FILE,file_item:{media:{encrypt_query_param:n.downloadEncryptedQueryParam,aes_key:Buffer.from(n.aeskey).toString("base64"),encrypt_type:1},file_name:i,len:String(n.fileSize)}};return re({to:e,text:s,mediaItem:o,opts:r,label:"sendFileMessage"})}async function Qe(t){let{filePath:e,to:s,text:i,opts:n,cdnBaseUrl:r}=t,o=V(e),a={baseUrl:n.baseUrl,token:n.token,routeTag:n.routeTag};if(o.startsWith("video/")){q.debug(`sendWeixinMediaFile: uploading video filePath=${e} to=${s}`);let u=await We({filePath:e,toUserId:s,opts:a,cdnBaseUrl:r});return kt({to:s,text:i,uploaded:u,opts:n})}if(o.startsWith("image/")){q.debug(`sendWeixinMediaFile: uploading image filePath=${e} to=${s}`);let u=await De({filePath:e,toUserId:s,opts:a,cdnBaseUrl:r});return Ut({to:s,text:i,uploaded:u,opts:n})}if(o.startsWith("audio/")){let u=Be.basename(e);q.debug(`sendWeixinMediaFile: uploading audio as file filePath=${e} name=${u} to=${s}`);let p=await ie({filePath:e,fileName:u,toUserId:s,opts:a,cdnBaseUrl:r});return je({to:s,text:i,fileName:u,uploaded:p,opts:n})}let d=Be.basename(e);q.debug(`sendWeixinMediaFile: uploading file attachment filePath=${e} name=${d} to=${s}`);let c=await ie({filePath:e,fileName:d,toUserId:s,opts:a,cdnBaseUrl:r});return je({to:s,text:i,fileName:d,uploaded:c,opts:n})}M();var f=_("channels"),Ve="https://novac2c.cdn.weixin.qq.com/c2c",de=new Map;function Ke(t){return I.join(H(),".adam","wechat",`${t}.context-tokens.json`)}function St(t){let e=Ke(t);try{let s=T.readFileSync(e,"utf-8"),i=JSON.parse(s);for(let[n,r]of Object.entries(i))typeof r=="string"&&r&&de.set(`${t}:${n}`,r);f.debug({channelId:t,count:Object.keys(i).length},"Restored context tokens from disk")}catch{}}function Ct(t,e,s){let i=Ke(t);try{let n={};try{let o=T.readFileSync(i,"utf-8");n=JSON.parse(o)}catch{}n[e]=s;let r=I.dirname(i);T.mkdirSync(r,{recursive:!0}),T.writeFileSync(i,JSON.stringify(n),"utf-8")}catch(n){f.warn({channelId:t,userId:e},`Failed to persist context token: ${String(n)}`)}}function Et(t,e,s){de.set(`${t}:${e}`,s),Ct(t,e,s)}function oe(t,e){return de.get(`${t}:${e}`)}function He(t){return I.join(H(),".adam","wechat",`${t}.sync`)}function At(t){try{return T.readFileSync(He(t),"utf-8")}catch{return""}}function Pt(t,e){let s=He(t);T.mkdirSync(I.dirname(s),{recursive:!0}),T.writeFileSync(s,e,"utf-8")}var ae=1440*60*1e3,ze=10,vt=20,Ge=1440*60*1e3,Ot=1320*60*1e3,qt=1,Nt=7200*1e3;function Xe(t){return I.join(H(),".adam","wechat",`${t}.session.json`)}function $t(t){let e=new Map,s=Xe(t);try{let i=T.readFileSync(s,"utf-8"),n=JSON.parse(i);for(let[r,o]of Object.entries(n))o&&typeof o.lastUserMessageAt=="number"&&e.set(r,o);f.debug({channelId:t,count:e.size},"Restored sessions from disk")}catch{}return e}function N(t,e){let s=Xe(t);try{let i={};for(let[r,o]of e)i[r]=o;let n=I.dirname(s);T.mkdirSync(n,{recursive:!0}),T.writeFileSync(s,JSON.stringify(i),"utf-8")}catch(i){f.warn({channelId:t},`Failed to persist sessions: ${String(i)}`)}}var Ft=0;function $(){return`adam-wechat-${Date.now()}-${++Ft}`}var K=class{platform="wechat";id;config;status="disconnected";messageHandler=null;pollAbort=null;getUpdatesBuf="";sessions=new Map;pendingQueue=new Map;lastReminderAt=new Map;constructor(e,s){if(this.id=e,!s.baseUrl)throw new Error("WeChat adapter requires baseUrl");this.config=s}async connect(){if(!this.config.botToken)throw new Error("WeChat adapter requires botToken. Complete QR login first.");this.status="connecting",this.getUpdatesBuf=At(this.id),St(this.id),this.sessions=$t(this.id),this.pollAbort=new AbortController,this.status="connected",f.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",f.info({channelId:this.id},"WeChat adapter disconnected")}getStatus(){if(this.status==="connected"&&j(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}async sendMessage(e,s){if(j(this.id)){let c=Math.ceil(Ue(this.id)/6e4);throw new Error(`WeChat session paused, ${c} min remaining. Re-scan QR to reconnect.`)}let i=this.getOrCreateSession(e),r=this.getSessionRemainingMs(i)/36e5;if(!this.isSessionActive(i))return f.warn({channelId:this.id,chatId:e.slice(0,12),lastUserMessageAt:i.lastUserMessageAt,sessionExpired:!0},"iLink session expired (>24h), message queued"),this.enqueueMessage(e,s),`queued-${$()}`;if(i.quotaRemaining<=0)return f.warn({channelId:this.id,chatId:e.slice(0,12),quotaRemaining:0,remainingHours:r.toFixed(1)},"iLink quota exhausted, message queued"),this.enqueueMessage(e,s),`queued-${$()}`;let o=$(),a=oe(this.id,e),d=this.config.cdnBaseUrl??Ve;try{if(s.mediaUrl){let c=!s.mediaUrl.includes("://")||s.mediaUrl.startsWith("file://"),u=I.join(H(),".adam","wechat","media","outbound-tmp");await R.mkdir(u,{recursive:!0});let p=this.getExtensionFromMediaType(s.mediaType),l;if(c){let m=s.mediaUrl.startsWith("file://")?new URL(s.mediaUrl).pathname:I.isAbsolute(s.mediaUrl)?s.mediaUrl:I.resolve(s.mediaUrl),b=await R.readFile(m);l=I.join(u,`${Date.now()}-${Math.random().toString(36).slice(2,7)}${p}`),await R.writeFile(l,b)}else{let m=await fetch(s.mediaUrl);if(!m.ok)throw new Error(`Failed to fetch media: ${m.status}`);let b=Buffer.from(await m.arrayBuffer());l=I.join(u,`${Date.now()}-${Math.random().toString(36).slice(2,7)}${p}`),await R.writeFile(l,b)}let h=await Qe({filePath:l,to:e,text:s.content??"",opts:{baseUrl:this.config.baseUrl,token:this.config.botToken,routeTag:this.config.routeTag,contextToken:a},cdnBaseUrl:d});return await R.unlink(l).catch(()=>{}),i.quotaRemaining--,N(this.id,this.sessions),f.info({channelId:this.id,chatId:e.slice(0,12),quotaRemaining:i.quotaRemaining,sessionRemainingHours:(this.getSessionRemainingMs(i)/36e5).toFixed(1)},"iLink send success: quota decremented"),this.checkAndSendReminder(e,i).catch(m=>{f.warn({channelId:this.id,chatId:e.slice(0,12)},`Reminder send failed: ${String(m)}`)}),h.messageId}return await E({baseUrl:this.config.baseUrl,token:this.config.botToken,routeTag:this.config.routeTag,body:{msg:{from_user_id:"",to_user_id:e,client_id:o,message_type:A.BOT,message_state:P.FINISH,item_list:s.content?[{type:y.TEXT,text_item:{text:s.content}}]:void 0,context_token:a}}}),i.quotaRemaining--,N(this.id,this.sessions),f.info({channelId:this.id,chatId:e.slice(0,12),quotaRemaining:i.quotaRemaining,sessionRemainingHours:(this.getSessionRemainingMs(i)/36e5).toFixed(1)},"iLink send success: quota decremented"),this.checkAndSendReminder(e,i).catch(c=>{f.warn({channelId:this.id,chatId:e.slice(0,12)},`Reminder send failed: ${String(c)}`)}),o}catch(c){if(c instanceof Error&&c.message.includes("ret=-2"))return i.quotaRemaining=0,N(this.id,this.sessions),f.warn({channelId:this.id,chatId:e.slice(0,12),quotaRemaining:0},"iLink quota exhausted (ret=-2 confirmed), message queued"),this.enqueueMessage(e,s),`queued-${$()}`;throw c}}onMessage(e){this.messageHandler=e}async sendTypingIndicator(e){if(j(this.id))return;let s=oe(this.id,e);try{await ye({baseUrl:this.config.baseUrl,token:this.config.botToken,routeTag:this.config.routeTag,body:{ilink_user_id:e,status:Re.TYPING}})}catch{}}updateConfig(e){Object.assign(this.config,e)}getOrCreateSession(e){let s=this.sessions.get(e);return s||(s={lastUserMessageAt:0,quotaRemaining:0},this.sessions.set(e,s)),s}isSessionActive(e){return e.lastUserMessageAt>0&&Date.now()-e.lastUserMessageAt<=ae}getSessionRemainingMs(e){return e.lastUserMessageAt===0?0:Math.max(0,ae-(Date.now()-e.lastUserMessageAt))}enqueueMessage(e,s){let i=this.pendingQueue.get(e);i||(i=[],this.pendingQueue.set(e,i));let n=Date.now();i=i.filter(r=>n-r.queuedAt<Ge),i.length>=vt&&(i.shift(),f.warn({channelId:this.id,chatId:e.slice(0,12)},"Queue full, dropping oldest message")),i.push({message:s,queuedAt:n}),this.pendingQueue.set(e,i),f.info({channelId:this.id,chatId:e.slice(0,12),queueDepth:i.length},"Message enqueued")}async flushQueue(e){let s=this.pendingQueue.get(e);if(!s||s.length===0)return;let i=this.getOrCreateSession(e),n=Math.min(s.length,Math.max(0,i.quotaRemaining-2));if(n<=0){f.info({channelId:this.id,chatId:e.slice(0,12),quotaRemaining:i.quotaRemaining},"Queue flush skipped: insufficient quota (reserving 2 for conversation)");return}f.info({channelId:this.id,chatId:e.slice(0,12),queueDepth:s.length,sending:n,quotaRemaining:i.quotaRemaining},"Flushing queued messages");let r=0;for(;r<n&&s.length>0;){let o=s[0];if(Date.now()-o.queuedAt>Ge){s.shift();continue}try{if(await this.sendMessage(e,o.message),s.shift(),r++,i.quotaRemaining<=0)break}catch{f.warn({channelId:this.id,chatId:e.slice(0,12)},"Queue flush: send failed, stopping");break}}s.length===0&&this.pendingQueue.delete(e),f.info({channelId:this.id,chatId:e.slice(0,12),sent:r,remaining:s.length},"Queue flush complete")}async checkAndSendReminder(e,s){let i=Date.now(),n=this.lastReminderAt.get(e)??0;if(i-n<Nt)return;let r=this.getSessionRemainingMs(s),a=i-s.lastUserMessageAt>=Ot,d=s.quotaRemaining<=qt;if(!a&&!d)return;let c=(r/36e5).toFixed(1),u;a&&d?u=`[\u7CFB\u7EDF\u63D0\u9192] \u6D88\u606F\u7A97\u53E3\u5373\u5C06\u5173\u95ED\uFF08\u5269\u4F59${c}\u5C0F\u65F6/${s.quotaRemaining}\u6761\u914D\u989D\uFF09\u3002\u8BF7\u56DE\u590D\u4EFB\u610F\u6D88\u606F\u4EE5\u4FDD\u6301\u8FDE\u63A5\u3002`:a?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${s.quotaRemaining}\u6761\uFF09\u3002\u8BF7\u56DE\u590D\u4EFB\u610F\u6D88\u606F\u4EE5\u91CD\u7F6E\u914D\u989D\u3002`;let p=oe(this.id,e);try{await E({baseUrl:this.config.baseUrl,token:this.config.botToken,routeTag:this.config.routeTag,body:{msg:{from_user_id:"",to_user_id:e,client_id:$(),message_type:A.BOT,message_state:P.FINISH,item_list:[{type:y.TEXT,text_item:{text:u}}],context_token:p}}}),s.quotaRemaining--,this.lastReminderAt.set(e,i),N(this.id,this.sessions),f.info({channelId:this.id,chatId:e.slice(0,12),remainingHours:c,quotaRemaining:s.quotaRemaining,trigger:a?"time":"quota"},"iLink session reminder sent")}catch(l){f.warn({channelId:this.id,chatId:e.slice(0,12)},`Reminder send failed: ${String(l)}`)}}async startLongPoll(){let e=this.pollAbort?.signal,s=0,i=3,n=3e4,r=2e3;for(;!e?.aborted;)try{let o=await he({baseUrl:this.config.baseUrl,token:this.config.botToken,routeTag:this.config.routeTag,get_updates_buf:this.getUpdatesBuf});if(o.ret===ee||o.errcode===ee){Me(this.id),this.status="error",f.error({channelId:this.id},"Session expired (errcode=-14), pausing for 1 hour"),await this.sleep(B,e),ke(this.id),this.status="connected";continue}if(o.ret!==void 0&&o.ret!==0||o.errcode!==void 0&&o.errcode!==0){s++,f.error({channelId:this.id,ret:o.ret,errcode:o.errcode},"getUpdates API error"),s>=i?(s=0,await this.sleep(n,e)):await this.sleep(r,e);continue}s=0,o.get_updates_buf&&(this.getUpdatesBuf=o.get_updates_buf,Pt(this.id,o.get_updates_buf));for(let d of o.msgs??[])await this.processInbound(d)}catch(o){if(e?.aborted)return;s++,f.error({channelId:this.id,error:o},"getUpdates error"),s>=i?(s=0,await this.sleep(n,e)):await this.sleep(r,e)}}async processInbound(e){if(!this.messageHandler)return;let s=!!e.group_id,i=s?e.group_id:e.from_user_id??"",n=e.from_user_id??"";e.context_token&&i&&Et(this.id,i,e.context_token);let r=this.getOrCreateSession(i),o=r.quotaRemaining;r.lastUserMessageAt=Date.now(),r.quotaRemaining=ze,N(this.id,this.sessions),f.info({channelId:this.id,chatId:i.slice(0,12),quotaReset:!0,prevQuota:o,newQuota:ze,sessionWindowMs:ae},"iLink session reset: user message received, quota restored"),this.flushQueue(i);let a="",d,c=[];for(let l of e.item_list??[])l.type===y.TEXT&&l.text_item?.text&&(a+=l.text_item.text),l.type===y.IMAGE&&(d="image",c.push(l)),l.type===y.VOICE&&(d="audio",c.push(l),l.voice_item?.text&&!a&&(a=l.voice_item.text)),l.type===y.FILE&&(d="file",c.push(l)),l.type===y.VIDEO&&(d="video",c.push(l));if(!a&&!d)return;let u;if(c.length>0){let l=this.config.cdnBaseUrl??Ve;try{let h=await Le(c[0],{cdnBaseUrl:l,channelId:this.id});h&&(u=h.path,d=h.type)}catch(h){f.error({channelId:this.id},`Media download failed: ${String(h)}`)}}let p={channelId:this.id,platform:"wechat",chatId:i,senderId:n,content:a,mediaType:d,mediaPath:u,isGroup:s,timestamp:e.create_time_ms??Date.now(),raw:e};this.messageHandler(p)}getExtensionFromMediaType(e){switch(e){case"image":return".png";case"video":return".mp4";case"audio":return".mp3";default:return".bin"}}sleep(e,s){return new Promise((i,n)=>{let r=setTimeout(i,e);s?.addEventListener("abort",()=>{clearTimeout(r),n(new Error("aborted"))},{once:!0})})}};M();var Lt=_("channels"),X=class{platform="discord";id;config;status="disconnected";messageHandler=null;client=null;constructor(e,s){if(this.id=e,!s.botToken)throw new Error("Discord adapter requires botToken");this.config=s}async connect(){this.status="connecting";try{let{Client:e,GatewayIntentBits:s}=await import("discord.js");this.client=new e({intents:[s.Guilds,s.GuildMessages,s.MessageContent,s.DirectMessages]});let i=this.client;i.on("messageCreate",n=>{if(!this.messageHandler||n.author.bot||this.config.allowedGuildIds?.length&&n.guildId&&!this.config.allowedGuildIds.includes(n.guildId))return;let r={channelId:this.id,platform:"discord",chatId:n.channelId,senderId:n.author.id,senderName:n.author.displayName??n.author.username,content:n.content,isGroup:!!n.guildId,timestamp:n.createdTimestamp,raw:n};this.messageHandler(r)}),await i.login(this.config.botToken),this.status="connected",Lt.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}async sendMessage(e,s){if(!this.client)throw new Error("Discord client not connected");let n=await this.client.channels.fetch(e);if(!n||!("send"in n))throw new Error(`Channel ${e} not found or not text channel`);return(await n.send({content:s.content,reply:s.replyToMessageId?{messageReference:s.replyToMessageId}:void 0})).id}onMessage(e){this.messageHandler=e}async sendTypingIndicator(e){if(!this.client)return;let i=await this.client.channels.fetch(e);i&&"sendTyping"in i&&await i.sendTyping()}};var k=g.object({id:g.string().uuid()}),Wt=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()}),Bt=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()}),ce;function Zn(t){ce=t}function es(){return ce}async function ts(t){let e=ce;t.get("/channels",{schema:{tags:["Channels"],summary:"List channels",querystring:{type:"object",properties:{enabled:{type:"boolean"}}}}},async(s,i)=>({channels:ge(s.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(s,i)=>{let n=Wt.safeParse(s.body);if(!n.success)return i.status(400).send({code:"VALIDATION_ERROR",message:g.prettifyError(n.error)});let{name:r,platform:o,config:a,enabled:d,linkedRoleId:c,allowedChatIds:u}=n.data,p={id:Dt(),name:r,platform:o,enabled:d,status:"disconnected",config:a,linkedRoleId:c,allowedChatIds:u,createdAt:Date.now(),messageCount:0};return le(p),i.status(201).send({channel:p})}),t.get("/channels/:id",{schema:{tags:["Channels"],summary:"Get channel by ID",params:{type:"object",required:["id"],properties:{id:{type:"string",format:"uuid"}}}}},async(s,i)=>{let n=k.safeParse(s.params);if(!n.success)return i.status(400).send({code:"VALIDATION_ERROR",message:g.prettifyError(n.error)});let r=x(n.data.id);return r?{channel:r}:i.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"}}}}}},async(s,i)=>{let n=k.safeParse(s.params);if(!n.success)return i.status(400).send({code:"VALIDATION_ERROR",message:g.prettifyError(n.error)});let r=x(n.data.id);if(!r)return i.status(404).send({code:"NOT_FOUND",message:"Channel not found"});let o=Bt.safeParse(s.body);return o.success?(J(r.id,o.data),{channel:x(r.id)}):i.status(400).send({code:"VALIDATION_ERROR",message:g.prettifyError(o.error)})}),t.delete("/channels/:id",{schema:{tags:["Channels"],summary:"Delete channel",params:{type:"object",required:["id"],properties:{id:{type:"string",format:"uuid"}}}}},async(s,i)=>{let n=k.safeParse(s.params);if(!n.success)return i.status(400).send({code:"VALIDATION_ERROR",message:g.prettifyError(n.error)});let r=x(n.data.id);return r?(me(r.id),i.status(204).send()):i.status(404).send({code:"NOT_FOUND",message:"Channel not found"})}),t.post("/channels/:id/connect",{schema:{tags:["Channels"],summary:"Connect channel",params:{type:"object",required:["id"],properties:{id:{type:"string",format:"uuid"}}}}},async(s,i)=>{let n=k.safeParse(s.params);if(!n.success)return i.status(400).send({code:"VALIDATION_ERROR",message:g.prettifyError(n.error)});if(!e)return i.status(501).send({code:"NOT_IMPLEMENTED",message:"Channel manager not initialized"});let r=x(n.data.id);if(!r)return i.status(404).send({code:"NOT_FOUND",message:"Channel not found"});if(!e.hasAdapter(r.id)&&r.platform==="discord"){let o=r.config;if(!o.botToken)return i.status(400).send({code:"MISSING_CONFIG",message:"Discord channel requires botToken in config"});let a=new X(r.id,{botToken:o.botToken});await e.addChannel(r,a)}if(!e.hasAdapter(r.id))return i.status(400).send({code:"NO_ADAPTER",message:"No adapter registered for this channel. Install the appropriate adapter first."});try{return await e.connectChannel(r.id),{channelId:r.id,status:"connected"}}catch(o){return i.status(500).send({code:"CONNECT_FAILED",message:String(o)})}}),t.post("/channels/:id/disconnect",{schema:{tags:["Channels"],summary:"Disconnect channel",params:{type:"object",required:["id"],properties:{id:{type:"string",format:"uuid"}}}}},async(s,i)=>{let n=k.safeParse(s.params);if(!n.success)return i.status(400).send({code:"VALIDATION_ERROR",message:g.prettifyError(n.error)});if(!e)return i.status(501).send({code:"NOT_IMPLEMENTED",message:"Channel manager not initialized"});let r=x(n.data.id);return r?(await e.disconnectChannel(r.id),{channelId:r.id,status:"disconnected"}):i.status(404).send({code:"NOT_FOUND",message:"Channel not found"})}),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(s,i)=>{let n=k.safeParse(s.params);if(!n.success)return i.status(400).send({code:"VALIDATION_ERROR",message:g.prettifyError(n.error)});let r=x(n.data.id);if(!r)return i.status(404).send({code:"NOT_FOUND",message:"Channel not found"});let{limit:o=50,offset:a=0}=s.query;return{messages:ue(r.id,o,a)}}),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(s,i)=>{let n=k.safeParse(s.params);if(!n.success)return i.status(400).send({code:"VALIDATION_ERROR",message:g.prettifyError(n.error)});let r=x(n.data.id);if(!r)return i.status(404).send({code:"NOT_FOUND",message:"Channel not found"});if(r.platform!=="wechat")return i.status(400).send({code:"INVALID_PLATFORM",message:"Channel is not a WeChat channel"});let o=r.config;return await Ie({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(s,i)=>{let n=k.safeParse(s.params);if(!n.success)return i.status(400).send({code:"VALIDATION_ERROR",message:g.prettifyError(n.error)});let r=x(n.data.id);if(!r)return i.status(404).send({code:"NOT_FOUND",message:"Channel not found"});if(r.platform!=="wechat")return i.status(400).send({code:"INVALID_PLATFORM",message:"Channel is not a WeChat channel"});let o=r.config,{sessionKey:a,timeoutMs:d}=s.body??{},c=await Te({sessionKey:a??"",apiBaseUrl:o.baseUrl,timeoutMs:d??12e4,routeTag:o.routeTag});if(c.connected&&c.botToken){let u={...o,botToken:c.botToken,accountId:c.accountId,baseUrl:c.baseUrl??o.baseUrl,userId:c.userId};if(J(r.id,{config:u}),e){let p=new K(r.id,u),l=x(r.id);l&&await e.addChannel(l,p)}}return{connected:c.connected,accountId:c.accountId,message:c.message}})}export{K as a,X as b,Zn as c,es as d,ts as e};
@@ -1,2 +1,2 @@
1
- import{b as r,d as s}from"./chunk-JAS3TUZX.js";import{c as i}from"./chunk-FCV2DPZQ.js";function p(e){let n=r().prepare("SELECT value FROM config WHERE key = ?").get(e);if(n)try{return JSON.parse(n.value)}catch{return n.value}}function E(e,t){let n=r(),o=JSON.stringify(t),u=Date.now();n.prepare(`INSERT INTO config (key, value, updated_at) VALUES (?, ?, ?)
1
+ import{b as r,d as s}from"./chunk-NCFVJCNQ.js";import{c as i}from"./chunk-FCV2DPZQ.js";function p(e){let n=r().prepare("SELECT value FROM config WHERE key = ?").get(e);if(n)try{return JSON.parse(n.value)}catch{return n.value}}function E(e,t){let n=r(),o=JSON.stringify(t),u=Date.now();n.prepare(`INSERT INTO config (key, value, updated_at) VALUES (?, ?, ?)
2
2
  ON CONFLICT(key) DO UPDATE SET value = excluded.value, updated_at = excluded.updated_at`).run(e,o,u)}function k(){let t=r().prepare("SELECT key, value FROM config").all(),n={};for(let o of t)try{n[o.key]=JSON.parse(o.value)}catch{n[o.key]=o.value}return n}function b(e){let t=r(),n=t.prepare("INSERT OR IGNORE INTO config (key, value, updated_at) VALUES (?, ?, ?)"),o=Date.now(),u=0;return t.transaction(()=>{for(let[c,a]of Object.entries(e)){if(a==null||a==="")continue;n.run(c,JSON.stringify(a),o).changes>0&&u++}})(),u}function w(){return r().prepare("SELECT COUNT(*) as count FROM config").get().count===0}function O(e){return r().prepare("DELETE FROM config WHERE key = ?").run(e).changes>0}var d=i(()=>{s()});export{p as a,E as b,k as c,b as d,w as e,O as f,d as g};
@@ -0,0 +1,6 @@
1
+ import{b as s,d as u}from"./chunk-NCFVJCNQ.js";u();function f(e){if(e)return e.startsWith("event:")?e.slice(6):void 0}var l=class extends Error{constructor(t){super(`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(", ")}`);this.failingStepIds=t;this.name="TemplateRoleConfigError"}code="TEMPLATE_INVALID_ROLE_CONFIG"};function a(e){if(e.rolePreference)return;let n=[];for(let t of e.steps){let i=typeof t.roleId=="string"&&t.roleId.length>0,r=t.autoSelectRole===!0;!i&&!r&&n.push(t.id)}if(n.length>0)throw new l(n)}function d(e){let n=e.trigger_type,t={type:n,cron:n==="event"?void 0:e.trigger_cron??void 0,event:n==="event"?void 0:e.trigger_event??void 0,eventDefId:n==="event"?f(e.trigger_event):void 0,runAt:n==="once"?e.trigger_cron??void 0:void 0};return{id:e.id,name:e.name,description:e.description??void 0,trigger:t,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}}function T(e){a(e),s().prepare(`
2
+ INSERT 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)
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)}function c(e){let t=s().prepare("SELECT * FROM task_templates WHERE id = ?").get(e);return t?d(t):void 0}function _(e,n){let t=s();if("steps"in n||"rolePreference"in n){let o=c(e);if(o){let g={rolePreference:"rolePreference"in n?n.rolePreference:o.rolePreference,steps:"steps"in n&&n.steps?n.steps:o.steps};a(g)}}let i=[],r=[];"name"in n&&(i.push("name = ?"),r.push(n.name)),"description"in n&&(i.push("description = ?"),r.push(n.description??null)),"trigger"in n&&n.trigger&&(i.push("trigger_type = ?"),r.push(n.trigger.type),i.push("trigger_cron = ?"),r.push(n.trigger.type==="once"?n.trigger.runAt??null:n.trigger.cron??null),i.push("trigger_event = ?"),r.push(n.trigger.type==="event"?`event:${n.trigger.eventDefId}`:n.trigger.event??null)),"steps"in n&&(i.push("steps = ?"),r.push(JSON.stringify(n.steps))),"rolePreference"in n&&(i.push("role_preference = ?"),r.push(n.rolePreference??null)),"config"in n&&(i.push("config = ?"),r.push(n.config?JSON.stringify(n.config):null)),"tags"in n&&(i.push("tags = ?"),r.push(n.tags?JSON.stringify(n.tags):null)),"enabled"in n&&(i.push("enabled = ?"),r.push(n.enabled?1:0)),"sourceSessionId"in n&&(i.push("source_session_id = ?"),r.push(n.sourceSessionId??null)),"deliverTo"in n&&(i.push("deliver_to = ?"),r.push(n.deliverTo?JSON.stringify(n.deliverTo):null)),"reportTo"in n&&(i.push("report_to = ?"),r.push(n.reportTo?JSON.stringify(n.reportTo):null)),"goalIds"in n&&(i.push("goal_ids = ?"),r.push(n.goalIds?JSON.stringify(n.goalIds):null)),i.length!==0&&(i.push("updated_at = ?"),r.push(Date.now()),r.push(e),t.prepare(`UPDATE task_templates SET ${i.join(", ")} WHERE id = ?`).run(...r))}function h(e=!1,n,t=0){let i=s(),r="SELECT * FROM task_templates",o=[];return e&&(r+=" WHERE enabled = 1"),r+=" ORDER BY COALESCE(updated_at, created_at) DESC",typeof n=="number"&&(r+=" LIMIT ? OFFSET ?",o.push(n,t)),i.prepare(r).all(...o).map(d)}function k(e){s().prepare("UPDATE task_templates SET enabled = 1, updated_at = ? WHERE id = ?").run(Date.now(),e)}function S(e){s().prepare("UPDATE task_templates SET enabled = 0, updated_at = ? WHERE id = ?").run(Date.now(),e)}function v(e){s().prepare("DELETE FROM task_templates WHERE id = ?").run(e)}export{l as a,a as b,T as c,c as d,_ as e,h as f,k as g,S as h,v as i};
@@ -1,4 +1,4 @@
1
- import{b as n,d as o}from"./chunk-JAS3TUZX.js";o();function a(e){return{id:e.id,sessionId:e.session_id,role:e.role,content:e.content,source:{type:e.source_type},taskId:e.task_id??void 0,channelMessageId:e.channel_message_id??void 0,metadata:e.metadata?JSON.parse(e.metadata):void 0,createdAt:e.created_at}}function c(e){n().prepare(`
1
+ import{b as n,d as o}from"./chunk-NCFVJCNQ.js";o();function a(e){return{id:e.id,sessionId:e.session_id,role:e.role,content:e.content,source:{type:e.source_type},taskId:e.task_id??void 0,channelMessageId:e.channel_message_id??void 0,metadata:e.metadata?JSON.parse(e.metadata):void 0,createdAt:e.created_at}}function c(e){n().prepare(`
2
2
  INSERT INTO chat_messages (id, session_id, role, content, source_type, task_id,
3
3
  channel_message_id, metadata, created_at)
4
4
  VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
@@ -0,0 +1,27 @@
1
+ import{q as C}from"./chunk-MDBVKBC7.js";import{a as D}from"./chunk-N4ES7TCL.js";import{b as _}from"./chunk-I7ZZKPHE.js";import{b as A}from"./chunk-VVSZZK5T.js";import{b as T}from"./chunk-YXYIA24D.js";import{a as S}from"./chunk-L7JP7DUO.js";import{d as b}from"./chunk-PG6LMSX6.js";import{l as x,r as F}from"./chunk-7ZGSJCX5.js";import{b as w,d as $}from"./chunk-NCFVJCNQ.js";import{c as E,h as N}from"./chunk-MRTJFYPR.js";N();F();$();function O(u){return{id:u.id,templateId:u.template_id,status:u.status,stepStatuses:JSON.parse(u.step_statuses),startedAt:u.started_at,completedAt:u.completed_at??void 0,error:u.error??void 0,eventId:u.event_id??void 0}}function M(u,e,t){w().prepare(`
2
+ INSERT INTO workflow_executions (id, template_id, status, step_statuses, started_at, event_id)
3
+ VALUES (?, ?, 'running', '{}', ?, ?)
4
+ `).run(u,e,Date.now(),t??null)}function h(u){let t=w().prepare("SELECT * FROM workflow_executions WHERE id = ?").get(u);return t?O(t):void 0}function R(u,e){let t=w(),n=[],s=[];e.status!==void 0&&(n.push("status = ?"),s.push(e.status)),e.stepStatuses!==void 0&&(n.push("step_statuses = ?"),s.push(JSON.stringify(e.stepStatuses))),e.completedAt!==void 0&&(n.push("completed_at = ?"),s.push(e.completedAt)),e.error!==void 0&&(n.push("error = ?"),s.push(e.error)),n.length!==0&&(s.push(u),t.prepare(`UPDATE workflow_executions SET ${n.join(", ")} WHERE id = ?`).run(...s))}function L(u,e=50,t=0){let n=w(),s="SELECT * FROM workflow_executions",a=[];return u&&(s+=" WHERE template_id = ?",a.push(u)),s+=" ORDER BY started_at DESC LIMIT ? OFFSET ?",a.push(e,t),n.prepare(s).all(...a).map(O)}function B(u,e=20,t=0){return w().prepare(`
5
+ SELECT we.id AS execution_id,
6
+ we.template_id,
7
+ tt.name AS template_name,
8
+ we.status,
9
+ we.started_at,
10
+ we.completed_at,
11
+ we.error,
12
+ we.event_id,
13
+ e.occurred_at AS event_occurred_at,
14
+ e.payload AS event_payload
15
+ FROM workflow_executions we
16
+ LEFT JOIN task_templates tt ON tt.id = we.template_id
17
+ INNER JOIN events e ON e.id = we.event_id
18
+ WHERE e.event_def_id = ?
19
+ ORDER BY we.started_at DESC
20
+ LIMIT ? OFFSET ?
21
+ `).all(u,e,t).map(a=>({executionId:a.execution_id,templateId:a.template_id,templateName:a.template_name,status:a.status,startedAt:a.started_at,completedAt:a.completed_at,error:a.error,eventId:a.event_id,eventOccurredAt:a.event_occurred_at,eventPayload:a.event_payload?JSON.parse(a.event_payload):null}))}var f=E("scheduler"),P=class{maxRetries;baseDelayMs;constructor(e){this.maxRetries=e?.maxRetries??3,this.baseDelayMs=e?.baseDelayMs??1e3}async execute(e,t,n){let s=b(),a={timeout:e.config?.timeout??s.timeout,approvalRequired:s.approvalRequired,approvalTimeout:s.approvalTimeout,plugins:e.config?.plugins,mcpServers:e.config?.mcpServers,model:e.config?.model??s.model,maxTurns:e.config?.maxTurns??s.maxTurns,maxBudgetUsd:e.config?.maxBudgetUsd??s.maxBudgetUsd,env:{...s.env,...e.config?.env},claudeCodePath:s.claudeCodePath},r={templateId:e.id,executionId:t,stepResults:new Map,stepStatuses:{},config:a,continueOnError:e.config?.continueOnError??!1,failedStepIds:new Set,rolePreference:e.rolePreference,deliverTo:e.deliverTo,reportTo:e.reportTo};M(t,e.id,n?.eventId),D(t),S.emit({type:"workflow_status_change",executionId:t,templateId:e.id,status:"running"});let i=this.groupIntoLayers(e.steps);for(let m of i){if(this.syncExternalState(r)==="cancelled")return this.finalizeCancelledWorkflow(e,r);let g=m.filter(l=>!this.shouldSkip(l,r)),v=m.filter(l=>this.shouldSkip(l,r));for(let l of v){let p={stepId:l.id,taskId:"",status:"skipped",error:"Skipped: dependency failed"};r.stepResults.set(l.id,p),r.stepStatuses[l.id]={taskId:"",status:"skipped",error:"Skipped: dependency failed"},f.info({stepId:l.id,executionId:t},"Step skipped due to failed dependency")}if(g.length===0)continue;let W=await Promise.allSettled(g.map(l=>this.executeStep(l,r)));if(this.syncExternalState(r)==="cancelled")return this.finalizeCancelledWorkflow(e,r);for(let l=0;l<g.length;l++){let p=g[l],k=W[l];if(k.status==="rejected"){f.error({stepId:p.id,error:k.reason},"Workflow step threw");let I={stepId:p.id,taskId:"",status:"failed",error:String(k.reason)};r.stepResults.set(p.id,I),r.failedStepIds.add(p.id),r.stepStatuses[p.id]={taskId:"",status:"failed",error:String(k.reason)}}let y=r.stepResults.get(p.id);if(y?.status==="failed"&&(r.failedStepIds.add(p.id),!r.continueOnError)){if(this.isWorkflowCancelled(r.executionId))return this.finalizeCancelledWorkflow(e,r);let I="failed";return R(t,{status:I,stepStatuses:r.stepStatuses,completedAt:Date.now(),error:y.error}),S.emit({type:"workflow_status_change",executionId:t,templateId:e.id,status:I}),f.warn({stepId:p.id,executionId:t},"Workflow step failed, workflow aborted"),{executionId:t,status:I,stepResults:r.stepResults}}}if(this.isWorkflowCancelled(r.executionId))return this.finalizeCancelledWorkflow(e,r);R(t,{stepStatuses:r.stepStatuses})}if(this.isWorkflowCancelled(r.executionId))return this.finalizeCancelledWorkflow(e,r);let d=r.failedStepIds.size>0,o=[...r.stepResults.values()].some(m=>m.status==="skipped"||m.status==="cancelled"),c=d||o?"partial":"completed";return R(t,{status:c,stepStatuses:r.stepStatuses,completedAt:Date.now()}),S.emit({type:"workflow_status_change",executionId:t,templateId:e.id,status:c}),f.info({executionId:t,status:c,completedSteps:r.stepResults.size,totalSteps:e.steps.length,failedSteps:r.failedStepIds.size},"Workflow completed"),await this.deliverWorkflowResult(r,c),{executionId:t,status:c,stepResults:r.stepResults}}groupIntoLayers(e){let t=new Map(e.map(i=>[i.id,i])),n=new Map,s=new Map;for(let i of e)n.set(i.id,0),s.set(i.id,[]);for(let i of e)if(i.dependsOn)for(let d of i.dependsOn)t.has(d)&&(n.set(i.id,(n.get(i.id)??0)+1),s.get(d)?.push(i.id));let a=[],r=new Set(e.map(i=>i.id));for(;r.size>0;){let i=[];for(let d of r)if((n.get(d)??0)===0){let o=t.get(d);o&&i.push(o)}if(i.length===0){f.warn({remaining:[...r]},"Cycle detected in step dependencies");for(let d of r){let o=t.get(d);o&&a.push([o])}break}a.push(i);for(let d of i){r.delete(d.id);for(let o of s.get(d.id)??[])n.set(o,(n.get(o)??0)-1)}}return a}syncExternalState(e){let t=h(e.executionId);if(t){for(let[n,s]of Object.entries(t.stepStatuses))(s.status==="skipped"||s.status==="failed"||s.status==="cancelled")&&!e.stepResults.has(n)&&!e.failedStepIds.has(n)&&(s.status==="skipped"?e.stepResults.set(n,{stepId:n,taskId:s.taskId,status:"skipped",error:s.error??"Manually skipped via API"}):s.status==="cancelled"?e.stepResults.set(n,{stepId:n,taskId:s.taskId,status:"cancelled",error:s.error??"Cancelled"}):(e.failedStepIds.add(n),e.stepResults.set(n,{stepId:n,taskId:s.taskId,status:"failed",error:s.error})),e.stepStatuses[n]=s,f.info({stepId:n,status:s.status,executionId:e.executionId},"Synced external step status from DB"));return t.status==="cancelled"?"cancelled":void 0}}shouldSkip(e,t){return e.dependsOn?e.dependsOn.some(n=>t.failedStepIds.has(n)?!0:t.stepResults.get(n)?.status==="skipped"):!1}async executeStep(e,t){let n=this.resolveVariables(e.prompt,t.stepResults),s=e.roleId??t.rolePreference,a=s?x(s):void 0,r=(e.config?.timeout??t.config?.timeout??600)*1e3,i="",d="failed",o;for(let l=1;l<=this.maxRetries;l++){let p=await C({prompt:n,roleId:s,requirements:e.requirements,autoSelectRole:e.autoSelectRole,config:{...t.config,...e.config?.timeout!==void 0?{timeout:e.config.timeout}:{},...e.config?.maxTurns!==void 0?{maxTurns:e.config.maxTurns}:{}},sourceSessionId:t.templateId,parentId:t.executionId,templateId:t.templateId,stepId:e.id});if(!p.ok){o=p;break}if(i=p.taskId,t.stepStatuses[e.id]={taskId:i,status:"running",roleId:s},f.debug({stepId:e.id,taskId:i,roleId:s,attempt:l},"Workflow step task created via admission"),d=await this.waitForTaskCompletion(i,r),d==="completed"||d==="cancelled")break;if(l<this.maxRetries){let k=this.baseDelayMs*Math.pow(2,l-1);f.info({stepId:e.id,attempt:l,maxRetries:this.maxRetries,delayMs:k},"Workflow step failed, retrying"),await this.sleep(k)}}if(o&&!o.ok){let l={stepId:e.id,taskId:"",status:"failed",roleId:s,roleName:a?.name,error:`Admission failed: ${o.reason}`,admissionError:{code:o.code,reason:o.reason,candidates:o.candidates?.map(p=>({roleId:p.roleId,name:p.name,fitScore:p.fitScore}))}};t.stepResults.set(e.id,l),t.stepStatuses[e.id]={taskId:"",status:"failed",roleId:s,error:o.reason},f.warn({stepId:e.id,admissionCode:o.code,reason:o.reason},"Workflow step admission failed");return}let c=_(i),m=h(t.executionId),g=m?.stepStatuses[e.id],v=d==="completed"?"completed":g?.status==="skipped"?"skipped":g?.status==="cancelled"||m?.status==="cancelled"?"cancelled":"failed",W={stepId:e.id,taskId:i,status:v,roleId:s,roleName:a?.name,result:c?.result,error:c?.error};t.stepResults.set(e.id,W),t.stepStatuses[e.id]={taskId:i,status:W.status,roleId:s,result:c?.result,error:c?.error}}async deliverWorkflowResult(e,t){let n=A();if(e.deliverTo&&e.deliverTo.length>0){let s=this.assembleWorkflowSummary(e);for(let a of e.deliverTo)if(a.type==="channel"){let r=T(a.channelId);try{await n.send({taskId:e.executionId,channelId:a.channelId,chatId:a.chatId,platform:r?.platform,content:s,messageType:"deliver"})}catch(i){f.error({executionId:e.executionId,channelId:a.channelId,error:i},"Workflow delivery failed")}}}if(e.reportTo&&e.reportTo.length>0){let s=[...e.stepResults.values()].filter(o=>o.status==="completed").length,a=e.failedStepIds.size,r=[...e.stepResults.values()].filter(o=>o.status==="skipped").length,i=e.stepResults.size,d=`Workflow ${t}: ${s}/${i} steps completed${a>0?`, ${a} failed`:""}${r>0?`, ${r} skipped`:""}`;for(let o of e.reportTo)if(o.type==="channel"){let c=T(o.channelId);try{await n.send({taskId:e.executionId,channelId:o.channelId,chatId:o.chatId,platform:c?.platform,content:d,messageType:"report"})}catch(m){f.error({executionId:e.executionId,channelId:o.channelId,error:m},"Workflow report delivery failed")}}}}assembleWorkflowSummary(e){let t=[];for(let[n,s]of e.stepResults){let a=s.status==="completed"?"OK":s.status==="skipped"?"SKIP":"FAIL",r=s.roleName?` (${s.roleName})`:"",i=s.result??s.error??"No output";t.push(`## [${a}] Step: ${n}${r}
22
+
23
+ ${i}`)}return t.join(`
24
+
25
+ ---
26
+
27
+ `)}resolveVariables(e,t){return e.replace(/\{\{([^}]+)\.result\}\}/g,(n,s)=>t.get(s)?.result??`[no result from ${s}]`)}waitForTaskCompletion(e,t=6e5){return new Promise(n=>{let s=!1,a=Date.now(),r=()=>{s=!0,S.off("task_status_change",i)},i=o=>{s||o.taskId!==e||(o.newStatus==="completed"?(r(),n("completed")):o.newStatus==="failed"?(r(),n("failed")):o.newStatus==="cancelled"&&(r(),n("cancelled")))};S.on("task_status_change",i);let d=()=>{if(s)return;if(Date.now()-a>t){r(),n("failed");return}let o=_(e);if(!o){r(),n("failed");return}if(o.status==="completed"){r(),n("completed");return}if(o.status==="failed"){r(),n("failed");return}if(o.status==="cancelled"){r(),n("cancelled");return}setTimeout(d,5e3)};setTimeout(d,100)})}sleep(e){return new Promise(t=>setTimeout(t,e))}isWorkflowCancelled(e){return h(e)?.status==="cancelled"}finalizeCancelledWorkflow(e,t){let n=h(t.executionId);return R(t.executionId,{status:"cancelled",stepStatuses:n?.stepStatuses??t.stepStatuses,completedAt:n?.completedAt??Date.now(),error:n?.error}),f.info({executionId:t.executionId,templateId:e.id},"Workflow cancelled"),{executionId:t.executionId,status:"cancelled",stepResults:t.stepResults}}};export{h as a,R as b,L as c,B as d,P as e};
@@ -1,4 +1,4 @@
1
- import{b as i,d as a}from"./chunk-JAS3TUZX.js";a();function l(t){return{id:t.id,parentId:t.parent_id??void 0,status:t.status,prompt:t.prompt,originalPrompt:t.original_prompt??void 0,config:JSON.parse(t.config),result:t.result??void 0,error:t.error??void 0,sdkSessionId:t.sdk_session_id??void 0,templateId:t.template_id??void 0,roleId:t.role_id??void 0,stepId:t.step_id??void 0,sourceSessionId:t.source_session_id??void 0,deliverTo:t.deliver_to?JSON.parse(t.deliver_to):void 0,reportTo:t.report_to?JSON.parse(t.report_to):void 0,createdAt:t.created_at,startedAt:t.started_at??void 0,completedAt:t.completed_at??void 0,costUsd:t.cost_usd??void 0,tokenUsage:t.token_usage?JSON.parse(t.token_usage):void 0,numTurns:t.num_turns??void 0,totalDurationMs:t.total_duration_ms??void 0}}function c(t){i().prepare(`
1
+ import{b as i,d as a}from"./chunk-NCFVJCNQ.js";a();function l(t){return{id:t.id,parentId:t.parent_id??void 0,status:t.status,prompt:t.prompt,originalPrompt:t.original_prompt??void 0,config:JSON.parse(t.config),result:t.result??void 0,error:t.error??void 0,sdkSessionId:t.sdk_session_id??void 0,templateId:t.template_id??void 0,roleId:t.role_id??void 0,stepId:t.step_id??void 0,sourceSessionId:t.source_session_id??void 0,deliverTo:t.deliver_to?JSON.parse(t.deliver_to):void 0,reportTo:t.report_to?JSON.parse(t.report_to):void 0,createdAt:t.created_at,startedAt:t.started_at??void 0,completedAt:t.completed_at??void 0,costUsd:t.cost_usd??void 0,tokenUsage:t.token_usage?JSON.parse(t.token_usage):void 0,numTurns:t.num_turns??void 0,totalDurationMs:t.total_duration_ms??void 0}}function c(t){i().prepare(`
2
2
  INSERT INTO tasks (id, parent_id, status, prompt, original_prompt, config, result, error,
3
3
  sdk_session_id, template_id, role_id, step_id, source_session_id, notify_targets, deliver_to, report_to,
4
4
  created_at, started_at, completed_at,
@@ -1 +1 @@
1
- import{c as n,h as g}from"./chunk-INNDBLZE.js";g();import{query as l}from"@anthropic-ai/claude-agent-sdk";import*as i from"fs/promises";import*as a from"path";import*as m from"os";var v=n("manager"),e=a.join(m.homedir(),".adam","llm-eval");async function w(u,t){await i.mkdir(e,{recursive:!0});let o={cwd:e,maxTurns:3,maxBudgetUsd:.05};t&&(o.systemPrompt=t);let c=l({prompt:u,options:o}),s="";for await(let f of c){let r=f;r.type==="result"&&typeof r.result=="string"&&(s=r.result)}return s}export{w as a};
1
+ import{c as n,h as g}from"./chunk-MRTJFYPR.js";g();import{query as l}from"@anthropic-ai/claude-agent-sdk";import*as i from"fs/promises";import*as a from"path";import*as m from"os";var v=n("manager"),e=a.join(m.homedir(),".adam","llm-eval");async function w(u,t){await i.mkdir(e,{recursive:!0});let o={cwd:e,maxTurns:3,maxBudgetUsd:.05};t&&(o.systemPrompt=t);let c=l({prompt:u,options:o}),s="";for await(let f of c){let r=f;r.type==="result"&&typeof r.result=="string"&&(s=r.result)}return s}export{w as a};
@@ -1,4 +1,4 @@
1
- import{a as oe}from"./chunk-5V36ACKZ.js";import{k as F}from"./chunk-VRJ7R766.js";import{b as ee}from"./chunk-Y3AMO6WC.js";import{a as Z,b as h}from"./chunk-ISZJV72D.js";import{e as N,f as D,j as Ae}from"./chunk-QWCRZDZS.js";import{a as Q}from"./chunk-UQJZU3R5.js";import{d as K}from"./chunk-GSMC3VUM.js";import{c as te,i as Ce,l as re,o as ne,r as xe}from"./chunk-GBTG5B5R.js";import{b as u,d as v}from"./chunk-JAS3TUZX.js";import{a as z,h as Le}from"./chunk-WBAPIPST.js";import{c as k,h as X}from"./chunk-INNDBLZE.js";Ce();import{homedir as Ie}from"os";import{resolve as j}from"path";import{z as g}from"zod";Le();function ie(){return[...z]}xe();Ae();var Oe=new Set(ie()),Pe=g.object({tools:g.array(g.string().refine(t=>Oe.has(t),{message:"Unknown tool"})).optional(),paths:g.array(g.object({path:g.string().refine(t=>t.startsWith("/")||t.startsWith("~"),{message:"path must be absolute or tilde-prefixed"}),access:g.enum(["ro","rw"])})).optional(),osCapabilities:g.array(g.object({id:g.enum(te),targets:g.array(g.string()).optional()})).optional(),network:g.boolean().optional(),plugins:g.array(g.string()).optional()});function ae(t){return t.startsWith("~")?t.replace(/^~/,Ie()):t}function Ne(t){let e=ae(t);return e.startsWith("/")?j(e):null}function ce(t,e){let n=[{path:j(e),access:"rw"}];for(let r of t.additionalDirectories??[])n.push({path:j(ae(r.path)),access:r.mode??"rw"});return n}function U(t,e){let n=Ne(t.path);if(!n)return!1;let r=e.filter(o=>n===o.path||n.startsWith(`${o.path}/`)).sort((o,s)=>s.path.length-o.path.length);if(r.length===0)return!1;let i=r[0];return t.access==="rw"?i.access==="rw":!0}function B(t,e){if(!t?.length)return[];let n=new Set(e??[]);return t.filter(r=>!n.has(r))}function G(t,e){if(!t?.length)return[];let n=new Set((e??[]).map(r=>r.id));return t.filter(r=>!n.has(r.id))}function W(t,e){if(!t?.length)return[];let n=new Set(e);return t.filter(r=>!n.has(r))}function H(t,e){return t?(e??[]).some(n=>n.id==="local-network"):!0}function le(t,e,n,r){let i=[];if(e.tools?.length){let o=B(e.tools,t.allowedTools).length;i.push((e.tools.length-o)/e.tools.length)}if(e.paths?.length){let o=e.paths.filter(s=>U(s,n)).length;i.push(o/e.paths.length)}if(e.osCapabilities?.length){let o=G(e.osCapabilities,t.osCapabilities).length;i.push((e.osCapabilities.length-o)/e.osCapabilities.length)}if(e.plugins?.length){let o=W(e.plugins,r).length;i.push((e.plugins.length-o)/e.plugins.length)}return e.network===!0&&i.push(H(e.network,t.osCapabilities)?1:0),i.length===0?1:i.reduce((o,s)=>o+s,0)/i.length}function De(t,e){if(!e.tools?.length||!t.approvalRequired?.length)return[];let n=new Set(t.approvalRequired),r=e.tools.filter(o=>n.has(o));if(!r.length)return[];let i=e.paths?.filter(o=>o.access==="rw").length??0;return[{code:"APPROVAL_WILL_TRIGGER",tools:r,expectedPromptCount:Math.max(r.length,i||r.length)}]}function Fe(t,e,n,r){let i=B(e.tools,t.allowedTools),o=(e.paths??[]).filter(d=>!U(d,n)),s=G(e.osCapabilities,t.osCapabilities),c=W(e.plugins,r),a={};return i.length&&(a.tools=i),o.length&&(a.paths=o),s.length&&(a.osCapabilities=s),c.length&&(a.plugins=c),e.network===!0&&!H(e.network,t.osCapabilities)&&(a.network=!0),a}function de(t,e){D(t);let n=N(t.name),r=ce(t,n),o=F(t).plugins.map(l=>l.name),s=B(e.tools,t.allowedTools);if(s.length)return{ok:!1,code:"ROLE_TOOL_MISMATCH",reason:`Missing tools: ${s.join(", ")}`,missing:{tools:s}};let c=(e.paths??[]).filter(l=>!U(l,r));if(c.length)return{ok:!1,code:"ROLE_PATH_SCOPE_MISMATCH",reason:`Missing path scope: ${c.map(l=>`${l.path} (${l.access})`).join(", ")}`,missing:{paths:c}};let a=G(e.osCapabilities,t.osCapabilities);if(a.length)return{ok:!1,code:"ROLE_OS_CAPABILITY_MISMATCH",reason:`Missing OS capabilities: ${a.map(l=>l.id).join(", ")}`,missing:{osCapabilities:a}};let d=W(e.plugins,o);return d.length?{ok:!1,code:"ROLE_PLUGIN_MISMATCH",reason:`Missing plugins: ${d.join(", ")}`,missing:{plugins:d}}:e.network===!0&&!H(e.network,t.osCapabilities)?{ok:!1,code:"ROLE_NETWORK_MISMATCH",reason:"Role lacks network capability (local-network)",missing:{network:!0}}:{ok:!0,roleId:t.id,executionProfile:t,fitScore:le(t,e,r,o),warnings:De(t,e)}}function se(t){return ne("active",100,0).filter(e=>e.source!=="system").map(e=>{D(e);let n=ce(e,N(e.name)),i=F(e).plugins.map(s=>s.name),o=de(e,t);return{role:e,evaluation:o,fitScore:le(e,t,n,i),missing:Fe(e,t,n,i)}}).sort((e,n)=>{let r=n.fitScore-e.fitScore;return r!==0?r:(n.role.performanceScore??0)-(e.role.performanceScore??0)})}async function ue(t){let{requirements:e,roleId:n,autoSelectRole:r}=t;if(!n&&!r)return{ok:!1,code:"REQUIREMENTS_MISSING",reason:"Must provide either roleId or autoSelectRole=true"};if(e){let l=Pe.safeParse(e);if(!l.success)return{ok:!1,code:"REQUIREMENTS_MISSING",reason:g.prettifyError(l.error)}}if(r&&!e)return{ok:!1,code:"REQUIREMENTS_MISSING",reason:"autoSelectRole requires a requirements object"};let i=e??{};if(n&&!r){let l=re(n);if(!l||l.status!=="active")return{ok:!1,code:"ROLE_NOT_FOUND",reason:`Role not found or not active: ${n}`};let p=de(l,i);return p.ok?(p.auditCandidates=[{roleId:l.id,name:l.name,fitScore:p.fitScore,fits:!0}],p):(e&&(p.candidates=se(e).map(S=>({roleId:S.role.id,name:S.role.name,fitScore:S.fitScore,missing:S.missing}))),p)}let o=se(e),s=o.filter(l=>l.evaluation.ok);if(!s.length)return{ok:!1,code:"ROLE_SELECTION_AMBIGUOUS",reason:"No role covers the requirements",candidates:o.map(l=>({roleId:l.role.id,name:l.role.name,fitScore:l.fitScore,missing:l.missing}))};let c=s[0],a=c.evaluation,d=s[1];return d&&d.fitScore===c.fitScore&&(a.tieBreakReason=`fitScore tie at ${c.fitScore}; chose ${c.role.name} by performanceScore`),a.auditCandidates=o.map(l=>({roleId:l.role.id,name:l.role.name,fitScore:l.fitScore,fits:l.evaluation.ok})),a}v();function L(t){return{id:t.id,roleId:t.role_id,taskType:t.task_type,name:t.name,promptTemplate:t.prompt_template,alpha:t.alpha,beta:t.beta,totalTrials:t.total_trials,avgReward:t.avg_reward??void 0,createdAt:t.created_at,updatedAt:t.updated_at??void 0}}function pe(t){u().prepare(`
1
+ import{a as oe}from"./chunk-IZNEOYRP.js";import{k as F}from"./chunk-3LY6PD6A.js";import{b as ee}from"./chunk-7446ZS6D.js";import{a as Z,b as h}from"./chunk-I7ZZKPHE.js";import{e as N,f as D,j as Ae}from"./chunk-DBP7GPWG.js";import{a as Q}from"./chunk-UQJZU3R5.js";import{d as K}from"./chunk-GSMC3VUM.js";import{c as te,i as Ce,l as re,o as ne,r as xe}from"./chunk-7ZGSJCX5.js";import{b as u,d as v}from"./chunk-NCFVJCNQ.js";import{a as z,h as Le}from"./chunk-WBAPIPST.js";import{c as k,h as X}from"./chunk-MRTJFYPR.js";Ce();import{homedir as Ie}from"os";import{resolve as j}from"path";import{z as g}from"zod";Le();function ie(){return[...z]}xe();Ae();var Oe=new Set(ie()),Pe=g.object({tools:g.array(g.string().refine(t=>Oe.has(t),{message:"Unknown tool"})).optional(),paths:g.array(g.object({path:g.string().refine(t=>t.startsWith("/")||t.startsWith("~"),{message:"path must be absolute or tilde-prefixed"}),access:g.enum(["ro","rw"])})).optional(),osCapabilities:g.array(g.object({id:g.enum(te),targets:g.array(g.string()).optional()})).optional(),network:g.boolean().optional(),plugins:g.array(g.string()).optional()});function ae(t){return t.startsWith("~")?t.replace(/^~/,Ie()):t}function Ne(t){let e=ae(t);return e.startsWith("/")?j(e):null}function ce(t,e){let n=[{path:j(e),access:"rw"}];for(let r of t.additionalDirectories??[])n.push({path:j(ae(r.path)),access:r.mode??"rw"});return n}function U(t,e){let n=Ne(t.path);if(!n)return!1;let r=e.filter(o=>n===o.path||n.startsWith(`${o.path}/`)).sort((o,s)=>s.path.length-o.path.length);if(r.length===0)return!1;let i=r[0];return t.access==="rw"?i.access==="rw":!0}function B(t,e){if(!t?.length)return[];let n=new Set(e??[]);return t.filter(r=>!n.has(r))}function G(t,e){if(!t?.length)return[];let n=new Set((e??[]).map(r=>r.id));return t.filter(r=>!n.has(r.id))}function W(t,e){if(!t?.length)return[];let n=new Set(e);return t.filter(r=>!n.has(r))}function H(t,e){return t?(e??[]).some(n=>n.id==="local-network"):!0}function le(t,e,n,r){let i=[];if(e.tools?.length){let o=B(e.tools,t.allowedTools).length;i.push((e.tools.length-o)/e.tools.length)}if(e.paths?.length){let o=e.paths.filter(s=>U(s,n)).length;i.push(o/e.paths.length)}if(e.osCapabilities?.length){let o=G(e.osCapabilities,t.osCapabilities).length;i.push((e.osCapabilities.length-o)/e.osCapabilities.length)}if(e.plugins?.length){let o=W(e.plugins,r).length;i.push((e.plugins.length-o)/e.plugins.length)}return e.network===!0&&i.push(H(e.network,t.osCapabilities)?1:0),i.length===0?1:i.reduce((o,s)=>o+s,0)/i.length}function De(t,e){if(!e.tools?.length||!t.approvalRequired?.length)return[];let n=new Set(t.approvalRequired),r=e.tools.filter(o=>n.has(o));if(!r.length)return[];let i=e.paths?.filter(o=>o.access==="rw").length??0;return[{code:"APPROVAL_WILL_TRIGGER",tools:r,expectedPromptCount:Math.max(r.length,i||r.length)}]}function Fe(t,e,n,r){let i=B(e.tools,t.allowedTools),o=(e.paths??[]).filter(d=>!U(d,n)),s=G(e.osCapabilities,t.osCapabilities),c=W(e.plugins,r),a={};return i.length&&(a.tools=i),o.length&&(a.paths=o),s.length&&(a.osCapabilities=s),c.length&&(a.plugins=c),e.network===!0&&!H(e.network,t.osCapabilities)&&(a.network=!0),a}function de(t,e){D(t);let n=N(t.name),r=ce(t,n),o=F(t).plugins.map(l=>l.name),s=B(e.tools,t.allowedTools);if(s.length)return{ok:!1,code:"ROLE_TOOL_MISMATCH",reason:`Missing tools: ${s.join(", ")}`,missing:{tools:s}};let c=(e.paths??[]).filter(l=>!U(l,r));if(c.length)return{ok:!1,code:"ROLE_PATH_SCOPE_MISMATCH",reason:`Missing path scope: ${c.map(l=>`${l.path} (${l.access})`).join(", ")}`,missing:{paths:c}};let a=G(e.osCapabilities,t.osCapabilities);if(a.length)return{ok:!1,code:"ROLE_OS_CAPABILITY_MISMATCH",reason:`Missing OS capabilities: ${a.map(l=>l.id).join(", ")}`,missing:{osCapabilities:a}};let d=W(e.plugins,o);return d.length?{ok:!1,code:"ROLE_PLUGIN_MISMATCH",reason:`Missing plugins: ${d.join(", ")}`,missing:{plugins:d}}:e.network===!0&&!H(e.network,t.osCapabilities)?{ok:!1,code:"ROLE_NETWORK_MISMATCH",reason:"Role lacks network capability (local-network)",missing:{network:!0}}:{ok:!0,roleId:t.id,executionProfile:t,fitScore:le(t,e,r,o),warnings:De(t,e)}}function se(t){return ne("active",100,0).filter(e=>e.source!=="system").map(e=>{D(e);let n=ce(e,N(e.name)),i=F(e).plugins.map(s=>s.name),o=de(e,t);return{role:e,evaluation:o,fitScore:le(e,t,n,i),missing:Fe(e,t,n,i)}}).sort((e,n)=>{let r=n.fitScore-e.fitScore;return r!==0?r:(n.role.performanceScore??0)-(e.role.performanceScore??0)})}async function ue(t){let{requirements:e,roleId:n,autoSelectRole:r}=t;if(!n&&!r)return{ok:!1,code:"REQUIREMENTS_MISSING",reason:"Must provide either roleId or autoSelectRole=true"};if(e){let l=Pe.safeParse(e);if(!l.success)return{ok:!1,code:"REQUIREMENTS_MISSING",reason:g.prettifyError(l.error)}}if(r&&!e)return{ok:!1,code:"REQUIREMENTS_MISSING",reason:"autoSelectRole requires a requirements object"};let i=e??{};if(n&&!r){let l=re(n);if(!l||l.status!=="active")return{ok:!1,code:"ROLE_NOT_FOUND",reason:`Role not found or not active: ${n}`};let p=de(l,i);return p.ok?(p.auditCandidates=[{roleId:l.id,name:l.name,fitScore:p.fitScore,fits:!0}],p):(e&&(p.candidates=se(e).map(S=>({roleId:S.role.id,name:S.role.name,fitScore:S.fitScore,missing:S.missing}))),p)}let o=se(e),s=o.filter(l=>l.evaluation.ok);if(!s.length)return{ok:!1,code:"ROLE_SELECTION_AMBIGUOUS",reason:"No role covers the requirements",candidates:o.map(l=>({roleId:l.role.id,name:l.role.name,fitScore:l.fitScore,missing:l.missing}))};let c=s[0],a=c.evaluation,d=s[1];return d&&d.fitScore===c.fitScore&&(a.tieBreakReason=`fitScore tie at ${c.fitScore}; chose ${c.role.name} by performanceScore`),a.auditCandidates=o.map(l=>({roleId:l.role.id,name:l.role.name,fitScore:l.fitScore,fits:l.evaluation.ok})),a}v();function L(t){return{id:t.id,roleId:t.role_id,taskType:t.task_type,name:t.name,promptTemplate:t.prompt_template,alpha:t.alpha,beta:t.beta,totalTrials:t.total_trials,avgReward:t.avg_reward??void 0,createdAt:t.created_at,updatedAt:t.updated_at??void 0}}function pe(t){u().prepare(`
2
2
  INSERT INTO strategies (id, role_id, task_type, name, prompt_template,
3
3
  alpha, beta, total_trials, avg_reward, created_at, updated_at)
4
4
  VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
@@ -0,0 +1,23 @@
1
+ import{f as d,j as v}from"./chunk-DBP7GPWG.js";import{k as c,l as f,m as h,o as R,r as w}from"./chunk-7ZGSJCX5.js";import{c as p,h as y}from"./chunk-MRTJFYPR.js";w();v();y();import{v4 as i}from"uuid";var n=p("store"),u="role-chat-manager",m=[{name:"Engineer",cagPrompt:`Role: General-purpose software engineer.
2
+ Capabilities: Read, write, and edit code; run shell commands; search codebases.
3
+ Approach: Analyze requirements \u2192 implement \u2192 test \u2192 verify. Write tests for new code. Follow existing code patterns.
4
+ Best for: Feature implementation, bug fixes, refactoring, build/deploy scripts.
5
+ Constraints: No web access. Works only within the assigned workspace directory.`,allowedTools:["Read","Write","Edit","Bash","Grep","Glob"],evaluationCriteria:{code_quality:4,test_pass:4,build_success:3},executionMode:"isolated"},{name:"Reviewer",cagPrompt:`Role: Code reviewer and security auditor. READ-ONLY \u2014 you do not modify files.
6
+ Capabilities: Read files, search code, run analysis commands (linters, type-checkers, test suites).
7
+ Approach: Systematically review code for bugs, security issues, performance problems, and style violations. Output structured findings with file:line references.
8
+ Best for: Code review, security audit, dependency audit, test coverage analysis.
9
+ Constraints: No Write or Edit tools. Cannot modify code \u2014 only report findings.`,allowedTools:["Read","Grep","Glob","Bash"],evaluationCriteria:{bug_detection_rate:5,insight_quality:4},executionMode:"isolated"},{name:"Researcher",cagPrompt:`Role: Information researcher and analyst with web access.
10
+ Capabilities: Search the web, fetch web pages, read local files, run data processing scripts.
11
+ Approach: Gather information from multiple sources \u2192 cross-reference \u2192 synthesize findings into structured reports.
12
+ Best for: Market research, technical investigation, API documentation lookup, competitive analysis, news monitoring.
13
+ Constraints: No file write/edit permissions. Cannot modify the codebase \u2014 only research and report.`,allowedTools:["WebSearch","WebFetch","Read","Grep","Glob","Bash"],evaluationCriteria:{insight_quality:5,data_accuracy:5},executionMode:"isolated"},{name:"Writer",cagPrompt:`Role: Content writer and document generator.
14
+ Capabilities: Create and edit text files, read reference material, search for context.
15
+ Approach: Understand the target audience and format \u2192 draft \u2192 refine. Match the project's existing tone and terminology.
16
+ Best for: Documentation, reports, emails, translations, summaries, changelog entries.
17
+ Constraints: No shell command execution. No web access. Works only with file read/write operations.`,allowedTools:["Read","Write","Edit","Grep","Glob"],evaluationCriteria:{content_quality:5,engagement:4},executionMode:"isolated"}],C=["Chat Manager","adam-automator",...m.map(t=>t.name)];function D(t){return t.source==="system"?!0:t.source==="user"?!1:C.includes(t.name)}function E(){b(),x();let t=R(void 0,1e3,0),o=new Set(m.map(e=>e.name)),r=t.filter(e=>o.has(e.name));if(r.length>0)return n.info({count:r.length},"Default roles already exist, skipping"),t;n.info({count:m.length},"Creating default roles");let s=[];for(let e of m){let l=`role-${i().slice(0,8)}`,g={id:l,name:e.name,cagPrompt:e.cagPrompt,learnedRules:[],memoryStreamId:`mem-${i().slice(0,8)}`,status:"active",preferences:{},createdAt:Date.now(),allowedTools:e.allowedTools,evaluationCriteria:e.evaluationCriteria,executionMode:e.executionMode};c(g),s.push(g),d(g),n.info({roleId:l,name:e.name},"Created default role")}return s}function b(){if(f(u)){n.debug({roleId:u},"ChatManager system role already exists");return}let o={id:u,name:"Chat Manager",cagPrompt:`You are the Chat Manager \u2014 orchestrating conversations and managing agent interactions.
18
+ You coordinate between user requests and agent execution, maintaining conversation context
19
+ and routing tasks to the appropriate roles. You have broad memory access across all roles.`,learnedRules:[],memoryStreamId:`mem-${i().slice(0,8)}`,status:"active",preferences:{},createdAt:Date.now()};c(o),d(o),n.info({roleId:u},"Created ChatManager system role")}var a={name:"adam-automator",cagPrompt:`Role: Deterministic automation executor.
20
+ Capabilities: Run preset Skills under .claude/skills/. Read/write files in the assigned workspace.
21
+ Approach: When given an event and Skill name, invoke that Skill with the provided inputs. Do not interpret, do not deviate from the instruction, do not chain additional Skills unless told.
22
+ Best for: Event-triggered deterministic logic (feature aggregation, threshold checks, artifact persistence, routing classification, event chaining).
23
+ Constraints: Minimize LLM reasoning \u2014 call the specified Skill and return its output. If the instruction is ambiguous, return an error message instead of guessing.`,allowedTools:["Skill","Read","Write","Edit","Bash","Grep","Glob"],evaluationCriteria:{determinism:5,skill_invocation_rate:5},executionMode:"isolated",model:"claude-haiku-4-5-20251001"};function x(){let t=h(a.name);if(t)return t;let o=`role-${i().slice(0,8)}`,r=i(),s=Date.now(),e={id:o,name:a.name,cagPrompt:a.cagPrompt,learnedRules:[],memoryStreamId:r,status:"active",preferences:{},createdAt:s,allowedTools:a.allowedTools,evaluationCriteria:a.evaluationCriteria,executionMode:a.executionMode,model:a.model};return c(e),d(e),A(e.id).catch(l=>{n.warn({roleId:o,err:l},"Failed to seed adam-automator Skills")}),n.info({roleId:o,name:a.name},"Created adam-automator Role"),e}async function A(t){try{let{seedAdamAutomatorSkills:o}=await import("./adam-automator-skills-UFW5TXCC.js");await o(t)}catch{}}export{u as a,C as b,D as c,E as d,x as e};
@@ -1 +1 @@
1
- import{a as m,c as d}from"./chunk-FCV2DPZQ.js";import o from"pino";import{Writable as g}from"stream";function b(n){i.push(n)}function L(){if(h)try{return m("pino-pretty")({colorize:!0,translateTime:"HH:MM:ss.l",ignore:"pid,hostname"})}catch{}return process.stdout}function y(n){return r[n]||e}function E(n){e.level=n;for(let t of Object.values(r))t.level=n}function S(){return e.level}function w(n){a=n}function C(){return a}var p,i,u,h,e,r,a,v=d(()=>{p=process.env.ADAM_LOG_LEVEL||"info",i=[];u=new g({write(n,t,l){try{let s=JSON.parse(n.toString());for(let c of i)c(s)}catch{}l()}}),h=process.env.NODE_ENV!=="production";e=o({level:p,timestamp:o.stdTimeFunctions.epochTime,formatters:{level:n=>({level:n}),bindings:n=>({component:n.name})},serializers:{error:o.stdSerializers.err}},o.multistream([{stream:L()},{stream:u}])),r={adam:e.child({name:"adam"}),manager:e.child({name:"manager"}),scheduler:e.child({name:"scheduler"}),api:e.child({name:"api"}),ws:e.child({name:"ws"}),cli:e.child({name:"cli"}),store:e.child({name:"store"}),embedding:e.child({name:"embedding"}),admin:e.child({name:"admin"}),agent:e.child({name:"agent"}),channels:e.child({name:"channels"}),"plugin-sync":e.child({name:"plugin-sync"}),watchdog:e.child({name:"watchdog"}),"chat-manager":e.child({name:"chat-manager"}),execution:e.child({name:"execution"}),"execution-pool":e.child({name:"execution-pool"}),"message-handler":e.child({name:"message-handler"}),"goal-manager":e.child({name:"goal-manager"}),"cli:register-ai-digest":e.child({name:"cli:register-ai-digest"}),"sandbox-macos":e.child({name:"sandbox-macos"}),"sandbox-linux":e.child({name:"sandbox-linux"}),sandbox:e.child({name:"sandbox"}),audit:e.child({name:"audit"}),config:e.child({name:"config"})};a=null});export{b as a,e as b,y as c,E as d,S as e,w as f,C as g,v as h};
1
+ import{a as m,c as d}from"./chunk-FCV2DPZQ.js";import o from"pino";import{Writable as g}from"stream";function b(n){i.push(n)}function L(){if(u)try{return m("pino-pretty")({colorize:!0,translateTime:"HH:MM:ss.l",ignore:"pid,hostname"})}catch{}return process.stdout}function y(n){return r[n]||e}function E(n){e.level=n;for(let t of Object.values(r))t.level=n}function S(){return e.level}function w(n){a=n}function C(){return a}var p,i,h,u,e,r,a,v=d(()=>{p=process.env.ADAM_LOG_LEVEL||"info",i=[];h=new g({write(n,t,l){try{let c=JSON.parse(n.toString());for(let s of i)s(c)}catch{}l()}}),u=process.env.NODE_ENV!=="production";e=o({level:p,timestamp:o.stdTimeFunctions.epochTime,formatters:{level:n=>({level:n}),bindings:n=>({component:n.name})},serializers:{error:o.stdSerializers.err}},o.multistream([{stream:L()},{stream:h}])),r={adam:e.child({name:"adam"}),manager:e.child({name:"manager"}),scheduler:e.child({name:"scheduler"}),api:e.child({name:"api"}),ws:e.child({name:"ws"}),cli:e.child({name:"cli"}),store:e.child({name:"store"}),embedding:e.child({name:"embedding"}),admin:e.child({name:"admin"}),agent:e.child({name:"agent"}),channels:e.child({name:"channels"}),"plugin-sync":e.child({name:"plugin-sync"}),watchdog:e.child({name:"watchdog"}),"chat-manager":e.child({name:"chat-manager"}),execution:e.child({name:"execution"}),"execution-pool":e.child({name:"execution-pool"}),"message-handler":e.child({name:"message-handler"}),"goal-manager":e.child({name:"goal-manager"}),"cli:register-ai-digest":e.child({name:"cli:register-ai-digest"}),"sandbox-macos":e.child({name:"sandbox-macos"}),"sandbox-linux":e.child({name:"sandbox-linux"}),sandbox:e.child({name:"sandbox"}),audit:e.child({name:"audit"}),config:e.child({name:"config"}),"event-dispatcher":e.child({name:"event-dispatcher"})};a=null});export{b as a,e as b,y as c,E as d,S as e,w as f,C as g,v as h};
@@ -1 +1 @@
1
- import{d as b,h as k}from"./chunk-WBAPIPST.js";import{c as w,h as x}from"./chunk-INNDBLZE.js";k();x();import{constants as S,copyFileSync as g,existsSync as d,lstatSync as P,mkdirSync as $,readdirSync as E,realpathSync as u,rmSync as z,statSync as m,unlinkSync as h}from"fs";import{dirname as I,extname as R,isAbsolute as B,join as a,sep as c}from"path";var y=w("watchdog");function W(){return process.env.ADAM_TEST_DIR||b}function p(){return a(W(),"workflows")}function v(t){return a(p(),t,"artifacts")}function D(t){let r=v(t);return $(r,{recursive:!0}),r}function T(t,r,i){if(!B(t))throw new Error(`path must be absolute: ${t}`);let o=u(r),s=o.endsWith(c)?o:o+c;if(i){let n=u(t),f=n.endsWith(c)?n:n+c;if(f===s||f.startsWith(s))return;throw new Error(`path escapes workspace: ${t} (resolved=${n}, root=${o})`)}if(d(t))throw P(t).isSymbolicLink()?new Error(`destination already exists and is a symlink: ${t}`):new Error(`destination already exists: ${t}`);let e=u(I(t)),l=e.endsWith(c)?e:e+c;if(!(l===s||l.startsWith(s)))throw new Error(`destination escapes workspace: ${t} (parent resolved=${e}, root=${o})`)}function C(t){let r=D(t.executionId),i=a(r,`${t.artifactId}.bin`);return g(t.sourcePath,i),{blobPath:i,sizeBytes:m(i).size}}function O(t){h(t)}function j(t){if(!d(t.blobPath))throw new Error(`blob file missing on disk: ${t.blobPath}`);return g(t.blobPath,t.destPath,S.COPYFILE_EXCL),{sizeBytes:m(t.destPath).size}}function F(t){try{h(t)}catch(r){y.warn({err:r,blobPath:t},"Failed to remove workflow artifact blob")}}function N(t){try{z(a(p(),t),{recursive:!0,force:!0})}catch(r){y.warn({err:r,executionId:t},"Failed to remove workflow artifacts directory")}}function U(t,r,i){let o=v(t);if(!d(o))return 0;let s=0;for(let e of E(o)){if(R(e)!==".bin")continue;let l=e.slice(0,-4);if(r.has(l))continue;let n=a(o,e),f=m(n);Date.now()-f.mtimeMs<i||(F(n),s++)}return s}export{D as a,T as b,C as c,O as d,j as e,F as f,N as g,U as h};
1
+ import{d as b,h as k}from"./chunk-WBAPIPST.js";import{c as w,h as x}from"./chunk-MRTJFYPR.js";k();x();import{constants as S,copyFileSync as g,existsSync as d,lstatSync as P,mkdirSync as $,readdirSync as E,realpathSync as u,rmSync as z,statSync as m,unlinkSync as h}from"fs";import{dirname as I,extname as R,isAbsolute as B,join as a,sep as c}from"path";var y=w("watchdog");function W(){return process.env.ADAM_TEST_DIR||b}function p(){return a(W(),"workflows")}function v(t){return a(p(),t,"artifacts")}function D(t){let r=v(t);return $(r,{recursive:!0}),r}function T(t,r,i){if(!B(t))throw new Error(`path must be absolute: ${t}`);let o=u(r),s=o.endsWith(c)?o:o+c;if(i){let n=u(t),f=n.endsWith(c)?n:n+c;if(f===s||f.startsWith(s))return;throw new Error(`path escapes workspace: ${t} (resolved=${n}, root=${o})`)}if(d(t))throw P(t).isSymbolicLink()?new Error(`destination already exists and is a symlink: ${t}`):new Error(`destination already exists: ${t}`);let e=u(I(t)),l=e.endsWith(c)?e:e+c;if(!(l===s||l.startsWith(s)))throw new Error(`destination escapes workspace: ${t} (parent resolved=${e}, root=${o})`)}function C(t){let r=D(t.executionId),i=a(r,`${t.artifactId}.bin`);return g(t.sourcePath,i),{blobPath:i,sizeBytes:m(i).size}}function O(t){h(t)}function j(t){if(!d(t.blobPath))throw new Error(`blob file missing on disk: ${t.blobPath}`);return g(t.blobPath,t.destPath,S.COPYFILE_EXCL),{sizeBytes:m(t.destPath).size}}function F(t){try{h(t)}catch(r){y.warn({err:r,blobPath:t},"Failed to remove workflow artifact blob")}}function N(t){try{z(a(p(),t),{recursive:!0,force:!0})}catch(r){y.warn({err:r,executionId:t},"Failed to remove workflow artifacts directory")}}function U(t,r,i){let o=v(t);if(!d(o))return 0;let s=0;for(let e of E(o)){if(R(e)!==".bin")continue;let l=e.slice(0,-4);if(r.has(l))continue;let n=a(o,e),f=m(n);Date.now()-f.mtimeMs<i||(F(n),s++)}return s}export{D as a,T as b,C as c,O as d,j as e,F as f,N as g,U as h};
@@ -1,4 +1,4 @@
1
- import{e as A,h as O}from"./chunk-WBAPIPST.js";import{c as R,h as X}from"./chunk-INNDBLZE.js";import{c as m}from"./chunk-FCV2DPZQ.js";import p from"better-sqlite3";import{existsSync as S,mkdirSync as u}from"fs";import{dirname as g}from"path";function D(e){e.exec(`
1
+ import{e as R,h as p}from"./chunk-WBAPIPST.js";import{c as I,h as O}from"./chunk-MRTJFYPR.js";import{c as m}from"./chunk-FCV2DPZQ.js";import X from"better-sqlite3";import{existsSync as S,mkdirSync as u}from"fs";import{dirname as g}from"path";function U(e){e.exec(`
2
2
  CREATE TABLE IF NOT EXISTS server_state (
3
3
  id INTEGER PRIMARY KEY CHECK(id = 1),
4
4
  sdk_session_id TEXT,
@@ -8,7 +8,7 @@ import{e as A,h as O}from"./chunk-WBAPIPST.js";import{c as R,h as X}from"./chunk
8
8
  created_at INTEGER NOT NULL DEFAULT (unixepoch('now') * 1000),
9
9
  last_active_at INTEGER
10
10
  );
11
- `),e.prepare("PRAGMA table_info(server_state)").all().some(E=>E.name==="schema_version")||e.exec("ALTER TABLE server_state ADD COLUMN schema_version INTEGER DEFAULT 0");let _=e.prepare("SELECT schema_version FROM server_state WHERE id = 1").get()?.schema_version??0;if(_<2){let E=["delivery_log","delivery_rules","manager_decisions","skill_scores","approval_rules","task_plans","calibration_history","task_plugins","marketplaces","plugins","trials","strategies","metric_tree","goals","chat_messages","chat_sessions","channels","evolution_audit","step_logs","task_templates","memories","tasks","config","memories_fts","memories_fts_config","memories_fts_data","memories_fts_docsize","memories_fts_idx"];for(let s of E)try{e.exec(`DROP TABLE IF EXISTS ${s}`)}catch{}for(let s of["memories_fts_insert","memories_fts_delete","memories_fts_update"])try{e.exec(`DROP TRIGGER IF EXISTS ${s}`)}catch{}}if(e.exec(`
11
+ `),e.prepare("PRAGMA table_info(server_state)").all().some(E=>E.name==="schema_version")||e.exec("ALTER TABLE server_state ADD COLUMN schema_version INTEGER DEFAULT 0");let o=e.prepare("SELECT schema_version FROM server_state WHERE id = 1").get()?.schema_version??0;if(o<2){let E=["delivery_log","delivery_rules","manager_decisions","skill_scores","approval_rules","task_plans","calibration_history","task_plugins","marketplaces","plugins","trials","strategies","metric_tree","goals","chat_messages","chat_sessions","channels","evolution_audit","step_logs","task_templates","memories","tasks","config","memories_fts","memories_fts_config","memories_fts_data","memories_fts_docsize","memories_fts_idx"];for(let s of E)try{e.exec(`DROP TABLE IF EXISTS ${s}`)}catch{}for(let s of["memories_fts_insert","memories_fts_delete","memories_fts_update"])try{e.exec(`DROP TRIGGER IF EXISTS ${s}`)}catch{}}if(e.exec(`
12
12
  CREATE TABLE IF NOT EXISTS tasks (
13
13
  id TEXT PRIMARY KEY,
14
14
  parent_id TEXT,
@@ -368,7 +368,7 @@ import{e as A,h as O}from"./chunk-WBAPIPST.js";import{c as R,h as X}from"./chunk
368
368
 
369
369
  CREATE INDEX IF NOT EXISTS idx_calibration_goal ON calibration_history(goal_id);
370
370
  CREATE INDEX IF NOT EXISTS idx_calibration_computed ON calibration_history(computed_at);
371
- `),_<2&&e.exec("UPDATE server_state SET schema_version = 2 WHERE id = 1"),(e.prepare("SELECT schema_version FROM server_state WHERE id = 1").get()?.schema_version??0)<4&&(e.exec(`
371
+ `),o<2&&e.exec("UPDATE server_state SET schema_version = 2 WHERE id = 1"),(e.prepare("SELECT schema_version FROM server_state WHERE id = 1").get()?.schema_version??0)<4&&(e.exec(`
372
372
  CREATE TABLE IF NOT EXISTS roles (
373
373
  id TEXT PRIMARY KEY,
374
374
  name TEXT NOT NULL UNIQUE,
@@ -567,7 +567,7 @@ import{e as A,h as O}from"./chunk-WBAPIPST.js";import{c as R,h as X}from"./chunk
567
567
  bound_at INTEGER NOT NULL,
568
568
  PRIMARY KEY (role_id, plugin_id)
569
569
  );
570
- `),e.exec("UPDATE server_state SET schema_version = 10 WHERE id = 1"),e.exec("PRAGMA foreign_keys = ON")}if(_<11){try{e.exec("ALTER TABLE task_templates RENAME COLUMN skill_preference TO role_preference")}catch(E){let s=e.prepare("PRAGMA table_info(task_templates)").all(),T=s.some(i=>i.name==="role_preference"),t=s.some(i=>i.name==="skill_preference");if(!T&&t)throw E}e.exec("UPDATE server_state SET schema_version = 11 WHERE id = 1")}if(_<12&&(e.prepare("PRAGMA table_info(server_state)").all().some(s=>s.name==="tools_fingerprint")||e.exec("ALTER TABLE server_state ADD COLUMN tools_fingerprint TEXT"),e.exec("UPDATE server_state SET schema_version = 12 WHERE id = 1")),_<13&&(e.prepare("PRAGMA table_info(roles)").all().some(s=>s.name==="additional_directories")||e.exec("ALTER TABLE roles ADD COLUMN additional_directories TEXT"),e.exec("UPDATE server_state SET schema_version = 13 WHERE id = 1")),_<14){let E=e.prepare("PRAGMA table_info(roles)").all();E.some(t=>t.name==="allowed_channels")||e.exec("ALTER TABLE roles ADD COLUMN allowed_channels TEXT"),E.some(t=>t.name==="mcp_servers")||e.exec("ALTER TABLE roles ADD COLUMN mcp_servers TEXT");let s=e.prepare("PRAGMA table_info(tasks)").all();s.some(t=>t.name==="deliver_to")||e.exec("ALTER TABLE tasks ADD COLUMN deliver_to TEXT"),s.some(t=>t.name==="report_to")||e.exec("ALTER TABLE tasks ADD COLUMN report_to TEXT"),e.prepare("PRAGMA table_info(goals)").all().some(t=>t.name==="deliver_to")||e.exec("ALTER TABLE goals ADD COLUMN deliver_to TEXT"),e.exec("UPDATE server_state SET schema_version = 14 WHERE id = 1")}if(_<15&&(e.prepare("PRAGMA table_info(roles)").all().some(s=>s.name==="inherit_user_settings")||e.exec("ALTER TABLE roles ADD COLUMN inherit_user_settings INTEGER DEFAULT 0"),e.exec("UPDATE server_state SET schema_version = 15 WHERE id = 1")),_<16&&(e.prepare("PRAGMA table_info(task_templates)").all().some(s=>s.name==="deliver_to")||e.exec("ALTER TABLE task_templates ADD COLUMN deliver_to TEXT"),e.exec("UPDATE server_state SET schema_version = 16 WHERE id = 1")),_<17){e.exec("PRAGMA foreign_keys = OFF"),e.exec("DROP TABLE IF EXISTS plugins"),e.exec("DROP TABLE IF EXISTS role_plugins"),e.exec("DROP TABLE IF EXISTS marketplaces"),e.exec("DROP INDEX IF EXISTS idx_plugins_source"),e.exec("DROP INDEX IF EXISTS idx_plugins_enabled");try{let T=e.prepare("SELECT id, additional_directories FROM roles WHERE additional_directories IS NOT NULL").all();for(let t of T)try{let i=JSON.parse(t.additional_directories);if(i.length>0&&typeof i[0]=="object"&&i[0]!==null&&"path"in i[0])continue;let N=i.map(n=>typeof n=="string"?{path:n}:n);e.prepare("UPDATE roles SET additional_directories = ? WHERE id = ?").run(JSON.stringify(N),t.id)}catch{}}catch{}let E=e.prepare("PRAGMA table_info(tasks)").all();E.some(T=>T.name==="deliver_to")||e.exec("ALTER TABLE tasks ADD COLUMN deliver_to TEXT"),E.some(T=>T.name==="report_to")||e.exec("ALTER TABLE tasks ADD COLUMN report_to TEXT");let s=e.prepare("PRAGMA table_info(strategies)").all();s.some(T=>T.name==="role")&&!s.some(T=>T.name==="role_id")&&(e.exec("ALTER TABLE strategies RENAME COLUMN role TO role_id"),e.exec("DROP INDEX IF EXISTS idx_strategies_role_task_type"),e.exec("DROP INDEX IF EXISTS idx_strategies_role"),e.exec("CREATE UNIQUE INDEX IF NOT EXISTS idx_strategies_role_task_type ON strategies(role_id, task_type, name)"),e.exec("CREATE INDEX IF NOT EXISTS idx_strategies_role ON strategies(role_id)")),e.exec("UPDATE server_state SET schema_version = 17 WHERE id = 1"),e.exec("PRAGMA foreign_keys = ON")}if(_<18){let E=e.prepare("PRAGMA table_info(tasks)").all();E.some(T=>T.name==="deliver_to")||e.exec("ALTER TABLE tasks ADD COLUMN deliver_to TEXT"),E.some(T=>T.name==="report_to")||e.exec("ALTER TABLE tasks ADD COLUMN report_to TEXT");let s=e.prepare("PRAGMA table_info(strategies)").all();s.some(T=>T.name==="role")&&!s.some(T=>T.name==="role_id")&&(e.exec("ALTER TABLE strategies RENAME COLUMN role TO role_id"),e.exec("DROP INDEX IF EXISTS idx_strategies_role_task_type"),e.exec("DROP INDEX IF EXISTS idx_strategies_role"),e.exec("CREATE UNIQUE INDEX IF NOT EXISTS idx_strategies_role_task_type ON strategies(role_id, task_type, name)"),e.exec("CREATE INDEX IF NOT EXISTS idx_strategies_role ON strategies(role_id)")),e.exec("UPDATE server_state SET schema_version = 18 WHERE id = 1")}e.prepare("PRAGMA table_info(delivery_log)").all().some(E=>E.name==="source")||(e.exec(`
570
+ `),e.exec("UPDATE server_state SET schema_version = 10 WHERE id = 1"),e.exec("PRAGMA foreign_keys = ON")}if(o<11){try{e.exec("ALTER TABLE task_templates RENAME COLUMN skill_preference TO role_preference")}catch(E){let s=e.prepare("PRAGMA table_info(task_templates)").all(),T=s.some(i=>i.name==="role_preference"),t=s.some(i=>i.name==="skill_preference");if(!T&&t)throw E}e.exec("UPDATE server_state SET schema_version = 11 WHERE id = 1")}if(o<12&&(e.prepare("PRAGMA table_info(server_state)").all().some(s=>s.name==="tools_fingerprint")||e.exec("ALTER TABLE server_state ADD COLUMN tools_fingerprint TEXT"),e.exec("UPDATE server_state SET schema_version = 12 WHERE id = 1")),o<13&&(e.prepare("PRAGMA table_info(roles)").all().some(s=>s.name==="additional_directories")||e.exec("ALTER TABLE roles ADD COLUMN additional_directories TEXT"),e.exec("UPDATE server_state SET schema_version = 13 WHERE id = 1")),o<14){let E=e.prepare("PRAGMA table_info(roles)").all();E.some(t=>t.name==="allowed_channels")||e.exec("ALTER TABLE roles ADD COLUMN allowed_channels TEXT"),E.some(t=>t.name==="mcp_servers")||e.exec("ALTER TABLE roles ADD COLUMN mcp_servers TEXT");let s=e.prepare("PRAGMA table_info(tasks)").all();s.some(t=>t.name==="deliver_to")||e.exec("ALTER TABLE tasks ADD COLUMN deliver_to TEXT"),s.some(t=>t.name==="report_to")||e.exec("ALTER TABLE tasks ADD COLUMN report_to TEXT"),e.prepare("PRAGMA table_info(goals)").all().some(t=>t.name==="deliver_to")||e.exec("ALTER TABLE goals ADD COLUMN deliver_to TEXT"),e.exec("UPDATE server_state SET schema_version = 14 WHERE id = 1")}if(o<15&&(e.prepare("PRAGMA table_info(roles)").all().some(s=>s.name==="inherit_user_settings")||e.exec("ALTER TABLE roles ADD COLUMN inherit_user_settings INTEGER DEFAULT 0"),e.exec("UPDATE server_state SET schema_version = 15 WHERE id = 1")),o<16&&(e.prepare("PRAGMA table_info(task_templates)").all().some(s=>s.name==="deliver_to")||e.exec("ALTER TABLE task_templates ADD COLUMN deliver_to TEXT"),e.exec("UPDATE server_state SET schema_version = 16 WHERE id = 1")),o<17){e.exec("PRAGMA foreign_keys = OFF"),e.exec("DROP TABLE IF EXISTS plugins"),e.exec("DROP TABLE IF EXISTS role_plugins"),e.exec("DROP TABLE IF EXISTS marketplaces"),e.exec("DROP INDEX IF EXISTS idx_plugins_source"),e.exec("DROP INDEX IF EXISTS idx_plugins_enabled");try{let T=e.prepare("SELECT id, additional_directories FROM roles WHERE additional_directories IS NOT NULL").all();for(let t of T)try{let i=JSON.parse(t.additional_directories);if(i.length>0&&typeof i[0]=="object"&&i[0]!==null&&"path"in i[0])continue;let n=i.map(_=>typeof _=="string"?{path:_}:_);e.prepare("UPDATE roles SET additional_directories = ? WHERE id = ?").run(JSON.stringify(n),t.id)}catch{}}catch{}let E=e.prepare("PRAGMA table_info(tasks)").all();E.some(T=>T.name==="deliver_to")||e.exec("ALTER TABLE tasks ADD COLUMN deliver_to TEXT"),E.some(T=>T.name==="report_to")||e.exec("ALTER TABLE tasks ADD COLUMN report_to TEXT");let s=e.prepare("PRAGMA table_info(strategies)").all();s.some(T=>T.name==="role")&&!s.some(T=>T.name==="role_id")&&(e.exec("ALTER TABLE strategies RENAME COLUMN role TO role_id"),e.exec("DROP INDEX IF EXISTS idx_strategies_role_task_type"),e.exec("DROP INDEX IF EXISTS idx_strategies_role"),e.exec("CREATE UNIQUE INDEX IF NOT EXISTS idx_strategies_role_task_type ON strategies(role_id, task_type, name)"),e.exec("CREATE INDEX IF NOT EXISTS idx_strategies_role ON strategies(role_id)")),e.exec("UPDATE server_state SET schema_version = 17 WHERE id = 1"),e.exec("PRAGMA foreign_keys = ON")}if(o<18){let E=e.prepare("PRAGMA table_info(tasks)").all();E.some(T=>T.name==="deliver_to")||e.exec("ALTER TABLE tasks ADD COLUMN deliver_to TEXT"),E.some(T=>T.name==="report_to")||e.exec("ALTER TABLE tasks ADD COLUMN report_to TEXT");let s=e.prepare("PRAGMA table_info(strategies)").all();s.some(T=>T.name==="role")&&!s.some(T=>T.name==="role_id")&&(e.exec("ALTER TABLE strategies RENAME COLUMN role TO role_id"),e.exec("DROP INDEX IF EXISTS idx_strategies_role_task_type"),e.exec("DROP INDEX IF EXISTS idx_strategies_role"),e.exec("CREATE UNIQUE INDEX IF NOT EXISTS idx_strategies_role_task_type ON strategies(role_id, task_type, name)"),e.exec("CREATE INDEX IF NOT EXISTS idx_strategies_role ON strategies(role_id)")),e.exec("UPDATE server_state SET schema_version = 18 WHERE id = 1")}e.prepare("PRAGMA table_info(delivery_log)").all().some(E=>E.name==="source")||(e.exec(`
571
571
  CREATE TABLE IF NOT EXISTS delivery_log_new (
572
572
  id TEXT PRIMARY KEY,
573
573
  rule_id TEXT REFERENCES delivery_rules(id),
@@ -584,7 +584,7 @@ import{e as A,h as O}from"./chunk-WBAPIPST.js";import{c as R,h as X}from"./chunk
584
584
  message_type TEXT
585
585
  )
586
586
  `),e.exec(`INSERT INTO delivery_log_new (id, rule_id, task_id, status, target, content, attempts, error, created_at, delivered_at, expires_at)
587
- SELECT id, rule_id, task_id, status, target, content, attempts, error, created_at, delivered_at, expires_at FROM delivery_log`),e.exec("DROP TABLE delivery_log"),e.exec("ALTER TABLE delivery_log_new RENAME TO delivery_log"),e.exec("CREATE INDEX IF NOT EXISTS idx_delivery_log_rule ON delivery_log(rule_id)"),e.exec("CREATE INDEX IF NOT EXISTS idx_delivery_log_task ON delivery_log(task_id)")),(e.prepare("SELECT schema_version FROM server_state WHERE id = 1").get()?.schema_version??0)<20&&(e.prepare("PRAGMA table_info(goals)").all().some(T=>T.name==="report_to")||e.exec("ALTER TABLE goals ADD COLUMN report_to TEXT"),e.prepare("PRAGMA table_info(task_templates)").all().some(T=>T.name==="report_to")||e.exec("ALTER TABLE task_templates ADD COLUMN report_to TEXT"),e.exec("UPDATE goals SET report_to = notify_targets WHERE notify_targets IS NOT NULL"),e.exec("UPDATE task_templates SET report_to = notify_targets WHERE notify_targets IS NOT NULL"),e.exec("UPDATE server_state SET schema_version = 20 WHERE id = 1")),e.prepare("PRAGMA table_info(config)").all().some(E=>E.name==="updated_at")||(e.exec("ALTER TABLE config ADD COLUMN updated_at INTEGER NOT NULL DEFAULT 0"),e.exec("UPDATE server_state SET schema_version = 21 WHERE id = 1"));let c=e.prepare("PRAGMA table_info(memories)").all();c.some(E=>E.name==="tier")||(e.exec("ALTER TABLE memories ADD COLUMN tier TEXT NOT NULL DEFAULT 'episodic'"),e.exec("CREATE INDEX IF NOT EXISTS idx_memories_tier ON memories(tier)")),c.some(E=>E.name==="superseded_by")||(e.exec("ALTER TABLE memories ADD COLUMN superseded_by TEXT"),e.exec("CREATE INDEX IF NOT EXISTS idx_memories_superseded ON memories(superseded_by)"));let L=e.prepare("PRAGMA table_info(memories)").all();L.some(E=>E.name==="tier")&&L.some(E=>E.name==="superseded_by")&&(e.prepare("SELECT schema_version FROM server_state WHERE id = 1").get()?.schema_version??0)<22&&e.exec("UPDATE server_state SET schema_version = 22 WHERE id = 1");{let E=e.prepare("PRAGMA table_info(roles)").all();E.some(T=>T.name==="permission_mode")||e.exec("ALTER TABLE roles ADD COLUMN permission_mode TEXT DEFAULT NULL"),E.some(T=>T.name==="allowed_bash_patterns")||e.exec("ALTER TABLE roles ADD COLUMN allowed_bash_patterns TEXT DEFAULT NULL"),E.some(T=>T.name==="denied_bash_patterns")||e.exec("ALTER TABLE roles ADD COLUMN denied_bash_patterns TEXT DEFAULT NULL"),(e.prepare("SELECT schema_version FROM server_state WHERE id = 1").get()?.schema_version??0)<23&&e.exec("UPDATE server_state SET schema_version = 23 WHERE id = 1")}if(e.prepare("PRAGMA table_info(roles)").all().some(T=>T.name==="env_vars")||e.prepare("ALTER TABLE roles ADD COLUMN env_vars TEXT DEFAULT NULL").run(),(e.prepare("SELECT schema_version FROM server_state WHERE id = 1").get()?.schema_version??0)<24&&e.prepare("UPDATE server_state SET schema_version = 24 WHERE id = 1").run(),_<25&&(e.exec(`
587
+ SELECT id, rule_id, task_id, status, target, content, attempts, error, created_at, delivered_at, expires_at FROM delivery_log`),e.exec("DROP TABLE delivery_log"),e.exec("ALTER TABLE delivery_log_new RENAME TO delivery_log"),e.exec("CREATE INDEX IF NOT EXISTS idx_delivery_log_rule ON delivery_log(rule_id)"),e.exec("CREATE INDEX IF NOT EXISTS idx_delivery_log_task ON delivery_log(task_id)")),(e.prepare("SELECT schema_version FROM server_state WHERE id = 1").get()?.schema_version??0)<20&&(e.prepare("PRAGMA table_info(goals)").all().some(T=>T.name==="report_to")||e.exec("ALTER TABLE goals ADD COLUMN report_to TEXT"),e.prepare("PRAGMA table_info(task_templates)").all().some(T=>T.name==="report_to")||e.exec("ALTER TABLE task_templates ADD COLUMN report_to TEXT"),e.exec("UPDATE goals SET report_to = notify_targets WHERE notify_targets IS NOT NULL"),e.exec("UPDATE task_templates SET report_to = notify_targets WHERE notify_targets IS NOT NULL"),e.exec("UPDATE server_state SET schema_version = 20 WHERE id = 1")),e.prepare("PRAGMA table_info(config)").all().some(E=>E.name==="updated_at")||(e.exec("ALTER TABLE config ADD COLUMN updated_at INTEGER NOT NULL DEFAULT 0"),e.exec("UPDATE server_state SET schema_version = 21 WHERE id = 1"));let L=e.prepare("PRAGMA table_info(memories)").all();L.some(E=>E.name==="tier")||(e.exec("ALTER TABLE memories ADD COLUMN tier TEXT NOT NULL DEFAULT 'episodic'"),e.exec("CREATE INDEX IF NOT EXISTS idx_memories_tier ON memories(tier)")),L.some(E=>E.name==="superseded_by")||(e.exec("ALTER TABLE memories ADD COLUMN superseded_by TEXT"),e.exec("CREATE INDEX IF NOT EXISTS idx_memories_superseded ON memories(superseded_by)"));let d=e.prepare("PRAGMA table_info(memories)").all();d.some(E=>E.name==="tier")&&d.some(E=>E.name==="superseded_by")&&(e.prepare("SELECT schema_version FROM server_state WHERE id = 1").get()?.schema_version??0)<22&&e.exec("UPDATE server_state SET schema_version = 22 WHERE id = 1");{let E=e.prepare("PRAGMA table_info(roles)").all();E.some(T=>T.name==="permission_mode")||e.exec("ALTER TABLE roles ADD COLUMN permission_mode TEXT DEFAULT NULL"),E.some(T=>T.name==="allowed_bash_patterns")||e.exec("ALTER TABLE roles ADD COLUMN allowed_bash_patterns TEXT DEFAULT NULL"),E.some(T=>T.name==="denied_bash_patterns")||e.exec("ALTER TABLE roles ADD COLUMN denied_bash_patterns TEXT DEFAULT NULL"),(e.prepare("SELECT schema_version FROM server_state WHERE id = 1").get()?.schema_version??0)<23&&e.exec("UPDATE server_state SET schema_version = 23 WHERE id = 1")}if(e.prepare("PRAGMA table_info(roles)").all().some(T=>T.name==="env_vars")||e.prepare("ALTER TABLE roles ADD COLUMN env_vars TEXT DEFAULT NULL").run(),(e.prepare("SELECT schema_version FROM server_state WHERE id = 1").get()?.schema_version??0)<24&&e.prepare("UPDATE server_state SET schema_version = 24 WHERE id = 1").run(),o<25&&(e.exec(`
588
588
  CREATE TABLE IF NOT EXISTS workflow_executions (
589
589
  id TEXT PRIMARY KEY,
590
590
  template_id TEXT NOT NULL,
@@ -595,7 +595,7 @@ import{e as A,h as O}from"./chunk-WBAPIPST.js";import{c as R,h as X}from"./chunk
595
595
  error TEXT,
596
596
  FOREIGN KEY (template_id) REFERENCES task_templates(id)
597
597
  )
598
- `),e.exec("UPDATE server_state SET schema_version = 25 WHERE id = 1")),_<26){let E=`
598
+ `),e.exec("UPDATE server_state SET schema_version = 25 WHERE id = 1")),o<26){let E=`
599
599
  CREATE TABLE IF NOT EXISTS workflow_artifacts (
600
600
  id TEXT PRIMARY KEY,
601
601
  execution_id TEXT NOT NULL,
@@ -633,4 +633,23 @@ import{e as A,h as O}from"./chunk-WBAPIPST.js";import{c as R,h as X}from"./chunk
633
633
  ON artifact_access_log (execution_id, timestamp);
634
634
  CREATE INDEX IF NOT EXISTS idx_artifact_access_log_role
635
635
  ON artifact_access_log (role_id, timestamp);
636
- `;e.exec(E),e.exec(s),e.prepare("PRAGMA table_info(tasks)").all().some(t=>t.name==="step_id")||e.prepare("ALTER TABLE tasks ADD COLUMN step_id TEXT").run(),e.exec("UPDATE server_state SET schema_version = 26 WHERE id = 1")}e.prepare("PRAGMA table_info(roles)").all().some(T=>T.name==="os_capabilities")||e.prepare("ALTER TABLE roles ADD COLUMN os_capabilities TEXT DEFAULT NULL").run(),(e.prepare("SELECT schema_version FROM server_state WHERE id = 1").get()?.schema_version??0)<27&&e.prepare("UPDATE server_state SET schema_version = 27 WHERE id = 1").run();{let E=e.prepare("PRAGMA table_info(manager_decisions)").all();E.some(T=>T.name==="requirements_json")||e.prepare("ALTER TABLE manager_decisions ADD COLUMN requirements_json TEXT").run(),E.some(T=>T.name==="fit_score")||e.prepare("ALTER TABLE manager_decisions ADD COLUMN fit_score REAL").run(),E.some(T=>T.name==="candidates_json")||e.prepare("ALTER TABLE manager_decisions ADD COLUMN candidates_json TEXT").run(),E.some(T=>T.name==="tie_break_reason")||e.prepare("ALTER TABLE manager_decisions ADD COLUMN tie_break_reason TEXT").run(),(e.prepare("SELECT schema_version FROM server_state WHERE id = 1").get()?.schema_version??0)<28&&e.prepare("UPDATE server_state SET schema_version = 28 WHERE id = 1").run()}{let E=[[/\brm -rf\b/,["rm -rf *"]],[/^git push/,["git push*"]],[/^git reset/,["git reset*"]],[/\bcurl.*POST\b/i,["curl * -X POST*","curl * --request POST*"]]],s=e.prepare("SELECT key, value FROM config WHERE key = 'defaults.approvalRequired'").all();for(let T of s)try{let t=JSON.parse(T.value),i=[];for(let n of t){let a=!1;for(let[d,r]of E)if(d.test(n)){i.push(...r),a=!0,I.info({from:n,to:r},"Config: migrated approvalRequired pattern from regex to glob");break}a||(/[.+?^${}()|[\]\\]/.test(n)&&I.warn({pattern:n},"Config: approvalRequired pattern contains regex metacharacters that won't work with glob matching; update to glob syntax (use * for wildcards)"),i.push(n))}let N=[...new Set(i)];e.prepare("UPDATE config SET value = ?, updated_at = ? WHERE key = ?").run(JSON.stringify(N),Date.now(),T.key)}catch{}}}function K(){if(o)return o;let e=process.env.ADAM_DB_PATH||A,l=g(e);return S(l)||u(l,{recursive:!0}),o=new p(e),o.pragma("journal_mode = WAL"),o.pragma("foreign_keys = ON"),o.pragma("trusted_schema = ON"),D(o),o}function W(){o&&(o.close(),o=null)}var I,o,C=m(()=>{O();X();I=R("store"),o=null});export{D as a,K as b,W as c,C as d};
636
+ `;e.exec(E),e.exec(s),e.prepare("PRAGMA table_info(tasks)").all().some(t=>t.name==="step_id")||e.prepare("ALTER TABLE tasks ADD COLUMN step_id TEXT").run(),e.exec("UPDATE server_state SET schema_version = 26 WHERE id = 1")}e.prepare("PRAGMA table_info(roles)").all().some(T=>T.name==="os_capabilities")||e.prepare("ALTER TABLE roles ADD COLUMN os_capabilities TEXT DEFAULT NULL").run(),(e.prepare("SELECT schema_version FROM server_state WHERE id = 1").get()?.schema_version??0)<27&&e.prepare("UPDATE server_state SET schema_version = 27 WHERE id = 1").run();{let E=e.prepare("PRAGMA table_info(manager_decisions)").all();E.some(T=>T.name==="requirements_json")||e.prepare("ALTER TABLE manager_decisions ADD COLUMN requirements_json TEXT").run(),E.some(T=>T.name==="fit_score")||e.prepare("ALTER TABLE manager_decisions ADD COLUMN fit_score REAL").run(),E.some(T=>T.name==="candidates_json")||e.prepare("ALTER TABLE manager_decisions ADD COLUMN candidates_json TEXT").run(),E.some(T=>T.name==="tie_break_reason")||e.prepare("ALTER TABLE manager_decisions ADD COLUMN tie_break_reason TEXT").run(),(e.prepare("SELECT schema_version FROM server_state WHERE id = 1").get()?.schema_version??0)<28&&e.prepare("UPDATE server_state SET schema_version = 28 WHERE id = 1").run()}{let E=[[/\brm -rf\b/,["rm -rf *"]],[/^git push/,["git push*"]],[/^git reset/,["git reset*"]],[/\bcurl.*POST\b/i,["curl * -X POST*","curl * --request POST*"]]],s=e.prepare("SELECT key, value FROM config WHERE key = 'defaults.approvalRequired'").all();for(let T of s)try{let t=JSON.parse(T.value),i=[];for(let _ of t){let l=!1;for(let[A,r]of E)if(A.test(_)){i.push(...r),l=!0,a.info({from:_,to:r},"Config: migrated approvalRequired pattern from regex to glob");break}l||(/[.+?^${}()|[\]\\]/.test(_)&&a.warn({pattern:_},"Config: approvalRequired pattern contains regex metacharacters that won't work with glob matching; update to glob syntax (use * for wildcards)"),i.push(_))}let n=[...new Set(i)];e.prepare("UPDATE config SET value = ?, updated_at = ? WHERE key = ?").run(JSON.stringify(n),Date.now(),T.key)}catch{}}if((e.prepare("SELECT schema_version FROM server_state WHERE id = 1").get()?.schema_version??0)<31){let s=e.prepare("SELECT count(*) AS n FROM task_templates WHERE trigger_type IN ('event', 'task_complete')").get();s.n>0&&a.info({legacyCount:s.n},"normalizing legacy template trigger types"),e.prepare("UPDATE task_templates SET trigger_type='workflow_complete' WHERE trigger_type='event' AND trigger_event LIKE 'workflow_complete:%'").run(),e.prepare("UPDATE task_templates SET trigger_type='template_complete' WHERE trigger_type='event'").run(),e.prepare("UPDATE task_templates SET trigger_type='manual' WHERE trigger_type='task_complete'").run();let T=e.prepare("SELECT count(*) AS n FROM task_templates WHERE trigger_type IN ('event', 'task_complete')").get();T.n>0&&a.warn({orphan:T.n},"migration left orphan legacy trigger_type rows; manual inspection required"),e.prepare("UPDATE server_state SET schema_version = 31 WHERE id = 1").run()}(e.prepare("SELECT schema_version FROM server_state WHERE id = 1").get()?.schema_version??0)<32&&(e.exec(`
637
+ CREATE TABLE IF NOT EXISTS event_defs (
638
+ id TEXT PRIMARY KEY, name TEXT NOT NULL, source_type TEXT NOT NULL,
639
+ source_config TEXT NOT NULL, enabled INTEGER NOT NULL DEFAULT 1,
640
+ description TEXT, created_at INTEGER NOT NULL, updated_at INTEGER NOT NULL
641
+ );
642
+ CREATE INDEX IF NOT EXISTS idx_event_defs_source_type ON event_defs(source_type, enabled);
643
+ CREATE UNIQUE INDEX IF NOT EXISTS idx_event_defs_name ON event_defs(name);
644
+
645
+ CREATE TABLE IF NOT EXISTS events (
646
+ id TEXT PRIMARY KEY, event_def_id TEXT,
647
+ occurred_at TEXT NOT NULL, ingested_at TEXT NOT NULL, user_day TEXT,
648
+ source TEXT NOT NULL, type TEXT NOT NULL, payload TEXT NOT NULL,
649
+ confidence REAL NOT NULL DEFAULT 1.0, dedup_key TEXT NOT NULL,
650
+ related_entities TEXT, trust_level TEXT NOT NULL DEFAULT 'trusted'
651
+ );
652
+ CREATE UNIQUE INDEX IF NOT EXISTS idx_events_dedup ON events(source, dedup_key);
653
+ CREATE INDEX IF NOT EXISTS idx_events_type ON events(type);
654
+ CREATE INDEX IF NOT EXISTS idx_events_def_id ON events(event_def_id, occurred_at);
655
+ `),e.prepare("UPDATE server_state SET schema_version = 32 WHERE id = 1").run()),(e.prepare("SELECT schema_version FROM server_state WHERE id = 1").get()?.schema_version??0)<33&&(e.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name='workflow_executions'").get()&&(e.prepare("PRAGMA table_info(workflow_executions)").all().some(i=>i.name==="event_id")||e.prepare("ALTER TABLE workflow_executions ADD COLUMN event_id TEXT").run(),e.prepare("CREATE INDEX IF NOT EXISTS idx_workflow_executions_event_id ON workflow_executions(event_id)").run()),e.prepare("UPDATE server_state SET schema_version = 33 WHERE id = 1").run());try{let E=e.prepare("SELECT id, name, steps, role_preference FROM task_templates WHERE enabled = 1").all(),s=0;for(let T of E){if(T.role_preference)continue;let t;try{t=JSON.parse(T.steps)}catch{continue}if(!Array.isArray(t))continue;let i=!1;for(let n of t){let _=typeof n.roleId=="string"&&n.roleId.length>0,l=n.autoSelectRole===!0;!_&&!l&&(n.autoSelectRole=!0,n.requirements===void 0&&(n.requirements={}),i=!0)}i&&(e.prepare("UPDATE task_templates SET steps = ?, updated_at = ? WHERE id = ?").run(JSON.stringify(t),Date.now(),T.id),s+=1,console.info(`[db migration] template auto-repaired: id=${T.id} name=${T.name}`))}s>0&&console.info(`[db migration] auto-repaired ${s} enabled template(s) with missing role config`)}catch(E){console.error("[db migration] template auto-repair failed:",E)}}function K(){if(N)return N;let e=process.env.ADAM_DB_PATH||R,c=g(e);return S(c)||u(c,{recursive:!0}),N=new X(e),N.pragma("journal_mode = WAL"),N.pragma("foreign_keys = ON"),N.pragma("trusted_schema = ON"),U(N),N}function W(){N&&(N.close(),N=null)}var a,N,D=m(()=>{p();O();a=I("store"),N=null});export{U as a,K as b,W as c,D as d};
@@ -1,3 +1,3 @@
1
- import{f as S}from"./chunk-BR2JY5X2.js";import{b as y}from"./chunk-YVS565QY.js";import{b as g}from"./chunk-ISZJV72D.js";import{b as C}from"./chunk-XL46AGRZ.js";import{b as R}from"./chunk-23VZKIB6.js";import{b as v}from"./chunk-2DLVAKH7.js";import{e as m}from"./chunk-HDP7A4XY.js";import{a as h}from"./chunk-L7JP7DUO.js";import{a as k,b as P,c as o,d as f,e as T,f as x,g as E}from"./chunk-QVKI7H7W.js";import{c as w,h as _}from"./chunk-INNDBLZE.js";_();import{v4 as M}from"uuid";var l=w("admin"),I=new Map,u=null,p=null,c=null,D=class{constructor(){h.on("task_status_change",e=>{(e.newStatus==="completed"||e.newStatus==="failed")&&this.handleTaskStatusChange(e.taskId,e.newStatus).catch(n=>{l.error({taskId:e.taskId,error:n},"Delivery processing failed")})}),h.on("plan_approval_request",e=>{this.handlePlanApprovalRequest(e.taskId,e.planId,e.plan).catch(n=>{l.error({taskId:e.taskId,error:n},"Delivery processing failed (plan_approval)")})}),l.info("DeliveryEngine initialized")}async handlePlanApprovalRequest(e,n,r){let t=g(e),i=this.getSourceChannelForTask(e);if(i){let d=y(r),{sendApprovalToChannel:b}=await import("./approval-handler-ORD4MUVM.js");await b(i.channelId,i.chatId,n,e,d)}let a=y(r)+`
1
+ import{f as S}from"./chunk-2H7UOW4P.js";import{b as v}from"./chunk-FXQAUQTI.js";import{b as y}from"./chunk-4C5ITATX.js";import{e as m}from"./chunk-GMMWA5EG.js";import{b as g}from"./chunk-I7ZZKPHE.js";import{b as C}from"./chunk-VVSZZK5T.js";import{b as R}from"./chunk-YXYIA24D.js";import{a as h}from"./chunk-L7JP7DUO.js";import{a as k,b as P,c as o,d as f,e as T,f as x,g as E}from"./chunk-RLJYEEQC.js";import{c as w,h as _}from"./chunk-MRTJFYPR.js";_();import{v4 as M}from"uuid";var l=w("admin"),I=new Map,u=null,p=null,c=null,D=class{constructor(){h.on("task_status_change",e=>{(e.newStatus==="completed"||e.newStatus==="failed")&&this.handleTaskStatusChange(e.taskId,e.newStatus).catch(n=>{l.error({taskId:e.taskId,error:n},"Delivery processing failed")})}),h.on("plan_approval_request",e=>{this.handlePlanApprovalRequest(e.taskId,e.planId,e.plan).catch(n=>{l.error({taskId:e.taskId,error:n},"Delivery processing failed (plan_approval)")})}),l.info("DeliveryEngine initialized")}async handlePlanApprovalRequest(e,n,r){let t=g(e),i=this.getSourceChannelForTask(e);if(i){let d=y(r),{sendApprovalToChannel:b}=await import("./approval-handler-HQO62WK2.js");await b(i.channelId,i.chatId,n,e,d)}let a=y(r)+`
2
2
 
3
3
  Task: ${e}`;await this.matchAndDeliver("plan_approval_request",{templateId:t?.templateId,roleId:t?.roleId,prompt:t?.prompt,taskStatus:"pending"},a,e)}getSourceChannelForTask(e){try{let n=m(e);if(!n)return null;let r=v(n.sessionId);return!r||r.source.type!=="channel"||!r.source.channelId||!r.source.chatId?null:{channelId:r.source.channelId,chatId:r.source.chatId}}catch{return null}}async handleTaskStatusChange(e,n){let r=g(e);if(!r)return;let t={templateId:r.templateId,roleId:r.roleId,prompt:r.prompt,taskStatus:n},i=n==="completed"?"task_complete":"task_error",a=r.result??r.error??"";await this.matchAndDeliver(i,t,a,e)}async matchAndDeliver(e,n,r,t){let i=S(e,n);if(i.length!==0){l.debug({eventType:e,ruleCount:i.length,taskId:t},"Matched delivery rules");for(let a of i){if(!this.checkRateLimit(a)){l.warn({ruleId:a.id,maxPerMinute:a.maxPerMinute},"Delivery rate limit exceeded, skipping");continue}if(a.skipOriginChannel&&a.target.type==="channel"&&t&&this.isOriginChannel(t,a.target))continue;let d={id:M(),ruleId:a.id,taskId:t,status:"pending",target:a.target,content:r,attempts:0,createdAt:Date.now(),expiresAt:Date.now()+k,source:"rule"};P(d),await this.attemptDelivery(d,a)}}}async attemptDeliveryPublic(e,n){return this.attemptDelivery(e,n)}async attemptDelivery(e,n){let r=C();try{if(e.target.type==="channel"){let t=e.target.chatId;!t&&e.target.channelId&&(t=R(e.target.channelId)?.config?.userId);let i=await r.send({taskId:e.taskId,channelId:e.target.channelId,chatId:t,content:e.content,messageType:"deliver"});i.success?(f(e.id),l.info({entryId:e.id,ruleId:n.id,targetType:"channel"},"Delivery successful")):o(e.id,"failed",i.error??"Gateway returned failure")}else if(e.target.type==="webhook"){let t=await r.send({taskId:e.taskId,webhookUrl:e.target.webhookUrl,content:e.content,messageType:"deliver"});t.success?(f(e.id),l.info({entryId:e.id,ruleId:n.id,targetType:"webhook"},"Webhook delivery successful")):o(e.id,"failed",t.error??"Gateway returned failure")}}catch(t){let i=t instanceof Error?t.message:String(t);o(e.id,"failed",i),l.warn({entryId:e.id,error:i},"Delivery attempt failed")}}checkRateLimit(e){let n=Date.now(),r=6e4,t=I.get(e.id);t||(t=[],I.set(e.id,t));let i=n-r;for(;t.length>0&&t[0]<i;)t.shift();return t.length>=e.maxPerMinute?!1:(t.push(n),!0)}isOriginChannel(e,n){try{if(n.type!=="channel"||!n.channelId)return!1;let r=m(e);if(!r)return!1;let t=v(r.sessionId);return t?t.source.type==="channel"&&t.source.channelId===n.channelId&&(!n.chatId||t.source.chatId===n.chatId):!1}catch{return!1}}async retryPending(){let e=T("rule",50),n=x("rule",50),r=[...e,...n];if(r.length!==0){l.debug({count:r.length},"Retrying pending/failed deliveries");for(let t of r){if(t.attempts>=3){o(t.id,"failed","Max retries (3) exceeded");continue}let i={id:t.ruleId??"retry-synthetic",eventType:"*",matchCriteria:{},target:t.target,maxPerMinute:5,skipOriginChannel:!0,enabled:!0,createdAt:0};await this.attemptDelivery(t,i)}}}};function $(){return c}function H(){c||(c=new D,u=setInterval(()=>{c?.retryPending().catch(s=>{l.error({error:s},"Delivery retry scan failed")})},6e4),p=setInterval(()=>{try{let s=E();s>0&&l.info({cleaned:s},"Expired delivery log entries cleaned up")}catch(s){l.error({error:s},"Delivery cleanup failed")}},36e5),l.info("DeliveryEngine started with retry (60s) and cleanup (1h) timers"))}function J(){u&&(clearInterval(u),u=null),p&&(clearInterval(p),p=null),c=null,I.clear(),l.info("DeliveryEngine stopped")}export{D as a,$ as b,H as c,J as d};