import{B as e,M as t,d as n,n as r,t as i}from"./server-DzOdtq8A.js";import{t as a}from"./lib-Cf16LgKj.js";import{n as o,t as s}from"./stdio-Cg20AQ5W.js";import{basename as c,extname as l,join as u}from"node:path";import{chmodSync as d,existsSync as f,mkdirSync as p,readFileSync as m,unlinkSync as ee,writeFileSync as h}from"node:fs";import{homedir as g,tmpdir as te}from"node:os";import{createCipheriv as ne,createDecipheriv as re,createHash as ie,randomBytes as _,randomUUID as v}from"node:crypto";var y={NONE:0,USER:1,BOT:2},b={NONE:0,TEXT:1,IMAGE:2,VOICE:3,FILE:4,VIDEO:5},x={NEW:0,GENERATING:1,FINISH:2},S={IMAGE:1,VIDEO:2,FILE:3,VOICE:4},ae={TYPING:1,CANCEL:2},oe=`0.1.0`;function C(){return{channel_version:oe}}function w(){return _(4).toString(`base64`)}function T(e){let t={"Content-Type":`application/json`,"X-WECHAT-UIN":w()};return e&&(t.AuthorizationType=`ilink_bot_token`,t.Authorization=`Bearer ${e}`),t}async function E(e,t,n,r,i=4e4,a){let o=new AbortController,s=setTimeout(()=>o.abort(),i);a&&a.addEventListener(`abort`,()=>o.abort(),{once:!0});try{let i=await fetch(`${e}${t}`,{method:`POST`,headers:T(r),body:JSON.stringify(n),signal:o.signal});if(!i.ok)throw Error(`HTTP ${i.status}: ${i.statusText}`);return await i.json()}finally{clearTimeout(s)}}async function se(e,t,n,r){let i={get_updates_buf:n,base_info:C()};try{return await E(e,`/ilink/bot/getupdates`,i,t,4e4,r)}catch(e){if(e instanceof Error&&e.name===`AbortError`)return{ret:0,msgs:[],get_updates_buf:n};throw e}}async function D(e,t,n){await E(e,`/ilink/bot/sendmessage`,{msg:n,base_info:C()},t)}async function O(e,t,n){return E(e,`/ilink/bot/getuploadurl`,{...n,base_info:C()},t)}async function k(e,t,n,r){return E(e,`/ilink/bot/getconfig`,{ilink_user_id:n,context_token:r,base_info:C()},t)}async function A(e,t,n){return E(e,`/ilink/bot/sendtyping`,{...n,base_info:C()},t)}var j=`https://ilinkai.weixin.qq.com`,M=`https://novac2c.cdn.weixin.qq.com/c2c`;function N(){let e=process.env.WEIXIN_STATE_DIR||u(g(),`.claude`,`channels`,`weixin`);return f(e)||p(e,{recursive:!0}),e}function P(){return u(N(),`account.json`)}function F(){let e=P();if(!f(e))return null;try{return JSON.parse(m(e,`utf-8`))}catch{return null}}function ce(e){let t=P();h(t,JSON.stringify(e,null,2),`utf-8`),d(t,384)}function le(){let e=P();f(e)&&ee(e)}var ue=a();async function I(e){let t=await(0,ue.toString)(e,{type:`terminal`,errorCorrectionLevel:`L`,small:!0});process.stderr.write(`${t}\n`)}async function L(e){let t=await fetch(`${e}/ilink/bot/get_bot_qrcode?bot_type=3`);if(!t.ok)throw Error(`Failed to get QR code: HTTP ${t.status}`);let n=await t.json();if(!n.qrcode)throw Error(`No qrcode in response`);let r=n.qrcode_img_content||``;return r&&await I(r),{qrcodeUrl:r,qrcodeId:n.qrcode,message:`Scan the QR code with WeChat to connect.`}}async function R(e){let{qrcodeId:t,apiBaseUrl:n,timeoutMs:r=48e4,maxRetries:i=3}=e,a=Date.now()+r,o=t,s=0;for(;Date.now()<a;){try{let e=new AbortController,t=setTimeout(()=>e.abort(),6e4),r=await fetch(`${n}/ilink/bot/get_qrcode_status?qrcode=${encodeURIComponent(o)}`,{headers:{"iLink-App-ClientVersion":`1`},signal:e.signal});if(clearTimeout(t),!r.ok)throw Error(`HTTP ${r.status}`);let a=await r.json();switch(a.status){case`confirmed`:return{connected:!0,token:a.bot_token,accountId:a.ilink_bot_id,baseUrl:a.baseurl,userId:a.ilink_user_id,message:`Connected to WeChat successfully!`};case`scaned`:process.stderr.write(`QR code scanned, waiting for confirmation...
`);break;case`expired`:if(s+=1,s>=i)return{connected:!1,message:`QR code expired after maximum retries.`};process.stderr.write(`QR code expired, refreshing...
`),o=(await L(n)).qrcodeId;break;default:break}}catch(e){if(e instanceof Error&&e.name===`AbortError`)continue;throw e}await new Promise(e=>setTimeout(e,1e3))}return{connected:!1,message:`Login timed out.`}}function z(){return u(N(),`access.json`)}function B(){return u(N(),`pending-pairings.json`)}function V(){let e=B();if(!f(e))return{};try{return JSON.parse(m(e,`utf-8`))}catch{return{}}}function H(e){h(B(),JSON.stringify(e,null,2),`utf-8`)}function U(){let e=z();if(!f(e))return{policy:`pairing`,allowFrom:[]};try{return JSON.parse(m(e,`utf-8`))}catch{return{policy:`pairing`,allowFrom:[]}}}function de(e){h(z(),JSON.stringify(e,null,2),`utf-8`)}function fe(e){let t=U();return t.policy===`disabled`?!0:t.allowFrom.includes(e)}function pe(e){let t=V(),n=Date.now();for(let e of Object.keys(t))t[e].expiresAt<n&&delete t[e];for(let[n,r]of Object.entries(t))if(r.userId===e)return H(t),n;let r=String(Math.floor(1e5+Math.random()*9e5));return t[r]={userId:e,expiresAt:n+600*1e3},H(t),r}function me(e){let t=V(),n=t[e];if(!n||n.expiresAt<Date.now())return delete t[e],H(t),null;delete t[e],H(t);let r=U();return r.allowFrom.includes(n.userId)||(r.allowFrom.push(n.userId),de(r)),n.userId}function he(e,t){let n=ne(`aes-128-ecb`,t,null);return Buffer.concat([n.update(e),n.final()])}function ge(e,t){let n=re(`aes-128-ecb`,t,null);return Buffer.concat([n.update(e),n.final()])}function _e(e,t){return`${t}/download?encrypted_query_param=${encodeURIComponent(e)}`}function ve(e,t,n){return`${e}/upload?encrypted_query_param=${encodeURIComponent(t)}&filekey=${encodeURIComponent(n)}`}function ye(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 Error(`Invalid aes_key: expected 16 raw bytes or 32 hex chars, got ${t.length} bytes`)}async function be(e){let t=_e(e.encryptQueryParam,e.cdnBaseUrl),n=await fetch(t);if(!n.ok)throw Error(`CDN download failed: HTTP ${n.status}`);return ge(Buffer.from(await n.arrayBuffer()),ye(e.aesKey))}async function W(e){let t=m(e.filePath),n=t.length,r=ie(`md5`).update(t).digest(`hex`),i=_(16),a=_(16).toString(`hex`),o=he(t,i),s=o.length,l=await O(e.apiBaseUrl,e.token,{filekey:a,media_type:e.mediaType,to_user_id:e.toUserId,rawsize:n,rawfilemd5:r,filesize:s,no_need_thumb:!0,aeskey:i.toString(`hex`)});if(!l.upload_param)throw Error(`No upload_param in response`);let u=ve(e.cdnBaseUrl,l.upload_param,a),d=await fetch(u,{method:`POST`,headers:{"Content-Type":`application/octet-stream`},body:new Uint8Array(o)});if(!d.ok)throw Error(`CDN upload failed: HTTP ${d.status}`);return{encryptQueryParam:d.headers.get(`x-encrypted-param`)||``,aesKey:Buffer.from(i.toString(`hex`)).toString(`base64`),fileSize:s,rawSize:n,fileName:c(e.filePath)}}function xe(e){let t=l(e).toLowerCase();return[`.jpg`,`.jpeg`,`.png`,`.gif`,`.bmp`,`.webp`,`.heic`].includes(t)?S.IMAGE:[`.mp4`,`.mov`,`.avi`,`.mkv`,`.webm`].includes(t)?S.VIDEO:S.FILE}function Se(e){let t=``,n=0;for(;n<e.length;)if(e.startsWith("```",n)){let r=n+3;for(;r<e.length&&e[r]!==`
`;)r++;r<e.length&&r++;let i=r;for(;r<e.length;){if(e.startsWith("```",r)){for(t+=e.slice(i,r),r+=3;r<e.length&&e[r]!==`
`;)r++;r<e.length&&r++;break}r++}r>=e.length&&!e.startsWith("```",r-3)&&(t+=e.slice(n)),n=r}else t+=e[n],n++;return t}function G(e){return Se(e).replace(/`([^`]+)`/g,`$1`).replace(/\*\*\*(.+?)\*\*\*/g,`$1`).replace(/\*\*(.+?)\*\*/g,`$1`).replace(/\*(.+?)\*/g,`$1`).replace(/___(.+?)___/g,`$1`).replace(/__(.+?)__/g,`$1`).replace(/_(.+?)_/g,`$1`).replace(/~~(.+?)~~/g,`$1`).replace(/^#{1,6}\s+/gm,``).replace(/\[([^\]]+)\]\(([^)]+)\)/g,`$1 ($2)`).replace(/!\[([^\]]*)\]\([^)]+\)/g,`[$1]`).replace(/^>\s+/gm,``).replace(/^[-*_]{3,}$/gm,`---`).replace(/^[\s]*[-*+]\s+/gm,`- `).replace(/^[\s]*(\d+)\.\s+/gm,`$1. `).replace(/\n{3,}/g,`

