@wps365/openclaw-wpsxiezuo 1.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +335 -0
  3. package/README_ZH-CN.md +318 -0
  4. package/bin/cli.mjs +677 -0
  5. package/dist/channel/event-crypto.d.ts +19 -0
  6. package/dist/channel/event-handlers.d.ts +61 -0
  7. package/dist/channel/event-types.d.ts +88 -0
  8. package/dist/channel/index.d.ts +8 -0
  9. package/dist/channel/plugin.d.ts +11 -0
  10. package/dist/channel/register-tool-bridge.d.ts +14 -0
  11. package/dist/channel/sdk-client-options.d.ts +24 -0
  12. package/dist/channel/sdk-helpers.d.ts +12 -0
  13. package/dist/channel/sdk-provider.d.ts +23 -0
  14. package/dist/channel/types.d.ts +324 -0
  15. package/dist/core/config.d.ts +267 -0
  16. package/dist/core/errors.d.ts +36 -0
  17. package/dist/core/index.d.ts +18 -0
  18. package/dist/core/lazy-client-store.d.ts +28 -0
  19. package/dist/core/media-utils.d.ts +27 -0
  20. package/dist/core/reaction.d.ts +29 -0
  21. package/dist/core/token-store.d.ts +34 -0
  22. package/dist/core/user-token-store.d.ts +35 -0
  23. package/dist/core/wps-client.d.ts +42 -0
  24. package/dist/index.d.ts +17 -0
  25. package/dist/index.js +33 -0
  26. package/dist/messaging/handler.d.ts +73 -0
  27. package/dist/messaging/inbound/content-parser.d.ts +17 -0
  28. package/dist/messaging/inbound/handler.d.ts +44 -0
  29. package/dist/messaging/inbound/index.d.ts +5 -0
  30. package/dist/messaging/inbound/media-prefetch.d.ts +43 -0
  31. package/dist/messaging/inbound/pairing-allow-store.d.ts +11 -0
  32. package/dist/messaging/index.d.ts +3 -0
  33. package/dist/messaging/outbound.d.ts +15 -0
  34. package/dist/session/idempotency.d.ts +8 -0
  35. package/dist/session/index.d.ts +5 -0
  36. package/dist/session/resolver.d.ts +17 -0
  37. package/dist/session/types.d.ts +37 -0
  38. package/dist/tools/oapi/calendar.d.ts +106 -0
  39. package/dist/tools/oapi/chat.d.ts +10 -0
  40. package/dist/tools/oapi/delegated-auth.d.ts +14 -0
  41. package/dist/tools/oapi/drive.d.ts +112 -0
  42. package/dist/tools/oapi/index.d.ts +24 -0
  43. package/dist/tools/oapi/media.d.ts +32 -0
  44. package/dist/tools/oapi/messaging.d.ts +10 -0
  45. package/dist/tools/oapi/todo.d.ts +96 -0
  46. package/dist/tools/oapi/user.d.ts +10 -0
  47. package/dist/tools/oauth/index.d.ts +65 -0
  48. package/openclaw.plugin.json +154 -0
  49. package/package.json +91 -0
  50. package/scripts/upgrade.sh +37 -0
  51. package/skills/wps-auth-provider.md +63 -0
  52. package/skills/wps-calendar/SKILL.md +147 -0
  53. package/skills/wps-channel-rules/SKILL.md +50 -0
  54. package/skills/wps-chat/SKILL.md +106 -0
  55. package/skills/wps-drive/SKILL.md +79 -0
  56. package/skills/wps-im-read/SKILL.md +88 -0
  57. package/skills/wps-im-send/SKILL.md +183 -0
  58. package/skills/wps-media/SKILL.md +101 -0
  59. package/skills/wps-message-handler.md +48 -0
  60. package/skills/wps-todo/SKILL.md +65 -0
  61. package/skills/wps-user/SKILL.md +105 -0
  62. package/skills/wps-xiezuo-session-mapper.md +62 -0
