adam-agent-server 1.16.0 → 1.17.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.
- package/dist/App-SIQUVFJY.js +14 -0
- package/dist/approval-handler-FONN2EGB.js +1 -0
- package/dist/{artifacts-S2KD6W76.js → artifacts-DMY2MI2F.js} +1 -1
- package/dist/audit-diagnostics-D4M4SA5O.js +1 -0
- package/dist/audit-manager-YEOJRE6K.js +1 -0
- package/dist/bree-engine-RGTBKKFE.js +1 -0
- package/dist/channels-VYNJFXDD.js +1 -0
- package/dist/channels-WFU4CVGW.js +1 -0
- package/dist/chat-tool-calls-WQGFYTUV.js +1 -0
- package/dist/{chunk-TCBGUVVU.js → chunk-2RBYM3X7.js} +1 -1
- package/dist/chunk-2V2H5PG5.js +182 -0
- package/dist/{chunk-TJTH7LHX.js → chunk-2WPUKCDA.js} +1 -1
- package/dist/{chunk-6Y2DN2UH.js → chunk-32D5GWJD.js} +1 -1
- package/dist/chunk-3GK65T2V.js +6 -0
- package/dist/chunk-3R7VGMAK.js +6 -0
- package/dist/{chunk-OXGWWSKT.js → chunk-3RITIMKB.js} +1 -1
- package/dist/{chunk-3UR2PN5N.js → chunk-3VUEB67V.js} +1 -1
- package/dist/{chunk-P5Q2UINT.js → chunk-4G2OZPP5.js} +1 -1
- package/dist/{chunk-NUJSTEV4.js → chunk-4N5G7ND2.js} +1 -1
- package/dist/{chunk-YNS5LQX5.js → chunk-4WJ2VSEJ.js} +1 -1
- package/dist/{chunk-TLMG5W3L.js → chunk-5G64P4KE.js} +1 -1
- package/dist/{chunk-245WE5AF.js → chunk-5M6IGE5G.js} +1 -1
- package/dist/chunk-5PELJRUQ.js +1 -0
- package/dist/{chunk-I44JKROJ.js → chunk-5WBFQMJL.js} +1 -1
- package/dist/chunk-725BGAO2.js +143 -0
- package/dist/{chunk-OGY42NUN.js → chunk-73GP6K5S.js} +1 -1
- package/dist/{chunk-HC34HJFF.js → chunk-7IXYCDUF.js} +1 -1
- package/dist/{chunk-H4MMEULK.js → chunk-A2S67EQG.js} +2 -2
- package/dist/{chunk-HXDS4NWI.js → chunk-A57SY3E4.js} +1 -1
- package/dist/{chunk-N2OLEUAQ.js → chunk-BRUHXRKK.js} +1 -1
- package/dist/{chunk-XYZVMTNN.js → chunk-CFPXWGFD.js} +1 -1
- package/dist/{chunk-VVQ532U2.js → chunk-D5PAJ3CB.js} +1 -1
- package/dist/{chunk-LQVBWVLE.js → chunk-DCTNMUQ5.js} +1 -1
- package/dist/{chunk-LVHLUAZW.js → chunk-ED2JAMEN.js} +8 -7
- package/dist/{chunk-BLCNUT53.js → chunk-EZLBMUQD.js} +1 -1
- package/dist/{chunk-ASPPM7TQ.js → chunk-FJ3DUJXO.js} +1 -1
- package/dist/chunk-FMJVKJJE.js +1 -0
- package/dist/{chunk-NLTYJUQG.js → chunk-HL373H4P.js} +1 -1
- package/dist/chunk-K3HWZBE5.js +10 -0
- package/dist/{chunk-R24YRJRG.js → chunk-MQTK4Q6M.js} +1 -1
- package/dist/chunk-NV5ZXKKF.js +61 -0
- package/dist/chunk-OH6VBBDV.js +1 -0
- package/dist/{chunk-SCUPWMI5.js → chunk-OII5SDMS.js} +1 -1
- package/dist/{chunk-MTQI6B7T.js → chunk-P76VP2UH.js} +3 -3
- package/dist/{chunk-AQAHVNNG.js → chunk-PBKZDNNV.js} +5 -5
- package/dist/{chunk-HJICGOD4.js → chunk-QWIBCFPC.js} +1 -1
- package/dist/{chunk-AG5SADAI.js → chunk-SJTIMT5U.js} +1 -1
- package/dist/chunk-TNBQFCXR.js +14 -0
- package/dist/chunk-TO27F23C.js +2 -0
- package/dist/chunk-UAF4KNXE.js +32 -0
- package/dist/{chunk-FYULPPFR.js → chunk-UUJ24BNJ.js} +1 -1
- package/dist/{chunk-QL2ZOLMC.js → chunk-VARIYH6K.js} +92 -6
- package/dist/{chunk-WBAPIPST.js → chunk-VO24C673.js} +1 -1
- package/dist/{chunk-52FETPCI.js → chunk-VSSKQAG5.js} +1 -1
- package/dist/{chunk-VKKDSXMR.js → chunk-VVBN35YG.js} +1 -1
- package/dist/chunk-WDSCTXT7.js +1 -0
- package/dist/chunk-YEBC67DJ.js +1 -0
- package/dist/cli.js +2 -2
- package/dist/config-GRL6O2ZY.js +1 -0
- package/dist/config-ZDKMTZJC.js +1 -0
- package/dist/db-LIKGSZCL.js +1 -0
- package/dist/{delivery-log-3O3OHKY4.js → delivery-log-2ILFP673.js} +1 -1
- package/dist/engine-JVPM3XE5.js +1 -0
- package/dist/evolution-audit-BDQM6NAX.js +1 -0
- package/dist/execution-tools-7MK257DY.js +1 -0
- package/dist/{external-api-YMEFVZGG.js → external-api-7GB3U775.js} +1 -1
- package/dist/index.js +41 -41
- package/dist/learner-V2HBTRAE.js +1 -0
- package/dist/logger-TEZSHFTZ.js +1 -0
- package/dist/{memories-2DY5G6ZN.js → memories-B3QGTYLX.js} +1 -1
- package/dist/memory-extractor-RYZ3VU7A.js +1 -0
- package/dist/memory-gc-5AYND3RL.js +1 -0
- package/dist/memory-service-XI3JZQ4E.js +1 -0
- package/dist/outbound-gateway-O27KKVOI.js +1 -0
- package/dist/presets-UAH3OG3C.js +1 -0
- package/dist/reflection-job-P6GIQVQN.js +23 -0
- package/dist/role-presets-RVYTO5FS.js +1 -0
- package/dist/role-workspace-KOTVFJD3.js +1 -0
- package/dist/roles-B6YC4GDC.js +1 -0
- package/dist/{runtime-TWLGJSL6.js → runtime-C3XN33A3.js} +1 -1
- package/dist/server-bus-6QGH2AVL.js +1 -0
- package/dist/session-manager-HO2ZCB47.js +1 -0
- package/dist/skill-registry-X2GY7SMI.js +1 -0
- package/dist/target-resolution-RLNUCT6M.js +1 -0
- package/dist/{task-templates-4YPKFFKG.js → task-templates-MNCF7JON.js} +1 -1
- package/dist/template-dispatch-BAMKX3QH.js +1 -0
- package/dist/trace-context-NVCN6UPC.js +1 -0
- package/package.json +2 -1
- package/web/dist/assets/{ArtifactDetail-9DJdEqCz.js → ArtifactDetail-Dt_xkaYJ.js} +2 -2
- package/web/dist/assets/{Artifacts-CQ6SAemH.js → Artifacts-DlPMk9VQ.js} +1 -1
- package/web/dist/assets/{Button-xVc-P0vm.js → Button-CRNb8sD3.js} +1 -1
- package/web/dist/assets/{Card-WUD1cwG6.js → Card-Cwvv0An8.js} +1 -1
- package/web/dist/assets/{ChannelDetail-B21nBQwi.js → ChannelDetail-kYtMmy6P.js} +1 -1
- package/web/dist/assets/{Channels-CAeGE1r7.js → Channels-BppR0Qc_.js} +2 -2
- package/web/dist/assets/{Chat-KpFWchPp.js → Chat-BLVREMCu.js} +2 -2
- package/web/dist/assets/{Dashboard-DkRwHNmr.js → Dashboard-XURc0f15.js} +1 -1
- package/web/dist/assets/{EmptyState-BLB33cKG.js → EmptyState-BvQA1o5K.js} +1 -1
- package/web/dist/assets/{EnvVarEditor-BchUNrmz.js → EnvVarEditor-DR-bSU0w.js} +1 -1
- package/web/dist/assets/{EventDefDetail-DnBwWWfT.js → EventDefDetail-DtkbGbQ0.js} +1 -1
- package/web/dist/assets/{Events-ByIzPIs2.js → Events-C_J4jvDh.js} +1 -1
- package/web/dist/assets/{Evolution-Vh9RKdma.js → Evolution-CEaSpRAm.js} +1 -1
- package/web/dist/assets/{ExtensionDetail-0CtJh5rF.js → ExtensionDetail-D5Qfq-W4.js} +1 -1
- package/web/dist/assets/{Extensions--O1ulwlC.js → Extensions-B_egkUP1.js} +1 -1
- package/web/dist/assets/{FeatureRequests-XhQbGg_q.js → FeatureRequests-D8WEYtoU.js} +1 -1
- package/web/dist/assets/{GoalDetail-DIOxf7ES.js → GoalDetail-DnMS_WWw.js} +1 -1
- package/web/dist/assets/{Goals-CZnHu9qC.js → Goals-BeKwpAss.js} +1 -1
- package/web/dist/assets/Logs-BfXBv-dV.js +1 -0
- package/web/dist/assets/{Memories-D-EAODUg.js → Memories-QRH7O8qP.js} +1 -1
- package/web/dist/assets/{Mistakes-wW78K3cP.js → Mistakes-mXU9PXft.js} +1 -1
- package/web/dist/assets/{NotFound-BsxIP-Xm.js → NotFound-DuH6sFz7.js} +1 -1
- package/web/dist/assets/{PageHeader-D8pqg_wk.js → PageHeader-acLQTYct.js} +1 -1
- package/web/dist/assets/Plugins-C8v4AsvM.js +1 -0
- package/web/dist/assets/{RoleDetail-CU3G9j_q.js → RoleDetail-Ct-k3uoK.js} +3 -3
- package/web/dist/assets/Roles-B8dQCKuS.js +1 -0
- package/web/dist/assets/{SectionHeader-DZo4QVWr.js → SectionHeader-NZWZgoOs.js} +1 -1
- package/web/dist/assets/Settings-CqtCBP6I.js +1 -0
- package/web/dist/assets/{Strategies-Bg4qlLei.js → Strategies-DFUWEKfU.js} +1 -1
- package/web/dist/assets/{Switch-WWPXnSOG.js → Switch-BcS5rOWb.js} +1 -1
- package/web/dist/assets/{Table-XjSmrOyn.js → Table-D2K039zr.js} +1 -1
- package/web/dist/assets/{Tabs-CSbcG_5T.js → Tabs-BwyLSH2c.js} +1 -1
- package/web/dist/assets/TaskDetail-BdhBhvKg.js +2 -0
- package/web/dist/assets/Work-D-t80Ekv.js +1 -0
- package/web/dist/assets/api-BRfbZQSW.js +1 -0
- package/web/dist/assets/{es2015-BgPT8VkR.js → es2015-BkFSNOYE.js} +1 -1
- package/web/dist/assets/index-DWU9AURw.css +2 -0
- package/web/dist/assets/index-PIFMZAPo.js +12 -0
- package/web/dist/assets/{useIsMobileLayout-DF2fEEM9.js → useIsMobileLayout-BogOiFTv.js} +1 -1
- package/web/dist/assets/{usePluginsWithUsage-CjU8Lkdn.js → usePluginsWithUsage-DE13JW16.js} +1 -1
- package/web/dist/assets/{vendor-icons-H7p0EuQJ.js → vendor-icons-Bc_e_XXa.js} +1 -1
- package/web/dist/assets/{vendor-react-C1yKjxEP.js → vendor-react-bQ_cvNuA.js} +1 -1
- package/web/dist/assets/{vendor-state-D0TNAbOY.js → vendor-state-BMVR_B0I.js} +1 -1
- package/web/dist/index.html +8 -8
- package/dist/App-Z2GJAMX3.js +0 -14
- package/dist/approval-handler-6NPN24UN.js +0 -1
- package/dist/audit-diagnostics-2MDM3IQT.js +0 -1
- package/dist/audit-manager-QG7CMBV2.js +0 -1
- package/dist/bree-engine-3QSLZF3W.js +0 -1
- package/dist/channels-S4AAOOTN.js +0 -1
- package/dist/channels-TYXSSI7D.js +0 -1
- package/dist/chat-tool-calls-2C7O4B2X.js +0 -1
- package/dist/chunk-32LOJEHE.js +0 -32
- package/dist/chunk-3UZIEE2D.js +0 -6
- package/dist/chunk-4234WJJD.js +0 -178
- package/dist/chunk-C2XFPUFV.js +0 -1
- package/dist/chunk-DRO3DG7X.js +0 -1
- package/dist/chunk-EWYXVBOG.js +0 -61
- package/dist/chunk-FCV2DPZQ.js +0 -1
- package/dist/chunk-FHESRUJY.js +0 -9
- package/dist/chunk-K2TZW4DU.js +0 -132
- package/dist/chunk-K4IE6DPX.js +0 -6
- package/dist/chunk-MNSZE3NV.js +0 -1
- package/dist/chunk-WVHN54MA.js +0 -14
- package/dist/chunk-Z6LHGA27.js +0 -1
- package/dist/config-HDAAV5FV.js +0 -1
- package/dist/config-VHWLMFIN.js +0 -1
- package/dist/db-HFBXO2O5.js +0 -1
- package/dist/dist-HCSYRPJU.js +0 -1
- package/dist/engine-J43ECCH7.js +0 -1
- package/dist/evolution-audit-BSGPFGFK.js +0 -1
- package/dist/execution-tools-HHUPWLCF.js +0 -1
- package/dist/learner-TQQZKRSB.js +0 -1
- package/dist/logger-PAMNFWI3.js +0 -1
- package/dist/memory-extractor-TUOOFST2.js +0 -1
- package/dist/memory-gc-MRO53MEY.js +0 -1
- package/dist/memory-service-23WVAW7T.js +0 -1
- package/dist/onnxruntime_binding-2BPLI7ZQ.node +0 -0
- package/dist/onnxruntime_binding-5J67DTMJ.node +0 -0
- package/dist/onnxruntime_binding-7ZZLEQ2F.node +0 -0
- package/dist/onnxruntime_binding-KDCXAPN5.node +0 -0
- package/dist/onnxruntime_binding-R73P2IQW.node +0 -0
- package/dist/outbound-gateway-VXODXSQR.js +0 -1
- package/dist/presets-KJV6SNNB.js +0 -1
- package/dist/reflection-job-EFFW3WOR.js +0 -23
- package/dist/role-presets-PHHL3OEN.js +0 -1
- package/dist/role-workspace-USY47ZPQ.js +0 -1
- package/dist/roles-3JXNHL7K.js +0 -1
- package/dist/server-bus-GEGVMSCA.js +0 -1
- package/dist/session-manager-PI3JEINK.js +0 -1
- package/dist/skill-registry-ROGU2WED.js +0 -1
- package/dist/target-resolution-PSSBM4LX.js +0 -1
- package/dist/template-dispatch-46TN534D.js +0 -1
- package/dist/trace-context-UR7DI5ME.js +0 -1
- package/web/dist/assets/Logs-DdeG3GiY.js +0 -1
- package/web/dist/assets/Plugins-DDUdX51_.js +0 -1
- package/web/dist/assets/Roles-BCoSzDBg.js +0 -1
- package/web/dist/assets/Settings-K3usfV-2.js +0 -1
- package/web/dist/assets/TaskDetail-C5roukcV.js +0 -2
- package/web/dist/assets/Work-DGTWSgtc.js +0 -1
- package/web/dist/assets/api-BkdixMz9.js +0 -1
- package/web/dist/assets/index-KNUbHDLy.css +0 -2
- package/web/dist/assets/index-iD-HOtIu.js +0 -12
|
@@ -1 +1 @@
|
|
|
1
|
-
import{g as Qe}from"./chunk-HJICGOD4.js";import{a as He,b as k,c as xe,d as B,e as Ke}from"./chunk-NNMQGISW.js";import{b as Xe,c as Je,f as se,g as re}from"./chunk-6Y2DN2UH.js";import{a as je,b as Ve,c as E,d as ne,e as F,f as Te,g as z,i as ze}from"./chunk-VVQ532U2.js";import{d as V}from"./chunk-Z6LHGA27.js";import{c as y,h as C}from"./chunk-BLCNUT53.js";import{z as g}from"zod/v4";import{v4 as Ms}from"uuid";import{randomUUID as st}from"crypto";import tn from"crypto";var Ye="2.1.7",ie="bot";function nn(t){let e=t.split(".").map(i=>parseInt(i,10)),n=e[0]??0,r=e[1]??0,s=e[2]??0;return(n&255)<<16|(r&255)<<8|s&255}var Me=nn(Ye),sn=35e3,Ze=15e3,rn=1e4;function ae(){return{channel_version:Ye}}function an(t){return t.endsWith("/")?t:`${t}/`}function on(){let t=tn.randomBytes(4).readUInt32BE(0);return Buffer.from(String(t),"utf-8").toString("base64")}function dn(t){let e={"Content-Type":"application/json",AuthorizationType:"ilink_bot_token","Content-Length":String(Buffer.byteLength(t.body,"utf-8")),"X-WECHAT-UIN":on(),"iLink-App-Id":ie,"iLink-App-ClientVersion":String(Me)};return t.token?.trim()&&(e.Authorization=`Bearer ${t.token.trim()}`),t.routeTag&&(e.SKRouteTag=t.routeTag),e}async function oe(t){let e=an(t.baseUrl),n=new URL(t.endpoint,e),r=dn({token:t.token,routeTag:t.routeTag,body:t.body}),s=new AbortController,i=setTimeout(()=>s.abort(),t.timeoutMs);try{let a=await fetch(n.toString(),{method:"POST",headers:r,body:t.body,signal:s.signal});clearTimeout(i);let o=await a.text();if(!a.ok)throw new Error(`${t.label} ${a.status}: ${o}`);return o}catch(a){throw clearTimeout(i),a}}async function et(t){let e=t.timeoutMs??sn;try{let n=await oe({baseUrl:t.baseUrl,endpoint:"ilink/bot/getupdates",body:JSON.stringify({get_updates_buf:t.get_updates_buf??"",base_info:ae()}),token:t.token,routeTag:t.routeTag,timeoutMs:e,label:"getUpdates"});return JSON.parse(n)}catch(n){if(n instanceof Error&&n.name==="AbortError")return{ret:0,msgs:[],get_updates_buf:t.get_updates_buf};throw n}}var un={[-2]:2,[-3]:3},cn=1e3;async function Q(t){let e=(await import("./logger-PAMNFWI3.js")).getLogger("channels"),n=new Map;for(;;){let r=await oe({baseUrl:t.baseUrl,endpoint:"ilink/bot/sendmessage",body:JSON.stringify({...t.body,base_info:ae()}),token:t.token,routeTag:t.routeTag,timeoutMs:t.timeoutMs??Ze,label:"sendMessage"});e.info({status:200,responseBody:r.slice(0,300)},"apiFetch sendMessage response");try{let s=JSON.parse(r);if(s.ret&&s.ret!==0){let i=un[s.ret],a=(n.get(s.ret)??0)+1;if(n.set(s.ret,a),i!==void 0&&a<i){e.warn({ret:s.ret,attempt:a,maxRetries:i},"sendMessage: retriable iLink error, retrying"),await new Promise(o=>setTimeout(o,cn*a));continue}throw e.error({ret:s.ret,errmsg:s.errmsg,attempt:a},"sendMessage: iLink API error, no more retries"),new Error(`sendMessage failed: iLink ret=${s.ret}${s.errmsg?` errmsg=${s.errmsg}`:""}`)}}catch(s){if(s instanceof SyntaxError)e.warn({rawText:r.slice(0,200)},"sendMessage: non-JSON response, treating as success");else throw s}return}}async function tt(t){await oe({baseUrl:t.baseUrl,endpoint:"ilink/bot/sendtyping",body:JSON.stringify({...t.body,base_info:ae()}),token:t.token,routeTag:t.routeTag,timeoutMs:t.timeoutMs??rn,label:"sendTyping"})}async function nt(t){let e=await oe({baseUrl:t.baseUrl,endpoint:"ilink/bot/getuploadurl",body:JSON.stringify({filekey:t.filekey,media_type:t.media_type,to_user_id:t.to_user_id,rawsize:t.rawsize,rawfilemd5:t.rawfilemd5,filesize:t.filesize,thumb_rawsize:t.thumb_rawsize,thumb_rawfilemd5:t.thumb_rawfilemd5,thumb_filesize:t.thumb_filesize,no_need_thumb:t.no_need_thumb,aeskey:t.aeskey,base_info:ae()}),token:t.token,routeTag:t.routeTag,timeoutMs:t.timeoutMs??Ze,label:"getUploadUrl"});return JSON.parse(e)}var ln=5*6e4,mn=35e3,rt="3",T=new Map;function Se(t){return Date.now()-t.startedAt<ln}function gn(){for(let[t,e]of T)Se(e)||T.delete(t)}async function it(t,e,n){let r=t.endsWith("/")?t:`${t}/`,s=new URL(`ilink/bot/get_bot_qrcode?bot_type=${encodeURIComponent(e)}`,r),i={"iLink-App-Id":ie};n&&(i.SKRouteTag=n);let a=await fetch(s.toString(),{headers:i});if(!a.ok){let o=await a.text().catch(()=>"(unreadable)");throw new Error(`Failed to fetch QR code: ${a.status} ${a.statusText} body=${o}`)}return await a.json()}async function pn(t,e,n){let r=t.endsWith("/")?t:`${t}/`,s=new URL(`ilink/bot/get_qrcode_status?qrcode=${encodeURIComponent(e)}`,r),i={"iLink-App-Id":ie,"iLink-App-ClientVersion":String(Me)};n&&(i.SKRouteTag=n);let a=new AbortController,o=setTimeout(()=>a.abort(),mn);try{let d=await fetch(s.toString(),{headers:i,signal:a.signal});clearTimeout(o);let c=await d.text();if(!d.ok)throw new Error(`Failed to poll QR status: ${d.status} ${d.statusText}`);return JSON.parse(c)}catch(d){if(clearTimeout(o),d instanceof Error&&d.name==="AbortError")return{status:"wait"};throw d}}async function at(t){let e=t.accountId||st();gn();let n=T.get(e);if(!t.force&&n&&Se(n)&&n.qrcodeUrl)return{qrcodeUrl:n.qrcodeUrl,message:"QR code ready. Scan with WeChat.",sessionKey:e};if(!t.apiBaseUrl)return{message:"No baseUrl configured for this WeChat channel.",sessionKey:e};try{let r=t.botType||rt,s=await it(t.apiBaseUrl,r,t.routeTag),i={sessionKey:e,id:st(),qrcode:s.qrcode,qrcodeUrl:s.qrcode_img_content,startedAt:Date.now()};return T.set(e,i),{qrcodeUrl:s.qrcode_img_content,message:"Scan the QR code with WeChat to connect.",sessionKey:e}}catch(r){return{message:`Failed to start login: ${String(r)}`,sessionKey:e}}}var fn=3;async function ot(t){let e=T.get(t.sessionKey);if(!e)return{connected:!1,message:"No active login session. Start QR login first."};if(!Se(e))return T.delete(t.sessionKey),{connected:!1,message:"QR code expired. Please start again."};let n=Math.max(t.timeoutMs??48e4,1e3),r=Date.now()+n,s=1;for(;Date.now()<r;){try{let i=await pn(t.apiBaseUrl,e.qrcode,t.routeTag);switch(e.status=i.status,i.status){case"wait":break;case"scaned":break;case"expired":{if(s++,s>fn)return T.delete(t.sessionKey),{connected:!1,message:"Login timeout: QR expired multiple times."};try{let a=t.botType||rt,o=await it(t.apiBaseUrl,a,t.routeTag);e.qrcode=o.qrcode,e.qrcodeUrl=o.qrcode_img_content,e.startedAt=Date.now()}catch(a){return T.delete(t.sessionKey),{connected:!1,message:`QR refresh failed: ${String(a)}`}}break}case"confirmed":return i.ilink_bot_id?(T.delete(t.sessionKey),{connected:!0,botToken:i.bot_token,accountId:i.ilink_bot_id,baseUrl:i.baseurl,userId:i.ilink_user_id,message:"Connected to WeChat successfully!"}):(T.delete(t.sessionKey),{connected:!1,message:"Login failed: server did not return bot ID."})}}catch(i){return T.delete(t.sessionKey),{connected:!1,message:`Login failed: ${String(i)}`}}await new Promise(i=>setTimeout(i,1e3))}return T.delete(t.sessionKey),{connected:!1,message:"Login timeout. Please try again."}}import A from"fs";import*as M from"fs/promises";import x from"path";import{homedir as pe}from"os";var de={IMAGE:1,VIDEO:2,FILE:3,VOICE:4},H={NONE:0,USER:1,BOT:2},_={NONE:0,TEXT:1,IMAGE:2,VOICE:3,FILE:4,VIDEO:5},K={NEW:0,GENERATING:1,FINISH:2},dt={TYPING:1,CANCEL:2};C();var hn=y("channels"),Ce=-14,ue=3600*1e3,$=new Map;function ut(t){let e=Date.now()+ue;$.set(t,e),hn.info({channelId:t},`Session paused until ${new Date(e).toISOString()} (${ue/1e3}s)`)}function ce(t){let e=$.get(t);return e===void 0?!1:Date.now()>=e?($.delete(t),!1):!0}function ct(t){let e=$.get(t);if(e===void 0)return 0;let n=e-Date.now();return n<=0?($.delete(t),0):n}function lt(t){$.delete(t)}C();import*as me from"fs/promises";import _t from"path";import{homedir as In}from"os";import{createCipheriv as yn,createDecipheriv as bn}from"crypto";function mt(t,e){let n=yn("aes-128-ecb",e,null);return Buffer.concat([n.update(t),n.final()])}function gt(t,e){let n=bn("aes-128-ecb",e,null);return Buffer.concat([n.update(t),n.final()])}function pt(t){return Math.ceil((t+1)/16)*16}function Ae(t,e){return`${e}/download?encrypted_query_param=${encodeURIComponent(t)}`}function ft(t){return`${t.cdnBaseUrl}/upload?encrypted_query_param=${encodeURIComponent(t.uploadParam)}&filekey=${encodeURIComponent(t.filekey)}`}C();var Ws=y("channels");function wn(t){let e=Buffer.from(t,"base64");if(e.length===16)return e;if(e.length===32&&/^[0-9a-fA-F]{32}$/.test(e.toString("ascii")))return Buffer.from(e.toString("ascii"),"hex");throw new Error(`aes_key must decode to 16 raw bytes or 32-char hex, got ${e.length} bytes`)}async function ht(t){let e=await fetch(t);if(!e.ok)throw new Error(`CDN download ${e.status} ${e.statusText}`);return Buffer.from(await e.arrayBuffer())}async function X(t){let{encryptQueryParam:e,aesKeyBase64:n,cdnBaseUrl:r,fullUrl:s}=t,i=wn(n),a=s?.trim()||(e?Ae(e,r):null);if(!a)throw new Error("CDN download: need full_url or encrypt_query_param");let o=await ht(a);return gt(o,i)}async function yt(t){let{encryptQueryParam:e,cdnBaseUrl:n,fullUrl:r}=t,s=r?.trim()||(e?Ae(e,n):null);if(!s)throw new Error("CDN download: need full_url or encrypt_query_param");return ht(s)}C();var le=y("channels"),bt=24e3;function _n(t,e){let n=t.byteLength,r=44+n,s=Buffer.allocUnsafe(r),i=0;return s.write("RIFF",i),i+=4,s.writeUInt32LE(r-8,i),i+=4,s.write("WAVE",i),i+=4,s.write("fmt ",i),i+=4,s.writeUInt32LE(16,i),i+=4,s.writeUInt16LE(1,i),i+=2,s.writeUInt16LE(1,i),i+=2,s.writeUInt32LE(e,i),i+=4,s.writeUInt32LE(e*2,i),i+=4,s.writeUInt16LE(2,i),i+=2,s.writeUInt16LE(16,i),i+=2,s.write("data",i),i+=4,s.writeUInt32LE(n,i),i+=4,Buffer.from(t.buffer,t.byteOffset,t.byteLength).copy(s,i),s}async function wt(t){try{let{decode:e}=await import("silk-wasm");le.debug(`silkToWav: decoding ${t.length} bytes of SILK`);let n=await e(t,bt);le.debug(`silkToWav: decoded duration=${n.duration}ms pcmBytes=${n.data.byteLength}`);let r=_n(n.data,bt);return le.debug(`silkToWav: WAV size=${r.length}`),r}catch(e){return le.warn(`silkToWav: transcode failed, will use raw silk err=${String(e)}`),null}}var N=y("channels"),It=100*1024*1024;function En(t){return re(t)??".bin"}async function J(t,e,n,r,s=It,i){if(t.length>s)throw new Error(`Media too large: ${t.length} bytes exceeds ${s} bytes`);let a=_t.join(In(),".adam","wechat","media",r,n);await me.mkdir(a,{recursive:!0});let o;if(i&&/^[a-zA-Z0-9._-]+$/.test(i))o=i;else{let c=e?En(e):".bin",u=Date.now(),p=Math.random().toString(36).slice(2,7);o=`${u}-${p}${c}`}let d=_t.join(a,o);return await me.writeFile(d,t),N.debug(`saveMedia: saved ${t.length} bytes to ${d}`),d}async function Et(t,e){let{cdnBaseUrl:n,channelId:r}=e;if(t.type===_.IMAGE){let s=t.image_item;if(!s?.media?.encrypt_query_param&&!s?.media?.full_url)return null;let i=s.aeskey?Buffer.from(s.aeskey,"hex").toString("base64"):s.media?.aes_key;try{let a=i?await X({encryptQueryParam:s.media?.encrypt_query_param,aesKeyBase64:i,cdnBaseUrl:n,fullUrl:s.media?.full_url}):await yt({encryptQueryParam:s.media?.encrypt_query_param,cdnBaseUrl:n,fullUrl:s.media?.full_url});return{path:await J(a,"image/png","inbound",r),mimeType:"image/png",type:"image"}}catch(a){return N.error({channelId:r},`Image download/decrypt failed: ${String(a)}`),null}}if(t.type===_.VOICE){let s=t.voice_item;if(!s?.media?.encrypt_query_param&&!s?.media?.full_url||!s?.media?.aes_key)return null;try{let i=await X({encryptQueryParam:s.media.encrypt_query_param,aesKeyBase64:s.media.aes_key,cdnBaseUrl:n,fullUrl:s.media.full_url}),a=await wt(i);if(a){let o=await J(a,"audio/wav","inbound",r);return N.debug(`Voice: saved WAV to ${o}`),{path:o,mimeType:"audio/wav",type:"audio"}}else{let o=await J(i,"audio/silk","inbound",r);return N.debug(`Voice: silk transcode unavailable, saved raw SILK to ${o}`),{path:o,mimeType:"audio/silk",type:"audio"}}}catch(i){return N.error({channelId:r},`Voice download/transcode failed: ${String(i)}`),null}}if(t.type===_.FILE){let s=t.file_item;if(!s?.media?.encrypt_query_param&&!s?.media?.full_url||!s?.media?.aes_key)return null;try{let i=await X({encryptQueryParam:s.media.encrypt_query_param,aesKeyBase64:s.media.aes_key,cdnBaseUrl:n,fullUrl:s.media.full_url}),a=se(s.file_name??"file.bin");return{path:await J(i,a,"inbound",r,It,s.file_name),mimeType:a,type:"file"}}catch(i){return N.error({channelId:r},`File download failed: ${String(i)}`),null}}if(t.type===_.VIDEO){let s=t.video_item;if(!s?.media?.encrypt_query_param&&!s?.media?.full_url||!s?.media?.aes_key)return null;try{let i=await X({encryptQueryParam:s.media.encrypt_query_param,aesKeyBase64:s.media.aes_key,cdnBaseUrl:n,fullUrl:s.media.full_url});return{path:await J(i,"video/mp4","inbound",r),mimeType:"video/mp4",type:"video"}}catch(i){return N.error({channelId:r},`Video download failed: ${String(i)}`),null}}return null}import Mt from"path";import Re from"crypto";import Tn from"fs/promises";C();var O=y("channels"),ge=3;async function xn(t){let{buf:e,uploadFullUrl:n,uploadParam:r,filekey:s,cdnBaseUrl:i,label:a,aeskey:o}=t,d=mt(e,o),c=n?.trim(),u;if(c)u=c;else if(r)u=ft({cdnBaseUrl:i,uploadParam:r,filekey:s});else throw new Error(`${a}: CDN upload URL missing (need upload_full_url or upload_param)`);O.debug(`${a}: CDN POST url=${u} ciphertextSize=${d.length}`);let p,f;for(let m=1;m<=ge;m++)try{let l=await fetch(u,{method:"POST",headers:{"Content-Type":"application/octet-stream"},body:new Uint8Array(d)});if(l.status>=400&&l.status<500){let b=l.headers.get("x-error-message")??await l.text();throw O.error(`${a}: CDN client error attempt=${m} status=${l.status} errMsg=${b}`),new Error(`CDN upload client error ${l.status}: ${b}`)}if(l.status!==200){let b=l.headers.get("x-error-message")??`status ${l.status}`;throw O.error(`${a}: CDN server error attempt=${m} status=${l.status} errMsg=${b}`),new Error(`CDN upload server error: ${b}`)}if(p=l.headers.get("x-encrypted-param")??void 0,!p)throw O.error(`${a}: CDN response missing x-encrypted-param header attempt=${m}`),new Error("CDN upload response missing x-encrypted-param header");O.debug(`${a}: CDN upload success attempt=${m}`);break}catch(l){if(f=l,l instanceof Error&&l.message.includes("client error"))throw l;m<ge?O.warn(`${a}: attempt ${m} failed, retrying... err=${String(l)}`):O.error(`${a}: all ${ge} attempts failed err=${String(l)}`)}if(!p)throw f instanceof Error?f:new Error(`CDN upload failed after ${ge} attempts`);return{downloadParam:p}}async function ke(t){let{filePath:e,toUserId:n,opts:r,cdnBaseUrl:s,mediaType:i,label:a}=t,o=await Tn.readFile(e),d=o.length,c=Re.createHash("md5").update(o).digest("hex"),u=pt(d),p=Re.randomBytes(16).toString("hex"),f=Re.randomBytes(16);O.debug(`${a}: file=${e} rawsize=${d} filesize=${u} md5=${c} filekey=${p}`);let m=await nt({...r,filekey:p,media_type:i,to_user_id:n,rawsize:d,rawfilemd5:c,filesize:u,no_need_thumb:!0,aeskey:f.toString("hex")}),l=m.upload_full_url?.trim(),b=m.upload_param;if(!l&&!b)throw new Error(`${a}: getUploadUrl returned no upload URL (need upload_full_url or upload_param)`);let{downloadParam:L}=await xn({buf:o,uploadFullUrl:l||void 0,uploadParam:b??void 0,filekey:p,cdnBaseUrl:s,aeskey:f,label:`${a}[orig filekey=${p}]`});return{filekey:p,downloadEncryptedQueryParam:L,aeskey:f.toString("hex"),fileSize:d,fileSizeCiphertext:u}}async function Tt(t){return ke({...t,mediaType:de.IMAGE,label:"uploadImageToWeixin"})}async function xt(t){return ke({...t,mediaType:de.VIDEO,label:"uploadVideoToWeixin"})}async function Pe(t){return ke({...t,mediaType:de.FILE,label:"uploadFileAttachmentToWeixin"})}C();var Y=y("channels");function Mn(){return`adam-wechat-${Date.now()}-${Math.random().toString(36).slice(2,7)}`}function Sn(t){let e=t;return e=e.replace(/```[^\n]*\n?([\s\S]*?)```/g,(n,r)=>r.trim()),e=e.replace(/!\[[^\]]*\]\([^)]*\)/g,""),e=e.replace(/\[([^\]]+)\]\([^)]*\)/g,"$1"),e=e.replace(/^\|[\s:|-]+\|$/gm,""),e=e.replace(/^\|(.+)\|$/gm,(n,r)=>r.split("|").map(s=>s.trim()).join(" ")),e}async function Ue(t){let{to:e,text:n,mediaItem:r,opts:s,label:i}=t,a=[],o=Sn(n);o&&a.push({type:_.TEXT,text_item:{text:o}}),a.push(r);let d="";for(let c of a){d=Mn();let u={msg:{from_user_id:"",to_user_id:e,client_id:d,message_type:H.BOT,message_state:K.FINISH,item_list:[c],context_token:s.contextToken}};await Q({baseUrl:s.baseUrl,token:s.token,routeTag:s.routeTag,body:u})}return Y.debug(`${i}: sent to=${e} messageId=${d}`),{messageId:d}}async function Cn(t){let{to:e,text:n,uploaded:r,opts:s}=t,i={type:_.IMAGE,image_item:{media:{encrypt_query_param:r.downloadEncryptedQueryParam,aes_key:Buffer.from(r.aeskey).toString("base64"),encrypt_type:1},mid_size:r.fileSizeCiphertext}};return Ue({to:e,text:n,mediaItem:i,opts:s,label:"sendImageMessage"})}async function An(t){let{to:e,text:n,uploaded:r,opts:s}=t,i={type:_.VIDEO,video_item:{media:{encrypt_query_param:r.downloadEncryptedQueryParam,aes_key:Buffer.from(r.aeskey).toString("base64"),encrypt_type:1},video_size:r.fileSizeCiphertext}};return Ue({to:e,text:n,mediaItem:i,opts:s,label:"sendVideoMessage"})}async function St(t){let{to:e,text:n,fileName:r,uploaded:s,opts:i}=t,a={type:_.FILE,file_item:{media:{encrypt_query_param:s.downloadEncryptedQueryParam,aes_key:Buffer.from(s.aeskey).toString("base64"),encrypt_type:1},file_name:r,len:String(s.fileSize)}};return Ue({to:e,text:n,mediaItem:a,opts:i,label:"sendFileMessage"})}async function Ct(t){let{filePath:e,to:n,text:r,opts:s,cdnBaseUrl:i}=t,a=se(e),o={baseUrl:s.baseUrl,token:s.token,routeTag:s.routeTag};if(a.startsWith("video/")){Y.debug(`sendWeixinMediaFile: uploading video filePath=${e} to=${n}`);let u=await xt({filePath:e,toUserId:n,opts:o,cdnBaseUrl:i});return An({to:n,text:r,uploaded:u,opts:s})}if(a.startsWith("image/")){Y.debug(`sendWeixinMediaFile: uploading image filePath=${e} to=${n}`);let u=await Tt({filePath:e,toUserId:n,opts:o,cdnBaseUrl:i});return Cn({to:n,text:r,uploaded:u,opts:s})}if(a.startsWith("audio/")){let u=Mt.basename(e);Y.debug(`sendWeixinMediaFile: uploading audio as file filePath=${e} name=${u} to=${n}`);let p=await Pe({filePath:e,fileName:u,toUserId:n,opts:o,cdnBaseUrl:i});return St({to:n,text:r,fileName:u,uploaded:p,opts:s})}let d=Mt.basename(e);Y.debug(`sendWeixinMediaFile: uploading file attachment filePath=${e} name=${d} to=${n}`);let c=await Pe({filePath:e,fileName:d,toUserId:n,opts:o,cdnBaseUrl:i});return St({to:n,text:r,fileName:d,uploaded:c,opts:s})}C();var h=y("channels"),At="https://novac2c.cdn.weixin.qq.com/c2c",Ne=new Map;function Pt(t){return x.join(pe(),".adam","wechat",`${t}.context-tokens.json`)}function Rn(t){let e=Pt(t);try{let n=A.readFileSync(e,"utf-8"),r=JSON.parse(n);for(let[s,i]of Object.entries(r))typeof i=="string"&&i&&Ne.set(`${t}:${s}`,i);h.debug({channelId:t,count:Object.keys(r).length},"Restored context tokens from disk")}catch{}}function kn(t,e,n){let r=Pt(t);try{let s={};try{let a=A.readFileSync(r,"utf-8");s=JSON.parse(a)}catch{}s[e]=n;let i=x.dirname(r);A.mkdirSync(i,{recursive:!0}),A.writeFileSync(r,JSON.stringify(s),"utf-8")}catch(s){h.warn({channelId:t,userId:e},`Failed to persist context token: ${String(s)}`)}}function Pn(t,e,n){Ne.set(`${t}:${e}`,n),kn(t,e,n)}function ve(t,e){return Ne.get(`${t}:${e}`)}function Ut(t){return x.join(pe(),".adam","wechat",`${t}.sync`)}function Un(t){try{return A.readFileSync(Ut(t),"utf-8")}catch{return""}}function vn(t,e){let n=Ut(t);A.mkdirSync(x.dirname(n),{recursive:!0}),A.writeFileSync(n,e,"utf-8")}var Oe=1440*60*1e3,Rt=10,On=20,kt=1440*60*1e3,Nn=1320*60*1e3,Dn=1,Ln=7200*1e3;function vt(t){return x.join(pe(),".adam","wechat",`${t}.session.json`)}function Fn(t){let e=new Map,n=vt(t);try{let r=A.readFileSync(n,"utf-8"),s=JSON.parse(r);for(let[i,a]of Object.entries(s))a&&typeof a.lastUserMessageAt=="number"&&e.set(i,a);h.debug({channelId:t,count:e.size},"Restored sessions from disk")}catch{}return e}function Z(t,e){let n=vt(t);try{let r={};for(let[i,a]of e)r[i]=a;let s=x.dirname(n);A.mkdirSync(s,{recursive:!0}),A.writeFileSync(n,JSON.stringify(r),"utf-8")}catch(r){h.warn({channelId:t},`Failed to persist sessions: ${String(r)}`)}}var Bn=0;function ee(){return`adam-wechat-${Date.now()}-${++Bn}`}var q=class{platform="wechat";id;config;status="disconnected";messageHandler=null;pollAbort=null;getUpdatesBuf="";sessions=new Map;pendingQueue=new Map;lastReminderAt=new Map;constructor(e,n){if(this.id=e,!n.baseUrl)throw new Error("WeChat adapter requires baseUrl");this.config=n}async connect(){if(!this.config.botToken)throw new Error("WeChat adapter requires botToken. Complete QR login first.");this.status="connecting",this.getUpdatesBuf=Un(this.id),Rn(this.id),this.sessions=Fn(this.id),this.pollAbort=new AbortController,this.status="connected",h.info({channelId:this.id},"WeChat adapter connected, starting long-poll"),this.startLongPoll()}async disconnect(){this.pollAbort&&(this.pollAbort.abort(),this.pollAbort=null),this.status="disconnected",h.info({channelId:this.id},"WeChat adapter disconnected")}getStatus(){if(this.status==="connected"&&ce(this.id))return"error";if(this.status==="connected"){for(let[,e]of this.sessions)if(this.isSessionActive(e)&&e.quotaRemaining<=0)return"degraded"}return this.status}getCapabilities(){return{canEdit:!1,canQuote:!0,canParseQuote:!0,canInlineButtons:!1,maxTextLength:4e3,supportsAttachments:!0,maxAttachmentsPerMessage:1}}async sendMessage(e,n){if(ce(this.id)){let c=Math.ceil(ct(this.id)/6e4);throw new Error(`WeChat session paused, ${c} min remaining. Re-scan QR to reconnect.`)}let r=this.getOrCreateSession(e),i=this.getSessionRemainingMs(r)/36e5;if(!this.isSessionActive(r))return h.warn({channelId:this.id,chatId:e.slice(0,12),lastUserMessageAt:r.lastUserMessageAt,sessionExpired:!0},"iLink session expired (>24h), message queued"),this.enqueueMessage(e,n),`queued-${ee()}`;if(r.quotaRemaining<=0)return h.warn({channelId:this.id,chatId:e.slice(0,12),quotaRemaining:0,remainingHours:i.toFixed(1)},"iLink quota exhausted, message queued"),this.enqueueMessage(e,n),`queued-${ee()}`;let a=ee(),o=ve(this.id,e),d=this.config.cdnBaseUrl??At;try{let c=n.attachments?.[0],u=c?.path??n.mediaUrl,p=c?.contentType,f=c?.filename,m=c?.mediaType??n.mediaType;if(u){let l=!u.includes("://")||u.startsWith("file://"),b=x.join(pe(),".adam","wechat","media","outbound-tmp");await M.mkdir(b,{recursive:!0});let L=this.getExtensionFromMediaType(m,p),R;if(l){let I=u.startsWith("file://")?new URL(u).pathname:x.isAbsolute(u)?u:x.resolve(u),v=await M.readFile(I);R=x.join(b,`${Date.now()}-${Math.random().toString(36).slice(2,7)}${L}`),await M.writeFile(R,v)}else{let I=await fetch(u);if(!I.ok)throw new Error(`Failed to fetch media: ${I.status}`);let v=Buffer.from(await I.arrayBuffer());R=x.join(b,`${Date.now()}-${Math.random().toString(36).slice(2,7)}${L}`),await M.writeFile(R,v)}let w=R;if(f){let I=f.replace(/[\\/]/g,"-").replace(/\.\./g,"-").replace(/[\x00-\x1f]/g,"");if(I.length>0&&I.length<200){let v=x.join(b,`${Date.now()}-${I}`);await M.copyFile(R,v),await M.unlink(R).catch(()=>{}),w=v}}let U=await Ct({filePath:w,to:e,text:n.content??"",opts:{baseUrl:this.config.baseUrl,token:this.config.botToken,routeTag:this.config.routeTag,contextToken:o},cdnBaseUrl:d});return await M.unlink(w).catch(()=>{}),r.quotaRemaining--,Z(this.id,this.sessions),h.info({channelId:this.id,chatId:e.slice(0,12),quotaRemaining:r.quotaRemaining,sessionRemainingHours:(this.getSessionRemainingMs(r)/36e5).toFixed(1)},"iLink send success: quota decremented"),this.checkAndSendReminder(e,r).catch(I=>{h.warn({channelId:this.id,chatId:e.slice(0,12)},`Reminder send failed: ${String(I)}`)}),U.messageId}return await Q({baseUrl:this.config.baseUrl,token:this.config.botToken,routeTag:this.config.routeTag,body:{msg:{from_user_id:"",to_user_id:e,client_id:a,message_type:H.BOT,message_state:K.FINISH,item_list:this.buildItemList(n),context_token:o}}}),r.quotaRemaining--,Z(this.id,this.sessions),h.info({channelId:this.id,chatId:e.slice(0,12),quotaRemaining:r.quotaRemaining,sessionRemainingHours:(this.getSessionRemainingMs(r)/36e5).toFixed(1)},"iLink send success: quota decremented"),this.checkAndSendReminder(e,r).catch(l=>{h.warn({channelId:this.id,chatId:e.slice(0,12)},`Reminder send failed: ${String(l)}`)}),a}catch(c){if(c instanceof Error&&c.message.includes("ret=-2"))return r.quotaRemaining=0,Z(this.id,this.sessions),h.warn({channelId:this.id,chatId:e.slice(0,12),quotaRemaining:0},"iLink quota exhausted (ret=-2 confirmed), message queued"),this.enqueueMessage(e,n),`queued-${ee()}`;throw c}}onMessage(e){this.messageHandler=e}async sendTypingIndicator(e){if(ce(this.id))return;let n=ve(this.id,e);try{await tt({baseUrl:this.config.baseUrl,token:this.config.botToken,routeTag:this.config.routeTag,body:{ilink_user_id:e,status:dt.TYPING}})}catch{}}updateConfig(e){Object.assign(this.config,e)}buildItemList(e){if(!e.content)return;let n={type:_.TEXT,text_item:{text:e.content}};if(e.replyToMessageId){let r=(e.quoteExcerpt??"").slice(0,80);n.ref_msg={message_item:{msg_id:e.replyToMessageId,text_item:{text:r}},title:e.quoteTitle}}return[n]}getOrCreateSession(e){let n=this.sessions.get(e);return n||(n={lastUserMessageAt:0,quotaRemaining:0},this.sessions.set(e,n)),n}isSessionActive(e){return e.lastUserMessageAt>0&&Date.now()-e.lastUserMessageAt<=Oe}getSessionRemainingMs(e){return e.lastUserMessageAt===0?0:Math.max(0,Oe-(Date.now()-e.lastUserMessageAt))}enqueueMessage(e,n){let r=this.pendingQueue.get(e);r||(r=[],this.pendingQueue.set(e,r));let s=Date.now();r=r.filter(i=>s-i.queuedAt<kt),r.length>=On&&(r.shift(),h.warn({channelId:this.id,chatId:e.slice(0,12)},"Queue full, dropping oldest message")),r.push({message:n,queuedAt:s}),this.pendingQueue.set(e,r),h.info({channelId:this.id,chatId:e.slice(0,12),queueDepth:r.length},"Message enqueued")}async flushQueue(e){let n=this.pendingQueue.get(e);if(!n||n.length===0)return;let r=this.getOrCreateSession(e),s=Math.min(n.length,Math.max(0,r.quotaRemaining-2));if(s<=0){h.info({channelId:this.id,chatId:e.slice(0,12),quotaRemaining:r.quotaRemaining},"Queue flush skipped: insufficient quota (reserving 2 for conversation)");return}h.info({channelId:this.id,chatId:e.slice(0,12),queueDepth:n.length,sending:s,quotaRemaining:r.quotaRemaining},"Flushing queued messages");let i=0;for(;i<s&&n.length>0;){let a=n[0];if(Date.now()-a.queuedAt>kt){n.shift();continue}try{if(await this.sendMessage(e,a.message),n.shift(),i++,r.quotaRemaining<=0)break}catch{h.warn({channelId:this.id,chatId:e.slice(0,12)},"Queue flush: send failed, stopping");break}}n.length===0&&this.pendingQueue.delete(e),h.info({channelId:this.id,chatId:e.slice(0,12),sent:i,remaining:n.length},"Queue flush complete")}async checkAndSendReminder(e,n){let r=Date.now(),s=this.lastReminderAt.get(e)??0;if(r-s<Ln)return;let i=this.getSessionRemainingMs(n),o=r-n.lastUserMessageAt>=Nn,d=n.quotaRemaining<=Dn;if(!o&&!d)return;let c=(i/36e5).toFixed(1),u;o&&d?u=`[\u7CFB\u7EDF\u63D0\u9192] \u6D88\u606F\u7A97\u53E3\u5373\u5C06\u5173\u95ED\uFF08\u5269\u4F59${c}\u5C0F\u65F6/${n.quotaRemaining}\u6761\u914D\u989D\uFF09\u3002\u8BF7\u56DE\u590D\u4EFB\u610F\u6D88\u606F\u4EE5\u4FDD\u6301\u8FDE\u63A5\u3002`:o?u=`[\u7CFB\u7EDF\u63D0\u9192] \u6D88\u606F\u7A97\u53E3\u5373\u5C06\u5173\u95ED\uFF08\u5269\u4F59${c}\u5C0F\u65F6\uFF09\u3002\u8BF7\u56DE\u590D\u4EFB\u610F\u6D88\u606F\u4EE5\u4FDD\u6301\u8FDE\u63A5\u3002`:u=`[\u7CFB\u7EDF\u63D0\u9192] \u6D88\u606F\u914D\u989D\u5373\u5C06\u7528\u5B8C\uFF08\u5269\u4F59${n.quotaRemaining}\u6761\uFF09\u3002\u8BF7\u56DE\u590D\u4EFB\u610F\u6D88\u606F\u4EE5\u91CD\u7F6E\u914D\u989D\u3002`;let p=ve(this.id,e);try{await Q({baseUrl:this.config.baseUrl,token:this.config.botToken,routeTag:this.config.routeTag,body:{msg:{from_user_id:"",to_user_id:e,client_id:ee(),message_type:H.BOT,message_state:K.FINISH,item_list:[{type:_.TEXT,text_item:{text:u}}],context_token:p}}}),n.quotaRemaining--,this.lastReminderAt.set(e,r),Z(this.id,this.sessions),h.info({channelId:this.id,chatId:e.slice(0,12),remainingHours:c,quotaRemaining:n.quotaRemaining,trigger:o?"time":"quota"},"iLink session reminder sent")}catch(f){h.warn({channelId:this.id,chatId:e.slice(0,12)},`Reminder send failed: ${String(f)}`)}}async startLongPoll(){let e=this.pollAbort?.signal,n=0,r=3,s=3e4,i=2e3;for(;!e?.aborted;)try{let a=await et({baseUrl:this.config.baseUrl,token:this.config.botToken,routeTag:this.config.routeTag,get_updates_buf:this.getUpdatesBuf});if(a.ret===Ce||a.errcode===Ce){ut(this.id),this.status="error",h.error({channelId:this.id},"Session expired (errcode=-14), pausing for 1 hour"),await this.sleep(ue,e),lt(this.id),this.status="connected";continue}if(a.ret!==void 0&&a.ret!==0||a.errcode!==void 0&&a.errcode!==0){n++,h.error({channelId:this.id,ret:a.ret,errcode:a.errcode},"getUpdates API error"),n>=r?(n=0,await this.sleep(s,e)):await this.sleep(i,e);continue}n=0,a.get_updates_buf&&(this.getUpdatesBuf=a.get_updates_buf,vn(this.id,a.get_updates_buf));for(let d of a.msgs??[])await this.processInbound(d)}catch(a){if(e?.aborted)return;n++,h.error({channelId:this.id,error:a},"getUpdates error"),n>=r?(n=0,await this.sleep(s,e)):await this.sleep(i,e)}}async processInbound(e){if(!this.messageHandler)return;let n=!!e.group_id,r=n?e.group_id:e.from_user_id??"",s=e.from_user_id??"";e.context_token&&r&&Pn(this.id,r,e.context_token);let i=this.getOrCreateSession(r),a=i.quotaRemaining;i.lastUserMessageAt=Date.now(),i.quotaRemaining=Rt,Z(this.id,this.sessions),h.info({channelId:this.id,chatId:r.slice(0,12),quotaReset:!0,prevQuota:a,newQuota:Rt,sessionWindowMs:Oe},"iLink session reset: user message received, quota restored"),this.flushQueue(r);let o="",d,c=[],u;for(let m of e.item_list??[]){let l=m.ref_msg?.message_item?.msg_id;if(l){u=l;break}}for(let m of e.item_list??[])m.type===_.TEXT&&m.text_item?.text&&(o+=m.text_item.text),m.type===_.IMAGE&&(d="image",c.push(m)),m.type===_.VOICE&&(d="audio",c.push(m),m.voice_item?.text&&!o&&(o=m.voice_item.text)),m.type===_.FILE&&(d="file",c.push(m)),m.type===_.VIDEO&&(d="video",c.push(m));if(!o&&!d)return;let p;if(c.length>0){let m=this.config.cdnBaseUrl??At;try{let l=await Et(c[0],{cdnBaseUrl:m,channelId:this.id});l&&(p=l.path,d=l.type)}catch(l){h.error({channelId:this.id},`Media download failed: ${String(l)}`)}}let f={channelId:this.id,platform:"wechat",chatId:r,senderId:s,content:o,mediaType:d,mediaPath:p,isGroup:n,timestamp:e.create_time_ms??Date.now(),raw:e,...u?{quotedPlatformMessageId:u}:{}};this.messageHandler(f)}getExtensionFromMediaType(e,n){if(n){let r=re(n);if(r&&r!==".bin")return r}switch(e){case"image":return".png";case"video":return".mp4";case"audio":return".mp3";default:return".bin"}}sleep(e,n){return new Promise((r,s)=>{let i=setTimeout(r,e);n?.addEventListener("abort",()=>{clearTimeout(i),s(new Error("aborted"))},{once:!0})})}};C();C();var $n=y("channels"),fe=class{platform="discord";id;config;status="disconnected";messageHandler=null;client=null;constructor(e,n){if(this.id=e,!n.botToken)throw new Error("Discord adapter requires botToken");this.config=n}async connect(){this.status="connecting";try{let{Client:e,GatewayIntentBits:n}=await import("discord.js");this.client=new e({intents:[n.Guilds,n.GuildMessages,n.MessageContent,n.DirectMessages]});let r=this.client;r.on("messageCreate",s=>{if(!this.messageHandler||s.author.bot||this.config.allowedGuildIds?.length&&s.guildId&&!this.config.allowedGuildIds.includes(s.guildId))return;let i={channelId:this.id,platform:"discord",chatId:s.channelId,senderId:s.author.id,senderName:s.author.displayName??s.author.username,content:s.content,isGroup:!!s.guildId,timestamp:s.createdTimestamp,raw:s};this.messageHandler(i)}),await r.login(this.config.botToken),this.status="connected",$n.info({channelId:this.id},"Discord bot connected")}catch(e){throw this.status="error",e}}async disconnect(){this.client&&await this.client.destroy(),this.client=null,this.status="disconnected"}getStatus(){return this.status}getCapabilities(){return{canEdit:!0,canQuote:!0,canParseQuote:!0,canInlineButtons:!0,maxTextLength:2e3,supportsAttachments:!0}}async sendMessage(e,n){if(!this.client)throw new Error("Discord client not connected");let s=await this.client.channels.fetch(e);if(!s||!("send"in s))throw new Error(`Channel ${e} not found or not text channel`);return(await s.send({content:n.content,reply:n.replyToMessageId?{messageReference:n.replyToMessageId}:void 0})).id}onMessage(e){this.messageHandler=e}async sendTypingIndicator(e){if(!this.client)return;let r=await this.client.channels.fetch(e);r&&"sendTyping"in r&&await r.sendTyping()}};import{statSync as es}from"fs";import{ImapFlow as ts}from"imapflow";import ns from"nodemailer";import{existsSync as qn,mkdirSync as Gn,readFileSync as Wn,writeFileSync as jn}from"fs";import{dirname as Vn,join as Ot}from"path";import{homedir as zn}from"os";var Qn={lastUid:0,seenMessageIds:[],sentMessageIds:[],updatedAt:0};function De(t=process.env.ADAM_TEST_DIR??Ot(zn(),".adam")){return Ot(t,"email-gateway","state.json")}function he(t=De()){if(!qn(t))return{...Qn};let e=JSON.parse(Wn(t,"utf-8"));return{uidValidity:e.uidValidity,lastUid:Number.isInteger(e.lastUid)?e.lastUid:0,seenMessageIds:Array.isArray(e.seenMessageIds)?e.seenMessageIds.filter(Nt):[],sentMessageIds:Array.isArray(e.sentMessageIds)?e.sentMessageIds.filter(Nt):[],updatedAt:typeof e.updatedAt=="number"?e.updatedAt:0}}function te(t,e=De()){Gn(Vn(e),{recursive:!0}),jn(e,JSON.stringify({...t,updatedAt:Date.now()},null,2),"utf-8")}function Dt(t,e){let n=G(e);return n?{...t,seenMessageIds:t.seenMessageIds.includes(n)?t.seenMessageIds:[...t.seenMessageIds,n]}:t}function Hn(t,e){let n=G(e);return n?{...t,sentMessageIds:t.sentMessageIds.includes(n)?t.sentMessageIds:[...t.sentMessageIds,n]}:t}function Lt(t,e=De()){let n=Hn(he(e),t);return te(n,e),n}function G(t){return typeof t=="string"?t.trim():""}function Nt(t){return typeof t=="string"}import{Readable as Kn}from"stream";import{MailParser as Xn}from"mailparser";import{convert as Jn}from"html-to-text";async function Bt(t){let e=new Xn({skipImageLinks:!0,skipTextToHtml:!0}),n={},r,s,i,a=[],o,d="",c="",u="",p,f=0,m;if(await new Promise((L,R)=>{e.on("headers",w=>{try{for(let[I,v]of w.entries())n[I.toLowerCase()]=Zn(v);r=Ft(w.get("message-id")),o=Ft(w.get("subject")),u=Gt(w.get("content-type"))??"";let U=w.get("date");U instanceof Date&&(p=U.getTime()),s=$t(w.get("from"),"from"),i=Yn(w.get("reply-to"),"reply-to"),a=qt(w.get("to"))}catch(U){m=U instanceof Error?U:new Error(String(U))}}),e.on("data",w=>{if(w.type==="attachment"){f+=1,w.release?.(),w.content?.resume?.();return}d=w.text??"",c=typeof w.html=="string"?w.html:""}),e.on("error",R),e.on("end",L),Kn.from([t]).pipe(e)}),m)throw m;if(!s)throw new Error("Inbound email must contain exactly one valid From address");let l=u.toLowerCase()==="text/html",b=d.trim();return(l||!b)&&c.trim()&&(b=Jn(c,{wordwrap:!1,selectors:[{selector:"h1",format:"heading",options:{uppercase:!1}},{selector:"h2",format:"heading",options:{uppercase:!1}},{selector:"h3",format:"heading",options:{uppercase:!1}},{selector:"h4",format:"heading",options:{uppercase:!1}},{selector:"h5",format:"heading",options:{uppercase:!1}},{selector:"h6",format:"heading",options:{uppercase:!1}}]}).trim()),!b&&o&&(b=o.trim()),{messageId:r,from:s,replyTo:i,to:a,subject:o,text:b,date:p,rawHeaders:n,attachmentCount:f}}function $t(t,e){let n=qt(t);if(n.length!==1){if(n.length===0)return;throw new Error(`Inbound email ${e} must contain exactly one mailbox address`)}return n[0]}function Yn(t,e){if(t)return $t(t,e)}function qt(t){return t?typeof t=="string"?[k(t)]:(t.value??[]).map(r=>r.address).filter(r=>typeof r=="string"&&r.trim().length>0).map(r=>k(r)):[]}function Ft(t){if(typeof t=="string")return t;if(Array.isArray(t))return t.map(String).join(", ")}function Zn(t){if(t instanceof Date)return t.toISOString();if(typeof t=="string")return t;if(Array.isArray(t))return t.map(String).join(", ");let e=Gt(t);return e||(t&&typeof t=="object"&&"text"in t?String(t.text??""):String(t??""))}function Gt(t){if(typeof t=="string")return t;if(t&&typeof t=="object"&&"value"in t){let e=t.value;if(typeof e=="string")return e}}var Wt=3e4,ss=5e3,rs=3e5,is=1.33,as=3e4;function os(t){if(!t||t.length===0)return Wt;let e=0;for(let r of t)try{e+=es(r.path).size}catch{}let n=e*is/(1024*1024);return Math.min(rs,Wt+Math.ceil(n*ss))}var Fe=class{imapClient;smtpTransporter;pollTimer;handlers=[];status={status:"stopped"};state=he();async start(e){if(await this.stop(),!e.enabled){this.status={status:"stopped",details:{reason:"disabled"}};return}this.status={status:"starting",lastStartedAt:Date.now()};try{this.imapClient=new ts({host:e.imap.host,port:e.imap.port,secure:e.imap.secure,auth:{user:e.imap.auth.user,pass:e.imap.auth.pass}}),await this.imapClient.connect();let n=await this.imapClient.mailboxOpen(e.imap.mailbox),r=n?.uidValidity?Number(n.uidValidity):void 0;r&&this.state.uidValidity&&r!==this.state.uidValidity?(this.state={...this.state,uidValidity:r,lastUid:0,seenMessageIds:[]},te(this.state)):r&&(this.state={...this.state,uidValidity:r},te(this.state)),this.smtpTransporter=ns.createTransport({host:e.smtp.host,port:e.smtp.port,secure:e.smtp.secure,auth:{user:e.smtp.auth.user,pass:e.smtp.auth.pass}}),await this.smtpTransporter.verify(),this.status={status:"connected",lastStartedAt:Date.now(),lastCheckedAt:Date.now()},this.schedulePoll(e)}catch(n){throw await this.cleanupResources(),this.status={status:"error",lastError:Be(n),details:{stage:this.smtpTransporter?"smtp":"imap"}},n}}async stop(){await this.cleanupResources(),this.status={status:"stopped"}}getStatus(){return{...this.status}}onInbound(e){this.handlers.push(e)}async send(e){if(!this.smtpTransporter)throw new Error("EmailGateway SMTP transporter is not started");let n=os(e.attachments),r=await ds(this.smtpTransporter.sendMail({from:e.from,to:e.to,subject:e.subject,text:e.text,html:e.html,attachments:e.attachments}),n,`SMTP send timed out after ${Math.round(n/1e3)}s`),s=G(r.messageId);if(!s)throw new Error("SMTP send returned no Message-ID");return this.state=Lt(s),s}isSentByAdam(e){let n=G(e);return n.length>0&&this.state.sentMessageIds.includes(n)}schedulePoll(e){this.pollTimer=setInterval(()=>{this.poll(e)},as)}async poll(e){if(this.imapClient)try{this.state=he();let n=`${this.state.lastUid+1}:*`,r=this.imapClient.fetch?.(n,{uid:!0,source:!0,envelope:!0},{uid:!0});if(!r||!r[Symbol.asyncIterator])return;let s=!1;for await(let i of r){let a=Number(i.uid);if(!Number.isInteger(a)||a<=this.state.lastUid)continue;if(!i.source){this.markDegraded(new Error(`IMAP fetch item ${a} is missing source`)),s=!0;break}let o;try{o=await Bt(i.source)}catch(u){this.markDegraded(u),s=!0;break}let d=o.rawHeaders["x-adam-probe-id"],c=G(o.messageId);if(d?.startsWith("adam-probe-")){this.advanceCursor(a);continue}if(c&&this.state.sentMessageIds.includes(c)){this.advanceCursor(a);continue}if(c&&this.state.seenMessageIds.includes(c)){this.advanceCursor(a);continue}try{await Promise.all(this.handlers.map(u=>u(o)))}catch(u){this.markDegraded(u),s=!0;break}this.state=Dt(this.state,c),this.advanceCursor(a)}s||(this.status={...this.status,status:"connected",lastCheckedAt:Date.now(),lastError:void 0})}catch(n){this.markDegraded(n)}}advanceCursor(e){this.state={...this.state,lastUid:e},te(this.state)}markDegraded(e){this.status={...this.status,status:"degraded",lastError:Be(e),lastCheckedAt:Date.now()}}async cleanupResources(){this.pollTimer&&(clearInterval(this.pollTimer),this.pollTimer=void 0);let e=this.imapClient,n=this.smtpTransporter;this.imapClient=void 0,this.smtpTransporter=void 0,e&&(await Le(e.logout?.()),await Le(e.close?.())),await Le(n?.close?.())}},jt;function S(){return jt??=new Fe,jt}async function ye(t){await S().start(t)}async function jr(t,e){await S().stop(),await S().start(t)}async function Vr(t){await S().stop()}async function ds(t,e,n){let r;try{return await Promise.race([t,new Promise((s,i)=>{r=setTimeout(()=>i(new Error(n)),e)})])}catch(s){throw new Error(Be(s))}finally{r&&clearTimeout(r)}}function Be(t){return t instanceof Error?t.message.replace(/pass(word)?=[^\s]+/gi,"password=****"):"Email gateway operation failed"}async function Le(t){t&&typeof t.then=="function"&&await t.catch(()=>{})}C();var ls=/\b55[234]\b/,ms=/(?:size|too large|exceeds|maximum|over.*?limit)/i,gs=/\b(\d{6,11})\b/,ps=/Final-Recipient:\s*rfc822;\s*([^\s>]+@([^\s>;]+))/i,fs=/To:[\s<]*([^\s>;]+@([^\s>;]+))/i;function Vt(t){let e=t.text??"",n=e.split(/\r?\n/).filter(a=>ls.test(a)&&ms.test(a));if(n.length===0)return null;let r=e.match(ps)??e.match(fs);if(!r)return null;let s=r[2].toLowerCase().trim();if(!je.test(s))return null;let i=null;for(let a of n){let o=a.match(gs);if(o){let d=parseInt(o[1],10);if(Number.isFinite(d)&&d>=1048576&&d<=209715200){i=d;break}}}return i===null?null:{recipientDomain:s,capBytes:i}}var be=y("channels"),zt=!1;function Qt(t){if(zt){be.debug("Bounce handler already registered; skipping duplicate registration");return}zt=!0,t.onInbound(async e=>{let n=Vt(e);if(!n){(/MAILER-DAEMON/i.test(e.from??"")||/Mail Delivery|Undeliverable|Returned mail|Delivery Status Notification/i.test(e.subject??""))&&be.warn({from:e.from,subject:e.subject},"Inbound looks like bounce but parser did not recognize a size-limit cap");return}let{recipientDomain:r,capBytes:s}=n;be.info({recipientDomain:r,capBytes:s},"Bounce-learning: detected SMTP size-limit bounce");let i=F().filter(a=>a.platform==="email");for(let a of i)try{ze(a.id,r,s)}catch(o){be.warn({channelId:a.id,recipientDomain:r,capBytes:s,err:o},"Bounce-learning: setRecipientCap failed (out of range or DB error); skipping")}})}C();var we=y("channels"),$e=class{constructor(e){this.gateway=e}gateway;adaptersByAddress=new Map;channelAddressById=new Map;registerAdapter(e,n){if(!He(e)||!e.enabled)return;let r=B(e);this.unregisterAdapter(e.id),this.adaptersByAddress.set(r,n),this.channelAddressById.set(e.id,r)}unregisterAdapter(e){let n=this.channelAddressById.get(e);n&&(this.adaptersByAddress.delete(n),this.channelAddressById.delete(e))}refreshFromChannels(e,n){this.adaptersByAddress.clear(),this.channelAddressById.clear();for(let r of e){let s=n.get(r.id);if(s)try{this.registerAdapter(r,s)}catch(i){we.warn({channelId:r.id,error:i},"Invalid email channel skipped during router refresh")}}}async handle(e){if(e.messageId&&this.gateway.isSentByAdam(e.messageId)){we.debug({messageId:e.messageId},"Skipping Adam-sent email");return}let n;try{n=k(e.from)}catch(s){we.warn({from:e.from,error:s},"Skipping email with invalid sender address");return}let r=this.adaptersByAddress.get(n);if(!r){we.info({from:n},"Skipping unmatched inbound email");return}await r.acceptInbound(e)}hasAddress(e){return this.adaptersByAddress.has(k(e))}},_e,Ht;function qe(t){return(!_e||Ht!==t)&&(_e=new $e(t),Ht=t,t.onInbound(e=>_e?.handle(e)??Promise.resolve())),_e}import{existsSync as hs}from"fs";import{basename as ys,isAbsolute as bs}from"path";function Kt(t){let e=[];return t.mediaUrl&&e.push({path:t.mediaUrl,mediaType:t.mediaType}),t.attachments&&e.push(...t.attachments),e.map(ws)}function ws(t){let e=t.path.startsWith("file://")?new URL(t.path).pathname:t.path;if(!bs(e)||e.includes("://"))throw new Error("Email attachment path must be an absolute local file path");if(!hs(e))throw new Error(`Email attachment file not found: ${e}`);return{filename:t.filename??ys(e),path:e,...t.contentType?{contentType:t.contentType}:t.mediaType?{contentType:_s(t.mediaType)}:{}}}function _s(t){return"application/octet-stream"}import Is from"markdown-it";var Es=new Is({html:!1,linkify:!0});function Xt(t){return{text:Xe(t),html:Es.render(t)}}function Jt(t){let e=t.prefix.trim()||"Adam";return t.messageType==="report"||t.messageType==="status_report"?`[${e} Report]`:t.messageType==="deliver"||t.messageType==="result_delivery"?`[${e} Deliver]`:`[${e}]`}var Ie=class{platform="email";id;channel;gateway;handler;inboundDispatchHandler;status="disconnected";identity;constructor(e,n,r={}){this.channel=e,this.gateway=n,this.id=e.id,this.identity=r}async connect(){let e=this.gateway.getStatus();this.status=Ee(e.status)}async disconnect(){this.status="disconnected"}getStatus(){return this.status}getCapabilities(){return{canEdit:!1,canQuote:!1,canParseQuote:!1,canInlineButtons:!1,maxTextLength:Number.POSITIVE_INFINITY,supportsAttachments:!0}}async sendMessage(e,n){let r=k(e),s=B(this.channel);if(r!==s)throw new Error("Email channel recipient does not match configured address");let i=Xt(n.content);return this.gateway.send({from:this.identity.from?Ke(this.identity.from,this.identity.displayName):void 0,to:r,subject:Jt({prefix:this.identity.subjectPrefix??"Adam",messageType:n.messageType??"reply"}),text:i.text,html:i.html,attachments:Kt(n)})}onMessage(e){this.handler=e}onInboundDispatch(e){this.inboundDispatchHandler=e}syncGatewayStatus(){this.status=Ee(this.gateway.getStatus().status)}async acceptInbound(e){let n=k(e.from),r={channelId:this.channel.id,platform:"email",chatId:n,senderId:n,senderName:e.from,content:e.text,replyToMessageId:e.messageId,isGroup:!1,timestamp:e.date??Date.now(),raw:{messageId:e.messageId,subject:e.subject,attachmentCount:e.attachmentCount,headers:e.rawHeaders}};this.handler?.(r),this.inboundDispatchHandler&&await this.inboundDispatchHandler(r)}};function Ee(t){switch(t){case"connected":return"connected";case"starting":return"connecting";case"degraded":case"error":return"degraded";case"stopped":return"disconnected";default:return"disconnected"}}var Yt=y("channels"),Ge=new Map;async function W(t,e){if(t.hasAdapter(e.id))return!0;if(e.platform==="wechat"){let n=e.config;return n.botToken?(await t.addChannel(e,new q(e.id,n)),!0):!1}if(e.platform==="discord"){let n=e.config;return n.botToken?(await t.addChannel(e,new fe(e.id,{botToken:n.botToken})),!0):!1}if(e.platform==="email"){B(e);let n=S(),r=V().emailGateway,s=new Ie(e,n,{from:r?.smtp?.from||r?.address,displayName:r?.displayName,subjectPrefix:r?.subjectPrefix??"Adam"});Ge.set(e.id,s),qe(n).registerAdapter(e,s);try{await Ts(),await t.addChannel(e,s)}catch(i){throw await j(t,e),i}return!0}return!1}async function Ei(t){for(let e of F(!0))try{await W(t,e)}catch(n){z(e.id,"error"),Yt.warn({channelId:e.id,platform:e.platform,error:n},"Failed to register built-in channel adapter")}}async function Zt(t,e){e.platform==="email"&&(await j(t,e),e.enabled&&await W(t,e))}async function en(t,e){await j(t,e)}async function j(t,e){e.platform==="email"&&(qe(S()).unregisterAdapter(e.id),Ge.delete(e.id),t?.hasAdapter(e.id)&&await t.removeChannel(e.id))}function Ti(t){for(let[e,n]of Ge.entries())n.syncGatewayStatus(),z(e,n.getStatus())}async function Ts(){let t=V().emailGateway;if(!t?.enabled)return;let e=S().getStatus().status;if(!(e!=="stopped"&&e!=="error"))try{await ye(t),Qt(S())}catch(n){Yt.warn({error:xs(n)},"EmailGateway start failed during built-in adapter registration")}}function xs(t){return t instanceof Error?t.message.replace(/pass(word)?=[^\s]+/gi,"password=****"):"Email gateway operation failed"}var P=g.object({id:g.string().uuid()}),Ss=g.object({name:g.string().min(1,"name is required"),platform:g.string().min(1,"platform is required"),config:g.record(g.string(),g.unknown()),enabled:g.boolean().optional().default(!0),linkedRoleId:g.string().optional(),allowedChatIds:g.array(g.string()).optional()}),Cs=g.object({name:g.string().min(1).optional(),enabled:g.boolean().optional(),config:g.record(g.string(),g.unknown()).optional(),linkedRoleId:g.string().optional(),allowedChatIds:g.array(g.string()).optional(),viewerKey:g.string().min(1).max(100).regex(/^[a-zA-Z0-9_.@:-]+$/,"viewerKey must be alphanumeric or one of _ . @ : -").optional(),defaultRecipientCapBytes:g.number().int().min(1048576).max(209715200).optional(),recipientCapMap:g.record(g.string().regex(/^[a-z0-9.-]+$/),g.number().int().min(1048576).max(209715200)).optional()}),We;function Li(t){We=t}function Fi(){return We}async function Bi(t){let e=We;async function n(r){Ve(r);try{return e&&r.enabled&&await W(e,r),r}catch(s){throw await j(e,r),Te(r.id),s}}t.get("/channels",{schema:{tags:["Channels"],summary:"List channels",querystring:{type:"object",properties:{enabled:{type:"boolean"}}}}},async(r,s)=>({channels:F(r.query.enabled)})),t.post("/channels",{schema:{tags:["Channels"],summary:"Create a channel",body:{type:"object",required:["name","platform","config"],properties:{name:{type:"string",minLength:1},platform:{type:"string",minLength:1},config:{type:"object"},enabled:{type:"boolean"},linkedRoleId:{type:"string"},allowedChatIds:{type:"array",items:{type:"string"}}}}}},async(r,s)=>{let i=Ss.safeParse(r.body);if(!i.success)return s.status(400).send({code:"VALIDATION_ERROR",message:g.prettifyError(i.error)});let{name:a,platform:o,config:d,enabled:c,linkedRoleId:u,allowedChatIds:p}=i.data,f=d;if(o==="email")try{f={...xe(d)}}catch(l){return s.status(400).send({code:"VALIDATION_ERROR",message:l instanceof Error?l.message:String(l)})}let m={id:Ms(),name:a,platform:o,enabled:c,status:"disconnected",config:f,linkedRoleId:u,allowedChatIds:p,viewerKey:Je(),createdAt:Date.now(),messageCount:0};try{await n(m)}catch(l){return s.status(400).send({code:"VALIDATION_ERROR",message:D(l)})}return s.status(201).send({channel:m})}),t.get("/channels/:id",{schema:{tags:["Channels"],summary:"Get channel by ID",params:{type:"object",required:["id"],properties:{id:{type:"string",format:"uuid"}}}}},async(r,s)=>{let i=P.safeParse(r.params);if(!i.success)return s.status(400).send({code:"VALIDATION_ERROR",message:g.prettifyError(i.error)});let a=E(i.data.id);return a?{channel:a}:s.status(404).send({code:"NOT_FOUND",message:"Channel not found"})}),t.patch("/channels/:id",{schema:{tags:["Channels"],summary:"Update channel",params:{type:"object",required:["id"],properties:{id:{type:"string",format:"uuid"}}},body:{type:"object",properties:{name:{type:"string"},enabled:{type:"boolean"},config:{type:"object"},linkedRoleId:{type:"string"},allowedChatIds:{type:"array",items:{type:"string"}},viewerKey:{type:"string",minLength:1,maxLength:100}}}}},async(r,s)=>{let i=P.safeParse(r.params);if(!i.success)return s.status(400).send({code:"VALIDATION_ERROR",message:g.prettifyError(i.error)});let a=E(i.data.id);if(!a)return s.status(404).send({code:"NOT_FOUND",message:"Channel not found"});let o=Cs.safeParse(r.body);if(!o.success)return s.status(400).send({code:"VALIDATION_ERROR",message:g.prettifyError(o.error)});let d={...o.data};if((a.platform==="email"||d.config)&&(d.config||a.config)){let p=d.config??a.config;if(a.platform==="email")try{d.config={...xe(p)}}catch(f){return s.status(400).send({code:"VALIDATION_ERROR",message:f instanceof Error?f.message:String(f)})}}let c=a.platform==="email"&&(d.enabled!==void 0||d.config!==void 0);ne(a.id,d);let u=E(a.id);if(e&&u&&c)try{await Zt(e,u)}catch(p){if(ne(a.id,{name:a.name,enabled:a.enabled,status:a.status,config:a.config,linkedRoleId:a.linkedRoleId,allowedChatIds:a.allowedChatIds,lastMessageAt:a.lastMessageAt,messageCount:a.messageCount}),await j(e,u),a.enabled)try{await W(e,a)}catch(f){return s.status(500).send({code:"RESTORE_FAILED",message:D(f)})}return s.status(400).send({code:"VALIDATION_ERROR",message:D(p)})}return{channel:u}}),t.delete("/channels/:id",{schema:{tags:["Channels"],summary:"Delete channel",params:{type:"object",required:["id"],properties:{id:{type:"string",format:"uuid"}}}}},async(r,s)=>{let i=P.safeParse(r.params);if(!i.success)return s.status(400).send({code:"VALIDATION_ERROR",message:g.prettifyError(i.error)});let a=E(i.data.id);if(!a)return s.status(404).send({code:"NOT_FOUND",message:"Channel not found"});if(Te(a.id),e)try{await en(e,a)}catch(o){t.log.warn({channelId:a.id,error:D(o)},"Failed to clean up built-in channel runtime")}return s.status(204).send()}),t.post("/channels/:id/connect",{schema:{tags:["Channels"],summary:"Connect channel",params:{type:"object",required:["id"],properties:{id:{type:"string",format:"uuid"}}}}},async(r,s)=>{let i=P.safeParse(r.params);if(!i.success)return s.status(400).send({code:"VALIDATION_ERROR",message:g.prettifyError(i.error)});if(!e)return s.status(501).send({code:"NOT_IMPLEMENTED",message:"Channel manager not initialized"});let a=E(i.data.id);if(!a)return s.status(404).send({code:"NOT_FOUND",message:"Channel not found"});if(a.platform==="email")try{await As()}catch(o){let d=S().getStatus();return z(a.id,Ee(d.status)),s.status(409).send({code:"EMAIL_GATEWAY_NOT_READY",message:D(o),gatewayStatus:d})}if(!e.hasAdapter(a.id))try{await W(e,a)}catch(o){return s.status(400).send({code:"VALIDATION_ERROR",message:D(o)})}if(!e.hasAdapter(a.id))return s.status(400).send({code:"NO_ADAPTER",message:"No adapter registered for this channel. Install the appropriate adapter first."});try{await e.connectChannel(a.id);let o=E(a.id)?.status??e.getChannelStatus(a.id);return o!=="connected"?s.status(409).send({code:"CONNECT_INCOMPLETE",message:`Channel connect finished with status "${o}"`,status:o}):{channelId:a.id,status:o}}catch(o){return s.status(500).send({code:"CONNECT_FAILED",message:D(o)})}}),t.post("/channels/:id/disconnect",{schema:{tags:["Channels"],summary:"Disconnect channel",params:{type:"object",required:["id"],properties:{id:{type:"string",format:"uuid"}}}}},async(r,s)=>{let i=P.safeParse(r.params);if(!i.success)return s.status(400).send({code:"VALIDATION_ERROR",message:g.prettifyError(i.error)});if(!e)return s.status(501).send({code:"NOT_IMPLEMENTED",message:"Channel manager not initialized"});let a=E(i.data.id);return a?(await e.disconnectChannel(a.id),{channelId:a.id,status:"disconnected"}):s.status(404).send({code:"NOT_FOUND",message:"Channel not found"})}),t.get("/channels/:id/capabilities",{schema:{tags:["Channels"],summary:"Get channel adapter capabilities",params:{type:"object",required:["id"],properties:{id:{type:"string",format:"uuid"}}}}},async(r,s)=>{let i=P.safeParse(r.params);if(!i.success)return s.status(400).send({code:"VALIDATION_ERROR",message:g.prettifyError(i.error)});if(!E(i.data.id))return s.status(404).send({code:"NOT_FOUND",message:"Channel not found"});if(!e)return s.status(503).send({code:"MANAGER_UNAVAILABLE",message:"ChannelManager not initialized"});let o=e.getCapabilities(i.data.id);return o?{capabilities:o}:s.status(404).send({code:"ADAPTER_NOT_REGISTERED",message:"Channel adapter not active"})}),t.get("/channels/:id/messages",{schema:{tags:["Channels"],summary:"Get channel message history",params:{type:"object",required:["id"],properties:{id:{type:"string",format:"uuid"}}},querystring:{type:"object",properties:{limit:{type:"integer",minimum:1,maximum:200,default:50},offset:{type:"integer",minimum:0,default:0}}}}},async(r,s)=>{let i=P.safeParse(r.params);if(!i.success)return s.status(400).send({code:"VALIDATION_ERROR",message:g.prettifyError(i.error)});let a=E(i.data.id);if(!a)return s.status(404).send({code:"NOT_FOUND",message:"Channel not found"});let{limit:o=50,offset:d=0}=r.query;return{messages:Qe(a.id,o,d)}}),t.post("/channels/:id/wechat/qr-start",{schema:{tags:["WeChat"],summary:"Start WeChat QR login",params:{type:"object",required:["id"],properties:{id:{type:"string",format:"uuid"}}}}},async(r,s)=>{let i=P.safeParse(r.params);if(!i.success)return s.status(400).send({code:"VALIDATION_ERROR",message:g.prettifyError(i.error)});let a=E(i.data.id);if(!a)return s.status(404).send({code:"NOT_FOUND",message:"Channel not found"});if(a.platform!=="wechat")return s.status(400).send({code:"INVALID_PLATFORM",message:"Channel is not a WeChat channel"});let o=a.config;return await at({apiBaseUrl:o.baseUrl,routeTag:o.routeTag})}),t.post("/channels/:id/wechat/qr-wait",{schema:{tags:["WeChat"],summary:"Wait for WeChat QR scan",params:{type:"object",required:["id"],properties:{id:{type:"string",format:"uuid"}}},body:{type:"object",properties:{sessionKey:{type:"string"},timeoutMs:{type:"number"}}}}},async(r,s)=>{let i=P.safeParse(r.params);if(!i.success)return s.status(400).send({code:"VALIDATION_ERROR",message:g.prettifyError(i.error)});let a=E(i.data.id);if(!a)return s.status(404).send({code:"NOT_FOUND",message:"Channel not found"});if(a.platform!=="wechat")return s.status(400).send({code:"INVALID_PLATFORM",message:"Channel is not a WeChat channel"});let o=a.config,{sessionKey:d,timeoutMs:c}=r.body??{},u=await ot({sessionKey:d??"",apiBaseUrl:o.baseUrl,timeoutMs:c??12e4,routeTag:o.routeTag});if(u.connected&&u.botToken){let p={...o,botToken:u.botToken,accountId:u.accountId,baseUrl:u.baseUrl??o.baseUrl,userId:u.userId};if(ne(a.id,{config:p}),e){let f=new q(a.id,p),m=E(a.id);m&&await e.addChannel(m,f)}}return{connected:u.connected,accountId:u.accountId,message:u.message}})}function D(t){return t instanceof Error?t.message.replace(/pass(word)?=[^\s]+/gi,"password=****"):String(t)}async function As(){let t=V().emailGateway;if(!t?.enabled)throw new Error("Email Gateway is disabled. Enable Email Gateway in Settings before connecting Mail channels.");let e=S();e.getStatus().status!=="connected"&&await ye(t);let n=e.getStatus();if(n.status!=="connected"){let r=n.lastError?`: ${n.lastError}`:"";throw new Error(`Email Gateway status is ${n.status}${r}`)}}export{Lt as a,G as b,Bt as c,S as d,jr as e,Vr as f,Ei as g,Ti as h,Li as i,Fi as j,Bi as k};
|
|
1
|
+
import{g as Qe}from"./chunk-QWIBCFPC.js";import{a as He,b as k,c as xe,d as B,e as Ke}from"./chunk-NNMQGISW.js";import{b as Xe,c as Je,f as se,g as re}from"./chunk-32D5GWJD.js";import{a as je,b as Ve,c as E,d as ne,e as F,f as Te,g as z,i as ze}from"./chunk-D5PAJ3CB.js";import{d as V}from"./chunk-OH6VBBDV.js";import{c as y,h as C}from"./chunk-EZLBMUQD.js";import{z as g}from"zod/v4";import{v4 as Ms}from"uuid";import{randomUUID as st}from"crypto";import tn from"crypto";var Ye="2.1.7",ie="bot";function nn(t){let e=t.split(".").map(i=>parseInt(i,10)),n=e[0]??0,r=e[1]??0,s=e[2]??0;return(n&255)<<16|(r&255)<<8|s&255}var Me=nn(Ye),sn=35e3,Ze=15e3,rn=1e4;function ae(){return{channel_version:Ye}}function an(t){return t.endsWith("/")?t:`${t}/`}function on(){let t=tn.randomBytes(4).readUInt32BE(0);return Buffer.from(String(t),"utf-8").toString("base64")}function dn(t){let e={"Content-Type":"application/json",AuthorizationType:"ilink_bot_token","Content-Length":String(Buffer.byteLength(t.body,"utf-8")),"X-WECHAT-UIN":on(),"iLink-App-Id":ie,"iLink-App-ClientVersion":String(Me)};return t.token?.trim()&&(e.Authorization=`Bearer ${t.token.trim()}`),t.routeTag&&(e.SKRouteTag=t.routeTag),e}async function oe(t){let e=an(t.baseUrl),n=new URL(t.endpoint,e),r=dn({token:t.token,routeTag:t.routeTag,body:t.body}),s=new AbortController,i=setTimeout(()=>s.abort(),t.timeoutMs);try{let a=await fetch(n.toString(),{method:"POST",headers:r,body:t.body,signal:s.signal});clearTimeout(i);let o=await a.text();if(!a.ok)throw new Error(`${t.label} ${a.status}: ${o}`);return o}catch(a){throw clearTimeout(i),a}}async function et(t){let e=t.timeoutMs??sn;try{let n=await oe({baseUrl:t.baseUrl,endpoint:"ilink/bot/getupdates",body:JSON.stringify({get_updates_buf:t.get_updates_buf??"",base_info:ae()}),token:t.token,routeTag:t.routeTag,timeoutMs:e,label:"getUpdates"});return JSON.parse(n)}catch(n){if(n instanceof Error&&n.name==="AbortError")return{ret:0,msgs:[],get_updates_buf:t.get_updates_buf};throw n}}var un={[-2]:2,[-3]:3},cn=1e3;async function Q(t){let e=(await import("./logger-TEZSHFTZ.js")).getLogger("channels"),n=new Map;for(;;){let r=await oe({baseUrl:t.baseUrl,endpoint:"ilink/bot/sendmessage",body:JSON.stringify({...t.body,base_info:ae()}),token:t.token,routeTag:t.routeTag,timeoutMs:t.timeoutMs??Ze,label:"sendMessage"});e.info({status:200,responseBody:r.slice(0,300)},"apiFetch sendMessage response");try{let s=JSON.parse(r);if(s.ret&&s.ret!==0){let i=un[s.ret],a=(n.get(s.ret)??0)+1;if(n.set(s.ret,a),i!==void 0&&a<i){e.warn({ret:s.ret,attempt:a,maxRetries:i},"sendMessage: retriable iLink error, retrying"),await new Promise(o=>setTimeout(o,cn*a));continue}throw e.error({ret:s.ret,errmsg:s.errmsg,attempt:a},"sendMessage: iLink API error, no more retries"),new Error(`sendMessage failed: iLink ret=${s.ret}${s.errmsg?` errmsg=${s.errmsg}`:""}`)}}catch(s){if(s instanceof SyntaxError)e.warn({rawText:r.slice(0,200)},"sendMessage: non-JSON response, treating as success");else throw s}return}}async function tt(t){await oe({baseUrl:t.baseUrl,endpoint:"ilink/bot/sendtyping",body:JSON.stringify({...t.body,base_info:ae()}),token:t.token,routeTag:t.routeTag,timeoutMs:t.timeoutMs??rn,label:"sendTyping"})}async function nt(t){let e=await oe({baseUrl:t.baseUrl,endpoint:"ilink/bot/getuploadurl",body:JSON.stringify({filekey:t.filekey,media_type:t.media_type,to_user_id:t.to_user_id,rawsize:t.rawsize,rawfilemd5:t.rawfilemd5,filesize:t.filesize,thumb_rawsize:t.thumb_rawsize,thumb_rawfilemd5:t.thumb_rawfilemd5,thumb_filesize:t.thumb_filesize,no_need_thumb:t.no_need_thumb,aeskey:t.aeskey,base_info:ae()}),token:t.token,routeTag:t.routeTag,timeoutMs:t.timeoutMs??Ze,label:"getUploadUrl"});return JSON.parse(e)}var ln=5*6e4,mn=35e3,rt="3",T=new Map;function Se(t){return Date.now()-t.startedAt<ln}function gn(){for(let[t,e]of T)Se(e)||T.delete(t)}async function it(t,e,n){let r=t.endsWith("/")?t:`${t}/`,s=new URL(`ilink/bot/get_bot_qrcode?bot_type=${encodeURIComponent(e)}`,r),i={"iLink-App-Id":ie};n&&(i.SKRouteTag=n);let a=await fetch(s.toString(),{headers:i});if(!a.ok){let o=await a.text().catch(()=>"(unreadable)");throw new Error(`Failed to fetch QR code: ${a.status} ${a.statusText} body=${o}`)}return await a.json()}async function pn(t,e,n){let r=t.endsWith("/")?t:`${t}/`,s=new URL(`ilink/bot/get_qrcode_status?qrcode=${encodeURIComponent(e)}`,r),i={"iLink-App-Id":ie,"iLink-App-ClientVersion":String(Me)};n&&(i.SKRouteTag=n);let a=new AbortController,o=setTimeout(()=>a.abort(),mn);try{let d=await fetch(s.toString(),{headers:i,signal:a.signal});clearTimeout(o);let c=await d.text();if(!d.ok)throw new Error(`Failed to poll QR status: ${d.status} ${d.statusText}`);return JSON.parse(c)}catch(d){if(clearTimeout(o),d instanceof Error&&d.name==="AbortError")return{status:"wait"};throw d}}async function at(t){let e=t.accountId||st();gn();let n=T.get(e);if(!t.force&&n&&Se(n)&&n.qrcodeUrl)return{qrcodeUrl:n.qrcodeUrl,message:"QR code ready. Scan with WeChat.",sessionKey:e};if(!t.apiBaseUrl)return{message:"No baseUrl configured for this WeChat channel.",sessionKey:e};try{let r=t.botType||rt,s=await it(t.apiBaseUrl,r,t.routeTag),i={sessionKey:e,id:st(),qrcode:s.qrcode,qrcodeUrl:s.qrcode_img_content,startedAt:Date.now()};return T.set(e,i),{qrcodeUrl:s.qrcode_img_content,message:"Scan the QR code with WeChat to connect.",sessionKey:e}}catch(r){return{message:`Failed to start login: ${String(r)}`,sessionKey:e}}}var fn=3;async function ot(t){let e=T.get(t.sessionKey);if(!e)return{connected:!1,message:"No active login session. Start QR login first."};if(!Se(e))return T.delete(t.sessionKey),{connected:!1,message:"QR code expired. Please start again."};let n=Math.max(t.timeoutMs??48e4,1e3),r=Date.now()+n,s=1;for(;Date.now()<r;){try{let i=await pn(t.apiBaseUrl,e.qrcode,t.routeTag);switch(e.status=i.status,i.status){case"wait":break;case"scaned":break;case"expired":{if(s++,s>fn)return T.delete(t.sessionKey),{connected:!1,message:"Login timeout: QR expired multiple times."};try{let a=t.botType||rt,o=await it(t.apiBaseUrl,a,t.routeTag);e.qrcode=o.qrcode,e.qrcodeUrl=o.qrcode_img_content,e.startedAt=Date.now()}catch(a){return T.delete(t.sessionKey),{connected:!1,message:`QR refresh failed: ${String(a)}`}}break}case"confirmed":return i.ilink_bot_id?(T.delete(t.sessionKey),{connected:!0,botToken:i.bot_token,accountId:i.ilink_bot_id,baseUrl:i.baseurl,userId:i.ilink_user_id,message:"Connected to WeChat successfully!"}):(T.delete(t.sessionKey),{connected:!1,message:"Login failed: server did not return bot ID."})}}catch(i){return T.delete(t.sessionKey),{connected:!1,message:`Login failed: ${String(i)}`}}await new Promise(i=>setTimeout(i,1e3))}return T.delete(t.sessionKey),{connected:!1,message:"Login timeout. Please try again."}}import A from"fs";import*as M from"fs/promises";import x from"path";import{homedir as pe}from"os";var de={IMAGE:1,VIDEO:2,FILE:3,VOICE:4},H={NONE:0,USER:1,BOT:2},_={NONE:0,TEXT:1,IMAGE:2,VOICE:3,FILE:4,VIDEO:5},K={NEW:0,GENERATING:1,FINISH:2},dt={TYPING:1,CANCEL:2};C();var hn=y("channels"),Ce=-14,ue=3600*1e3,$=new Map;function ut(t){let e=Date.now()+ue;$.set(t,e),hn.info({channelId:t},`Session paused until ${new Date(e).toISOString()} (${ue/1e3}s)`)}function ce(t){let e=$.get(t);return e===void 0?!1:Date.now()>=e?($.delete(t),!1):!0}function ct(t){let e=$.get(t);if(e===void 0)return 0;let n=e-Date.now();return n<=0?($.delete(t),0):n}function lt(t){$.delete(t)}C();import*as me from"fs/promises";import _t from"path";import{homedir as In}from"os";import{createCipheriv as yn,createDecipheriv as bn}from"crypto";function mt(t,e){let n=yn("aes-128-ecb",e,null);return Buffer.concat([n.update(t),n.final()])}function gt(t,e){let n=bn("aes-128-ecb",e,null);return Buffer.concat([n.update(t),n.final()])}function pt(t){return Math.ceil((t+1)/16)*16}function Ae(t,e){return`${e}/download?encrypted_query_param=${encodeURIComponent(t)}`}function ft(t){return`${t.cdnBaseUrl}/upload?encrypted_query_param=${encodeURIComponent(t.uploadParam)}&filekey=${encodeURIComponent(t.filekey)}`}C();var Ws=y("channels");function wn(t){let e=Buffer.from(t,"base64");if(e.length===16)return e;if(e.length===32&&/^[0-9a-fA-F]{32}$/.test(e.toString("ascii")))return Buffer.from(e.toString("ascii"),"hex");throw new Error(`aes_key must decode to 16 raw bytes or 32-char hex, got ${e.length} bytes`)}async function ht(t){let e=await fetch(t);if(!e.ok)throw new Error(`CDN download ${e.status} ${e.statusText}`);return Buffer.from(await e.arrayBuffer())}async function X(t){let{encryptQueryParam:e,aesKeyBase64:n,cdnBaseUrl:r,fullUrl:s}=t,i=wn(n),a=s?.trim()||(e?Ae(e,r):null);if(!a)throw new Error("CDN download: need full_url or encrypt_query_param");let o=await ht(a);return gt(o,i)}async function yt(t){let{encryptQueryParam:e,cdnBaseUrl:n,fullUrl:r}=t,s=r?.trim()||(e?Ae(e,n):null);if(!s)throw new Error("CDN download: need full_url or encrypt_query_param");return ht(s)}C();var le=y("channels"),bt=24e3;function _n(t,e){let n=t.byteLength,r=44+n,s=Buffer.allocUnsafe(r),i=0;return s.write("RIFF",i),i+=4,s.writeUInt32LE(r-8,i),i+=4,s.write("WAVE",i),i+=4,s.write("fmt ",i),i+=4,s.writeUInt32LE(16,i),i+=4,s.writeUInt16LE(1,i),i+=2,s.writeUInt16LE(1,i),i+=2,s.writeUInt32LE(e,i),i+=4,s.writeUInt32LE(e*2,i),i+=4,s.writeUInt16LE(2,i),i+=2,s.writeUInt16LE(16,i),i+=2,s.write("data",i),i+=4,s.writeUInt32LE(n,i),i+=4,Buffer.from(t.buffer,t.byteOffset,t.byteLength).copy(s,i),s}async function wt(t){try{let{decode:e}=await import("silk-wasm");le.debug(`silkToWav: decoding ${t.length} bytes of SILK`);let n=await e(t,bt);le.debug(`silkToWav: decoded duration=${n.duration}ms pcmBytes=${n.data.byteLength}`);let r=_n(n.data,bt);return le.debug(`silkToWav: WAV size=${r.length}`),r}catch(e){return le.warn(`silkToWav: transcode failed, will use raw silk err=${String(e)}`),null}}var N=y("channels"),It=100*1024*1024;function En(t){return re(t)??".bin"}async function J(t,e,n,r,s=It,i){if(t.length>s)throw new Error(`Media too large: ${t.length} bytes exceeds ${s} bytes`);let a=_t.join(In(),".adam","wechat","media",r,n);await me.mkdir(a,{recursive:!0});let o;if(i&&/^[a-zA-Z0-9._-]+$/.test(i))o=i;else{let c=e?En(e):".bin",u=Date.now(),p=Math.random().toString(36).slice(2,7);o=`${u}-${p}${c}`}let d=_t.join(a,o);return await me.writeFile(d,t),N.debug(`saveMedia: saved ${t.length} bytes to ${d}`),d}async function Et(t,e){let{cdnBaseUrl:n,channelId:r}=e;if(t.type===_.IMAGE){let s=t.image_item;if(!s?.media?.encrypt_query_param&&!s?.media?.full_url)return null;let i=s.aeskey?Buffer.from(s.aeskey,"hex").toString("base64"):s.media?.aes_key;try{let a=i?await X({encryptQueryParam:s.media?.encrypt_query_param,aesKeyBase64:i,cdnBaseUrl:n,fullUrl:s.media?.full_url}):await yt({encryptQueryParam:s.media?.encrypt_query_param,cdnBaseUrl:n,fullUrl:s.media?.full_url});return{path:await J(a,"image/png","inbound",r),mimeType:"image/png",type:"image"}}catch(a){return N.error({channelId:r},`Image download/decrypt failed: ${String(a)}`),null}}if(t.type===_.VOICE){let s=t.voice_item;if(!s?.media?.encrypt_query_param&&!s?.media?.full_url||!s?.media?.aes_key)return null;try{let i=await X({encryptQueryParam:s.media.encrypt_query_param,aesKeyBase64:s.media.aes_key,cdnBaseUrl:n,fullUrl:s.media.full_url}),a=await wt(i);if(a){let o=await J(a,"audio/wav","inbound",r);return N.debug(`Voice: saved WAV to ${o}`),{path:o,mimeType:"audio/wav",type:"audio"}}else{let o=await J(i,"audio/silk","inbound",r);return N.debug(`Voice: silk transcode unavailable, saved raw SILK to ${o}`),{path:o,mimeType:"audio/silk",type:"audio"}}}catch(i){return N.error({channelId:r},`Voice download/transcode failed: ${String(i)}`),null}}if(t.type===_.FILE){let s=t.file_item;if(!s?.media?.encrypt_query_param&&!s?.media?.full_url||!s?.media?.aes_key)return null;try{let i=await X({encryptQueryParam:s.media.encrypt_query_param,aesKeyBase64:s.media.aes_key,cdnBaseUrl:n,fullUrl:s.media.full_url}),a=se(s.file_name??"file.bin");return{path:await J(i,a,"inbound",r,It,s.file_name),mimeType:a,type:"file"}}catch(i){return N.error({channelId:r},`File download failed: ${String(i)}`),null}}if(t.type===_.VIDEO){let s=t.video_item;if(!s?.media?.encrypt_query_param&&!s?.media?.full_url||!s?.media?.aes_key)return null;try{let i=await X({encryptQueryParam:s.media.encrypt_query_param,aesKeyBase64:s.media.aes_key,cdnBaseUrl:n,fullUrl:s.media.full_url});return{path:await J(i,"video/mp4","inbound",r),mimeType:"video/mp4",type:"video"}}catch(i){return N.error({channelId:r},`Video download failed: ${String(i)}`),null}}return null}import Mt from"path";import Re from"crypto";import Tn from"fs/promises";C();var O=y("channels"),ge=3;async function xn(t){let{buf:e,uploadFullUrl:n,uploadParam:r,filekey:s,cdnBaseUrl:i,label:a,aeskey:o}=t,d=mt(e,o),c=n?.trim(),u;if(c)u=c;else if(r)u=ft({cdnBaseUrl:i,uploadParam:r,filekey:s});else throw new Error(`${a}: CDN upload URL missing (need upload_full_url or upload_param)`);O.debug(`${a}: CDN POST url=${u} ciphertextSize=${d.length}`);let p,f;for(let m=1;m<=ge;m++)try{let l=await fetch(u,{method:"POST",headers:{"Content-Type":"application/octet-stream"},body:new Uint8Array(d)});if(l.status>=400&&l.status<500){let b=l.headers.get("x-error-message")??await l.text();throw O.error(`${a}: CDN client error attempt=${m} status=${l.status} errMsg=${b}`),new Error(`CDN upload client error ${l.status}: ${b}`)}if(l.status!==200){let b=l.headers.get("x-error-message")??`status ${l.status}`;throw O.error(`${a}: CDN server error attempt=${m} status=${l.status} errMsg=${b}`),new Error(`CDN upload server error: ${b}`)}if(p=l.headers.get("x-encrypted-param")??void 0,!p)throw O.error(`${a}: CDN response missing x-encrypted-param header attempt=${m}`),new Error("CDN upload response missing x-encrypted-param header");O.debug(`${a}: CDN upload success attempt=${m}`);break}catch(l){if(f=l,l instanceof Error&&l.message.includes("client error"))throw l;m<ge?O.warn(`${a}: attempt ${m} failed, retrying... err=${String(l)}`):O.error(`${a}: all ${ge} attempts failed err=${String(l)}`)}if(!p)throw f instanceof Error?f:new Error(`CDN upload failed after ${ge} attempts`);return{downloadParam:p}}async function ke(t){let{filePath:e,toUserId:n,opts:r,cdnBaseUrl:s,mediaType:i,label:a}=t,o=await Tn.readFile(e),d=o.length,c=Re.createHash("md5").update(o).digest("hex"),u=pt(d),p=Re.randomBytes(16).toString("hex"),f=Re.randomBytes(16);O.debug(`${a}: file=${e} rawsize=${d} filesize=${u} md5=${c} filekey=${p}`);let m=await nt({...r,filekey:p,media_type:i,to_user_id:n,rawsize:d,rawfilemd5:c,filesize:u,no_need_thumb:!0,aeskey:f.toString("hex")}),l=m.upload_full_url?.trim(),b=m.upload_param;if(!l&&!b)throw new Error(`${a}: getUploadUrl returned no upload URL (need upload_full_url or upload_param)`);let{downloadParam:L}=await xn({buf:o,uploadFullUrl:l||void 0,uploadParam:b??void 0,filekey:p,cdnBaseUrl:s,aeskey:f,label:`${a}[orig filekey=${p}]`});return{filekey:p,downloadEncryptedQueryParam:L,aeskey:f.toString("hex"),fileSize:d,fileSizeCiphertext:u}}async function Tt(t){return ke({...t,mediaType:de.IMAGE,label:"uploadImageToWeixin"})}async function xt(t){return ke({...t,mediaType:de.VIDEO,label:"uploadVideoToWeixin"})}async function Pe(t){return ke({...t,mediaType:de.FILE,label:"uploadFileAttachmentToWeixin"})}C();var Y=y("channels");function Mn(){return`adam-wechat-${Date.now()}-${Math.random().toString(36).slice(2,7)}`}function Sn(t){let e=t;return e=e.replace(/```[^\n]*\n?([\s\S]*?)```/g,(n,r)=>r.trim()),e=e.replace(/!\[[^\]]*\]\([^)]*\)/g,""),e=e.replace(/\[([^\]]+)\]\([^)]*\)/g,"$1"),e=e.replace(/^\|[\s:|-]+\|$/gm,""),e=e.replace(/^\|(.+)\|$/gm,(n,r)=>r.split("|").map(s=>s.trim()).join(" ")),e}async function Ue(t){let{to:e,text:n,mediaItem:r,opts:s,label:i}=t,a=[],o=Sn(n);o&&a.push({type:_.TEXT,text_item:{text:o}}),a.push(r);let d="";for(let c of a){d=Mn();let u={msg:{from_user_id:"",to_user_id:e,client_id:d,message_type:H.BOT,message_state:K.FINISH,item_list:[c],context_token:s.contextToken}};await Q({baseUrl:s.baseUrl,token:s.token,routeTag:s.routeTag,body:u})}return Y.debug(`${i}: sent to=${e} messageId=${d}`),{messageId:d}}async function Cn(t){let{to:e,text:n,uploaded:r,opts:s}=t,i={type:_.IMAGE,image_item:{media:{encrypt_query_param:r.downloadEncryptedQueryParam,aes_key:Buffer.from(r.aeskey).toString("base64"),encrypt_type:1},mid_size:r.fileSizeCiphertext}};return Ue({to:e,text:n,mediaItem:i,opts:s,label:"sendImageMessage"})}async function An(t){let{to:e,text:n,uploaded:r,opts:s}=t,i={type:_.VIDEO,video_item:{media:{encrypt_query_param:r.downloadEncryptedQueryParam,aes_key:Buffer.from(r.aeskey).toString("base64"),encrypt_type:1},video_size:r.fileSizeCiphertext}};return Ue({to:e,text:n,mediaItem:i,opts:s,label:"sendVideoMessage"})}async function St(t){let{to:e,text:n,fileName:r,uploaded:s,opts:i}=t,a={type:_.FILE,file_item:{media:{encrypt_query_param:s.downloadEncryptedQueryParam,aes_key:Buffer.from(s.aeskey).toString("base64"),encrypt_type:1},file_name:r,len:String(s.fileSize)}};return Ue({to:e,text:n,mediaItem:a,opts:i,label:"sendFileMessage"})}async function Ct(t){let{filePath:e,to:n,text:r,opts:s,cdnBaseUrl:i}=t,a=se(e),o={baseUrl:s.baseUrl,token:s.token,routeTag:s.routeTag};if(a.startsWith("video/")){Y.debug(`sendWeixinMediaFile: uploading video filePath=${e} to=${n}`);let u=await xt({filePath:e,toUserId:n,opts:o,cdnBaseUrl:i});return An({to:n,text:r,uploaded:u,opts:s})}if(a.startsWith("image/")){Y.debug(`sendWeixinMediaFile: uploading image filePath=${e} to=${n}`);let u=await Tt({filePath:e,toUserId:n,opts:o,cdnBaseUrl:i});return Cn({to:n,text:r,uploaded:u,opts:s})}if(a.startsWith("audio/")){let u=Mt.basename(e);Y.debug(`sendWeixinMediaFile: uploading audio as file filePath=${e} name=${u} to=${n}`);let p=await Pe({filePath:e,fileName:u,toUserId:n,opts:o,cdnBaseUrl:i});return St({to:n,text:r,fileName:u,uploaded:p,opts:s})}let d=Mt.basename(e);Y.debug(`sendWeixinMediaFile: uploading file attachment filePath=${e} name=${d} to=${n}`);let c=await Pe({filePath:e,fileName:d,toUserId:n,opts:o,cdnBaseUrl:i});return St({to:n,text:r,fileName:d,uploaded:c,opts:s})}C();var h=y("channels"),At="https://novac2c.cdn.weixin.qq.com/c2c",Ne=new Map;function Pt(t){return x.join(pe(),".adam","wechat",`${t}.context-tokens.json`)}function Rn(t){let e=Pt(t);try{let n=A.readFileSync(e,"utf-8"),r=JSON.parse(n);for(let[s,i]of Object.entries(r))typeof i=="string"&&i&&Ne.set(`${t}:${s}`,i);h.debug({channelId:t,count:Object.keys(r).length},"Restored context tokens from disk")}catch{}}function kn(t,e,n){let r=Pt(t);try{let s={};try{let a=A.readFileSync(r,"utf-8");s=JSON.parse(a)}catch{}s[e]=n;let i=x.dirname(r);A.mkdirSync(i,{recursive:!0}),A.writeFileSync(r,JSON.stringify(s),"utf-8")}catch(s){h.warn({channelId:t,userId:e},`Failed to persist context token: ${String(s)}`)}}function Pn(t,e,n){Ne.set(`${t}:${e}`,n),kn(t,e,n)}function ve(t,e){return Ne.get(`${t}:${e}`)}function Ut(t){return x.join(pe(),".adam","wechat",`${t}.sync`)}function Un(t){try{return A.readFileSync(Ut(t),"utf-8")}catch{return""}}function vn(t,e){let n=Ut(t);A.mkdirSync(x.dirname(n),{recursive:!0}),A.writeFileSync(n,e,"utf-8")}var Oe=1440*60*1e3,Rt=10,On=20,kt=1440*60*1e3,Nn=1320*60*1e3,Dn=1,Ln=7200*1e3;function vt(t){return x.join(pe(),".adam","wechat",`${t}.session.json`)}function Fn(t){let e=new Map,n=vt(t);try{let r=A.readFileSync(n,"utf-8"),s=JSON.parse(r);for(let[i,a]of Object.entries(s))a&&typeof a.lastUserMessageAt=="number"&&e.set(i,a);h.debug({channelId:t,count:e.size},"Restored sessions from disk")}catch{}return e}function Z(t,e){let n=vt(t);try{let r={};for(let[i,a]of e)r[i]=a;let s=x.dirname(n);A.mkdirSync(s,{recursive:!0}),A.writeFileSync(n,JSON.stringify(r),"utf-8")}catch(r){h.warn({channelId:t},`Failed to persist sessions: ${String(r)}`)}}var Bn=0;function ee(){return`adam-wechat-${Date.now()}-${++Bn}`}var q=class{platform="wechat";id;config;status="disconnected";messageHandler=null;pollAbort=null;getUpdatesBuf="";sessions=new Map;pendingQueue=new Map;lastReminderAt=new Map;constructor(e,n){if(this.id=e,!n.baseUrl)throw new Error("WeChat adapter requires baseUrl");this.config=n}async connect(){if(!this.config.botToken)throw new Error("WeChat adapter requires botToken. Complete QR login first.");this.status="connecting",this.getUpdatesBuf=Un(this.id),Rn(this.id),this.sessions=Fn(this.id),this.pollAbort=new AbortController,this.status="connected",h.info({channelId:this.id},"WeChat adapter connected, starting long-poll"),this.startLongPoll()}async disconnect(){this.pollAbort&&(this.pollAbort.abort(),this.pollAbort=null),this.status="disconnected",h.info({channelId:this.id},"WeChat adapter disconnected")}getStatus(){if(this.status==="connected"&&ce(this.id))return"error";if(this.status==="connected"){for(let[,e]of this.sessions)if(this.isSessionActive(e)&&e.quotaRemaining<=0)return"degraded"}return this.status}getCapabilities(){return{canEdit:!1,canQuote:!0,canParseQuote:!0,canInlineButtons:!1,maxTextLength:4e3,supportsAttachments:!0,maxAttachmentsPerMessage:1}}async sendMessage(e,n){if(ce(this.id)){let c=Math.ceil(ct(this.id)/6e4);throw new Error(`WeChat session paused, ${c} min remaining. Re-scan QR to reconnect.`)}let r=this.getOrCreateSession(e),i=this.getSessionRemainingMs(r)/36e5;if(!this.isSessionActive(r))return h.warn({channelId:this.id,chatId:e.slice(0,12),lastUserMessageAt:r.lastUserMessageAt,sessionExpired:!0},"iLink session expired (>24h), message queued"),this.enqueueMessage(e,n),`queued-${ee()}`;if(r.quotaRemaining<=0)return h.warn({channelId:this.id,chatId:e.slice(0,12),quotaRemaining:0,remainingHours:i.toFixed(1)},"iLink quota exhausted, message queued"),this.enqueueMessage(e,n),`queued-${ee()}`;let a=ee(),o=ve(this.id,e),d=this.config.cdnBaseUrl??At;try{let c=n.attachments?.[0],u=c?.path??n.mediaUrl,p=c?.contentType,f=c?.filename,m=c?.mediaType??n.mediaType;if(u){let l=!u.includes("://")||u.startsWith("file://"),b=x.join(pe(),".adam","wechat","media","outbound-tmp");await M.mkdir(b,{recursive:!0});let L=this.getExtensionFromMediaType(m,p),R;if(l){let I=u.startsWith("file://")?new URL(u).pathname:x.isAbsolute(u)?u:x.resolve(u),v=await M.readFile(I);R=x.join(b,`${Date.now()}-${Math.random().toString(36).slice(2,7)}${L}`),await M.writeFile(R,v)}else{let I=await fetch(u);if(!I.ok)throw new Error(`Failed to fetch media: ${I.status}`);let v=Buffer.from(await I.arrayBuffer());R=x.join(b,`${Date.now()}-${Math.random().toString(36).slice(2,7)}${L}`),await M.writeFile(R,v)}let w=R;if(f){let I=f.replace(/[\\/]/g,"-").replace(/\.\./g,"-").replace(/[\x00-\x1f]/g,"");if(I.length>0&&I.length<200){let v=x.join(b,`${Date.now()}-${I}`);await M.copyFile(R,v),await M.unlink(R).catch(()=>{}),w=v}}let U=await Ct({filePath:w,to:e,text:n.content??"",opts:{baseUrl:this.config.baseUrl,token:this.config.botToken,routeTag:this.config.routeTag,contextToken:o},cdnBaseUrl:d});return await M.unlink(w).catch(()=>{}),r.quotaRemaining--,Z(this.id,this.sessions),h.info({channelId:this.id,chatId:e.slice(0,12),quotaRemaining:r.quotaRemaining,sessionRemainingHours:(this.getSessionRemainingMs(r)/36e5).toFixed(1)},"iLink send success: quota decremented"),this.checkAndSendReminder(e,r).catch(I=>{h.warn({channelId:this.id,chatId:e.slice(0,12)},`Reminder send failed: ${String(I)}`)}),U.messageId}return await Q({baseUrl:this.config.baseUrl,token:this.config.botToken,routeTag:this.config.routeTag,body:{msg:{from_user_id:"",to_user_id:e,client_id:a,message_type:H.BOT,message_state:K.FINISH,item_list:this.buildItemList(n),context_token:o}}}),r.quotaRemaining--,Z(this.id,this.sessions),h.info({channelId:this.id,chatId:e.slice(0,12),quotaRemaining:r.quotaRemaining,sessionRemainingHours:(this.getSessionRemainingMs(r)/36e5).toFixed(1)},"iLink send success: quota decremented"),this.checkAndSendReminder(e,r).catch(l=>{h.warn({channelId:this.id,chatId:e.slice(0,12)},`Reminder send failed: ${String(l)}`)}),a}catch(c){if(c instanceof Error&&c.message.includes("ret=-2"))return r.quotaRemaining=0,Z(this.id,this.sessions),h.warn({channelId:this.id,chatId:e.slice(0,12),quotaRemaining:0},"iLink quota exhausted (ret=-2 confirmed), message queued"),this.enqueueMessage(e,n),`queued-${ee()}`;throw c}}onMessage(e){this.messageHandler=e}async sendTypingIndicator(e){if(ce(this.id))return;let n=ve(this.id,e);try{await tt({baseUrl:this.config.baseUrl,token:this.config.botToken,routeTag:this.config.routeTag,body:{ilink_user_id:e,status:dt.TYPING}})}catch{}}updateConfig(e){Object.assign(this.config,e)}buildItemList(e){if(!e.content)return;let n={type:_.TEXT,text_item:{text:e.content}};if(e.replyToMessageId){let r=(e.quoteExcerpt??"").slice(0,80);n.ref_msg={message_item:{msg_id:e.replyToMessageId,text_item:{text:r}},title:e.quoteTitle}}return[n]}getOrCreateSession(e){let n=this.sessions.get(e);return n||(n={lastUserMessageAt:0,quotaRemaining:0},this.sessions.set(e,n)),n}isSessionActive(e){return e.lastUserMessageAt>0&&Date.now()-e.lastUserMessageAt<=Oe}getSessionRemainingMs(e){return e.lastUserMessageAt===0?0:Math.max(0,Oe-(Date.now()-e.lastUserMessageAt))}enqueueMessage(e,n){let r=this.pendingQueue.get(e);r||(r=[],this.pendingQueue.set(e,r));let s=Date.now();r=r.filter(i=>s-i.queuedAt<kt),r.length>=On&&(r.shift(),h.warn({channelId:this.id,chatId:e.slice(0,12)},"Queue full, dropping oldest message")),r.push({message:n,queuedAt:s}),this.pendingQueue.set(e,r),h.info({channelId:this.id,chatId:e.slice(0,12),queueDepth:r.length},"Message enqueued")}async flushQueue(e){let n=this.pendingQueue.get(e);if(!n||n.length===0)return;let r=this.getOrCreateSession(e),s=Math.min(n.length,Math.max(0,r.quotaRemaining-2));if(s<=0){h.info({channelId:this.id,chatId:e.slice(0,12),quotaRemaining:r.quotaRemaining},"Queue flush skipped: insufficient quota (reserving 2 for conversation)");return}h.info({channelId:this.id,chatId:e.slice(0,12),queueDepth:n.length,sending:s,quotaRemaining:r.quotaRemaining},"Flushing queued messages");let i=0;for(;i<s&&n.length>0;){let a=n[0];if(Date.now()-a.queuedAt>kt){n.shift();continue}try{if(await this.sendMessage(e,a.message),n.shift(),i++,r.quotaRemaining<=0)break}catch{h.warn({channelId:this.id,chatId:e.slice(0,12)},"Queue flush: send failed, stopping");break}}n.length===0&&this.pendingQueue.delete(e),h.info({channelId:this.id,chatId:e.slice(0,12),sent:i,remaining:n.length},"Queue flush complete")}async checkAndSendReminder(e,n){let r=Date.now(),s=this.lastReminderAt.get(e)??0;if(r-s<Ln)return;let i=this.getSessionRemainingMs(n),o=r-n.lastUserMessageAt>=Nn,d=n.quotaRemaining<=Dn;if(!o&&!d)return;let c=(i/36e5).toFixed(1),u;o&&d?u=`[\u7CFB\u7EDF\u63D0\u9192] \u6D88\u606F\u7A97\u53E3\u5373\u5C06\u5173\u95ED\uFF08\u5269\u4F59${c}\u5C0F\u65F6/${n.quotaRemaining}\u6761\u914D\u989D\uFF09\u3002\u8BF7\u56DE\u590D\u4EFB\u610F\u6D88\u606F\u4EE5\u4FDD\u6301\u8FDE\u63A5\u3002`:o?u=`[\u7CFB\u7EDF\u63D0\u9192] \u6D88\u606F\u7A97\u53E3\u5373\u5C06\u5173\u95ED\uFF08\u5269\u4F59${c}\u5C0F\u65F6\uFF09\u3002\u8BF7\u56DE\u590D\u4EFB\u610F\u6D88\u606F\u4EE5\u4FDD\u6301\u8FDE\u63A5\u3002`:u=`[\u7CFB\u7EDF\u63D0\u9192] \u6D88\u606F\u914D\u989D\u5373\u5C06\u7528\u5B8C\uFF08\u5269\u4F59${n.quotaRemaining}\u6761\uFF09\u3002\u8BF7\u56DE\u590D\u4EFB\u610F\u6D88\u606F\u4EE5\u91CD\u7F6E\u914D\u989D\u3002`;let p=ve(this.id,e);try{await Q({baseUrl:this.config.baseUrl,token:this.config.botToken,routeTag:this.config.routeTag,body:{msg:{from_user_id:"",to_user_id:e,client_id:ee(),message_type:H.BOT,message_state:K.FINISH,item_list:[{type:_.TEXT,text_item:{text:u}}],context_token:p}}}),n.quotaRemaining--,this.lastReminderAt.set(e,r),Z(this.id,this.sessions),h.info({channelId:this.id,chatId:e.slice(0,12),remainingHours:c,quotaRemaining:n.quotaRemaining,trigger:o?"time":"quota"},"iLink session reminder sent")}catch(f){h.warn({channelId:this.id,chatId:e.slice(0,12)},`Reminder send failed: ${String(f)}`)}}async startLongPoll(){let e=this.pollAbort?.signal,n=0,r=3,s=3e4,i=2e3;for(;!e?.aborted;)try{let a=await et({baseUrl:this.config.baseUrl,token:this.config.botToken,routeTag:this.config.routeTag,get_updates_buf:this.getUpdatesBuf});if(a.ret===Ce||a.errcode===Ce){ut(this.id),this.status="error",h.error({channelId:this.id},"Session expired (errcode=-14), pausing for 1 hour"),await this.sleep(ue,e),lt(this.id),this.status="connected";continue}if(a.ret!==void 0&&a.ret!==0||a.errcode!==void 0&&a.errcode!==0){n++,h.error({channelId:this.id,ret:a.ret,errcode:a.errcode},"getUpdates API error"),n>=r?(n=0,await this.sleep(s,e)):await this.sleep(i,e);continue}n=0,a.get_updates_buf&&(this.getUpdatesBuf=a.get_updates_buf,vn(this.id,a.get_updates_buf));for(let d of a.msgs??[])await this.processInbound(d)}catch(a){if(e?.aborted)return;n++,h.error({channelId:this.id,error:a},"getUpdates error"),n>=r?(n=0,await this.sleep(s,e)):await this.sleep(i,e)}}async processInbound(e){if(!this.messageHandler)return;let n=!!e.group_id,r=n?e.group_id:e.from_user_id??"",s=e.from_user_id??"";e.context_token&&r&&Pn(this.id,r,e.context_token);let i=this.getOrCreateSession(r),a=i.quotaRemaining;i.lastUserMessageAt=Date.now(),i.quotaRemaining=Rt,Z(this.id,this.sessions),h.info({channelId:this.id,chatId:r.slice(0,12),quotaReset:!0,prevQuota:a,newQuota:Rt,sessionWindowMs:Oe},"iLink session reset: user message received, quota restored"),this.flushQueue(r);let o="",d,c=[],u;for(let m of e.item_list??[]){let l=m.ref_msg?.message_item?.msg_id;if(l){u=l;break}}for(let m of e.item_list??[])m.type===_.TEXT&&m.text_item?.text&&(o+=m.text_item.text),m.type===_.IMAGE&&(d="image",c.push(m)),m.type===_.VOICE&&(d="audio",c.push(m),m.voice_item?.text&&!o&&(o=m.voice_item.text)),m.type===_.FILE&&(d="file",c.push(m)),m.type===_.VIDEO&&(d="video",c.push(m));if(!o&&!d)return;let p;if(c.length>0){let m=this.config.cdnBaseUrl??At;try{let l=await Et(c[0],{cdnBaseUrl:m,channelId:this.id});l&&(p=l.path,d=l.type)}catch(l){h.error({channelId:this.id},`Media download failed: ${String(l)}`)}}let f={channelId:this.id,platform:"wechat",chatId:r,senderId:s,content:o,mediaType:d,mediaPath:p,isGroup:n,timestamp:e.create_time_ms??Date.now(),raw:e,...u?{quotedPlatformMessageId:u}:{}};this.messageHandler(f)}getExtensionFromMediaType(e,n){if(n){let r=re(n);if(r&&r!==".bin")return r}switch(e){case"image":return".png";case"video":return".mp4";case"audio":return".mp3";default:return".bin"}}sleep(e,n){return new Promise((r,s)=>{let i=setTimeout(r,e);n?.addEventListener("abort",()=>{clearTimeout(i),s(new Error("aborted"))},{once:!0})})}};C();C();var $n=y("channels"),fe=class{platform="discord";id;config;status="disconnected";messageHandler=null;client=null;constructor(e,n){if(this.id=e,!n.botToken)throw new Error("Discord adapter requires botToken");this.config=n}async connect(){this.status="connecting";try{let{Client:e,GatewayIntentBits:n}=await import("discord.js");this.client=new e({intents:[n.Guilds,n.GuildMessages,n.MessageContent,n.DirectMessages]});let r=this.client;r.on("messageCreate",s=>{if(!this.messageHandler||s.author.bot||this.config.allowedGuildIds?.length&&s.guildId&&!this.config.allowedGuildIds.includes(s.guildId))return;let i={channelId:this.id,platform:"discord",chatId:s.channelId,senderId:s.author.id,senderName:s.author.displayName??s.author.username,content:s.content,isGroup:!!s.guildId,timestamp:s.createdTimestamp,raw:s};this.messageHandler(i)}),await r.login(this.config.botToken),this.status="connected",$n.info({channelId:this.id},"Discord bot connected")}catch(e){throw this.status="error",e}}async disconnect(){this.client&&await this.client.destroy(),this.client=null,this.status="disconnected"}getStatus(){return this.status}getCapabilities(){return{canEdit:!0,canQuote:!0,canParseQuote:!0,canInlineButtons:!0,maxTextLength:2e3,supportsAttachments:!0}}async sendMessage(e,n){if(!this.client)throw new Error("Discord client not connected");let s=await this.client.channels.fetch(e);if(!s||!("send"in s))throw new Error(`Channel ${e} not found or not text channel`);return(await s.send({content:n.content,reply:n.replyToMessageId?{messageReference:n.replyToMessageId}:void 0})).id}onMessage(e){this.messageHandler=e}async sendTypingIndicator(e){if(!this.client)return;let r=await this.client.channels.fetch(e);r&&"sendTyping"in r&&await r.sendTyping()}};import{statSync as es}from"fs";import{ImapFlow as ts}from"imapflow";import ns from"nodemailer";import{existsSync as qn,mkdirSync as Gn,readFileSync as Wn,writeFileSync as jn}from"fs";import{dirname as Vn,join as Ot}from"path";import{homedir as zn}from"os";var Qn={lastUid:0,seenMessageIds:[],sentMessageIds:[],updatedAt:0};function De(t=process.env.ADAM_TEST_DIR??Ot(zn(),".adam")){return Ot(t,"email-gateway","state.json")}function he(t=De()){if(!qn(t))return{...Qn};let e=JSON.parse(Wn(t,"utf-8"));return{uidValidity:e.uidValidity,lastUid:Number.isInteger(e.lastUid)?e.lastUid:0,seenMessageIds:Array.isArray(e.seenMessageIds)?e.seenMessageIds.filter(Nt):[],sentMessageIds:Array.isArray(e.sentMessageIds)?e.sentMessageIds.filter(Nt):[],updatedAt:typeof e.updatedAt=="number"?e.updatedAt:0}}function te(t,e=De()){Gn(Vn(e),{recursive:!0}),jn(e,JSON.stringify({...t,updatedAt:Date.now()},null,2),"utf-8")}function Dt(t,e){let n=G(e);return n?{...t,seenMessageIds:t.seenMessageIds.includes(n)?t.seenMessageIds:[...t.seenMessageIds,n]}:t}function Hn(t,e){let n=G(e);return n?{...t,sentMessageIds:t.sentMessageIds.includes(n)?t.sentMessageIds:[...t.sentMessageIds,n]}:t}function Lt(t,e=De()){let n=Hn(he(e),t);return te(n,e),n}function G(t){return typeof t=="string"?t.trim():""}function Nt(t){return typeof t=="string"}import{Readable as Kn}from"stream";import{MailParser as Xn}from"mailparser";import{convert as Jn}from"html-to-text";async function Bt(t){let e=new Xn({skipImageLinks:!0,skipTextToHtml:!0}),n={},r,s,i,a=[],o,d="",c="",u="",p,f=0,m;if(await new Promise((L,R)=>{e.on("headers",w=>{try{for(let[I,v]of w.entries())n[I.toLowerCase()]=Zn(v);r=Ft(w.get("message-id")),o=Ft(w.get("subject")),u=Gt(w.get("content-type"))??"";let U=w.get("date");U instanceof Date&&(p=U.getTime()),s=$t(w.get("from"),"from"),i=Yn(w.get("reply-to"),"reply-to"),a=qt(w.get("to"))}catch(U){m=U instanceof Error?U:new Error(String(U))}}),e.on("data",w=>{if(w.type==="attachment"){f+=1,w.release?.(),w.content?.resume?.();return}d=w.text??"",c=typeof w.html=="string"?w.html:""}),e.on("error",R),e.on("end",L),Kn.from([t]).pipe(e)}),m)throw m;if(!s)throw new Error("Inbound email must contain exactly one valid From address");let l=u.toLowerCase()==="text/html",b=d.trim();return(l||!b)&&c.trim()&&(b=Jn(c,{wordwrap:!1,selectors:[{selector:"h1",format:"heading",options:{uppercase:!1}},{selector:"h2",format:"heading",options:{uppercase:!1}},{selector:"h3",format:"heading",options:{uppercase:!1}},{selector:"h4",format:"heading",options:{uppercase:!1}},{selector:"h5",format:"heading",options:{uppercase:!1}},{selector:"h6",format:"heading",options:{uppercase:!1}}]}).trim()),!b&&o&&(b=o.trim()),{messageId:r,from:s,replyTo:i,to:a,subject:o,text:b,date:p,rawHeaders:n,attachmentCount:f}}function $t(t,e){let n=qt(t);if(n.length!==1){if(n.length===0)return;throw new Error(`Inbound email ${e} must contain exactly one mailbox address`)}return n[0]}function Yn(t,e){if(t)return $t(t,e)}function qt(t){return t?typeof t=="string"?[k(t)]:(t.value??[]).map(r=>r.address).filter(r=>typeof r=="string"&&r.trim().length>0).map(r=>k(r)):[]}function Ft(t){if(typeof t=="string")return t;if(Array.isArray(t))return t.map(String).join(", ")}function Zn(t){if(t instanceof Date)return t.toISOString();if(typeof t=="string")return t;if(Array.isArray(t))return t.map(String).join(", ");let e=Gt(t);return e||(t&&typeof t=="object"&&"text"in t?String(t.text??""):String(t??""))}function Gt(t){if(typeof t=="string")return t;if(t&&typeof t=="object"&&"value"in t){let e=t.value;if(typeof e=="string")return e}}var Wt=3e4,ss=5e3,rs=3e5,is=1.33,as=3e4;function os(t){if(!t||t.length===0)return Wt;let e=0;for(let r of t)try{e+=es(r.path).size}catch{}let n=e*is/(1024*1024);return Math.min(rs,Wt+Math.ceil(n*ss))}var Fe=class{imapClient;smtpTransporter;pollTimer;handlers=[];status={status:"stopped"};state=he();async start(e){if(await this.stop(),!e.enabled){this.status={status:"stopped",details:{reason:"disabled"}};return}this.status={status:"starting",lastStartedAt:Date.now()};try{this.imapClient=new ts({host:e.imap.host,port:e.imap.port,secure:e.imap.secure,auth:{user:e.imap.auth.user,pass:e.imap.auth.pass}}),await this.imapClient.connect();let n=await this.imapClient.mailboxOpen(e.imap.mailbox),r=n?.uidValidity?Number(n.uidValidity):void 0;r&&this.state.uidValidity&&r!==this.state.uidValidity?(this.state={...this.state,uidValidity:r,lastUid:0,seenMessageIds:[]},te(this.state)):r&&(this.state={...this.state,uidValidity:r},te(this.state)),this.smtpTransporter=ns.createTransport({host:e.smtp.host,port:e.smtp.port,secure:e.smtp.secure,auth:{user:e.smtp.auth.user,pass:e.smtp.auth.pass}}),await this.smtpTransporter.verify(),this.status={status:"connected",lastStartedAt:Date.now(),lastCheckedAt:Date.now()},this.schedulePoll(e)}catch(n){throw await this.cleanupResources(),this.status={status:"error",lastError:Be(n),details:{stage:this.smtpTransporter?"smtp":"imap"}},n}}async stop(){await this.cleanupResources(),this.status={status:"stopped"}}getStatus(){return{...this.status}}onInbound(e){this.handlers.push(e)}async send(e){if(!this.smtpTransporter)throw new Error("EmailGateway SMTP transporter is not started");let n=os(e.attachments),r=await ds(this.smtpTransporter.sendMail({from:e.from,to:e.to,subject:e.subject,text:e.text,html:e.html,attachments:e.attachments}),n,`SMTP send timed out after ${Math.round(n/1e3)}s`),s=G(r.messageId);if(!s)throw new Error("SMTP send returned no Message-ID");return this.state=Lt(s),s}isSentByAdam(e){let n=G(e);return n.length>0&&this.state.sentMessageIds.includes(n)}schedulePoll(e){this.pollTimer=setInterval(()=>{this.poll(e)},as)}async poll(e){if(this.imapClient)try{this.state=he();let n=`${this.state.lastUid+1}:*`,r=this.imapClient.fetch?.(n,{uid:!0,source:!0,envelope:!0},{uid:!0});if(!r||!r[Symbol.asyncIterator])return;let s=!1;for await(let i of r){let a=Number(i.uid);if(!Number.isInteger(a)||a<=this.state.lastUid)continue;if(!i.source){this.markDegraded(new Error(`IMAP fetch item ${a} is missing source`)),s=!0;break}let o;try{o=await Bt(i.source)}catch(u){this.markDegraded(u),s=!0;break}let d=o.rawHeaders["x-adam-probe-id"],c=G(o.messageId);if(d?.startsWith("adam-probe-")){this.advanceCursor(a);continue}if(c&&this.state.sentMessageIds.includes(c)){this.advanceCursor(a);continue}if(c&&this.state.seenMessageIds.includes(c)){this.advanceCursor(a);continue}try{await Promise.all(this.handlers.map(u=>u(o)))}catch(u){this.markDegraded(u),s=!0;break}this.state=Dt(this.state,c),this.advanceCursor(a)}s||(this.status={...this.status,status:"connected",lastCheckedAt:Date.now(),lastError:void 0})}catch(n){this.markDegraded(n)}}advanceCursor(e){this.state={...this.state,lastUid:e},te(this.state)}markDegraded(e){this.status={...this.status,status:"degraded",lastError:Be(e),lastCheckedAt:Date.now()}}async cleanupResources(){this.pollTimer&&(clearInterval(this.pollTimer),this.pollTimer=void 0);let e=this.imapClient,n=this.smtpTransporter;this.imapClient=void 0,this.smtpTransporter=void 0,e&&(await Le(e.logout?.()),await Le(e.close?.())),await Le(n?.close?.())}},jt;function S(){return jt??=new Fe,jt}async function ye(t){await S().start(t)}async function jr(t,e){await S().stop(),await S().start(t)}async function Vr(t){await S().stop()}async function ds(t,e,n){let r;try{return await Promise.race([t,new Promise((s,i)=>{r=setTimeout(()=>i(new Error(n)),e)})])}catch(s){throw new Error(Be(s))}finally{r&&clearTimeout(r)}}function Be(t){return t instanceof Error?t.message.replace(/pass(word)?=[^\s]+/gi,"password=****"):"Email gateway operation failed"}async function Le(t){t&&typeof t.then=="function"&&await t.catch(()=>{})}C();var ls=/\b55[234]\b/,ms=/(?:size|too large|exceeds|maximum|over.*?limit)/i,gs=/\b(\d{6,11})\b/,ps=/Final-Recipient:\s*rfc822;\s*([^\s>]+@([^\s>;]+))/i,fs=/To:[\s<]*([^\s>;]+@([^\s>;]+))/i;function Vt(t){let e=t.text??"",n=e.split(/\r?\n/).filter(a=>ls.test(a)&&ms.test(a));if(n.length===0)return null;let r=e.match(ps)??e.match(fs);if(!r)return null;let s=r[2].toLowerCase().trim();if(!je.test(s))return null;let i=null;for(let a of n){let o=a.match(gs);if(o){let d=parseInt(o[1],10);if(Number.isFinite(d)&&d>=1048576&&d<=209715200){i=d;break}}}return i===null?null:{recipientDomain:s,capBytes:i}}var be=y("channels"),zt=!1;function Qt(t){if(zt){be.debug("Bounce handler already registered; skipping duplicate registration");return}zt=!0,t.onInbound(async e=>{let n=Vt(e);if(!n){(/MAILER-DAEMON/i.test(e.from??"")||/^no-reply@mailsupport\.aliyun\.com$/i.test(e.from??"")||/Mail Delivery|Undeliverable|Returned mail|Delivery Status Notification|退信|无法投递|投递失败/i.test(e.subject??""))&&be.warn({from:e.from,subject:e.subject},"Inbound looks like bounce but parser did not recognize a size-limit cap");return}let{recipientDomain:r,capBytes:s}=n;be.info({recipientDomain:r,capBytes:s},"Bounce-learning: detected SMTP size-limit bounce");let i=F().filter(a=>a.platform==="email");for(let a of i)try{ze(a.id,r,s)}catch(o){be.warn({channelId:a.id,recipientDomain:r,capBytes:s,err:o},"Bounce-learning: setRecipientCap failed (out of range or DB error); skipping")}})}C();var we=y("channels"),$e=class{constructor(e){this.gateway=e}gateway;adaptersByAddress=new Map;channelAddressById=new Map;registerAdapter(e,n){if(!He(e)||!e.enabled)return;let r=B(e);this.unregisterAdapter(e.id),this.adaptersByAddress.set(r,n),this.channelAddressById.set(e.id,r)}unregisterAdapter(e){let n=this.channelAddressById.get(e);n&&(this.adaptersByAddress.delete(n),this.channelAddressById.delete(e))}refreshFromChannels(e,n){this.adaptersByAddress.clear(),this.channelAddressById.clear();for(let r of e){let s=n.get(r.id);if(s)try{this.registerAdapter(r,s)}catch(i){we.warn({channelId:r.id,error:i},"Invalid email channel skipped during router refresh")}}}async handle(e){if(e.messageId&&this.gateway.isSentByAdam(e.messageId)){we.debug({messageId:e.messageId},"Skipping Adam-sent email");return}let n;try{n=k(e.from)}catch(s){we.warn({from:e.from,error:s},"Skipping email with invalid sender address");return}let r=this.adaptersByAddress.get(n);if(!r){we.info({from:n},"Skipping unmatched inbound email");return}await r.acceptInbound(e)}hasAddress(e){return this.adaptersByAddress.has(k(e))}},_e,Ht;function qe(t){return(!_e||Ht!==t)&&(_e=new $e(t),Ht=t,t.onInbound(e=>_e?.handle(e)??Promise.resolve())),_e}import{existsSync as hs}from"fs";import{basename as ys,isAbsolute as bs}from"path";function Kt(t){let e=[];return t.mediaUrl&&e.push({path:t.mediaUrl,mediaType:t.mediaType}),t.attachments&&e.push(...t.attachments),e.map(ws)}function ws(t){let e=t.path.startsWith("file://")?new URL(t.path).pathname:t.path;if(!bs(e)||e.includes("://"))throw new Error("Email attachment path must be an absolute local file path");if(!hs(e))throw new Error(`Email attachment file not found: ${e}`);return{filename:t.filename??ys(e),path:e,...t.contentType?{contentType:t.contentType}:t.mediaType?{contentType:_s(t.mediaType)}:{}}}function _s(t){return"application/octet-stream"}import Is from"markdown-it";var Es=new Is({html:!1,linkify:!0});function Xt(t){return{text:Xe(t),html:Es.render(t)}}function Jt(t){let e=t.prefix.trim()||"Adam";return t.messageType==="report"||t.messageType==="status_report"?`[${e} Report]`:t.messageType==="deliver"||t.messageType==="result_delivery"?`[${e} Deliver]`:`[${e}]`}var Ie=class{platform="email";id;channel;gateway;handler;inboundDispatchHandler;status="disconnected";identity;constructor(e,n,r={}){this.channel=e,this.gateway=n,this.id=e.id,this.identity=r}async connect(){let e=this.gateway.getStatus();this.status=Ee(e.status)}async disconnect(){this.status="disconnected"}getStatus(){return this.status}getCapabilities(){return{canEdit:!1,canQuote:!1,canParseQuote:!1,canInlineButtons:!1,maxTextLength:Number.POSITIVE_INFINITY,supportsAttachments:!0}}async sendMessage(e,n){let r=k(e),s=B(this.channel);if(r!==s)throw new Error("Email channel recipient does not match configured address");let i=Xt(n.content);return this.gateway.send({from:this.identity.from?Ke(this.identity.from,this.identity.displayName):void 0,to:r,subject:Jt({prefix:this.identity.subjectPrefix??"Adam",messageType:n.messageType??"reply"}),text:i.text,html:i.html,attachments:Kt(n)})}onMessage(e){this.handler=e}onInboundDispatch(e){this.inboundDispatchHandler=e}syncGatewayStatus(){this.status=Ee(this.gateway.getStatus().status)}async acceptInbound(e){let n=k(e.from),r={channelId:this.channel.id,platform:"email",chatId:n,senderId:n,senderName:e.from,content:e.text,replyToMessageId:e.messageId,isGroup:!1,timestamp:e.date??Date.now(),raw:{messageId:e.messageId,subject:e.subject,attachmentCount:e.attachmentCount,headers:e.rawHeaders}};this.handler?.(r),this.inboundDispatchHandler&&await this.inboundDispatchHandler(r)}};function Ee(t){switch(t){case"connected":return"connected";case"starting":return"connecting";case"degraded":case"error":return"degraded";case"stopped":return"disconnected";default:return"disconnected"}}var Yt=y("channels"),Ge=new Map;async function W(t,e){if(t.hasAdapter(e.id))return!0;if(e.platform==="wechat"){let n=e.config;return n.botToken?(await t.addChannel(e,new q(e.id,n)),!0):!1}if(e.platform==="discord"){let n=e.config;return n.botToken?(await t.addChannel(e,new fe(e.id,{botToken:n.botToken})),!0):!1}if(e.platform==="email"){B(e);let n=S(),r=V().emailGateway,s=new Ie(e,n,{from:r?.smtp?.from||r?.address,displayName:r?.displayName,subjectPrefix:r?.subjectPrefix??"Adam"});Ge.set(e.id,s),qe(n).registerAdapter(e,s);try{await Ts(),await t.addChannel(e,s)}catch(i){throw await j(t,e),i}return!0}return!1}async function Ei(t){for(let e of F(!0))try{await W(t,e)}catch(n){z(e.id,"error"),Yt.warn({channelId:e.id,platform:e.platform,error:n},"Failed to register built-in channel adapter")}}async function Zt(t,e){e.platform==="email"&&(await j(t,e),e.enabled&&await W(t,e))}async function en(t,e){await j(t,e)}async function j(t,e){e.platform==="email"&&(qe(S()).unregisterAdapter(e.id),Ge.delete(e.id),t?.hasAdapter(e.id)&&await t.removeChannel(e.id))}function Ti(t){for(let[e,n]of Ge.entries())n.syncGatewayStatus(),z(e,n.getStatus())}async function Ts(){let t=V().emailGateway;if(!t?.enabled)return;let e=S().getStatus().status;if(!(e!=="stopped"&&e!=="error"))try{await ye(t),Qt(S())}catch(n){Yt.warn({error:xs(n)},"EmailGateway start failed during built-in adapter registration")}}function xs(t){return t instanceof Error?t.message.replace(/pass(word)?=[^\s]+/gi,"password=****"):"Email gateway operation failed"}var P=g.object({id:g.string().uuid()}),Ss=g.object({name:g.string().min(1,"name is required"),platform:g.string().min(1,"platform is required"),config:g.record(g.string(),g.unknown()),enabled:g.boolean().optional().default(!0),linkedRoleId:g.string().optional(),allowedChatIds:g.array(g.string()).optional()}),Cs=g.object({name:g.string().min(1).optional(),enabled:g.boolean().optional(),config:g.record(g.string(),g.unknown()).optional(),linkedRoleId:g.string().optional(),allowedChatIds:g.array(g.string()).optional(),viewerKey:g.string().min(1).max(100).regex(/^[a-zA-Z0-9_.@:-]+$/,"viewerKey must be alphanumeric or one of _ . @ : -").optional(),defaultRecipientCapBytes:g.number().int().min(1048576).max(209715200).optional(),recipientCapMap:g.record(g.string().regex(/^[a-z0-9.-]+$/),g.number().int().min(1048576).max(209715200)).optional()}),We;function Li(t){We=t}function Fi(){return We}async function Bi(t){let e=We;async function n(r){Ve(r);try{return e&&r.enabled&&await W(e,r),r}catch(s){throw await j(e,r),Te(r.id),s}}t.get("/channels",{schema:{tags:["Channels"],summary:"List channels",querystring:{type:"object",properties:{enabled:{type:"boolean"}}}}},async(r,s)=>({channels:F(r.query.enabled)})),t.post("/channels",{schema:{tags:["Channels"],summary:"Create a channel",body:{type:"object",required:["name","platform","config"],properties:{name:{type:"string",minLength:1},platform:{type:"string",minLength:1},config:{type:"object"},enabled:{type:"boolean"},linkedRoleId:{type:"string"},allowedChatIds:{type:"array",items:{type:"string"}}}}}},async(r,s)=>{let i=Ss.safeParse(r.body);if(!i.success)return s.status(400).send({code:"VALIDATION_ERROR",message:g.prettifyError(i.error)});let{name:a,platform:o,config:d,enabled:c,linkedRoleId:u,allowedChatIds:p}=i.data,f=d;if(o==="email")try{f={...xe(d)}}catch(l){return s.status(400).send({code:"VALIDATION_ERROR",message:l instanceof Error?l.message:String(l)})}let m={id:Ms(),name:a,platform:o,enabled:c,status:"disconnected",config:f,linkedRoleId:u,allowedChatIds:p,viewerKey:Je(),createdAt:Date.now(),messageCount:0};try{await n(m)}catch(l){return s.status(400).send({code:"VALIDATION_ERROR",message:D(l)})}return s.status(201).send({channel:m})}),t.get("/channels/:id",{schema:{tags:["Channels"],summary:"Get channel by ID",params:{type:"object",required:["id"],properties:{id:{type:"string",format:"uuid"}}}}},async(r,s)=>{let i=P.safeParse(r.params);if(!i.success)return s.status(400).send({code:"VALIDATION_ERROR",message:g.prettifyError(i.error)});let a=E(i.data.id);return a?{channel:a}:s.status(404).send({code:"NOT_FOUND",message:"Channel not found"})}),t.patch("/channels/:id",{schema:{tags:["Channels"],summary:"Update channel",params:{type:"object",required:["id"],properties:{id:{type:"string",format:"uuid"}}},body:{type:"object",properties:{name:{type:"string"},enabled:{type:"boolean"},config:{type:"object"},linkedRoleId:{type:"string"},allowedChatIds:{type:"array",items:{type:"string"}},viewerKey:{type:"string",minLength:1,maxLength:100}}}}},async(r,s)=>{let i=P.safeParse(r.params);if(!i.success)return s.status(400).send({code:"VALIDATION_ERROR",message:g.prettifyError(i.error)});let a=E(i.data.id);if(!a)return s.status(404).send({code:"NOT_FOUND",message:"Channel not found"});let o=Cs.safeParse(r.body);if(!o.success)return s.status(400).send({code:"VALIDATION_ERROR",message:g.prettifyError(o.error)});let d={...o.data};if((a.platform==="email"||d.config)&&(d.config||a.config)){let p=d.config??a.config;if(a.platform==="email")try{d.config={...xe(p)}}catch(f){return s.status(400).send({code:"VALIDATION_ERROR",message:f instanceof Error?f.message:String(f)})}}let c=a.platform==="email"&&(d.enabled!==void 0||d.config!==void 0);ne(a.id,d);let u=E(a.id);if(e&&u&&c)try{await Zt(e,u)}catch(p){if(ne(a.id,{name:a.name,enabled:a.enabled,status:a.status,config:a.config,linkedRoleId:a.linkedRoleId,allowedChatIds:a.allowedChatIds,lastMessageAt:a.lastMessageAt,messageCount:a.messageCount}),await j(e,u),a.enabled)try{await W(e,a)}catch(f){return s.status(500).send({code:"RESTORE_FAILED",message:D(f)})}return s.status(400).send({code:"VALIDATION_ERROR",message:D(p)})}return{channel:u}}),t.delete("/channels/:id",{schema:{tags:["Channels"],summary:"Delete channel",params:{type:"object",required:["id"],properties:{id:{type:"string",format:"uuid"}}}}},async(r,s)=>{let i=P.safeParse(r.params);if(!i.success)return s.status(400).send({code:"VALIDATION_ERROR",message:g.prettifyError(i.error)});let a=E(i.data.id);if(!a)return s.status(404).send({code:"NOT_FOUND",message:"Channel not found"});if(Te(a.id),e)try{await en(e,a)}catch(o){t.log.warn({channelId:a.id,error:D(o)},"Failed to clean up built-in channel runtime")}return s.status(204).send()}),t.post("/channels/:id/connect",{schema:{tags:["Channels"],summary:"Connect channel",params:{type:"object",required:["id"],properties:{id:{type:"string",format:"uuid"}}}}},async(r,s)=>{let i=P.safeParse(r.params);if(!i.success)return s.status(400).send({code:"VALIDATION_ERROR",message:g.prettifyError(i.error)});if(!e)return s.status(501).send({code:"NOT_IMPLEMENTED",message:"Channel manager not initialized"});let a=E(i.data.id);if(!a)return s.status(404).send({code:"NOT_FOUND",message:"Channel not found"});if(a.platform==="email")try{await As()}catch(o){let d=S().getStatus();return z(a.id,Ee(d.status)),s.status(409).send({code:"EMAIL_GATEWAY_NOT_READY",message:D(o),gatewayStatus:d})}if(!e.hasAdapter(a.id))try{await W(e,a)}catch(o){return s.status(400).send({code:"VALIDATION_ERROR",message:D(o)})}if(!e.hasAdapter(a.id))return s.status(400).send({code:"NO_ADAPTER",message:"No adapter registered for this channel. Install the appropriate adapter first."});try{await e.connectChannel(a.id);let o=E(a.id)?.status??e.getChannelStatus(a.id);return o!=="connected"?s.status(409).send({code:"CONNECT_INCOMPLETE",message:`Channel connect finished with status "${o}"`,status:o}):{channelId:a.id,status:o}}catch(o){return s.status(500).send({code:"CONNECT_FAILED",message:D(o)})}}),t.post("/channels/:id/disconnect",{schema:{tags:["Channels"],summary:"Disconnect channel",params:{type:"object",required:["id"],properties:{id:{type:"string",format:"uuid"}}}}},async(r,s)=>{let i=P.safeParse(r.params);if(!i.success)return s.status(400).send({code:"VALIDATION_ERROR",message:g.prettifyError(i.error)});if(!e)return s.status(501).send({code:"NOT_IMPLEMENTED",message:"Channel manager not initialized"});let a=E(i.data.id);return a?(await e.disconnectChannel(a.id),{channelId:a.id,status:"disconnected"}):s.status(404).send({code:"NOT_FOUND",message:"Channel not found"})}),t.get("/channels/:id/capabilities",{schema:{tags:["Channels"],summary:"Get channel adapter capabilities",params:{type:"object",required:["id"],properties:{id:{type:"string",format:"uuid"}}}}},async(r,s)=>{let i=P.safeParse(r.params);if(!i.success)return s.status(400).send({code:"VALIDATION_ERROR",message:g.prettifyError(i.error)});if(!E(i.data.id))return s.status(404).send({code:"NOT_FOUND",message:"Channel not found"});if(!e)return s.status(503).send({code:"MANAGER_UNAVAILABLE",message:"ChannelManager not initialized"});let o=e.getCapabilities(i.data.id);return o?{capabilities:o}:s.status(404).send({code:"ADAPTER_NOT_REGISTERED",message:"Channel adapter not active"})}),t.get("/channels/:id/messages",{schema:{tags:["Channels"],summary:"Get channel message history",params:{type:"object",required:["id"],properties:{id:{type:"string",format:"uuid"}}},querystring:{type:"object",properties:{limit:{type:"integer",minimum:1,maximum:200,default:50},offset:{type:"integer",minimum:0,default:0}}}}},async(r,s)=>{let i=P.safeParse(r.params);if(!i.success)return s.status(400).send({code:"VALIDATION_ERROR",message:g.prettifyError(i.error)});let a=E(i.data.id);if(!a)return s.status(404).send({code:"NOT_FOUND",message:"Channel not found"});let{limit:o=50,offset:d=0}=r.query;return{messages:Qe(a.id,o,d)}}),t.post("/channels/:id/wechat/qr-start",{schema:{tags:["WeChat"],summary:"Start WeChat QR login",params:{type:"object",required:["id"],properties:{id:{type:"string",format:"uuid"}}}}},async(r,s)=>{let i=P.safeParse(r.params);if(!i.success)return s.status(400).send({code:"VALIDATION_ERROR",message:g.prettifyError(i.error)});let a=E(i.data.id);if(!a)return s.status(404).send({code:"NOT_FOUND",message:"Channel not found"});if(a.platform!=="wechat")return s.status(400).send({code:"INVALID_PLATFORM",message:"Channel is not a WeChat channel"});let o=a.config;return await at({apiBaseUrl:o.baseUrl,routeTag:o.routeTag})}),t.post("/channels/:id/wechat/qr-wait",{schema:{tags:["WeChat"],summary:"Wait for WeChat QR scan",params:{type:"object",required:["id"],properties:{id:{type:"string",format:"uuid"}}},body:{type:"object",properties:{sessionKey:{type:"string"},timeoutMs:{type:"number"}}}}},async(r,s)=>{let i=P.safeParse(r.params);if(!i.success)return s.status(400).send({code:"VALIDATION_ERROR",message:g.prettifyError(i.error)});let a=E(i.data.id);if(!a)return s.status(404).send({code:"NOT_FOUND",message:"Channel not found"});if(a.platform!=="wechat")return s.status(400).send({code:"INVALID_PLATFORM",message:"Channel is not a WeChat channel"});let o=a.config,{sessionKey:d,timeoutMs:c}=r.body??{},u=await ot({sessionKey:d??"",apiBaseUrl:o.baseUrl,timeoutMs:c??12e4,routeTag:o.routeTag});if(u.connected&&u.botToken){let p={...o,botToken:u.botToken,accountId:u.accountId,baseUrl:u.baseUrl??o.baseUrl,userId:u.userId};if(ne(a.id,{config:p}),e){let f=new q(a.id,p),m=E(a.id);m&&await e.addChannel(m,f)}}return{connected:u.connected,accountId:u.accountId,message:u.message}})}function D(t){return t instanceof Error?t.message.replace(/pass(word)?=[^\s]+/gi,"password=****"):String(t)}async function As(){let t=V().emailGateway;if(!t?.enabled)throw new Error("Email Gateway is disabled. Enable Email Gateway in Settings before connecting Mail channels.");let e=S();e.getStatus().status!=="connected"&&await ye(t);let n=e.getStatus();if(n.status!=="connected"){let r=n.lastError?`: ${n.lastError}`:"";throw new Error(`Email Gateway status is ${n.status}${r}`)}}export{Lt as a,G as b,Bt as c,S as d,jr as e,Vr as f,Ei as g,Ti as h,Li as i,Fi as j,Bi as k};
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import{d as D}from"./chunk-
|
|
1
|
+
import{d as D}from"./chunk-OII5SDMS.js";import{a as b}from"./chunk-4N5G7ND2.js";import{f as v}from"./chunk-QWIBCFPC.js";import{g as O}from"./chunk-UAF4KNXE.js";import{a as S,b as P,c,d as I,e as w,f as C,g as M}from"./chunk-DCTNMUQ5.js";import{b as y}from"./chunk-SJTIMT5U.js";import{b as R}from"./chunk-PBKZDNNV.js";import{s as k}from"./chunk-3R7VGMAK.js";import{a as f}from"./chunk-L7JP7DUO.js";import{b as h,p as B}from"./chunk-P76VP2UH.js";import{c as x}from"./chunk-D5PAJ3CB.js";import{n as d,p as j}from"./chunk-VARIYH6K.js";import{c as E,h as N}from"./chunk-EZLBMUQD.js";j();function L(i){return{id:i.id,eventType:i.event_type,matchCriteria:JSON.parse(i.match_criteria),target:JSON.parse(i.target),formatTemplate:i.format_template??void 0,maxPerMinute:i.max_per_minute,skipOriginChannel:i.skip_origin_channel===1,enabled:i.enabled===1,createdAt:i.created_at,createdBy:i.created_by??void 0}}function q(i){d().prepare(`
|
|
2
2
|
INSERT INTO delivery_rules (id, event_type, match_criteria, target, format_template,
|
|
3
3
|
max_per_minute, skip_origin_channel, enabled, created_at, created_by)
|
|
4
4
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
5
|
-
`).run(i.id,i.eventType,JSON.stringify(i.matchCriteria),JSON.stringify(i.target),i.formatTemplate??null,i.maxPerMinute,i.skipOriginChannel?1:0,i.enabled?1:0,i.createdAt,i.createdBy??null)}function H(i){let n=d().prepare("SELECT * FROM delivery_rules WHERE id = ?").get(i);return n?L(n):void 0}function W(i){let e=d(),n="SELECT * FROM delivery_rules",r=[];return i!==void 0&&(n+=" WHERE enabled = ?",r.push(i?1:0)),n+=" ORDER BY created_at DESC",e.prepare(n).all(...r).map(L)}function U(i,e){let n=d(),r=[],t=[];e.eventType!==void 0&&(r.push("event_type = ?"),t.push(e.eventType)),e.matchCriteria!==void 0&&(r.push("match_criteria = ?"),t.push(JSON.stringify(e.matchCriteria))),e.target!==void 0&&(r.push("target = ?"),t.push(JSON.stringify(e.target))),e.formatTemplate!==void 0&&(r.push("format_template = ?"),t.push(e.formatTemplate)),e.maxPerMinute!==void 0&&(r.push("max_per_minute = ?"),t.push(e.maxPerMinute)),e.skipOriginChannel!==void 0&&(r.push("skip_origin_channel = ?"),t.push(e.skipOriginChannel?1:0)),e.enabled!==void 0&&(r.push("enabled = ?"),t.push(e.enabled?1:0)),r.length!==0&&(t.push(i),n.prepare(`UPDATE delivery_rules SET ${r.join(", ")} WHERE id = ?`).run(...t))}function G(i){let e=d();e.prepare("DELETE FROM delivery_log WHERE rule_id = ?").run(i),e.prepare("DELETE FROM delivery_rules WHERE id = ?").run(i)}function A(i,e){return W(!0).filter(r=>{if(r.eventType!=="*"&&r.eventType!==i)return!1;let t=r.matchCriteria;if(t.templateId&&t.templateId!==e.templateId||t.roleId&&t.roleId!==e.roleId||t.taskStatus&&t.taskStatus!==e.taskStatus)return!1;if(t.promptPattern)try{if(!new RegExp(t.promptPattern,"i").test(e.prompt??""))return!1}catch{return!1}if(t.excludePromptPatterns&&t.excludePromptPatterns.length>0){let a=e.prompt??"";for(let s of t.excludePromptPatterns)if(!(typeof s!="string"||s.length>200))try{if(new RegExp(s,"i").test(a))return!1}catch{continue}}return!0})}B();N();import{v4 as J}from"uuid";function F(i){return!!(i.templateId&&i.stepId&&i.parentId)}var l=E("admin"),_=new Map,m=null,g=null,u=null,T=class{constructor(){f.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")})}),f.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)")})}),f.on("template_execution_status_change",e=>{e.status==="failed"&&this.handleTemplateExecutionFailure(e.executionId,e.templateId).catch(n=>{l.error({executionId:e.executionId,error:n},"Template failure delivery processing failed")})}),l.info("DeliveryEngine initialized")}async handlePlanApprovalRequest(e,n,r){let t=h(e),a=this.getSourceChannelForTask(e);if(a){let o=D(r),{sendApprovalToChannel:p}=await import("./approval-handler-
|
|
5
|
+
`).run(i.id,i.eventType,JSON.stringify(i.matchCriteria),JSON.stringify(i.target),i.formatTemplate??null,i.maxPerMinute,i.skipOriginChannel?1:0,i.enabled?1:0,i.createdAt,i.createdBy??null)}function H(i){let n=d().prepare("SELECT * FROM delivery_rules WHERE id = ?").get(i);return n?L(n):void 0}function W(i){let e=d(),n="SELECT * FROM delivery_rules",r=[];return i!==void 0&&(n+=" WHERE enabled = ?",r.push(i?1:0)),n+=" ORDER BY created_at DESC",e.prepare(n).all(...r).map(L)}function U(i,e){let n=d(),r=[],t=[];e.eventType!==void 0&&(r.push("event_type = ?"),t.push(e.eventType)),e.matchCriteria!==void 0&&(r.push("match_criteria = ?"),t.push(JSON.stringify(e.matchCriteria))),e.target!==void 0&&(r.push("target = ?"),t.push(JSON.stringify(e.target))),e.formatTemplate!==void 0&&(r.push("format_template = ?"),t.push(e.formatTemplate)),e.maxPerMinute!==void 0&&(r.push("max_per_minute = ?"),t.push(e.maxPerMinute)),e.skipOriginChannel!==void 0&&(r.push("skip_origin_channel = ?"),t.push(e.skipOriginChannel?1:0)),e.enabled!==void 0&&(r.push("enabled = ?"),t.push(e.enabled?1:0)),r.length!==0&&(t.push(i),n.prepare(`UPDATE delivery_rules SET ${r.join(", ")} WHERE id = ?`).run(...t))}function G(i){let e=d();e.prepare("DELETE FROM delivery_log WHERE rule_id = ?").run(i),e.prepare("DELETE FROM delivery_rules WHERE id = ?").run(i)}function A(i,e){return W(!0).filter(r=>{if(r.eventType!=="*"&&r.eventType!==i)return!1;let t=r.matchCriteria;if(t.templateId&&t.templateId!==e.templateId||t.roleId&&t.roleId!==e.roleId||t.taskStatus&&t.taskStatus!==e.taskStatus)return!1;if(t.promptPattern)try{if(!new RegExp(t.promptPattern,"i").test(e.prompt??""))return!1}catch{return!1}if(t.excludePromptPatterns&&t.excludePromptPatterns.length>0){let a=e.prompt??"";for(let s of t.excludePromptPatterns)if(!(typeof s!="string"||s.length>200))try{if(new RegExp(s,"i").test(a))return!1}catch{continue}}return!0})}B();N();import{v4 as J}from"uuid";function F(i){return!!(i.templateId&&i.stepId&&i.parentId)}var l=E("admin"),_=new Map,m=null,g=null,u=null,T=class{constructor(){f.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")})}),f.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)")})}),f.on("template_execution_status_change",e=>{e.status==="failed"&&this.handleTemplateExecutionFailure(e.executionId,e.templateId).catch(n=>{l.error({executionId:e.executionId,error:n},"Template failure delivery processing failed")})}),l.info("DeliveryEngine initialized")}async handlePlanApprovalRequest(e,n,r){let t=h(e),a=this.getSourceChannelForTask(e);if(a){let o=D(r),{sendApprovalToChannel:p}=await import("./approval-handler-FONN2EGB.js");await p(a.channelId,a.chatId,n,e,o)}let s=D(r)+`
|
|
6
6
|
|
|
7
7
|
Task: ${e}`;await this.matchAndDeliver("plan_approval_request",{templateId:t?.templateId,roleId:t?.roleId,prompt:t?.prompt,taskStatus:"pending"},s,e)}async handleTemplateExecutionFailure(e,n){let r=R(e),t=n?k(n):null,a=r?Object.entries(r.stepStatuses).filter(([,o])=>o.status==="failed"):[],s=["\u26A0\uFE0F TemplateExecution failed",`Template: ${t?.name??n}`,`Execution: ${e}`,`Failed steps: ${a.map(([o])=>o).join(", ")||"(unknown \u2014 no failed step recorded)"}`,a[0]?.[1]?.error?`
|
|
8
8
|
First error: ${a[0][1].error.slice(0,300)}`:""].filter(Boolean).join(`
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{n as e,p as i}from"./chunk-
|
|
1
|
+
import{n as e,p as i}from"./chunk-VARIYH6K.js";import{c as o,e as d}from"./chunk-5M6IGE5G.js";i();d();function s(t){return{id:t.id,taskId:t.task_id,index:t.index,type:t.type,content:t.content,toolName:t.tool_name??void 0,toolInput:t.tool_input?JSON.parse(t.tool_input):void 0,toolOutput:t.tool_output??void 0,truncated:t.truncated===1,timestamp:t.timestamp,tokenUsage:t.token_usage?JSON.parse(t.token_usage):void 0,planStepIndex:t.plan_step_index??void 0,traceId:t.trace_id??void 0}}function _(t){e().prepare(`
|
|
2
2
|
INSERT INTO step_logs (id, task_id, "index", type, content, tool_name,
|
|
3
3
|
tool_input, tool_output, truncated, timestamp, token_usage, plan_step_index, trace_id)
|
|
4
4
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{d as a}from"./chunk-
|
|
1
|
+
import{d as a}from"./chunk-OH6VBBDV.js";function s(){try{let t=a().server?.timezone;return t==="system"||!t?void 0:t}catch{return}}function p(t){let e=s();return new Date(t).toLocaleTimeString(void 0,e?{timeZone:e}:void 0)}function l(t){let e=t??s(),r=new Date,i=r.toLocaleDateString("en-CA",e?{timeZone:e}:void 0);if(e){let n=(new Intl.DateTimeFormat("en-US",{timeZone:e,timeZoneName:"shortOffset"}).formatToParts(r).find(o=>o.type==="timeZoneName")?.value??"").match(/GMT([+-]?)(\d+)(?::(\d+))?/);if(n){let o=n[1]==="-"?-1:1,m=parseInt(n[2],10),c=parseInt(n[3]??"0",10),f=o*(m*60+c)*6e4;return new Date(`${i}T00:00:00Z`).getTime()-f}}return new Date(`${i}T00:00:00`).getTime()}export{p as a,l as b};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{c as n,h as d}from"./chunk-
|
|
1
|
+
import{c as n,h as d}from"./chunk-EZLBMUQD.js";d();import{query as f}from"@anthropic-ai/claude-agent-sdk";import*as a from"fs/promises";import*as i from"path";import*as l from"os";var x=n("manager"),m=i.join(l.homedir(),".adam","llm-eval");async function y(u,s){await a.mkdir(m,{recursive:!0});let t=typeof s=="string"?{systemPrompt:s}:s??{},o={cwd:m,maxTurns:t.maxTurns??3,maxBudgetUsd:t.maxBudgetUsd??.05,persistSession:!1};t.systemPrompt&&(o.systemPrompt=t.systemPrompt),t.model&&(o.model=t.model);let p=f({prompt:u,options:o}),e="";for await(let g of p){let r=g;r.type==="result"&&typeof r.result=="string"&&(e=r.result)}return e}export{y as a};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{n as s,p as m}from"./chunk-
|
|
1
|
+
import{n as s,p as m}from"./chunk-VARIYH6K.js";import{c as d,h as f}from"./chunk-EZLBMUQD.js";m();f();var p=/^[a-z0-9.-]+$/;var u=d("store");function r(e){let n;if(e.recipient_cap_map_json)try{n=JSON.parse(e.recipient_cap_map_json)}catch(i){u.warn({channelId:e.id,err:i},"Malformed recipient_cap_map_json; using empty map"),n=void 0}return{id:e.id,name:e.name,platform:e.platform,enabled:e.enabled===1,status:e.status,config:JSON.parse(e.config),linkedRoleId:e.linked_role_id??void 0,allowedChatIds:e.allowed_chat_ids?JSON.parse(e.allowed_chat_ids):void 0,viewerKey:e.viewer_key??void 0,createdAt:e.created_at,updatedAt:e.updated_at??void 0,lastMessageAt:e.last_message_at??void 0,messageCount:e.message_count,recipientCapMap:n,defaultRecipientCapBytes:e.default_recipient_cap_bytes??void 0}}function R(e){s().prepare(`
|
|
2
2
|
INSERT INTO channels (id, name, platform, enabled, status, config, linked_role_id,
|
|
3
3
|
allowed_chat_ids, viewer_key, created_at, updated_at, last_message_at, message_count,
|
|
4
4
|
recipient_cap_map_json, default_recipient_cap_bytes)
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{n as s,p as d}from"./chunk-
|
|
1
|
+
import{n as s,p as d}from"./chunk-VARIYH6K.js";import{c as l,e as u}from"./chunk-5M6IGE5G.js";d();u();function a(e){return{id:e.id,ruleId:e.rule_id??void 0,taskId:e.task_id??void 0,executionId:e.execution_id??void 0,status:e.status,target:JSON.parse(e.target),content:e.content,attempts:e.attempts,error:e.error??void 0,createdAt:e.created_at,deliveredAt:e.delivered_at??void 0,expiresAt:e.expires_at,source:e.source,messageType:e.message_type??void 0,traceId:e.trace_id??void 0}}var g=1440*60*1e3;function E(e){s().prepare(`
|
|
2
2
|
INSERT INTO delivery_log (id, rule_id, task_id, execution_id, status, target, content,
|
|
3
3
|
attempts, error, created_at, delivered_at, expires_at, source, message_type, trace_id)
|
|
4
4
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
@@ -1,22 +1,23 @@
|
|
|
1
|
-
import{n as o,p as k}from"./chunk-
|
|
1
|
+
import{n as o,p as k}from"./chunk-VARIYH6K.js";import{b}from"./chunk-5PELJRUQ.js";import{basename as S}from"path";import{v4 as x}from"uuid";function u(t){return{id:t.id,sourceKind:t.source_kind,executionId:t.execution_id??void 0,taskId:t.task_id??void 0,chatSessionId:t.chat_session_id??void 0,stepId:t.step_id??void 0,roleId:t.role_id??void 0,key:t.key??void 0,kind:t.kind,value:t.value_json?JSON.parse(t.value_json):void 0,blobPath:t.blob_path??void 0,mime:t.mime??void 0,originalFilename:t.original_filename??void 0,sizeBytes:t.size_bytes,createdAt:t.created_at,locator:t.locator??void 0,contentHash:t.content_hash??void 0,retentionHint:t.retention_hint??void 0,encryptionClass:t.encryption_class??void 0,purpose:t.purpose??void 0,replaces:t.replaces??void 0,producedByRole:t.produced_by_role??void 0,access:t.access??void 0,priority:t.priority??void 0,artifactRole:t.artifact_role??void 0}}function w(t){if(!t.roleId||t.roleId.trim()==="")throw new Error("createArtifact: roleId required (application-layer enforcement)");p(o(),t)}function p(t,e){t.prepare(`
|
|
2
2
|
INSERT INTO artifacts (
|
|
3
3
|
id, source_kind, execution_id, task_id, chat_session_id, step_id, role_id,
|
|
4
4
|
key, kind, value_json, blob_path, mime, original_filename, size_bytes, created_at,
|
|
5
|
-
locator, content_hash, retention_hint, encryption_class, purpose, replaces, produced_by_role, access, priority
|
|
5
|
+
locator, content_hash, retention_hint, encryption_class, purpose, replaces, produced_by_role, access, priority,
|
|
6
|
+
artifact_role
|
|
6
7
|
)
|
|
7
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
8
|
-
`).run(e.id,e.sourceKind,e.executionId??null,e.taskId??null,e.chatSessionId??null,e.stepId??null,e.roleId??null,e.key??null,e.kind,e.value!==void 0?JSON.stringify(e.value):null,e.blobPath??null,e.mime??null,e.originalFilename??null,e.sizeBytes,e.createdAt,e.locator??null,e.contentHash??null,e.retentionHint??null,e.encryptionClass??null,e.purpose??null,e.replaces??null,e.producedByRole??null,e.access??null,e.priority??null)}function y(t,e,n,i){let r=t.prepare(`
|
|
8
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
9
|
+
`).run(e.id,e.sourceKind,e.executionId??null,e.taskId??null,e.chatSessionId??null,e.stepId??null,e.roleId??null,e.key??null,e.kind,e.value!==void 0?JSON.stringify(e.value):null,e.blobPath??null,e.mime??null,e.originalFilename??null,e.sizeBytes,e.createdAt,e.locator??null,e.contentHash??null,e.retentionHint??null,e.encryptionClass??null,e.purpose??null,e.replaces??null,e.producedByRole??null,e.access??null,e.priority??null,e.artifactRole??null)}function y(t,e,n,i){let r=t.prepare(`
|
|
9
10
|
SELECT * FROM artifacts
|
|
10
11
|
WHERE source_kind = 'template_step' AND execution_id = ? AND step_id = ? AND key = ?
|
|
11
|
-
`).get(e,n,i);return r?u(r):void 0}function v(t,e,n){return y(o(),t,e,n)}function H(t){let e=o().prepare("SELECT * FROM artifacts WHERE id = ?").get(t);return e?u(e):void 0}function h(t,e){let n=o(),i="SELECT * FROM artifacts WHERE execution_id = ?",r=[t];return e&&(i+=" AND step_id = ?",r.push(e)),i+=" ORDER BY created_at ASC",n.prepare(i).all(...r).map(u)}function L(t){return o().prepare("SELECT * FROM artifacts WHERE task_id = ? ORDER BY created_at ASC").all(t).map(u)}function P(t){return o().prepare("SELECT * FROM artifacts WHERE chat_session_id = ? ORDER BY created_at ASC").all(t).map(u)}function K(t,e){let n=o(),i="SELECT * FROM artifacts WHERE role_id = ?",r=[t];e?.sourceKind&&(i+=" AND source_kind = ?",r.push(e.sourceKind)),i+=" ORDER BY created_at ASC";let s=n.prepare(i).all(...r).map(u);return e?.mimePrefix&&(s=s.filter(a=>a.mime?.startsWith(e.mimePrefix))),s}function W(t){let e=o(),n=h(t);return e.prepare("DELETE FROM artifacts WHERE execution_id = ?").run(t),n}function z(t,e){let n=o(),i=h(t).filter(r=>r.stepId===e);return n.prepare("DELETE FROM artifacts WHERE execution_id = ? AND step_id = ?").run(t,e),i}function N(t){o().prepare("DELETE FROM artifacts WHERE id = ?").run(t)}function $(t){return o().prepare("DELETE FROM artifacts WHERE id = ?").run(t).changes>0}function T(t){if(!t||typeof t!="object")return!1;let e=t;return e.type!=="artifact_collection"||typeof e.outputAs!="string"||e.outputAs.length===0||!Array.isArray(e.items)?!1:e.items.every(n=>n!=null&&typeof n=="object"&&typeof n.artifactId=="string"&&n.artifactId.length>0&&typeof n.key=="string"&&n.key.length>0&&typeof n.sizeBytes=="number"&&Number.isFinite(n.sizeBytes)&&(n.filename===void 0||typeof n.filename=="string")&&(n.mime===void 0||typeof n.mime=="string")&&(n.purpose===void 0||typeof n.purpose=="string"))}function j(t,e,n){return g(o(),t,e,n)}function q(t,e,n,i){let r=o();return r.transaction(()=>{let s=y(r,t,e,n);if(!s||s.kind!=="json"||!T(s.value))throw new Error(`Artifact collection manifest not found at ${e}/${n}`);let a=g(r,t,e,i.key??"",new Set([n])),l={...i,key:a};p(r,l);let d={...s.value,items:[...s.value.items,m(l)]};return{manifestArtifact:I(r,s,d),childArtifact:l}})()}function U(t,e,n,i,r){let c=o();return c.transaction(()=>{let a=y(c,t,e,n);if(!a||a.id!==i.id)throw new Error(`Primary artifact changed before collection conversion at ${e}/${n}`);if(a.kind!=="file"||!a.blobPath)throw new Error(`Primary artifact at ${e}/${n} is not a file`);let l=g(c,t,e,a.originalFilename??a.key??n,new Set([n]));c.prepare("UPDATE artifacts SET key = ? WHERE id = ?").run(l,a.id);let d={...a,key:l},A=g(c,t,e,r.key??"",new Set([n,l])),f={...r,key:A};p(c,f);let _={type:"artifact_collection",outputAs:n,items:[m(d),m(f)]},E={id:x(),sourceKind:i.sourceKind,executionId:t,stepId:e,key:n,kind:"json",value:_,sizeBytes:
|
|
12
|
+
`).get(e,n,i);return r?u(r):void 0}function v(t,e,n){return y(o(),t,e,n)}function H(t){let e=o().prepare("SELECT * FROM artifacts WHERE id = ?").get(t);return e?u(e):void 0}function h(t,e){let n=o(),i="SELECT * FROM artifacts WHERE execution_id = ?",r=[t];return e&&(i+=" AND step_id = ?",r.push(e)),i+=" ORDER BY created_at ASC",n.prepare(i).all(...r).map(u)}function L(t){return o().prepare("SELECT * FROM artifacts WHERE task_id = ? ORDER BY created_at ASC").all(t).map(u)}function P(t){return o().prepare("SELECT * FROM artifacts WHERE chat_session_id = ? ORDER BY created_at ASC").all(t).map(u)}function K(t,e){let n=o(),i="SELECT * FROM artifacts WHERE role_id = ?",r=[t];e?.sourceKind&&(i+=" AND source_kind = ?",r.push(e.sourceKind)),i+=" ORDER BY created_at ASC";let s=n.prepare(i).all(...r).map(u);return e?.mimePrefix&&(s=s.filter(a=>a.mime?.startsWith(e.mimePrefix))),s}function W(t){let e=o(),n=h(t);return e.prepare("DELETE FROM artifacts WHERE execution_id = ?").run(t),n}function z(t,e){let n=o(),i=h(t).filter(r=>r.stepId===e);return n.prepare("DELETE FROM artifacts WHERE execution_id = ? AND step_id = ?").run(t,e),i}function N(t){o().prepare("DELETE FROM artifacts WHERE id = ?").run(t)}function $(t){return o().prepare("DELETE FROM artifacts WHERE id = ?").run(t).changes>0}function T(t){if(!t||typeof t!="object")return!1;let e=t;return e.type!=="artifact_collection"||typeof e.outputAs!="string"||e.outputAs.length===0||!Array.isArray(e.items)?!1:e.items.every(n=>n!=null&&typeof n=="object"&&typeof n.artifactId=="string"&&n.artifactId.length>0&&typeof n.key=="string"&&n.key.length>0&&typeof n.sizeBytes=="number"&&Number.isFinite(n.sizeBytes)&&(n.filename===void 0||typeof n.filename=="string")&&(n.mime===void 0||typeof n.mime=="string")&&(n.purpose===void 0||typeof n.purpose=="string"))}function j(t,e,n){return g(o(),t,e,n)}function q(t,e,n,i){let r=o();return r.transaction(()=>{let s=y(r,t,e,n);if(!s||s.kind!=="json"||!T(s.value))throw new Error(`Artifact collection manifest not found at ${e}/${n}`);let a=g(r,t,e,i.key??"",new Set([n])),l={...i,key:a};p(r,l);let d={...s.value,items:[...s.value.items,m(l)]};return{manifestArtifact:I(r,s,d),childArtifact:l}})()}function U(t,e,n,i,r){let c=o();return c.transaction(()=>{let a=y(c,t,e,n);if(!a||a.id!==i.id)throw new Error(`Primary artifact changed before collection conversion at ${e}/${n}`);if(a.kind!=="file"||!a.blobPath)throw new Error(`Primary artifact at ${e}/${n} is not a file`);let l=g(c,t,e,a.originalFilename??a.key??n,new Set([n]));c.prepare("UPDATE artifacts SET key = ? WHERE id = ?").run(l,a.id);let d={...a,key:l},A=g(c,t,e,r.key??"",new Set([n,l])),f={...r,key:A};p(c,f);let _={type:"artifact_collection",outputAs:n,items:[m(d),m(f)]},E={id:x(),sourceKind:i.sourceKind,executionId:t,stepId:e,key:n,kind:"json",value:_,sizeBytes:R(_),createdAt:Date.now(),purpose:"data",roleId:i.roleId};return p(c,E),{manifestArtifact:E,childArtifact:f,rekeyedPrimaryArtifact:d}})()}function Y(t){return o().prepare(`
|
|
12
13
|
SELECT id
|
|
13
14
|
FROM template_executions
|
|
14
15
|
WHERE status != 'running' AND COALESCE(completed_at, started_at) < ?
|
|
15
16
|
`).all(t).map(i=>i.id)}function g(t,e,n,i,r=new Set){let c=t.prepare(`
|
|
16
17
|
SELECT key FROM artifacts
|
|
17
18
|
WHERE execution_id = ? AND step_id = ?
|
|
18
|
-
`).all(e,n),s=new Set(c.map(l=>l.key));for(let l of r)s.add(l);let a=B(i);if(!s.has(a))return a;for(let l=2;l<1e4;l++){let d=`-${l}`,f=`${a.slice(0,Math.max(1,256-d.length))}${d}`;if(!s.has(f))return f}throw new Error(`Unable to allocate unique artifact key for ${n}/${i}`)}function B(t){let e=t.replace(/\\/g,"/"),i=S(e).replace(/[^A-Za-z0-9._-]+/g,"-").replace(/^-+|-+$/g,"").slice(0,256);return!i||i==="."||i===".."?"artifact":C.test(i)?i:"artifact"}function m(t){return{artifactId:t.id,key:t.key??"",...t.originalFilename?{filename:t.originalFilename}:{},...t.mime?{mime:t.mime}:{},sizeBytes:t.sizeBytes,...t.purpose?{purpose:t.purpose}:{}}}function I(t,e,n){let i=
|
|
19
|
+
`).all(e,n),s=new Set(c.map(l=>l.key));for(let l of r)s.add(l);let a=B(i);if(!s.has(a))return a;for(let l=2;l<1e4;l++){let d=`-${l}`,f=`${a.slice(0,Math.max(1,256-d.length))}${d}`;if(!s.has(f))return f}throw new Error(`Unable to allocate unique artifact key for ${n}/${i}`)}function B(t){let e=t.replace(/\\/g,"/"),i=S(e).replace(/[^A-Za-z0-9._-]+/g,"-").replace(/^-+|-+$/g,"").slice(0,256);return!i||i==="."||i===".."?"artifact":C.test(i)?i:"artifact"}function m(t){return{artifactId:t.id,key:t.key??"",...t.originalFilename?{filename:t.originalFilename}:{},...t.mime?{mime:t.mime}:{},sizeBytes:t.sizeBytes,...t.purpose?{purpose:t.purpose}:{},...t.artifactRole?{role:t.artifactRole}:{}}}function I(t,e,n){let i=R(n);return t.prepare(`
|
|
19
20
|
UPDATE artifacts
|
|
20
21
|
SET value_json = ?, size_bytes = ?
|
|
21
22
|
WHERE id = ?
|
|
22
|
-
`).run(JSON.stringify(n),i,e.id),{...e,value:n,sizeBytes:i}}function
|
|
23
|
+
`).run(JSON.stringify(n),i,e.id),{...e,value:n,sizeBytes:i}}function R(t){return Buffer.byteLength(JSON.stringify(t),"utf8")}function J(t,e){let n=[],i=[];t.sourceKind&&(n.push("source_kind = ?"),i.push(t.sourceKind)),t.mimePrefix&&(n.push("mime LIKE ? ESCAPE '\\'"),i.push(t.mimePrefix.replace(/[\\%_]/g,"\\$&")+"%")),t.roleId&&(n.push("role_id = ?"),i.push(t.roleId)),t.taskId&&(n.push("task_id = ?"),i.push(t.taskId)),t.executionId&&(n.push("execution_id = ?"),i.push(t.executionId)),t.chatSessionId&&(n.push("chat_session_id = ?"),i.push(t.chatSessionId)),t.from!==void 0&&(n.push("created_at >= ?"),i.push(t.from)),t.to!==void 0&&(n.push("created_at <= ?"),i.push(t.to)),t.deliveryStatus&&(n.push("(EXISTS (SELECT 1 FROM delivery_log dl WHERE dl.status = ? AND (dl.task_id = artifacts.task_id OR dl.task_id = artifacts.execution_id)))"),i.push(t.deliveryStatus));let r=n.length?"WHERE "+n.join(" AND "):"",c=o(),s=c.prepare(`SELECT COUNT(*) AS n FROM artifacts ${r}`).get(...i);return{artifacts:c.prepare(`SELECT * FROM artifacts ${r} ORDER BY created_at DESC LIMIT ? OFFSET ?`).all(...i,e.limit,e.offset).map(u),total:s.n}}var C,M=b(()=>{k();C=/^[\p{L}0-9._-]{1,256}$/u});export{w as a,v as b,H as c,h as d,L as e,P as f,K as g,W as h,z as i,N as j,$ as k,T as l,j as m,q as n,U as o,Y as p,J as q,M as r};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{a as m,
|
|
1
|
+
import{a as m,b as d}from"./chunk-5PELJRUQ.js";import o from"pino";import{Writable as g}from"stream";function b(n){r.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 i[n]||e}function w(n){e.level=n;for(let t of Object.values(i))t.level=n}function E(){return e.level}function S(n){a=n}function C(){return a}var p,r,h,u,e,i,a,v=d(()=>{p=process.env.ADAM_LOG_LEVEL||"info",r=[];h=new g({write(n,t,c){try{let l=JSON.parse(n.toString());for(let s of r)s(l)}catch{}c()}}),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}])),i={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"}),"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"}),"context-compact":e.child({name:"context-compact"}),"workspace-watcher":e.child({name:"workspace-watcher"}),"memory-service":e.child({name:"memory-service"})};a=null});export{b as a,e as b,y as c,w as d,E as e,S as f,C as g,v as h};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{b as e,d as t,h as a}from"./chunk-
|
|
1
|
+
import{b as e,d as t,h as a}from"./chunk-VO24C673.js";a();var r={defaults:{timeout:600,maxTurns:400,maxBudgetUsd:5,effort:"high",model:"",settingSources:["user","project"],allowedTools:[],disallowedTools:[],approvalRequired:["rm -rf *","git push*","git reset*","curl * -X POST*","curl * --request POST*"],approvalTimeout:600,env:{},plugins:[],workspacePath:t,workspaceRetention:"immediate",deniedReadPaths:[...e]},externalApis:[],server:{port:7100,host:"0.0.0.0",timezone:"system"},identity:{ownerViewerKey:"local-owner"},logging:{level:"info"},roles:{presets:[],evolution:{triggerEvery:5,reflectionThreshold:150,retirementThreshold:.4,probationTasks:5}},chat:{sessionTimeoutMinutes:30,maxSessionTurns:20,autoTitle:!0,archiveExtractMemory:!0,contextBudgetTokens:2e4,artifactThresholdChars:4e3,commitmentDetection:{locales:["zh","en"],blockedText:{zh:"\u4EFB\u52A1\u5DF2\u63D0\u4EA4\uFF0C\u5B8C\u6210\u540E\u6211\u4F1A\u66F4\u65B0\u7ED3\u679C\u3002",en:"Task dispatched; I will update you when it completes."},unsupportedSuccessText:{zh:"\u56FE\u7247\u5DF2\u751F\u6210\uFF0C\u53D1\u9001\u72B6\u6001\u8FD8\u6CA1\u6709\u5B8C\u6210\u9A8C\u8BC1\u3002",en:"Result is ready; delivery status is not yet verified."},unsupportedFailureText:{zh:"\u56FE\u7247\u5DF2\u751F\u6210\uFF0C\u4F46\u8FD8\u6CA1\u6709\u6267\u884C\u53D1\u9001\u3002",en:"Result is ready, but delivery has not been attempted."},unsupportedMutationText:{zh:"\u6211\u6CA1\u6709\u5B8C\u6210\u8FD9\u6B21\u8BB0\u5F55\uFF0C\u4E0D\u80FD\u8BF4\u5DF2\u8BB0\u5F55\u3002\u9700\u8981\u5148\u66F4\u65B0\u5BF9\u5E94\u6A21\u677F\u6216\u914D\u7F6E\u540E\u518D\u786E\u8BA4\u3002",en:"I did not actually record this. The template or config has not been updated yet."}}},memory:{midTaskInjection:{enabled:!0,toolCallThreshold:10,cooldownMs:6e4,topK:3,maxTokens:1e3},retrievalWeights:{cosSim:.4,recency:.2,tokenCost:.05},globalBudgetTokens:1500,retrievalDecayDays:30,attributionThresholds:{high:.7,low:.4},antiFlipMinUses:5,antiFlipSuccessEmaThreshold:.25,reflection:{maxBudgetUsd:5},scope:{emaAlpha:.3,humanFeedbackWeight:3,reflectionPoolMax:100,decayBase:.995,archiveThreshold:.2},embeddingModel:"bge-small-zh-v1.5"},watchdog:{enabled:!0,intervalMinutes:5,rules:{managerHealthCheck:{enabled:!0,action:"restart",staleDurationMinutes:15},staleTasks:{enabled:!0,action:"notify",maxPendingMinutes:30},staleRunningTasks:{enabled:!0,action:"notify",maxRunningMinutes:15},staleTemplateExecutions:{enabled:!0,action:"notify",maxOrphanMinutes:60},dbMaintenance:{enabled:!0,action:"ignore",walCheckpointThresholdMB:100},artifactCleanup:{enabled:!0,action:"ignore",ttlDays:7,orphanGcMinAgeHours:1},sandboxViolation:{enabled:!0,action:"alert"},reflectionJob:{enabled:!0,intervalMinutes:30},memoryGc:{enabled:!0,intervalHours:24,observationTtlDays:14}}},execution:{maxConcurrent:5,pollIntervalMs:3e4},anthropic:{apiKey:"",baseUrl:"",model:"",defaultOpusModel:"",defaultSonnetModel:"",defaultHaikuModel:"",smallFastModel:""},emailGateway:{enabled:!1,address:"",displayName:"Adam",imap:{host:"",port:993,secure:!0,auth:{user:"",pass:""},mailbox:"INBOX"},smtp:{host:"",port:465,secure:!0,auth:{user:"",pass:""},from:""},subjectPrefix:"Adam"},audit:{intentEval:{maxBudgetUsd:1,timeoutMs:3e4}},evaluation:{},delivery:{cronDefaultReportTo:null},storage:{localProfile:"default"}};export{r as a};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{h as c,i as m}from"./chunk-PBKZDNNV.js";import{c as a,h as f}from"./chunk-EZLBMUQD.js";import{c as s,e as u}from"./chunk-5M6IGE5G.js";u();f();var r=a("adam");function T(e){let i=e.traceIdOverride??s();if(!i){r.debug({toolName:e.toolName,entityType:e.entityType,verb:e.verb},"Mutation receipt skipped: no active trace context");return}let n={traceId:i,toolName:e.toolName,taskId:e.taskId,roleId:e.roleId};try{m({traceId:i,taskId:e.taskId,sessionId:e.sessionId,effectCategory:"entity_mutation",verb:e.verb,entityType:e.entityType,entityId:e.entityId,entityIds:e.entityIds,fieldChanges:e.fieldChanges,scope:e.scope,actor:n,outcome:"success"})}catch(o){o instanceof c?r.warn({errors:o.errors,toolName:e.toolName,entityType:e.entityType},"Mutation receipt validation failed"):r.warn({error:o instanceof Error?o.message:String(o),toolName:e.toolName},"Mutation receipt write failed")}}import{z as t}from"zod";var p=t.object({kind:t.literal("lengthTarget"),min:t.number().int().nonnegative(),max:t.number().int().positive(),unit:t.enum(["characters","words","bytes"])}).refine(e=>e.min<=e.max,{message:"min must be <= max"}),g=t.object({kind:t.literal("format"),value:t.enum(["markdown","json","text"])}),k=t.object({kind:t.literal("requireHeading"),value:t.boolean()}),y=t.object({kind:t.literal("mime"),declared:t.string().regex(/^[a-z]+\/[a-z0-9.+-]+(\/)?$/i,{message:"declared must be a valid MIME type (e.g. audio/mpeg, application/json)"})}),b=t.object({kind:t.literal("fileSizeBytes"),min:t.number().int().nonnegative().optional(),max:t.number().int().positive().optional()}).refine(e=>e.min!==void 0||e.max!==void 0,{message:"at least one of min/max required"}).refine(e=>e.min===void 0||e.max===void 0||e.min<=e.max,{message:"min must be <= max"}),x=t.object({kind:t.literal("audioZeroCrossingRatePerS"),max:t.number().positive()}),I=t.object({kind:t.literal("audioDurationMs"),min:t.number().int().nonnegative().optional(),max:t.number().int().positive().optional()}).refine(e=>e.min!==void 0||e.max!==void 0,{message:"at least one of min/max required"}).refine(e=>e.min===void 0||e.max===void 0||e.min<=e.max,{message:"min must be <= max"}),R=t.discriminatedUnion("kind",[p,g,k,y,b,x,I]),A=t.array(R);function d(e){return e.kind==="lengthTarget"||e.kind==="format"||e.kind==="requireHeading"||e.kind==="mime"}function l(e){return e.outputContract?.contractRules??[]}function E(e){return l(e).some(i=>!d(i)||i.kind==="mime"&&i.declared.toLowerCase()!=="application/json")}function N(e,i){return typeof i!="string"?!1:l(e).some(n=>n.kind==="format"&&(n.value==="markdown"||n.value==="text"))}export{T as a,R as b,A as c,d,l as e,E as f,N as g};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{d as w,h as S}from"./chunk-
|
|
1
|
+
import{d as w,h as S}from"./chunk-VO24C673.js";import{c as g,h as P}from"./chunk-EZLBMUQD.js";P();S();import{readFileSync as v,existsSync as E}from"fs";import{join as p}from"path";import{homedir as R}from"os";var T=g("ws"),x=p(R(),".adam"),f=p(x,"adam.port"),b=p(w,"adam.key");function d(){let n=process.env.ADAM_API_KEY;if(n)return n;if(E(b))return v(b,"utf-8").trim()||void 0}function m(){if(!E(f))return null;let n=parseInt(v(f,"utf-8").trim(),10);return isNaN(n)?null:n}function C(){let n=m();if(!n)throw new Error("Server not running. Run: adam server start");return`http://localhost:${n}`}var u=class extends Error{constructor(e,s){super(s);this.status=e;this.name="ApiError"}status};async function A(n,t={}){let s=`${C()}${n}`,r=d(),o=await fetch(s,{method:t.method||"GET",headers:{"Content-Type":"application/json",...r?{"x-api-key":r}:{},...t.headers},body:t.body?JSON.stringify(t.body):void 0});if(!o.ok){let a=await o.text().catch(()=>"Unknown error");throw new u(o.status,a)}return o.headers.get("content-type")?.includes("application/json")?o.json():o.text()}function D(){return A("/healthz")}var k=class{ws=null;callbacks=new Map;reconnectAttempts=0;reconnectTimer=null;url;constructor(t="/events"){let e=m();if(!e)throw new Error("Server not running. Run: adam server start");let s=d(),r=new URL(`ws://localhost:${e}${t}`);s&&r.searchParams.set("api_key",s),this.url=r.toString()}connect(){return new Promise((t,e)=>{try{this.ws=new WebSocket(this.url),this.ws.onopen=()=>{this.reconnectAttempts=0,t()},this.ws.onmessage=s=>{try{let r=JSON.parse(s.data),{type:o,data:c,...a}=r,i=this.callbacks.get(o);i&&i.forEach(l=>l(c??a))}catch(r){T.error({error:r},"Failed to parse WebSocket message")}},this.ws.onclose=()=>{this.scheduleReconnect()},this.ws.onerror=s=>{e(s)}}catch(s){e(s)}})}scheduleReconnect(){let t=[1e3,2e3,4e3,8e3,15e3],e=t[Math.min(this.reconnectAttempts,t.length-1)];this.reconnectAttempts++,this.reconnectTimer=setTimeout(()=>{this.connect().catch(()=>{})},e)}on(t,e){this.callbacks.has(t)||this.callbacks.set(t,new Set),this.callbacks.get(t).add(e)}off(t,e){this.callbacks.get(t)?.delete(e)}close(){this.reconnectTimer&&clearTimeout(this.reconnectTimer),this.ws?.close()}isConnected(){return this.ws?.readyState===WebSocket.OPEN}},y=class{ws=null;callbacks=new Map;url;constructor(t){let e=m();if(!e)throw new Error("Server not running. Run: adam server start");let s=d(),r=new URL(`ws://localhost:${e}/tasks/${t}/stream`);s&&r.searchParams.set("api_key",s),this.url=r.toString()}connect(){return new Promise((t,e)=>{try{this.ws=new WebSocket(this.url),this.ws.onopen=()=>{t()},this.ws.onmessage=s=>{try{let r=JSON.parse(s.data),{type:o,data:c,...a}=r,i=this.callbacks.get(o);i&&i.forEach(h=>h(c??a));let l=this.callbacks.get("*");l&&l.forEach(h=>h(r))}catch(r){T.error({error:r},"Failed to parse task stream message")}},this.ws.onerror=s=>{e(s)},this.ws.onclose=()=>{}}catch(s){e(s)}})}on(t,e){this.callbacks.has(t)||this.callbacks.set(t,new Set),this.callbacks.get(t).add(e)}off(t,e){this.callbacks.get(t)?.delete(e)}close(){this.ws?.close()}isConnected(){return this.ws?.readyState===WebSocket.OPEN}};export{d as a,A as b,D as c,k as d,y as e};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import{h as c}from"./chunk-2WPUKCDA.js";import{K as u,L as p}from"./chunk-P76VP2UH.js";import{n as s,p as f}from"./chunk-VARIYH6K.js";f();p();function r(e){return{id:e.id,roleId:e.role_id,content:e.content,isAnti:e.is_anti===1,evidenceObsIds:e.evidence_obs_ids?JSON.parse(e.evidence_obs_ids):[],embedding:e.embedding?new Float32Array(e.embedding.buffer,e.embedding.byteOffset,e.embedding.byteLength/4):void 0,supersededBy:e.superseded_by??void 0,createdAt:e.created_at,lastUsedAt:e.last_used_at,lastValidatedAt:e.last_validated_at,scopeKey:e.scope_key??void 0,status:e.status,successEma:e.success_ema??void 0,injectCount:e.inject_count??0}}function _(e){return Buffer.from(e.buffer,e.byteOffset,e.byteLength)}function g(e){let t=s(),n=e.lastUsedAt??u(e.roleId);t.prepare(`
|
|
2
|
+
INSERT INTO beliefs (id, role_id, content,
|
|
3
|
+
is_anti, evidence_obs_ids, embedding, superseded_by,
|
|
4
|
+
created_at, last_used_at, last_validated_at,
|
|
5
|
+
scope_key, status, success_ema, inject_count)
|
|
6
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
7
|
+
`).run(e.id,e.roleId,e.content,e.isAnti?1:0,JSON.stringify(e.evidenceObsIds),e.embedding?_(e.embedding):null,e.supersededBy??null,e.createdAt,n,e.lastValidatedAt,e.scopeKey??null,e.status??"active",e.successEma??null,e.injectCount??0)}function y(e){let n=s().prepare("SELECT * FROM beliefs WHERE id = ?").get(e);return n?r(n):void 0}function A(e,t){let n=s(),d=["role_id = ?"],l=[e];return t?.includeSuperseded||d.push("superseded_by IS NULL"),t?.includeAnti===!1&&d.push("is_anti = 0"),t?.onlyActive&&d.push("status = 'active'"),n.prepare(`SELECT * FROM beliefs WHERE ${d.join(" AND ")} ORDER BY last_used_at DESC`).all(...l).map(r)}function B(e,t,n){let a=s().prepare(`SELECT * FROM beliefs
|
|
8
|
+
WHERE role_id = ? AND embedding IS NOT NULL AND superseded_by IS NULL AND status = 'active'
|
|
9
|
+
ORDER BY last_used_at DESC
|
|
10
|
+
LIMIT ?`).all(e,Math.min(n*10,1e3)).map(i=>({node:r(i),cosine:i.embedding?c(t,new Float32Array(i.embedding.buffer,i.embedding.byteOffset,i.embedding.byteLength/4)):0})).filter(i=>i.cosine>=0);return a.sort((i,o)=>o.cosine-i.cosine),a.slice(0,n)}function S(e,t){s().prepare("UPDATE beliefs SET superseded_by = ? WHERE id = ?").run(t,e)}function R(e,t){s().prepare("UPDATE beliefs SET content = ?, is_anti = 1, last_validated_at = ? WHERE id = ?").run(t,Date.now(),e)}function v(e,t,n){let d=s();n?.scopeKey!==void 0?d.prepare("UPDATE beliefs SET status = ?, scope_key = COALESCE(?, scope_key) WHERE id = ?").run(t,n?.scopeKey??null,e):d.prepare("UPDATE beliefs SET status = ? WHERE id = ?").run(t,e)}function T(e,t,n){s().prepare("UPDATE beliefs SET success_ema = ?, last_used_at = ?, last_validated_at = ? WHERE id = ?").run(t,n,Date.now(),e)}function D(e){s().prepare("UPDATE beliefs SET inject_count = inject_count + 1 WHERE id = ?").run(e)}export{g as a,y as b,A as c,B as d,S as e,R as f,v as g,T as h,D as i};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{n as o,p as a}from"./chunk-
|
|
1
|
+
import{n as o,p as a}from"./chunk-VARIYH6K.js";import{c as u,e as c}from"./chunk-5M6IGE5G.js";a();c();import{v4 as p}from"uuid";function R(t){o().prepare(`
|
|
2
2
|
INSERT INTO evolution_audit (id, timestamp, old_rules, new_rules, diff, trigger_task_id, role_id, source, trace_id)
|
|
3
3
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
4
4
|
`).run(p(),t.timestamp,t.oldRules,t.newRules,t.diff,t.triggerTaskId??null,t.roleId??null,t.source??"reflection",t.traceId??u()??null)}function _(t=100,e=0){return o().prepare(`
|