`).trim()}async function K(e){let t=v();return await D(e.baseUrl,e.token,{to_user_id:e.to,from_user_id:``,client_id:t,message_type:y.BOT,message_state:x.FINISH,context_token:e.contextToken,item_list:[{type:b.TEXT,text_item:{text:G(e.text)}}]}),{messageId:t}}async function Ce(e){let t=``;for(let n of e.items)t=v(),await D(e.baseUrl,e.token,{to_user_id:e.to,from_user_id:``,client_id:t,message_type:y.BOT,message_state:x.FINISH,context_token:e.contextToken,item_list:[n]});return t}async function we(e){let t=xe(e.filePath),n=await W({filePath:e.filePath,toUserId:e.to,mediaType:t,apiBaseUrl:e.baseUrl,token:e.token,cdnBaseUrl:e.cdnBaseUrl}),r={encrypt_query_param:n.encryptQueryParam,aes_key:n.aesKey,encrypt_type:1},i=[];switch(e.text&&i.push({type:b.TEXT,text_item:{text:G(e.text)}}),t){case 1:i.push({type:b.IMAGE,image_item:{media:r,mid_size:n.fileSize}});break;case 2:i.push({type:b.VIDEO,video_item:{media:r,video_size:n.fileSize}});break;default:i.push({type:b.FILE,file_item:{media:r,file_name:n.fileName,len:String(n.rawSize)}});break}return{messageId:await Ce({items:i,to:e.to,baseUrl:e.baseUrl,token:e.token,contextToken:e.contextToken})}}var Te=900*1e3,q=new Map,J=null;function Y(e=Date.now()){for(let[t,n]of q.entries())n.expiresAt<=e&&q.delete(t)}function Ee(e,t){J={chatId:e,contextToken:t,updatedAt:Date.now()}}function De(){return J}function Oe(e,t,n){Y();let r={...e,chatId:t,contextToken:n,createdAt:Date.now(),expiresAt:Date.now()+Te};return q.set(e.request_id.toLowerCase(),r),r}function ke(e,t){Y();let n=e.toLowerCase(),r=q.get(n);return!r||r.chatId!==t?null:(q.delete(n),r)}var Ae=/^\s*(y|yes|n|no)\s+([a-km-z]{5})\s*$/i,X=new Map;function Z(e){return X.get(e)}function Q(){return u(N(),`cursor.txt`)}function je(){let e=Q();return f(e)?m(e,`utf-8`).trim():``}function Me(e){h(Q(),e,`utf-8`)}async function Ne(e,t){let n,r,i=``,a=``;switch(e.type){case b.IMAGE:n=e.image_item?.media?.encrypt_query_param,r=e.image_item?.aeskey?Buffer.from(e.image_item.aeskey,`hex`).toString(`base64`):e.image_item?.media?.aes_key,i=`.jpg`,a=`image`;break;case b.VOICE:n=e.voice_item?.media?.encrypt_query_param,r=e.voice_item?.media?.aes_key,i=`.silk`,a=`voice`;break;case b.FILE:n=e.file_item?.media?.encrypt_query_param,r=e.file_item?.media?.aes_key,i=e.file_item?.file_name?`.${e.file_item.file_name.split(`.`).pop()}`:``,a=`file`;break;case b.VIDEO:n=e.video_item?.media?.encrypt_query_param,r=e.video_item?.media?.aes_key,i=`.mp4`,a=`video`;break;default:return null}if(!n||!r)return null;try{let o=await be({encryptQueryParam:n,aesKey:r,cdnBaseUrl:t}),s=u(te(),`weixin-media`);f(s)||p(s,{recursive:!0});let l=u(s,c(e.file_item?.file_name||`${Date.now()}${i}`));return h(l,o),{path:l,type:a}}catch(e){return process.stderr.write(`[weixin] Failed to download media: ${e}\n`),null}}function Pe(e){let t=e.match(Ae);if(!t)return null;let n=t[1]?.toLowerCase().startsWith(`y`)?`allow`:`deny`,r=t[2]?.toLowerCase();return r?{requestId:r,behavior:n}:null}async function Fe(e){let{baseUrl:t,cdnBaseUrl:n,token:r,onMessage:i,onPermissionResponse:a,abortSignal:o}=e,s=je(),c=0;for(process.stderr.write(`[weixin] Starting message poll loop...
`);!o.aborted;)try{let e=await se(t,r,s,o);if(e.errcode===-14){process.stderr.write(`[weixin] Session expired (errcode -14). Pausing for 30s...
`),await new Promise(e=>setTimeout(e,3e4));continue}if(e.ret!==0&&e.ret!==void 0)throw Error(`getUpdates error: ret=${e.ret} errcode=${e.errcode} ${e.errmsg}`);if(c=0,e.get_updates_buf&&(s=e.get_updates_buf,Me(s)),e.msgs&&e.msgs.length>0)for(let o of e.msgs)await Ie(o,{baseUrl:t,cdnBaseUrl:n,token:r,onMessage:i,onPermissionResponse:a})}catch(e){if(o.aborted)break;c+=1,process.stderr.write(`[weixin] Poll error (${c}): ${e instanceof Error?e.message:String(e)}\n`),c>=3?(process.stderr.write(`[weixin] Too many consecutive errors, backing off 30s...
`),await new Promise(e=>setTimeout(e,3e4)),c=0):await new Promise(e=>setTimeout(e,2e3))}process.stderr.write(`[weixin] Poll loop stopped.
`)}async function Ie(e,t){if(e.message_type!==y.USER)return;let n=e.from_user_id;if(!n)return;if(e.context_token&&X.set(n,e.context_token),!fe(n)){let r=pe(n);try{await K({to:n,text:`Your pairing code is: ${r}\n\nAsk the operator to confirm:\nccb weixin access pair ${r}`,baseUrl:t.baseUrl,token:t.token,contextToken:e.context_token||``})}catch(e){process.stderr.write(`[weixin] Failed to send pairing code: ${e}\n`)}return}Ee(n,e.context_token);let r=``,i,a;if(e.item_list){for(let n of e.item_list)if(n.type===b.TEXT&&n.text_item?.text)r+=`${r?`
`:``}${n.text_item.text}`;else if(n.type===b.IMAGE||n.type===b.VOICE||n.type===b.FILE||n.type===b.VIDEO){let e=await Ne(n,t.cdnBaseUrl);e&&(i=e.path,a=e.type),n.type===b.VOICE&&n.voice_item?.text&&(r+=`${r?`
`:``}[Voice transcription]: ${n.voice_item.text}`)}}if(!(!r&&!i)){if(r&&t.onPermissionResponse){let e=Pe(r);if(e){let r=ke(e.requestId,n);if(r){await t.onPermissionResponse({requestId:r.request_id,behavior:e.behavior,fromUserId:n});return}}}await t.onMessage({fromUserId:n,messageId:String(e.message_id||``),text:r||`(media attachment)`,attachmentPath:i,attachmentType:a})}}r(),o(),e();function Le(e){return[`Claude Code needs your approval.`,``,`Tool: ${e.tool_name}`,`Reason: ${e.description}`,`Input: ${e.input_preview}`,``,`Reply with: yes ${e.request_id}`,`Or deny with: no ${e.request_id}`].join(`
`)}function Re(e){let r=new i({name:`weixin`,version:e},{capabilities:{experimental:{"claude/channel":{},"claude/channel/permission":{}},tools:{}},instructions:`Messages from WeChat arrive as <channel source="plugin:weixin:weixin" chat_id="..." sender_id="...">. Reply using the reply tool with the chat_id from the channel tag. Use absolute paths for file attachments.`});return r.setRequestHandler(t,async()=>({tools:[{name:`reply`,description:`Reply to a WeChat message. Pass the chat_id from the channel tag.`,inputSchema:{type:`object`,properties:{chat_id:{type:`string`,description:`The chat_id from the channel notification`},text:{type:`string`,description:`The reply text`},files:{type:`array`,items:{type:`string`},description:`Optional absolute file paths to attach`}},required:[`chat_id`,`text`]}},{name:`send_typing`,description:`Send a typing indicator to a WeChat user.`,inputSchema:{type:`object`,properties:{chat_id:{type:`string`,description:`The chat_id (user ID)`}},required:[`chat_id`]}}]})),r.setRequestHandler(n,async e=>{let{name:t,arguments:n}=e.params,r=F();if(!r)return{content:[{type:`text`,text:"WeChat not connected. Run `ccb weixin login` first."}],isError:!0};let i=r.baseUrl||`https://ilinkai.weixin.qq.com`,a=M;switch(t){case`reply`:{let e=typeof n?.chat_id==`string`?n.chat_id:``,t=typeof n?.text==`string`?n.text:``,o=Array.isArray(n?.files)?n.files.filter(e=>typeof e==`string`):void 0;if(!e||!t)return{content:[{type:`text`,text:`Missing chat_id or text parameter.`}],isError:!0};let s=Z(e)||``;try{if(o&&o.length>0){for(let[n,c]of o.entries()){if(!f(c))return{content:[{type:`text`,text:`File not found: ${c}`}],isError:!0};await we({filePath:c,to:e,text:n===0?t:``,baseUrl:i,token:r.token,contextToken:s,cdnBaseUrl:a})}return{content:[{type:`text`,text:`Message sent with attachments.`}]}}return await K({to:e,text:t,baseUrl:i,token:r.token,contextToken:s}),{content:[{type:`text`,text:`Message sent.`}]}}catch(e){return{content:[{type:`text`,text:`Failed to send: ${e}`}],isError:!0}}}case`send_typing`:{let e=typeof n?.chat_id==`string`?n.chat_id:``;if(!e)return{content:[{type:`text`,text:`Missing chat_id parameter.`}],isError:!0};try{let t=Z(e),n=await k(i,r.token,e,t);return n.typing_ticket&&await A(i,r.token,{ilink_user_id:e,typing_ticket:n.typing_ticket,status:ae.TYPING}),{content:[{type:`text`,text:`Typing indicator sent.`}]}}catch(e){return{content:[{type:`text`,text:`Failed to send typing: ${e}`}],isError:!0}}}default:return{content:[{type:`text`,text:`Unknown tool: ${t}`}],isError:!0}}}),r}async function ze(e,t){t.enableConfigs(),t.initializeAnalyticsSink();let n=F();n||(process.stderr.write("[weixin] No account configured. Run `ccb weixin login` to connect your WeChat account.\n"),await Promise.all([t.shutdown1PEventLogging(),t.shutdownDatadog()]),process.exit(1));let r=Re(e),i=new s;t.registerPermissionHandler(r,async e=>{let r=e.channel_context?.chat_id,i=r?{chatId:r,contextToken:Z(r)}:De();if(!i){t.logForDebugging(`[Weixin MCP] No active chat available for permission request ${e.request_id}`);return}try{Oe(e,i.chatId,i.contextToken),await K({to:i.chatId,text:Le(e),baseUrl:a,token:n.token,contextToken:i.contextToken||``})}catch(t){process.stderr.write(`[weixin] Failed to relay permission request ${e.request_id}: ${t}\n`)}}),await r.connect(i);let a=n.baseUrl||`https://ilinkai.weixin.qq.com`,o=new AbortController,c=!1,l=async()=>{c||(c=!0,o.signal.aborted||o.abort(),await Promise.all([t.shutdown1PEventLogging(),t.shutdownDatadog()]),process.exit(0))};process.stdin.on(`end`,()=>void l()),process.stdin.on(`error`,()=>void l()),process.on(`SIGINT`,()=>void l()),process.on(`SIGTERM`,()=>void l()),process.on(`SIGHUP`,()=>void l());let u=process.ppid,d=setInterval(()=>{try{process.kill(u,0)}catch{process.stderr.write(`[weixin] Parent process exited, shutting down...
`),clearInterval(d),l()}},5e3);t.logForDebugging(`[Weixin MCP] Starting poll loop`),await Fe({baseUrl:a,cdnBaseUrl:M,token:n.token,onMessage:async e=>{await r.notification({method:`notifications/claude/channel`,params:{content:e.text,meta:{chat_id:e.fromUserId,sender_id:e.fromUserId,message_id:e.messageId,...e.attachmentPath&&{attachment_path:e.attachmentPath},...e.attachmentType&&{attachment_type:e.attachmentType}}}})},onPermissionResponse:async e=>{await r.notification({method:`notifications/claude/channel/permission`,params:{request_id:e.requestId,behavior:e.behavior}})},abortSignal:o.signal}),clearInterval(d),await l()}function $(){process.stdout.write([`Usage:`,`  ccb weixin serve`,`  ccb weixin login`,`  ccb weixin login clear`,`  ccb weixin access pair <code>`,``,`Session enablement:`,`  ccb --channels plugin:weixin@builtin`].join(`
`)+`
`)}async function Be(e=!1){if(e){le(),process.stdout.write(`WeChat account cleared.
`);return}let t=F();if(t){process.stdout.write([`Already connected:`,`  User ID: ${t.userId||`unknown`}`,`  Connected since: ${t.savedAt}`,``,"Run `ccb weixin login clear` to disconnect.",`Restart Claude Code with:`,`  ccb --channels plugin:weixin@builtin`].join(`
`)+`
`);return}process.stdout.write(`Starting WeChat QR login...