package/dist/index.js ADDED
@@ -0,0 +1,33 @@
1
+ var Fr=Object.defineProperty;var re=(e,t)=>()=>(e&&(t=e(e=0)),t);var Dn=(e,t)=>{for(var n in t)Fr(e,n,{get:t[n],enumerable:!0})};function Ut(e){return e===401?{hint:"invalid/expired token or app credentials",retriable:!1}:e===403?{hint:"permission denied or scope not granted",retriable:!1}:e===404?{hint:"resource not found",retriable:!1}:e===409?{hint:"resource state conflict",retriable:!1}:e===429?{hint:"rate limited by WPS API",retriable:!0}:e>=500?{hint:"WPS API temporarily unavailable",retriable:!0}:{hint:"unexpected WPS API status",retriable:!1}}var he,H,Fe=re(()=>{"use strict";he=class extends Error{detail;name="WpsRequestError";constructor(t,n){super(t),this.detail=n}get retriable(){return this.detail.retriable===!0}get stage(){return this.detail.stage}},H=class extends Error{cause;name="WpsTokenError";constructor(t,n){super(t),this.cause=n}}});function Kr(e){return e===401?"invalid app credentials (check client_id/client_secret)":e===403?"app not authorized for this enterprise or scope":e===429?"rate limited by WPS token endpoint":e>=500?"WPS OAuth service unavailable":"unexpected OAuth response"}function E(e){let t=`${e.clientId}@${e.baseUrl}`,n=jn.get(t);return n||(n=new dt(e),jn.set(t,n)),n}var Br,Gr,dt,jn,Dt=re(()=>{"use strict";Fe();Br=6e4,Gr=["/oauth2/token","/openapi/oauth2/token"];dt=class{creds;token=null;inFlight=null;constructor(t){this.creds=t}async getToken(){if(this.token&&Date.now()<this.token.expiresAt-Br)return this.token.accessToken;if(this.inFlight)return this.inFlight;this.inFlight=this.requestToken();try{return await this.inFlight}finally{this.inFlight=null}}invalidate(){this.token=null}async requestToken(){let t=this.creds.baseUrl.replace(/\/$/,""),n="unknown token error";for(let r of Gr){let i=`${t}${r}`,o;try{o=await fetch(i,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:new URLSearchParams({grant_type:"client_credentials",client_id:this.creds.clientId,client_secret:this.creds.clientSecret})})}catch(a){n=`Network error requesting token from ${i}: ${String(a)}`;continue}if(!o.ok){let a=await o.text();n=`Token request failed (${o.status}) at ${i}: ${Kr(o.status)}; body=${a}`;continue}let s=await o.json();if(s.code!==void 0&&s.code!==0){n=`WPS OAuth error (code ${s.code}): ${s.msg??"unknown"}`;continue}if(!s.access_token||!s.expires_in){n=`Invalid token response from ${i}: missing access_token or expires_in`;continue}return this.token={accessToken:s.access_token,expiresAt:Date.now()+s.expires_in*1e3},this.token.accessToken}throw new H(n)}},jn=new Map});import{z as w}from"zod";function pt(e){return lt}function Nt(e){let t=e?.defaultAccountId?.trim();if(t)return t;let n=e?.accounts?Object.keys(e.accounts)[0]:void 0;return n&&n.trim()?n:pe}function Mt(e){return e?e.accounts&&Object.keys(e.accounts).length>0?e.accounts:!(e.appId||e.appSecret||e.companyId||e.webhook||e.sdk||e.groups||e.dmPolicy||e.groupPolicy)?{}:!e.appId||!e.appSecret?{}:{[pe]:{enabled:e.enabled??!0,appId:e.appId,appSecret:e.appSecret,companyId:e.companyId,baseUrl:e.baseUrl??"https://openapi.wps.cn",enableEncryption:e.enableEncryption??!0,webhook:e.webhook,sdk:e.sdk,dmPolicy:e.dmPolicy,allowFrom:e.allowFrom,groupPolicy:e.groupPolicy,groups:e.groups,instantAck:e.instantAck,robotJoinGroupMessage:e.robotJoinGroupMessage,mcp:e.mcp}}:{}}function Q(e){return!e?.appId||!e?.appSecret?null:{clientId:e.appId,clientSecret:e.appSecret,baseUrl:e.baseUrl??"https://openapi.wps.cn"}}var qn,Nn,Mn,Wn,zn,Ln,lt,jt,qt,x,ie,pe,ve=re(()=>{"use strict";qn=w.enum(["disabled","open","allowlist","pairing"]).default("pairing"),Nn=w.object({requireMention:w.boolean().optional(),toolPolicy:w.enum(["full","limited","none"]).optional()}).passthrough(),Mn=w.object({enabled:w.boolean().default(!1),mode:w.literal("app").default("app"),clientId:w.string().optional(),clientSecret:w.string().optional(),baseUrl:w.string().optional(),toolAllowlist:w.array(w.string()).min(1,"mcp.toolAllowlist must contain at least one tool").default(["wps_user_search","wps_user_get","wps_im_message_send","wps_calendar_create","wps_calendar_list_events","wps_calendar_get_event","wps_calendar_list_event_attendees","wps_calendar_list_calendar_event_instances","wps_calendar_list_event_instances","wps_calendar_respond_invitation","wps_todo_create_personal_task","wps_todo_list_personal_tasks","wps_todo_get_personal_task","wps_todo_update_personal_task","wps_todo_update_personal_task_status","wps_drive_list_drives","wps_drive_create_file","wps_drive_extract_file_content","wps_drive_get_file_meta","wps_drive_search_files"])}),Wn=w.object({enabled:w.boolean().default(!0),text:w.string().default("\u5185\u5BB9\u5904\u7406\u4E2D\uFF0C\u8BF7\u7A0D\u5019...")}),zn=w.object({enabled:w.boolean().default(!1),logLevel:w.enum(["debug","info","warn","error"]).default("info"),endpoint:w.string().optional(),connectTimeoutMs:w.number().min(3e3).max(12e4).default(2e4),pongTimeout:w.number().min(3e4).max(3e5).default(15e4),autoReconnect:w.boolean().default(!0),reconnectBaseInterval:w.number().min(500).max(1e4).default(1e3),reconnectMaxInterval:w.number().min(1e4).max(3e5).default(6e4),reconnectMultiplier:w.number().min(1.5).max(3).default(2),reconnectMaxRetry:w.number().min(-1).max(100).default(-1),reconnectJitter:w.number().min(0).max(.5).default(.2)}),Ln=w.object({path:w.string().default("/wps/webhook"),port:w.number().default(3e3)}),lt="https://o.wpsgo.com/app/41000207/aY5vaqfh9T0o/",jt=w.object({enabled:w.boolean().default(!0),appId:w.string().describe("WPS App ID (client_id)"),appSecret:w.string().describe("WPS App Secret (client_secret)"),companyId:w.string().optional().describe("WPS Company ID"),baseUrl:w.string().default("https://openapi.wps.cn"),enableEncryption:w.boolean().default(!0),webhook:Ln.optional(),sdk:zn.optional(),dmPolicy:qn.optional(),allowFrom:w.array(w.string()).optional(),groupPolicy:w.enum(["open","allowlist"]).optional(),groups:w.record(w.string(),Nn).optional(),instantAck:Wn.optional(),robotJoinGroupMessage:w.string().optional(),mcp:Mn.optional()}),qt=jt.partial().extend({defaultAccountId:w.string().optional(),accounts:w.record(w.string(),jt).optional()});x="wps-xiezuo",ie="wps-xiezuo",pe="default"});function Wt(e){Be=e}function zt(e,t){Te.set(e,t),Bn(e,t)}function Lt(e){let t=Te.get(e);return t?Date.now()>=t.expiresAt?(Te.delete(e),Fn(e),null):t.accessToken:null}function Fn(e){let t=ut.get(e);t&&(clearTimeout(t),ut.delete(e))}function Bn(e,t){if(Fn(e),!t.refreshToken)return;let n=Math.max(t.expiresAt-Date.now()-Hr,1e4),r=setTimeout(()=>{Jr(e).catch(()=>{Te.delete(e),ut.delete(e)})},n);r.unref?.(),ut.set(e,r)}async function Jr(e){let t=Te.get(e);if(!t?.refreshToken||!Be)return;let n=Be.baseUrl.replace(/\/$/,""),r=new URLSearchParams({grant_type:"refresh_token",client_id:Be.appId,client_secret:Be.appSecret,refresh_token:t.refreshToken}),i=await fetch(`${n}/oauth2/token`,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:r.toString()}),o=await i.text(),s;try{s=JSON.parse(o)}catch{throw new H(`OAuth refresh: non-JSON response (${i.status}): ${o.slice(0,200)}`)}if(!i.ok||typeof s.code=="number"&&s.code!==0)throw new H(`OAuth refresh failed (${i.status}): ${JSON.stringify(s)}`);let a=typeof s.access_token=="string"?s.access_token:"";if(!a)throw new H(`OAuth refresh: missing access_token: ${JSON.stringify(s)}`);let d=typeof s.expires_in=="number"?s.expires_in:7200,l={accessToken:a,refreshToken:typeof s.refresh_token=="string"?s.refresh_token:t.refreshToken,expiresAt:Date.now()+d*1e3,openid:typeof s.openid=="string"?s.openid:t.openid};Te.set(e,l),Bn(e,l)}async function Ft(e){let t=e.baseUrl.replace(/\/$/,""),n=new URLSearchParams({grant_type:"authorization_code",client_id:e.appId,client_secret:e.appSecret,code:e.code,redirect_uri:e.redirectUri??lt}),r=await fetch(`${t}/oauth2/token`,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:n.toString()}),i=await r.text(),o;try{o=JSON.parse(i)}catch{throw new H(`OAuth code exchange: non-JSON response (${r.status}): ${i.slice(0,200)}`)}if(!r.ok||typeof o.code=="number"&&o.code!==0)throw new H(`OAuth code exchange failed (${r.status}): ${JSON.stringify(o)}`);let s=typeof o.access_token=="string"?o.access_token:"";if(!s)throw new H(`OAuth code exchange: missing access_token in response: ${JSON.stringify(o)}`);let a=typeof o.expires_in=="number"?o.expires_in:7200;return{accessToken:s,refreshToken:typeof o.refresh_token=="string"?o.refresh_token:"",expiresAt:Date.now()+a*1e3,openid:typeof o.openid=="string"?o.openid:""}}var Te,ut,Hr,Be,Ge=re(()=>{"use strict";Fe();ve();Te=new Map,ut=new Map,Hr=5*6e4,Be=null});function $(e,t){return new Ke(e,new ft(t))}function Bt(e,t){return new Ke(e,new mt(t))}var ft,mt,Ke,_t=re(()=>{"use strict";Fe();ft=class{tokenStore;constructor(t){this.tokenStore=t}async getHeaders(){return{Authorization:`Bearer ${await this.tokenStore.getToken()}`}}},mt=class{accessToken;constructor(t){this.accessToken=t}async getHeaders(){return{Authorization:`Bearer ${this.accessToken}`}}},Ke=class{baseUrl;auth;constructor(t,n){this.baseUrl=t,this.auth=n}async request(t){let n=await this.auth.getHeaders(),r=this.buildUrl(t.path,t.query),i=t.method??"GET",o=await fetch(r,{method:i,headers:{"Content-Type":"application/json",...n,...t.headers??{}},body:t.body?JSON.stringify(t.body):void 0}),s=o.headers.get("X-Request-Id")??o.headers.get("x-request-id")??o.headers.get("X-Trace-Id")??o.headers.get("x-trace-id")??void 0;if(!o.ok){let a=await o.text(),d;try{let u=JSON.parse(a);d=u.code??u.result}catch{}let{hint:l,retriable:c}=Ut(o.status),p=s?` request_id=${s}`:"";throw console.error(`[WPS-API-ERROR] ${o.status} ${i} ${t.path}${p} body=${a}`),new he(`WPS API error (${o.status} ${i} ${t.path}): ${a}`,{stage:"http",method:i,path:t.path,httpStatus:o.status,wpsCode:d,hint:l,retriable:c,requestId:s})}return this.parseResponse(o,i,t.path,s)}buildUrl(t,n){let r=new URL(t,this.baseUrl);if(n){for(let[i,o]of Object.entries(n))if(o!==void 0)if(Array.isArray(o))for(let s of o)r.searchParams.append(i,s);else r.searchParams.set(i,String(o))}return r.toString()}async parseResponse(t,n,r,i){let o=await t.text();if(!o||o.trim()==="")return{};let s;try{s=JSON.parse(o)}catch{throw new he(`Failed to parse JSON from ${n} ${r}: ${o.slice(0,200)}`,{stage:"parse",method:n,path:r,hint:"response is not valid JSON",retriable:!1})}let a=s.code??s.result;if(a!==void 0&&a!==0&&a!=="ok"){let d=String(a)==="40300001"?"permission denied by WPS business policy":"WPS business validation failed",l=s.request_id??i,c=l?` request_id=${String(l)}`:"";throw console.error(`[WPS-API-ERROR] biz_code=${String(a)} ${n} ${r}${c} msg=${s.msg??s.message??"unknown"}`),new he(`WPS business error code=${String(a)}: ${s.msg??s.message??"unknown"}`,{stage:"business",method:n,path:r,wpsCode:a,hint:d,retriable:!1,requestId:l?String(l):void 0})}return s}}});import{imageSize as Xr}from"image-size";function He(e,t=0){if(!e||typeof e!="object"||t>2)return null;let n=e;for(let r of Yr){let i=n[r];if(typeof i=="string"&&i.trim())return i.trim()}return n.data&&typeof n.data=="object"?He(n.data,t+1):null}function Gt(e){let t=He(e);if(!t)throw new Error("cannot resolve download URL from WPS API response");return t}function Gn(e){try{let t=Xr(Buffer.isBuffer(e)?e:Buffer.from(e));return t.width&&t.height?{width:t.width,height:t.height}:null}catch{return null}}var Yr,Je=re(()=>{"use strict";Yr=["url","download_url","downloadUrl","file_url","fileUrl"]});async function Ht(e,t,n){let r=E(e);await $(e.baseUrl,r).request({method:"POST",path:`/v7/chats/${encodeURIComponent(t)}/messages/${encodeURIComponent(n)}/reactions/create`,body:{reaction_type:Kt}})}async function Jt(e,t,n,r){try{let i=E(e);await $(e.baseUrl,i).request({method:"POST",path:`/v7/chats/${encodeURIComponent(t)}/messages/${encodeURIComponent(n)}/reactions/delete`,body:{reaction_type:Kt}})}catch(i){(r?.error??console.error)(`WPS thinking reaction cleanup failed: ${String(i)}`)}}var Kt,Xt=re(()=>{"use strict";Dt();_t();Kt="emoji_busy"});var Xe=re(()=>{"use strict";Fe();Dt();Ge();_t();Je();Xt();ve()});var fr={};Dn(fr,{getDelegatedScopes:()=>be,getLazyClient:()=>cn,getLazyCreds:()=>wt,getLazyLog:()=>we,getLazyWpsCfg:()=>dn,setDelegatedScopes:()=>bt,setLazyClient:()=>an});function an(e,t,n,r){rn=e,pr=t??null,on=n??null,sn=r??null}function cn(){if(!rn)throw new Error("WPS client not initialized yet (startAccount has not been called)");return rn}function we(){return pr}function dn(){if(!on)throw new Error("WPS config not set yet (startAccount has not been called)");return on}function wt(){if(!sn)throw new Error("WPS credentials not set yet (startAccount has not been called)");return sn}function bt(e){ur=e}function be(){return ur}var rn,pr,on,sn,ur,Ae=re(()=>{"use strict";rn=null,pr=null,on=null,sn=null;ur=[]});var pn={};Dn(pn,{buildAuthCard:()=>gr,buildAuthSuccessCard:()=>yr,buildAuthorizeUrl:()=>hr,decodeState:()=>_r,encodeState:()=>mr,handleAuthEvent:()=>ji,sendAuthCard:()=>ln});import{randomBytes as Ui}from"node:crypto";function mr(e){let t=Ui(16).toString("hex");e.nonce=t;let n=t;return Ce.set(n,e),setTimeout(()=>Ce.delete(n),10*6e4).unref?.(),n}function _r(e){let t=Ce.get(e);return t&&Ce.delete(e),t??null}function hr(e){let t=new URL("/oauth2/auth",e.baseUrl);return t.searchParams.set("response_type","code"),t.searchParams.set("client_id",e.appId),t.searchParams.set("redirect_uri",e.redirectUri),t.searchParams.set("scope",e.scopes.join(",")),t.searchParams.set("state",e.state),t.toString()}function gr(e,t){let n=t.length>xt,i=(n?t.slice(0,xt):t).join(`
2
+ `)+(n?`
3
+ ... \u7B49\u5171 ${t.length} \u9879\u6743\u9650`:"");return{card:{i18n_items:[{key:"zh-CN",value:{elements:[{text:{tag:"text",text:{content:`\u5E94\u7528\u9700\u8981\u6388\u6743 ${t.length} \u4E2A\u7528\u6237\u6743\u9650\u3002`,text_align:"left",text_size:"small",type:"markdown"}}},{text:{tag:"text",text:{content:`**\u5C06\u8981\u6388\u6743\u7684\u6743\u9650\uFF1A**
4
+
5
+ ${i}
6
+ `,text_align:"left",text_size:"small",type:"markdown"}}},{action:{actions:[{button:{disabled_tips:{content:"",type:"plain"},hover_tips:{content:"",type:"plain"},link:{url:e,pc_url:e,web_url:e,android_url:e,ios_url:e,harmony_url:e},margin:"0px 0px 0px 0px",style:"normal",tag:"button",text:{content:"\u524D\u5F80\u6388\u6743",type:"plain"}}}],layout:"exclusive_row",tag:"action"}},{text:{tag:"text",text:{content:`<font color='gray'>\u6388\u6743\u94FE\u63A5\u4EC5\u53EF\u4F7F\u7528\u4E00\u6B21\uFF0C10\u5206\u949F\u5185\u672A\u4F7F\u7528\u5C06\u81EA\u52A8\u8FC7\u671F</font>
7
+ `,text_align:"left",text_size:"small",type:"markdown"}}}],header:{subtitle:{tag:"text",text:{content:"",type:"plain"}},template:"blue",title:{tag:"text",text:{content:"\u8BF7\u6388\u6743\u4EE5\u65B9\u4FBF\u7EE7\u7EED\u64CD\u4F5C",type:"plain"}}}}}]}}}function yr(e){let t=e.length>xt;return{card:{i18n_items:[{key:"zh-CN",value:{elements:[{text:{tag:"text",text:{content:`**\u5DF2\u5B8C\u6210\u4EE5\u4E0B\u6743\u9650\u6388\u6743\uFF1A**
8
+
9
+ ${(t?e.slice(0,xt):e).join(`
10
+ `)+(t?`
11
+ ... \u7B49\u5171 ${e.length} \u9879\u6743\u9650`:"")}
12
+ `,text_align:"left",text_size:"small",type:"markdown"}}},{action:{actions:[{button:{disabled_tips:{content:"",type:"plain"},hover_tips:{content:"",type:"plain"},margin:"0px 0px 0px 0px",style:"disable",tag:"button",text:{content:"\u5DF2\u6388\u6743",type:"plain"}}}],layout:"exclusive_row",tag:"action"}}],header:{subtitle:{tag:"text",text:{content:"",type:"plain"}},template:"green",title:{tag:"text",text:{content:"\u6388\u6743\u5DF2\u5B8C\u6210",type:"plain"}}}}}]}}}async function ln(e){let t=mr({wpsUserId:e.wpsUserId,receiverType:e.receiverType,receiverId:e.receiverId,nonce:"",originalMessage:e.originalMessage}),n;if(e.scopes&&e.scopes.names.length>0){let f=be(),g=new Set(f.map(_=>_.name)),h=e.scopes.names.filter(_=>!g.has(_));h.length>0&&f.length>0&&we()?.warn?.(`[OAuth] Requested scopes not in delegated list: ${h.join(", ")}. \u9700\u5728\u5F00\u653E\u5E73\u53F0\u540E\u53F0\u5F00\u901A\u5BF9\u5E94\u80FD\u529B\u6743\u9650\u3002`),n=e.scopes.names}else{let f=be();if(f.length===0)return we()?.error?.("[OAuth] No delegated scopes available. \u5E94\u7528\u672A\u914D\u7F6E delegated \u6743\u9650\uFF0C\u8BF7\u5728\u5F00\u653E\u5E73\u53F0\u540E\u53F0\u5F00\u901A\u3002"),null;n=f.map(g=>g.name)}let r=Ce.get(t);r&&(r.requestedScopeNames=[...n]);let i=pt(e.wpsCfg),o=hr({baseUrl:e.wpsCfg.baseUrl??"https://openapi.wps.cn",appId:e.creds.clientId,scopes:n,state:t,redirectUri:i}),s=gr(o,n),a=E(e.creds),d=$(e.creds.baseUrl,a),l={type:"card",receiver:{type:e.receiverType,receiver_id:e.receiverId},content:s},c=we();c?.info?.(`[OAuth] sendAuthCard request: receiverType=${e.receiverType}, receiverId=${e.receiverId}`);let p=await d.request({method:"POST",path:"/v7/messages/create",body:l});c?.info?.(`[OAuth] sendAuthCard response: code=${p.code}, msg=${p.msg}, message_id=${p.data?.message_id}`);let u=p.data?.message_id??"",m=Ce.get(t);return m&&(m.messageId=u),{messageId:u,authorizeUrl:o}}async function Di(e,t,n,r){if(t)try{let i=E(e),o=$(e.baseUrl,i),s=yr(n);await o.request({method:"POST",path:`/v7/messages/${encodeURIComponent(t)}/update`,body:{type:"card",content:s}})}catch(i){r?.warn?.(`Failed to update auth card: ${String(i)}`)}}async function ji(e){let{code:t,creds:n,log:r}=e,i=e.state?_r(e.state):null,o=i?.wpsUserId??e.userId??"";if(!o){r?.warn?.(`[OAuth] Cannot determine user: state=${e.state}, userId=${e.userId}`);return}r?.info?.(`[OAuth] Auth event for user=${o}, code=${t.slice(0,8)}..., hasState=${!!i}`);let s=pt(e.wpsCfg),a=await Ft({appId:n.clientId,appSecret:n.clientSecret,baseUrl:n.baseUrl,code:t,redirectUri:s});if(zt(o,a),r?.info?.(`[OAuth] Token exchange success for user=${o}, openid=${a.openid}, expiresAt=${new Date(a.expiresAt).toISOString()}, hasRefresh=${!!a.refreshToken}`),i?.messageId){let d=i.requestedScopeNames&&i.requestedScopeNames.length>0?i.requestedScopeNames.filter(l=>l.length>0):be().map(l=>l.name).filter(l=>l.length>0);await Di(n,i.messageId,d,r)}}var Ce,xt,St=re(()=>{"use strict";Ge();Xe();Ae();ve();Ce=new Map;xt=6});Xe();import{createRequire as Vr}from"node:module";var Qr=Vr(import.meta.url);function Zr(){try{return Qr("openclaw/plugin-sdk")}catch{return null}}var Z=Zr(),Us=typeof Z?.DEFAULT_ACCOUNT_ID=="string"&&Z.DEFAULT_ACCOUNT_ID.trim()?Z.DEFAULT_ACCOUNT_ID:"default";function Kn(){return typeof Z?.emptyPluginConfigSchema=="function"?Z.emptyPluginConfigSchema():{type:"object",additionalProperties:!1,properties:{}}}function Hn(e){return typeof Z?.buildChannelConfigSchema=="function"?Z.buildChannelConfigSchema(e):e}function Jn(e){return typeof Z?.formatPairingApproveHint=="function"?Z.formatPairingApproveHint(e):`Run pairing approval command for channel '${e}'.`}function Xn(e,t){return typeof Z?.waitUntilAbort=="function"?Z.waitUntilAbort(e,t):new Promise(n=>{let r=()=>{e.removeEventListener("abort",r),t().finally(n)};if(e.aborted){r();return}e.addEventListener("abort",r,{once:!0})})}Xe();import{existsSync as Yi,readFileSync as Vi}from"node:fs";import{readFile as Qi}from"node:fs/promises";import{homedir as Zi}from"node:os";import It from"node:path";var ht="kso.app_chat.message";import*as Pe from"node:crypto";function Yn(e){if(!e||typeof e!="object")return!1;let t=e;return typeof t.encrypted_data=="string"&&typeof t.nonce=="string"&&typeof t.signature=="string"&&typeof t.topic=="string"&&typeof t.time=="number"}function Vn(e){let t=`${e.appId}:${e.topic}:${e.nonce}:${e.time}:${e.encryptedData}`,n=Pe.createHmac("sha256",e.appSecret);return n.update(t),n.digest("base64url").replace(/=+$/,"")===e.signature}function Qn(e,t,n){let r=Pe.createHash("md5").update(t).digest("hex"),i=Buffer.from(r,"utf-8"),o=Buffer.from(n,"utf-8").subarray(0,16),s=Buffer.from(e,"base64"),a=Pe.createDecipheriv("aes-256-cbc",i,o),d=a.update(s);return d=Buffer.concat([d,a.final()]),d.toString("utf-8")}function Vt(e){return typeof e=="string"&&e.trim()!==""&&e!==ht}function ge(e){return e&&typeof e=="object"?e:{}}function Yt(...e){for(let t of e)if(typeof t=="string"&&t.trim())return t.trim();return""}function ei(e){let t=e.content;if(!t||typeof t!="object")return{};let n=t,r=n.text;if(r&&typeof r=="object"&&r!==null&&"content"in r)return n;if(typeof n.text=="string")return{text:{content:n.text,type:"plain"}};let i=n.image;if(i?.file_id)return{image:{storage_key:i.file_id}};let o=n.file;if(o?.file_id)return{file:{type:"local",local:{storage_key:o.file_id,name:o.name??"file"}}};let s=n.rich_text;if(s&&typeof s=="object"){let a=ti(s);if(a.length>0)return{text:{content:a.join(`
13
+ `),type:"markdown"}}}return n}function ti(e){if(!e||typeof e!="object")return[];let t=e.elements;if(!Array.isArray(t))return[];let n=[];for(let r of t){if(!r||typeof r!="object")continue;let o=r.elements;if(Array.isArray(o))for(let s of o){if(!s||typeof s!="object")continue;let a=s,d=a.type;if(d==="doc"){let l=a.doc_content;if(l&&typeof l=="object"){let c=l,p=typeof c.text=="string"?c.text:"\u6587\u6863",u=(typeof c.link_url=="string"?c.link_url:"")||c.file?.link_url||"";u?n.push(`[${p}](${u})`):n.push(p)}}else if(d==="text"){let l=a.text_content;if(l&&typeof l=="object"){let c=l,p=typeof c.content=="string"?c.content:"";p&&n.push(p)}}else if(d==="image"){let l=a.image_content;if(l&&typeof l=="object"){let c=l,p=typeof c.name=="string"?c.name:"\u56FE\u7247",u=typeof c.storage_key=="string"?c.storage_key:"";u&&n.push(`![${p}](storage_key:${u})`)}}}}return n}function ni(e){if(!Array.isArray(e))return;let t=e.map(n=>ge(n)).map(n=>{let r=ge(n.identity),i={id:typeof r.id=="string"?r.id:void 0,app_id:typeof r.app_id=="string"?r.app_id:void 0,name:typeof r.name=="string"?r.name:void 0,type:typeof r.type=="string"?r.type:void 0,company_id:typeof r.company_id=="string"?r.company_id:void 0},o=Object.values(i).some(s=>s!==void 0);return{type:typeof n.type=="string"?n.type:void 0,id:typeof n.id=="string"?n.id:void 0,user_id:typeof n.user_id=="string"?n.user_id:void 0,userId:typeof n.userId=="string"?n.userId:void 0,offset:typeof n.offset=="number"?n.offset:void 0,length:typeof n.length=="number"?n.length:void 0,...o?{identity:i}:{}}}).filter(n=>!!(n.id||n.user_id||n.userId||n.type||n.identity));return t.length>0?t:void 0}function ri(e){let t=ge(e),n=ge(t.sender),r=typeof t.sender_id=="string"?t.sender_id:void 0,i=typeof n.id=="string"?n.id:void 0;if(!(!r&&!i))return{sender_id:r,sender:i?{id:i}:void 0}}function Zn(e){let t=ge(e),n=ge(e.message),r=e.send_time<1e12?Math.floor(e.send_time*1e3):e.send_time;return{topic:typeof t.topic=="string"?t.topic:ht,event_id:Yt(t.event_id,t.id,e.message.id)||void 0,company_id:Yt(t.company_id,t.companyId,t.corp_id)||void 0,chat:{id:e.chat.id,type:e.chat.type},message:{id:e.message.id,type:e.message.type,content:ei(e.message),sender:{id:e.sender.id,type:e.sender.type},mentions:ni(n.mentions),reply_to:ri(n.reply_to)},quote_msg_id:Yt(t.quote_msg_id,t.quote_message_id,typeof n.quote_msg_id=="string"?n.quote_msg_id:void 0)||void 0,sender:{id:e.sender.id,type:e.sender.type,name:e.sender.extended_attribute?.name},send_time:r}}function er(e,t,n,r){let i=ge(e);if(typeof i.challenge=="string")return r?.info?.("WPS webhook challenge verification"),{challenge:i.challenge};if(n&&Yn(e)){let s=e;if(s.topic!==ht)return r?.info?.(`WPS webhook skip non-message topic=${s.topic}`),{ok:!1,error:"skip",status:200};if(!Vn({appId:t.appId,appSecret:t.appSecret,topic:s.topic,nonce:s.nonce,time:s.time,encryptedData:s.encrypted_data,signature:s.signature}))return r?.error?.("WPS signature verification failed"),{ok:!1,error:"Invalid signature",status:403};try{let d=Qn(s.encrypted_data,t.appSecret,s.nonce),l=JSON.parse(d);return l.topic=s.topic,l.event_id||(l.event_id=l.message?.id),r?.info?.(`WPS decrypted event: topic=${s.topic}, operation=${s.operation}`),{ok:!0,payload:l}}catch(d){return r?.error?.("WPS decryption failed:",d),{ok:!1,error:"Decryption failed",status:400}}}let o=e;return Vt(o.topic)?(r?.info?.(`WPS webhook skip non-message topic=${String(o.topic)}`),{ok:!1,error:"skip",status:200}):(o.event_id||(o.event_id=o.message?.id),{ok:!0,payload:o})}function tr(e,t){return{...e,pongTimeout:t?.pongTimeout??15e4,autoReconnect:t?.autoReconnect??!0,reconnectBaseInterval:t?.reconnectBaseInterval??1e3,reconnectMaxInterval:t?.reconnectMaxInterval??6e4,reconnectMultiplier:t?.reconnectMultiplier??2,reconnectMaxRetry:t?.reconnectMaxRetry??-1,reconnectJitter:t?.reconnectJitter??.2}}ve();Xe();ve();var J=class extends Error{code;name="SessionResolverError";constructor(t,n){super(n),this.code=t}};function te(...e){for(let t of e)if(typeof t=="string"&&t.trim())return t.trim();return""}function ee(e){return e&&typeof e=="object"?e:{}}function nr(e){return e.trim().replace(/^wps-xiezuo:/i,"").replace(/^wps:/i,"").replace(/^user:/i,"")}function rr(e,t){let n=nr(e),r=nr(t);return n.length>0&&r.length>0&&n===r}function ii(e){if(!Array.isArray(e))return[];let t=[];for(let n of e){let r=ee(n),i=te(r.type).toLowerCase(),o=ee(r.identity),s=[te(r.id,r.user_id,r.userId,r.open_id),te(o.app_id,o.id)].filter(Boolean);for(let a of s)t.push({type:i,id:a})}return t}var Ye=class{config;idempotencyStore;constructor(t,n){this.config=t,this.idempotencyStore=n}normalizeEvent(t){let n=ee(t),r=ee(n.chat),i=ee(n.message),o=ee(n.sender),s=ee(i.sender),a=te(n.event_id,n.eventId,i.event_id,i.eventId,i.id),d=te(i.id,n.message_id,n.messageId,a),l=te(n.company_id,n.companyId),c=te(r.type).toLowerCase(),p=te(r.id),u=te(s.id,o.id,n.user_id,n.userId),m=ee(i.content).text,f=typeof m=="string"?m:te(ee(m).content,i.content,n.message_text,n.messageText),g=u,h;if(c==="group")h=p;else if(["p2p","single","direct"].includes(c))h=void 0;else throw new J("E_CHAT_TYPE_INVALID",`\u672A\u77E5\u7684 chat.type: ${c||"(empty)"}`);let _=ii(i.mentions),y=_.some(fe=>rr(fe.id,this.config.botId)),S=c==="group"&&!y&&_.length===1&&_[0]?.type!=="all",I=y||S,v=ee(i.reply_to),A=ee(v.sender),ae=te(A.id,v.sender_id,v.senderId),Me=rr(ae,this.config.botId);return{event_id:a,message_id:d,company_id:l,user_id:g,group_id:h,message:f,is_at_bot:I,is_reply_to_bot:Me}}resolve(t){let n=t.group_id?"group":"p2p";if(!t.message_id)throw new J("E_MESSAGE_ID_MISSING","\u7F3A\u5C11 message_id");if(!t.event_id)throw new J("E_EVENT_ID_MISSING","\u7F3A\u5C11 event_id");if(!t.company_id)throw new J("E_COMPANY_ID_MISSING","\u7F3A\u5C11 company_id");if(n==="group"&&!t.group_id)throw new J("E_GROUP_ID_MISSING","\u7FA4\u804A\u6D88\u606F\u7F3A\u5C11 group_id");if(n==="p2p"&&!t.user_id)throw new J("E_USER_ID_MISSING","\u79C1\u804A\u6D88\u606F\u7F3A\u5C11 user_id");let r=n==="group"?`${x}:${t.company_id}:acct:${this.config.accountId??"default"}:group:${t.group_id}:bot:${this.config.botId}`:`${x}:${t.company_id}:acct:${this.config.accountId??"default"}:p2p:${t.user_id}:bot:${this.config.botId}`;return{scene:n,session_key:r,idempotency_key:t.event_id,message_id:t.message_id,company_id:t.company_id,user_id:t.user_id,group_id:t.group_id}}async checkIdempotency(t){return this.idempotencyStore.check(t)}async markProcessed(t,n=36e5){await this.idempotencyStore.mark(t,n)}};var Ve=class{store=new Map;async check(t){let n=this.store.get(t);return n?Date.now()>n?(this.store.delete(t),!1):!0:!1}async mark(t,n){this.store.set(t,Date.now()+n)}cleanup(){let t=Date.now();for(let[n,r]of this.store.entries())t>r&&this.store.delete(n)}};function b(...e){for(let t of e)if(typeof t=="string"&&t.trim())return t.trim();return""}function K(...e){for(let t of e){if(typeof t=="number"&&Number.isFinite(t))return t;if(typeof t=="string"&&t.trim()){let n=Number(t);if(Number.isFinite(n))return n}}}var oi=new Set(["text","content","title","caption","desc","description","md","markdown","alt_text"]);function ir(e){let t=[],n=(r,i)=>{if(!(i>6||r==null)){if(typeof r=="string"){r.trim()&&t.push(r.trim());return}if(Array.isArray(r)){for(let o of r)n(o,i+1);return}if(typeof r=="object")for(let[o,s]of Object.entries(r))(oi.has(o.toLowerCase())||typeof s=="object")&&n(s,i+1)}};return n(e,0),Array.from(new Set(t))}function si(e){let t=String(e.type??"").toLowerCase();return["image","img","pic","picture"].includes(t)?!0:!!(e.image_url??e.pic_url??e.thumb_url??e.preview_url)}function ai(e){let t=String(e.type??"").toLowerCase();return["file","attachment","doc","document"].includes(t)?!0:!!(e.file_id??e.file_name??e.mime_type??e.download_url)}function sr(e){return{kind:"image",storageKey:b(e.storage_key),name:b(e.name),mimeType:b(e.type),size:K(e.size),width:K(e.width),height:K(e.height),thumbnailStorageKey:b(e.thumbnail_storage_key)}}function or(e){let t=[],n=(r,i)=>{if(i>8||r==null)return;if(Array.isArray(r)){for(let d of r)n(d,i+1);return}if(typeof r!="object")return;let o=r,s=o.image_content;if(s&&typeof s=="object"&&b(s.storage_key)){t.push(sr(s));return}let a=o.doc_content;if(a&&typeof a=="object"){let d=a.file;d&&typeof d=="object"&&t.push({kind:"file",name:b(a.text,o.alt_text),fileId:b(d.id),url:b(d.link_url)});return}if(si(o)){let d=b(o.storage_key);t.push({kind:"image",storageKey:d||void 0,name:b(o.name,o.file_name,o.title),fileId:b(o.file_id,o.id),url:b(o.image_url,o.pic_url,o.thumb_url,o.preview_url,o.url),mimeType:b(o.mime_type,o.content_type),size:K(o.size,o.file_size)})}else if(ai(o)){let d=b(o.storage_key);t.push({kind:"file",storageKey:d||void 0,name:b(o.file_name,o.name,o.title),fileId:b(o.file_id,o.id),url:b(o.download_url,o.url,o.preview_url),mimeType:b(o.mime_type,o.content_type),size:K(o.size,o.file_size)})}for(let d of Object.values(o))n(d,i+1)};return n(e,0),t}function gt(e){return e<1024?`${e}B`:e<1024*1024?`${(e/1024).toFixed(1)}KB`:`${(e/(1024*1024)).toFixed(1)}MB`}function Ee(e){return e.map((t,n)=>{let r=[`#${n+1}`,t.kind==="image"?"\u56FE\u7247":"\u6587\u4EF6"];return t.cloudType&&r.push("type=cloud"),t.name&&r.push(`display_name=${t.name}`),t.storageKey&&r.push(`storage_key=${t.storageKey}`),t.mimeType&&r.push(`mime=${t.mimeType}`),t.size!==void 0&&r.push(`size=${gt(t.size)}`),t.width!==void 0&&t.height!==void 0&&r.push(`${t.width}x${t.height}`),t.fileId&&r.push(`fileId=${t.fileId}`),t.cloudLinkUrl&&r.push(`link_url=${t.cloudLinkUrl}`),t.url&&r.push(`url=${t.url}`),r.join(" | ")})}function ci(e){let t=e.image;return!t||typeof t!="object"?null:{kind:"image",storageKey:b(t.storage_key),name:b(t.name),mimeType:b(t.type),size:K(t.size),width:K(t.width),height:K(t.height),thumbnailStorageKey:b(t.thumbnail_storage_key)}}function di(e){let t=e.file;if(!t||typeof t!="object")return null;let n=b(t.type),r=t.cloud;if((n==="cloud"||!n&&r)&&r&&typeof r=="object")return{kind:"file",fileId:b(r.id),cloudType:!0,cloudLinkUrl:b(r.link_url),cloudLinkId:b(r.link_id),name:b(t.name,t.file_name)||void 0};let i=t.local;return i&&typeof i=="object"?{kind:"file",storageKey:b(i.storage_key),name:b(i.name),size:K(i.size)}:{kind:"file",storageKey:b(t.storage_key),name:b(t.name,t.file_name),size:K(t.size)}}function li(e){let t=[],n=[],r=(i,o)=>{if(o>8||i==null)return;if(Array.isArray(i)){for(let f of i)r(f,o+1);return}if(typeof i!="object")return;let s=i,a=String(s.type??"").toLowerCase(),d=s.text_content;if(d&&typeof d=="object"){let f=b(d.content);f&&t.push(f)}let l=s.style_text_content;if(l&&typeof l=="object"){let f=b(l.text);f&&t.push(f)}let c=s.mention_content;if(c&&typeof c=="object"){let f=b(c.text);f&&t.push(f)}let p=s.link_content;if(p&&typeof p=="object"){let f=b(p.text);f&&t.push(f)}let u=s.image_content;u&&typeof u=="object"&&b(u.storage_key)&&n.push(sr(u));let m=s.doc_content;if(m&&typeof m=="object"){let f=m.file;f&&typeof f=="object"&&n.push({kind:"file",name:b(m.text,s.alt_text),fileId:b(f.id),url:b(f.link_url)})}if(!d&&!l&&!c&&!p&&!u&&!m&&a!=="nl"&&a!=="ol"&&a!=="ul"){let f=b(s.alt_text);f&&t.push(f)}if(Array.isArray(s.elements))for(let f of s.elements)r(f,o+1)};for(let i of e)r(i,0);return{textTokens:t,attachments:n}}function pi(e){let t=e.rich_text;if(!t||typeof t!="object")return null;let n=t.elements;if(!Array.isArray(n))return null;let r=li(n);return{plainText:r.textTokens.join(`
14
+ `).trim(),attachments:r.attachments}}function ui(e){let t=[],n=(r,i)=>{if(i>12||r==null)return;if(typeof r=="string"){r.trim()&&t.push(r.trim());return}if(Array.isArray(r)){for(let l of r)n(l,i+1);return}if(typeof r!="object")return;let o=r,s=String(o.tag??"").toLowerCase();if(s==="hr"||s==="action"||s==="button"||s==="dropdown"||o.config)return;let a=o.text;if(a&&typeof a=="object"&&typeof a.content=="string"){let l=a.content.trim();l&&t.push(l);return}typeof a=="string"&&a.trim()&&t.push(a.trim());let d=o.title;if(d&&typeof d=="object"){let l=d.text;if(l&&typeof l=="object"&&typeof l.content=="string"){let c=l.content.trim();c&&t.push(c)}}typeof o.content=="string"&&o.content.trim()&&t.push(o.content.trim());for(let l of Object.values(o))typeof l=="object"&&n(l,i+1)};for(let r of e)n(r,0);return t}function ar(e){let t=e.card;if(!t||typeof t!="object")return null;let n=t,i=n.i18n_items?.[0]?.value,o=i?.header?.title?.text?.content??n.header?.title?.text?.content??n.header?.title?.content??"",s=i?.elements??n.elements??[],a=Array.from(new Set(ui(s))),d=[];o&&d.push(`[\u5361\u7247\u6807\u9898] ${o}`),a.length>0&&d.push(a.join(`
15
+ `));let l=d.join(`
16
+ `).trim();return{headerTitle:o,plainText:l}}function fi(e){let t=e.sticker;if(!t||typeof t!="object")return null;let n=t.image;return!n||typeof n!="object"?null:{kind:"image",storageKey:b(n.storage_key),name:b(n.name),mimeType:b(n.type),size:K(n.size),width:K(n.width),height:K(n.height)}}function $e(e,t){let n=e.filter(r=>r.storageKey);return n.length===0?[]:n.map(r=>`[\u9644\u4EF6\u5F85\u5904\u7406: ${r.kind} ${r.name?`"${r.name}" `:""}storage_key=${r.storageKey}]`)}function mi(e){let t=new Set,n=[];for(let r of e){let i=r.storageKey?.trim()||[r.kind,r.fileId??"",r.url??r.cloudLinkUrl??"",r.name??""].join("|");!i||t.has(i)||(t.add(i),n.push(r))}return n}function yt(e,t){let n=e?.content??{},r=(e?.type??"").toLowerCase();if(r==="text"){let c=n,p=c.text,u=b(p?.content,...p?[]:ir(c)),m=mi(or(c));if(m.length===0)return{kind:"text",plainText:u,agentText:u||"[\u6536\u5230\u6D88\u606F] type=text\uFF08\u5185\u5BB9\u4E3A\u7A7A\uFF09",attachments:[]};let f=[];u&&f.push(u),u&&f.push(""),f.push(`[\u672C\u6761\u6D88\u606F type=text\uFF0C\u4F46 content \u5185\u542B\u6709\u9644\u4EF6] count=${m.length}`),f.push(...Ee(m)),f.push(...$e(m,t));let g=m.every(y=>y.kind==="image"),h=m.every(y=>y.kind==="file"),_="mixed";return!u&&g?_="image":!u&&h?_="file":u&&(_="mixed"),{kind:_,plainText:u,agentText:f.join(`
17
+ `).trim(),attachments:m}}if(r==="image"){let c=ci(n);if(c){let u=[`[\u6536\u5230\u56FE\u7247: ${[c.name||"\u672A\u547D\u540D\u56FE\u7247",c.width&&c.height?`${c.width}x${c.height}`:null,c.size?gt(c.size):null].filter(Boolean).join(", ")}]`,...Ee([c])];return u.push(...$e([c],t)),{kind:"image",plainText:"",agentText:u.join(`
18
+ `),attachments:[c]}}}if(r==="file"){let c=di(n);if(c){let u=[`[\u6536\u5230\u6587\u4EF6: ${[c.name||"\u672A\u547D\u540D\u6587\u4EF6",c.size?gt(c.size):null].filter(Boolean).join(", ")}]`,...Ee([c])];return c.cloudType&&c.cloudLinkUrl?(u.push(`[\u4E91\u6587\u4EF6\u94FE\u63A5: ${c.cloudLinkUrl}]`),u.push("[\u63D0\u793A: \u8FD9\u662F WPS \u4E91\u6587\u4EF6\uFF0C\u65E0\u6CD5\u76F4\u63A5\u4E0B\u8F7D\u5230\u672C\u5730\u3002\u53EF\u7528 wps_message_send \u5DE5\u5177\u4EE5 file \u7C7B\u578B\u8F6C\u53D1\uFF0C\u9700\u4F7F\u7528 cloud \u7ED3\u6784\u3002]")):u.push(...$e([c],t)),{kind:"file",plainText:"",agentText:u.join(`
19
+ `),attachments:[c]}}}if(r==="rich_text"){let c=pi(n);if(c){let p=!!c.plainText,u=c.attachments.length>0,m=[];return p&&m.push(c.plainText),u&&(p&&m.push(""),m.push(`[\u6536\u5230\u5BCC\u6587\u672C\u9644\u4EF6] count=${c.attachments.length}`),m.push(...Ee(c.attachments)),m.push(...$e(c.attachments,t))),!p&&!u&&m.push("[\u6536\u5230\u5BCC\u6587\u672C\u6D88\u606F]\uFF08\u672A\u89E3\u6790\u51FA\u6587\u672C/\u9644\u4EF6\u5143\u4FE1\u606F\uFF09"),{kind:p&&u?"mixed":"rich_text",plainText:c.plainText,agentText:m.join(`
20
+ `).trim(),attachments:c.attachments}}}if(r==="card"){let c=ar(n);if(c)return{kind:"card",plainText:c.plainText,agentText:c.plainText||"[\u6536\u5230\u5361\u7247\u6D88\u606F] type=card\uFF08\u672A\u89E3\u6790\u51FA\u6587\u672C\u5185\u5BB9\uFF09",attachments:[]}}if(r==="sticker"){let c=fi(n);if(c){let u=[`[\u6536\u5230\u8868\u60C5\u5305: ${[c.name||"\u672A\u547D\u540D\u8868\u60C5",c.width&&c.height?`${c.width}x${c.height}`:null,c.size?gt(c.size):null].filter(Boolean).join(", ")}]`,...Ee([c])];return u.push(...$e([c],t)),{kind:"sticker",plainText:"",agentText:u.join(`
21
+ `),attachments:[c]}}}let i=ir(n).join(`
22
+ `).trim(),o=or(n),s=!!i,a=o.length>0,d="unknown";s&&!a&&(d="text"),!s&&a&&(d=o.every(c=>c.kind==="image")?"image":"file"),s&&a&&(d="mixed");let l=[];return s&&l.push(i),a&&(l.push(""),l.push(`[\u6536\u5230\u9644\u4EF6] kind=${d} count=${o.length}`),l.push(...Ee(o)),l.push(...$e(o,t))),!s&&!a&&l.push(`[\u6536\u5230\u6D88\u606F] type=${e?.type??"unknown"}\uFF08\u672A\u89E3\u6790\u51FA\u6587\u672C/\u9644\u4EF6\u5143\u4FE1\u606F\uFF09`),{kind:d,plainText:i,agentText:l.join(`
23
+ `).trim(),attachments:o}}Je();import{mkdir as _i,writeFile as hi}from"node:fs/promises";import{createHash as gi}from"node:crypto";import{tmpdir as yi}from"node:os";import ye from"node:path";var Qt=5*1024*1024,wi=10*1024*1024,bi=64*1024;function xi(){let e=ye.join(yi(),"openclaw-media");return ye.isAbsolute(e)?e:ye.resolve(e)}var cr=xi();function Si(e,t){let n=t?ye.extname(t).replace(".",""):"";return n||({"image/png":"png","image/jpeg":"jpg","image/jpg":"jpg","image/gif":"gif","image/webp":"webp","image/bmp":"bmp","application/pdf":"pdf"}[e]??"bin")}function ki(e){return gi("md5").update(e).digest("hex").substring(0,8)}var Ii=new Set(["md","markdown","txt","text","log","rst","json","yaml","yml","xml","html","htm","csv","tsv","js","mjs","cjs","ts","tsx","jsx","py","go","rs","java","kt","rb","php","c","h","cc","cpp","hpp","cs","swift","m","mm","sh","bash","zsh","fish","ps1","ini","conf","cfg","toml","env","properties","sql","graphql","proto"]),vi=["text/"],Ti=new Set(["application/json","application/xml","application/yaml","application/x-yaml","application/javascript","application/typescript","application/x-sh","application/toml"]);function Pi(e,t){let n=(e||"").toLowerCase();if(vi.some(i=>n.startsWith(i))||Ti.has(n))return!0;let r=t?ye.extname(t).replace(".","").toLowerCase():"";return r?Ii.has(r):!1}var dr={md:"markdown",markdown:"markdown",json:"json",yaml:"yaml",yml:"yaml",xml:"xml",html:"html",htm:"html",csv:"csv",tsv:"tsv",js:"javascript",mjs:"javascript",cjs:"javascript",ts:"typescript",tsx:"tsx",jsx:"jsx",py:"python",go:"go",rs:"rust",java:"java",kt:"kotlin",rb:"ruby",php:"php",c:"c",h:"c",cc:"cpp",cpp:"cpp",hpp:"cpp",cs:"csharp",swift:"swift",sh:"bash",bash:"bash",zsh:"bash",fish:"bash",ps1:"powershell",toml:"toml",ini:"ini",conf:"ini",cfg:"ini",env:"ini",sql:"sql",graphql:"graphql",proto:"protobuf"};function Ei(e,t){let n=e?ye.extname(e).replace(".","").toLowerCase():"";return n&&dr[n]?dr[n]:t==="application/json"?"json":t.startsWith("text/")?t.slice(5):""}function $i(e){let t=0,n=/`+/g,r;for(;(r=n.exec(e))!==null;)r[0].length>t&&(t=r[0].length);return"`".repeat(Math.max(3,t+1))}async function en(e){let{client:t,chatId:n,messageId:r,attachments:i,log:o}=e,s=o?.info??(()=>{}),a=i.filter(c=>c.storageKey);if(!a.length||!n||!r)return{fetched:[],skipped:a.map(c=>({storageKey:c.storageKey??"",reason:n?r?"no storageKey":"missing messageId":"missing chatId"}))};await _i(cr,{recursive:!0});let d={fetched:[],skipped:[]},l=0;for(let c of a){let p=c.storageKey;try{if(c.size&&c.size>Qt){d.skipped.push({storageKey:p,reason:`too large: ${c.size} bytes`});continue}if(l>=wi){d.skipped.push({storageKey:p,reason:"total download budget exceeded"});continue}s(`WPS prefetch: downloading ${p.substring(0,20)}\u2026 chatId=${n} messageId=${r}`);let u=await t.request({method:"GET",path:`/v7/chats/${encodeURIComponent(n)}/messages/${encodeURIComponent(r)}/resources/${encodeURIComponent(p)}/download`}),m=He(u);if(!m){d.skipped.push({storageKey:p,reason:"no download URL in API response"}),s(`WPS prefetch skip: no download URL for ${p.substring(0,20)}\u2026`);continue}s("WPS prefetch: resolved download URL, fetching bytes\u2026");let f=await fetch(m);if(!f.ok){d.skipped.push({storageKey:p,reason:`HTTP ${f.status}`}),s(`WPS prefetch skip: HTTP ${f.status} for ${p.substring(0,20)}\u2026`);continue}let g=Number(f.headers.get("content-length")??"0");if(g>Qt){d.skipped.push({storageKey:p,reason:`content-length ${g} > limit`});continue}let h=new Uint8Array(await f.arrayBuffer());if(h.byteLength>Qt){d.skipped.push({storageKey:p,reason:`downloaded ${h.byteLength} > limit`});continue}l+=h.byteLength;let _=f.headers.get("content-type")?.split(";")[0]?.trim()??"",y=_&&_!=="application/octet-stream"?_:c.mimeType??(_||"application/octet-stream"),S=c.name?.trim(),I=ki(p),v=S?`${I}_${S}`:`${r}_${I}.${Si(y,c.name)}`,A=ye.join(cr,v);await hi(A,h);let ae;if(Pi(y,c.name)&&h.byteLength<=bi)try{ae=new TextDecoder("utf-8",{fatal:!1}).decode(h)}catch{ae=void 0}d.fetched.push({storageKey:p,displayName:c.name??"attachment",mimeType:y,size:h.byteLength,localPath:A,...ae!==void 0?{inlineText:ae}:{}}),s(`WPS prefetch ok: ${p.substring(0,20)}\u2026 \u2192 ${A} (${y}, ${h.byteLength}B${ae!==void 0?", text inlined":""})`)}catch(u){d.skipped.push({storageKey:p,reason:String(u)}),s(`WPS prefetch failed: ${p.substring(0,20)}\u2026 ${String(u)}`)}}return d}function tn(e,t){let n=[];for(let r of e.fetched)if(r.mimeType.startsWith("image/"))n.push(`[\u5DF2\u4E0B\u8F7D\u56FE\u7247: ${r.localPath} | ${r.displayName} | ${r.mimeType} | ${Zt(r.size)}]`);else if(r.inlineText!==void 0){n.push(`[\u5DF2\u4E0B\u8F7D\u6587\u672C\u9644\u4EF6: ${r.displayName} | ${r.mimeType} | ${Zt(r.size)} | path=${r.localPath}]`),n.push("\u4EE5\u4E0B\u662F\u6587\u4EF6\u5B8C\u6574\u5185\u5BB9\uFF1A");let i=$i(r.inlineText),o=Ei(r.displayName,r.mimeType);n.push(`${i}${o}`),n.push(r.inlineText),n.push(i)}else n.push(`[\u5DF2\u4E0B\u8F7D\u6587\u4EF6: ${r.localPath} | ${r.displayName} | ${r.mimeType} | ${Zt(r.size)}]`);for(let r of e.skipped)n.push(`[\u9644\u4EF6\u672A\u4E0B\u8F7D: storage_key=${r.storageKey.substring(0,30)}\u2026 \u539F\u56E0: ${r.reason}]`);if(t?.fromQuote&&e.fetched.length>0){n.push(""),n.push("[\u5F15\u7528\u9644\u4EF6\u56DE\u53D1\u6307\u4EE4] \u7528\u6237\u8981\u6C42\u53D1\u56DE\u5F15\u7528\u7684\u56FE\u7247/\u6587\u4EF6\u65F6\uFF0C\u8C03\u7528 message \u5DE5\u5177\uFF1A");for(let r of e.fetched)n.push(` \u2192 message(action="send", message="\u4E3A\u60A8\u53D1\u56DE\u56FE\u7247", media="${r.localPath}")`)}return n.join(`
24
+ `)}function Zt(e){return e<1024?`${e}B`:e<1024*1024?`${(e/1024).toFixed(1)}KB`:`${(e/(1024*1024)).toFixed(1)}MB`}import{readFile as Ai}from"node:fs/promises";import Ci from"node:os";import nn from"node:path";function Oi(){let e=process.env.OPENCLAW_CREDENTIALS_DIR?.trim();if(e)return e;let t=process.env.OPENCLAW_HOME?.trim()||nn.join(Ci.homedir(),".openclaw");return nn.join(t,"credentials")}function Ri(e){return e.trim().replace(/^wps-xiezuo:/i,"").replace(/^wps:/i,"")}async function lr(e){let t=nn.join(Oi(),`${e.channelId}-${e.accountId}-allowFrom.json`),n="";try{n=await Ai(t,"utf8")}catch(r){return r?.code!=="ENOENT"&&e.log?.debug?.(`[wps-xiezuo] load pairing allowFrom failed: ${String(r)}`),[]}try{let r=JSON.parse(n);return Array.isArray(r.allowFrom)?r.allowFrom.map(i=>Ri(String(i))).filter(i=>i.length>0):[]}catch(r){return e.log?.warn?.(`[wps-xiezuo] invalid pairing allowFrom json (${t}): ${String(r)}`),[]}}Xt();var qi=36e5;function Ni(e){if(!e||typeof e!="object")return null;let t=e;if(typeof t.id=="string"&&typeof t.type=="string")return t;let n=t.message;return n&&typeof n=="object"&&typeof n.id=="string"?n:null}var wr=new Map;function Mi(e,t){let n=`${e}:${t}`,r=wr.get(n);return r||(r=new Ye({botId:t,accountId:e},new Ve),wr.set(n,r)),r}function un(e){return e.trim().replace(/^wps-xiezuo:/i,"").replace(/^wps:/i,"")}function Wi(e,t,n){if(n==="disabled")return!1;if(n==="open")return!0;if(!t||t.length===0)return!1;let r=un(e);return t.some(i=>i==="*"||un(i)===r)}function zi(e,t){let n=e?.groups??{};return(n[t]??n["*"])?.requireMention??!0}function Li(e){let t=(n,r)=>r>8||n==null?!1:typeof n=="string"?/<at\b[^>]*>/i.test(n)||/@\S+/.test(n):Array.isArray(n)?n.some(i=>t(i,r+1)):typeof n=="object"?Object.values(n).some(i=>t(i,r+1)):!1;return t(e,0)}function Fi(e){let t=String(e??"").toLowerCase();return t==="image"||t==="file"||t==="sticker"}function Bi(e){let t=e.match(/:group:([^:]+)/);if(t)return{type:"chat",receiver_id:t[1]};let n=e.match(/:p2p:([^:]+)/);return n?{type:"user",receiver_id:n[1]}:{type:"user",receiver_id:e}}async function Oe(e,t,n){let r=E(e),i=$(e.baseUrl,r),o=Bi(t);await i.request({method:"POST",path:"/v7/messages/create",body:{type:"text",receiver:o,content:{text:{content:n,type:"markdown"}}}})}async function Gi(e,t,n,r){let i=E(e);await $(e.baseUrl,i).request({method:"POST",path:`/v7/chats/${encodeURIComponent(t)}/messages/${encodeURIComponent(n)}/reply`,body:{type:"text",content:{text:{content:r,type:"markdown"}}}})}async function fn(e){let t=e.log??{},n=t.info??console.log,r=t.error??console.error,{cfg:i,accountId:o,channelRuntime:s,wpsCfg:a,creds:d,eventPayload:l}=e;if(Vt(l.topic)){n(`WPS skip non-message topic: ${String(l.topic)}`);return}let c=l.message,p=l.sender,u=l.chat;if(!c||!p)return;let m=Mi(o,d.clientId),f,g;try{f=m.normalizeEvent(l),g=m.resolve(f)}catch(C){if(C instanceof J){n(`WPS session resolve skipped: code=${C.code}, reason=${C.message}`);return}r("WPS session resolve failed:",C);return}if(!g){n(`WPS skip inbound: not mentioning/replying bot (event_id=${f.event_id||"unknown"})`);return}if(g.scene==="group"){let C=g.group_id??u?.id??"",G=zi(a,C),D=Li(c.content),O=Fi(c.type);if(G&&!(f.is_at_bot||f.is_reply_to_bot||D||O)){n(`WPS skip: group not mentioning bot (event_id=${f.event_id||"unknown"})`);return}}if(await m.checkIdempotency(g.idempotency_key)){n(`WPS dedupe: skip duplicate event_id=${g.idempotency_key}`);return}await m.markProcessed(g.idempotency_key,qi);let _=g.user_id||p.id||"";if(!_){r("Unable to identify sender");return}let y=g.group_id??u?.id??"",S=c.id??"",I=yt(c,{chatId:y,messageId:S}),v=g.scene==="p2p",A=g.session_key,ae=v?`wps:${_}`:g.session_key,Me=I.agentText,fe,We=[],ot=[],ze=[];I.plainText&&ze.push(I.plainText);let ce=l.quote_msg_id,st,Ot=[];if(ce&&y){let C=E(d),G=$(d.baseUrl,C);try{n(`WPS quote fetch: chatId=${y} quote_msg_id=${ce}`);let D=await G.request({method:"GET",path:`/v7/chats/${encodeURIComponent(y)}/messages/${encodeURIComponent(ce)}`}),O=Ni(D?.data??null);if(O){let P=yt(O,{chatId:y,messageId:ce}),ke=P.attachments.filter(j=>j.storageKey),de=P.attachments.filter(j=>j.cloudType),W=[];if(W.push("[\u7528\u6237\u5F15\u7528\u4E86\u4EE5\u4E0B\u6D88\u606F]"),P.plainText&&W.push(P.plainText),ke.length>0){let j=await en({client:G,chatId:y,messageId:ce,attachments:ke,log:t});if(j.fetched.length>0||j.skipped.length>0){W.push(tn(j,{chatId:y,messageId:ce,fromQuote:!0}));for(let R of j.fetched)Ot.push({storageKey:R.storageKey,displayName:R.displayName,mimeType:R.mimeType,size:R.size,localPath:R.localPath,fromQuote:!0}),We.push(R.localPath),ot.push(R.mimeType);n(`WPS quote prefetch: ${j.fetched.length} ok, ${j.skipped.length} skipped`)}}if(de.length>0){for(let q of de){let me=q.name||"\u672A\u547D\u540D\u4E91\u6587\u4EF6";W.push(`[\u5F15\u7528\u4E91\u6587\u4EF6: ${me}]`),q.cloudLinkUrl&&W.push(`\u94FE\u63A5: ${q.cloudLinkUrl}`),q.fileId&&W.push(`\u6587\u4EF6ID: ${q.fileId}`)}W.push(""),W.push("[\u4E91\u6587\u4EF6\u56DE\u53D1\u6307\u4EE4] \u7528\u6237\u8981\u6C42\u53D1\u56DE\u5F15\u7528\u7684\u4E91\u6587\u4EF6\u65F6\uFF0C\u4F7F\u7528 wps_message_send \u5DE5\u5177\uFF1A");let j=v?"user":"chat",R=v?_:y;for(let q of de){let me={file:{type:"cloud",cloud:{}}},Ie=me.file.cloud;q.fileId&&(Ie.id=q.fileId),q.cloudLinkId&&(Ie.link_id=q.cloudLinkId),q.cloudLinkUrl&&(Ie.link_url=q.cloudLinkUrl),W.push(` \u2192 wps_message_send(receiver_type="${j}", receiver_id="${R}", msg_type="file", content='${JSON.stringify(me)}')`)}}ke.length===0&&de.length===0&&P.attachments.length===0&&!P.plainText&&W.push(`[\u5F15\u7528\u6D88\u606F\u5185\u5BB9\u4E3A\u7A7A\u6216\u672A\u89E3\u6790] type=${O.type??"unknown"}`),st=W.join(`
25
+ `)}else n(`WPS quote fetch: empty data for quote_msg_id=${ce}`)}catch(D){r(`WPS quote fetch failed for quote_msg_id=${ce}:`,D),st=`[\u5F15\u7528\u6D88\u606F\u83B7\u53D6\u5931\u8D25 quote_msg_id=${ce}]`}}if(I.attachments.some(C=>C.storageKey)&&y&&S){let C=E(d),G=$(d.baseUrl,C),D=await en({client:G,chatId:y,messageId:S,attachments:I.attachments,log:t});if(D.fetched.length>0||D.skipped.length>0){ze.push(tn(D,{chatId:y,messageId:S})),fe=D.fetched.map(O=>({storageKey:O.storageKey,displayName:O.displayName,mimeType:O.mimeType,size:O.size,localPath:O.localPath}));for(let O of D.fetched)We.push(O.localPath),ot.push(O.mimeType);n(`WPS media prefetch: ${D.fetched.length} ok, ${D.skipped.length} skipped`)}}st&&ze.push(st),ze.length>0&&(Me=ze.join(`
26
+
27
+ `)),Ot.length>0&&(fe=[...fe??[],...Ot]);let Rt=Me,at=I.plainText||Me;n(`WPS received: kind=${I.kind}, session_key=${g.session_key}, preview=${at.substring(0,50)}`);try{let C=(a.allowFrom??[]).map(k=>un(String(k))),G=a.dmPolicy??"pairing",D=v&&(G==="pairing"||G==="allowlist")?await lr({channelId:x,accountId:o,log:t}):[],O=Array.from(new Set([...C,...D]));if(v&&G==="disabled"){n(`Direct message denied by dmPolicy=disabled (accountId=${o}, sender=${_})`);return}if(v&&!Wi(_,O,G)){if(n(`Sender ${_} not in allowFrom (policy: ${G})`),G==="pairing"&&s?.pairing){let k=s.pairing;if(k?.upsertPairingRequest&&k?.buildPairingReply){let{code:N,created:M}=await k.upsertPairingRequest({channel:x,accountId:o,id:_});if(N&&M){let ct=`${k.buildPairingReply({channel:x,idLine:`Your WPS user id: ${_}`,code:N})}
28
+
29
+ For multi-account channels, approve with:
30
+ openclaw pairing approve --channel ${x} --account ${o} ${N}`;await Oe(d,A,ct)}}}return}if(!v){let k=a?.groupPolicy??"allowlist",N=a?.groups??{};if(k==="allowlist"&&!N[y]&&!N["*"]){n(`Group ${y} blocked by groupPolicy=allowlist`);return}}if(at.trim()==="/wpsxiezuo auth"){let{sendAuthCard:k}=await Promise.resolve().then(()=>(St(),pn)),{getLazyWpsCfg:N}=await Promise.resolve().then(()=>(Ae(),fr));try{let M=y?"chat":"user",_e=y||_;await k({creds:d,wpsCfg:N(),wpsUserId:_,receiverType:M,receiverId:_e})||await Oe(d,A,"\u5F53\u524D\u5E94\u7528\u6CA1\u6709\u53EF\u6388\u6743\u7684\u7528\u6237\u6743\u9650\uFF08delegated scopes \u4E3A\u7A7A\uFF09\uFF0C\u8BF7\u5148\u5728\u5F00\u653E\u5E73\u53F0\u540E\u53F0\u5F00\u901A\u3002")}catch(M){r("WPS /wpsxiezuo auth failed:",M),await Oe(d,A,`\u6388\u6743\u5361\u7247\u53D1\u9001\u5931\u8D25\uFF1A${String(M)}`)}return}if(at.trim()==="/wps-id"||at.trim().startsWith("/wps-id ")){let k={sender:{id:p.id??"",type:p.type??"",name:p.name??""},chat:{id:u?.id??"",type:u?.type??""},message:{id:c.id??"",type:c.type??""},isDirect:v};await Oe(d,A,`WPS id debug:
31
+ ${JSON.stringify(k,null,2)}`);return}if(!s){n("WPS: channelRuntime not available \u2014 skipping AI dispatch");return}let P=s.reply,ke=s.routing,de="main",W="",j=o;if(ke?.resolveAgentRoute){let k=ke.resolveAgentRoute({cfg:i,channel:x,accountId:o,peer:{kind:v?"direct":"group",id:g.session_key}});de=k.agentId,W=k.sessionKey?.trim()??"",k.accountId&&(j=k.accountId,n(`WPS route account override: ${o} -> ${k.accountId}`))}let R=W||g.session_key,q=j;n(`WPS route: agentId=${de}, inboundSessionKey=${R}, accountId=${q}`);let me={Body:Rt,BodyForAgent:Rt,...We.length>0?{MediaPath:We[0],MediaType:ot[0],MediaPaths:We,MediaTypes:ot}:{},RawBody:JSON.stringify({session:g,chatId:y,messageId:S,messageType:I.kind,plainText:I.plainText,attachments:I.attachments,...fe?{prefetchedMedia:fe}:{}}),CommandBody:Rt,From:ae,To:v?`user:${_}`:`chat:${y}`,SessionKey:R,Label:R,ConversationLabel:R,DisplayName:R,SessionLabel:R,AccountId:q,ChatType:v?"direct":"group",GroupId:void 0,SenderName:p.name??void 0,SenderId:_,Provider:x,Surface:"wps",Channel:x,Timestamp:l.send_time??Date.now(),OriginatingChannel:x,OriginatingFrom:`wps:${_}`,OriginatingTo:`wps:${d.clientId}`},Ie=P.finalizeInboundContext?P.finalizeInboundContext(me):me,Le=null;if(y&&S)try{await Ht(d,y,S),Le={kind:"reaction",chatId:y,messageId:S},n(`WPS thinking reaction added: chatId=${y}, messageId=${S}`)}catch(k){n(`WPS thinking reaction failed, falling back to text: ${String(k)}`);try{await Oe(d,A,"\u6B63\u5728\u601D\u8003\u4E2D..."),Le={kind:"text-fallback"}}catch(N){n(`WPS thinking fallback text failed: ${String(N)}`)}}let Un=()=>async(k,N)=>{let M=k.text??"";if(!M)return;let _e=M.trim();if(/Message:.*[\\/]openclaw-media[\\/].*failed/i.test(_e)){n(`WPS deliver: suppressed media-failed noise: ${_e.substring(0,80)}`);return}n(`WPS deliver: text length=${M.length}, preview=${M.substring(0,80)}`),!v&&y&&S?await Gi(d,y,S,M):await Oe(d,A,M)};try{if(P.dispatchReplyWithBufferedBlockDispatcher)await P.dispatchReplyWithBufferedBlockDispatcher({ctx:Ie,cfg:i,dispatcherOptions:{deliver:Un(),responsePrefix:"",humanDelay:P.resolveHumanDelayConfig?P.resolveHumanDelayConfig(i,de):void 0,onError:(k,N)=>{r(`WPS ${N.kind} reply error: ${String(k)}`)}}}),n("WPS: agent dispatch completed");else if(P.dispatchReplyFromConfig&&P.createReplyDispatcherWithTyping){let k=P.resolveHumanDelayConfig?P.resolveHumanDelayConfig(i,de):void 0,{dispatcher:N,replyOptions:M,markDispatchIdle:_e}=P.createReplyDispatcherWithTyping({responsePrefix:"",humanDelay:k,deliver:Un(),onError:(ct,Lr)=>{r(`WPS ${Lr.kind} reply error: ${String(ct)}`)}});try{await P.dispatchReplyFromConfig({ctx:Ie,cfg:i,dispatcher:N,replyOptions:M})}finally{_e()}n("WPS: agent dispatch completed (fallback path)")}else n("WPS: channelRuntime.reply dispatch APIs not found, skipping agent dispatch")}finally{Le?.kind==="reaction"&&(await Jt(d,Le.chatId,Le.messageId,t),n("WPS thinking reaction removed"))}}catch(C){r("WPS async inbound error:",C)}}Ae();Ge();Je();import{createHash as Ki}from"node:crypto";function Hi(e){return Ki("sha256").update(e).digest("hex")}var br=20*1024*1024;function _n(e){let t=e.trim();return!t||t.startsWith("http://")||t.startsWith("https://")?!1:!!(/^[a-zA-Z]:[\\/]/.test(t)||t.startsWith("\\\\")||t.startsWith("/tmp/")||t.startsWith("/var/folders/")||t.includes("openclaw-media"))}async function hn(e,t,n,r,i){let o=i?.info??console.log,s=i?.error??console.error,a=r.byteLength;if(a===0)throw new Error("upload content is empty");if(a>br)throw new Error(`file too large: ${a} bytes (max ${br})`);let d=Hi(r);o(`[upload] phase1 start: fileName=${t} fileType=${n} size=${a} checksum=${d.substring(0,16)}\u2026`);let l=await e.request({method:"POST",path:"/v7/chats/resources/upload",body:{file_name:t,file_size:a,file_type:n,checksum:d}}),c=l.data??l;if(!c||typeof c!="object")throw new Error(`upload phase 1 returned no data: ${JSON.stringify(l).substring(0,300)}`);let p=c.data,u=p&&typeof p=="object"?p:c;o(`[upload] phase1 response keys: source=[${Object.keys(u)}] hasNested=${!!p}`);let m=u.upload_entry;m&&o(`[upload] upload_entry keys: [${Object.keys(m)}]`);let f=typeof u.url=="string"&&u.url.trim()?u.url.trim():typeof u.upload_url=="string"&&u.upload_url.trim()?u.upload_url.trim():m&&typeof m.url=="string"&&m.url.trim()?m.url.trim():null,g=typeof u.storage_key=="string"&&u.storage_key.trim()?u.storage_key.trim():null;if(!f)throw new Error(`upload phase 1 did not return an upload URL: keys=${JSON.stringify(Object.keys(u))}, raw=${JSON.stringify(c).substring(0,300)}`);if(!g)throw new Error(`upload phase 1 did not return a storage_key: keys=${JSON.stringify(Object.keys(u))}`);o(`[upload] phase1 ok: storageKey=${g.substring(0,20)}\u2026 uploadUrl=${f.substring(0,80)}\u2026`);let h=m&&typeof m.headers=="object"&&m.headers&&Object.keys(m.headers).length>0,_={};if(h)for(let[S,I]of Object.entries(m.headers))typeof I=="string"&&(_[S]=I);else _["Content-Type"]=n,_["Content-Length"]=String(a);o(`[upload] phase2 PUT headers: ${JSON.stringify(_)}`);let y=await fetch(f,{method:"PUT",headers:_,body:r});if(!y.ok){let S=await y.text().catch(()=>"");throw s(`[upload] phase2 PUT failed: HTTP ${y.status} body=${S.substring(0,300)}`),new Error(`upload phase 2 PUT failed: HTTP ${y.status} ${S.substring(0,200)}`)}return o(`[upload] phase2 PUT ok: HTTP ${y.status} storageKey=${g.substring(0,20)}\u2026`),{storage_key:g,file_name:t,file_size:a}}function mn(e){return e.data??null}function kt(e){return{error:e instanceof Error?e.message:String(e)}}function X(e,t){let n=e[t];if(typeof n!="string"||!n.trim())throw new Error(`${t} is required and must be a non-empty string`);return n.trim()}function Ji(e,t){let n=e[t];if(typeof n=="number"&&Number.isFinite(n))return n;if(typeof n=="string"&&n.trim()!==""){let r=Number(n);if(Number.isFinite(r))return r}throw new Error(`${t} is required and must be a finite number`)}function Xi(e,t){let n=e[t];if(n!=null){if(typeof n=="number"&&Number.isFinite(n))return n;if(typeof n=="string"&&n.trim()!==""){let r=Number(n);if(Number.isFinite(r))return r}throw new Error(`${t} must be a finite number when provided`)}}function gn(e,t,n){let r=n?.info??(()=>{}),i=n?.error??(()=>{});t({name:"wps_media_download",description:"Obtain a pre-signed download URL for a message attachment or resource (GET /v7/chats/{chat_id}/messages/{message_id}/resources/{storage_key}/download). Use storage_key from inbound message attachments (WPS cloud). Do NOT use the generic read() tool with the attachment display filename \u2014 that file is not on the OpenClaw workspace disk. The returned data typically includes a short-lived URL for HTTP GET.",parameters:{type:"object",properties:{chat_id:{type:"string",description:"Chat id containing the message."},message_id:{type:"string",description:"Message id that owns the resource."},storage_key:{type:"string",description:"Resource storage key from the message."}},required:["chat_id","message_id","storage_key"]},async execute(o,s){try{let a=encodeURIComponent(X(s,"chat_id")),d=encodeURIComponent(X(s,"message_id")),l=encodeURIComponent(X(s,"storage_key")),c=await e.request({method:"GET",path:`/v7/chats/${a}/messages/${d}/resources/${l}/download`});return mn(c)}catch(a){return kt(a)}}}),t({name:"wps_media_fetch_base64",description:"Fetch attachment bytes from WPS and return base64 (no shell/exec required). It internally calls the WPS media download endpoint, follows the pre-signed URL, and returns `{ mime_type, size, base64 }`. Use this when you need OCR or image understanding in-tool; do NOT call exec/curl manually.",parameters:{type:"object",properties:{chat_id:{type:"string",description:"Chat id containing the message."},message_id:{type:"string",description:"Message id that owns the resource."},storage_key:{type:"string",description:"Resource storage key from the message."},max_bytes:{type:"number",description:"Optional max bytes limit for safety (default 5MB). If exceeded, tool returns an error."}},required:["chat_id","message_id","storage_key"]},async execute(o,s){try{let a=encodeURIComponent(X(s,"chat_id")),d=encodeURIComponent(X(s,"message_id")),l=encodeURIComponent(X(s,"storage_key")),c=Xi(s,"max_bytes")??5*1024*1024;if(c<=0)throw new Error("max_bytes must be positive");r(`[tool:wps_media_fetch_base64] start: chatId=${decodeURIComponent(a)} msgId=${decodeURIComponent(d)} sk=${decodeURIComponent(l).substring(0,20)}\u2026`);let p=await e.request({method:"GET",path:`/v7/chats/${a}/messages/${d}/resources/${l}/download`}),u=mn(p),m=Gt(u),f=await fetch(m);if(!f.ok)throw new Error(`download url request failed: HTTP ${f.status}`);let g=Number(f.headers.get("content-length")??"0");if(Number.isFinite(g)&&g>c)throw new Error(`attachment too large: ${g} bytes > max_bytes=${c}`);let h=f.headers.get("content-type")??"application/octet-stream",_=new Uint8Array(await f.arrayBuffer());if(_.byteLength>c)throw new Error(`attachment too large after download: ${_.byteLength} bytes > max_bytes=${c}`);return r(`[tool:wps_media_fetch_base64] ok: ${h} ${_.byteLength}B`),{chat_id:decodeURIComponent(a),message_id:decodeURIComponent(d),storage_key:decodeURIComponent(l),mime_type:h,size:_.byteLength,base64:Buffer.from(_).toString("base64")}}catch(a){return i("[tool:wps_media_fetch_base64] error:",a),kt(a)}}}),t({name:"wps_media_upload",description:"Low-level Phase 1 upload (POST /v7/chats/resources/upload). Returns pre-signed URL + storage_key. The API requires a `checksum` of the file bytes (SHA256 lowercase hex). Prefer wps_media_upload_base64 which computes checksum and completes the PUT automatically.",parameters:{type:"object",properties:{file_name:{type:"string",description:"Original file name including extension."},file_size:{type:"number",description:"File size in bytes."},file_type:{type:"string",description:"MIME type or WPS file type discriminator as required by the API (e.g. image/png)."},checksum:{type:"string",description:"SHA256 lowercase hex digest of the entire file (must match the bytes you will PUT in phase 2 and file_size)."}},required:["file_name","file_size","file_type","checksum"]},async execute(o,s){try{let a=X(s,"file_name"),d=Ji(s,"file_size"),l=X(s,"file_type"),c=X(s,"checksum");if(d<0)throw new Error("file_size must be non-negative");let p=await e.request({method:"POST",path:"/v7/chats/resources/upload",body:{file_name:a,file_size:d,file_type:l,checksum:c}});return mn(p)}catch(a){return kt(a)}}}),t({name:"wps_media_upload_base64",description:"Upload a file to WPS and get a storage_key for sending as image/file message. Accepts base64-encoded file content. Internally performs: 1) POST metadata (includes SHA256 checksum of decoded bytes) to get pre-signed upload URL + storage_key, 2) PUT raw bytes to the pre-signed URL. Returns { storage_key, file_name, file_size }. After getting storage_key, use wps_message_send(receiver_type, receiver_id, msg_type=image, content JSON with storage_key) to send to the current WPS chat or user.",parameters:{type:"object",properties:{file_name:{type:"string",description:"File name with extension (e.g. photo.png)."},file_type:{type:"string",description:"MIME type (e.g. image/png, image/jpeg, application/pdf)."},base64:{type:"string",description:"Base64-encoded file content. For images previously fetched, pass the base64 from wps_media_fetch_base64 or from a local file read."}},required:["file_name","file_type","base64"]},async execute(o,s){try{let a=X(s,"file_name"),d=X(s,"file_type"),l=X(s,"base64"),c=Buffer.from(l,"base64");r(`[tool:wps_media_upload_base64] start: ${a} ${d} ${c.byteLength}B`);let{storage_key:p,file_name:u,file_size:m}=await hn(e,a,d,c);return r(`[tool:wps_media_upload_base64] ok: storage_key=${p.substring(0,20)}\u2026 ${u} ${m}B`),{storage_key:p,file_name:u,file_size:m}}catch(a){return i("[tool:wps_media_upload_base64] error:",a),kt(a)}}})}Je();var Re=null;function Sr(e){Re=e}function eo(){if(!Re)throw new Error("WPS plugin runtime not initialized");return Re}var vt="wps",xr={id:x,label:"WPS",selectionLabel:"WPS365 (Open Platform)",docsPath:"/channels/wps-xiezuo",docsLabel:"WPS",blurb:"WPS365 Open Platform bot integration.",aliases:[x,vt,"wps365"],order:70};function Tt(e){let t=e.channels;if(t)return t[x]??t[vt]}function ue(e){return Mt(Tt(e))}function to(){let e=It.join(Zi(),".openclaw","openclaw.json");if(!Yi(e))return null;try{let t=Vi(e,"utf8");return t.trim()?JSON.parse(t):null}catch{return null}}function yn(e){let t=e&&typeof e=="object"?e:null;if(t&&Object.keys(ue(t)).length>0)return t;let n=Re?.config&&typeof Re.config=="object"?Re.config:null;if(n&&Object.keys(ue(n)).length>0)return n;let r=to();return r&&Object.keys(ue(r)).length>0?r:t??n??r??{}}function z(e){return Nt(Tt(e))}function Y(e,t){let n=ue(e);return n[t]??n[z(e)]??n[pe]}function no(e,t=pe){let n=Y(e,t);return{accountId:t,enabled:n?.enabled!==!1,configured:!!Q(n),config:n??{enabled:!1}}}function wn(e){return e.trim().replace(/^wps-xiezuo:/i,"").replace(/^wps:/i,"")}function ro(e){return e.trim().length>0}function kr(e){if(e.startsWith("user:"))return{type:"user",id:e.slice(5)};if(e.startsWith("chat:"))return{type:"chat",id:e.slice(5)};if(e.startsWith("wps:")||e.startsWith("wps-xiezuo:")){let t=e.match(/:group:([^:]+)/);if(t)return{type:"chat",id:t[1]};let n=e.match(/:p2p:([^:]+)/);if(n)return{type:"user",id:n[1]};let r=e.split(":");if(r.length===2)return{type:"user",id:r[1]};let i=r[2]??r[1],o=r[3]??r[2];return{type:i==="group"?"chat":"user",id:o??r[r.length-1]??e}}return{type:"user",id:e}}async function bn(e,t,n){let r=E(e),i=$(e.baseUrl,r),o=kr(t);return{messageId:(await i.request({method:"POST",path:"/v7/messages/create",body:{type:"text",receiver:{type:o.type,receiver_id:o.id},content:{text:{content:n,type:"markdown"}}}})).data?.message_id??""}}var xn={id:x,meta:{...xr,aliases:[...xr.aliases]},capabilities:{chatTypes:["direct","group"],media:!0,threads:!0,nativeCommands:!1,blockStreaming:!0},reload:{configPrefixes:[`channels.${x}`,`channels.${vt}`]},configSchema:Hn(qt),messaging:{normalizeTarget:e=>e.trim(),targetResolver:{hint:"WPS target: user_id or chat_id (obfuscated string, case-sensitive)",looksLikeId:e=>e.trim().length>0}},config:{listAccountIds:e=>{let t=yn(e),n=Object.keys(ue(t));return n.length>0?n:[pe]},resolveAccount:e=>{let t=yn(e);return no(t,z(t))},defaultAccountId:e=>{let t=yn(e);return z(t)},setAccountEnabled:({cfg:e,enabled:t})=>({...e,channels:{...e.channels,[x]:{...Tt(e),accounts:{...ue(e),[z(e)]:{...Y(e,z(e))??{},enabled:t}}}}}),deleteAccount:({cfg:e})=>{let t={...e},n={...t.channels},r=Tt(e);if(r){let i=z(e),o={...ue(e)};delete o[i],n[x]={...r,accounts:o}}else delete n[x],delete n[vt];return t.channels=Object.keys(n).length>0?n:void 0,t},isConfigured:(e,t)=>!!Q(Y(t,e.accountId)),describeAccount:e=>({accountId:e.accountId,enabled:e.enabled,configured:e.configured}),resolveAllowFrom:({cfg:e})=>{let t=e;return Y(t,z(t))?.allowFrom??[]},formatAllowFrom:({allowFrom:e})=>e.map(t=>wn(String(t)))},security:{resolveDmPolicy:({cfg:e})=>{let t=e,n=z(t),r=Y(t,n);return{policy:r?.dmPolicy??"pairing",allowFrom:r?.allowFrom??[],policyPath:`channels.${x}.accounts.${n}.dmPolicy`,allowFromPath:`channels.${x}.accounts.${n}.allowFrom`,approveHint:Jn(x),normalizeEntry:wn}},collectWarnings:({cfg:e})=>{let t=[],n=ue(e);for(let[r,i]of Object.entries(n))i.dmPolicy==="open"&&t.push(`- WPS account '${r}' DMs are open to anyone. Set channels.${x}.accounts.${r}.dmPolicy="pairing" or "allowlist" for security.`),(i.groupPolicy??"allowlist")==="open"&&t.push(`- WPS account '${r}' groups: groupPolicy="open" allows any group to trigger. Set channels.${x}.accounts.${r}.groupPolicy="allowlist".`);return t}},pairing:{idLabel:"wpsUserId",normalizeAllowEntry:wn,notifyApproval:async({cfg:e,id:t})=>{let n=e,r=Y(n,z(n)),i=Q(r);if(!i)throw new Error("WPS credentials not configured");await bn(i,`user:${t}`,"Your pairing request has been approved. You can now chat with this bot.")}},groups:{resolveRequireMention:({cfg:e,groupId:t})=>{let n=e,r=Y(n,z(n));return!r?.groups||!t?!0:(r.groups[t]??r.groups["*"])?.requireMention??!0},resolveToolPolicy:()=>{}},outbound:{deliveryMode:"direct",textChunkLimit:5e3,chunker:(e,t)=>eo().channel.text.chunkMarkdownText(e,t),chunkerMode:"markdown",resolveTarget:({to:e,allowFrom:t})=>{let n=e?.trim()??"";if(n&&ro(n))return{ok:!0,to:n};let r=t?.[0];return r?{ok:!0,to:String(r).trim()}:{ok:!1,error:new Error("WPS target is required (user_id or chat_id)")}},sendText:async({cfg:e,to:t,text:n})=>{let r=e,i=Y(r,z(r)),o=Q(i);if(!o)throw new Error("WPS credentials not configured");return bn(o,t,n)},sendMedia:async({cfg:e,to:t,mediaUrl:n,mimeType:r})=>{let i=e,o=Y(i,z(i)),s=Q(o);if(!s)throw new Error("WPS credentials not configured");let a=E(s),d=$(s.baseUrl,a),l=kr(t),c=(n??"").trim();if(!c)throw new Error("WPS sendMedia requires mediaUrl");let p,u,m=(r??"").trim()||"application/octet-stream",f=null;if(_n(c)){let _=await Qi(c),y=It.basename(c)||"attachment";if(p=/^[0-9a-f]{8}_/.test(y)?y.substring(9):y,!(r??"").trim()){let I=It.extname(p).toLowerCase();m={".png":"image/png",".jpg":"image/jpeg",".jpeg":"image/jpeg",".gif":"image/gif",".webp":"image/webp",".bmp":"image/bmp"}[I]??"application/octet-stream"}m.startsWith("image/")&&(f=Gn(_),console.log(`[${x}] sendMedia: parsed dimensions ${f?`${f.width}x${f.height}`:"(null)"} for ${p}`)),u=_.byteLength,c=(await hn(d,p,m,_)).storage_key}let h=m.startsWith("image/")?{type:"image",receiver:{type:l.type,receiver_id:l.id},content:{image:{storage_key:c,...m.startsWith("image/")?{type:m}:{},...p?{name:p}:{},...u!==void 0?{size:u}:{},...f?{width:f.width,height:f.height}:{}}}}:{type:"file",receiver:{type:l.type,receiver_id:l.id},content:{file:{type:"local",local:{storage_key:c,...p?{name:p}:{},...u!==void 0?{size:u}:{}}}}};return d.request({method:"POST",path:"/v7/messages/create",body:h})}},status:{defaultRuntime:{accountId:pe,running:!1,lastStartAt:null,lastStopAt:null,lastError:null},collectStatusIssues:e=>e.flatMap(t=>{let n=[];return t.enabled&&!t.configured&&n.push({channel:x,accountId:t.accountId,kind:"config",message:"WPS credentials not configured (appId and appSecret required).",fix:`Set channels.${x}.accounts.${t.accountId}.appId and channels.${x}.accounts.${t.accountId}.appSecret.`}),n}),buildChannelSummary:({snapshot:e})=>({configured:e.configured??!1,running:e.running??!1,lastStartAt:e.lastStartAt??null,lastStopAt:e.lastStopAt??null,lastError:e.lastError??null,probe:e.probe,lastProbeAt:e.lastProbeAt??null}),probeAccount:async({account:e})=>{let t=Q(e.config);if(!t)return{ok:!1,error:"Not configured"};try{return{ok:!0,token:(await E(t).getToken()).substring(0,8)+"..."}}catch(n){return{ok:!1,error:String(n)}}},buildAccountSnapshot:({account:e,runtime:t,probe:n})=>({accountId:e.accountId,enabled:e.enabled,configured:e.configured,running:t?.running??!1,lastStartAt:t?.lastStartAt??null,lastStopAt:t?.lastStopAt??null,lastError:t?.lastError??null,lastInboundAt:t?.lastInboundAt??null,lastOutboundAt:t?.lastOutboundAt??null,dmPolicy:e.config.dmPolicy??"pairing",probe:n})},gateway:{startAccount:async e=>{let t=Y(e.cfg,e.accountId);if(!t?.enabled){e.log?.info?.(`[${e.accountId}] WPS provider disabled`);return}let n=Q(t);if(!n){e.log?.error?.(`[${e.accountId}] WPS credentials not configured`);return}let r=async()=>{},i=a=>{fn({cfg:e.cfg,accountId:e.accountId,channelRuntime:e.channelRuntime??void 0,wpsCfg:t,creds:n,eventPayload:a,log:e.log}).catch(d=>e.log?.error?.("WPS inbound handler error:",d))},o=!1;if(t.sdk?.enabled)try{let{Client:a,Dispatcher:d,LogLevel:l}=await import("open-event-sdk"),p={debug:l.Debug,warn:l.Warn,error:l.Error}[t.sdk.logLevel??"info"]??l.Info,u=new d().onV7AppChatMessageCreate(async h=>{try{let _=h.parsedData;e.log?.info?.(`[WPS SDK][${e.accountId}/${n.clientId}] message: chat_id=${_.chat.id}, message_id=${_.message.id}`);let y=Zn(_);i(y)}catch(_){e.log?.error?.("WPS SDK message handler error:",_)}}).onV7AppGroupChatMemberRobotCreate(async h=>{let _=h.parsedData;if(e.log?.info?.(`[WPS SDK] robot joined group: chat_id=${_.chat_id}`),t.robotJoinGroupMessage!==void 0){let y=t.robotJoinGroupMessage||"\u4F60\u597D\uFF01\u6211\u662F AI \u52A9\u624B\uFF0C\u53EF\u4EE5\u5E2E\u52A9\u5927\u5BB6\u5904\u7406\u5404\u79CD\u95EE\u9898\u3002";try{let S=E(n);await $(n.baseUrl,S).request({method:"POST",path:"/v7/messages/create",body:{type:"text",receiver:{type:"chat",receiver_id:_.chat_id},content:{text:{content:y,type:"markdown"}}}})}catch(S){e.log?.error?.("WPS welcome message failed:",S)}}}).onV7AppGroupChatMemberRobotDelete(async h=>{e.log?.info?.(`[WPS SDK] robot left group: chat_id=${h.parsedData.chat_id}`)}).registerFallbackFunc(h=>{let _=null;if(h.parsedData&&typeof h.parsedData=="object")_=h.parsedData;else if(typeof h.data=="string"&&h.data)try{_=JSON.parse(h.data)}catch{}let y=_?Object.keys(_).join(","):"N/A";if(e.log?.info?.(`[WPS SDK] unhandled event: ${h.eventCode}, keys=${y}`),_&&e.log?.info?.(`[WPS SDK] event payload: ${JSON.stringify(_).slice(0,500)}`),_){let S=typeof _.code=="string"?_.code:typeof _.authorization_code=="string"?_.authorization_code:void 0,I=typeof _.state=="string"?_.state:void 0;if(S){let v=typeof _.user_id=="string"?_.user_id:void 0;e.log?.info?.(`[WPS SDK] Auth code detected: eventCode=${h.eventCode}, code=${S.slice(0,8)}..., state=${I??"(none)"}, userId=${v??"(none)"}`),(async()=>{try{let{handleAuthEvent:A}=await Promise.resolve().then(()=>(St(),pn));await A({code:S,state:I??"",creds:n,wpsCfg:t,log:e.log,userId:v})}catch(A){e.log?.error?.(`[WPS SDK] Auth event handling failed: ${String(A)}`)}})()}}}),m=new a(tr({appId:n.clientId,appSecret:n.clientSecret,dispatcher:u,logLevel:p,endpoint:t.sdk.endpoint},t.sdk));m.start().catch(h=>{e.log?.error?.("WPS SDK client.run ended:",h)});let f=t.sdk.connectTimeoutMs??2e4,g=Date.now()+f;for(;Date.now()<g&&!m.isConnected();)await new Promise(h=>setTimeout(h,150));if(m.isConnected()){o=!0,e.log?.info?.("[WPS SDK] long connection established");let h=()=>m.stop();e.abortSignal.addEventListener("abort",h),r=async()=>{e.abortSignal.removeEventListener("abort",h),m.stop()}}else m.stop(),e.log?.warn?.(`[WPS SDK] connect timeout (${f}ms), falling back to Webhook`)}catch(a){e.log?.warn?.(`[WPS SDK] init failed: ${String(a)}, falling back to Webhook`)}if(!o){let a=await import("express"),d=a.default();d.use(a.json());let l=t.webhook?.port??3e3,c=t.webhook?.path??"/wps/webhook",p=t.enableEncryption!==!1;d.post(c,(m,f)=>{let g=er(m.body,{appId:n.clientId,appSecret:n.clientSecret},p,e.log);if("challenge"in g){f.status(200).json({challenge:g.challenge});return}if(!g.ok){let h=g.status??200;h===200?f.status(200).json({code:0,msg:"ok"}):f.status(h).json({code:-1,msg:g.error});return}f.status(200).json({code:0,msg:"ok"}),i(g.payload)});let u=d.listen(l,()=>{e.log?.info?.(`[${e.accountId}] WPS webhook listening on :${l}${c}`)});r=async()=>{u&&(u.close(),u=null)}}let s=o?"sdk":"webhook";e.setStatus({accountId:e.accountId,running:!0,lastStartAt:Date.now(),mode:s}),e.log?.info?.(`[${e.accountId}] WPS channel started (mode=${s})`);try{let a=E(n),d=$(n.baseUrl,a);an(d,e.log,t,n),Wt({appId:n.clientId,appSecret:n.clientSecret,baseUrl:n.baseUrl}),e.log?.info?.(`[${e.accountId}] WPS client initialized for OAPI tools`);try{let c=((await d.request({method:"GET",path:`/v7/developer/apps/${encodeURIComponent(n.clientId)}`})).data?.scopes??[]).filter(p=>p.auth_types?.includes("delegated")).map(p=>({name:p.name??"",description:p.description??""})).filter(p=>p.name);bt(c),e.log?.info?.(`[${e.accountId}] Delegated scopes: ${c.map(p=>p.name).join(", ")||"(none)"}`)}catch(l){bt([]);let c=String(l);c.includes("invalid_scope")?e.log?.info?.(`[${e.accountId}] Delegated scopes unavailable (invalid_scope). OAuth \u6388\u6743\u5361\u7247\u80FD\u529B\u4E0D\u53EF\u7528\uFF0C\u4F46\u4E0D\u5F71\u54CD\u666E\u901A\u6D88\u606F\u6536\u53D1\u3002`):e.log?.warn?.(`[${e.accountId}] Failed to fetch delegated scopes: ${c}`)}}catch(a){e.log?.error?.(`[${e.accountId}] WPS client init failed:`,a)}return Xn(e.abortSignal,r)}},onboarding:{channel:x,getStatus:async({cfg:e})=>{let t=e,n=Y(t,z(t)),r=!!Q(n);return{channel:x,configured:r,statusLines:[`WPS: ${r?"configured":"needs appId and appSecret"}`],selectionHint:r?"configured":"needs credentials",quickstartScore:r?2:1}},configure:async({cfg:e})=>({cfg:e})},agentPrompt:{messageToolHints:e=>["- WPS targeting: omit `target` to reply in the current conversation (auto-inferred by the framework). To send to a **different** conversation, use `message(action=send, to=chat:<chat_id>, message=...)`.","- To find a chat by name, use `wps_chat_find_by_name` first, then use the returned chat_id as `to=chat:<chat_id>`.","- WPS supports `send` action for proactive messaging. The `to` parameter is required for `action=send` (e.g. `user:<user_id>` or `chat:<chat_id>`)."]},actions:{describeMessageTool:()=>({actions:["send"]}),handleAction:async e=>{if(e.action!=="send")throw new Error(`WPS does not support action: ${e.action}`);let t=e.params.to??e.params.target??e.params.receiver_id,n=e.params.message??e.params.text??e.params.content,r=e.params.media,i=e.cfg,o=Y(i,z(i)),s=Q(o);if(!s)throw new Error("WPS credentials not configured");let a=t&&typeof t=="string"&&t.trim()?t.trim():"";if(r&&typeof r=="string"&&r.trim()){let l=r.trim();if(_n(l)){if(!a)throw new Error("WPS send with media requires 'to' (e.g. 'user:<id>' or 'chat:<id>')");return await xn.outbound.sendMedia({cfg:e.cfg,to:a,mediaUrl:l,mimeType:void 0}),{text:`Media sent (${It.basename(l)||"attachment"})`}}}if(!a)throw new Error("WPS send requires 'to' (e.g. 'user:<id>' or 'chat:<id>')");if(!n||typeof n!="string"||!n.trim())throw new Error("WPS send requires 'message' or 'text'");return{text:`Message sent (id: ${(await bn(s,a,n.trim())).messageId})`}}}};Ae();function Pt(e){return e.data??null}function Et(e){return{error:e instanceof Error?e.message:String(e)}}function ne(e,t){let n=e[t];if(typeof n!="string"||!n.trim())throw new Error(`${t} is required and must be a non-empty string`);return n.trim()}function Sn(e,t){let n=e[t];if(n!=null){if(typeof n=="number"&&Number.isFinite(n))return n;if(typeof n=="string"&&n.trim()!==""){let r=Number(n);if(Number.isFinite(r))return r}throw new Error(`${t} must be a finite number`)}}function io(e,t){let n=e[t];if(n!=null){if(typeof n!="string")throw new Error(`${t} must be a string`);return n}}function Ir(e){try{return JSON.parse(e)}catch{throw new Error("content must be valid JSON matching the WPS message content structure")}}function oo(e,t){if(e==="text"){try{let r=JSON.parse(t);if(r&&typeof r=="object"&&"text"in r)return{type:"text",content:r}}catch{}return{type:"text",content:{text:{content:t,type:"markdown"}}}}let n=Ir(t);if(typeof n!="object"||n===null)throw new Error(`content for ${e} must be a JSON object (message content subtree)`);return e==="rich_text"?{type:"rich_text",content:n}:{type:"image",content:n}}function kn(e,t){t({name:"wps_message_send",description:`Send a message to any WPS user or chat via OpenAPI. IMPORTANT: When the user asks to send a message to someone or to a chat/group, use THIS tool. If the user provides a chat name instead of an ID, call wps_chat_find_by_name first to resolve the chat_id, then call this tool with receiver_type='chat'. receiver_type: 'user' (for P2P/DM by user_id) or 'chat' (for group/chat by chat_id). receiver_id MUST be the real WPS chat id or user id (numeric/string id from the WPS API). For replies in the current conversation, read inbound RawBody JSON \`chatId\` and \`SenderId\`: use receiver_type='chat' + receiver_id=chatId when chatId is present, else receiver_type='user' + receiver_id=SenderId. NEVER use SessionKey segments after ':bot:' (often looks like AK\u2026) as receiver_id \u2014 that is a bot/app id, not a chat id, and causes invalid chatId / deMixValue errors. Text: msg_type='text', content='{"text":{"content":"hello","type":"markdown"}}'. Image/file: first call wps_media_upload_base64 for storage_key, then msg_type='image' or 'file' with the matching content JSON. Cloud file forwarding: msg_type='file', content='{"file":{"type":"cloud","cloud":{"id":"...","link_id":"...","link_url":"..."}}}' \u2014 use the original cloud structure from the inbound message.`,parameters:{type:"object",properties:{receiver_type:{type:"string",enum:["user","chat"],description:"Target kind: `user` opens or uses p2p with that user id; `chat` sends to a chat id."},receiver_id:{type:"string",description:"WPS user id or chat id from the API (not SessionKey `:bot:` segment). For the active thread, prefer RawBody `chatId` or user id."},msg_type:{type:"string",enum:["text","rich_text","image","file"],description:"WPS message type field sent as `type` in the API body."},content:{type:"string",description:"JSON string for the WPS message `content` object (structure depends on msg_type)."},mentions:{type:"array",description:"Optional mention list for group messages.",items:{}}},required:["receiver_type","receiver_id","msg_type","content"]},async execute(n,r){try{let i=ne(r,"receiver_type");if(i!=="user"&&i!=="chat")throw new Error("receiver_type must be 'user' or 'chat'");let o=ne(r,"receiver_id"),s=ne(r,"msg_type");if(!["text","rich_text","image","file"].includes(s))throw new Error("msg_type must be one of: text, rich_text, image, file");let a=ne(r,"content");if(a.length>5e3)throw new Error("content JSON string exceeds 5000 characters");let d=Ir(a);if(typeof d!="object"||d===null)throw new Error("parsed content must be a JSON object");let l={type:s,receiver:{type:i,receiver_id:o},content:d},c=r.mentions;if(c!==void 0){if(!Array.isArray(c))throw new Error("mentions must be an array when provided");l.mentions=c}let p=await e.request({method:"POST",path:"/v7/messages/create",body:l});return Pt(p)}catch(i){return Et(i)}}}),t({name:"wps_message_reply",description:"Reply to an existing message in a chat (POST /v7/chats/{chat_id}/messages/{message_id}/reply). Use this to reply in-thread to a specific message. For sending NEW messages (not replies), use wps_message_send instead. Supports msg_type text, rich_text, or image. For text, content can be plain text or JSON content object.",parameters:{type:"object",properties:{chat_id:{type:"string",description:"Chat session id."},message_id:{type:"string",description:"Message id to reply to."},msg_type:{type:"string",enum:["text","rich_text","image"],description:"Reply payload type."},content:{type:"string",description:"For text: plain string or JSON string of `content`. For rich_text/image: JSON string of the `content` subtree."}},required:["chat_id","message_id","msg_type","content"]},async execute(n,r){try{let i=encodeURIComponent(ne(r,"chat_id")),o=encodeURIComponent(ne(r,"message_id")),s=ne(r,"msg_type");if(s!=="text"&&s!=="rich_text"&&s!=="image")throw new Error("msg_type must be text, rich_text, or image");let a=ne(r,"content"),d=oo(s,a),l=await e.request({method:"POST",path:`/v7/chats/${i}/messages/${o}/reply`,body:d});return Pt(l)}catch(i){return Et(i)}}}),t({name:"wps_message_list",description:"List messages in a chat (GET /v7/chats/{chat_id}/messages). page_size defaults to 50. `start_time` and `end_time` are Unix timestamps in **seconds** (converted to milliseconds for the API). Returns paginated message list; use page_token for next pages.",parameters:{type:"object",properties:{chat_id:{type:"string",description:"Chat session id."},start_time:{type:"number",description:"Optional inclusive range start (Unix seconds); sent as start_time query in ms."},end_time:{type:"number",description:"Optional inclusive range end (Unix seconds); sent as end_time query in ms."},page_size:{type:"number",description:"Page size (default 50, max 100)."},page_token:{type:"string",description:"Pagination cursor from a previous response."}},required:["chat_id"]},async execute(n,r){try{let i=encodeURIComponent(ne(r,"chat_id")),o=Sn(r,"start_time"),s=Sn(r,"end_time"),a=Sn(r,"page_size")??50,d=io(r,"page_token"),l={page_size:a};d!==void 0&&(l.page_token=d),o!==void 0&&(l.start_time=Math.trunc(o*1e3)),s!==void 0&&(l.end_time=Math.trunc(s*1e3));let c=await e.request({method:"GET",path:`/v7/chats/${i}/messages`,query:l});return Pt(c)}catch(i){return Et(i)}}}),t({name:"wps_message_get",description:"Fetch a single message by id within a chat (GET /v7/chats/{chat_id}/messages/{message_id}).",parameters:{type:"object",properties:{chat_id:{type:"string",description:"Chat session id."},message_id:{type:"string",description:"Message id."}},required:["chat_id","message_id"]},async execute(n,r){try{let i=encodeURIComponent(ne(r,"chat_id")),o=encodeURIComponent(ne(r,"message_id")),s=await e.request({method:"GET",path:`/v7/chats/${i}/messages/${o}`});return Pt(s)}catch(i){return Et(i)}}})}function vr(e){return e.data??null}function Tr(e){return{error:e instanceof Error?e.message:String(e)}}function so(e,t){let n=e[t];if(typeof n!="string"||!n.trim())throw new Error(`${t} is required and must be a non-empty string`);return n.trim()}function ao(e,t){let n=e[t];if(n!=null){if(typeof n=="number"&&Number.isFinite(n))return n;if(typeof n=="string"&&n.trim()!==""){let r=Number(n);if(Number.isFinite(r))return r}throw new Error(`${t} must be a finite number`)}}function co(e,t){let n=e[t];if(n!=null){if(typeof n!="string")throw new Error(`${t} must be a string`);return n}}var lo=["active"],po=["user_name","email","phone"],uo=["company_user"],fo=50;function In(e,t){t({name:"wps_user_get",description:"Get the current authenticated bot/app user profile (GET /v7/users/current). Returns fields such as id, user_name, avatar, and company_id when exposed by the API.",parameters:{type:"object",properties:{},required:[]},async execute(n,r){try{let i=await e.request({method:"GET",path:"/v7/users/current"});return vr(i)}catch(i){return Tr(i)}}}),t({name:"wps_user_search",description:"Search company users by keyword (GET /v7/users/search). Always applies status=active, search_field=user_name+email+phone, and search_source=company_user. page_size defaults to 50 (WPS API requires this field). Returns a paginated user list; use page_token for next pages. If no results found, suggest the user refine the keyword or try email/phone.",parameters:{type:"object",properties:{keyword:{type:"string",description:"Search keyword (name, email fragment, phone, etc.)."},page_size:{type:"number",description:"Page size (default 50, max 100)."},page_token:{type:"string",description:"Pagination token from a prior call."}},required:["keyword"]},async execute(n,r){try{let i=so(r,"keyword"),o=ao(r,"page_size")??fo,s=co(r,"page_token"),a={keyword:i,status:[...lo],search_field:[...po],search_source:[...uo],page_size:o};s!==void 0&&(a.page_token=s);let d=await e.request({method:"GET",path:"/v7/users/search",query:a});return vr(d)}catch(i){return Tr(i)}}})}function Qe(e){return e.data??null}function Ue(e){return{error:e instanceof Error?e.message:String(e)}}function Ze(e,t){let n=e[t];if(typeof n!="string"||!n.trim())throw new Error(`${t} is required and must be a non-empty string`);return n.trim()}function Pr(e,t){let n=e[t];if(n!=null){if(typeof n=="number"&&Number.isFinite(n))return n;if(typeof n=="string"&&n.trim()!==""){let r=Number(n);if(Number.isFinite(r))return r}throw new Error(`${t} must be a finite number`)}}function vn(e,t){let n=e[t];if(n!=null){if(typeof n!="string")throw new Error(`${t} must be a string`);return n}}var Er=50;function mo(e,t){let n=e[t];if(!Array.isArray(n)||n.length===0)throw new Error(`${t} must be a non-empty array of user id strings`);let r=[];for(let i=0;i<n.length;i++){let o=n[i];if(typeof o!="string"||!o.trim())throw new Error(`${t}[${i}] must be a non-empty string`);r.push(o.trim())}return r}function Tn(e,t="user"){return{id:e,type:t}}var $t=null;async function _o(e){if($t)return $t;let n=(await e.request({method:"GET",path:"/v7/users/current"})).data;if(!n||typeof n.id!="string"||!n.id.trim())throw new Error("Cannot retrieve current operator identity from /v7/users/current. Ensure the app has kso.user_base.read permission.");return $t={id:n.id.trim(),type:"user"},$t}function Pn(e,t){t({name:"wps_chat_create",description:"Create a p2p or group chat (POST /v7/chats/create). For P2P: provide exactly 2 user ids in member_ids (no auto-injection). For group: provide other member user ids; the current operator is auto-included and becomes owner. Requires kso.chat.readwrite permission.",parameters:{type:"object",properties:{type:{type:"string",enum:["p2p","group"],description:"Chat kind: p2p or group."},member_ids:{type:"array",items:{type:"string"},description:"For P2P: exactly 2 user ids. For group: other member ids (operator auto-included)."},name:{type:"string",description:"Group chat display name (only for group type)."}},required:["type","member_ids"]},async execute(n,r){try{let i=Ze(r,"type");if(i!=="p2p"&&i!=="group")throw new Error("type must be 'p2p' or 'group'");let o=mo(r,"member_ids"),s,a={type:i};if(i==="group"){let l=await _o(e),c=new Set;s=[],c.add(l.id),s.push(Tn(l.id));for(let u of o)c.has(u)||(s.push(Tn(u)),c.add(u));a.owner_id=l.id;let p=vn(r,"name");p!==void 0&&p!==""&&(a.name=p)}else{let l=[...new Set(o)];if(l.length!==2)throw new Error(`P2P chat requires exactly 2 distinct user ids in member_ids. Got ${l.length} after dedup.`);s=l.map(c=>Tn(c))}a.account_id_list=s;let d=await e.request({method:"POST",path:"/v7/chats/create",body:a});return Qe(d)}catch(i){return Ue(i)}}}),t({name:"wps_chat_list",description:"List chats for the current context (GET /v7/chats). page_size defaults to 50. Returns paginated chat list; use page_token for next pages.",parameters:{type:"object",properties:{page_size:{type:"number",description:"Page size (default 50, max 100)."},page_token:{type:"string",description:"Pagination token from a prior call."}},required:[]},async execute(n,r){try{let i=Pr(r,"page_size")??Er,o=vn(r,"page_token"),s={page_size:i};o!==void 0&&(s.page_token=o);let a=await e.request({method:"GET",path:"/v7/chats",query:s});return Qe(a)}catch(i){return Ue(i)}}}),t({name:"wps_chat_get",description:"Get metadata for a single chat (GET /v7/chats/{chat_id}).",parameters:{type:"object",properties:{chat_id:{type:"string",description:"Chat session id."}},required:["chat_id"]},async execute(n,r){try{let i=encodeURIComponent(Ze(r,"chat_id")),o=await e.request({method:"GET",path:`/v7/chats/${i}`});return Qe(o)}catch(i){return Ue(i)}}}),t({name:"wps_chat_members",description:"List members of a chat (GET /v7/chats/{chat_id}/members). page_size defaults to 50. Returns paginated member list; use page_token for next pages.",parameters:{type:"object",properties:{chat_id:{type:"string",description:"Chat session id."},page_size:{type:"number",description:"Page size (default 50, max 100)."},page_token:{type:"string",description:"Pagination token from a prior call."}},required:["chat_id"]},async execute(n,r){try{let i=encodeURIComponent(Ze(r,"chat_id")),o=Pr(r,"page_size")??Er,s=vn(r,"page_token"),a={page_size:o};s!==void 0&&(a.page_token=s);let d=await e.request({method:"GET",path:`/v7/chats/${i}/members`,query:a});return Qe(d)}catch(i){return Ue(i)}}}),t({name:"wps_chat_is_member",description:"Check whether the current operator is a member of the chat (GET /v7/chats/{chat_id}/members/is_in_chat).",parameters:{type:"object",properties:{chat_id:{type:"string",description:"Chat session id."}},required:["chat_id"]},async execute(n,r){try{let i=encodeURIComponent(Ze(r,"chat_id")),o=await e.request({method:"GET",path:`/v7/chats/${i}/members/is_in_chat`});return Qe(o)}catch(i){return Ue(i)}}}),t({name:"wps_chat_find_by_name",description:"Find a WPS chat/group by name. IMPORTANT: When the user says 'send message to <group name>' or '\u7ED9 <\u7FA4\u540D> \u53D1\u6D88\u606F', ALWAYS call this tool first to resolve the chat_id, then use wps_message_send with receiver_type='chat' and the resolved chat_id. Returns matching chats with owner info for disambiguation. If multiple matches, present the list to the user for selection.",parameters:{type:"object",properties:{keyword:{type:"string",description:"Chat name keyword to search for."}},required:["keyword"]},async execute(n,r){try{let i=Ze(r,"keyword").toLowerCase(),o=[],s,a=!1;for(let l=0;l<10;l++){let c={page_size:100};s&&(c.page_token=s);let p=await e.request({method:"GET",path:"/v7/chats",query:c});for(let u of p.data?.items??[])u.chat_id&&u.name?.toLowerCase().includes(i)&&o.push({chat_id:u.chat_id,name:u.name,owner_id:u.owner_id});if(!p.data?.has_more)break;if(s=p.data?.page_token,!s){a=!0;break}}let d={};return a&&(d.warning="Results may be incomplete: pagination was truncated due to missing page_token."),o.length===0?{...d,found:!1,message:`No chats found matching "${i}"`}:o.length===1?{...d,found:!0,match:o[0]}:{...d,found:!0,multiple:!0,matches:o,hint:"Multiple matches found. Present the list to the user with chat name and owner info for selection."}}catch(i){return Ue(i)}}})}Ge();Ae();_t();St();async function De(e){let t=Lt(e.wpsUserId);if(t){let o=wt(),s=Bt(o.baseUrl,t);return await e.run(s)}let n=dn(),r=wt(),i=we();try{let o=be().map(a=>a.name).join(",");i?.info?.(`[${e.logTag}] Sending auth card: receiverId=${e.wpsUserId}, delegatedScopes=[${o}]`);let s=await ln({creds:r,wpsCfg:n,wpsUserId:e.wpsUserId,receiverType:"user",receiverId:e.wpsUserId,originalMessage:e.authCardOriginalMessage});i?.info?.(`[${e.logTag}] Auth card result: ${JSON.stringify(s)}`)}catch(o){i?.error?.(`[${e.logTag}] Failed to send auth card: ${String(o)}`)}return{needsAuth:!0,message:e.needsAuthMessage}}var $r=31*24*60*60*1e3,ho=100;function le(e){return{error:e instanceof Error?e.message:String(e)}}function L(e,t){let n=e[t];if(typeof n!="string"||!n.trim())throw new Error(`${t} is required and must be a non-empty string`);return n.trim()}function T(e,t){let n=e[t];if(n!=null){if(typeof n!="string")throw new Error(`${t} must be a string`);return n}}function En(e,t){let n=e[t];if(n!=null){if(typeof n=="number"&&Number.isFinite(n))return n;if(typeof n=="string"&&n.trim()!==""){let r=Number(n);if(Number.isFinite(r))return r}throw new Error(`${t} must be a finite number`)}}function go(e,t){let n=e[t];if(n!=null){if(typeof n=="boolean")return n;if(n==="true"||n==="false")return n==="true";throw new Error(`${t} must be a boolean`)}}function yo(e,t){let n=e[t];if(n==null)throw new Error(`${t} is required and must be a finite number`);if(typeof n=="number"&&Number.isFinite(n))return n;if(typeof n=="string"&&n.trim()!==""){let r=Number(n);if(Number.isFinite(r))return r}throw new Error(`${t} must be a finite number`)}function At(e,t){let n=new Date(t.trim());if(Number.isNaN(n.getTime()))throw new Error(`${e} must be a valid RFC3339 / ISO 8601 datetime string`);return n}function je(e){return e.toISOString()}function $n(e){let t=e.now??new Date,n,r,i=!!e.startRfc?.trim(),o=!!e.endRfc?.trim();if(i&&o?(n=At("start_time",e.startRfc),r=At("end_time",e.endRfc)):i?(n=At("start_time",e.startRfc),r=new Date(n.getTime()+14*86400*1e3)):o?(r=At("end_time",e.endRfc),n=new Date(r.getTime()-14*86400*1e3)):(n=new Date(t.getTime()-86400*1e3),r=new Date(t.getTime()+14*86400*1e3)),r.getTime()<n.getTime())throw new Error("end_time must be >= start_time (RFC3339 range)");return r.getTime()-n.getTime()>$r&&(r=new Date(n.getTime()+$r)),{start:n,end:r}}function wo(e){let{start:t,end:n}=$n({startRfc:e.startRfc,endRfc:e.endRfc,now:e.now}),r={start_time:je(t),end_time:je(n)},i=e.pageSize??30;return r.page_size=Math.max(1,Math.min(500,Math.trunc(i))),e.pageToken!==void 0&&e.pageToken.trim()!==""&&(r.page_token=e.pageToken.trim()),r}function bo(e){let{start:t,end:n}=$n({startRfc:e.startRfc,endRfc:e.endRfc,now:e.now});return{start_time:je(t),end_time:je(n)}}function xo(e){let t={},n=e.pageSize??30;if(t.page_size=Math.max(1,Math.min(500,Math.trunc(n))),e.pageToken!==void 0&&e.pageToken.trim()!==""&&(t.page_token=e.pageToken.trim()),e.withCancelled===!0&&(t.with_cancelled=!0),e.syncToken!==void 0&&e.syncToken.trim()!==""&&(t.sync_token=e.syncToken.trim()),e.anchorTime!==void 0&&e.anchorTime.trim()!==""&&(t.anchor_time=e.anchorTime.trim()),t.sync_token)return t;let{start:r,end:i}=$n({startRfc:e.startRfc,endRfc:e.endRfc,now:e.now});return t.start_time=je(r),t.end_time=je(i),t}function So(e){let t=new Date(e.trim());if(Number.isNaN(t.getTime()))throw new Error("start_time must be a valid ISO 8601 datetime");return t.setTime(t.getTime()+60*60*1e3),t.toISOString()}function Ct(e,t){return`/v7/calendars/${encodeURIComponent(e)}/events/${encodeURIComponent(t)}`}function ko(e,t){return`${Ct(e,t)}/respond`}function Io(e,t){return`${Ct(e,t)}/attendees`}function vo(e){let t=e.pageSize??30,r={page_size:Math.max(1,Math.min(ho,Math.trunc(t)))};return e.pageToken!==void 0&&e.pageToken.trim()!==""&&(r.page_token=e.pageToken.trim()),r}function Ar(e){let t=T(e,"x_kso_id_type");if(t===void 0||t.trim()==="")return;let n=t.trim();if(n!=="internal"&&n!=="external")throw new Error("x_kso_id_type must be internal or external when provided");return{"X-Kso-Id-Type":n}}async function xe(e,t,n){try{return await De({wpsUserId:e,authCardOriginalMessage:t,needsAuthMessage:"\u9700\u8981\u7528\u6237\u6388\u6743\u624D\u80FD\u64CD\u4F5C\u65E5\u7A0B\u3002\u5DF2\u53D1\u9001\u6388\u6743\u5361\u7247\uFF0C\u8BF7\u7528\u6237\u70B9\u51FB\u300C\u524D\u5F80\u6388\u6743\u300D\u5B8C\u6210\u6388\u6743\u540E\u91CD\u8BD5\u3002",logTag:"calendar",run:n})}catch(r){return le(r)}}function An(e,t){t({name:"wps_calendar_create",description:"Create a calendar event for the current user via WPS OpenAPI. Requires user OAuth authorization. If the user has not authorized, an authorization card will be sent automatically. IMPORTANT: Use the SenderId from the current conversation context as wps_user_id. Do NOT call wps_user_search or wps_user_get to look up the user. If end_time is omitted, it defaults to start_time + 1 hour (computed as UTC ISO).",parameters:{type:"object",properties:{summary:{type:"string",description:"Event title."},start_time:{type:"string",description:"Start time in ISO 8601 with timezone (e.g. '2026-04-22T14:00:00+08:00')."},end_time:{type:"string",description:"End time in ISO 8601 with timezone. Omit to default to start_time + 1 hour."},description:{type:"string",description:"Optional event description."},location:{type:"string",description:"Optional event location."},wps_user_id:{type:"string",description:"WPS user ID. Use SenderId from the conversation context. Do NOT call wps_user_search or wps_user_get for this."}},required:["summary","start_time"]},async execute(n,r){try{let i=L(r,"summary"),o=L(r,"start_time"),s=T(r,"end_time"),a=s&&s.trim()!==""?s.trim():So(o),d=T(r,"description"),l=T(r,"location"),c=T(r,"wps_user_id")??"";return c?await xe(c,i,async p=>{let u={summary:i,start_time:{datetime:o},end_time:{datetime:a}};d&&(u.description=d),l&&(u.locations=[{name:l}]);let m=await p.request({method:"POST",path:"/v7/calendars/primary/events/create",body:u});return m.data??m}):le(new Error("wps_user_id is required. Use the SenderId from the conversation context."))}catch(i){return le(i)}}}),t({name:"wps_calendar_list_events",description:"List calendar events on the user's primary calendar: GET `/v7/calendars/primary/events` (same as `/v7/calendars/{calendar_id}/events` with calendar_id `primary`). Official doc: https://365.kdocs.cn/3rd/open/documents/app-integration-dev/wps365/server/calendar/calendar-event/get-calendar-event-list Requires user delegated OAuth (same as wps_calendar_create). Use SenderId as wps_user_id. Time range: `start_time` and `end_time` query params are **RFC3339 / ISO8601 strings** (not Unix seconds). If both are omitted, defaults to about last 24 hours through next 14 days, clamped to max 31-day span per API. If `sync_token` is set, incremental sync mode: only sync_token/page_token/page_size/with_cancelled are sent (no automatic time window). Optional: anchor_time (RFC3339), with_cancelled (boolean).",parameters:{type:"object",properties:{wps_user_id:{type:"string",description:"WPS user ID (SenderId). Do NOT call wps_user_search for this."},start_time:{type:"string",description:"Optional range start (RFC3339 / ISO8601). Must be used with end_time for explicit window, or omit both for defaults."},end_time:{type:"string",description:"Optional range end (RFC3339 / ISO8601). API allows 0\u201331 days between start and end; longer ranges are truncated."},page_size:{type:"number",description:"Page size (default 30 per API doc, max 500 client-side cap)."},page_token:{type:"string",description:"Pagination cursor from data.next_page_token."},with_cancelled:{type:"boolean",description:"Include cancelled events (per API)."},sync_token:{type:"string",description:"Incremental sync token from data.next_sync_token; when set, time range is not auto-filled."},anchor_time:{type:"string",description:"Anchor time RFC3339 for incremental sync (per API)."}},required:["wps_user_id"]},async execute(n,r){try{let i=L(r,"wps_user_id"),o=T(r,"start_time"),s=T(r,"end_time"),a=En(r,"page_size"),d=T(r,"page_token"),l=go(r,"with_cancelled"),c=T(r,"sync_token"),p=T(r,"anchor_time");return await xe(i,"\u67E5\u8BE2\u4E3B\u65E5\u5386\u65E5\u7A0B\u5217\u8868",async u=>{let m=xo({startRfc:o,endRfc:s,pageSize:a,pageToken:d,withCancelled:l,syncToken:c,anchorTime:p}),f=await u.request({method:"GET",path:"/v7/calendars/primary/events",query:m});return f.data??f})}catch(i){return le(i)}}}),t({name:"wps_calendar_get_event",description:"Get **one** calendar event by id (official \u67E5\u8BE2\u65E5\u7A0B): GET `/v7/calendars/{calendar_id}/events/{event_id}`. Response `data` is a single event object (summary, recurrence, online_meeting, etc.), not `items[]`. Requires `event_id` from `wps_calendar_list_events` (or equivalent). Same delegated Bearer auth as `wps_calendar_create`. Optional `calendar_id` (default `primary`). Optional header `X-Kso-Id-Type`: pass `x_kso_id_type` as `internal` or `external` per API.",parameters:{type:"object",properties:{wps_user_id:{type:"string",description:"WPS user ID (SenderId). Do NOT call wps_user_search for this."},event_id:{type:"string",description:"Event id from the calendar event list API."},calendar_id:{type:"string",description:"Calendar id or `primary` (default)."},x_kso_id_type:{type:"string",description:"Optional. When set, sent as `X-Kso-Id-Type` header: `internal` or `external` (per WPS API).",enum:["internal","external"]}},required:["wps_user_id","event_id"]},async execute(n,r){try{let i=L(r,"wps_user_id"),o=L(r,"event_id"),s=T(r,"calendar_id")??"primary";return await xe(i,"\u67E5\u8BE2\u65E5\u7A0B\u8BE6\u60C5",async a=>{let d=await a.request({method:"GET",path:Ct(s,o),headers:Ar(r)});return d.data??d})}catch(i){return le(i)}}}),t({name:"wps_calendar_list_event_attendees",description:"List attendees for one calendar event (official \u83B7\u53D6\u65E5\u7A0B\u53C2\u4E0E\u8005\u5217\u8868): GET `/v7/calendars/{calendar_id}/events/{event_id}/attendees`. Response `data` typically has `items[]` and optional `next_page_token`. Requires `event_id` from `wps_calendar_list_events` or `wps_calendar_get_event`. Same delegated Bearer auth as `wps_calendar_create`. Optional `calendar_id` (default `primary`). Query: optional `page_size` (default 30, max 100 per API), `page_token` from `data.next_page_token`. Optional `x_kso_id_type` \u2192 `X-Kso-Id-Type` header (`internal` | `external`).",parameters:{type:"object",properties:{wps_user_id:{type:"string",description:"WPS user ID (SenderId). Do NOT call wps_user_search for this."},event_id:{type:"string",description:"Event id from the calendar event list API."},calendar_id:{type:"string",description:"Calendar id or `primary` (default)."},page_size:{type:"number",description:"Page size (default 30; API max 100)."},page_token:{type:"string",description:"Pagination cursor from data.next_page_token."},x_kso_id_type:{type:"string",description:"Optional. When set, sent as `X-Kso-Id-Type`: `internal` or `external`.",enum:["internal","external"]}},required:["wps_user_id","event_id"]},async execute(n,r){try{let i=L(r,"wps_user_id"),o=L(r,"event_id"),s=T(r,"calendar_id")??"primary",a=En(r,"page_size"),d=T(r,"page_token");return await xe(i,"\u83B7\u53D6\u65E5\u7A0B\u53C2\u4E0E\u8005\u5217\u8868",async l=>{let c=vo({pageSize:a,pageToken:d}),p=await l.request({method:"GET",path:Io(s,o),query:c,headers:Ar(r)});return p.data??p})}catch(i){return le(i)}}}),t({name:"wps_calendar_respond_invitation",description:"Reply to a calendar invitation (official \u7B54\u590D\u65E5\u7A0B\u9080\u8BF7): POST `/v7/calendars/{calendar_id}/events/{event_id}/respond`. Requires delegated OAuth (same as `wps_calendar_create`). Body per API: `mod_type` (`normal` = non-recurring reply, `one` = one occurrence of recurring, `all` = entire series), `response_status` (`accepted` | `declined` | `tentative`), `which_day_time` = **start time in milliseconds** (Unix ms) for the occurrence being answered. Use `event_id` from `wps_calendar_list_events` / `wps_calendar_get_event`; for recurring series pick `which_day_time` from instance or event `start_time`. Optional `calendar_id` (default `primary`).",parameters:{type:"object",properties:{wps_user_id:{type:"string",description:"WPS user ID (SenderId). Do NOT call wps_user_search for this."},event_id:{type:"string",description:"Calendar event id (from event list or get-event API)."},calendar_id:{type:"string",description:"Calendar id or `primary` (default)."},mod_type:{type:"string",description:"Reply scope per WPS API.",enum:["normal","one","all"]},response_status:{type:"string",description:"Invitation response.",enum:["accepted","declined","tentative"]},which_day_time:{type:"number",description:"Schedule start time as **milliseconds since Unix epoch** (per API `which_day_time`). Use the occurrence start from list/get/event_instances."}},required:["wps_user_id","event_id","mod_type","response_status","which_day_time"]},async execute(n,r){try{let i=L(r,"wps_user_id"),o=L(r,"event_id"),s=T(r,"calendar_id")??"primary",a=L(r,"mod_type");if(a!=="normal"&&a!=="one"&&a!=="all")throw new Error("mod_type must be normal, one, or all");let d=L(r,"response_status");if(d!=="accepted"&&d!=="declined"&&d!=="tentative")throw new Error("response_status must be accepted, declined, or tentative");let l=Math.trunc(yo(r,"which_day_time"));return await xe(i,"\u7B54\u590D\u65E5\u7A0B\u9080\u8BF7",async c=>{let p=await c.request({method:"POST",path:ko(s,o),body:{mod_type:a,response_status:d,which_day_time:l}});return p.data??p})}catch(i){return le(i)}}}),t({name:"wps_calendar_list_calendar_event_instances",description:"List expanded **calendar-level** event instances (all occurrences in a time window): GET `/v7/calendars/{calendar_id}/event_instances` (use `calendar_id=primary` for main calendar). Same delegated Bearer auth as `wps_calendar_create`. Query: RFC3339 `start_time` / `end_time` (0\u201331 days), optional `page_size` (default 30), `page_token`. Use when you need many instances across the calendar without a specific `event_id`. To expand **one** recurring event by id, use `wps_calendar_list_event_instances` instead.",parameters:{type:"object",properties:{wps_user_id:{type:"string",description:"WPS user ID (SenderId). Do NOT call wps_user_search for this."},calendar_id:{type:"string",description:"Calendar id or the literal `primary` (default)."},start_time:{type:"string",description:"Optional range start (RFC3339). Omit both for default window."},end_time:{type:"string",description:"Optional range end (RFC3339). Max 31-day span; longer truncated."},page_size:{type:"number",description:"Page size (default 30, max 500)."},page_token:{type:"string",description:"Pagination cursor if returned by API."}},required:["wps_user_id"]},async execute(n,r){try{let i=L(r,"wps_user_id"),o=T(r,"calendar_id")??"primary",s=T(r,"start_time"),a=T(r,"end_time"),d=En(r,"page_size"),l=T(r,"page_token");return await xe(i,"\u67E5\u8BE2\u65E5\u5386\u65E5\u7A0B\u5B9E\u4F8B\u5217\u8868",async c=>{let p=wo({startRfc:s,endRfc:a,pageSize:d,pageToken:l}),u=await c.request({method:"GET",path:`/v7/calendars/${encodeURIComponent(o)}/event_instances`,query:p});return u.data??u})}catch(i){return le(i)}}}),t({name:"wps_calendar_list_event_instances",description:"Query **instances of one calendar event** (expand a recurring series for that event id): GET `/v7/calendars/{calendar_id}/events/{event_id}/event_instances` per WPS365 doc. Requires `event_id` from `wps_calendar_list_events` (or equivalent). Optional query: `start_time` / `end_time` **RFC3339** strings; range 0\u201331 days (truncated if longer); omit both for default window. Same delegated Bearer auth as `wps_calendar_create`. Optional `calendar_id` (default `primary`).",parameters:{type:"object",properties:{wps_user_id:{type:"string",description:"WPS user ID (SenderId). Do NOT call wps_user_search for this."},event_id:{type:"string",description:"Calendar event id from the event list API."},calendar_id:{type:"string",description:"Calendar id or `primary` (default)."},start_time:{type:"string",description:"Optional query range start (RFC3339). Used with end_time; omit both for defaults."},end_time:{type:"string",description:"Optional query range end (RFC3339)."}},required:["wps_user_id","event_id"]},async execute(n,r){try{let i=L(r,"wps_user_id"),o=L(r,"event_id"),s=T(r,"calendar_id")??"primary",a=T(r,"start_time"),d=T(r,"end_time");return await xe(i,"\u67E5\u8BE2\u5355\u6761\u65E5\u7A0B\u5B9E\u4F8B",async l=>{let c=bo({startRfc:a,endRfc:d}),p=await l.request({method:"GET",path:`${Ct(s,o)}/event_instances`,query:c});return p.data??p})}catch(i){return le(i)}}})}var To="/v7/todo/personal_tasks",Po="/v7/todo/personal_tasks/batch_get";function Cn(e){return`/v7/todo/personal_tasks/${encodeURIComponent(e.trim())}`}function Eo(e){return`${Cn(e.trim())}/update`}function $o(e){return`${Cn(e.trim())}/update_status`}var Cr=100,Ao=20,Co=50;function qe(e){return{error:e instanceof Error?e.message:String(e)}}function oe(e,t){let n=e[t];if(typeof n!="string"||!n.trim())throw new Error(`${t} is required and must be a non-empty string`);return n.trim()}function V(e,t){let n=e[t];if(n!=null){if(typeof n!="string")throw new Error(`${t} must be a string`);return n}}function Se(e,t){let n=e[t];if(n!=null){if(typeof n=="number"&&Number.isFinite(n))return n;if(typeof n=="string"&&n.trim()!==""){let r=Number(n);if(Number.isFinite(r))return r}throw new Error(`${t} must be a finite number`)}}function Oo(e,t){let n=e[t];if(n==null)return;if(!Array.isArray(n))throw new Error(`${t} must be an array of strings`);let r=n.map(i=>String(i).trim()).filter(Boolean);return r.length>0?r:void 0}function Ro(e,t){let n=e[t];if(n==null)return;if(!Array.isArray(n))throw new Error(`${t} must be an array of objects with name and value`);let r=[];for(let i of n){if(typeof i!="object"||i===null)continue;let o=i;typeof o.name!="string"||typeof o.value!="string"||r.push({name:o.name.trim(),value:o.value})}return r.length>0?r:void 0}function Uo(e,t){let n=V(e,t);if(!(n===void 0||n.trim()===""))try{let r=JSON.parse(n);if(typeof r!="object"||r===null||Array.isArray(r))throw new Error(`${t} must be a JSON object`);return r}catch(r){throw r instanceof SyntaxError?new Error(`${t} must be valid JSON`):r}}function et(e){let t=V(e,"x_kso_id_type");if(t===void 0||t.trim()==="")return;let n=t.trim();if(n!=="internal"&&n!=="external")throw new Error("x_kso_id_type must be internal or external when provided");return{"X-Kso-Id-Type":n}}function Do(e){let t=e.titleSubject.trim();if(!t)throw new Error("title_subject must be non-empty");let n={subject:t};e.titlePrefix!==void 0&&e.titlePrefix.trim()!==""&&(n.prefix=e.titlePrefix.trim());let r={title:n};if(e.description!==void 0&&e.description.trim()!==""&&(r.description=e.description.trim()),e.dueTimeMs!==void 0){if(!Number.isFinite(e.dueTimeMs))throw new Error("due_time_ms must be a finite number");r.due_time=Math.trunc(e.dueTimeMs)}if((e.status==="todo"||e.status==="finish")&&(r.status=e.status),e.executors!==void 0&&e.executors.length>0){if(e.executors.length>Cr)throw new Error(`executors must have at most ${Cr} entries`);r.executors=[...e.executors]}return r}function jo(e){let t={};if(e.keyword!==void 0&&e.keyword.trim()!==""&&(t.keyword=e.keyword.trim().slice(0,50)),e.executor!==void 0&&e.executor.trim()!==""&&(t.executor=e.executor.trim()),(e.status==="todo"||e.status==="finish")&&(t.status=e.status),e.pageSize!==void 0){let n=e.pageSize;t.page_size=Math.max(1,Math.min(Co,Math.trunc(n)))}else t.page_size=Ao;if(e.pageToken!==void 0&&e.pageToken.trim()!==""&&(t.page_token=e.pageToken.trim()),e.createdTimeStartMs!==void 0||e.createdTimeEndMs!==void 0){let n={};e.createdTimeStartMs!==void 0&&Number.isFinite(e.createdTimeStartMs)&&(n.start_time=Math.trunc(e.createdTimeStartMs)),e.createdTimeEndMs!==void 0&&Number.isFinite(e.createdTimeEndMs)&&(n.end_time=Math.trunc(e.createdTimeEndMs)),Object.keys(n).length>0&&(t.created_time=n)}if(e.dueTimeStartMs!==void 0||e.dueTimeEndMs!==void 0){let n={};e.dueTimeStartMs!==void 0&&Number.isFinite(e.dueTimeStartMs)&&(n.start_time=Math.trunc(e.dueTimeStartMs)),e.dueTimeEndMs!==void 0&&Number.isFinite(e.dueTimeEndMs)&&(n.end_time=Math.trunc(e.dueTimeEndMs)),Object.keys(n).length>0&&(t.due_time=n)}return t}function qo(e){let t={},n=e.titleSubject?.trim()??"",r=e.titlePrefix?.trim()??"";if(n!==""||r!==""){let i={};n!==""&&(i.subject=n),r!==""&&(i.prefix=r),t.title=i}if(e.description!==void 0&&e.description.trim()!==""&&(t.description=e.description.trim()),e.dueTimeMs!==void 0){if(!Number.isFinite(e.dueTimeMs))throw new Error("due_time_ms must be a finite number");t.due_time=Math.trunc(e.dueTimeMs)}if(e.extAttrs!==void 0&&e.extAttrs.length>0&&(t.ext_attrs=e.extAttrs.map(i=>({name:i.name,value:i.value}))),e.notifyConfig!==void 0&&Object.keys(e.notifyConfig).length>0&&(t.notify_config=e.notifyConfig),Object.keys(t).length===0)throw new Error("provide at least one of: title_subject, title_prefix, description, due_time_ms, ext_attrs, notify_config_json");return t}function No(e){let t=e.trim();if(t==="finish"||t==="unfinish"||t==="finish_all"||t==="unfinish_all")return t;throw new Error("action must be exactly one of: finish, unfinish, finish_all, unfinish_all")}function Mo(e){return{action:No(e.action)}}async function tt(e,t,n){try{return await De({wpsUserId:e,authCardOriginalMessage:t,needsAuthMessage:"\u9700\u8981\u7528\u6237\u6388\u6743\u624D\u80FD\u4F7F\u7528\u5F85\u529E\u80FD\u529B\u3002\u5DF2\u53D1\u9001\u6388\u6743\u5361\u7247\uFF0C\u8BF7\u7528\u6237\u70B9\u51FB\u300C\u524D\u5F80\u6388\u6743\u300D\u5B8C\u6210\u6388\u6743\u540E\u91CD\u8BD5\u3002",logTag:"todo",run:n})}catch(r){return qe(r)}}function On(e,t){t({name:"wps_todo_create_personal_task",description:"Create a personal todo/task via WPS OpenAPI (\u521B\u5EFA\u4E2A\u4EBA\u5F85\u529E): POST `/v7/todo/personal_tasks`. Requires user delegated OAuth scope `kso.task.readwrite` (or equivalent per console). Use SenderId as `wps_user_id`. Required: `title_subject` \u2192 body `title.subject`; optional `title_prefix` \u2192 `title.prefix`. Optional: `description`, `due_time_ms` (deadline **milliseconds** Unix epoch), `status` (`todo`|`finish`), `executors` (\u2264100 user ids). Response `data.task_id` is the new task id. Optional `x_kso_id_type`: `internal`|`external` \u2192 header `X-Kso-Id-Type`.",parameters:{type:"object",properties:{wps_user_id:{type:"string",description:"WPS user ID (SenderId). Do NOT call wps_user_search for this."},title_subject:{type:"string",description:"Todo title subject (maps to request body title.subject)."},title_prefix:{type:"string",description:"Optional. Maps to title.prefix."},description:{type:"string",description:"Optional todo description."},due_time_ms:{type:"number",description:"Optional deadline as Unix timestamp in **milliseconds** (due_time)."},status:{type:"string",description:"Optional initial status.",enum:["todo","finish"]},executors:{type:"array",items:{type:"string"},description:"Optional executor user ids (max 100)."},x_kso_id_type:{type:"string",description:"Optional. Sent as X-Kso-Id-Type: internal or external.",enum:["internal","external"]}},required:["wps_user_id","title_subject"]},async execute(n,r){try{let i=oe(r,"wps_user_id"),o=oe(r,"title_subject"),s=V(r,"title_prefix"),a=V(r,"description"),d=Se(r,"due_time_ms"),l=V(r,"status"),c=Oo(r,"executors"),p;if(l!==void 0){if(l!=="todo"&&l!=="finish")throw new Error("status must be todo or finish when provided");p=l}let u=Do({titleSubject:o,titlePrefix:s,description:a,dueTimeMs:d,status:p,executors:c});return await tt(i,"\u521B\u5EFA\u4E2A\u4EBA\u5F85\u529E",async m=>{let f=await m.request({method:"POST",path:To,body:u,headers:et(r)});return f.data??f})}catch(i){return qe(i)}}}),t({name:"wps_todo_list_personal_tasks",description:"List personal todos via WPS OpenAPI (\u83B7\u53D6\u4E2A\u4EBA\u5F85\u529E\u5217\u8868): POST `/v7/todo/personal_tasks/batch_get`. Requires delegated OAuth (`kso.task.read` / `kso.task.readwrite`). Use SenderId as `wps_user_id`. Body filters are optional: `keyword` (\u226450 chars), `executor`, `status` (`todo`|`finish`), `page_size` (default 20, max 50), `page_token` (from previous `data` pagination field per API). `created_time` / `due_time` ranges use **milliseconds** (`*_start_ms`, `*_end_ms`). Response `data` typically includes `tasks`, `total`, `next_offset`. Optional `x_kso_id_type`.",parameters:{type:"object",properties:{wps_user_id:{type:"string",description:"WPS user ID (SenderId). Do NOT call wps_user_search for this."},keyword:{type:"string",description:"Optional. Fuzzy match title/description (max 50 chars)."},executor:{type:"string",description:"Optional. Filter by executor user id."},status:{type:"string",description:"Optional list filter: todo (=\u672A\u5B8C\u6210) or finish (=\u5DF2\u5B8C\u6210).",enum:["todo","finish"]},page_size:{type:"number",description:"Page size (default 20; API max 50)."},page_token:{type:"string",description:"Pagination cursor from previous response (see API field names e.g. next_offset)."},created_time_start_ms:{type:"number",description:"Optional. Creation range start (Unix ms)."},created_time_end_ms:{type:"number",description:"Optional. Creation range end (Unix ms)."},due_time_start_ms:{type:"number",description:"Optional. Due range start (Unix ms)."},due_time_end_ms:{type:"number",description:"Optional. Due range end (Unix ms)."},x_kso_id_type:{type:"string",description:"Optional. Sent as X-Kso-Id-Type: internal or external.",enum:["internal","external"]}},required:["wps_user_id"]},async execute(n,r){try{let i=oe(r,"wps_user_id"),o=V(r,"keyword"),s=V(r,"executor"),a=V(r,"status"),d=Se(r,"page_size"),l=V(r,"page_token"),c=Se(r,"created_time_start_ms"),p=Se(r,"created_time_end_ms"),u=Se(r,"due_time_start_ms"),m=Se(r,"due_time_end_ms"),f;if(a!==void 0){if(a!=="todo"&&a!=="finish")throw new Error("status must be todo or finish when provided");f=a}let g=jo({keyword:o,executor:s,status:f,pageSize:d,pageToken:l,createdTimeStartMs:c,createdTimeEndMs:p,dueTimeStartMs:u,dueTimeEndMs:m});return await tt(i,"\u83B7\u53D6\u4E2A\u4EBA\u5F85\u529E\u5217\u8868",async h=>{let _=await h.request({method:"POST",path:Po,body:g,headers:et(r)});return _.data??_})}catch(i){return qe(i)}}}),t({name:"wps_todo_get_personal_task",description:"Get one personal todo by id (\u83B7\u53D6\u4E2A\u4EBA\u5F85\u529E\u8BE6\u60C5): GET `/v7/todo/personal_tasks/{task_id}`. Requires delegated OAuth (`kso.task.read` / `kso.task.readwrite`). Use SenderId as `wps_user_id`. Requires **`task_id`** from `wps_todo_list_personal_tasks` (`tasks[].id`) or create response. Response `data` is a single todo object (`todo_personal_task`). Optional `x_kso_id_type`.",parameters:{type:"object",properties:{wps_user_id:{type:"string",description:"WPS user ID (SenderId). Do NOT call wps_user_search for this."},task_id:{type:"string",description:"Todo task id from list or create API."},x_kso_id_type:{type:"string",description:"Optional. Sent as X-Kso-Id-Type: internal or external.",enum:["internal","external"]}},required:["wps_user_id","task_id"]},async execute(n,r){try{let i=oe(r,"wps_user_id"),o=oe(r,"task_id");return await tt(i,"\u83B7\u53D6\u4E2A\u4EBA\u5F85\u529E\u8BE6\u60C5",async s=>{let a=await s.request({method:"GET",path:Cn(o),headers:et(r)});return a.data??a})}catch(i){return qe(i)}}}),t({name:"wps_todo_update_personal_task_status",description:'Update personal todo status (\u66F4\u65B0\u4E2A\u4EBA\u5F85\u529E\u72B6\u6001): POST `/v7/todo/personal_tasks/{task_id}/update_status`. Request JSON body: **`{ "action": "..." }`** only. Requires delegated `kso.task.readwrite`. Use SenderId as `wps_user_id`. Required tool params: `task_id` and `action`. Official enum: `finish`, `unfinish`, `finish_all`, `unfinish_all` (`finish_all` / `unfinish_all` are creator-only per WPS docs).',parameters:{type:"object",properties:{wps_user_id:{type:"string",description:"WPS user ID (SenderId). Do NOT call wps_user_search for this."},task_id:{type:"string",description:"Todo id to update status."},action:{type:"string",description:"Maps to request body `action`. `finish` / `unfinish` = \u5355\u6761\uFF1B`finish_all` / `unfinish_all` = \u5168\u90E8\uFF08\u521B\u5EFA\u8005\uFF09.",enum:["finish","unfinish","finish_all","unfinish_all"]},x_kso_id_type:{type:"string",description:"Optional. Sent as X-Kso-Id-Type: internal or external.",enum:["internal","external"]}},required:["wps_user_id","task_id","action"]},async execute(n,r){try{let i=oe(r,"wps_user_id"),o=oe(r,"task_id"),s=oe(r,"action"),a=Mo({action:s});return await tt(i,"\u66F4\u65B0\u4E2A\u4EBA\u5F85\u529E\u72B6\u6001",async d=>{let l=await d.request({method:"POST",path:$o(o),body:a,headers:et(r)});return l.data??l})}catch(i){return qe(i)}}}),t({name:"wps_todo_update_personal_task",description:"Update a personal todo (\u66F4\u65B0\u4E2A\u4EBA\u5F85\u529E): POST `/v7/todo/personal_tasks/{task_id}/update`. Requires delegated **`kso.task.readwrite`**. Use SenderId as `wps_user_id`. Requires **`task_id`**. Body fields are optional but **at least one** must be provided: `title_subject` / `title_prefix` (maps to `title`), `description`, `due_time_ms` (ms), `ext_attrs` (`[{name,value}]`), or `notify_config_json` (JSON object string for `notify_config`). Response is typically `code` + `msg` only.",parameters:{type:"object",properties:{wps_user_id:{type:"string",description:"WPS user ID (SenderId). Do NOT call wps_user_search for this."},task_id:{type:"string",description:"Todo id to update."},title_subject:{type:"string",description:"Optional. Maps to title.subject."},title_prefix:{type:"string",description:"Optional. Maps to title.prefix."},description:{type:"string",description:"Optional. New description."},due_time_ms:{type:"number",description:"Optional. New deadline as Unix **milliseconds**."},ext_attrs:{type:"array",items:{type:"object",properties:{name:{type:"string"},value:{type:"string"}},required:["name","value"]},description:"Optional. Extension attributes."},notify_config_json:{type:"string",description:"Optional. JSON object string for notify_config (e.g. reminders, switch). Must parse to an object."},x_kso_id_type:{type:"string",description:"Optional. Sent as X-Kso-Id-Type: internal or external.",enum:["internal","external"]}},required:["wps_user_id","task_id"]},async execute(n,r){try{let i=oe(r,"wps_user_id"),o=oe(r,"task_id"),s=V(r,"title_subject"),a=V(r,"title_prefix"),d=V(r,"description"),l=Se(r,"due_time_ms"),c=Ro(r,"ext_attrs"),p=Uo(r,"notify_config_json"),u=qo({titleSubject:s,titlePrefix:a,description:d,dueTimeMs:l,extAttrs:c,notifyConfig:p});return await tt(i,"\u66F4\u65B0\u4E2A\u4EBA\u5F85\u529E",async m=>{let f=await m.request({method:"POST",path:Eo(o),body:u,headers:et(r)});return f.data??f})}catch(i){return qe(i)}}})}var Wo="/v7/drives",zo="/v7/files/search",Lo=50,Fo=500,Bo=50,Go=500,Or=["folder","file","shortcut"],Rr=["fail","rename","overwrite","replace"],Mr=["kdc","plain","markdown"],Wr=["sync","async","auto"],Ko=["para","table","component","textbox","all"],Ur=["file_name","content","all"],Dr=["folder","file","shortcut"],jr=["ctime","mtime","otime","stime"],qr=["desc","asc"],Nr=["ctime","mtime"],Ho=["all","share_by_me","share_to_me","latest","personal_drive","group_drive","recycle","customize","latest_opened","latest_edited"];function Ne(e){return{error:e instanceof Error?e.message:String(e)}}function F(e,t){let n=e[t];if(typeof n!="string"||!n.trim())throw new Error(`${t} is required and must be a non-empty string`);return n.trim()}function B(e,t){let n=e[t];if(n!=null){if(typeof n!="string")throw new Error(`${t} must be a string`);return n}}function nt(e,t){let n=e[t];if(n!=null){if(typeof n=="number"&&Number.isFinite(n))return n;if(typeof n=="string"&&n.trim()!==""){let r=Number(n);if(Number.isFinite(r))return r}throw new Error(`${t} must be a finite number`)}}function se(e,t){let n=e[t];if(n!=null){if(typeof n=="boolean")return n;if(n==="true"||n==="false")return n==="true";throw new Error(`${t} must be a boolean`)}}function U(e,t){let n=e[t];if(n==null)return;if(!Array.isArray(n))throw new Error(`${t} must be an array of strings`);let r=n.map(i=>String(i).trim()).filter(Boolean);return r.length>0?r:void 0}function rt(e){let t=B(e,"x_kso_id_type");if(t===void 0||t.trim()==="")return;let n=t.trim();if(n!=="internal"&&n!=="external")throw new Error("x_kso_id_type must be internal or external when provided");return{"X-Kso-Id-Type":n}}function Jo(e){let t={allotee_type:e.alloteeType,page_size:Math.max(1,Math.min(Fo,Math.trunc(e.pageSize??Lo)))};return e.alloteeId!==void 0&&e.alloteeId.trim()!==""&&(t.allotee_id=e.alloteeId.trim()),e.withExtAttrs!==void 0&&(t.with_ext_attrs=e.withExtAttrs),e.pageToken!==void 0&&e.pageToken.trim()!==""&&(t.page_token=e.pageToken.trim()),e.sources!==void 0&&e.sources.length>0&&(t.sources=[...e.sources]),t}function Xo(e,t){return`/v7/drives/${encodeURIComponent(e.trim())}/files/${encodeURIComponent(t.trim())}/create`}function Yo(e){let t=e.name.trim();if(!t)throw new Error("name must be a non-empty string");let n={file_type:e.fileType,name:t};if(e.fileType==="shortcut"){if(!e.fileId||!e.fileId.trim())throw new Error("file_id is required when file_type is shortcut");n.file_id=e.fileId.trim()}else e.fileId!==void 0&&e.fileId.trim()!==""&&(n.file_id=e.fileId.trim());return e.onNameConflict!==void 0&&(n.on_name_conflict=e.onNameConflict),e.parentPath!==void 0&&e.parentPath.length>0&&(n.parent_path=[...e.parentPath]),n}function Vo(e,t){return`/v7/drives/${encodeURIComponent(e.trim())}/files/${encodeURIComponent(t.trim())}/content`}function Qo(e){let t={};if(e.format!==void 0&&e.format.trim()!==""){let n=e.format.trim();if(!Mr.includes(n))throw new Error("format must be one of: kdc, plain, markdown");t.format=n}if(e.includeElements!==void 0&&e.includeElements.length>0){let n=e.includeElements.map(r=>r.trim()).filter(Boolean).filter((r,i,o)=>o.indexOf(r)===i);for(let r of n)if(!Ko.includes(r))throw new Error("include_elements items must be one of: para, table, component, textbox, all");n.length>0&&(t.include_elements=n)}if(e.mode!==void 0&&e.mode.trim()!==""){let n=e.mode.trim();if(!Wr.includes(n))throw new Error("mode must be one of: sync, async, auto");t.mode=n}return e.taskId!==void 0&&e.taskId.trim()!==""&&(t.task_id=e.taskId.trim()),t}function Zo(e){return`/v7/files/${encodeURIComponent(e.trim())}/meta`}function es(e){let t={};return e.withPermission!==void 0&&(t.with_permission=e.withPermission),e.withExtAttrs!==void 0&&(t.with_ext_attrs=e.withExtAttrs),e.withDrive!==void 0&&(t.with_drive=e.withDrive),t}function ts(e){let t={type:e.type,page_size:Math.max(1,Math.min(Go,Math.trunc(e.pageSize??Bo)))};return e.keyword!==void 0&&e.keyword.trim()!==""&&(t.keyword=e.keyword.trim()),e.fileType!==void 0&&(t.file_type=e.fileType),e.fileExts!==void 0&&e.fileExts.length>0&&(t.file_exts=[...e.fileExts]),e.driveIds!==void 0&&e.driveIds.length>0&&(t.drive_ids=[...e.driveIds]),e.parentIds!==void 0&&e.parentIds.length>0&&(t.parent_ids=[...e.parentIds]),e.creatorIds!==void 0&&e.creatorIds.length>0&&(t.creator_ids=[...e.creatorIds]),e.modifierIds!==void 0&&e.modifierIds.length>0&&(t.modifier_ids=[...e.modifierIds]),e.sharerIds!==void 0&&e.sharerIds.length>0&&(t.sharer_ids=[...e.sharerIds]),e.receiverIds!==void 0&&e.receiverIds.length>0&&(t.receiver_ids=[...e.receiverIds]),e.timeType!==void 0&&(t.time_type=e.timeType),e.startTime!==void 0&&(t.start_time=Math.trunc(e.startTime)),e.endTime!==void 0&&(t.end_time=Math.trunc(e.endTime)),e.withPermission!==void 0&&(t.with_permission=e.withPermission),e.withLink!==void 0&&(t.with_link=e.withLink),e.withTotal!==void 0&&(t.with_total=e.withTotal),e.pageToken!==void 0&&e.pageToken.trim()!==""&&(t.page_token=e.pageToken.trim()),e.channels!==void 0&&e.channels.length>0&&(t.channels=[...e.channels]),e.deviceIds!==void 0&&e.deviceIds.length>0&&(t.device_ids=[...e.deviceIds]),e.excludeChannels!==void 0&&e.excludeChannels.length>0&&(t.exclude_channels=[...e.excludeChannels]),e.excludeFileExts!==void 0&&e.excludeFileExts.length>0&&(t.exclude_file_exts=[...e.excludeFileExts]),e.filterUserId!==void 0&&(t.filter_user_id=Math.trunc(e.filterUserId)),e.fileExtGroups!==void 0&&e.fileExtGroups.length>0&&(t.file_ext_groups=[...e.fileExtGroups]),e.withFolder!==void 0&&(t.with_folder=e.withFolder),e.withDrive!==void 0&&(t.with_drive=e.withDrive),e.order!==void 0&&(t.order=e.order),e.orderBy!==void 0&&(t.order_by=e.orderBy),e.scope!==void 0&&e.scope.length>0&&(t.scope=[...e.scope]),e.searchOperatorName!==void 0&&(t.search_operator_name=e.searchOperatorName),t}async function it(e,t,n,r){try{return await De({wpsUserId:e,authCardOriginalMessage:t,needsAuthMessage:n,logTag:"drive",run:r})}catch(i){return Ne(i)}}function Rn(e,t){t({name:"wps_drive_list_drives",description:"List cloud drives (\u83B7\u53D6\u76D8\u5217\u8868): GET `/v7/drives`. Requires delegated OAuth (`kso.drive.readwrite`). Use SenderId as `wps_user_id`. Required query: `allotee_type` (`user` | `group` | `app`). Optional `allotee_id` can be supplied for user/group/app scopes. Optional: `with_ext_attrs`, `page_size` (default 50, max 500), `page_token`, `sources` (array). Optional `x_kso_id_type` header (`internal` | `external`).",parameters:{type:"object",properties:{wps_user_id:{type:"string",description:"WPS user ID (SenderId). Do NOT call wps_user_search for this."},allotee_type:{type:"string",description:"Drive allocation type.",enum:["user","group","app"]},allotee_id:{type:"string",description:"Optional allocation id for user/group/app scope."},with_ext_attrs:{type:"boolean",description:"Optional. Include ext_attrs in response."},page_size:{type:"number",description:"Optional. Page size (default 50, max 500)."},page_token:{type:"string",description:"Optional pagination token."},sources:{type:"array",items:{type:"string"},description:"Optional source filters."},x_kso_id_type:{type:"string",description:"Optional. Sent as X-Kso-Id-Type: internal or external.",enum:["internal","external"]}},required:["wps_user_id","allotee_type"]},async execute(n,r){try{let i=F(r,"wps_user_id"),o=F(r,"allotee_type");if(o!=="user"&&o!=="group"&&o!=="app")throw new Error("allotee_type must be user, group, or app");let s=o,a=B(r,"allotee_id"),d=se(r,"with_ext_attrs"),l=nt(r,"page_size"),c=B(r,"page_token"),p=U(r,"sources");return await it(i,"\u83B7\u53D6\u76D8\u5217\u8868","\u9700\u8981\u7528\u6237\u6388\u6743\u624D\u80FD\u8BBF\u95EE\u4E91\u6587\u6863\u76D8\u5217\u8868\u3002\u5DF2\u53D1\u9001\u6388\u6743\u5361\u7247\uFF0C\u8BF7\u7528\u6237\u70B9\u51FB\u300C\u524D\u5F80\u6388\u6743\u300D\u540E\u91CD\u8BD5\u3002",async u=>{let m=Jo({alloteeType:s,alloteeId:a,withExtAttrs:d,pageSize:l,pageToken:c,sources:p}),f=await u.request({method:"GET",path:Wo,query:m,headers:rt(r)});return f.data??f})}catch(i){return Ne(i)}}}),t({name:"wps_drive_create_file",description:"Create file/folder/shortcut (\u65B0\u5EFA\u6587\u4EF6(\u5939)): POST `/v7/drives/{drive_id}/files/{parent_id}/create`. Requires delegated OAuth (`kso.file.readwrite`). Use SenderId as `wps_user_id`. Required: `drive_id`, `parent_id`, `file_type` (`folder` | `file` | `shortcut`), `name`. When `file_type` is `shortcut`, `file_id` is required. Optional: `on_name_conflict` (`fail` | `rename` | `overwrite` | `replace`), `parent_path` (string array). Optional `x_kso_id_type` header (`internal` | `external`).",parameters:{type:"object",properties:{wps_user_id:{type:"string",description:"WPS user ID (SenderId). Do NOT call wps_user_search for this."},drive_id:{type:"string",description:"Drive ID."},parent_id:{type:"string",description:"Parent file/folder ID (root is 0)."},file_type:{type:"string",enum:[...Or],description:"Created resource type: folder, file, or shortcut."},name:{type:"string",description:"Name to create. Include extension for files when needed."},file_id:{type:"string",description:"Required only for file_type=shortcut (target file id)."},on_name_conflict:{type:"string",enum:[...Rr],description:"Name conflict behavior."},parent_path:{type:"array",items:{type:"string"},description:"Optional relative nested path array under parent_id."},x_kso_id_type:{type:"string",description:"Optional. Sent as X-Kso-Id-Type: internal or external.",enum:["internal","external"]}},required:["wps_user_id","drive_id","parent_id","file_type","name"]},async execute(n,r){try{let i=F(r,"wps_user_id"),o=F(r,"drive_id"),s=F(r,"parent_id"),a=F(r,"file_type");if(!Or.includes(a))throw new Error("file_type must be one of: folder, file, shortcut");let d=a,l=F(r,"name"),c=B(r,"file_id"),p=B(r,"on_name_conflict");if(p!==void 0&&!Rr.includes(p))throw new Error("on_name_conflict must be one of: fail, rename, overwrite, replace");let u=p,m=U(r,"parent_path");return await it(i,"\u65B0\u5EFA\u6587\u4EF6\uFF08\u5939\uFF09","\u9700\u8981\u7528\u6237\u6388\u6743\u624D\u80FD\u65B0\u5EFA\u4E91\u6587\u6863\u6587\u4EF6\uFF08\u5939\uFF09\u3002\u5DF2\u53D1\u9001\u6388\u6743\u5361\u7247\uFF0C\u8BF7\u7528\u6237\u70B9\u51FB\u300C\u524D\u5F80\u6388\u6743\u300D\u540E\u91CD\u8BD5\u3002",async f=>{let g=Yo({fileType:d,name:l,fileId:c,onNameConflict:u,parentPath:m}),h=await f.request({method:"POST",path:Xo(o,s),body:g,headers:rt(r)});return h.data??h})}catch(i){return Ne(i)}}}),t({name:"wps_drive_extract_file_content",description:"Extract file content (\u6587\u6863\u5185\u5BB9\u62BD\u53D6): GET `/v7/drives/{drive_id}/files/{file_id}/content`. Requires delegated OAuth (`kso.file.read`). Use SenderId as `wps_user_id`. Required: `drive_id`, `file_id`. Optional query: `format` (`kdc` | `plain` | `markdown`), `include_elements` (`para` | `table` | `component` | `textbox` | `all`), `mode` (`sync` | `async` | `auto`), `task_id`. Returns upstream `data` as-is (for fields like `task_id`, `task_status`, `doc`, `markdown`, `plain`, etc.).",parameters:{type:"object",properties:{wps_user_id:{type:"string",description:"WPS user ID (SenderId). Do NOT call wps_user_search for this."},drive_id:{type:"string",description:"Drive ID."},file_id:{type:"string",description:"File ID."},format:{type:"string",enum:[...Mr],description:"Optional output format."},include_elements:{type:"array",items:{type:"string"},description:"Optional extracted element types."},mode:{type:"string",enum:[...Wr],description:"Optional extraction mode."},task_id:{type:"string",description:"Optional task id for async/auto result polling."},x_kso_id_type:{type:"string",description:"Optional. Sent as X-Kso-Id-Type: internal or external.",enum:["internal","external"]}},required:["wps_user_id","drive_id","file_id"]},async execute(n,r){try{let i=F(r,"wps_user_id"),o=F(r,"drive_id"),s=F(r,"file_id"),a=B(r,"format"),d=U(r,"include_elements"),l=B(r,"mode"),c=B(r,"task_id");return await it(i,"\u6587\u6863\u5185\u5BB9\u62BD\u53D6","\u9700\u8981\u7528\u6237\u6388\u6743\u624D\u80FD\u8FDB\u884C\u6587\u6863\u5185\u5BB9\u62BD\u53D6\u3002\u5DF2\u53D1\u9001\u6388\u6743\u5361\u7247\uFF0C\u8BF7\u7528\u6237\u70B9\u51FB\u300C\u524D\u5F80\u6388\u6743\u300D\u540E\u91CD\u8BD5\u3002",async p=>{let u=Qo({format:a,includeElements:d,mode:l,taskId:c}),m=await p.request({method:"GET",path:Vo(o,s),query:Object.keys(u).length>0?u:void 0,headers:rt(r)});return m.data??m})}catch(i){return Ne(i)}}}),t({name:"wps_drive_get_file_meta",description:"Get file metadata (\u83B7\u53D6\u6587\u4EF6\u4FE1\u606F): GET `/v7/files/{file_id}/meta`. Requires delegated OAuth (`kso.file.read`). Use SenderId as `wps_user_id`. Required: `file_id`. Optional query: `with_permission`, `with_ext_attrs`, `with_drive` (boolean). Returns upstream `data` as-is (for fields like `drive`, `permission`, `ext_attrs`, etc.).",parameters:{type:"object",properties:{wps_user_id:{type:"string",description:"WPS user ID (SenderId). Do NOT call wps_user_search for this."},file_id:{type:"string",description:"File ID."},with_permission:{type:"boolean",description:"Optional. Include permission field in response."},with_ext_attrs:{type:"boolean",description:"Optional. Include ext_attrs field in response."},with_drive:{type:"boolean",description:"Optional. Include drive field in response."},x_kso_id_type:{type:"string",description:"Optional. Sent as X-Kso-Id-Type: internal or external.",enum:["internal","external"]}},required:["wps_user_id","file_id"]},async execute(n,r){try{let i=F(r,"wps_user_id"),o=F(r,"file_id"),s=se(r,"with_permission"),a=se(r,"with_ext_attrs"),d=se(r,"with_drive");return await it(i,"\u83B7\u53D6\u6587\u4EF6\u4FE1\u606F","\u9700\u8981\u7528\u6237\u6388\u6743\u624D\u80FD\u83B7\u53D6\u6587\u4EF6\u4FE1\u606F\u3002\u5DF2\u53D1\u9001\u6388\u6743\u5361\u7247\uFF0C\u8BF7\u7528\u6237\u70B9\u51FB\u300C\u524D\u5F80\u6388\u6743\u300D\u540E\u91CD\u8BD5\u3002",async l=>{let c=es({withPermission:s,withExtAttrs:a,withDrive:d}),p=await l.request({method:"GET",path:Zo(o),query:Object.keys(c).length>0?c:void 0,headers:rt(r)});return p.data??p})}catch(i){return Ne(i)}}}),t({name:"wps_drive_search_files",description:"Search files (\u6587\u4EF6\u641C\u7D22): GET `/v7/files/search`. Requires delegated OAuth (`kso.file.search`). Use SenderId as `wps_user_id`. Required query: `type` (`file_name` | `content` | `all`), `page_size` (default 50, max 500). Supports optional filters: keyword, file_type, file_exts, drive_ids, parent_ids, creator_ids, modifier_ids, sharer_ids, receiver_ids, time_type/start_time/end_time, with_permission/with_link/with_total, page_token, channels/device_ids/exclude_channels/exclude_file_exts, filter_user_id, file_ext_groups, with_folder, with_drive, order/order_by, scope, search_operator_name.",parameters:{type:"object",properties:{wps_user_id:{type:"string",description:"WPS user ID (SenderId)."},keyword:{type:"string",description:"Optional search keyword."},type:{type:"string",enum:[...Ur],description:"Search type."},file_type:{type:"string",enum:[...Dr],description:"Optional file type filter."},file_exts:{type:"array",items:{type:"string"},description:"Optional file extension filters."},drive_ids:{type:"array",items:{type:"string"},description:"Optional drive id filters."},parent_ids:{type:"array",items:{type:"string"},description:"Optional parent id filters."},creator_ids:{type:"array",items:{type:"string"},description:"Optional creator id filters."},modifier_ids:{type:"array",items:{type:"string"},description:"Optional modifier id filters."},sharer_ids:{type:"array",items:{type:"string"},description:"Optional sharer id filters."},receiver_ids:{type:"array",items:{type:"string"},description:"Optional receiver id filters."},time_type:{type:"string",enum:[...jr],description:"Optional time type."},start_time:{type:"number",description:"Optional start time (unix seconds)."},end_time:{type:"number",description:"Optional end time (unix seconds)."},with_permission:{type:"boolean",description:"Optional. Include permission fields."},with_link:{type:"boolean",description:"Optional. Include sharing link fields."},with_total:{type:"boolean",description:"Optional. Include total count in response."},page_size:{type:"number",description:"Optional. Default 50, max 500."},page_token:{type:"string",description:"Optional pagination token."},channels:{type:"array",items:{type:"string"},description:"Optional channel filters."},device_ids:{type:"array",items:{type:"string"},description:"Optional device filters."},exclude_channels:{type:"array",items:{type:"string"},description:"Optional excluded channel filters."},exclude_file_exts:{type:"array",items:{type:"string"},description:"Optional excluded file extension filters."},filter_user_id:{type:"number",description:"Optional filter user id."},file_ext_groups:{type:"array",items:{type:"string"},description:"Optional file extension groups."},with_folder:{type:"boolean",description:"Optional include folder results."},with_drive:{type:"boolean",description:"Optional include drive info."},order:{type:"string",enum:[...qr],description:"Optional order."},order_by:{type:"string",enum:[...Nr],description:"Optional order by field."},scope:{type:"array",items:{type:"string"},description:"Optional search scopes."},search_operator_name:{type:"boolean",description:"Optional search by operator name switch."},x_kso_id_type:{type:"string",enum:["internal","external"],description:"Optional. Sent as X-Kso-Id-Type."}},required:["wps_user_id","type"]},async execute(n,r){try{let i=F(r,"wps_user_id"),o=F(r,"type");if(!Ur.includes(o))throw new Error("type must be one of: file_name, content, all");let s=o,a=B(r,"file_type");if(a!==void 0&&!Dr.includes(a))throw new Error("file_type must be one of: folder, file, shortcut");let d=a,l=B(r,"time_type");if(l!==void 0&&!jr.includes(l))throw new Error("time_type must be one of: ctime, mtime, otime, stime");let c=l,p=B(r,"order");if(p!==void 0&&!qr.includes(p))throw new Error("order must be one of: desc, asc");let u=p,m=B(r,"order_by");if(m!==void 0&&!Nr.includes(m))throw new Error("order_by must be one of: ctime, mtime");let f=m,g=U(r,"scope");if(g!==void 0){for(let h of g)if(!Ho.includes(h))throw new Error("scope items must be one of: all, share_by_me, share_to_me, latest, personal_drive, group_drive, recycle, customize, latest_opened, latest_edited")}return await it(i,"\u6587\u4EF6\u641C\u7D22","\u9700\u8981\u7528\u6237\u6388\u6743\u624D\u80FD\u641C\u7D22\u4E91\u6587\u6863\u6587\u4EF6\u3002\u5DF2\u53D1\u9001\u6388\u6743\u5361\u7247\uFF0C\u8BF7\u7528\u6237\u70B9\u51FB\u300C\u524D\u5F80\u6388\u6743\u300D\u540E\u91CD\u8BD5\u3002",async h=>{let _=ts({keyword:B(r,"keyword"),type:s,fileType:d,fileExts:U(r,"file_exts"),driveIds:U(r,"drive_ids"),parentIds:U(r,"parent_ids"),creatorIds:U(r,"creator_ids"),modifierIds:U(r,"modifier_ids"),sharerIds:U(r,"sharer_ids"),receiverIds:U(r,"receiver_ids"),timeType:c,startTime:nt(r,"start_time"),endTime:nt(r,"end_time"),withPermission:se(r,"with_permission"),withLink:se(r,"with_link"),withTotal:se(r,"with_total"),pageSize:nt(r,"page_size"),pageToken:B(r,"page_token"),channels:U(r,"channels"),deviceIds:U(r,"device_ids"),excludeChannels:U(r,"exclude_channels"),excludeFileExts:U(r,"exclude_file_exts"),filterUserId:nt(r,"filter_user_id"),fileExtGroups:U(r,"file_ext_groups"),withFolder:se(r,"with_folder"),withDrive:se(r,"with_drive"),order:u,orderBy:f,scope:g,searchOperatorName:se(r,"search_operator_name")}),y=await h.request({method:"GET",path:zo,query:_,headers:rt(r)});return y.data??y})}catch(i){return Ne(i)}}})}function ns(){return new Proxy({},{get(e,t,n){let r=cn(),i=Reflect.get(r,t,n);return typeof i=="function"?i.bind(r):i}})}function zr(e){let t=[],n=i=>{e(()=>({name:i.name,label:i.name,description:i.description,parameters:i.parameters,async execute(s,a){let d=await i.execute(s,a);if(d&&typeof d=="object"&&"error"in d)throw new Error(d.error);return{content:[{type:"text",text:JSON.stringify(d,null,2)}],details:d}}}),{name:i.name}),t.push(i.name)},r=ns();return kn(r,n),In(r,n),Pn(r,n),gn(r,n),An(r,n),On(r,n),Rn(r,n),console.log(`[wps-xiezuo] OAPI tools registered: [${t.join(", ")}] (${t.length} total)`),t.length}var rs={id:ie,name:"WPS Xiezuo",description:"WPS365 Open Platform channel plugin for OpenClaw",configSchema:Kn(),register(e){Sr(e.runtime);let t=e.logger??{info:()=>{},warn:()=>{},error:()=>{}};if(e.registerChannel({plugin:xn}),typeof e.registerTool=="function"){t.info(`[${ie}] registerTool is available (type: ${typeof e.registerTool})`);try{let n=zr(e.registerTool);t.info(`[${ie}] registered ${n} WPS OAPI tool factories`)}catch(n){t.error(`[${ie}] tool registration failed: ${n}`)}}else t.warn(`[${ie}] registerTool not available (type: ${typeof e.registerTool})`);typeof e.on=="function"?(e.on("before_prompt_build",async(n,r)=>{let i=r;if(i.channelId==="wps-xiezuo"||i.messageProvider==="wps-xiezuo")return{appendSystemContext:["","## WPS \u6D88\u606F\u8DEF\u7531","- \u53D1\u6587\u672C\u5230\u7FA4\u804A/\u7528\u6237\uFF1A`wps_message_send(receiver_type, receiver_id, msg_type='text', content=...)`","- \u6309\u540D\u5B57\u627E\u7FA4\uFF1A\u5148 `wps_chat_find_by_name(keyword=<\u540D\u79F0>)` \u62FF chat_id","- \u56DE\u5F53\u524D\u4F1A\u8BDD\uFF1Areceiver_id \u7528 RawBody \u7684 `chatId`\uFF08\u7FA4\u804A\uFF09\u6216 `SenderId`\uFF08\u5355\u804A\uFF09","","## WPS365 \u65E5\u7A0B / \u65E5\u5386","\u610F\u56FE\u2192\u5DE5\u5177\u3001\u53C2\u6570\u4E0E\u793A\u4F8B\u4EE5 **`skills/wps-calendar/SKILL.md`** \u4E3A\u51C6\uFF08\u968F\u63D2\u4EF6\u52A0\u8F7D\uFF09\u3002\u4EC5\u5141\u8BB8\u901A\u8FC7 **`wps_calendar_*`** \u8C03\u7528\u5F00\u653E\u5E73\u53F0\u7528\u6237\u65E5\u5386\uFF1B**\u7981\u6B62**\u7528 .ics\u3001\u672C\u5730\u811A\u672C\u6216\u5176\u5B83\u6377\u5F84\u5192\u5145\u5DF2\u521B\u5EFA/\u5DF2\u67E5\u8BE2\u3002","## WPS365 \u4E2A\u4EBA\u5F85\u529E","\u610F\u56FE\u4E0E\u53C2\u6570\u4EE5 **`skills/wps-todo/SKILL.md`** \u4E3A\u51C6\u3002\u521B\u5EFA **`wps_todo_create_personal_task`**\uFF0C\u5217\u4E3E **`wps_todo_list_personal_tasks`**\uFF0C\u8BE6\u60C5 **`wps_todo_get_personal_task`**\uFF0C\u66F4\u65B0 **`wps_todo_update_personal_task`**\uFF0C\u72B6\u6001\u66F4\u65B0 **`wps_todo_update_personal_task_status`**\uFF1B`wps_user_id` \u4F7F\u7528 **SenderId**\uFF0C\u672A\u6388\u6743\u65F6\u540C\u6837\u8FD4\u56DE `needsAuth`\u3002","## WPS365 \u4E91\u6587\u6863","\u4E91\u6587\u6863\u53C2\u6570\u4E0E\u7EA6\u675F\u4EE5 **`skills/wps-drive/SKILL.md`** \u4E3A\u51C6\u3002\u83B7\u53D6\u76D8\u5217\u8868\u7528 **`wps_drive_list_drives`**\uFF08\u53C2\u6570\u540D `allotee_type/allotee_id`\uFF09\uFF1B\u65B0\u5EFA\u6587\u4EF6\uFF08\u5939\uFF09\u7528 **`wps_drive_create_file`**\uFF1B\u6587\u6863\u5185\u5BB9\u62BD\u53D6\u7528 **`wps_drive_extract_file_content`**\uFF1B\u83B7\u53D6\u6587\u4EF6\u4FE1\u606F\u7528 **`wps_drive_get_file_meta`**\uFF1B\u6587\u4EF6\u641C\u7D22\u7528 **`wps_drive_search_files`**\u3002`wps_user_id` \u5FC5\u987B\u4F7F\u7528 **SenderId**\uFF0C\u672A\u6388\u6743\u65F6\u5DE5\u5177\u8FD4\u56DE `needsAuth` \u5E76\u81EA\u52A8\u4E0B\u53D1\u6388\u6743\u5361\u7247\u3002","`wps_user_id` \u4F7F\u7528\u5165\u7AD9\u4E0A\u4E0B\u6587\u7684 **SenderId**\uFF1B\u4E0D\u8981\u4E3A\u6B64\u8C03\u7528 `wps_user_search`\u3002\u672A\u6388\u6743\u65F6\u5DE5\u5177\u8FD4\u56DE `needsAuth` \u5E76\u5DF2\u53D1\u6388\u6743\u5361\u7247\uFF0C\u5F15\u5BFC\u7528\u6237\u5B8C\u6210\u6388\u6743\u540E\u518D\u8BD5\u3002","","## \u53D1\u56FE\u7247/\u6587\u4EF6\uFF08\u672C\u5730\u5DF2\u4E0B\u8F7D\u8DEF\u5F84\uFF09","\u5F53 Body \u4E2D\u51FA\u73B0 `[\u5DF2\u4E0B\u8F7D\u56FE\u7247: <\u8DEF\u5F84>]` \u6216 `[\u5DF2\u4E0B\u8F7D\u6587\u4EF6: <\u8DEF\u5F84>]`\uFF0C\u8981\u53D1\u56DE\u7ED9\u7528\u6237\u65F6\uFF1A","\u7528 `message` \u5DE5\u5177\uFF08\u53C2\u6570\u540D\u662F `to` \u548C `message`\uFF0C\u4E0D\u662F receiver_id \u548C content\uFF09\uFF1A",' message(action="send", to="user:<SenderId>", message="\u4E3A\u60A8\u53D1\u56DE\u56FE\u7247", media="<\u8DEF\u5F84>")',"\u26A0\uFE0F `to` \u53C2\u6570\u662F**\u5FC5\u586B**\u7684\uFF01\u7EDD\u5BF9\u4E0D\u80FD\u7701\u7565 `to`\uFF0C\u5426\u5219\u4F1A\u5BFC\u81F4 deMixValue \u9519\u8BEF\u3002","\u26A0\uFE0F `to` \u7684\u503C\u5FC5\u987B\u662F `user:<\u7528\u6237ID>` \u6216 `chat:<\u7FA4ID>`\uFF0C\u4ECE RawBody \u4E2D\u7684 SenderId \u6216 chatId \u83B7\u53D6\u3002","\u63D2\u4EF6\u4F1A\u81EA\u52A8\u5B8C\u6210\u4E0A\u4F20\u548C\u53D1\u9001\uFF0C\u4E0D\u9700\u8981\u4F60\u624B\u52A8\u8C03\u7528 upload\u3002","","## \u6536\u5230\u56FE\u7247/\u6587\u4EF6\u65F6\u7684\u884C\u4E3A\u51C6\u5219","- \u7528\u6237\u76F4\u63A5\u53D1\u9001\u56FE\u7247\u6216\u6587\u4EF6\u65F6\uFF08\u6CA1\u6709\u9644\u52A0\u6587\u5B57\u6307\u4EE4\uFF09\uFF0C**\u4E0D\u8981\u81EA\u52A8\u53D1\u56DE**\uFF0C\u5E94\u8BE2\u95EE\u7528\u6237\u9700\u8981\u4EC0\u4E48\u64CD\u4F5C\u3002","- \u53EA\u6709\u5F53\u7528\u6237\u660E\u786E\u8981\u6C42\u300C\u53D1\u56DE\u6765\u300D\u300C\u8F6C\u53D1\u300D\u300C\u53D1\u7ED9\u6211\u300D\u7B49\u64CD\u4F5C\u65F6\uFF0C\u624D\u4F7F\u7528 message \u5DE5\u5177\u53D1\u56DE\u3002","","## \u4E91\u6587\u4EF6\uFF08cloud file\uFF09","\u5F53 Body \u4E2D\u51FA\u73B0 `[\u5F15\u7528\u4E91\u6587\u4EF6: ...]` \u6216 `[\u4E91\u6587\u4EF6\u94FE\u63A5: ...]` \u65F6\uFF0C\u8FD9\u662F WPS \u4E91\u6587\u4EF6\uFF08\u65E0\u672C\u5730\u8DEF\u5F84\uFF09\u3002","\u8981\u53D1\u56DE\u4E91\u6587\u4EF6\uFF0C\u4F7F\u7528 `wps_message_send` \u5DE5\u5177\uFF0Cmsg_type='file'\uFF0Ccontent \u4F7F\u7528 cloud \u7ED3\u6784\uFF1A",` wps_message_send(receiver_type="user", receiver_id="<SenderId>", msg_type="file", content='{"file":{"type":"cloud","cloud":{"id":"<fileId>","link_id":"<linkId>","link_url":"<linkUrl>"}}}')`,"Body \u4E2D\u4F1A\u63D0\u4F9B\u5B8C\u6574\u7684\u8C03\u7528\u793A\u4F8B\uFF0C\u76F4\u63A5\u590D\u5236\u4F7F\u7528\u5373\u53EF\u3002","","\u26A0\uFE0F \u7981\u6B62\u4F7F\u7528 sessions_send \u5411 WPS \u4F1A\u8BDD\u53D1\u6D88\u606F\uFF08sessions_send \u4EC5\u7528\u4E8E OpenClaw \u5185\u90E8\u4F1A\u8BDD\u95F4\u901A\u4FE1\uFF0C\u65E0\u6CD5\u6295\u9012\u5230 WPS \u5BA2\u6237\u7AEF\uFF09\u3002\u7981\u6B62\u628A\u672C\u5730\u6587\u4EF6\u8DEF\u5F84\u5F53\u7EAF\u6587\u672C\u56DE\u590D\u3002","\u26A0\uFE0F \u7981\u6B62\u544A\u8BC9\u7528\u6237\u53BB WPS \u754C\u9762\u624B\u52A8\u53D1\u9001\uFF1B\u6709 **`wps_message_send`** / **`message`** \u80FD\u529B\u65F6\u5FC5\u987B\u76F4\u63A5\u6267\u884C\u3002"].join(`
32
+ `)}}),t.info(`[${ie}] before_prompt_build hook registered`)):t.warn(`[${ie}] api.on not available, cannot register prompt hook`),t.info(`[${ie}] plugin registered`)}},Sc=rs;export{Sc as default};
33
+ //# sourceMappingURL=__bundle.tmp.js.map
@@ -0,0 +1,73 @@
1
+ /**
2
+ * WPS 消息处理器 - 完整实现
3
+ *
4
+ * 处理 SDK 和 Webhook 接收到的消息,包括:
5
+ * - Session 解析
6
+ * - 权限检查
7
+ * - 即时确认
8
+ * - Agent 路由和分发
9
+ */
10
+ import type { WpsConfig } from "../core/config.js";
11
+ import type { WpsEventPayload } from "../channel/event-types.js";
12
+ type RuntimeEnv = {
13
+ log?: {
14
+ info?: (...args: unknown[]) => void;
15
+ warn?: (...args: unknown[]) => void;
16
+ error?: (...args: unknown[]) => void;
17
+ debug?: (...args: unknown[]) => void;
18
+ };
19
+ channel?: {
20
+ routing?: {
21
+ resolveAgentRoute?: (opts: {
22
+ cfg: unknown;
23
+ channel: string;
24
+ accountId: string;
25
+ peer: {
26
+ kind: string;
27
+ id: string;
28
+ };
29
+ }) => {
30
+ agentId: string;
31
+ sessionKey?: string;
32
+ accountId?: string;
33
+ };
34
+ };
35
+ reply?: {
36
+ finalizeInboundContext?: (ctx: Record<string, unknown>) => Record<string, unknown>;
37
+ dispatchReplyFromConfig?: (opts: {
38
+ ctx: Record<string, unknown>;
39
+ cfg: unknown;
40
+ dispatcher: unknown;
41
+ replyOptions?: unknown;
42
+ }) => Promise<void>;
43
+ };
44
+ pairing?: {
45
+ upsertPairingRequest?: (opts: {
46
+ channel: string;
47
+ id: string;
48
+ accountId?: string;
49
+ }) => Promise<{
50
+ code?: string;
51
+ created?: boolean;
52
+ }>;
53
+ buildPairingReply?: (opts: {
54
+ channel: string;
55
+ idLine: string;
56
+ code: string;
57
+ }) => string;
58
+ };
59
+ };
60
+ [key: string]: unknown;
61
+ };
62
+ type HandleMessageParams = {
63
+ config: WpsConfig;
64
+ runtime?: RuntimeEnv;
65
+ eventPayload: WpsEventPayload;
66
+ cfg: unknown;
67
+ };
68
+ /**
69
+ * 处理入站消息
70
+ */
71
+ export declare function handleWpsMessage(params: HandleMessageParams): Promise<void>;
72
+ export {};
73
+ //# sourceMappingURL=handler.d.ts.map
@@ -0,0 +1,17 @@
1
+ /**
2
+ * 入站消息内容归一化。
3
+ *
4
+ * 将 WPS 的 8 种消息类型统一解析为 NormalizedInboundMessage。
5
+ * 从 v1 monitor.ts 迁移,对标飞书 src/messaging/inbound/content-parser.ts。
6
+ */
7
+ import type { WpsEventPayload, NormalizedInboundMessage } from "../../channel/event-types.js";
8
+ export declare function parseCardContent(content: Record<string, unknown>): {
9
+ headerTitle: string;
10
+ plainText: string;
11
+ } | null;
12
+ export type MessageMediaContext = {
13
+ chatId?: string;
14
+ messageId?: string;
15
+ };
16
+ export declare function normalizeInboundMessage(message: WpsEventPayload["message"], mediaCtx?: MessageMediaContext): NormalizedInboundMessage;
17
+ //# sourceMappingURL=content-parser.d.ts.map
@@ -0,0 +1,44 @@
1
+ /**
2
+ * WPS 入站消息处理器。
3
+ *
4
+ * Webhook 与 SDK 共用:接收统一 WpsEventPayload → 会话解析 → 策略校验 → 路由 → 回复分发。
5
+ * 从 v1 monitor.ts handleWpsInboundAsync 迁移,对标飞书 src/messaging/inbound/handler.ts。
6
+ */
7
+ import type { WpsEventPayload } from "../../channel/event-types.js";
8
+ import type { WpsConfig } from "../../core/config.js";
9
+ import type { AppCredentials } from "../../core/token-store.js";
10
+ import type { LogFacade, ChannelRuntimeSurface } from "../../channel/types.js";
11
+ export type HandleInboundParams = {
12
+ /** 顶层 OpenClaw 配置 */
13
+ cfg: Record<string, unknown>;
14
+ /** 当前处理的渠道账号 ID */
15
+ accountId: string;
16
+ /** OpenClaw channelRuntime(来自 ctx.channelRuntime),包含 reply/routing/session 等 */
17
+ channelRuntime?: ChannelRuntimeSurface;
18
+ /** WPS 渠道配置 */
19
+ wpsCfg: WpsConfig;
20
+ /** 应用凭证 */
21
+ creds: AppCredentials;
22
+ /** 统一入站事件 */
23
+ eventPayload: WpsEventPayload;
24
+ /** 日志 */
25
+ log?: LogFacade;
26
+ };
27
+ /**
28
+ * 处理单条入站事件。Webhook 和 SDK 长连接统一调用此函数。
29
+ *
30
+ * 流程:
31
+ * 1. Topic 过滤
32
+ * 2. 事件标准化 + 会话解析
33
+ * 3. 群聊 @提及 校验
34
+ * 4. 幂等去重
35
+ * 5. DM 策略(disabled / open / allowlist / pairing)
36
+ * 6. 群聊 groupPolicy 校验
37
+ * 7. Agent 路由
38
+ * 8. 入站上下文构建
39
+ * 9. Thinking Reaction Indicator(替代 InstantAck)
40
+ * 10. Agent 分发(reply dispatcher)
41
+ * 11. Thinking Reaction 清理(finally)
42
+ */
43
+ export declare function handleInbound(params: HandleInboundParams): Promise<void>;
44
+ //# sourceMappingURL=handler.d.ts.map
@@ -0,0 +1,5 @@
1
+ export { handleInbound } from "./handler.js";
2
+ export type { HandleInboundParams } from "./handler.js";
3
+ export { normalizeInboundMessage, parseCardContent } from "./content-parser.js";
4
+ export type { MessageMediaContext } from "./content-parser.js";
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,43 @@
1
+ /**
2
+ * 入站媒体预取。
3
+ *
4
+ * 在 agent dispatch 之前,自动把带 storage_key 的附件从 WPS 云端下载到本地临时文件,
5
+ * Body 中只注入文件路径 + 元信息,不内联 base64(节省 token)。
6
+ * 模型如需读取图片可用 read(path) 工具。
7
+ */
8
+ import type { WpsClient } from "../../core/wps-client.js";
9
+ import type { InboundAttachmentMeta } from "../../channel/event-types.js";
10
+ import type { LogFacade } from "../../channel/types.js";
11
+ export type PrefetchedMedia = {
12
+ storageKey: string;
13
+ displayName: string;
14
+ mimeType: string;
15
+ size: number;
16
+ localPath: string;
17
+ /** UTF-8 文本内容(仅 text 类附件、且大小 ≤ MAX_INLINE_TEXT_BYTES 时填充) */
18
+ inlineText?: string;
19
+ };
20
+ export type PrefetchResult = {
21
+ fetched: PrefetchedMedia[];
22
+ skipped: {
23
+ storageKey: string;
24
+ reason: string;
25
+ }[];
26
+ };
27
+ export declare function prefetchMediaAttachments(opts: {
28
+ client: WpsClient;
29
+ chatId: string;
30
+ messageId: string;
31
+ attachments: InboundAttachmentMeta[];
32
+ log?: LogFacade;
33
+ }): Promise<PrefetchResult>;
34
+ /**
35
+ * 将预取结果转为 Body 段落(只含路径和元信息,不含 base64)。
36
+ * 同时嵌入工具使用指令,引导模型使用 WPS 专用工具。
37
+ */
38
+ export declare function buildPrefetchedBodySegment(prefetched: PrefetchResult, context?: {
39
+ chatId?: string;
40
+ messageId?: string;
41
+ fromQuote?: boolean;
42
+ }): string;
43
+ //# sourceMappingURL=media-prefetch.d.ts.map