adam-agent-server 0.3.0 → 0.4.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/{adam-tools-RTCTINZI.js → adam-tools-PQC7EI3J.js} +1 -1
- package/dist/{approval-handler-SSKO2IGC.js → approval-handler-HK7GQPHU.js} +1 -1
- package/dist/{bree-engine-SQMSKGAP.js → bree-engine-25VACELK.js} +1 -1
- package/dist/{channels-WFZAONF3.js → channels-JEBBMFUQ.js} +1 -1
- package/dist/chunk-BREBCBG4.js +49 -0
- package/dist/{chunk-BQE7XAMQ.js → chunk-HICJBGGJ.js} +10 -10
- package/dist/{chunk-KMMC7BEF.js → chunk-MX6AZ7WD.js} +1 -1
- package/dist/chunk-NXTTKAQX.js +3 -0
- package/dist/chunk-URW2DJQF.js +1 -0
- package/dist/{engine-6SFURLSL.js → engine-DEBMZJBM.js} +1 -1
- package/dist/index.js +13 -13
- package/dist/{outbound-gateway-UCB57NPJ.js → outbound-gateway-DZTXBUTP.js} +1 -1
- package/package.json +2 -1
- package/dist/chunk-2EP27EGS.js +0 -1
- package/dist/chunk-DT2LX4XI.js +0 -49
- package/dist/chunk-LBLERTM4.js +0 -3
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{f as se}from"./chunk-742NWPTQ.js";import{a as oe,b as _,c as G,d as ae,e as de}from"./chunk-PQ7KPALO.js";import{c as f}from"./chunk-3DAK2XWP.js";import{z as g}from"zod/v4";import{v4 as St}from"uuid";import{randomUUID as me}from"crypto";import Ge from"crypto";var ce="1.0.0",A="";function Qe(e){let t=e.split(".").map(i=>parseInt(i,10)),r=t[0]??0,s=t[1]??0,n=t[2]??0;return(r&255)<<16|(s&255)<<8|n&255}var K=Qe(ce),Ke=35e3,le=15e3,He=1e4;function v(){return{channel_version:ce}}function Xe(e){return e.endsWith("/")?e:`${e}/`}function Je(){let e=Ge.randomBytes(4).readUInt32BE(0);return Buffer.from(String(e),"utf-8").toString("base64")}function Ye(e){let t={"Content-Type":"application/json",AuthorizationType:"ilink_bot_token","Content-Length":String(Buffer.byteLength(e.body,"utf-8")),"X-WECHAT-UIN":Je(),"iLink-App-Id":A,"iLink-App-ClientVersion":String(K)};return e.token?.trim()&&(t.Authorization=`Bearer ${e.token.trim()}`),e.routeTag&&(t.SKRouteTag=e.routeTag),t}async function O(e){let t=Xe(e.baseUrl),r=new URL(e.endpoint,t),s=Ye({token:e.token,routeTag:e.routeTag,body:e.body}),n=new AbortController,i=setTimeout(()=>n.abort(),e.timeoutMs);try{let o=await fetch(r.toString(),{method:"POST",headers:s,body:e.body,signal:n.signal});clearTimeout(i);let a=await o.text();if(!o.ok)throw new Error(`${e.label} ${o.status}: ${a}`);return a}catch(o){throw clearTimeout(i),o}}async function ue(e){let t=e.timeoutMs??Ke;try{let r=await O({baseUrl:e.baseUrl,endpoint:"ilink/bot/getupdates",body:JSON.stringify({get_updates_buf:e.get_updates_buf??"",base_info:v()}),token:e.token,routeTag:e.routeTag,timeoutMs:t,label:"getUpdates"});return JSON.parse(r)}catch(r){if(r instanceof Error&&r.name==="AbortError")return{ret:0,msgs:[],get_updates_buf:e.get_updates_buf};throw r}}var Ze=new Set([-2,-3]),Q=3,et=1e3;async function N(e){let t=(await import("./logger-BEG4WFIM.js")).getLogger("channels");for(let r=1;r<=Q;r++){let s=await O({baseUrl:e.baseUrl,endpoint:"ilink/bot/sendmessage",body:JSON.stringify({...e.body,base_info:v()}),token:e.token,routeTag:e.routeTag,timeoutMs:e.timeoutMs??le,label:"sendMessage"});t.info({status:200,responseBody:s.slice(0,300)},"apiFetch sendMessage response");try{let n=JSON.parse(s);if(n.ret&&n.ret!==0){if(Ze.has(n.ret)&&r<Q){t.warn({ret:n.ret,attempt:r,maxRetries:Q},"sendMessage: transient iLink error, retrying"),await new Promise(i=>setTimeout(i,et*r));continue}throw t.error({ret:n.ret,errmsg:n.errmsg,attempt:r},"sendMessage: iLink API returned non-zero ret"),new Error(`sendMessage failed: iLink ret=${n.ret}${n.errmsg?` errmsg=${n.errmsg}`:""}`)}}catch(n){if(n instanceof SyntaxError)t.warn({rawText:s.slice(0,200),attempt:r},"sendMessage: non-JSON response, treating as success");else throw n}return}}async function ge(e){await O({baseUrl:e.baseUrl,endpoint:"ilink/bot/sendtyping",body:JSON.stringify({...e.body,base_info:v()}),token:e.token,routeTag:e.routeTag,timeoutMs:e.timeoutMs??He,label:"sendTyping"})}async function pe(e){let t=await O({baseUrl:e.baseUrl,endpoint:"ilink/bot/getuploadurl",body:JSON.stringify({filekey:e.filekey,media_type:e.media_type,to_user_id:e.to_user_id,rawsize:e.rawsize,rawfilemd5:e.rawfilemd5,filesize:e.filesize,thumb_rawsize:e.thumb_rawsize,thumb_rawfilemd5:e.thumb_rawfilemd5,thumb_filesize:e.thumb_filesize,no_need_thumb:e.no_need_thumb,aeskey:e.aeskey,base_info:v()}),token:e.token,routeTag:e.routeTag,timeoutMs:e.timeoutMs??le,label:"getUploadUrl"});return JSON.parse(t)}var tt=5*6e4,nt=35e3,fe="3",h=new Map;function H(e){return Date.now()-e.startedAt<tt}function rt(){for(let[e,t]of h)H(t)||h.delete(e)}async function ye(e,t,r){let s=e.endsWith("/")?e:`${e}/`,n=new URL(`ilink/bot/get_bot_qrcode?bot_type=${encodeURIComponent(t)}`,s),i={"iLink-App-Id":A};r&&(i.SKRouteTag=r);let o=await fetch(n.toString(),{headers:i});if(!o.ok){let a=await o.text().catch(()=>"(unreadable)");throw new Error(`Failed to fetch QR code: ${o.status} ${o.statusText} body=${a}`)}return await o.json()}async function it(e,t,r){let s=e.endsWith("/")?e:`${e}/`,n=new URL(`ilink/bot/get_qrcode_status?qrcode=${encodeURIComponent(t)}`,s),i={"iLink-App-Id":A,"iLink-App-ClientVersion":String(K)};r&&(i.SKRouteTag=r);let o=new AbortController,a=setTimeout(()=>o.abort(),nt);try{let c=await fetch(n.toString(),{headers:i,signal:o.signal});clearTimeout(a);let l=await c.text();if(!c.ok)throw new Error(`Failed to poll QR status: ${c.status} ${c.statusText}`);return JSON.parse(l)}catch(c){if(clearTimeout(a),c instanceof Error&&c.name==="AbortError")return{status:"wait"};throw c}}async function he(e){let t=e.accountId||me();rt();let r=h.get(t);if(!e.force&&r&&H(r)&&r.qrcodeUrl)return{qrcodeUrl:r.qrcodeUrl,message:"QR code ready. Scan with WeChat.",sessionKey:t};if(!e.apiBaseUrl)return{message:"No baseUrl configured for this WeChat channel.",sessionKey:t};try{let s=e.botType||fe,n=await ye(e.apiBaseUrl,s,e.routeTag),i={sessionKey:t,id:me(),qrcode:n.qrcode,qrcodeUrl:n.qrcode_img_content,startedAt:Date.now()};return h.set(t,i),{qrcodeUrl:n.qrcode_img_content,message:"Scan the QR code with WeChat to connect.",sessionKey:t}}catch(s){return{message:`Failed to start login: ${String(s)}`,sessionKey:t}}}var st=3;async function be(e){let t=h.get(e.sessionKey);if(!t)return{connected:!1,message:"No active login session. Start QR login first."};if(!H(t))return h.delete(e.sessionKey),{connected:!1,message:"QR code expired. Please start again."};let r=Math.max(e.timeoutMs??48e4,1e3),s=Date.now()+r,n=1;for(;Date.now()<s;){try{let i=await it(e.apiBaseUrl,t.qrcode,e.routeTag);switch(t.status=i.status,i.status){case"wait":break;case"scaned":break;case"expired":{if(n++,n>st)return h.delete(e.sessionKey),{connected:!1,message:"Login timeout: QR expired multiple times."};try{let o=e.botType||fe,a=await ye(e.apiBaseUrl,o,e.routeTag);t.qrcode=a.qrcode,t.qrcodeUrl=a.qrcode_img_content,t.startedAt=Date.now()}catch(o){return h.delete(e.sessionKey),{connected:!1,message:`QR refresh failed: ${String(o)}`}}break}case"confirmed":return i.ilink_bot_id?(h.delete(e.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!"}):(h.delete(e.sessionKey),{connected:!1,message:"Login failed: server did not return bot ID."})}}catch(i){return h.delete(e.sessionKey),{connected:!1,message:`Login failed: ${String(i)}`}}await new Promise(i=>setTimeout(i,1e3))}return h.delete(e.sessionKey),{connected:!1,message:"Login timeout. Please try again."}}import C,{promises as P}from"fs";import x from"path";import{homedir as ne}from"os";var F={IMAGE:1,VIDEO:2,FILE:3,VOICE:4},$={NONE:0,USER:1,BOT:2},m={NONE:0,TEXT:1,IMAGE:2,VOICE:3,FILE:4,VIDEO:5},L={NEW:0,GENERATING:1,FINISH:2},_e={TYPING:1,CANCEL:2};var ot=f("channels"),X=-14,D=3600*1e3,M=new Map;function we(e){let t=Date.now()+D;M.set(e,t),ot.info({channelId:e},`Session paused until ${new Date(t).toISOString()} (${D/1e3}s)`)}function B(e){let t=M.get(e);return t===void 0?!1:Date.now()>=t?(M.delete(e),!1):!0}function xe(e){let t=M.get(e);if(t===void 0)return 0;let r=t-Date.now();return r<=0?(M.delete(e),0):r}function Ie(e){M.delete(e)}import Ae from"fs";import ve from"path";import{homedir as mt}from"os";import{createCipheriv as at,createDecipheriv as dt}from"crypto";function Te(e,t){let r=at("aes-128-ecb",t,null);return Buffer.concat([r.update(e),r.final()])}function Ue(e,t){let r=dt("aes-128-ecb",t,null);return Buffer.concat([r.update(e),r.final()])}function ke(e){return Math.ceil((e+1)/16)*16}function J(e,t){return`${t}/download?encrypted_query_param=${encodeURIComponent(e)}`}function Ce(e){return`${e.cdnBaseUrl}/upload?encrypted_query_param=${encodeURIComponent(e.uploadParam)}&filekey=${encodeURIComponent(e.filekey)}`}var Qt=f("channels");function ct(e){let t=Buffer.from(e,"base64");if(t.length===16)return t;if(t.length===32&&/^[0-9a-fA-F]{32}$/.test(t.toString("ascii")))return Buffer.from(t.toString("ascii"),"hex");throw new Error(`aes_key must decode to 16 raw bytes or 32-char hex, got ${t.length} bytes`)}async function Me(e){let t=await fetch(e);if(!t.ok)throw new Error(`CDN download ${t.status} ${t.statusText}`);return Buffer.from(await t.arrayBuffer())}async function R(e){let{encryptQueryParam:t,aesKeyBase64:r,cdnBaseUrl:s,fullUrl:n}=e,i=ct(r),o=n?.trim()||(t?J(t,s):null);if(!o)throw new Error("CDN download: need full_url or encrypt_query_param");let a=await Me(o);return Ue(a,i)}async function Re(e){let{encryptQueryParam:t,cdnBaseUrl:r,fullUrl:s}=e,n=s?.trim()||(t?J(t,r):null);if(!n)throw new Error("CDN download: need full_url or encrypt_query_param");return Me(n)}var W=f("channels"),Ee=24e3;function lt(e,t){let r=e.byteLength,s=44+r,n=Buffer.allocUnsafe(s),i=0;return n.write("RIFF",i),i+=4,n.writeUInt32LE(s-8,i),i+=4,n.write("WAVE",i),i+=4,n.write("fmt ",i),i+=4,n.writeUInt32LE(16,i),i+=4,n.writeUInt16LE(1,i),i+=2,n.writeUInt16LE(1,i),i+=2,n.writeUInt32LE(t,i),i+=4,n.writeUInt32LE(t*2,i),i+=4,n.writeUInt16LE(2,i),i+=2,n.writeUInt16LE(16,i),i+=2,n.write("data",i),i+=4,n.writeUInt32LE(r,i),i+=4,Buffer.from(e.buffer,e.byteOffset,e.byteLength).copy(n,i),n}async function Se(e){try{let{decode:t}=await import("silk-wasm");W.debug(`silkToWav: decoding ${e.length} bytes of SILK`);let r=await t(e,Ee);W.debug(`silkToWav: decoded duration=${r.duration}ms pcmBytes=${r.data.byteLength}`);let s=lt(r.data,Ee);return W.debug(`silkToWav: WAV size=${s.length}`),s}catch(t){return W.warn(`silkToWav: transcode failed, will use raw silk err=${String(t)}`),null}}import ut from"path";var gt={".pdf":"application/pdf",".doc":"application/msword",".docx":"application/vnd.openxmlformats-officedocument.wordprocessingml.document",".xls":"application/vnd.ms-excel",".xlsx":"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",".ppt":"application/vnd.ms-powerpoint",".pptx":"application/vnd.openxmlformats-officedocument.presentationml.presentation",".txt":"text/plain",".csv":"text/csv",".zip":"application/zip",".tar":"application/x-tar",".gz":"application/gzip",".mp3":"audio/mpeg",".ogg":"audio/ogg",".wav":"audio/wav",".amr":"audio/amr",".silk":"audio/x-silk",".mp4":"video/mp4",".mov":"video/quicktime",".webm":"video/webm",".mkv":"video/x-matroska",".avi":"video/x-msvideo",".png":"image/png",".jpg":"image/jpeg",".jpeg":"image/jpeg",".gif":"image/gif",".webp":"image/webp",".bmp":"image/bmp"},pt={"image/jpeg":".jpg","image/jpg":".jpg","image/png":".png","image/gif":".gif","image/webp":".webp","image/bmp":".bmp","video/mp4":".mp4","video/quicktime":".mov","video/webm":".webm","video/x-matroska":".mkv","video/x-msvideo":".avi","audio/mpeg":".mp3","audio/ogg":".ogg","audio/wav":".wav","audio/amr":".amr","audio/x-silk":".silk","application/pdf":".pdf","application/zip":".zip","application/x-tar":".tar","application/gzip":".gz","text/plain":".txt","text/csv":".csv"};function q(e){let t=ut.extname(e).toLowerCase();return gt[t]??"application/octet-stream"}function Pe(e){let t=e.split(";")[0].trim().toLowerCase();return pt[t]??".bin"}var k=f("channels"),Oe=100*1024*1024;function ft(e){return Pe(e)??".bin"}async function E(e,t,r,s,n=Oe,i){if(e.length>n)throw new Error(`Media too large: ${e.length} bytes exceeds ${n} bytes`);let o=ve.join(mt(),".adam","wechat","media",s,r);await Ae.promises.mkdir(o,{recursive:!0});let a;if(i&&/^[a-zA-Z0-9._-]+$/.test(i))a=i;else{let l=t?ft(t):".bin",d=Date.now(),u=Math.random().toString(36).slice(2,7);a=`${d}-${u}${l}`}let c=ve.join(o,a);return await Ae.promises.writeFile(c,e),k.debug(`saveMedia: saved ${e.length} bytes to ${c}`),c}async function Ne(e,t){let{cdnBaseUrl:r,channelId:s}=t;if(e.type===m.IMAGE){let n=e.image_item;if(!n?.media?.encrypt_query_param&&!n?.media?.full_url)return null;let i=n.aeskey?Buffer.from(n.aeskey,"hex").toString("base64"):n.media?.aes_key;try{let o=i?await R({encryptQueryParam:n.media?.encrypt_query_param,aesKeyBase64:i,cdnBaseUrl:r,fullUrl:n.media?.full_url}):await Re({encryptQueryParam:n.media?.encrypt_query_param,cdnBaseUrl:r,fullUrl:n.media?.full_url});return{path:await E(o,"image/png","inbound",s),mimeType:"image/png",type:"image"}}catch(o){return k.error({channelId:s},`Image download/decrypt failed: ${String(o)}`),null}}if(e.type===m.VOICE){let n=e.voice_item;if(!n?.media?.encrypt_query_param&&!n?.media?.full_url||!n?.media?.aes_key)return null;try{let i=await R({encryptQueryParam:n.media.encrypt_query_param,aesKeyBase64:n.media.aes_key,cdnBaseUrl:r,fullUrl:n.media.full_url}),o=await Se(i);if(o){let a=await E(o,"audio/wav","inbound",s);return k.debug(`Voice: saved WAV to ${a}`),{path:a,mimeType:"audio/wav",type:"audio"}}else{let a=await E(i,"audio/silk","inbound",s);return k.debug(`Voice: silk transcode unavailable, saved raw SILK to ${a}`),{path:a,mimeType:"audio/silk",type:"audio"}}}catch(i){return k.error({channelId:s},`Voice download/transcode failed: ${String(i)}`),null}}if(e.type===m.FILE){let n=e.file_item;if(!n?.media?.encrypt_query_param&&!n?.media?.full_url||!n?.media?.aes_key)return null;try{let i=await R({encryptQueryParam:n.media.encrypt_query_param,aesKeyBase64:n.media.aes_key,cdnBaseUrl:r,fullUrl:n.media.full_url}),o=q(n.file_name??"file.bin");return{path:await E(i,o,"inbound",s,Oe,n.file_name),mimeType:o,type:"file"}}catch(i){return k.error({channelId:s},`File download failed: ${String(i)}`),null}}if(e.type===m.VIDEO){let n=e.video_item;if(!n?.media?.encrypt_query_param&&!n?.media?.full_url||!n?.media?.aes_key)return null;try{let i=await R({encryptQueryParam:n.media.encrypt_query_param,aesKeyBase64:n.media.aes_key,cdnBaseUrl:r,fullUrl:n.media.full_url});return{path:await E(i,"video/mp4","inbound",s),mimeType:"video/mp4",type:"video"}}catch(i){return k.error({channelId:s},`Video download failed: ${String(i)}`),null}}return null}import Le from"path";import Y from"crypto";import yt from"fs/promises";var T=f("channels"),j=3;async function ht(e){let{buf:t,uploadFullUrl:r,uploadParam:s,filekey:n,cdnBaseUrl:i,label:o,aeskey:a}=e,c=Te(t,a),l=r?.trim(),d;if(l)d=l;else if(s)d=Ce({cdnBaseUrl:i,uploadParam:s,filekey:n});else throw new Error(`${o}: CDN upload URL missing (need upload_full_url or upload_param)`);T.debug(`${o}: CDN POST url=${d} ciphertextSize=${c.length}`);let u,y;for(let b=1;b<=j;b++)try{let p=await fetch(d,{method:"POST",headers:{"Content-Type":"application/octet-stream"},body:new Uint8Array(c)});if(p.status>=400&&p.status<500){let I=p.headers.get("x-error-message")??await p.text();throw T.error(`${o}: CDN client error attempt=${b} status=${p.status} errMsg=${I}`),new Error(`CDN upload client error ${p.status}: ${I}`)}if(p.status!==200){let I=p.headers.get("x-error-message")??`status ${p.status}`;throw T.error(`${o}: CDN server error attempt=${b} status=${p.status} errMsg=${I}`),new Error(`CDN upload server error: ${I}`)}if(u=p.headers.get("x-encrypted-param")??void 0,!u)throw T.error(`${o}: CDN response missing x-encrypted-param header attempt=${b}`),new Error("CDN upload response missing x-encrypted-param header");T.debug(`${o}: CDN upload success attempt=${b}`);break}catch(p){if(y=p,p instanceof Error&&p.message.includes("client error"))throw p;b<j?T.warn(`${o}: attempt ${b} failed, retrying... err=${String(p)}`):T.error(`${o}: all ${j} attempts failed err=${String(p)}`)}if(!u)throw y instanceof Error?y:new Error(`CDN upload failed after ${j} attempts`);return{downloadParam:u}}async function Z(e){let{filePath:t,toUserId:r,opts:s,cdnBaseUrl:n,mediaType:i,label:o}=e,a=await yt.readFile(t),c=a.length,l=Y.createHash("md5").update(a).digest("hex"),d=ke(c),u=Y.randomBytes(16).toString("hex"),y=Y.randomBytes(16);T.debug(`${o}: file=${t} rawsize=${c} filesize=${d} md5=${l} filekey=${u}`);let b=await pe({...s,filekey:u,media_type:i,to_user_id:r,rawsize:c,rawfilemd5:l,filesize:d,no_need_thumb:!0,aeskey:y.toString("hex")}),p=b.upload_full_url?.trim(),I=b.upload_param;if(!p&&!I)throw new Error(`${o}: getUploadUrl returned no upload URL (need upload_full_url or upload_param)`);let{downloadParam:ze}=await ht({buf:a,uploadFullUrl:p||void 0,uploadParam:I??void 0,filekey:u,cdnBaseUrl:n,aeskey:y,label:`${o}[orig filekey=${u}]`});return{filekey:u,downloadEncryptedQueryParam:ze,aeskey:y.toString("hex"),fileSize:c,fileSizeCiphertext:d}}async function Fe(e){return Z({...e,mediaType:F.IMAGE,label:"uploadImageToWeixin"})}async function $e(e){return Z({...e,mediaType:F.VIDEO,label:"uploadVideoToWeixin"})}async function ee(e){return Z({...e,mediaType:F.FILE,label:"uploadFileAttachmentToWeixin"})}var S=f("channels");function bt(){return`adam-wechat-${Date.now()}-${Math.random().toString(36).slice(2,7)}`}function _t(e){let t=e;return t=t.replace(/```[^\n]*\n?([\s\S]*?)```/g,(r,s)=>s.trim()),t=t.replace(/!\[[^\]]*\]\([^)]*\)/g,""),t=t.replace(/\[([^\]]+)\]\([^)]*\)/g,"$1"),t=t.replace(/^\|[\s:|-]+\|$/gm,""),t=t.replace(/^\|(.+)\|$/gm,(r,s)=>s.split("|").map(n=>n.trim()).join(" ")),t}async function te(e){let{to:t,text:r,mediaItem:s,opts:n,label:i}=e,o=[],a=_t(r);a&&o.push({type:m.TEXT,text_item:{text:a}}),o.push(s);let c="";for(let l of o){c=bt();let d={msg:{from_user_id:"",to_user_id:t,client_id:c,message_type:$.BOT,message_state:L.FINISH,item_list:[l],context_token:n.contextToken}};await N({baseUrl:n.baseUrl,token:n.token,routeTag:n.routeTag,body:d})}return S.debug(`${i}: sent to=${t} messageId=${c}`),{messageId:c}}async function wt(e){let{to:t,text:r,uploaded:s,opts:n}=e,i={type:m.IMAGE,image_item:{media:{encrypt_query_param:s.downloadEncryptedQueryParam,aes_key:Buffer.from(s.aeskey).toString("base64"),encrypt_type:1},mid_size:s.fileSizeCiphertext}};return te({to:t,text:r,mediaItem:i,opts:n,label:"sendImageMessage"})}async function xt(e){let{to:t,text:r,uploaded:s,opts:n}=e,i={type:m.VIDEO,video_item:{media:{encrypt_query_param:s.downloadEncryptedQueryParam,aes_key:Buffer.from(s.aeskey).toString("base64"),encrypt_type:1},video_size:s.fileSizeCiphertext}};return te({to:t,text:r,mediaItem:i,opts:n,label:"sendVideoMessage"})}async function De(e){let{to:t,text:r,fileName:s,uploaded:n,opts:i}=e,o={type:m.FILE,file_item:{media:{encrypt_query_param:n.downloadEncryptedQueryParam,aes_key:Buffer.from(n.aeskey).toString("base64"),encrypt_type:1},file_name:s,len:String(n.fileSize)}};return te({to:t,text:r,mediaItem:o,opts:i,label:"sendFileMessage"})}async function Be(e){let{filePath:t,to:r,text:s,opts:n,cdnBaseUrl:i}=e,o=q(t),a={baseUrl:n.baseUrl,token:n.token,routeTag:n.routeTag};if(o.startsWith("video/")){S.debug(`sendWeixinMediaFile: uploading video filePath=${t} to=${r}`);let d=await $e({filePath:t,toUserId:r,opts:a,cdnBaseUrl:i});return xt({to:r,text:s,uploaded:d,opts:n})}if(o.startsWith("image/")){S.debug(`sendWeixinMediaFile: uploading image filePath=${t} to=${r}`);let d=await Fe({filePath:t,toUserId:r,opts:a,cdnBaseUrl:i});return wt({to:r,text:s,uploaded:d,opts:n})}if(o.startsWith("audio/")){let d=Le.basename(t);S.debug(`sendWeixinMediaFile: uploading audio as file filePath=${t} name=${d} to=${r}`);let u=await ee({filePath:t,fileName:d,toUserId:r,opts:a,cdnBaseUrl:i});return De({to:r,text:s,fileName:d,uploaded:u,opts:n})}let c=Le.basename(t);S.debug(`sendWeixinMediaFile: uploading file attachment filePath=${t} name=${c} to=${r}`);let l=await ee({filePath:t,fileName:c,toUserId:r,opts:a,cdnBaseUrl:i});return De({to:r,text:s,fileName:c,uploaded:l,opts:n})}var w=f("channels"),We="https://novac2c.cdn.weixin.qq.com/c2c",re=new Map;function je(e){return x.join(ne(),".adam","wechat",`${e}.context-tokens.json`)}function It(e){let t=je(e);try{let r=C.readFileSync(t,"utf-8"),s=JSON.parse(r);for(let[n,i]of Object.entries(s))typeof i=="string"&&i&&re.set(`${e}:${n}`,i);w.debug({channelId:e,count:Object.keys(s).length},"Restored context tokens from disk")}catch{}}function Tt(e,t,r){let s=je(e);try{let n={};try{let o=C.readFileSync(s,"utf-8");n=JSON.parse(o)}catch{}n[t]=r;let i=x.dirname(s);C.mkdirSync(i,{recursive:!0}),C.writeFileSync(s,JSON.stringify(n),"utf-8")}catch(n){w.warn({channelId:e,userId:t},`Failed to persist context token: ${String(n)}`)}}function Ut(e,t,r){re.set(`${e}:${t}`,r),Tt(e,t,r)}function qe(e,t){return re.get(`${e}:${t}`)}function Ve(e){return x.join(ne(),".adam","wechat",`${e}.sync`)}function kt(e){try{return C.readFileSync(Ve(e),"utf-8")}catch{return""}}function Ct(e,t){let r=Ve(e);C.mkdirSync(x.dirname(r),{recursive:!0}),C.writeFileSync(r,t,"utf-8")}var Mt=0;function Rt(){return`adam-wechat-${Date.now()}-${++Mt}`}var V=class{platform="wechat";id;config;status="disconnected";messageHandler=null;pollAbort=null;getUpdatesBuf="";constructor(t,r){if(this.id=t,!r.baseUrl)throw new Error("WeChat adapter requires baseUrl");this.config=r}async connect(){if(!this.config.botToken)throw new Error("WeChat adapter requires botToken. Complete QR login first.");this.status="connecting",this.getUpdatesBuf=kt(this.id),It(this.id),this.pollAbort=new AbortController,this.status="connected",w.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",w.info({channelId:this.id},"WeChat adapter disconnected")}getStatus(){return this.status==="connected"&&B(this.id)?"error":this.status}async sendMessage(t,r){if(B(this.id)){let o=Math.ceil(xe(this.id)/6e4);throw new Error(`WeChat session paused, ${o} min remaining. Re-scan QR to reconnect.`)}let s=Rt(),n=qe(this.id,t),i=this.config.cdnBaseUrl??We;if(r.mediaUrl)try{let o=!r.mediaUrl.includes("://")||r.mediaUrl.startsWith("file://"),a=x.join(ne(),".adam","wechat","media","outbound-tmp");await P.mkdir(a,{recursive:!0});let c=this.getExtensionFromMediaType(r.mediaType),l;if(o){let u=r.mediaUrl.startsWith("file://")?new URL(r.mediaUrl).pathname:x.isAbsolute(r.mediaUrl)?r.mediaUrl:x.resolve(r.mediaUrl),y=await P.readFile(u);l=x.join(a,`${Date.now()}-${Math.random().toString(36).slice(2,7)}${c}`),await P.writeFile(l,y)}else{let u=await fetch(r.mediaUrl);if(!u.ok)throw new Error(`Failed to fetch media: ${u.status}`);let y=Buffer.from(await u.arrayBuffer());l=x.join(a,`${Date.now()}-${Math.random().toString(36).slice(2,7)}${c}`),await P.writeFile(l,y)}let d=await Be({filePath:l,to:t,text:r.content??"",opts:{baseUrl:this.config.baseUrl,token:this.config.botToken,routeTag:this.config.routeTag,contextToken:n},cdnBaseUrl:i});return await P.unlink(l).catch(()=>{}),d.messageId}catch(o){throw w.error({channelId:this.id},`sendMessage media handling failed: ${String(o)}`),o}return await N({baseUrl:this.config.baseUrl,token:this.config.botToken,routeTag:this.config.routeTag,body:{msg:{from_user_id:"",to_user_id:t,client_id:s,message_type:$.BOT,message_state:L.FINISH,item_list:r.content?[{type:m.TEXT,text_item:{text:r.content}}]:void 0,context_token:n}}}),s}onMessage(t){this.messageHandler=t}async sendTypingIndicator(t){if(B(this.id))return;let r=qe(this.id,t);try{await ge({baseUrl:this.config.baseUrl,token:this.config.botToken,routeTag:this.config.routeTag,body:{ilink_user_id:t,status:_e.TYPING}})}catch{}}updateConfig(t){Object.assign(this.config,t)}async startLongPoll(){let t=this.pollAbort?.signal,r=0,s=3,n=3e4,i=2e3;for(;!t?.aborted;)try{let o=await ue({baseUrl:this.config.baseUrl,token:this.config.botToken,routeTag:this.config.routeTag,get_updates_buf:this.getUpdatesBuf});if(o.ret===X||o.errcode===X){we(this.id),this.status="error",w.error({channelId:this.id},"Session expired (errcode=-14), pausing for 1 hour"),await this.sleep(D,t),Ie(this.id),this.status="connected";continue}if(o.ret!==void 0&&o.ret!==0||o.errcode!==void 0&&o.errcode!==0){r++,w.error({channelId:this.id,ret:o.ret,errcode:o.errcode},"getUpdates API error"),r>=s?(r=0,await this.sleep(n,t)):await this.sleep(i,t);continue}r=0,o.get_updates_buf&&(this.getUpdatesBuf=o.get_updates_buf,Ct(this.id,o.get_updates_buf));for(let c of o.msgs??[])await this.processInbound(c)}catch(o){if(t?.aborted)return;r++,w.error({channelId:this.id,error:o},"getUpdates error"),r>=s?(r=0,await this.sleep(n,t)):await this.sleep(i,t)}}async processInbound(t){if(!this.messageHandler)return;let r=!!t.group_id,s=r?t.group_id:t.from_user_id??"",n=t.from_user_id??"";t.context_token&&s&&Ut(this.id,s,t.context_token);let i="",o,a=[];for(let d of t.item_list??[])d.type===m.TEXT&&d.text_item?.text&&(i+=d.text_item.text),d.type===m.IMAGE&&(o="image",a.push(d)),d.type===m.VOICE&&(o="audio",a.push(d),d.voice_item?.text&&!i&&(i=d.voice_item.text)),d.type===m.FILE&&(o="file",a.push(d)),d.type===m.VIDEO&&(o="video",a.push(d));if(!i&&!o)return;let c;if(a.length>0){let d=this.config.cdnBaseUrl??We;try{let u=await Ne(a[0],{cdnBaseUrl:d,channelId:this.id});u&&(c=u.path,o=u.type)}catch(u){w.error({channelId:this.id},`Media download failed: ${String(u)}`)}}let l={channelId:this.id,platform:"wechat",chatId:s,senderId:n,content:i,mediaType:o,mediaPath:c,isGroup:r,timestamp:t.create_time_ms??Date.now(),raw:t};this.messageHandler(l)}getExtensionFromMediaType(t){switch(t){case"image":return".png";case"video":return".mp4";case"audio":return".mp3";default:return".bin"}}sleep(t,r){return new Promise((s,n)=>{let i=setTimeout(s,t);r?.addEventListener("abort",()=>{clearTimeout(i),n(new Error("aborted"))},{once:!0})})}};var Et=f("channels"),z=class{platform="discord";id;config;status="disconnected";messageHandler=null;client=null;constructor(t,r){if(this.id=t,!r.botToken)throw new Error("Discord adapter requires botToken");this.config=r}async connect(){this.status="connecting";try{let{Client:t,GatewayIntentBits:r}=await import("discord.js");this.client=new t({intents:[r.Guilds,r.GuildMessages,r.MessageContent,r.DirectMessages]});let s=this.client;s.on("messageCreate",n=>{if(!this.messageHandler||n.author.bot||this.config.allowedGuildIds?.length&&n.guildId&&!this.config.allowedGuildIds.includes(n.guildId))return;let i={channelId:this.id,platform:"discord",chatId:n.channelId,senderId:n.author.id,senderName:n.author.displayName??n.author.username,content:n.content,isGroup:!!n.guildId,timestamp:n.createdTimestamp,raw:n};this.messageHandler(i)}),await s.login(this.config.botToken),this.status="connected",Et.info({channelId:this.id},"Discord bot connected")}catch(t){throw this.status="error",t}}async disconnect(){this.client&&await this.client.destroy(),this.client=null,this.status="disconnected"}getStatus(){return this.status}async sendMessage(t,r){if(!this.client)throw new Error("Discord client not connected");let n=await this.client.channels.fetch(t);if(!n||!("send"in n))throw new Error(`Channel ${t} not found or not text channel`);return(await n.send({content:r.content,reply:r.replyToMessageId?{messageReference:r.replyToMessageId}:void 0})).id}onMessage(t){this.messageHandler=t}async sendTypingIndicator(t){if(!this.client)return;let s=await this.client.channels.fetch(t);s&&"sendTyping"in s&&await s.sendTyping()}};var U=g.object({id:g.string().uuid()}),Pt=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()}),At=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()}),ie;function Vn(e){ie=e}function zn(){return ie}async function Gn(e){let t=ie;e.get("/channels",{schema:{tags:["Channels"],summary:"List channels",querystring:{type:"object",properties:{enabled:{type:"boolean"}}}}},async(r,s)=>({channels:ae(r.query.enabled)})),e.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 n=Pt.safeParse(r.body);if(!n.success)return s.status(400).send({code:"VALIDATION_ERROR",message:g.prettifyError(n.error)});let{name:i,platform:o,config:a,enabled:c,linkedRoleId:l,allowedChatIds:d}=n.data,u={id:St(),name:i,platform:o,enabled:c,status:"disconnected",config:a,linkedRoleId:l,allowedChatIds:d,createdAt:Date.now(),messageCount:0};return oe(u),s.status(201).send({channel:u})}),e.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 n=U.safeParse(r.params);if(!n.success)return s.status(400).send({code:"VALIDATION_ERROR",message:g.prettifyError(n.error)});let i=_(n.data.id);return i?{channel:i}:s.status(404).send({code:"NOT_FOUND",message:"Channel not found"})}),e.patch("/channels/:id",{schema:{tags:["Channels"],summary:"Update channel",params:{type:"object",required:["id"],properties:{id:{type:"string",format:"uuid"}}},body:{type:"object",properties:{name:{type:"string"},enabled:{type:"boolean"},config:{type:"object"},linkedRoleId:{type:"string"},allowedChatIds:{type:"array",items:{type:"string"}}}}}},async(r,s)=>{let n=U.safeParse(r.params);if(!n.success)return s.status(400).send({code:"VALIDATION_ERROR",message:g.prettifyError(n.error)});let i=_(n.data.id);if(!i)return s.status(404).send({code:"NOT_FOUND",message:"Channel not found"});let o=At.safeParse(r.body);return o.success?(G(i.id,o.data),{channel:_(i.id)}):s.status(400).send({code:"VALIDATION_ERROR",message:g.prettifyError(o.error)})}),e.delete("/channels/:id",{schema:{tags:["Channels"],summary:"Delete channel",params:{type:"object",required:["id"],properties:{id:{type:"string",format:"uuid"}}}}},async(r,s)=>{let n=U.safeParse(r.params);if(!n.success)return s.status(400).send({code:"VALIDATION_ERROR",message:g.prettifyError(n.error)});let i=_(n.data.id);return i?(de(i.id),s.status(204).send()):s.status(404).send({code:"NOT_FOUND",message:"Channel not found"})}),e.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 n=U.safeParse(r.params);if(!n.success)return s.status(400).send({code:"VALIDATION_ERROR",message:g.prettifyError(n.error)});if(!t)return s.status(501).send({code:"NOT_IMPLEMENTED",message:"Channel manager not initialized"});let i=_(n.data.id);if(!i)return s.status(404).send({code:"NOT_FOUND",message:"Channel not found"});if(!t.hasAdapter(i.id)&&i.platform==="discord"){let o=i.config;if(!o.botToken)return s.status(400).send({code:"MISSING_CONFIG",message:"Discord channel requires botToken in config"});let a=new z(i.id,{botToken:o.botToken});await t.addChannel(i,a)}if(!t.hasAdapter(i.id))return s.status(400).send({code:"NO_ADAPTER",message:"No adapter registered for this channel. Install the appropriate adapter first."});try{return await t.connectChannel(i.id),{channelId:i.id,status:"connected"}}catch(o){return s.status(500).send({code:"CONNECT_FAILED",message:String(o)})}}),e.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 n=U.safeParse(r.params);if(!n.success)return s.status(400).send({code:"VALIDATION_ERROR",message:g.prettifyError(n.error)});if(!t)return s.status(501).send({code:"NOT_IMPLEMENTED",message:"Channel manager not initialized"});let i=_(n.data.id);return i?(await t.disconnectChannel(i.id),{channelId:i.id,status:"disconnected"}):s.status(404).send({code:"NOT_FOUND",message:"Channel not found"})}),e.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 n=U.safeParse(r.params);if(!n.success)return s.status(400).send({code:"VALIDATION_ERROR",message:g.prettifyError(n.error)});let i=_(n.data.id);if(!i)return s.status(404).send({code:"NOT_FOUND",message:"Channel not found"});let{limit:o=50,offset:a=0}=r.query;return{messages:se(i.id,o,a)}}),e.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 n=U.safeParse(r.params);if(!n.success)return s.status(400).send({code:"VALIDATION_ERROR",message:g.prettifyError(n.error)});let i=_(n.data.id);if(!i)return s.status(404).send({code:"NOT_FOUND",message:"Channel not found"});if(i.platform!=="wechat")return s.status(400).send({code:"INVALID_PLATFORM",message:"Channel is not a WeChat channel"});let o=i.config;return await he({apiBaseUrl:o.baseUrl,routeTag:o.routeTag})}),e.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 n=U.safeParse(r.params);if(!n.success)return s.status(400).send({code:"VALIDATION_ERROR",message:g.prettifyError(n.error)});let i=_(n.data.id);if(!i)return s.status(404).send({code:"NOT_FOUND",message:"Channel not found"});if(i.platform!=="wechat")return s.status(400).send({code:"INVALID_PLATFORM",message:"Channel is not a WeChat channel"});let o=i.config,{sessionKey:a,timeoutMs:c}=r.body??{},l=await be({sessionKey:a??"",apiBaseUrl:o.baseUrl,timeoutMs:c??12e4,routeTag:o.routeTag});if(l.connected&&l.botToken){let d={...o,botToken:l.botToken,accountId:l.accountId,baseUrl:l.baseUrl??o.baseUrl,userId:l.userId};if(G(i.id,{config:d}),t){let u=new V(i.id,d),y=_(i.id);y&&await t.addChannel(y,u)}}return{connected:l.connected,accountId:l.accountId,message:l.message}})}export{V as a,z as b,Vn as c,zn as d,Gn as e};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{a,b,c,d}from"./chunk-
|
|
1
|
+
import{a,b,c,d}from"./chunk-MX6AZ7WD.js";import"./chunk-NXTTKAQX.js";import"./chunk-KICPHTI2.js";import"./chunk-5ASEAZCR.js";import"./chunk-742NWPTQ.js";import"./chunk-PQ7KPALO.js";import"./chunk-FDWW245P.js";import"./chunk-L7426WNY.js";import"./chunk-L7JP7DUO.js";import"./chunk-PCSZW2PE.js";import"./chunk-SFUS33SO.js";import"./chunk-3DAK2XWP.js";import"./chunk-FCV2DPZQ.js";export{a as DeliveryEngine,b as getDeliveryEngine,c as initDeliveryEngine,d as stopDeliveryEngine};
|