`);let n=await L(j);process.stdout.write(`\nScan the QR code above with WeChat, or open this URL:\n${n.qrcodeUrl||``}\n\n`);let r=await R({qrcodeId:n.qrcodeId,apiBaseUrl:j});(!r.connected||!r.token)&&(process.stderr.write(`Login failed: ${r.message}\n`),process.exit(1)),ce({token:r.token,baseUrl:r.baseUrl||`https://ilinkai.weixin.qq.com`,userId:r.userId,savedAt:new Date().toISOString()}),process.stdout.write([`Connected successfully!`,`  User ID: ${r.userId||`unknown`}`,`  Base URL: ${r.baseUrl||`https://ilinkai.weixin.qq.com`}`,``,`Restart Claude Code with:`,`  ccb --channels plugin:weixin@builtin`].join(`
`)+`
`)}function Ve(e){(e[0]!==`pair`||!e[1])&&($(),process.exit(1));let t=me(e[1]);t||(process.stderr.write(`Invalid or expired pairing code.
`),process.exit(1)),process.stdout.write(`Paired successfully: ${t}\n`)}async function He(e,t,n){let[r,...i]=e;switch(r){case`serve`:t||(process.stderr.write(`[weixin] serve handler not available in this context.
`),process.exit(1)),await ze(n??`0.0.0`,t);return;case`login`:await Be(i[0]===`clear`);return;case`access`:Ve(i);return;default:$()}}export{He as handleWeixinCli};