From 9657107a2101263ca867934dfc19ca1c21223a73 Mon Sep 17 00:00:00 2001 From: xmanrui <841206367@qq.com> Date: Tue, 25 Aug 2026 00:52:54 +0800 Subject: [PATCH] chore: release v2.2.0 --- CHANGELOG.md | 19 ++++++++++++++++++- lib/index.js | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 4 files changed, 22 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index feeaf2a..afd4605 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,22 @@ This file records the notable changes in each dsh-im release. Its format follows ## [Unreleased] +## [2.2.0] - 2026-08-25 + +### Added / 新增 + +- 所有聊天渠道新增 `/reasoninglist`、`/reasonings` 和 `/reasoning` 命令,可查看当前模型支持的推理等级、切换指定等级或恢复模型默认值;`/model` 也支持在切换模型时同时指定推理等级。 + Added `/reasoninglist`, `/reasonings`, and `/reasoning` commands across all chat channels for listing the current model's reasoning efforts, selecting an effort, or restoring the model default; `/model` can also select a reasoning effort while switching models. + +### Fixed / 修复 + +- 当浏览器使用不兼容的回环地址访问 Web 设置页并触发 RPC 403 时,插件现在会提供保留当前端口的 `localhost` 恢复入口,避免各 IM 渠道配置页面持续请求失败。 + When an incompatible loopback address causes RPC 403 responses in the Web settings UI, the plugin now offers a `localhost` recovery link that preserves the current port, preventing persistent request failures across IM channel settings. +- 微信长回复现在在桥接层和运行时统一按腾讯 iLink 的 1,800 字符限制分段发送,避免超长回复被平台拒绝或截断。 + Long WeChat replies are now split consistently at Tencent iLink's 1,800-character limit across the bridge and runtime, preventing oversized replies from being rejected or truncated. +- Telegram Bot API 无法连接时会给出明确的代理诊断提示,并补充 Node 环境代理、`HTTPS_PROXY` 和 `NO_PROXY` 的中英文配置说明。 + Telegram Bot API connection failures now provide actionable proxy diagnostics, with bilingual setup guidance for Node environment proxy support, `HTTPS_PROXY`, and `NO_PROXY`. + ## [2.1.0] - 2026-08-24 ### Added / 新增 @@ -269,7 +285,8 @@ This file records the notable changes in each dsh-im release. Its format follows - 改进 npm 发布包结构,保留 CLI 入口并避免安装脚本拦截。 Improved npm package contents to preserve the CLI entry point and avoid install-script blocking. -[Unreleased]: https://github.com/xmanrui/dsh-im/compare/v2.1.0...HEAD +[Unreleased]: https://github.com/xmanrui/dsh-im/compare/v2.2.0...HEAD +[2.2.0]: https://github.com/xmanrui/dsh-im/compare/v2.1.0...v2.2.0 [2.1.0]: https://github.com/xmanrui/dsh-im/compare/v2.0.1...v2.1.0 [2.0.1]: https://github.com/xmanrui/dsh-im/compare/v2.0.0...v2.0.1 [2.0.0]: https://github.com/xmanrui/dsh-im/compare/v1.5.0...v2.0.0 diff --git a/lib/index.js b/lib/index.js index 6da94f8..33fa3f6 100644 --- a/lib/index.js +++ b/lib/index.js @@ -313,7 +313,7 @@ ${s.join(` \u8BE5\u5DE5\u4F5C\u533A\u6682\u65E0\u4F1A\u8BDD\u3002`,{workspace:c}));return}let I=Math.ceil(g.length/Pg),d=Number.isSafeInteger(e)&&e>0?Math.min(e,I-1):0,B=new Set((this.#r.watchEntries?.(o)??[]).map(Q=>Q.sessionId)),f=g.slice(d*Pg,(d+1)*Pg);this.#ae(o,{kind:"sessions",sessions:f.map(Q=>({...Q,watched:B.has(Q.sessionId)}))}),await this.#j(t,Qz(c,g,d,g.length,B),{key:o,updateMessageId:a,sessionWorkspace:r.workspace,sessionPage:d})}catch(A){this.#m.warn?.("[dsh-feishu] session list failed:",A.message),await this.#D(t,w("\u6682\u65F6\u65E0\u6CD5\u83B7\u53D6\u4F1A\u8BDD\u5217\u8868\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002"))}}async#be({chatId:t,key:o},{updateMessageId:i=null}={}){try{let{current:e,paths:a}=await Th(this.#t,{signal:this.#K()});this.#ae(o,{kind:"workspaces",paths:a}),await this.#j(t,yz(a,e),{key:o,updateMessageId:i})}catch(e){this.#m.warn?.("[dsh-feishu] workspace list failed:",e.message),await this.#D(t,w("\u6682\u65F6\u65E0\u6CD5\u83B7\u53D6\u5DE5\u4F5C\u533A\u5217\u8868\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002"))}}async#Je(t,o,i,{updateMessageId:e=null}={}){try{let a=await this.#t.bindWorkspaceSession(t,i),A=String(a?.title??"").replace(/\s+/gu," ").trim()||w("\u6682\u65E0\u6807\u9898");await this.#D(o,w(`\u5DF2\u7ED1\u5B9A\u4F1A\u8BDD\u300C{title}\u300D ID\uFF1A{id}`,{title:A,id:a?.sessionId??i})),await this.#V(t,o,{updateMessageId:e})}catch(a){await this.#D(o,w("\u7ED1\u5B9A\u5931\u8D25\uFF1A{message}",{message:hC(a)}))}}async#qe(t,o,i,{updateMessageId:e=null}={}){try{let a=await this.#t.switchWorkspace(i);await this.#D(o,w("\u5DE5\u4F5C\u533A\u5DF2\u5207\u6362\u4E3A\uFF1A{workspace}",{workspace:a})),await this.#V(t,o,{updateMessageId:e})}catch(a){await this.#D(o,w("\u5207\u6362\u5931\u8D25\uFF1A{message}",{message:hC(a)}))}}#Me(t,o,i){if(!(!i.key||!t)&&(this.#x.delete(t),this.#x.set(t,{key:i.key,chatId:o,sessionWorkspace:typeof i.sessionWorkspace=="string"&&i.sessionWorkspace?i.sessionWorkspace:null,sessionPage:Number.isSafeInteger(i.sessionPage)&&i.sessionPage>=0?i.sessionPage:0}),this.#x.size>200)){let e=this.#x.keys().next().value;e!==void 0&&this.#x.delete(e)}}async#j(t,o,i={}){let e=CA(i.updateMessageId);if(e)try{let r=await this.#e.im.v1.message.patch({path:{message_id:e},data:{content:o}});if(r?.code&&r.code!==0)throw new Error(`Feishu card update failed: ${r.msg||r.code}`);return this.#Me(e,t,i),e}catch(r){this.#m.warn?.("[dsh-feishu] card update failed:",r?.code??r?.message??r,"sending new")}let a=await this.#e.im.v1.message.create({params:{receive_id_type:"chat_id"},data:{receive_id:t,msg_type:"interactive",content:o}});if(a?.code&&a.code!==0)throw new Error(`Feishu card send failed: ${a.msg||a.code}`);let A=CA(a?.data?.message_id);return this.#Me(A,t,i),A}async#V(t,o,{updateMessageId:i=null}={}){let e=null,a=null;try{let Y=this.#r.sessionFor(t);if(typeof Y=="string"&&Y){e=Y;let j=this.#t.workspaceSession?.(Y);a=CA(j?.title)??CA(j?.name)??CA(j?.displayName)}}catch{}let A=this.#K(),r=Th(this.#t,{signal:A}).catch(()=>{let Y=typeof this.#t.currentWorkspace=="function"?this.#t.currentWorkspace():null;return{current:Y,paths:Y?[Y]:[]}}),s=(async()=>{let Y=typeof this.#t.currentWorkspace=="function"?this.#t.currentWorkspace():null;if(!Y||typeof this.#t.listWorkspaceSessions!="function")return[];try{let j=await this.#t.listWorkspaceSessions(Y,{signal:A});return this.#ie(Array.isArray(j?.sessions)?j.sessions:[])}catch{return[]}})(),g=(async()=>{try{let Y=await this.#t.agentPresetSettings({signal:A});return{...Y.agentPresetCatalog,_currentId:Y.agentPreset}}catch{return null}})(),c=(async()=>{try{if(e){let Y=this.#t.workspaceSession?.(e);if(typeof Y?.models=="function")return await Y.models({signal:A})}return await this.#t.listModels({signal:A})}catch{return null}})(),[I,d,B,f]=await Promise.all([r,s,g,c]),Q=Array.isArray(I.paths)?I.paths:[],y=I.current??null,m=d.find(Y=>Y.sessionId===e),_=e?CA(m?.title)??CA(m?.name)??a??e:null,N=d.map(Y=>({id:Y.sessionId,title:Y.title??Y.name??Y.sessionId})).slice(0,20);e&&(N=N.filter(Y=>Y.id!==e),N.unshift({id:e,title:_??e}),N=N.slice(0,20));let G=this.#r?.includesArchivedSessions?.()??!1;this.#ae(t,{kind:"menu",chatId:o}),await this.#j(o,dz({workspaces:Q,currentWorkspace:y,currentSession:e?{id:e,title:_}:null,sessions:N,archiveVisible:G,presetCatalog:B,modelCatalog:f}),{key:t,updateMessageId:i})}async#dA(t,o){try{if(typeof this.#t.workspaceSession=="function"){let e=this.#t.workspaceSession(o);if(e&&typeof e=="object"){let a=CA(e.title)??CA(e.name)??CA(e.displayName);if(a)return a}}let i=typeof this.#t.currentWorkspace=="function"?this.#t.currentWorkspace():null;if(i&&typeof this.#t.listWorkspaceSessions=="function"){let e=await this.#t.listWorkspaceSessions(i),a=(Array.isArray(e?.sessions)?e.sessions:[]).find(A=>A.sessionId===o);if(a){let A=CA(a.title)??CA(a.name);if(A)return A}}}catch{}return null}async#ze(t,o,{updateMessageId:i=null}={}){try{let e=await this.#t.agentPresetSettings({signal:this.#K()}),a=e.agentPresetCatalog;a._currentId=e.agentPreset,await this.#j(o,hz(a),{key:t,updateMessageId:i})}catch(e){this.#m.warn?.("[dsh-feishu] preset card failed:",e.message),await this.#D(o,w("\u6682\u65F6\u65E0\u6CD5\u83B7\u53D6\u9884\u8BBE\u5217\u8868\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002"))}}async#Ve(t,o,{updateMessageId:i=null}={}){try{let e=this.#K();await this.#t.ensureRunning({signal:e});let a=this.#r?.sessionFor?.(t),A;if(typeof a=="string"&&a){let r=this.#t.workspaceSession(a);r?.models&&(A=await r.models({signal:e}))}A||(A=await this.#t.listModels({signal:e})),await this.#j(o,Ez(A),{key:t,updateMessageId:i})}catch(e){this.#m.warn?.("[dsh-feishu] model card failed:",e.message),await this.#D(o,w("\u6682\u65F6\u65E0\u6CD5\u83B7\u53D6\u6A21\u578B\u5217\u8868\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002"))}}async#We(t,o){try{await this.#t.ensureRunning({signal:this.#S});let i=[w("\u8FDE\u63A5\u6B63\u5E38")],e=typeof this.#t.currentWorkspace=="function"?this.#t.currentWorkspace():null;e&&i.push(w("\u5DE5\u4F5C\u533A\uFF1A{workspace}",{workspace:e}));let a=typeof this.#t.agentPresetSettings=="function"?await this.#t.agentPresetSettings({signal:this.#S}).catch(()=>null):null;if(a){let A=a.agentPresetCatalog?.items?.find(r=>r.id===a.agentPreset);i.push(w("\u9884\u8BBE\uFF1A{preset}",{preset:A?`${A.label}\uFF08${A.id}\uFF09`:a.agentPreset||w("\u8DDF\u968F\u9ED8\u8BA4")}))}await this.#D(o,i.join(` `))}catch(i){this.#m.warn?.("[dsh-feishu] status text failed:",i.message),await this.#D(o,w("\u6682\u65F6\u65E0\u6CD5\u83B7\u53D6\u7CFB\u7EDF\u72B6\u6001\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002"))}}async#Ze(t,o,{updateMessageId:i=null}={}){try{let e=this.#K();await this.#t.ensureRunning({signal:e});let a={connected:!0,workspace:null,preset:null,model:null,sessionCount:0};try{let A=typeof this.#t.currentWorkspace=="function"?this.#t.currentWorkspace():null;a.workspace=A||w("\u672A\u77E5")}catch{}try{let A=await this.#t.agentPresetSettings({signal:e}),r=A.agentPresetCatalog.items.find(s=>s.id===A.agentPreset);a.preset=r?`${r.label}\uFF08${r.id}\uFF09`:A.agentPreset||w("\u8DDF\u968F\u9ED8\u8BA4")}catch{}try{let A=this.#r?.sessionFor?.(t);if(typeof A=="string"&&A){let r=this.#t.workspaceSession(A);if(r?.models){let s=await r.models({signal:e});s.current&&(a.model=`${s.current.provider}/${s.current.model}`)}}}catch{}try{let A=typeof this.#t.currentWorkspace=="function"?this.#t.currentWorkspace():null;if(A){let r=await this.#t.listWorkspaceSessions(A,{signal:e});Array.isArray(r?.sessions)&&(a.sessionCount=r.sessions.length)}}catch{}await this.#j(o,Cz(a),{key:t,updateMessageId:i})}catch(e){this.#m.warn?.("[dsh-feishu] status card failed:",e.message),await this.#D(o,w("\u6682\u65F6\u65E0\u6CD5\u83B7\u53D6\u7CFB\u7EDF\u72B6\u6001\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002"))}}async#Xe(t,o,{updateMessageId:i=null}={}){await this.#j(o,Bz(d_e.map(e=>w(e))),{key:t,updateMessageId:i})}async#$e(t,o){try{let i=await ei("/compact",this.#t,this.#r,t,{signal:this.#S});await this.#D(o,i?.message||w("\u4E0A\u4E0B\u6587\u538B\u7F29\u5931\u8D25\u3002"))}catch(i){this.#m.warn?.("[dsh-feishu] compact failed:",i.message,i.code),await this.#D(o,w("\u4E0A\u4E0B\u6587\u538B\u7F29\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002"))}}async#eA(t,o){try{let i=await Ai("/stop",this.#t,this.#r,t,{signal:this.#S,control:{owner:this,key:t}});i?.stopped&&await Promise.allSettled([this.#me(t),this.#w.closeRoute(t)]),await this.#D(o,i?.message||w("/stop \u6267\u884C\u5B8C\u6210\u3002"))}catch(i){this.#m.warn?.("[dsh-feishu] stop failed:",i.message),await this.#D(o,w("\u505C\u6B62\u4EFB\u52A1\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002"))}}async#AA(t,o,{updateMessageId:i=null}={}){let e=!!this.#r.sessionFor?.(t);this.#ae(t,{kind:"steer"}),await this.#j(o,wz({hasSession:e}),{key:t,updateMessageId:i})}async#pe(t,o){let{key:i,chatId:e}=t,a=await Ai(`/steer ${o}`,this.#t,this.#r,i,{signal:this.#S,pendingInteraction:this.#Z(i),control:{owner:this,key:i}});await this.#D(e,a?.message||w("\u5DF2\u63D0\u4EA4\u8865\u5145\u6307\u4EE4\u3002"))}async#_e(t,o,{updateMessageId:i=null}={}){try{let e=await ti("/preset --default",this.#t,this.#r,t,{signal:this.#S});for(let a of e?.messages??[e?.message])a&&await this.#D(o,a)}catch(e){this.#m.warn?.("[dsh-feishu] preset default failed:",e.message),await this.#D(o,w("\u9884\u8BBE\u91CD\u7F6E\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002"));return}try{await this.#V(t,o,{updateMessageId:i})}catch(e){this.#m.warn?.("[dsh-feishu] menu refresh failed after preset reset:",e.message)}}async#tA(t,o,i,{updateMessageId:e=null}={}){try{let a=/^\d+$/u.test(i)?`id:${i}`:i,A=await ti(`/preset ${a}`,this.#t,this.#r,t,{signal:this.#S});for(let r of A?.messages??[A?.message])r&&await this.#D(o,r)}catch(a){this.#m.warn?.("[dsh-feishu] preset select failed:",a.message),await this.#D(o,w("\u9884\u8BBE\u5207\u6362\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002"));return}try{await this.#V(t,o,{updateMessageId:e})}catch(a){this.#m.warn?.("[dsh-feishu] menu refresh failed after preset select:",a.message)}}async#rA(t,o,i,{updateMessageId:e=null}={}){try{let a=await Oi(`/model ${i}`,this.#t,this.#r,t,{signal:this.#S,pendingInteraction:this.#Z(t),control:{owner:this,key:t}});for(let A of a?.messages??[a?.message])A&&await this.#D(o,A)}catch(a){this.#m.warn?.("[dsh-feishu] model select failed:",a.message),await this.#D(o,w("\u6A21\u578B\u5207\u6362\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002"));return}try{await this.#V(t,o,{updateMessageId:e})}catch(a){this.#m.warn?.("[dsh-feishu] menu refresh failed after model select:",a.message)}}#Te(){if(this.#U||typeof this.#t?.watchHarnessEvents!="function"||this.#S?.aborted)return;let t=this.#S??new AbortController().signal;try{this.#U=this.#t.watchHarnessEvents({signal:t,onSessionEvent:o=>this.#nA(o),onReconnect:()=>{this.#sA()}}),Promise.resolve(this.#U).catch(o=>{t.aborted||this.#m.warn?.("[dsh-feishu] event watcher stopped:",o.message)})}catch(o){this.#U=null,this.#m.warn?.("[dsh-feishu] event watcher failed to start:",o.message)}}#Ne(t,o){let i=this.#Y.get(t)??Promise.resolve(),e;return e=i.then(o,o).catch(a=>{this.#S?.aborted||this.#m.warn?.("[dsh-feishu] completion event failed:",a.message)}).finally(()=>{this.#Y.get(t)===e&&this.#Y.delete(t)}),this.#Y.set(t,e),e}#de(t=Date.now()){let o=0;for(let[i,e]of this.#H){for(let[a,A]of e)(!Number.isSafeInteger(A?.arrivalAt)||A.arrivalAt<0||A.arrivalAt+a_e<=t)&&e.delete(a);for(;e.size>o_e;){let a=e.keys().next().value;if(a===void 0)break;e.delete(a)}e.size===0?this.#H.delete(i):o+=e.size}for(;this.#H.size>i_e;){let i=this.#H.keys().next().value;if(i===void 0)break;o-=this.#H.get(i)?.size??0,this.#H.delete(i)}for(;o>n_e;){let i=this.#H.keys().next().value;if(i===void 0)break;let e=this.#H.get(i),a=e?.keys().next().value;if(a===void 0){this.#H.delete(i);continue}e.delete(a),o-=1,e.size===0&&this.#H.delete(i)}}#aA(t,o,i=Date.now()){this.#de(i);let e=this.#H.get(t);e||(e=new Map);let a=o?.data?.reason,A=typeof a=="string"?a:typeof a?.kind=="string"?{kind:a.kind}:null;e.delete(o.seq),e.set(o.seq,{arrivalAt:i,event:{type:"turn/end",seq:o.seq,...Number.isSafeInteger(o.time)&&o.time>=0?{time:o.time}:{},data:{reason:A}}}),this.#H.delete(t),this.#H.set(t,e),this.#de(i)}async#iA(t,{workspaceHint:o=null,signal:i=this.#S}={}){if(typeof t!="string"||t==="")return{error:w("\u7528\u6CD5\uFF1A/watch ")};let e=/^\d{1,4}$/.test(t)?Number(t):null,a=typeof this.#t?.currentWorkspace=="function"?this.#t.currentWorkspace():null,A=async s=>{let g=await this.#t.listWorkspaceSessions(s,{signal:i});return Array.isArray(g?.sessions)?g.sessions:[]};if(e!==null){if(!a)return{error:w("\u5F53\u524D\u673A\u5668\u4EBA\u6CA1\u6709\u53EF\u7528\u7684\u5DE5\u4F5C\u533A\uFF0C\u65E0\u6CD5\u6309\u5E8F\u53F7\u89E3\u6790\u4F1A\u8BDD\u3002")};let s=this.#ie(await A(a)),g=s[e-1];return g?.sessionId?{sessionId:g.sessionId,title:g.title??w("\u6682\u65E0\u6807\u9898"),workspace:a,...qo(g.lastSeq)?{lastSeq:g.lastSeq}:{}}:{error:w("\u5F53\u524D\u5DE5\u4F5C\u533A\u53EA\u6709 {count} \u4E2A\u4F1A\u8BDD\u3002",{count:s.length})}}let r;if(CA(o))r=[o];else{let s=typeof this.#t?.listWorkspaces=="function"?(await this.#t.listWorkspaces({signal:i})).filter(g=>g!==a):[];r=[a,...s].filter(Boolean)}for(let s of r){let c=(await A(s)).find(I=>I.sessionId===t);if(c)return{sessionId:t,title:c.title??w("\u6682\u65E0\u6807\u9898"),workspace:s,...qo(c.lastSeq)?{lastSeq:c.lastSeq}:{}}}return{error:w("\u6CA1\u6709\u627E\u5230\u8FD9\u4E2A\u4F1A\u8BDD\uFF0C\u8BF7\u7528 /sessionlist \u67E5\u770B\u53EF\u7528\u4F1A\u8BDD\u3002")}}async#oA(t){let o=CA(t)??(typeof this.#t?.currentWorkspace=="function"?CA(this.#t.currentWorkspace()):null);if(!o||typeof this.#t?.listWorkspaceSessions!="function")return new Map;let i=await this.#t.listWorkspaceSessions(o,{signal:this.#K()});return new Map(this.#ie(Array.isArray(i?.sessions)?i.sessions:[]).filter(e=>CA(e?.sessionId)).map(e=>[e.sessionId,{sessionId:e.sessionId,title:e.title??e.name??w("\u6682\u65E0\u6807\u9898"),workspace:o,...qo(e.lastSeq)?{lastSeq:e.lastSeq}:{}}]))}#Re(t){let o=this.#J.get(t);if(o)return o.requested=!0,o.promise;let i={requested:!0,promise:null};return this.#J.set(t,i),i.promise=Promise.resolve().then(async()=>{try{do i.requested=!1,await this.#Ne(t,()=>this.#ve(t));while(i.requested&&!this.#S?.aborted)}finally{this.#J.get(t)===i&&this.#J.delete(t)}}),i.promise}async#he(t,o,i,{notify:e=!0,validatedTarget:a=null,workspaceHint:A=null}={}){let r=Date.now(),s=async Q=>{e&&await this.#D(o,Q).catch(y=>{this.#m.warn?.("[dsh-feishu] watch notification failed:",y.message)})};if(this.#Te(),typeof this.#r?.setWatch!="function")return await s(w("\u5F53\u524D\u72B6\u6001\u5B58\u50A8\u4E0D\u652F\u6301\u5173\u6CE8\u3002")),{ok:!1,changed:!1,reason:"unsupported"};let g;try{g=a?.sessionId===i?a:await this.#iA(i,{workspaceHint:A,signal:A?this.#K():this.#S})}catch(Q){return await s(w("\u65E0\u6CD5\u89E3\u6790\u4F1A\u8BDD\uFF1A{message}",{message:hC(Q)})),{ok:!1,changed:!1,reason:"resolve"}}if(g.error)return await s(g.error),{ok:!1,changed:!1,reason:"not-found"};let c=this.#r.watchEntries?.(t)??[],I=c.find(Q=>Q.sessionId===g.sessionId);if(!I&&c.length>=by)return await s(w("\u6BCF\u4E2A\u804A\u5929\u6700\u591A\u5173\u6CE8 {count} \u4E2A\u4F1A\u8BDD\u3002",{count:by})),{ok:!1,changed:!1,reason:"limit"};let d=qo(I?.lastSeq)?I.lastSeq:qo(g.lastSeq)?g.lastSeq:null,f=vy(I)??(I?null:r);try{await this.#r.setWatch(t,{sessionId:g.sessionId,title:g.title,chatId:o,lastSeq:d,...f!==null?{watchStartedAt:f}:{}})}catch(Q){return await s(w("\u5173\u6CE8\u5931\u8D25\uFF1A{message}",{message:hC(Q)})),{ok:!1,changed:!1,reason:"persist"}}return(!I||f!==null||!qo(d))&&this.#Re(g.sessionId),await s(w("\u5DF2\u5173\u6CE8\u4F1A\u8BDD\u300C{title}\u300D\uFF0C\u4EFB\u52A1\u5B8C\u6210\u4F1A\u63A8\u9001\u7ED3\u679C\u3002",{title:String(g.title).replace(/\s+/gu," ")})),{ok:!0,changed:!I,entry:this.#r.watchEntry?.(t,g.sessionId)}}async#Ee(t,o,i,{notify:e=!0}={}){let a=async s=>{e&&await this.#D(o,s).catch(g=>{this.#m.warn?.("[dsh-feishu] unwatch notification failed:",g.message)})};if(typeof this.#r?.removeWatch!="function")return{ok:!1,changed:!1,reason:"unsupported"};let A=this.#r.watchEntries?.(t)??[],r=typeof i=="string"&&/^\d{1,4}$/.test(i)?A[Number(i)-1]:A.find(s=>s.sessionId===i);if(!r)return await a(w("\u5173\u6CE8\u5217\u8868\u91CC\u6CA1\u6709\u8FD9\u4E2A\u4F1A\u8BDD\uFF0C\u56DE\u590D /watchlist \u67E5\u770B\u3002")),{ok:!0,changed:!1,reason:"absent"};try{await this.#r.removeWatch(t,r.sessionId),this.#q.delete(`${t}\0${r.sessionId}`)}catch(s){return await a(w("\u53D6\u6D88\u5931\u8D25\uFF1A{message}",{message:hC(s)})),{ok:!1,changed:!1,reason:"persist"}}return await a(w("\u5DF2\u53D6\u6D88\u5173\u6CE8\u300C{title}\u300D\u3002",{title:String(r.title??"").replace(/\s+/gu," ")})),{ok:!0,changed:!0,entry:r}}async#Ce(t,o,{updateMessageId:i=null}={}){let e=this.#r.watchEntries?.(t)??[],a=[],A=null;try{if(A=typeof this.#t?.currentWorkspace=="function"?this.#t.currentWorkspace():null,A&&typeof this.#t?.listWorkspaceSessions=="function"){let r=await this.#t.listWorkspaceSessions(A,{signal:this.#K()});a=this.#ie(Array.isArray(r?.sessions)?r.sessions:[]).map(s=>({sessionId:s.sessionId,title:s.title??s.name??s.sessionId}))}}catch{}this.#ae(t,{kind:"watches",entries:e}),await this.#j(o,mz(e,a),{key:t,updateMessageId:i,sessionWorkspace:A})}#nA({sessionId:t,event:o}){this.#S?.aborted||!t||!o||typeof o!="object"||o.type!=="turn/end"||!CC(o.seq)||(this.#aA(t,o),this.#Ne(t,async()=>{let i=this.#r.keysWatching?.(t)??[],e=i.some(A=>Ry(this.#r.watchEntry?.(A,t))),a=i.some(A=>this.#q.has(`${A}\0${t}`));(e||a)&&await this.#ve(t),await this.#ke(t,o)}))}async#ke(t,o,{keys:i=null}={}){if(this.#S?.aborted||typeof this.#r?.keysWatching!="function")return;let e=o?.data?.reason?.kind??o?.data?.reason??null,a=i??this.#r.keysWatching(t);for(let A of a){if(this.#S?.aborted)return;let r=this.#r.watchEntry?.(A,t),s=`${A}\0${t}`,g=this.#q.get(s);if(CC(g)&&qo(r?.lastSeq)&&r.lastSeq>=g&&(this.#q.delete(s),g=void 0),!(!r?.chatId||Ry(r)||qo(r.lastSeq)&&r.lastSeq>=o.seq||CC(g)&&o.seq>g))try{await this.#j(r.chatId,Sz(t,r.title,e),{key:A});let c=this.#r.watchEntry?.(A,t);if(!c||c.chatId!==r.chatId||Ry(c)||qo(c.lastSeq)&&c.lastSeq>=o.seq)continue;await this.#r.setWatch(A,{...c,lastSeq:o.seq}),g===o.seq&&this.#q.delete(s)}catch(c){this.#q.set(s,CC(g)?Math.min(g,o.seq):o.seq),this.#m.warn?.("[dsh-feishu] completion push failed:",c.message)}}}async#ve(t){if(!(this.#S?.aborted||typeof this.#t?.rpc!="function"))try{let o=await this.#t.rpc("session.history",{sessionId:t,maxMessages:20},3e4,{signal:this.#S}),i=E_e(o);this.#de();let e=this.#H.get(t)??new Map,a=new Map(i.map(g=>[g.seq,g]));for(let[g,c]of e)a.has(g)||a.set(g,c.event);let A=[...a.values()].sort((g,c)=>g.seq-c.seq),r=A.at(-1)?.seq??-1,s=typeof this.#r?.keysWatching=="function"?this.#r.keysWatching(t):[];for(let g of s){let c=this.#r.watchEntry?.(g,t);if(!Ry(c))continue;let I=vy(c),d=qo(c.lastSeq)?c.lastSeq:-1,B=I===null?null:A.find(_=>{if(_.seq<=d)return!1;let N=Number.isSafeInteger(_.time)&&_.time>=0?_.time:e.get(_.seq)?.arrivalAt;return Number.isSafeInteger(N)&&N>=I}),f=B?Math.max(d,B.seq-1):Math.max(d,r),Q=this.#r.watchEntry?.(g,t);if(!Q||Q.chatId!==c.chatId||Q.lastSeq!==c.lastSeq||vy(Q)!==I)continue;let{watchStartedAt:y,...m}=Q;await this.#r.setWatch(g,{...m,lastSeq:f})}for(let g of A)g.type==="turn/end"&&await this.#ke(t,g,{keys:s})}catch(o){this.#S?.aborted||this.#m.warn?.(`[dsh-feishu] watch compensation failed for ${t}:`,o.message)}}async#sA(){let t=typeof this.#r?.watchedSessionIds=="function"?this.#r.watchedSessionIds():[];this.#S?.aborted||await Promise.allSettled(t.map(o=>this.#Re(o)))}#ue(t,o,i){return{timeoutMs:this.#O,signal:this.#S,control:{owner:this,key:o},onInteraction:e=>this.#IA(e,{key:o,actor:Py(t),chatId:t.message.chat_id,requiresMention:t.message.chat_type!=="p2p"}),onInteractionResolved:e=>this.#lA(e),files:i}}async#Be(t,o,{deliveryId:i,presentation:e}){let a=[];for(let A of Iz(o)){this.#S?.throwIfAborted();let r=await this.#D(t,A);r&&a.push(r)}return xt({deliveryId:i,presentation:e,providerMessageIds:a})}async#ge(t,o,i=[],e){let a=await to({artifacts:i,baseReceipt:e,deliveryId:e?.deliveryId??i[0]?.deliveryKey??o,aggregatePresentation:e?"feishu-text-and-files":"feishu-files",channelKey:"feishu",signal:this.#S,sendImage:typeof this.#A?.sendImage=="function"?A=>this.#A.sendImage(t,A,{replyTo:o,signal:this.#S}):void 0,sendFile:typeof this.#A?.sendFile=="function"?A=>this.#A.sendFile(t,A,{replyTo:o,signal:this.#S}):void 0,sendFailureNotice:async(A,r)=>({messageId:await this.#D(t,h_e(A?.fileName,r))}),logger:this.#m});return this.#u.artifactsSent=(this.#u.artifactsSent??0)+a.artifactsSent,this.#u.artifactSendErrors=(this.#u.artifactSendErrors??0)+a.artifactSendErrors,a.receipt?{receipt:a.receipt,failureNoticeVisible:a.failureNoticeVisible}:{receipt:xt({deliveryId:o,presentation:"feishu-files"}),failureNoticeVisible:a.failureNoticeVisible}}async#gA(t,o,i){let e=t.message.chat_id,a=t.message.message_id,A=i.content,r=Cr(i)?await Zi(i,{signal:this.#S}):void 0;if(!this.#A?.stream){let{answer:B,artifacts:f=[]}=await $a({harness:this.#t,state:this.#r,key:o,text:A,content:r,createOptions:{signal:this.#S},existsOptions:{signal:this.#S},askOptions:this.#ue(t,o,i.files)}),Q,y=null;try{Q=await this.#Be(e,Ny(B,f),{deliveryId:a,presentation:"feishu-text"})}catch(N){y=N,this.#m.warn?.("[dsh-feishu] final text delivery failed; continuing with result files:",N)}let m=await this.#ge(e,a,f,Q),_=m.receipt.artifacts.some(({outcome:N})=>N==="sent"||N==="unknown");if(y&&!_&&!m.failureNoticeVisible)throw y;return this.#u.streamFallbacks=(this.#u.streamFallbacks??0)+1,m.receipt}let s=!1,g="",c=[],I;try{I=await this.#A.stream(e,{markdown:async B=>{s=!0;let f={...this.#ue(t,o,i.files),onUpdate:async y=>{await B.setContent(this.#pA(y)),this.#u.streamUpdates=(this.#u.streamUpdates??0)+1}},Q=await $a({harness:this.#t,state:this.#r,key:o,text:A,content:r,createOptions:{signal:this.#S},existsOptions:{signal:this.#S},askOptions:f});g=Q.answer,c=Q.artifacts??[],await B.setContent(Ny(g,c))}},{replyTo:a})}catch(B){if(this.#u.streamErrors=(this.#u.streamErrors??0)+1,g||c.length>0){this.#m.warn?.("[dsh-feishu] native stream failed after generation; sending final text:",B.message);let G,Y=null;try{G=await this.#Be(e,Ny(g,c),{deliveryId:a,presentation:"feishu-text-fallback"})}catch(q){Y=q,this.#m.warn?.("[dsh-feishu] fallback text delivery failed; continuing with result files:",q)}let j=await this.#ge(e,a,c,G),x=j.receipt.artifacts.some(({outcome:q})=>q==="sent"||q==="unknown");if(Y&&!x&&!j.failureNoticeVisible)throw Y;return this.#u.streamFallbacks=(this.#u.streamFallbacks??0)+1,j.receipt}if(s)throw B;this.#m.warn?.("[dsh-feishu] native stream unavailable; using text fallback:",B.message);let{answer:f,artifacts:Q=[]}=await $a({harness:this.#t,state:this.#r,key:o,text:A,content:r,createOptions:{signal:this.#S},existsOptions:{signal:this.#S},askOptions:this.#ue(t,o,i.files)}),y,m=null;try{y=await this.#Be(e,Ny(f,Q),{deliveryId:a,presentation:"feishu-text-fallback"})}catch(G){m=G,this.#m.warn?.("[dsh-feishu] fallback text delivery failed; continuing with result files:",G)}let _=await this.#ge(e,a,Q,y),N=_.receipt.artifacts.some(({outcome:G})=>G==="sent"||G==="unknown");if(m&&!N&&!_.failureNoticeVisible)throw m;return this.#u.streamFallbacks=(this.#u.streamFallbacks??0)+1,_.receipt}let d=await this.#ge(e,a,c,xt({deliveryId:a,presentation:"feishu-cardkit",providerMessageIds:I?.messageId?[I.messageId]:[]}));return this.#u.streamResponses=(this.#u.streamResponses??0)+1,d.receipt}async#cA(t,o,i,e,a){this.#S?.throwIfAborted();let A=this.#i.get(i),r=e.claimedReplyMessageId===o;if(!A||A!==e||A.submitting)return this.#fe(t,i)?this.#Qe(t,o):r&&(!A||A!==e)?this.#Qe(t,o):this.#X(t,o,i,a,{releaseMessageId:!1,finalize:!1});if(this.#r.hasSeen(o))return;await this.#r.markSeen(o),this.#u.lastMessageAt=new Date().toISOString(),this.#u.messagesReceived+=1;let s=lC(t);if(!s){await this.#D(t.message.chat_id,w("\u8BF7\u7528\u6587\u5B57\u56DE\u7B54\u5F53\u524D\u95EE\u9898\u3002"));return}let g=this.#i.get(i);if(!g||g!==e||g.submitting){if(this.#fe(t,i)){await this.#D(t.message.chat_id,_y()).catch(()=>{});return}if(r&&(!g||g!==e)){await this.#D(t.message.chat_id,_y());return}return this.#X(t,o,i,a,{releaseMessageId:!1,alreadyRecorded:!0,finalize:!1})}if(g.chatId=t.message.chat_id,g.needsPresentation){try{await this.#ce(g)}catch{this.#u.lastError="\u98DE\u4E66\u4EA4\u4E92\u95EE\u9898\u53D1\u9001\u5931\u8D25\u3002",this.#m.error?.("[dsh-feishu] failed to retry an interaction question"),g.interaction.reconnect?.()}return}let c=g.questions[g.index];if(c){if(g.answers.push(Wa(c,s)),g.index+=1,g.index{});return}g.submitting=!1,g.answers.pop(),g.index-=1,this.#u.lastError="\u56DE\u7B54\u63D0\u4EA4\u5931\u8D25\u3002",this.#m.error?.("[dsh-feishu] failed to answer a Harness interaction"),await this.#D(t.message.chat_id,w("\u56DE\u7B54\u63D0\u4EA4\u5931\u8D25\uFF0C\u8BF7\u91CD\u65B0\u53D1\u9001\u5F53\u524D\u95EE\u9898\u7684\u7B54\u6848\u3002")).catch(()=>{})}}}async#IA(t,{key:o,actor:i,chatId:e,requiresMention:a}){if(await this.#w.handleRequested(t,{key:o,actor:i,requiresMention:a,send:c=>this.#D(e,c)})||t?.kind!=="question")return;let A=t?.payload?.questions,r=typeof t?.interactionId=="string"?t.interactionId:t?.rpcId;if(typeof t.rpcId!="string"||typeof r!="string"||typeof t.sessionId!="string"||!Array.isArray(A)||A.length===0||A.some(c=>!za(c))){this.#m.warn?.("[dsh-feishu] ignored an invalid Harness question interaction");return}if(t.recovered===!0){await t.respond({ok:!1,error:{code:"cancelled",message:"Feishu safely cancelled an interaction left by an earlier client.",details:{}}}),await this.#D(e,w("\u68C0\u6D4B\u5230\u8FD9\u4E2A Session \u4E2D\u9057\u7559\u7684\u5F85\u56DE\u7B54\u95EE\u9898\uFF0C\u5DF2\u5B89\u5168\u53D6\u6D88\u5E76\u7EE7\u7EED\u5904\u7406\u4F60\u521A\u624D\u7684\u6D88\u606F\u3002")).catch(()=>{});return}let s=this.#i.get(o);if(s?.interactionId===r){s.interaction=t,s.needsPresentation&&await this.#ce(s);return}if(this.#c.has(r))return;if(s){await t.respond({ok:!1,error:{code:"cancelled",message:"Feishu is already handling another user interaction.",details:{}}});return}let g={kind:"question",interactionId:r,sessionId:t.sessionId,interaction:t,key:o,actor:i,requiresMention:a,questions:A,answers:[],index:0,chatId:e,queue:null,claimedReplyMessageId:null,submitting:!1,needsPresentation:!0,questionMessageIds:new Set,inactive:!1};this.#i.set(o,g),this.#c.set(g.interactionId,o),await this.#ce(g)}async#lA(t){if(await this.#w.handleResolved(t))return;let o=t?.interactionId;if(t?.kind!=="question"||typeof o!="string")return;let i=this.#c.get(o);if(!i)return;let e=this.#i.get(i);e&&this.#oe(i,e),this.#ye(i,o)}async#ce(t){let o=t.questions[t.index];if(!o)return;let i=await this.#D(t.chatId,Va(o,t.index,t.questions.length,{requiresMention:t.requiresMention}));i&&(t.questionMessageIds.add(i),t.inactive&&this.#oe(t.key,t)),t.needsPresentation=!1}#oe(t,o){let i=Date.now()+jMe;for(let e of o.questionMessageIds??[])this.#s.set(e,{key:t,expiresAt:i})}#fe(t,o){let i=Date.now();for(let[e,a]of this.#s)a.expiresAt<=i&&this.#s.delete(e);for(let e of[t?.message?.parent_id,t?.message?.root_id]){let a=this.#s.get(e);if(a?.key===o&&a.expiresAt>i)return!0}return!1}async#Qe(t,o){this.#r.hasSeen(o)||(await this.#r.markSeen(o),this.#u.lastMessageAt=new Date().toISOString(),this.#u.messagesReceived+=1,await this.#D(t.message.chat_id,_y()).catch(()=>{}))}#Pe(t,o){let i=this.#i.get(t);return!i||o!==void 0&&i.interactionId!==o?null:(this.#i.delete(t),this.#c.delete(i.interactionId),i.inactive=!0,i)}#ye(t,o){return this.#Pe(t,o)!==null}async#me(t){let o=this.#Pe(t);if(!(!o||o.kind!=="question")){this.#oe(t,o);try{await o.interaction.respond({ok:!1,error:{code:"cancelled",message:"The Feishu interaction ended before the user answered.",details:{}}},{signal:AbortSignal.timeout(5e3)})}catch(i){i?.code!=="interaction-not-pending"&&this.#m.warn?.("[dsh-feishu] failed to cancel a pending Harness interaction")}}}#pA(t){return t.type==="text"&&t.text?t.text:t.type==="tool"?t.name==="web_search"?w("_\u6B63\u5728\u641C\u7D22\u7F51\u7EDC\u5E76\u6574\u7406\u4FE1\u606F\u2026_"):w("_\u6B63\u5728\u4F7F\u7528 {name}\u2026_",{name:t.name||w("\u5DE5\u5177")}):w("_{text}_",{text:t.text||w("\u6B63\u5728\u5904\u7406\u2026")})}async#Ge(t,o){if(!this.#A?.addReaction)return null;try{let i=await this.#A.addReaction(t,o);return this.#u.reactionsAdded=(this.#u.reactionsAdded??0)+1,i}catch(i){return this.#u.reactionErrors=(this.#u.reactionErrors??0)+1,this.#m.warn?.(`[dsh-feishu] unable to add ${o} reaction:`,i.message),null}}async#Se(t,o){let i=await o;if(i&&this.#A?.removeReaction)try{await this.#A.removeReaction(t,i),this.#u.reactionsRemoved=(this.#u.reactionsRemoved??0)+1}catch(e){this.#u.reactionErrors=(this.#u.reactionErrors??0)+1,this.#m.warn?.("[dsh-feishu] unable to remove processing reaction:",e.message)}}async#$(t,o,i){await this.#Se(t,o),await this.#Ge(t,i)}async#D(t,o){let i=await this.#e.im.v1.message.create({params:{receive_id_type:"chat_id"},data:{receive_id:t,msg_type:"text",content:JSON.stringify({text:o})}});if(i?.code&&i.code!==0)throw new Error(`Feishu send failed: ${i.msg||i.code}`);return CA(i?.data?.message_id)}};import{createHash as f_e}from"node:crypto";var Fz="stream_md",Q_e="\u5DF2\u8FDE\u63A5 DeepSeek Harness\uFF0C\u6B63\u5728\u601D\u8003\u2026",vz=28e3,Fy=12e4,Lz=new Map([[99991672,["artifact-permission-required","Feishu file delivery requires the im:resource permission."]],[234006,["artifact-too-large","The result file exceeds Feishu's size limit."]],[234010,["artifact-empty","Feishu does not accept empty files."]],[230017,["artifact-provider-rejected","Feishu rejected the uploaded file ownership."]],[230020,["artifact-rate-limited","Feishu temporarily rate-limited file delivery."]],[230049,["artifact-delivery-uncertain","Feishu could not confirm the file message result."]],[230055,["artifact-provider-rejected","Feishu rejected the file message type."]]]);function uI(n,t){if(t?.code&&t.code!==0)throw new Error(`${n} failed: ${t.msg||t.code}`);return t}function Uz(n){let t=[n],o=new Set,i;for(;t.length>0;){let e=t.shift();if(!e||o.has(e))continue;if(typeof e=="object"&&o.add(e),Array.isArray(e)){t.push(...e);continue}let a=Number(e?.code);if(Number.isFinite(a)&&a!==0){if(Lz.has(a))return a;i??=a}t.push(e?.response?.data,e?.data,e?.error,e?.cause)}return i}function uC(n,t,o,{uncertain:i=!1}={}){let e=o==null?void 0:Number(o),a=Number.isFinite(e)&&e!==0?e:Uz(t),A=Number.isFinite(a)?["artifact-provider-rejected",`Feishu rejected file ${n}.`]:i?["artifact-delivery-uncertain","Feishu could not confirm the file message result."]:["artifact-provider-failed",`Feishu file ${n} failed.`],[r,s]=Lz.get(a)??A,g=new Error(s,{cause:t});return g.code=r,Number.isFinite(a)&&(g.providerCode=a),g}function Pz(n,t){if(!Number.isInteger(n)||n<1||n>Fy)throw new TypeError(`${t} must be an integer between 1 and ${Fy}`);return n}function Sk(n){return n?.reason??new DOMException("The operation was aborted","AbortError")}function y_e(n){let t=new Error(`Feishu file ${n} timed out.`);return t.code="provider-timeout",t}function Gz(n,{signal:t,timeoutMs:o,stage:i}){t?.throwIfAborted();let e=new AbortController,a=t?AbortSignal.any([t,e.signal]):e.signal;return new Promise((A,r)=>{let s=!1,g=(d,B)=>{s||(s=!0,clearTimeout(I),a.removeEventListener("abort",c),d(B))},c=()=>g(r,t?.aborted?Sk(t):y_e(i)),I=setTimeout(()=>e.abort(),o);a.addEventListener("abort",c,{once:!0}),Promise.resolve().then(()=>n(a)).then(d=>g(A,d),d=>g(r,d)),a.aborted&&c()})}function m_e(n,t,o){let i=`${n.deliveryKey}\0${t}`;return`dshim_${f_e("sha256").update(o==="file"?i:`${i}\0${o}`).digest("hex").slice(0,40)}`}function S_e(n){let t=String(n??"").replace(/\s+/g," ").trim();return t.length<=50?t:`${t.slice(0,49)}\u2026`}function D_e(n){return{schema:"2.0",config:{streaming_mode:!0,summary:{content:w("\u6B63\u5728\u751F\u6210\u2026")},streaming_config:{print_frequency_ms:{default:70},print_step:{default:1},print_strategy:"fast"}},body:{elements:[{tag:"markdown",element_id:Fz,content:n}]}}}var Ly=class{#e;#A;#t;#r;constructor({client:t,initialText:o,fileUploadTimeoutMs:i=Fy,fileMessageTimeoutMs:e=Fy}){this.#e=t,this.#A=o??w(Q_e),this.#t=Pz(i,"fileUploadTimeoutMs"),this.#r=Pz(e,"fileMessageTimeoutMs")}async stream(t,o,i={}){if(typeof o?.markdown!="function")throw new Error("Feishu stream requires a markdown producer");let e=null,A=uI("Feishu card.create",await this.#e.cardkit.v1.card.create({data:{type:"card_json",data:JSON.stringify(D_e(this.#A))}}))?.data?.card_id;if(!A)throw new Error("Feishu card.create returned no card_id");try{e=await this.#i(t,A,i.replyTo);let r=0,s=this.#A,g={messageId:e,setContent:async I=>{let d=String(I??"")||"\u2026";if(d===s)return;if(d.length>vz)throw new Error(`Feishu stream content exceeds ${vz} characters`);let B=await this.#e.cardkit.v1.cardElement.content({path:{card_id:A,element_id:Fz},data:{content:d,sequence:++r,uuid:`content_${A}_${r}`}});uI("Feishu cardElement.content",B),s=d}};await o.markdown(g);let c=await this.#e.cardkit.v1.card.settings({path:{card_id:A},data:{settings:JSON.stringify({config:{streaming_mode:!1,summary:{content:S_e(s)||w("\u56DE\u7B54\u5B8C\u6210")}}}),sequence:++r,uuid:`settings_${A}_${r}`}});return uI("Feishu card.settings",c),{messageId:e}}catch(r){throw e&&await this.#c(e),r}}async sendFile(t,o,{replyTo:i,signal:e}={}){return this.#o(t,o,{replyTo:i,signal:e,messageType:"file",presentation:"feishu-file"})}async sendImage(t,o,{replyTo:i,signal:e}={}){return this.#o(t,o,{replyTo:i,signal:e,messageType:"image",presentation:"feishu-image"})}async#o(t,o,{replyTo:i,signal:e,messageType:a,presentation:A}){if(e?.throwIfAborted(),typeof t!="string"||!t)throw new TypeError("chatId is required");if(!o||typeof o!="object"||typeof o.artifactId!="string"||!o.artifactId||typeof o.deliveryKey!="string"||!o.deliveryKey||typeof o.fileName!="string"||!o.fileName||!Buffer.isBuffer(o.bytes))throw new TypeError("A materialized result file is required");let r;try{r=await Gz(Q=>{Q.throwIfAborted();let y=a==="image"?this.#e.im.v1.image.create({data:{image_type:"message",image:o.bytes}}):this.#e.im.v1.file.create({data:{file_type:"stream",file_name:o.fileName,file:o.bytes}});return Fo(o,y),y},{signal:e,timeoutMs:this.#t,stage:"upload"})}catch(Q){throw e?.aborted?Sk(e):uC("upload",Q)}e?.throwIfAborted();let s=a==="image"?r?.image_key??r?.data?.image_key:r?.file_key??r?.data?.file_key;if(typeof s!="string"||!s)throw uC("upload",void 0,r?.code);let g=m_e(o,t,a),c=JSON.stringify(a==="image"?{image_key:s}:{file_key:s}),I=i?{path:{message_id:i},data:{msg_type:a,content:c,uuid:g}}:{params:{receive_id_type:"chat_id"},data:{receive_id:t,msg_type:a,content:c,uuid:g}},d=()=>{let Q=i?this.#e.im.v1.message.reply(I):this.#e.im.v1.message.create(I);return Fo(o,Q),Q},B;try{B=await Gz(async Q=>{Q.throwIfAborted();let y;try{y=await d()}catch(m){if(Uz(m)!==230049)throw m;y={code:230049}}return Q.throwIfAborted(),Number(y?.code)===230049&&(y=await d(),Q.throwIfAborted()),y},{signal:e,timeoutMs:this.#r,stage:"message send"})}catch(Q){throw e?.aborted?Sk(e):uC("message send",Q,void 0,{uncertain:!0})}if(Number.isFinite(Number(B?.code))&&Number(B.code)!==0)throw uC("message send",void 0,B.code,{uncertain:!0});let f=B?.data?.message_id;if(typeof f!="string"||!f)throw uC("message send",void 0,void 0,{uncertain:!0});return xt({deliveryId:o.deliveryKey,presentation:A,providerMessageIds:[f],artifacts:[{artifactId:o.artifactId,outcome:"sent"}]})}async#i(t,o,i){let e=JSON.stringify({type:"card",data:{card_id:o}}),a=i?await this.#e.im.v1.message.reply({path:{message_id:i},data:{msg_type:"interactive",content:e}}):await this.#e.im.v1.message.create({params:{receive_id_type:"chat_id"},data:{receive_id:t,msg_type:"interactive",content:e}});uI("Feishu message send",a);let A=a?.data?.message_id;if(!A)throw new Error("Feishu message send returned no message_id");return A}async#c(t){try{let o=await this.#e.im.v1.message.delete({path:{message_id:t}});uI("Feishu message delete",o)}catch(o){console.warn("[bridge] unable to recall a failed streaming card:",o.message)}}async addReaction(t,o){let e=uI("Feishu reaction.create",await this.#e.im.v1.messageReaction.create({path:{message_id:t},data:{reaction_type:{emoji_type:o}}}))?.data?.reaction_id;if(!e)throw new Error("Feishu reaction.create returned no reaction_id");return e}async removeReaction(t,o){uI("Feishu reaction.delete",await this.#e.im.v1.messageReaction.delete({path:{message_id:t,reaction_id:o}}))}};var O_e=15e3,b_e="\u2705 \u4FEE\u590D\u5B8C\u6210\uFF1A\u5DF2\u5B9E\u6D4B\u6536\u5230 card.action.trigger\uFF0C\u83DC\u5355\u6309\u94AE\u73B0\u5728\u53EF\u7528\u3002",M_e="\u26A0\uFE0F \u4FEE\u590D\u9A8C\u8BC1\u8D85\u65F6\uFF1A\u672A\u6536\u5230\u6D4B\u8BD5\u5361\u6309\u94AE\u7684 card.action.trigger\uFF0C\u4E0D\u80FD\u786E\u8BA4\u6309\u94AE\u5DF2\u4FEE\u590D\u3002\u8BF7\u4E0D\u8981\u91CD\u590D\u6388\u6743\uFF1B\u5148\u68C0\u67E5\u98DE\u4E66\u5F00\u653E\u5E73\u53F0\u7684\u5361\u7247\u56DE\u8C03\u914D\u7F6E\uFF0C\u786E\u8BA4\u540E\u518D\u53D1\u9001 /repair\u3002",Dk="\u26A0\uFE0F \u4FEE\u590D\u9A8C\u8BC1\u5931\u8D25\uFF1A\u65E0\u6CD5\u53D1\u9001\u4E13\u7528\u6D4B\u8BD5\u5361\uFF0C\u4E0D\u80FD\u786E\u8BA4 card.action.trigger \u5DF2\u6062\u590D\u3002\u8BF7\u4E0D\u8981\u91CD\u590D\u6388\u6743\uFF1B\u5148\u68C0\u67E5\u673A\u5668\u4EBA\u6D88\u606F\u6743\u9650\u548C\u8FDE\u63A5\u72B6\u6001\u3002",__e="\u26A0\uFE0F \u4FEE\u590D\u9A8C\u8BC1\u4E2D\u65AD\uFF1ARuntime \u5DF2\u505C\u6B62\uFF0C\u672A\u5B8C\u6210 card.action.trigger \u5B9E\u6D4B\uFF0C\u4E0D\u80FD\u786E\u8BA4\u4FEE\u590D\u6210\u529F\u3002\u8BF7\u4E0D\u8981\u91CD\u590D\u6388\u6743\uFF1B\u5148\u7B49\u5F85\u673A\u5668\u4EBA\u6062\u590D\u8FDE\u63A5\u3002",T_e=new Set(["connected","connecting","reconnecting"]);function Gs(n){return typeof n=="string"&&n.trim()?n.trim():null}function N_e(n){return Gs(n?.operator?.open_id)??Gs(n?.operator?.operator_id?.open_id)}function R_e(n,t){try{let o=n?.getConnectionStatus?.()?.state;return typeof o=="string"&&o?o:t}catch{return t}}function Np(n,t){let o=new Error(t);return o.code=n,o}function k_e(n,t){if(!n||typeof n.request!="function")return;let o=i=>({...i??{},timeout:i?.timeout??t});return{request:i=>n.request(o(i)),get:(i,e)=>n.get(i,o(e)),delete:(i,e)=>n.delete(i,o(e)),head:(i,e)=>n.head(i,o(e)),options:(i,e)=>n.options(i,o(e)),post:(i,e,a)=>n.post(i,e,o(a)),put:(i,e,a)=>n.put(i,e,o(a)),patch:(i,e,a)=>n.patch(i,e,o(a))}}function v_e({allowedSenderCount:n=1}={}){return{startedAt:null,ready:!1,feishuLongConnectionState:"idle",harnessReachable:!1,messagesReceived:0,messagesReplied:0,messagesRejected:0,reactionsAdded:0,reactionsRemoved:0,reactionErrors:0,streamResponses:0,streamUpdates:0,streamFallbacks:0,streamErrors:0,cardActionsReceived:0,cardActionProbesVerified:0,lastMessageAt:null,lastReplyAt:null,lastRejectedAt:null,lastCardActionAt:null,lastError:null,agentPreset:"standard",authorizationMode:"sender-open-id-allowlist",allowedSenderCount:n}}var Uy=class{#e;#A;#t;#r;#o;#i;#c;#s;#I;#a;#n;#g;#l;#p;#d;#E;#h=null;#C=null;#B=null;#f=null;#y=null;#w=null;#u=new Map;#Q;constructor({lark:t,botId:o,appId:i,appSecret:e,domain:a="feishu",botOpenId:A,groupResponseMode:r,ownerOpenId:s,ownerOpenIds:g,harness:c,state:I,repair:d,replyTimeoutMs:B=6e5,connectTimeoutMs:f=15e3,requestTimeoutMs:Q=O_e,wsAgent:y,logger:m=console}){if(!t)throw new Error("FeishuRuntime requires the Feishu SDK");if(!i||!e)throw new Error("FeishuRuntime requires app credentials");let _=Array.isArray(g)?g:[s],N=[...new Set(_.filter(G=>typeof G=="string"&&G))];if(N.length===0)throw new Error("FeishuRuntime requires at least one owner open_id");if(!c)throw new Error("FeishuRuntime requires a Harness client");if(!I)throw new Error("FeishuRuntime requires a state store");if(d!=null&&!Gs(o))throw new TypeError("FeishuRuntime repair capability requires a botId");if(!Number.isFinite(Q)||Q<=0)throw new TypeError("FeishuRuntime requestTimeoutMs must be a positive number");this.#e=t,this.#A=Gs(o),this.#t=i,this.#r=e,this.#o=a,this.#i=Gs(A),this.#c=Pi(r),this.#s=N,this.#I=c,this.#a=I,this.#E=d??null,this.#n=B,this.#g=f,this.#l=Q,this.#p=y,this.#d=m,this.#Q=v_e({allowedSenderCount:N.length})}get status(){return structuredClone(this.#Q)}setGroupResponseMode(t){this.#c=Pi(t),this.#C?.setGroupResponseMode(this.#c)}async start(){for(;;){for(;this.#y;)await this.#y;if(this.#f)return this.#f;let o=this.#B;if(o){let i=R_e(o,this.#Q.feishuLongConnectionState);if(T_e.has(i))return this.status;await this.stop({preserveError:i==="failed"});continue}if(this.#h||this.#C||this.#w){await this.stop({preserveError:this.#Q.feishuLongConnectionState==="failed"});continue}break}let t;return t=this.#O().finally(()=>{this.#f===t&&(this.#f=null)}),this.#f=t,t}async#O(){let t=new AbortController;this.#w=t;let{signal:o}=t,i=()=>o.reason??new DOMException("Feishu runtime stopped","AbortError"),e=()=>!o.aborted&&this.#w===t,a=()=>{if(!e())throw i()};this.#Q.startedAt=new Date().toISOString(),this.#Q.feishuLongConnectionState="connecting",this.#Q.lastError=null;try{await this.#I.ensureRunning({signal:o}),a(),this.#Q.harnessReachable=!0;let A=this.#o==="lark"?this.#e.Domain.Lark:this.#e.Domain.Feishu,r={appId:this.#t,appSecret:this.#r,domain:A},s=k_e(this.#e.defaultHttpInstance,this.#l);s&&(r.httpInstance=s);let g=new this.#e.Client(r);this.#h=g;let c=new Ly({client:g,initialText:w("\u5DF2\u8FDE\u63A5 DeepSeek Harness\uFF0C\u6B63\u5728\u601D\u8003\u2026")}),I=new Gy({client:g,channel:c,harness:this.#I,state:this.#a,status:this.#Q,allowedSenderOpenIds:new Set(this.#s),botId:this.#A,appId:this.#t,botOpenId:this.#i,groupResponseMode:this.#c,repair:this.#E,repairOwnerOpenIds:new Set(this.#s.filter(_=>_!=="*")),replyTimeoutMs:this.#n,signal:o,logger:this.#d});this.#C=I;let d=new this.#e.EventDispatcher({}).register({"im.message.receive_v1":_=>{e()&&I.accept(_)},"im.message.reaction.created_v1":()=>{},"im.message.reaction.deleted_v1":()=>{},"card.action.trigger":_=>{e()&&(this.#Q.cardActionsReceived+=1,this.#Q.lastCardActionAt=new Date().toISOString(),this.#m(_)||I.onCardAction(_))}}),B,f,Q=new Promise((_,N)=>{let G=!1,Y=()=>{f(i())},j=(q,J)=>{G||(G=!0,clearTimeout(x),o.removeEventListener("abort",Y),q(J))},x=setTimeout(()=>{j(N,new Error(`Feishu WebSocket handshake timed out after ${this.#g}ms`))},this.#g);B=()=>{j(_)},f=q=>{j(N,q)},o.addEventListener("abort",Y,{once:!0}),o.aborted&&Y()});Q.catch(()=>{});let y=new this.#e.WSClient({...r,...this.#p?{agent:this.#p}:{},loggerLevel:this.#e.LoggerLevel.info,handshakeTimeoutMs:this.#g,onReady:()=>{e()&&(this.#Q.feishuLongConnectionState="connected",this.#Q.ready=!0,this.#Q.lastError=null,B())},onError:_=>{e()&&(this.#Q.feishuLongConnectionState="failed",this.#Q.ready=!1,this.#Q.lastError=_?.message??String(_),this.#d.error("[dsh-feishu] Feishu long connection failed:",this.#Q.lastError),f(_))},onReconnecting:()=>{e()&&(this.#Q.feishuLongConnectionState="reconnecting",this.#Q.ready=!1)},onReconnected:()=>{e()&&(this.#Q.feishuLongConnectionState="connected",this.#Q.ready=!0,this.#Q.lastError=null)}});this.#B=y;let m=Promise.resolve().then(()=>y.start({eventDispatcher:d})).catch(_=>{throw f(_),_});return await Promise.all([m,Q]),a(),this.status}catch(A){throw o.aborted||(this.#Q.ready=!1,this.#Q.feishuLongConnectionState="failed",this.#Q.lastError=A?.message??String(A),await this.#R({preserveError:!0,abortController:t})),A}}async beginCardActionProbe({expectedOperatorOpenId:t,timeoutMs:o=9e4}={}){if(!this.#Q.ready||!this.#h)throw Np("card_action_probe_unavailable","\u98DE\u4E66\u673A\u5668\u4EBA\u5C1A\u672A\u8FDE\u63A5");let i=Gs(t);if(!i||i==="*")throw new TypeError("A precise Feishu operator open_id is required");if(!Number.isFinite(o)||o<=0||o>10*6e4)throw new TypeError("Card-action probe timeout must be between 1 and 600000ms");let e=w_e().replaceAll("-",""),a;try{a=await this.#h.im.v1.message.create({params:{receive_id_type:"open_id"},data:{receive_id:i,msg_type:"interactive",content:fz(e)}})}catch{throw this.#S(i,w(Dk),"failure"),Np("card_action_probe_send_failed","\u65E0\u6CD5\u53D1\u9001\u98DE\u4E66\u5361\u7247\u56DE\u8C03\u6D4B\u8BD5")}if(a?.code&&a.code!==0)throw this.#S(i,w(Dk),"failure"),Np("card_action_probe_send_failed","\u65E0\u6CD5\u53D1\u9001\u98DE\u4E66\u5361\u7247\u56DE\u8C03\u6D4B\u8BD5");let A=Gs(a?.data?.message_id)??Gs(a?.message_id);if(!A)throw this.#S(i,w(Dk),"failure"),Np("card_action_probe_send_failed","\u98DE\u4E66\u672A\u8FD4\u56DE\u6D4B\u8BD5\u5361\u7247\u7684\u6D88\u606F ID");return new Promise((r,s)=>{let g=setTimeout(()=>{let c=this.#u.get(A);!c||c.nonce!==e||(this.#u.delete(A),this.#S(i,w(M_e),"timeout"),s(Np("card_action_probe_timeout","\u5728\u89C4\u5B9A\u65F6\u95F4\u5185\u672A\u6536\u5230\u98DE\u4E66\u5361\u7247\u6309\u94AE\u56DE\u8C03")))},o);g.unref?.(),this.#u.set(A,{messageId:A,nonce:e,expectedOperatorOpenId:i,timeout:g,resolve:r,reject:s})})}#m(t){let o=Gs(t?.context?.open_message_id);if(!o)return!1;let i=this.#u.get(o);if(!i)return!1;let e=t?.action?.value,a=N_e(t);return e?.action!=="repair_verify"||e?.nonce!==i.nonce||a!==i.expectedOperatorOpenId?!1:(clearTimeout(i.timeout),this.#u.delete(o),this.#Q.cardActionProbesVerified+=1,this.#S(a,w(b_e),"success").finally(()=>{i.resolve({verified:!0,messageId:o,operatorOpenId:a})}),!0)}#S(t,o,i){let e=this.#h;return e?Promise.resolve().then(async()=>{let a=await e.im.v1.message.create({params:{receive_id_type:"open_id"},data:{receive_id:t,msg_type:"text",content:JSON.stringify({text:o})}});if(a?.code&&a.code!==0)throw new Error("Feishu callback repair notice failed");return!0}).catch(()=>(this.#d.warn?.(`[dsh-feishu] unable to send the callback repair ${i} notice`),!1)):(this.#d.warn?.(`[dsh-feishu] unable to send the callback repair ${i} notice`),Promise.resolve(!1))}async sendConnectionTest(t){if(!this.#Q.ready||!this.#h){let e=new Error("\u98DE\u4E66\u673A\u5668\u4EBA\u5C1A\u672A\u8FDE\u63A5");throw e.code="test-target-unavailable",e}if(typeof t!="string"||!t.trim())throw new TypeError("Feishu connection test text is required");let o=async(e,a,A)=>{let r=await this.#h.im.v1.message.create({params:{receive_id_type:e},data:{receive_id:a,msg_type:"text",content:JSON.stringify({text:A})}});if(r?.code&&r.code!==0)throw new Error(`Feishu connection test failed: ${r.msg||r.code}`)},i=this.#s.find(e=>e!=="*");return i?(await o("open_id",i,t),{sent:!0}):dg({state:this.#a,text:t,channelLabel:w("\u98DE\u4E66\u673A\u5668\u4EBA"),send:async(e,a)=>{let A=typeof e?.chatId=="string"?e.chatId.trim():"";if(!A)throw sr(w("\u98DE\u4E66\u673A\u5668\u4EBA"));await o("chat_id",A,a)}})}stop(t={}){if(this.#y)return this.#y;let o;return o=this.#_(t).finally(()=>{this.#y===o&&(this.#y=null)}),this.#y=o,o}async#_({preserveError:t=!1}={}){let o=this.#w;this.#w===o&&(this.#w=null),o?.abort(new DOMException("Feishu runtime stopped","AbortError"));let i=this.#f;return i&&await i.catch(()=>{}),this.#R({preserveError:t,abortController:o})}async#R({preserveError:t=!1,abortController:o}={}){let i=t?this.#Q.lastError:null;this.#w===o&&(this.#w=null),o?.abort(new DOMException("Feishu runtime stopped","AbortError"));for(let A of this.#u.values())clearTimeout(A.timeout),this.#S(A.expectedOperatorOpenId,w(__e),"abort"),A.reject(Np("abort","\u98DE\u4E66\u8FD0\u884C\u65F6\u5DF2\u505C\u6B62"));this.#u.clear(),this.#Q.ready=!1;let e=this.#B;this.#B=null,e?.close({force:!0});let a=this.#C;return this.#C=null,a&&await a.waitForIdle(),this.#h=null,this.#Q.feishuLongConnectionState=t?"failed":"idle",this.#Q.lastError=i,this.status}};var Hy=class extends gr{constructor(t){super({...t,rpcIdPrefix:"feishu",logPrefix:"dsh-feishu"})}};import{createHash as P_e}from"node:crypto";import{mkdir as G_e,readFile as F_e,rename as L_e,unlink as U_e,writeFile as H_e}from"node:fs/promises";import{dirname as K_e}from"node:path";var Yy="DSH_FEISHU_APP_SECRET";function Rn(n){return typeof n=="string"&&n.trim()?n.trim():null}function Hz(n){let t=Rn(n);return t&&/^[A-Za-z0-9_-]{1,128}$/.test(t)?t:null}function Kz(n){return`bot_${P_e("sha256").update(n).digest("hex").slice(0,24)}`}function x_e(n){let t=Array.isArray(n.ownerOpenIds)?n.ownerOpenIds:[n.ownerOpenId];return[...new Set(t.map(Rn).filter(Boolean))]}function Ky(n,{legacy:t=!1}={}){if(!n||typeof n!="object")return null;let o=Rn(n.appId),i=x_e(n);if(!o||i.length===0)return null;let e=Hz(n.id)??(t?Kz(o):null),a=Rn(n.secretRef)??(t?Yy:null);if(!e||!a||!/^[A-Za-z_][A-Za-z0-9_]*$/.test(a))return null;let A=n.domain==="lark"?"lark":"feishu";return Object.freeze({id:e,appId:o,secretRef:a,ownerOpenIds:Object.freeze(i),domain:A,botName:Rn(n.botName),botOpenId:Rn(n.botOpenId),activated:n.activated??null,groupResponseMode:Pi(n.groupResponseMode),groupMessagePermissionGranted:n.groupMessagePermissionGranted===!0,deletionPending:n.deletionPending===!0,connectedAt:Rn(n.connectedAt),createdAt:Rn(n.createdAt)??Rn(n.connectedAt)})}function Y_e(n){if(!n||typeof n!="object")return null;if(n.version===2&&Array.isArray(n.bots)){let o=n.bots.map(A=>Ky(A));if(o.some(A=>A===null))throw new Error("dsh-feishu config contains an invalid bot entry");let i=new Set,e=new Set,a=new Set;for(let A of o){if(i.has(A.id)||e.has(A.secretRef)||a.has(A.appId))throw new Error("dsh-feishu config contains duplicate bot identities");i.add(A.id),e.add(A.secretRef),a.add(A.appId)}return{value:Object.freeze({version:2,bots:Object.freeze(o)}),migrated:!1}}let t=Ky(n,{legacy:!0});return t?{value:Object.freeze({version:2,bots:Object.freeze([t])}),migrated:!0}:null}var xy=class{#e;#A=Object.freeze({version:2,bots:Object.freeze([])});#t=Promise.resolve();constructor(t){this.#e=t}async load(){try{let t=JSON.parse(await F_e(this.#e,"utf8")),o=Y_e(t);if(!o)throw new Error("dsh-feishu config is incomplete or invalid");this.#A=o.value,o.migrated&&await this.#i(this.#A)}catch(t){if(t?.code!=="ENOENT")throw t;this.#A=Object.freeze({version:2,bots:Object.freeze([])})}return this}get(){let t=this.#A.bots[0];if(!t)return null;let o=structuredClone(t);return o.ownerOpenId=o.ownerOpenIds[0],o}list(){return structuredClone(this.#A.bots)}getBot(t){let o=this.#A.bots.find(i=>i.id===t);return o?structuredClone(o):null}async save(t){let o={...t};o.id||(o.id=Kz(Rn(o.appId)??"invalid")),o.secretRef||(o.secretRef=Yy);let i=Ky(o);if(!i)throw new Error("Refusing to persist incomplete dsh-feishu configuration");return await this.#r([i]),this.get()}async saveBot(t){let o=Ky(t);if(!o)throw new Error("Refusing to persist incomplete dsh-feishu bot configuration");return this.#o(i=>{if(i.find(r=>r.secretRef===o.secretRef&&r.id!==o.id))throw new Error("Refusing to share a credential reference between Feishu bots");if(i.find(r=>r.appId===o.appId&&r.id!==o.id))throw new Error("Refusing to persist the same Feishu app twice");let A=i.findIndex(r=>r.id===o.id);return A===-1?i.push(o):i[A]=o,structuredClone(o)})}async removeBot(t){if(!Hz(t))throw new TypeError("Invalid Feishu bot id");return this.#o(o=>{let i=o.findIndex(a=>a.id===t);if(i===-1)return null;let[e]=o.splice(i,1);return structuredClone(e)})}async clear(){let t=this.#t.then(async()=>{try{await U_e(this.#e)}catch(o){if(o?.code!=="ENOENT")throw o}this.#A=Object.freeze({version:2,bots:Object.freeze([])})});this.#t=t.then(()=>{},()=>{}),await t}async#r(t){let o=Object.freeze({version:2,bots:Object.freeze([...t])}),i=this.#t.then(async()=>{await this.#i(o),this.#A=o});this.#t=i.then(()=>{},()=>{}),await i}async#o(t){let o,i=this.#t.then(async()=>{let e=[...this.#A.bots];o=t(e);let a=Object.freeze({version:2,bots:Object.freeze(e)});await this.#i(a),this.#A=a});return this.#t=i.then(()=>{},()=>{}),await i,o}async#i(t){await G_e(K_e(this.#e),{recursive:!0,mode:448});let o=`${this.#e}.tmp`;await H_e(o,`${JSON.stringify(t,null,2)} -`,{encoding:"utf8",mode:384}),await L_e(o,this.#e)}};import{randomUUID as qz}from"node:crypto";var wk=new Set(["starting","qr_ready","polling","slow_down","domain_switched","saving"]),j_e=new Set(["polling","slow_down","domain_switched"]),pi=Object.freeze({IDLE:"idle",STARTING:"starting",QR_READY:"qr_ready",POLLING:"polling",SLOW_DOWN:"slow_down",DOMAIN_SWITCHED:"domain_switched",SAVING:"saving",SUCCEEDED:"succeeded",EXPIRED:"expired",CANCELLED:"cancelled",ERROR:"error"});function xz(n){return["access_denied","expired_token","abort"].includes(n?.code)?n.code:"registration_failed"}function Ok(n){let t=xz(n);return{code:t,message:{access_denied:"Registration was denied.",abort:"Registration was cancelled.",expired_token:"The registration QR code expired."}[t]??"Unable to register the Feishu app."}}function J_e(n){let t=Number(n);if(!Number.isFinite(t)||t<=0)throw new TypeError("registerApp onQRCodeReady returned an invalid expireIn");return t}function q_e(n){if(n!==void 0){if(n===null||typeof n!="object"||Array.isArray(n))throw new TypeError("registerApp returned invalid user_info");return{...n}}}var Fs=class{#e;#A;#t;#r;#o;#i=0;#c=null;#s;constructor({registerApp:t,onCredentials:o,now:i=Date.now,setTimeout:e=globalThis.setTimeout,clearTimeout:a=globalThis.clearTimeout}={}){if(typeof t!="function")throw new TypeError("RegistrationManager requires a registerApp function");if(typeof o!="function")throw new TypeError("RegistrationManager requires an onCredentials function");if(typeof i!="function"||typeof e!="function"||typeof a!="function")throw new TypeError("RegistrationManager clock dependencies must be functions");this.#e=t,this.#A=o,this.#t=i,this.#r=e,this.#o=a,this.#s=this.#a(null,pi.IDLE)}start(t={}){if(t===null||typeof t!="object"||Array.isArray(t))throw new TypeError("Registration options must be an object");this.#f();let o={id:++this.#i,controller:new AbortController,qrCodeUrl:null,expiresAt:null,pollIntervalSeconds:null,expiryTimer:null};this.#c=o,this.#s=this.#a(o,pi.STARTING);let i={...t,signal:o.controller.signal,onQRCodeReady:a=>this.#g(o,a),onStatusChange:a=>this.#l(o,a)};return Promise.resolve().then(()=>this.#e(i)).then(a=>this.#p(o,a),a=>this.#d(o,a)),this.status()}status(){this.#E();let t={...this.#s};t.error&&(t.error={...t.error});let o=this.#c;return o&&o.expiresAt!==null&&wk.has(t.state)&&(t.remainingSeconds=Math.max(0,Math.ceil((o.expiresAt-this.#t())/1e3))),t}cancel(){let t=this.#c;return t?(this.#C(t,pi.CANCELLED,{error:{code:"abort",message:"Registration was cancelled."}}),t.controller.abort(),this.status()):this.status()}#I(t){return this.#c===t}#a(t,o,i={}){let e={state:o,attempt:t?.id??this.#i,updatedAt:this.#t(),...i};return t?.qrCodeUrl&&wk.has(o)&&(e.qrCodeUrl=t.qrCodeUrl,e.expiresAt=t.expiresAt),t?.pollIntervalSeconds!==null&&wk.has(o)&&(e.pollIntervalSeconds=t.pollIntervalSeconds),e}#n(t,o,i={}){this.#I(t)&&(this.#s=this.#a(t,o,i))}#g(t,o){if(!this.#I(t))return;if(typeof o?.url!="string"||!o.url)throw new TypeError("registerApp onQRCodeReady returned an invalid URL");let i=J_e(o.expireIn);t.qrCodeUrl=o.url,t.expiresAt=this.#t()+i*1e3,this.#B(t),t.expiryTimer=this.#r(()=>this.#h(t),i*1e3),t.expiryTimer?.unref?.(),this.#n(t,pi.QR_READY)}#l(t,o){!this.#I(t)||!j_e.has(o?.status)||(o.status===pi.SLOW_DOWN&&Number.isFinite(Number(o.interval))&&(t.pollIntervalSeconds=Number(o.interval)),this.#n(t,o.status))}async#p(t,o){if(!this.#I(t))return;let i=o?.client_id,e=o?.client_secret;if(typeof i!="string"||!i||typeof e!="string"||!e){this.#C(t,pi.ERROR,{error:{code:"invalid_credentials",message:"Feishu registration returned invalid credentials."}});return}let a;try{a=q_e(o.user_info)}catch{this.#C(t,pi.ERROR,{error:{code:"invalid_credentials",message:"Feishu registration returned invalid credentials."}});return}this.#B(t),t.qrCodeUrl=null,t.expiresAt=null,t.pollIntervalSeconds=null,this.#n(t,pi.SAVING);try{await this.#A({client_id:i,client_secret:e,user_info:a})}catch{this.#I(t)&&this.#C(t,pi.ERROR,{error:{code:"credentials_callback_failed",message:"Unable to store the Feishu credentials."}});return}this.#I(t)&&this.#C(t,pi.SUCCEEDED)}#d(t,o){if(!this.#I(t))return;let i=xz(o);if(i==="expired_token"){this.#C(t,pi.EXPIRED,{error:Ok(o)});return}if(i==="abort"){this.#C(t,pi.CANCELLED,{error:Ok(o)});return}this.#C(t,pi.ERROR,{error:Ok(o)})}#E(){let t=this.#c;t&&t.expiresAt!==null&&this.#t()>=t.expiresAt&&this.#h(t)}#h(t){this.#I(t)&&(this.#C(t,pi.EXPIRED,{error:{code:"expired_token",message:"The registration QR code expired."}}),t.controller.abort())}#C(t,o,i={}){this.#I(t)&&(this.#B(t),this.#s=this.#a(t,o,i),this.#c=null)}#B(t){t.expiryTimer!==null&&(this.#o(t.expiryTimer),t.expiryTimer=null)}#f(){let t=this.#c;t&&(this.#B(t),this.#c=null,t.controller.abort())}};var z_e="card.action.trigger",BC="callback_repair";function V_e(n){return n==="lark"?"accounts.larksuite.com":"accounts.feishu.cn"}function W_e(n){return n==="lark"?"open.larksuite.com":"open.feishu.cn"}function bk(n,t,o="feishu",i="Feishu app update"){let e;try{e=new URL(n)}catch{throw new Error(`${i} returned an invalid verification URL`)}let a=o==="feishu"||o==="lark",A=e.searchParams.getAll("clientID"),r=e.searchParams.getAll("tp"),s=e.searchParams.getAll("addons"),g=String(t).includes("{{")||String(t).includes("}}")||[...e.searchParams.values()].some(c=>c.includes("{{")||c.includes("}}"));if(!a||e.protocol!=="https:"||e.hostname!==W_e(o)||e.port!==""||e.username!==""||e.password!==""||r.length!==1||r[0]!=="sdk"||A.length!==1||A[0]!==t||e.searchParams.has("createOnly")||s.length!==1||!s[0]?.trim()||g)throw new Error(`${i} returned an unsafe verification URL`);return e.toString()}function Z_e(n,t,o="feishu"){return bk(n,t,o,"Feishu callback repair")}var jy=class{#e;#A;#t;constructor({registerApp:t,onCredentials:o,appId:i,domain:e="feishu"}={}){if(typeof t!="function")throw new TypeError("registerApp is required");if(typeof o!="function")throw new TypeError("onCredentials is required");if(typeof i!="string"||!i.trim())throw new TypeError("appId is required");if(e!=="feishu"&&e!=="lark")throw new TypeError("domain is invalid");this.#A=i.trim(),this.#t=e,this.#e=new Fs({registerApp:a=>t({...a,onQRCodeReady:A=>{Z_e(A?.url,this.#A,this.#t),a.onQRCodeReady(A)}}),onCredentials:o})}start(){return this.#e.start({source:"deepseek-harness-card-action-repair",domain:V_e(this.#t),appId:this.#A,addons:{preset:!1,callbacks:{items:[z_e]}}})}status(){return this.#e.status()}cancel(){return this.#e.cancel()}};var X_e="im:message.group_msg",qy="group_message_permission";function $_e(n){return n==="lark"?"accounts.larksuite.com":"accounts.feishu.cn"}function eTe(n,t,o="feishu"){return bk(n,t,o,"Feishu group message permission update")}var Jy=class{#e;#A;#t;constructor({registerApp:t,onCredentials:o,appId:i,domain:e="feishu"}={}){if(typeof t!="function")throw new TypeError("registerApp is required");if(typeof o!="function")throw new TypeError("onCredentials is required");if(typeof i!="string"||!i.trim())throw new TypeError("appId is required");if(e!=="feishu"&&e!=="lark")throw new TypeError("domain is invalid");this.#A=i.trim(),this.#t=e,this.#e=new Fs({registerApp:a=>t({...a,onQRCodeReady:A=>{eTe(A?.url,this.#A,this.#t),a.onQRCodeReady(A)}}),onCredentials:o})}start(){return this.#e.start({source:"deepseek-harness-group-message-permission",domain:$_e(this.#t),appId:this.#A,addons:{preset:!1,scopes:{tenant:[X_e]}}})}status(){return this.#e.status()}cancel(){return this.#e.cancel()}};var Yz=Object.freeze(["im:message.p2p_msg:readonly","im:message.group_at_msg:readonly","im:message:readonly","im:message:send_as_bot","im:message.reactions:write_only","im:message:recall","im:resource","cardkit:card:write"]);var _k=new Set(["starting","qr_ready","polling","slow_down","domain_switched"]),zy=new Set([..._k,"saving"]),jz=new Set([BC,qy]),Mk="*",ATe=12e4,tTe=6e5;function zz(){return{ready:!1,feishuLongConnectionState:"idle",harnessReachable:!1}}function Vy(n){return n?n.status:zz()}function Wy(n){return n.ready===!0&&n.feishuLongConnectionState==="connected"&&n.harnessReachable===!0}function Vz(n){return n.length>12?`${n.slice(0,8)}\u2022\u2022\u2022\u2022${n.slice(-4)}`:"cli_\u2022\u2022\u2022\u2022"}function rTe(n){return{name:n.botName,appIdMasked:Vz(n.appId),activated:n.activated,domain:n.domain}}function aTe({connected:n,error:t,connection:o}){return n?"connected":t||o.feishuLongConnectionState==="failed"?"error":"disconnected"}function iTe(){return`bot_${qz().replaceAll("-","")}`}function oTe(){return`reg_${qz().replaceAll("-","")}`}function Jz(n){return`DSH_FEISHU_APP_SECRET_${n.slice(4).toUpperCase()}`}function Zy(n){return JSON.stringify({id:n.id,appId:n.appId,secretRef:n.secretRef,ownerOpenIds:n.ownerOpenIds,domain:n.domain,botName:n.botName,botOpenId:n.botOpenId,activated:n.activated,groupResponseMode:Pi(n.groupResponseMode),groupMessagePermissionGranted:n.groupMessagePermissionGranted===!0,deletionPending:n.deletionPending===!0,connectedAt:n.connectedAt??null,createdAt:n.createdAt??null})}function Xy(n){return typeof n=="string"&&n.trim()?n.trim():null}var fC=class{#e;#A;#t;#r;#o;#i;#c;#s;#I=new Map;#a=new Map;#n=new Map;#g=new Map;#l=new Map;#p=null;#d=Promise.resolve();#E=new Map;#h=1;#C;#B=!1;constructor({registerApp:t,verifyApp:o,credentials:i,configStore:e,createRuntime:a,deleteState:A=async()=>{},createBotId:r=iTe,createRegistrationId:s=oTe,callbackProbeTimeoutMs:g=ATe}){if(typeof t!="function")throw new Error("registerApp is required");if(typeof o!="function")throw new Error("verifyApp is required");if(!i)throw new Error("credentials service is required");if(!e||typeof e.list!="function")throw new Error("multi-bot config store is required");if(typeof a!="function")throw new Error("createRuntime is required");if(typeof A!="function")throw new Error("deleteState must be a function");if(!Number.isFinite(g)||g<=0||g>tTe)throw new TypeError("callbackProbeTimeoutMs must be between 1 and 600000ms");this.#e=t,this.#A=o,this.#t=i,this.#r=e,this.#o=a,this.#i=A,this.#c=r,this.#s=s,this.#C=g}async initialize(){if(this.#B)return this.status();let t=this.#r.list(),o=!1;return await Promise.allSettled(t.map(i=>this.#T(i.id,async()=>{let e=Vy(this.#I.get(i.id));if(Wy(e)||e.feishuLongConnectionState==="connecting"||e.feishuLongConnectionState==="reconnecting")return;if(o=!0,i.deletionPending){this.#a.set(i.id,{code:"deletion_pending",message:"\u673A\u5668\u4EBA\u6B63\u5728\u7B49\u5F85\u5B8C\u6210\u672C\u5730\u5220\u9664\uFF0C\u8BF7\u91CD\u8BD5\u79FB\u9664\u3002"});return}let a;try{a=await this.#t.resolve(i.secretRef)}catch{this.#a.set(i.id,{code:"missing_credentials",message:"\u65E0\u6CD5\u8BFB\u53D6\u673A\u5668\u4EBA\u51ED\u636E\uFF0C\u8BF7\u68C0\u67E5\u51ED\u636E\u5B58\u50A8\u3002"});return}if(!a?.value){this.#a.set(i.id,{code:"missing_credentials",message:"\u673A\u5668\u4EBA\u51ED\u636E\u7F3A\u5931\uFF0C\u8BF7\u5220\u9664\u540E\u91CD\u65B0\u626B\u7801\u63A5\u5165\u3002"});return}try{await this.#m(i,a.value),this.#a.delete(i.id)}catch{this.#a.set(i.id,{code:"connection_failed",message:"\u673A\u5668\u4EBA\u6682\u65F6\u65E0\u6CD5\u8FDE\u63A5\u98DE\u4E66\uFF0C\u8BF7\u91CD\u8BD5\u3002"})}}))),o&&this.#k(),this.status()}startRegistration(){this.#N();let t=this.#s();if(typeof t!="string"||!/^[A-Za-z0-9_-]{1,128}$/.test(t)||this.#n.has(t))throw new Error("Registration id generator returned an invalid or duplicate id");let o={id:t,manager:null,botId:null,createdNew:!1,cancelled:!1};return o.manager=new Fs({registerApp:this.#e,onCredentials:i=>this.#G(()=>this.#O(o,i))}),this.#n.set(t,o),this.#p=t,this.#F(),o.manager.start({source:"deepseek-harness",createOnly:!0,appPreset:{name:"{user} \u7684\u5317\u6C47\u661F\u6CB3 AI \u52A9\u624B",desc:"\u8FDE\u63A5\u98DE\u4E66\u4E0E DeepSeek Harness\uFF0C\u5728\u804A\u5929\u4E2D\u4F7F\u7528\u4F01\u4E1A AI \u52A9\u624B\u3002"},addons:{preset:!1,scopes:{tenant:[...Yz]},events:{items:{tenant:["im.message.receive_v1"]}},callbacks:{items:["card.action.trigger"]}}}),this.#k(),this.registrationStatus(t)}startCallbackRepair(t,{actorOpenId:o,chatId:i}={}){this.#N();let e=this.#M(t);if(e.deletionPending)throw new Error("Cannot repair a Feishu bot pending deletion");let a=this.#g.get(t),A=a?this.#n.get(a):null;if(A&&zy.has(A.manager.status().state)){if(A.operation!==BC)throw new Error("Another Feishu app update is already active for this bot");return this.registrationStatus(A.id)}this.#g.delete(t);let r=this.#s();if(typeof r!="string"||!/^[A-Za-z0-9_-]{1,128}$/.test(r)||this.#n.has(r))throw new Error("Registration id generator returned an invalid or duplicate id");let s={id:r,operation:BC,manager:null,botId:t,createdNew:!1,cancelled:!1,remoteCommitted:!1,processing:null,publicError:null,stage:"authorizing",target:structuredClone(e),targetFingerprint:Zy(e),initiator:{actorOpenId:Xy(o),chatId:Xy(i)}};return s.manager=new jy({registerApp:this.#e,appId:e.appId,domain:e.domain,onCredentials:g=>{s.remoteCommitted=!0;let I=this.#u(s,g).finally(()=>{s.processing===I&&(s.processing=null)});return s.processing=I,I}}),this.#n.set(r,s),this.#g.set(t,r),this.#p=r,this.#F(),s.manager.start(),this.#k(),this.registrationStatus(r)}startGroupMessagePermission(t){this.#N();let o=this.#M(t);if(o.deletionPending)throw new Error("Cannot update permissions for a Feishu bot pending deletion");let i=this.#g.get(t),e=i?this.#n.get(i):null;if(e&&zy.has(e.manager.status().state)){if(e.operation!==qy)throw new Error("Another Feishu app update is already active for this bot");return this.registrationStatus(e.id)}this.#g.delete(t);let a=this.#s();if(typeof a!="string"||!/^[A-Za-z0-9_-]{1,128}$/.test(a)||this.#n.has(a))throw new Error("Registration id generator returned an invalid or duplicate id");let A={id:a,operation:qy,manager:null,botId:t,createdNew:!1,cancelled:!1,remoteCommitted:!1,processing:null,publicError:null,stage:"authorizing",target:structuredClone(o),targetFingerprint:Zy(o),initiator:{actorOpenId:null,chatId:null}};return A.manager=new Jy({registerApp:this.#e,appId:o.appId,domain:o.domain,onCredentials:r=>{A.remoteCommitted=!0;let g=this.#w(A,r).finally(()=>{A.processing===g&&(A.processing=null)});return A.processing=g,g}}),this.#n.set(a,A),this.#g.set(t,a),this.#p=a,this.#F(),A.manager.start(),this.#k(),this.registrationStatus(a)}hasRegistration(t){return this.#n.has(t)}registrationStatus(t){let o=this.#n.get(t);return o?this.#f({registration:o,selectedBotId:o.botId}):null}async cancelRegistration(t=this.#p){let o=this.#n.get(t);if(!o)return this.status();let i=o.manager.status().state;return jz.has(o.operation)&&i==="saving"?this.registrationStatus(t):zy.has(i)?(o.cancelled=!0,o.manager.cancel(),await this.#G(async()=>{o.createdNew&&o.botId&&this.#l.get(o.botId)===o.id&&this.#r.getBot(o.botId)&&await this.#T(o.botId,()=>this.#R(o.botId))}),this.#k(),this.registrationStatus(t)??this.status()):this.registrationStatus(t)}status(t){return this.#f({registration:this.#n.get(this.#p)??null,selectedBotId:t})}async bindCredentials({appId:t,appSecret:o,domain:i="feishu"}={}){this.#N();let e=typeof t=="string"?t.trim():"",a=typeof o=="string"?o.trim():"",A=i==="lark"?"lark":"feishu";if(!e||!a)throw new TypeError("Feishu App ID and App Secret are required");return this.#G(async()=>{this.#N();let r=await this.#A({appId:e,appSecret:a,domain:A});this.#N();let s=this.#r.list().find(f=>f.appId===e),g=s?.id??this.#c();if(typeof g!="string"||!/^[A-Za-z0-9_-]{1,128}$/.test(g)||!s&&this.#r.getBot(g))throw new Error("Bot id generator returned an invalid or duplicate id");let c=s?.secretRef??Jz(g),I=await this.#t.resolve(c).catch(()=>{}),d={...s,id:g,appId:e,secretRef:c,ownerOpenIds:s?.ownerOpenIds?.length?s.ownerOpenIds:[Mk],domain:A,botName:r.name,botOpenId:r.openId,activated:r.activated,deletionPending:!1,connectedAt:new Date().toISOString(),createdAt:s?.createdAt??new Date().toISOString()};await this.#t.set(c,a);let B;try{B=await this.#r.saveBot(d)}catch(f){throw await this.#b(c,I),f}return await this.#T(g,async()=>{try{await this.#m(B,a),this.#a.delete(g)}catch{this.#a.set(g,{code:"connection_failed",message:"\u673A\u5668\u4EBA\u5DF2\u7ECF\u7ED1\u5B9A\uFF0C\u4F46\u957F\u8FDE\u63A5\u672A\u5C31\u7EEA\uFF0C\u8BF7\u70B9\u51FB\u91CD\u8BD5\u3002"})}}),this.#k(),this.status(g)})}async reconnectBot(t){return this.#N(),this.#T(t,async()=>{let o=this.#M(t);if(o.deletionPending)return this.#a.set(t,{code:"deletion_pending",message:"\u673A\u5668\u4EBA\u6B63\u5728\u7B49\u5F85\u5B8C\u6210\u672C\u5730\u5220\u9664\uFF0C\u8BF7\u91CD\u8BD5\u79FB\u9664\u3002"}),this.status(t);if(Wy(Vy(this.#I.get(t))))return this.status(t);let i;try{i=await this.#t.resolve(o.secretRef)}catch{i=null}if(!i?.value)return this.#a.set(t,{code:"missing_credentials",message:"\u673A\u5668\u4EBA\u51ED\u636E\u7F3A\u5931\uFF0C\u8BF7\u5220\u9664\u540E\u91CD\u65B0\u626B\u7801\u63A5\u5165\u3002"}),this.#k(),this.status(t);try{await this.#m(o,i.value),this.#a.delete(t)}catch{this.#a.set(t,{code:"connection_failed",message:"\u673A\u5668\u4EBA\u6682\u65F6\u65E0\u6CD5\u8FDE\u63A5\u98DE\u4E66\uFF0C\u8BF7\u91CD\u8BD5\u3002"})}return this.#k(),this.status(t)})}async sendConnectionTest(t){return this.#N(),this.#T(t,async()=>{let o=this.#M(t),i=this.#I.get(t);if(!Wy(Vy(i))||typeof i.sendConnectionTest!="function"){let e=new Error("\u98DE\u4E66\u673A\u5668\u4EBA\u5C1A\u672A\u8FDE\u63A5");throw e.code="test-target-unavailable",e}return i.sendConnectionTest(Ea(`${o.botName}\uFF08${Vz(o.appId)}\uFF09`,"\u98DE\u4E66\u673A\u5668\u4EBA"))})}async disconnectBot(t){return this.#N(),this.#T(t,async()=>(this.#M(t),await this.#_(t),this.#a.delete(t),this.#k(),this.status(t)))}async updateGroupResponseMode(t,o){if(this.#N(),!My(o))throw new TypeError("Invalid Feishu group response mode");return this.#G(()=>this.#T(t,async()=>{let i=this.#M(t);if(o==="all"&&i.groupMessagePermissionGranted!==!0){let a=new Error("Authorize im:message.group_msg before enabling all group messages");throw a.code="group_message_permission_required",a}let e=await this.#r.saveBot({...i,groupResponseMode:o});return this.#I.get(t)?.setGroupResponseMode?.(e.groupResponseMode),this.#k(),this.status(t)}))}async deleteBot(t){return this.#N(),this.#G(()=>this.#T(t,async()=>(this.#M(t),await this.#R(t),this.#k(),this.status())))}async reconnect(){let t=this.#r.list()[0];return t?this.reconnectBot(t.id):this.status()}async disconnect(){let t=this.#r.list()[0];return t?this.deleteBot(t.id):this.status()}async close(){if(this.#B)return;this.#B=!0;let t=[];for(let o of this.#n.values()){let i=o.manager.status().state;jz.has(o.operation)&&i==="saving"?(o.manager.cancel(),o.processing&&t.push(o.processing)):zy.has(i)&&(o.cancelled=!0,o.manager.cancel())}await this.#d,await Promise.allSettled([...this.#E.values()]),await Promise.allSettled([...this.#I.keys()].map(o=>this.#_(o))),await Promise.allSettled(t),await this.#d,await Promise.allSettled([...this.#E.values()]),await Promise.allSettled([...this.#I.keys()].map(o=>this.#_(o)))}#f({registration:t,selectedBotId:o}={}){let i=this.#r.list().map(I=>{let d=Vy(this.#I.get(I.id)),B=Wy(d),f=this.#a.get(I.id)??null;return{botId:I.id,phase:aTe({connected:B,error:f,connection:d}),connected:B,configured:!0,groupResponseMode:Pi(I.groupResponseMode),groupMessagePermissionGranted:I.groupMessagePermissionGranted===!0,bot:rTe(I),connection:d,error:f}}),e=t?this.#y(t):{state:"idle",attempt:0,updatedAt:Date.now()},a=_k.has(e.state),A=e.state==="saving",r=!!t&&(a||A),s=i.find(I=>I.botId===o)??(r?null:i[0]??null),g=i.some(I=>I.connected),c=s?.phase??"unconfigured";return a?c="registering":A?c="connecting":e.state==="error"&&!s&&(c="error"),{schemaVersion:2,revision:this.#h,phase:c,connected:s?.connected??!1,configured:i.length>0,bot:s?.bot??null,connection:s?.connection??zz(),error:s?.error??e.error??null,registration:e,bots:i,totals:{configured:i.length,connected:i.filter(I=>I.connected).length},anyConnected:g}}#y(t){let o=t.manager.status();return{...o,attempt:t.id,...t.botId?{botId:t.botId}:{},...t.operation?{operation:t.operation}:{},...t.stage?{stage:t.stage}:{},...o.state==="error"&&t.publicError?{error:{...t.publicError}}:{}}}async#w(t,o){let i=o.client_id,e=o.client_secret,a=Xy(o.user_info?.open_id),A=o.user_info?.tenant_brand,r=t.target;if(t.cancelled)throw this.#Q(t,"abort","Group message permission update was cancelled before local activation.");if(i!==r.appId)throw this.#Q(t,"repair_app_mismatch","Feishu returned credentials for a different app.");if(!a)throw this.#Q(t,"repair_owner_missing","Feishu returned no permission operator identity.");if(A!==void 0&&A!==r.domain)throw this.#Q(t,"repair_domain_mismatch","Feishu returned credentials for a different account domain.");if(!r.ownerOpenIds.includes(Mk)&&!r.ownerOpenIds.includes(a))throw this.#Q(t,"repair_owner_mismatch","The Feishu permission operator is not an owner of this configured bot.");t.stage="verifying_identity";let s;try{s=await this.#A({appId:i,appSecret:e,domain:r.domain})}catch(g){throw this.#Q(t,"repair_credentials_invalid","Feishu could not verify the updated app credentials.",g)}if(r.botOpenId&&s?.openId!==r.botOpenId)throw this.#Q(t,"repair_bot_mismatch","The updated Feishu app belongs to a different bot identity.");await this.#G(()=>this.#T(t.botId,async()=>{let g=this.#r.getBot(t.botId);if(!g||g.deletionPending||Zy(g)!==t.targetFingerprint)throw this.#Q(t,"repair_target_changed","The Feishu bot changed while its permission update was in progress.");let c;try{c=await this.#t.resolve(g.secretRef)}catch(d){throw this.#Q(t,"credential_update_failed","Unable to read the current Feishu credential.",d)}if(c?.value!==e){t.stage="persisting_secret";try{await this.#t.set(g.secretRef,e)}catch(B){if((await this.#t.resolve(g.secretRef).catch(()=>null))?.value!==e)throw this.#Q(t,"credential_update_failed","Unable to store the updated Feishu credential.",B)}if((await this.#t.resolve(g.secretRef).catch(()=>null))?.value!==e)throw this.#Q(t,"credential_state_unknown","The updated Feishu credential could not be confirmed after writing.")}t.stage="enabling_all_messages";let I;try{I=await this.#r.saveBot({...g,groupMessagePermissionGranted:!0,groupResponseMode:"all"})}catch(d){throw this.#Q(t,"group_message_permission_save_failed","The permission was accepted, but all-message mode could not be saved.",d)}t.stage="restarting";try{await this.#m(I,e)}catch(d){throw this.#a.set(t.botId,{code:"connection_failed",message:"\u7FA4\u6D88\u606F\u6743\u9650\u5DF2\u5F00\u901A\uFF0C\u4F46\u673A\u5668\u4EBA\u957F\u8FDE\u63A5\u672A\u5C31\u7EEA\uFF0C\u8BF7\u70B9\u51FB\u91CD\u8BD5\u3002"}),this.#k(),this.#Q(t,"group_message_permission_connection_failed","The permission was accepted, but the Feishu runtime could not restart.",d)}this.#a.delete(t.botId),t.stage="verified",t.publicError=null,this.#k()}))}async#u(t,o){let i=o.client_id,e=o.client_secret,a=Xy(o.user_info?.open_id),A=o.user_info?.tenant_brand,r=t.target;if(t.cancelled)throw this.#Q(t,"abort","Callback repair was cancelled before local activation.");if(i!==r.appId)throw this.#Q(t,"repair_app_mismatch","Feishu returned credentials for a different app.");if(!a)throw this.#Q(t,"repair_owner_missing","Feishu returned no repair operator identity.");if(A!==void 0&&A!==r.domain)throw this.#Q(t,"repair_domain_mismatch","Feishu returned credentials for a different account domain.");if(t.initiator.actorOpenId&&t.initiator.actorOpenId!==a)throw this.#Q(t,"repair_owner_mismatch","The Feishu repair was confirmed by a different operator.");if(!r.ownerOpenIds.includes(Mk)&&!r.ownerOpenIds.includes(a))throw this.#Q(t,"repair_owner_mismatch","The Feishu repair operator is not an owner of this configured bot.");t.stage="verifying_identity";let s;try{s=await this.#A({appId:i,appSecret:e,domain:r.domain})}catch(c){throw this.#Q(t,"repair_credentials_invalid","Feishu could not verify the repaired app credentials.",c)}if(r.botOpenId&&s?.openId!==r.botOpenId)throw this.#Q(t,"repair_bot_mismatch","The repaired Feishu app belongs to a different bot identity.");let g=await this.#G(()=>this.#T(t.botId,async()=>{let c=this.#r.getBot(t.botId);if(!c||c.deletionPending||Zy(c)!==t.targetFingerprint)throw this.#Q(t,"repair_target_changed","The Feishu bot changed while its callback repair was in progress.");let I;try{I=await this.#t.resolve(c.secretRef)}catch(f){throw this.#Q(t,"credential_update_failed","Unable to read the current Feishu credential.",f)}if(I?.value!==e){t.stage="persisting_secret";try{await this.#t.set(c.secretRef,e)}catch(Q){if((await this.#t.resolve(c.secretRef).catch(()=>null))?.value!==e)throw this.#Q(t,"credential_update_failed","Unable to store the repaired Feishu credential.",Q)}if((await this.#t.resolve(c.secretRef).catch(()=>null))?.value!==e)throw this.#Q(t,"credential_state_unknown","The repaired Feishu credential could not be confirmed after writing.")}let B;t.stage="restarting";try{await this.#m(c,e),B=this.#I.get(t.botId)}catch(f){throw this.#a.set(t.botId,{code:"connection_failed",message:"\u673A\u5668\u4EBA\u56DE\u8C03\u4FEE\u590D\u5DF2\u4FDD\u5B58\uFF0C\u4F46\u957F\u8FDE\u63A5\u672A\u5C31\u7EEA\uFF0C\u8BF7\u70B9\u51FB\u91CD\u8BD5\u3002"}),this.#k(),this.#Q(t,"repair_connection_failed","The repaired Feishu runtime could not be started.",f)}if(!B)throw this.#Q(t,"repair_connection_failed","The repaired Feishu runtime is unavailable.");return this.#a.delete(t.botId),this.#k(),B}));if(typeof g.beginCardActionProbe!="function")throw this.#Q(t,"card_action_probe_unavailable","The Feishu runtime cannot verify card callbacks.");t.stage="awaiting_callback";try{if((await g.beginCardActionProbe({expectedOperatorOpenId:a,timeoutMs:this.#C,...t.initiator.chatId?{chatId:t.initiator.chatId}:{}}))?.verified!==!0){let I=new Error("Feishu runtime returned no callback proof");throw I.code="card_action_probe_failed",I}}catch(c){let I=c?.code==="card_action_probe_timeout"?"card_action_probe_timeout":c?.code==="card_action_probe_unavailable"?"card_action_probe_unavailable":c?.code==="card_action_probe_send_failed"?"card_action_probe_send_failed":"card_action_probe_failed";throw this.#Q(t,I,I==="card_action_probe_timeout"?"Timed out waiting for the Feishu callback verification button.":"The Feishu card callback probe failed.",c)}t.stage="verified",t.publicError=null,this.#k()}#Q(t,o,i,e){t.publicError={code:o,message:i};let a=new Error(i,e?{cause:e}:void 0);return a.code=o,a}async#O(t,o){if(t.cancelled)throw new Error("Registration was cancelled");let i=o.client_id,e=o.client_secret,a=o.user_info?.open_id,A=o.user_info?.tenant_brand==="lark"?"lark":"feishu";if(!a)throw new Error("Feishu registration returned no owner open_id");let r=await this.#A({appId:i,appSecret:e,domain:A});if(t.cancelled)throw new Error("Registration was cancelled");let s=this.#r.list().find(Q=>Q.appId===i),g=s?.id??this.#c();if(typeof g!="string"||!/^[A-Za-z0-9_-]{1,128}$/.test(g)||!s&&this.#r.getBot(g))throw new Error("Bot id generator returned an invalid or duplicate id");let c=s?.secretRef??Jz(g),I=this.#l.get(g),d=await this.#t.resolve(c).catch(()=>{});await this.#t.set(c,e);let B;try{B=await this.#r.saveBot({...s,id:g,appId:i,secretRef:c,ownerOpenIds:[...new Set([...s?.ownerOpenIds??[],a])],domain:A,botName:r.name,botOpenId:r.openId,activated:r.activated,deletionPending:!1,connectedAt:new Date().toISOString(),createdAt:s?.createdAt??new Date().toISOString()}),t.botId=g,t.createdNew=!s,this.#l.set(g,t.id)}catch(Q){try{await this.#b(c,d)}catch(y){throw new Error("Unable to restore the Feishu credential after a config failure.",{cause:y})}throw Q}if(t.cancelled)throw t.createdNew?await this.#T(g,()=>this.#R(g)):(await this.#r.saveBot(s),await this.#b(c,d),I?this.#l.set(g,I):this.#l.delete(g)),new Error("Registration was cancelled");let f=!1;try{if(await this.#T(g,()=>this.#m(B,e)),t.cancelled)throw t.createdNew?await this.#T(g,()=>this.#R(g)):(await this.#r.saveBot(s),await this.#b(c,d),I?this.#l.set(g,I):this.#l.delete(g),d?.value&&!s.deletionPending?await this.#T(g,()=>this.#m(s,d.value)):await this.#T(g,()=>this.#_(g))),f=!0,new Error("Registration was cancelled");this.#a.delete(g),this.#k()}catch(Q){if(t.cancelled)throw!f&&t.createdNew&&this.#r.getBot(g)?await this.#T(g,()=>this.#R(g)):!f&&s&&(await this.#r.saveBot(s),await this.#b(c,d),I?this.#l.set(g,I):this.#l.delete(g),!this.#B&&d?.value&&!s.deletionPending?await this.#T(g,()=>this.#m(s,d.value)):await this.#T(g,()=>this.#_(g))),this.#k(),Q;if(s&&d?.value)try{throw await this.#r.saveBot(s),await this.#b(c,d),I?this.#l.set(g,I):this.#l.delete(g),s.deletionPending?(await this.#T(g,()=>this.#_(g)),this.#a.set(g,{code:"deletion_pending",message:"\u673A\u5668\u4EBA\u6B63\u5728\u7B49\u5F85\u5B8C\u6210\u672C\u5730\u5220\u9664\uFF0C\u8BF7\u91CD\u8BD5\u79FB\u9664\u3002"})):(await this.#T(g,()=>this.#m(s,d.value)),this.#a.delete(g)),this.#k(),Q}catch(y){throw y===Q?Q:(this.#a.set(g,{code:"connection_failed",message:"\u673A\u5668\u4EBA\u8FDE\u63A5\u66F4\u65B0\u5931\u8D25\uFF0C\u4E14\u539F\u8FDE\u63A5\u65E0\u6CD5\u6062\u590D\uFF0C\u8BF7\u91CD\u8BD5\u3002"}),this.#k(),new Error("Unable to restore the previous Feishu bot connection.",{cause:y}))}throw this.#a.set(g,{code:"connection_failed",message:"\u673A\u5668\u4EBA\u5DF2\u7ECF\u521B\u5EFA\uFF0C\u4F46\u957F\u8FDE\u63A5\u672A\u5C31\u7EEA\uFF0C\u8BF7\u70B9\u51FB\u91CD\u8BD5\u3002"}),this.#k(),Q}}async#m(t,o){await this.#_(t.id);let i=await this.#o({botId:t.id,config:t,appSecret:o,repair:this.#S(t.id)});this.#I.set(t.id,i);try{await i.start()}catch(e){throw this.#I.get(t.id)===i&&this.#I.delete(t.id),await i.stop({preserveError:!0}).catch(()=>{}),e}}#S(t){let o=i=>{let e=this.#n.get(i);return e?.operation===BC&&e.botId===t?e:null};return Object.freeze({start:({actorOpenId:i,chatId:e}={})=>this.startCallbackRepair(t,{actorOpenId:i,chatId:e}),status:({attemptId:i}={})=>o(i)?this.registrationStatus(i):null,cancel:async({attemptId:i}={})=>o(i)?this.cancelRegistration(i):this.status(t)})}async#_(t){let o=this.#I.get(t);this.#I.delete(t),o&&await o.stop()}async#R(t){let o=this.#r.getBot(t);if(o){o.deletionPending||(o=await this.#r.saveBot({...o,deletionPending:!0})),await this.#_(t);try{await this.#t.unset(o.secretRef)}catch(i){throw this.#a.set(t,{code:"credential_removal_failed",message:"\u65E0\u6CD5\u5220\u9664\u673A\u5668\u4EBA\u51ED\u636E\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002"}),new Error("Unable to remove the Feishu credential.",{cause:i})}try{await this.#i({botId:t,config:o})}catch(i){throw this.#a.set(t,{code:"state_cleanup_failed",message:"\u65E0\u6CD5\u5220\u9664\u673A\u5668\u4EBA\u7684\u672C\u5730\u4F1A\u8BDD\u6570\u636E\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002"}),new Error("Unable to remove the Feishu bot session state.",{cause:i})}await this.#r.removeBot(t),this.#a.delete(t),this.#l.delete(t)}}async#b(t,o){o?.value?await this.#t.set(t,o.value):await this.#t.unset(t)}#M(t){let o=this.#r.getBot(t);if(!o)throw new Error("Unknown Feishu bot");return o}#N(){if(this.#B)throw new Error("The Feishu controller is closed")}#G(t){let o=this.#d.then(t,t);return this.#d=o.then(()=>{},()=>{}),o}#T(t,o){let e=(this.#E.get(t)??Promise.resolve()).then(o,o),a=e.then(()=>{},()=>{});return this.#E.set(t,a),a.finally(()=>{this.#E.get(t)===a&&this.#E.delete(t)}),e}#F(){if(!(this.#n.size<=32))for(let[t,o]of this.#n){if(t===this.#p)continue;let i=o.manager.status().state;if(!_k.has(i)&&i!=="saving"&&this.#n.delete(t),this.#n.size<=32)break}}#k(){this.#h+=1}};function gTe(n){for(let t of["https_proxy","HTTPS_PROXY","http_proxy","HTTP_PROXY"]){let o=n?.[t];if(typeof o=="string"&&o.trim())return o.trim()}}function cTe(n,t=o=>new Wz.default(o)){let o=gTe(n);return o?t(o):void 0}function ITe(n,t){if(t!==void 0)return new URL(t);let o=n?.port;if(!Number.isInteger(o)||o<1||o>65535)throw new Error("dsh-feishu requires an initialized DSH webServer port");return new URL(`http://127.0.0.1:${o}`)}function lTe(n){let t=Fg(n.dshHome??process.env.DSH_HOME??Rp(nTe(),".dsh")),o=Fg(n.dataDir??Rp(t,"integrations","dsh-feishu"));return{root:o,config:Fg(n.configPath??Rp(o,"config.json")),legacyState:Fg(n.statePath??Rp(o,"state.json")),bots:Fg(n.botsDir??Rp(o,"bots")),workspaces:Fg(n.workspacesPath??Rp(o,"workspaces.json"))}}async function Tk(n,t={},o={}){if(!n?.credentials)throw new TypeError("dsh-feishu requires ctx.credentials");if(!n?.webServer)throw new TypeError("dsh-feishu requires ctx.webServer");let i=o.lark??Ek,e=o.Controller??fC,a=o.ConfigStore??xy,A=o.StateStore??Oy,r=o.HarnessClient??Hy,s=o.FeishuRuntime??Uy,g=o.verifyFeishuApp??gz,c=we=>g({...we,httpInstance:i.defaultHttpInstance}),I=o.createConnectionSupervisor??Ck,d=typeof n.logger=="function"?n.logger("dsh-feishu"):n.logger??console,B=()=>Ba(n),f=lTe(t),Q=await new a(f.config).load(),y=Fg(t.workspace??process.cwd()),m=o.WorkspaceStore??Jr,_=o.workspaces??await new m(f.workspaces,{defaultWorkspace:y}).load(),N=typeof Q.list=="function",G=()=>N?Q.list():[],Y=G();N&&await _.reconcile(Y.map(we=>we.id)),await Promise.all(Y.map(we=>_.ensure(we.id,{defaultAgentPreset:t.agentPreset})));let j=typeof Q.removeBot=="function"?fa(Q,{workspaces:_,method:"removeBot",botIdFromRemoved:we=>we.id}):Q,x=new Map,q=we=>!we.id||!we.secretRef||we.secretRef===Yy?f.legacyState:Fg(f.bots,we.id,"state.json"),J=async we=>{let Be=we.id??"__legacy__",Pe=x.get(Be);return Pe||(Pe=await new A(q(we)).load(),x.set(Be,Pe)),Pe},F=async we=>{let Be=G().find(Pe=>Pe.id===we);if(!Be)throw new Error("Unknown Feishu bot");return J(Be)},P=ma(n,o.commandExecutor),{controlExecutor:V,sessionMaintenanceExecutor:K,fileIngressExecutor:T}=Sa(n,{controlExecutor:o.controlExecutor,sessionMaintenanceExecutor:o.sessionMaintenanceExecutor,fileIngressExecutor:o.fileIngressExecutor}),v=new r({baseUrl:ITe(n.webServer,t.harnessBaseUrl),workspace:y,autostart:!1,dshBin:t.dshBin??"dsh",...P?{commandExecutor:P}:{},...V?{controlExecutor:V}:{},...K?{sessionMaintenanceExecutor:K}:{},...T?{fileIngressExecutor:T}:{}}),W=o.proxyEnv??process.env,se=cTe(W,o.createProxyAgent),ye=new e({registerApp:we=>i.registerApp(we),verifyApp:c,credentials:n.credentials,configStore:j,createRuntime:async({botId:we,config:Be,appSecret:Pe,repair:Ve})=>{let rA=await J(Be),Fe=we??Be.id??Be.appId;await _.ensure(Fe,{defaultAgentPreset:t.agentPreset});let iA=Qa(v,{botId:Fe,workspaces:_,state:rA,agentPresetCatalog:B});return new s({lark:i,botId:Fe,repair:Ve,appId:Be.appId,appSecret:Pe,domain:Be.domain,botOpenId:Be.botOpenId,groupResponseMode:Be.groupResponseMode,ownerOpenIds:Be.ownerOpenIds??[Be.ownerOpenId],harness:iA.harness,state:iA.state,replyTimeoutMs:t.replyTimeoutMs??6e5,...se?{wsAgent:se}:{},logger:{error:(...Ce)=>d.error?.(`[${we??Be.id}]`,...Ce),warn:(...Ce)=>d.warn?.(`[${we??Be.id}]`,...Ce),info:(...Ce)=>d.info?.(`[${we??Be.id}]`,...Ce),debug:(...Ce)=>d.debug?.(`[${we??Be.id}]`,...Ce)}})},deleteState:async({botId:we,config:Be})=>{x.delete(we);try{await sTe(q(Be))}catch(Pe){if(Pe?.code!=="ENOENT")throw Pe}}}),Me=ya(ye,{workspaces:_,stateFor:F,agentPresetCatalog:B}),fe=I({controller:Me,harness:v,logger:d,retryDelaysMs:t.retryDelaysMs,healthyIntervalMs:t.healthyIntervalMs}).start();return{controller:Me,ready:fe.ready,async close(){await fe.close(),await Me.close(),v.stopManagedProcess(),se?.destroy?.()}}}import TTe from"qrcode";var vp=ze(Fk(),1);var bTe=ze(Fk(),1);var MTe=Object.freeze({$locale:"en",IM\u673A\u5668\u4EBA:"IM bots",IM\u673A\u5668\u4EBA\u8BBE\u7F6E:"IM bot settings","IM \u6E20\u9053":"IM channels","\u8BA9 DeepSeek Harness \u89E6\u624B\u53EF\u53CA":"DeepSeek Harness, always within reach","AI Office":"AI Office","\uFF08\u5B9E\u9A8C\u529F\u80FD\uFF09":"(Experimental)","AI Office \u8BBE\u7F6E":"AI Office settings","AI Office \u8BBE\u7F6E\u9875\u7F3A\u5C11 RPC \u8FDE\u63A5":"AI Office settings are missing an RPC connection","\u6B63\u5728\u8BFB\u53D6 AI Office Connector\u2026":"Loading AI Office Connector\u2026","\u672C\u673A\u4E3B\u52A8\u8FDE\u63A5\u516C\u7F51 Office\uFF1BHarness \u4E0D\u5F00\u653E\u7AEF\u53E3\u3002\u534F\u8BAE Hook \u56FA\u5B9A\u4E3A ":"This machine connects outward to the public Office; Harness exposes no port. Protocol hooks: ",\u5C1A\u672A\u914D\u7F6E:"Not configured","\u5DF2\u8FDE\u63A5 Office":"Connected to Office",\u5DF2\u914D\u7F6E:"Configured",\u7B49\u5F85\u91CD\u8FDE:"Waiting to reconnect",\u51ED\u636E\u7F3A\u5931:"Credential missing",\u6700\u8FD1\u5FC3\u8DF3:"Last heartbeat",\u6700\u8FD1\u4E8B\u4EF6:"Last event",\u91CD\u8FDE\u6B21\u6570:"Reconnects","\u8FD0\u884C Job":"Running Jobs","\u5B8C\u6210 Job":"Completed Jobs",\u5C1A\u65E0:"None yet",\u8BBE\u5907\u8FDE\u63A5:"Device connection","Token \u53EA\u5199\u5165\u672C\u673A\u51ED\u636E\u5B58\u50A8":"Token is written only to the local credential store","\u7C98\u8D34 Office \u4E00\u6B21\u6027\u51ED\u636E":"Paste the one-time Office credential","\u5DF2\u5B89\u5168\u4FDD\u5B58\uFF1B\u7559\u7A7A\u4FDD\u6301\u4E0D\u53D8":"Stored securely; leave blank to keep it",\u6700\u5927\u5E76\u53D1:"Max concurrency","Heartbeat \u79D2\u6570":"Heartbeat seconds","Workspace \u6620\u5C04":"Workspace mappings","\u6BCF\u884C alias=/\u672C\u673A/\u7EDD\u5BF9\u8DEF\u5F84\uFF1BOffice \u53EA\u80FD\u770B\u5230 alias\u3002":"One alias=/local/absolute/path per line; Office sees only aliases.","Instruction Preset \u6620\u5C04":"Instruction preset mappings","\u6BCF\u884C alias=\u6307\u4EE4\uFF1B\u65B0\u589E preset \u4E0D\u9700\u8981\u6539 Office \u4EE3\u7801\u3002":"One alias=instruction per line; new presets require no Office code change.",\u4FDD\u5B58\u5E76\u8FDE\u63A5:"Save and connect",\u6D4B\u8BD5\u8FDE\u63A5:"Test connection","\u6D4B\u8BD5\u4E2D\u2026":"Testing\u2026",\u91CD\u65B0\u8FDE\u63A5:"Reconnect",\u79FB\u9664\u8FDE\u63A5:"Remove connection","\u8FDE\u63A5\u6D4B\u8BD5\u901A\u8FC7\u3002":"Connection test passed.","\u914D\u7F6E\u5DF2\u4FDD\u5B58\u3002":"Configuration saved.","\u534F\u8BAE Hook \u9884\u89C8":"Protocol hook preview","\u7531 Base URL \u81EA\u52A8\u6D3E\u751F\uFF0C\u4E0D\u5355\u72EC\u586B\u5199":"Derived from Base URL; no separate input","Base URL \u65E0\u6548":"Invalid Base URL","Office Hook \u5C1A\u672A\u90E8\u7F72\u65F6\uFF0C\u914D\u7F6E\u4F1A\u5B89\u5168\u4FDD\u5B58\u5E76\u81EA\u52A8\u91CD\u8BD5\uFF1B\u51FA\u73B0 HTTP 404 \u4EE3\u8868\u534F\u8BAE\u7AEF\u70B9\u5F85\u4E0A\u7EBF\uFF0C\u4E0D\u4EE3\u8868 Harness \u6545\u969C\u3002":"Configuration is saved and retried while Office hooks are unavailable; HTTP 404 means the protocol endpoint is pending, not a Harness failure.","Workspace \u6620\u5C04\u6BCF\u884C\u5FC5\u987B\u4F7F\u7528 alias=value":"Each workspace mapping must use alias=value","Instruction Preset \u6620\u5C04\u6BCF\u884C\u5FC5\u987B\u4F7F\u7528 alias=value":"Each instruction preset mapping must use alias=value","action-items=\u8F6C\u6362\u4E3A\u8D1F\u8D23\u4EBA\u3001\u622A\u6B62\u548C\u9A8C\u6536\u660E\u786E\u7684\u5DE5\u5355":"action-items=Turn this into accountable tasks with deadlines and acceptance criteria","AI Office \u62D2\u7EDD\u4E86 Device Token\u3002":"AI Office rejected the Device Token.","AI Office Connector Hook \u5C1A\u672A\u5C31\u7EEA\u3002":"AI Office Connector hooks are not available yet.","AI Office Connector \u534F\u8BAE\u7248\u672C\u4E0D\u517C\u5BB9\u3002":"The AI Office Connector protocol is incompatible.","\u672C\u673A\u6682\u65F6\u65E0\u6CD5\u8BBF\u95EE AI Office\u3002":"AI Office cannot currently be reached from this machine.","AI Office \u8FDE\u63A5\u5DF2\u4E2D\u65AD\u3002":"The AI Office connection was interrupted.","\u5E2E\u52A9\u4E0E\u53CD\u9988 \xB7 \u524D\u5F80 GitHub":"Help & feedback \xB7 Open GitHub",\u5FAE\u4FE1:"WeChat",\u98DE\u4E66:"Feishu",\u9489\u9489:"DingTalk",\u4F01\u4E1A\u5FAE\u4FE1:"WeCom",\u5FAE\u4FE1\u673A\u5668\u4EBA:"WeChat bot",\u98DE\u4E66\u673A\u5668\u4EBA:"Feishu bot",\u9489\u9489\u673A\u5668\u4EBA:"DingTalk bot",\u4F01\u4E1A\u5FAE\u4FE1\u673A\u5668\u4EBA:"WeCom bot",QQ\u673A\u5668\u4EBA:"QQ bot",WhatsApp\u673A\u5668\u4EBA:"WhatsApp bot",WhatsApp\u8D26\u53F7:"WhatsApp account",\u5FAE\u4FE1\u8BBE\u7F6E:"WeChat settings",\u98DE\u4E66\u673A\u5668\u4EBA\u8BBE\u7F6E:"Feishu bot settings",\u7FA4\u804A\u54CD\u5E94\u65B9\u5F0F:"Group response mode","\u4EC5\u5728 @\u673A\u5668\u4EBA\u65F6\u54CD\u5E94\uFF08\u63A8\u8350\uFF09":"Only respond when @mentioned (recommended)",\u54CD\u5E94\u6240\u6709\u7FA4\u6D88\u606F:"Respond to all group messages","\u54CD\u5E94\u6240\u6709\u7FA4\u6D88\u606F\uFF08\u9700\u98DE\u4E66\u654F\u611F\u6743\u9650\uFF09":"Respond to all group messages (requires a sensitive Feishu scope)",\u91CD\u65B0\u6388\u6743:"Reauthorize",\u53BB\u6388\u6743:"Authorize",\u91CD\u65B0\u6388\u6743\u7FA4\u6D88\u606F\u6743\u9650:"Reauthorize group-message permission",\u6388\u6743\u7FA4\u6D88\u606F\u6743\u9650:"Authorize group-message permission","\u6B63\u5728\u51C6\u5907\u6388\u6743\u2026":"Preparing authorization\u2026","\u6B63\u5728\u51C6\u5907\u2026":"Preparing\u2026","\u79C1\u804A\u59CB\u7EC8\u54CD\u5E94\uFF1B\u7FA4\u804A\u4EC5\u5904\u7406\u660E\u786E @\u5F53\u524D\u673A\u5668\u4EBA\u7684\u6D88\u606F\u3002\u7FA4\u6D88\u606F\u6743\u9650\u5DF2\u5F00\u901A\uFF0C\u518D\u6B21\u5207\u6362\u65E0\u9700\u6388\u6743\u3002":"Direct messages always work; group chats require an explicit @mention of this bot. The group-message permission is already granted, so switching again needs no authorization.","\u79C1\u804A\u59CB\u7EC8\u54CD\u5E94\uFF1B\u7FA4\u804A\u4EC5\u5904\u7406\u660E\u786E @\u5F53\u524D\u673A\u5668\u4EBA\u7684\u6D88\u606F\u3002\u9009\u62E9\u5168\u90E8\u6D88\u606F\u540E\u4F1A\u6253\u5F00\u98DE\u4E66\u5B98\u65B9\u6388\u6743\u6D41\u7A0B\u3002":"Direct messages always work; group chats require an explicit @mention of this bot. Selecting all messages opens the official Feishu authorization flow.","\u5DF2\u5F00\u901A\u201C\u83B7\u53D6\u7FA4\u7EC4\u4E2D\u6240\u6709\u6D88\u606F\u201D\u6743\u9650\uFF08im:message.group_msg\uFF09\uFF1B\u673A\u5668\u4EBA\u4F1A\u5904\u7406\u7FA4\u804A\u4E2D\u7684\u6240\u6709\u53EF\u89C1\u6D88\u606F\u3002":"The \u201CRead all messages in associated group chat\u201D scope (im:message.group_msg) is granted; the bot processes every visible group message.","\u5C1A\u672A\u786E\u8BA4\u201C\u83B7\u53D6\u7FA4\u7EC4\u4E2D\u6240\u6709\u6D88\u606F\u201D\u6743\u9650\uFF0C\u8BF7\u5B8C\u6210\u98DE\u4E66\u6388\u6743\u3002":"The \u201CRead all messages in associated group chat\u201D scope has not been confirmed. Complete Feishu authorization.","\u79C1\u804A\u59CB\u7EC8\u54CD\u5E94\uFF1B\u7FA4\u804A\u4EC5\u5904\u7406\u660E\u786E @\u5F53\u524D\u673A\u5668\u4EBA\u7684\u6D88\u606F\u3002":"Direct messages always work; group chats require an explicit @mention of this bot.","\u9700\u5728\u98DE\u4E66\u4E3A\u8BE5\u673A\u5668\u4EBA\u5F00\u901A\u201C\u83B7\u53D6\u7FA4\u7EC4\u4E2D\u6240\u6709\u6D88\u606F\u201D\u6743\u9650\uFF08im:message.group_msg\uFF09\uFF1B\u5F00\u901A\u540E\uFF0C\u673A\u5668\u4EBA\u4F1A\u5904\u7406\u7FA4\u804A\u4E2D\u7684\u6240\u6709\u53EF\u89C1\u6D88\u606F\u3002":"Grant this bot the \u201CRead all messages in associated group chat\u201D Feishu scope (im:message.group_msg); once granted, it will process every visible group message.","\u7FA4\u804A\u54CD\u5E94\u65B9\u5F0F\u4FEE\u6539\u5931\u8D25\uFF0C\u8BF7\u91CD\u8BD5\u3002":"Could not update the group response mode. Try again.","\u7FA4\u6D88\u606F\u6743\u9650\u6388\u6743\u5931\u8D25\uFF0C\u8BF7\u91CD\u8BD5\u3002":"Could not authorize group-message permission. Try again.",\u9489\u9489\u8BBE\u7F6E:"DingTalk settings",\u4F01\u4E1A\u5FAE\u4FE1\u8BBE\u7F6E:"WeCom settings",\u626B\u7801\u63A5\u5165\u673A\u5668\u4EBA:"Scan QR code",\u6B63\u5728\u63A5\u5165:"Connecting",\u624B\u52A8\u63A5\u5165:"Manual setup",\u6536\u8D77\u51ED\u636E:"Hide credentials",\u6536\u8D77\u63A5\u5165:"Hide setup",\u63A5\u5165\u673A\u5668\u4EBA:"Connect bot",\u5F00\u59CB\u63A5\u5165:"Start setup",\u5728\u7EBF:"online",\u8FD0\u884C\u6B63\u5E38:"Connected",\u6B63\u5728\u8FDE\u63A5:"Connecting","\u6B63\u5728\u8FDE\u63A5\u2026":"Connecting\u2026",\u8FDE\u63A5\u672A\u5C31\u7EEA:"Not connected",\u8FDE\u63A5\u4E2D:"Connecting",\u8FDE\u63A5\u4E2D\u65AD:"Disconnected",\u9700\u8981\u5904\u7406:"Needs attention",\u72B6\u6001\u672A\u77E5:"Unknown status",\u79BB\u7EBF:"Offline",\u5DF2\u65AD\u5F00:"Disconnected",\u6D88\u606F\u901A\u9053:"Message channel",\u67E5\u770B\u6D88\u606F\u901A\u9053\u8BF4\u660E:"View message channel details",\u6700\u8FD1\u68C0\u67E5:"Last checked",\u5F53\u524D\u5DE5\u4F5C\u533A:"Current workspace",\u9009\u62E9\u76EE\u5F55:"Choose folder",\u9009\u62E9\u673A\u5668\u4EBA\u5DE5\u4F5C\u533A\u76EE\u5F55:"Select bot workspace folder",\u5F53\u524D\u76EE\u5F55:"Current folder",\u4E3B\u76EE\u5F55:"Home","\u6B63\u5728\u51C6\u5907\u76EE\u5F55\u9009\u62E9\u5668\u2026":"Preparing folder picker\u2026","\u6B63\u5728\u8BFB\u53D6\u76EE\u5F55\u2026":"Loading folders\u2026","\u8FD9\u4E2A\u76EE\u5F55\u4E2D\u6CA1\u6709\u5B50\u6587\u4EF6\u5939\u3002":"This folder has no subfolders.","\u6B64\u76EE\u5F55\u7684\u5B50\u6587\u4EF6\u5939\u8FC7\u591A\uFF0C\u4EC5\u663E\u793A\u524D\u4E00\u90E8\u5206\u3002":"This folder has too many subfolders; only the first group is shown.","\u65E0\u6CD5\u8BFB\u53D6\u76EE\u5F55\uFF0C\u8BF7\u91CD\u8BD5\u3002":"Could not load the folder. Try again.",\u91CD\u8BD5:"Retry",\u663E\u793A\u9690\u85CF\u6587\u4EF6\u5939:"Show hidden folders","\u5207\u6362\u540E\u4F1A\u6E05\u9664\u8FD9\u4E2A\u673A\u5668\u4EBA\u7684\u65E7\u4F1A\u8BDD\u6620\u5C04\u3002":"Switching clears this bot\u2019s previous session mappings.","\u5207\u6362\u4E2D\u2026":"Switching\u2026",\u9009\u62E9\u6B64\u76EE\u5F55:"Select this folder",\u5DE5\u4F5C\u533A\u7EDD\u5BF9\u8DEF\u5F84:"Absolute workspace path","/\u7EDD\u5BF9\u8DEF\u5F84/\u5230/\u5DE5\u4F5C\u533A":"/absolute/path/to/workspace",\u4FEE\u6539:"Change",\u4FDD\u5B58:"Save","\u4FDD\u5B58\u4E2D\u2026":"Saving\u2026",\u672A\u8BBE\u7F6E:"Not set","\u5DE5\u4F5C\u533A\u4FEE\u6539\u5931\u8D25\uFF0C\u8BF7\u91CD\u8BD5\u3002":"Could not update the workspace. Try again.","\u8BF7\u8F93\u5165\u5DE5\u4F5C\u533A\u7EDD\u5BF9\u8DEF\u5F84\u3002":"Enter an absolute workspace path.","\u5DE5\u4F5C\u533A\u5FC5\u987B\u662F\u7EDD\u5BF9\u8DEF\u5F84\u3002":"The workspace must be an absolute path.","\u5DE5\u4F5C\u533A\u8DEF\u5F84\u4E0D\u5B58\u5728\u3002":"The workspace path does not exist.","\u5DE5\u4F5C\u533A\u8DEF\u5F84\u5FC5\u987B\u6307\u5411\u4E00\u4E2A\u76EE\u5F55\u3002":"The workspace path must point to a directory.","\u627E\u4E0D\u5230\u8981\u4FEE\u6539\u7684\u673A\u5668\u4EBA\u3002":"The bot could not be found.","Agent Preset":"Agent Preset","\u67E5\u770B Agent Preset \u8BF4\u660E":"View Agent Preset help","\u8DDF\u968F Host \u9ED8\u8BA4":"Follow the Host default","\uFF08\u5DF2\u4E0D\u53EF\u7528\uFF09":" (unavailable)","\u53EA\u5F71\u54CD\u65B0\u5EFA\u4F1A\u8BDD\uFF1B\u82E5\u5F53\u524D\u804A\u5929\u5DF2\u6709\u4F1A\u8BDD\uFF0C\u5148\u53D1\u9001 /new\uFF0C\u518D\u53D1\u9001\u666E\u901A\u6D88\u606F\u751F\u6548\u3002":"This affects only new sessions. If the current chat already has a session, send /new, then send a regular message to apply it.","\u5F53\u524D Agent Preset \u5DF2\u4E0D\u53EF\u7528\uFF0C\u8BF7\u9009\u62E9\u5176\u4ED6 Preset \u6216\u8DDF\u968F Host \u9ED8\u8BA4\u3002":"The current Agent Preset is unavailable. Choose another preset or follow the Host default.","Agent Preset \u4FEE\u6539\u5931\u8D25\uFF0C\u8BF7\u91CD\u8BD5\u3002":"Could not update the Agent Preset. Try again.","\u8BF7\u9009\u62E9 Agent Preset\u3002":"Choose an Agent Preset.","Agent Preset \u65E0\u6548\u3002":"The Agent Preset is invalid.","Agent Preset \u4E0D\u5B58\u5728\u6216\u4E0D\u53EF\u7528\u3002":"The Agent Preset does not exist or is unavailable.",\u5C1A\u672A\u68C0\u67E5:"Not checked yet",\u521A\u521A:"Just now",\u68C0\u67E5\u8FDE\u63A5:"Check connection","\u68C0\u67E5\u4E2D\u2026":"Checking\u2026","\u8FDE\u63A5\u68C0\u67E5\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002":"Connection check failed. Try again later.","\u6D4B\u8BD5\u6D88\u606F\u5DF2\u53D1\u9001\uFF0C\u8BF7\u5230\u5BF9\u5E94\u673A\u5668\u4EBA\u4F1A\u8BDD\u4E2D\u786E\u8BA4\u3002":"Test message sent. Check the matching bot conversation.","\u8FDE\u63A5\u68C0\u67E5\u5B8C\u6210\u3002\u673A\u5668\u4EBA\u5C1A\u672A\u6536\u5230\u53EF\u7528\u4E8E\u6D4B\u8BD5\u7684\u79C1\u804A\u6D88\u606F\u3002":"Connection check completed. The bot has not received a direct message it can use for testing.","\u8FDE\u63A5\u68C0\u67E5\u5B8C\u6210\uFF0C\u4F46\u6D4B\u8BD5\u6D88\u606F\u53D1\u9001\u5931\u8D25\u3002":"Connection check completed, but the test message could not be sent.","\u6D4B\u8BD5\u6D88\u606F\u5DF2\u53D1\u9001\uFF0C\u8BF7\u5230\u98DE\u4E66\u4F1A\u8BDD\u4E2D\u786E\u8BA4\u3002":"Test message sent. Check the Feishu conversation.","\u6D4B\u8BD5\u6D88\u606F\u5DF2\u53D1\u9001\uFF0C\u8BF7\u5230 WhatsApp \u81EA\u804A\u4F1A\u8BDD\u4E2D\u786E\u8BA4\u3002":"Test message sent. Check the WhatsApp self-chat.","\u8FDE\u63A5\u68C0\u67E5\u5B8C\u6210\uFF0C\u4F46\u5F53\u524D\u6CA1\u6709\u53EF\u7528\u7684 WhatsApp \u81EA\u804A\u76EE\u6807\u3002":"Connection check completed, but no WhatsApp self-chat target is available.","\u9489\u9489\u8FDE\u63A5\u68C0\u67E5\u5B8C\u6210\uFF0C\u6D4B\u8BD5\u6D88\u606F\u5DF2\u53D1\u9001\u3002":"DingTalk connection check completed and the test message was sent.","\u9489\u9489\u8FDE\u63A5\u68C0\u67E5\u5B8C\u6210\uFF0C\u4F46\u6D4B\u8BD5\u6D88\u606F\u53D1\u9001\u5931\u8D25\u3002":"DingTalk connection check completed, but the test message could not be sent.","\u5FAE\u4FE1\u8FDE\u63A5\u68C0\u67E5\u5B8C\u6210\uFF0C\u6D4B\u8BD5\u6D88\u606F\u5DF2\u53D1\u9001\u3002":"WeChat connection check completed and the test message was sent.","\u5FAE\u4FE1\u8FDE\u63A5\u68C0\u67E5\u5B8C\u6210\uFF0C\u4F46\u6D4B\u8BD5\u6D88\u606F\u53D1\u9001\u5931\u8D25\u3002":"WeChat connection check completed, but the test message could not be sent.","\u4F01\u4E1A\u5FAE\u4FE1\u8FDE\u63A5\u68C0\u67E5\u5B8C\u6210\uFF0C\u6D4B\u8BD5\u6D88\u606F\u5DF2\u53D1\u9001\u3002":"WeCom connection check completed and the test message was sent.","\u4F01\u4E1A\u5FAE\u4FE1\u8FDE\u63A5\u68C0\u67E5\u5B8C\u6210\uFF0C\u4F46\u6D4B\u8BD5\u6D88\u606F\u53D1\u9001\u5931\u8D25\u3002":"WeCom connection check completed, but the test message could not be sent.",\u91CD\u8BD5\u8FDE\u63A5:"Reconnect","\u91CD\u8BD5\u4E2D\u2026":"Retrying\u2026",\u79FB\u9664\u63A5\u5165:"Remove connection",\u786E\u8BA4\u79FB\u9664\u63A5\u5165:"Remove connection",\u786E\u8BA4\u79FB\u9664:"Remove","\u6B63\u5728\u79FB\u9664\u2026":"Removing\u2026",\u4FDD\u7559\u673A\u5668\u4EBA:"Keep bot",\u4FDD\u7559\u8D26\u53F7:"Keep account",\u53D6\u6D88:"Cancel",\u5173\u95ED:"Close",\u7ACB\u5373\u91CD\u8BD5:"Retry now",\u91CD\u65B0\u8BFB\u53D6:"Reload",\u91CD\u65B0\u751F\u6210\u4E8C\u7EF4\u7801:"Generate a new QR code",\u91CD\u65B0\u751F\u6210\u4E8C\u7EF4\u7801\u540E\u7EE7\u7EED:"Generate a new QR code",\u5237\u65B0\u4E8C\u7EF4\u7801:"Refresh QR code","\u5237\u65B0\u4E2D\u2026":"Refreshing\u2026",\u6362\u4E00\u4E2A\u4E8C\u7EF4\u7801:"Get another QR code",\u7EE7\u7EED\u8FDE\u63A5:"Continue connecting",\u7ED1\u5B9A\u5E76\u8FDE\u63A5:"Connect","\u6B63\u5728\u7ED1\u5B9A\u2026":"Connecting\u2026",\u9A8C\u8BC1\u5E76\u8FDE\u63A5:"Verify and connect","\u6B63\u5728\u9A8C\u8BC1\u5E76\u8FDE\u63A5\u2026":"Verifying and connecting\u2026","\u6B63\u5728\u9A8C\u8BC1\u2026":"Verifying\u2026","\u64CD\u4F5C\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5":"The operation failed. Try again later.",\u8BF7\u7A0D\u540E\u91CD\u8BD5:"Try again later.",\u5F53\u524D\u4E8C\u7EF4\u7801\u6709\u6548\u65F6\u95F4:"QR code expires in",\u4E8C\u7EF4\u7801\u6709\u6548\u65F6\u95F4:"QR code expires in",\u4E8C\u7EF4\u7801\u5DF2\u8FC7\u671F:"QR code expired",\u4E8C\u7EF4\u7801\u5DF2\u5931\u6548:"QR code expired","\u4E8C\u7EF4\u7801\u5DF2\u8FC7\u671F\n\u8BF7\u91CD\u65B0\u751F\u6210":`QR code expired +`,{encoding:"utf8",mode:384}),await L_e(o,this.#e)}};import{randomUUID as qz}from"node:crypto";var wk=new Set(["starting","qr_ready","polling","slow_down","domain_switched","saving"]),j_e=new Set(["polling","slow_down","domain_switched"]),pi=Object.freeze({IDLE:"idle",STARTING:"starting",QR_READY:"qr_ready",POLLING:"polling",SLOW_DOWN:"slow_down",DOMAIN_SWITCHED:"domain_switched",SAVING:"saving",SUCCEEDED:"succeeded",EXPIRED:"expired",CANCELLED:"cancelled",ERROR:"error"});function xz(n){return["access_denied","expired_token","abort"].includes(n?.code)?n.code:"registration_failed"}function Ok(n){let t=xz(n);return{code:t,message:{access_denied:"Registration was denied.",abort:"Registration was cancelled.",expired_token:"The registration QR code expired."}[t]??"Unable to register the Feishu app."}}function J_e(n){let t=Number(n);if(!Number.isFinite(t)||t<=0)throw new TypeError("registerApp onQRCodeReady returned an invalid expireIn");return t}function q_e(n){if(n!==void 0){if(n===null||typeof n!="object"||Array.isArray(n))throw new TypeError("registerApp returned invalid user_info");return{...n}}}var Fs=class{#e;#A;#t;#r;#o;#i=0;#c=null;#s;constructor({registerApp:t,onCredentials:o,now:i=Date.now,setTimeout:e=globalThis.setTimeout,clearTimeout:a=globalThis.clearTimeout}={}){if(typeof t!="function")throw new TypeError("RegistrationManager requires a registerApp function");if(typeof o!="function")throw new TypeError("RegistrationManager requires an onCredentials function");if(typeof i!="function"||typeof e!="function"||typeof a!="function")throw new TypeError("RegistrationManager clock dependencies must be functions");this.#e=t,this.#A=o,this.#t=i,this.#r=e,this.#o=a,this.#s=this.#a(null,pi.IDLE)}start(t={}){if(t===null||typeof t!="object"||Array.isArray(t))throw new TypeError("Registration options must be an object");this.#f();let o={id:++this.#i,controller:new AbortController,qrCodeUrl:null,expiresAt:null,pollIntervalSeconds:null,expiryTimer:null};this.#c=o,this.#s=this.#a(o,pi.STARTING);let i={...t,signal:o.controller.signal,onQRCodeReady:a=>this.#g(o,a),onStatusChange:a=>this.#l(o,a)};return Promise.resolve().then(()=>this.#e(i)).then(a=>this.#p(o,a),a=>this.#d(o,a)),this.status()}status(){this.#E();let t={...this.#s};t.error&&(t.error={...t.error});let o=this.#c;return o&&o.expiresAt!==null&&wk.has(t.state)&&(t.remainingSeconds=Math.max(0,Math.ceil((o.expiresAt-this.#t())/1e3))),t}cancel(){let t=this.#c;return t?(this.#C(t,pi.CANCELLED,{error:{code:"abort",message:"Registration was cancelled."}}),t.controller.abort(),this.status()):this.status()}#I(t){return this.#c===t}#a(t,o,i={}){let e={state:o,attempt:t?.id??this.#i,updatedAt:this.#t(),...i};return t?.qrCodeUrl&&wk.has(o)&&(e.qrCodeUrl=t.qrCodeUrl,e.expiresAt=t.expiresAt),t?.pollIntervalSeconds!==null&&wk.has(o)&&(e.pollIntervalSeconds=t.pollIntervalSeconds),e}#n(t,o,i={}){this.#I(t)&&(this.#s=this.#a(t,o,i))}#g(t,o){if(!this.#I(t))return;if(typeof o?.url!="string"||!o.url)throw new TypeError("registerApp onQRCodeReady returned an invalid URL");let i=J_e(o.expireIn);t.qrCodeUrl=o.url,t.expiresAt=this.#t()+i*1e3,this.#B(t),t.expiryTimer=this.#r(()=>this.#h(t),i*1e3),t.expiryTimer?.unref?.(),this.#n(t,pi.QR_READY)}#l(t,o){!this.#I(t)||!j_e.has(o?.status)||(o.status===pi.SLOW_DOWN&&Number.isFinite(Number(o.interval))&&(t.pollIntervalSeconds=Number(o.interval)),this.#n(t,o.status))}async#p(t,o){if(!this.#I(t))return;let i=o?.client_id,e=o?.client_secret;if(typeof i!="string"||!i||typeof e!="string"||!e){this.#C(t,pi.ERROR,{error:{code:"invalid_credentials",message:"Feishu registration returned invalid credentials."}});return}let a;try{a=q_e(o.user_info)}catch{this.#C(t,pi.ERROR,{error:{code:"invalid_credentials",message:"Feishu registration returned invalid credentials."}});return}this.#B(t),t.qrCodeUrl=null,t.expiresAt=null,t.pollIntervalSeconds=null,this.#n(t,pi.SAVING);try{await this.#A({client_id:i,client_secret:e,user_info:a})}catch{this.#I(t)&&this.#C(t,pi.ERROR,{error:{code:"credentials_callback_failed",message:"Unable to store the Feishu credentials."}});return}this.#I(t)&&this.#C(t,pi.SUCCEEDED)}#d(t,o){if(!this.#I(t))return;let i=xz(o);if(i==="expired_token"){this.#C(t,pi.EXPIRED,{error:Ok(o)});return}if(i==="abort"){this.#C(t,pi.CANCELLED,{error:Ok(o)});return}this.#C(t,pi.ERROR,{error:Ok(o)})}#E(){let t=this.#c;t&&t.expiresAt!==null&&this.#t()>=t.expiresAt&&this.#h(t)}#h(t){this.#I(t)&&(this.#C(t,pi.EXPIRED,{error:{code:"expired_token",message:"The registration QR code expired."}}),t.controller.abort())}#C(t,o,i={}){this.#I(t)&&(this.#B(t),this.#s=this.#a(t,o,i),this.#c=null)}#B(t){t.expiryTimer!==null&&(this.#o(t.expiryTimer),t.expiryTimer=null)}#f(){let t=this.#c;t&&(this.#B(t),this.#c=null,t.controller.abort())}};var z_e="card.action.trigger",BC="callback_repair";function V_e(n){return n==="lark"?"accounts.larksuite.com":"accounts.feishu.cn"}function W_e(n){return n==="lark"?"open.larksuite.com":"open.feishu.cn"}function bk(n,t,o="feishu",i="Feishu app update"){let e;try{e=new URL(n)}catch{throw new Error(`${i} returned an invalid verification URL`)}let a=o==="feishu"||o==="lark",A=e.searchParams.getAll("clientID"),r=e.searchParams.getAll("tp"),s=e.searchParams.getAll("addons"),g=String(t).includes("{{")||String(t).includes("}}")||[...e.searchParams.values()].some(c=>c.includes("{{")||c.includes("}}"));if(!a||e.protocol!=="https:"||e.hostname!==W_e(o)||e.port!==""||e.username!==""||e.password!==""||r.length!==1||r[0]!=="sdk"||A.length!==1||A[0]!==t||e.searchParams.has("createOnly")||s.length!==1||!s[0]?.trim()||g)throw new Error(`${i} returned an unsafe verification URL`);return e.toString()}function Z_e(n,t,o="feishu"){return bk(n,t,o,"Feishu callback repair")}var jy=class{#e;#A;#t;constructor({registerApp:t,onCredentials:o,appId:i,domain:e="feishu"}={}){if(typeof t!="function")throw new TypeError("registerApp is required");if(typeof o!="function")throw new TypeError("onCredentials is required");if(typeof i!="string"||!i.trim())throw new TypeError("appId is required");if(e!=="feishu"&&e!=="lark")throw new TypeError("domain is invalid");this.#A=i.trim(),this.#t=e,this.#e=new Fs({registerApp:a=>t({...a,onQRCodeReady:A=>{Z_e(A?.url,this.#A,this.#t),a.onQRCodeReady(A)}}),onCredentials:o})}start(){return this.#e.start({source:"deepseek-harness-card-action-repair",domain:V_e(this.#t),appId:this.#A,addons:{preset:!1,callbacks:{items:[z_e]}}})}status(){return this.#e.status()}cancel(){return this.#e.cancel()}};var X_e="im:message.group_msg",qy="group_message_permission";function $_e(n){return n==="lark"?"accounts.larksuite.com":"accounts.feishu.cn"}function eTe(n,t,o="feishu"){return bk(n,t,o,"Feishu group message permission update")}var Jy=class{#e;#A;#t;constructor({registerApp:t,onCredentials:o,appId:i,domain:e="feishu"}={}){if(typeof t!="function")throw new TypeError("registerApp is required");if(typeof o!="function")throw new TypeError("onCredentials is required");if(typeof i!="string"||!i.trim())throw new TypeError("appId is required");if(e!=="feishu"&&e!=="lark")throw new TypeError("domain is invalid");this.#A=i.trim(),this.#t=e,this.#e=new Fs({registerApp:a=>t({...a,onQRCodeReady:A=>{eTe(A?.url,this.#A,this.#t),a.onQRCodeReady(A)}}),onCredentials:o})}start(){return this.#e.start({source:"deepseek-harness-group-message-permission",domain:$_e(this.#t),appId:this.#A,addons:{preset:!1,scopes:{tenant:[X_e]}}})}status(){return this.#e.status()}cancel(){return this.#e.cancel()}};var Yz=Object.freeze(["im:message.p2p_msg:readonly","im:message.group_at_msg:readonly","im:message:readonly","im:message:send_as_bot","im:message.reactions:write_only","im:message:recall","im:resource","cardkit:card:write"]);var _k=new Set(["starting","qr_ready","polling","slow_down","domain_switched"]),zy=new Set([..._k,"saving"]),jz=new Set([BC,qy]),Mk="*",ATe=12e4,tTe=6e5;function zz(){return{ready:!1,feishuLongConnectionState:"idle",harnessReachable:!1}}function Vy(n){return n?n.status:zz()}function Wy(n){return n.ready===!0&&n.feishuLongConnectionState==="connected"&&n.harnessReachable===!0}function Vz(n){return n.length>12?`${n.slice(0,8)}\u2022\u2022\u2022\u2022${n.slice(-4)}`:"cli_\u2022\u2022\u2022\u2022"}function rTe(n){return{name:n.botName,appIdMasked:Vz(n.appId),activated:n.activated,domain:n.domain}}function aTe({connected:n,error:t,connection:o}){return n?"connected":t||o.feishuLongConnectionState==="failed"?"error":"disconnected"}function iTe(){return`bot_${qz().replaceAll("-","")}`}function oTe(){return`reg_${qz().replaceAll("-","")}`}function Jz(n){return`DSH_FEISHU_APP_SECRET_${n.slice(4).toUpperCase()}`}function Zy(n){return JSON.stringify({id:n.id,appId:n.appId,secretRef:n.secretRef,ownerOpenIds:n.ownerOpenIds,domain:n.domain,botName:n.botName,botOpenId:n.botOpenId,activated:n.activated,groupResponseMode:Pi(n.groupResponseMode),groupMessagePermissionGranted:n.groupMessagePermissionGranted===!0,deletionPending:n.deletionPending===!0,connectedAt:n.connectedAt??null,createdAt:n.createdAt??null})}function Xy(n){return typeof n=="string"&&n.trim()?n.trim():null}var fC=class{#e;#A;#t;#r;#o;#i;#c;#s;#I=new Map;#a=new Map;#n=new Map;#g=new Map;#l=new Map;#p=null;#d=Promise.resolve();#E=new Map;#h=1;#C;#B=!1;constructor({registerApp:t,verifyApp:o,credentials:i,configStore:e,createRuntime:a,deleteState:A=async()=>{},createBotId:r=iTe,createRegistrationId:s=oTe,callbackProbeTimeoutMs:g=ATe}){if(typeof t!="function")throw new Error("registerApp is required");if(typeof o!="function")throw new Error("verifyApp is required");if(!i)throw new Error("credentials service is required");if(!e||typeof e.list!="function")throw new Error("multi-bot config store is required");if(typeof a!="function")throw new Error("createRuntime is required");if(typeof A!="function")throw new Error("deleteState must be a function");if(!Number.isFinite(g)||g<=0||g>tTe)throw new TypeError("callbackProbeTimeoutMs must be between 1 and 600000ms");this.#e=t,this.#A=o,this.#t=i,this.#r=e,this.#o=a,this.#i=A,this.#c=r,this.#s=s,this.#C=g}async initialize(){if(this.#B)return this.status();let t=this.#r.list(),o=!1;return await Promise.allSettled(t.map(i=>this.#T(i.id,async()=>{let e=Vy(this.#I.get(i.id));if(Wy(e)||e.feishuLongConnectionState==="connecting"||e.feishuLongConnectionState==="reconnecting")return;if(o=!0,i.deletionPending){this.#a.set(i.id,{code:"deletion_pending",message:"\u673A\u5668\u4EBA\u6B63\u5728\u7B49\u5F85\u5B8C\u6210\u672C\u5730\u5220\u9664\uFF0C\u8BF7\u91CD\u8BD5\u79FB\u9664\u3002"});return}let a;try{a=await this.#t.resolve(i.secretRef)}catch{this.#a.set(i.id,{code:"missing_credentials",message:"\u65E0\u6CD5\u8BFB\u53D6\u673A\u5668\u4EBA\u51ED\u636E\uFF0C\u8BF7\u68C0\u67E5\u51ED\u636E\u5B58\u50A8\u3002"});return}if(!a?.value){this.#a.set(i.id,{code:"missing_credentials",message:"\u673A\u5668\u4EBA\u51ED\u636E\u7F3A\u5931\uFF0C\u8BF7\u5220\u9664\u540E\u91CD\u65B0\u626B\u7801\u63A5\u5165\u3002"});return}try{await this.#m(i,a.value),this.#a.delete(i.id)}catch{this.#a.set(i.id,{code:"connection_failed",message:"\u673A\u5668\u4EBA\u6682\u65F6\u65E0\u6CD5\u8FDE\u63A5\u98DE\u4E66\uFF0C\u8BF7\u91CD\u8BD5\u3002"})}}))),o&&this.#k(),this.status()}startRegistration(){this.#N();let t=this.#s();if(typeof t!="string"||!/^[A-Za-z0-9_-]{1,128}$/.test(t)||this.#n.has(t))throw new Error("Registration id generator returned an invalid or duplicate id");let o={id:t,manager:null,botId:null,createdNew:!1,cancelled:!1};return o.manager=new Fs({registerApp:this.#e,onCredentials:i=>this.#G(()=>this.#O(o,i))}),this.#n.set(t,o),this.#p=t,this.#F(),o.manager.start({source:"deepseek-harness",createOnly:!0,appPreset:{name:"{user} \u7684\u5317\u6C47\u661F\u6CB3 AI \u52A9\u624B",desc:"\u8FDE\u63A5\u98DE\u4E66\u4E0E DeepSeek Harness\uFF0C\u5728\u804A\u5929\u4E2D\u4F7F\u7528\u4F01\u4E1A AI \u52A9\u624B\u3002"},addons:{preset:!1,scopes:{tenant:[...Yz]},events:{items:{tenant:["im.message.receive_v1"]}},callbacks:{items:["card.action.trigger"]}}}),this.#k(),this.registrationStatus(t)}startCallbackRepair(t,{actorOpenId:o,chatId:i}={}){this.#N();let e=this.#M(t);if(e.deletionPending)throw new Error("Cannot repair a Feishu bot pending deletion");let a=this.#g.get(t),A=a?this.#n.get(a):null;if(A&&zy.has(A.manager.status().state)){if(A.operation!==BC)throw new Error("Another Feishu app update is already active for this bot");return this.registrationStatus(A.id)}this.#g.delete(t);let r=this.#s();if(typeof r!="string"||!/^[A-Za-z0-9_-]{1,128}$/.test(r)||this.#n.has(r))throw new Error("Registration id generator returned an invalid or duplicate id");let s={id:r,operation:BC,manager:null,botId:t,createdNew:!1,cancelled:!1,remoteCommitted:!1,processing:null,publicError:null,stage:"authorizing",target:structuredClone(e),targetFingerprint:Zy(e),initiator:{actorOpenId:Xy(o),chatId:Xy(i)}};return s.manager=new jy({registerApp:this.#e,appId:e.appId,domain:e.domain,onCredentials:g=>{s.remoteCommitted=!0;let I=this.#u(s,g).finally(()=>{s.processing===I&&(s.processing=null)});return s.processing=I,I}}),this.#n.set(r,s),this.#g.set(t,r),this.#p=r,this.#F(),s.manager.start(),this.#k(),this.registrationStatus(r)}startGroupMessagePermission(t){this.#N();let o=this.#M(t);if(o.deletionPending)throw new Error("Cannot update permissions for a Feishu bot pending deletion");let i=this.#g.get(t),e=i?this.#n.get(i):null;if(e&&zy.has(e.manager.status().state)){if(e.operation!==qy)throw new Error("Another Feishu app update is already active for this bot");return this.registrationStatus(e.id)}this.#g.delete(t);let a=this.#s();if(typeof a!="string"||!/^[A-Za-z0-9_-]{1,128}$/.test(a)||this.#n.has(a))throw new Error("Registration id generator returned an invalid or duplicate id");let A={id:a,operation:qy,manager:null,botId:t,createdNew:!1,cancelled:!1,remoteCommitted:!1,processing:null,publicError:null,stage:"authorizing",target:structuredClone(o),targetFingerprint:Zy(o),initiator:{actorOpenId:null,chatId:null}};return A.manager=new Jy({registerApp:this.#e,appId:o.appId,domain:o.domain,onCredentials:r=>{A.remoteCommitted=!0;let g=this.#w(A,r).finally(()=>{A.processing===g&&(A.processing=null)});return A.processing=g,g}}),this.#n.set(a,A),this.#g.set(t,a),this.#p=a,this.#F(),A.manager.start(),this.#k(),this.registrationStatus(a)}hasRegistration(t){return this.#n.has(t)}registrationStatus(t){let o=this.#n.get(t);return o?this.#f({registration:o,selectedBotId:o.botId}):null}async cancelRegistration(t=this.#p){let o=this.#n.get(t);if(!o)return this.status();let i=o.manager.status().state;return jz.has(o.operation)&&i==="saving"?this.registrationStatus(t):zy.has(i)?(o.cancelled=!0,o.manager.cancel(),await this.#G(async()=>{o.createdNew&&o.botId&&this.#l.get(o.botId)===o.id&&this.#r.getBot(o.botId)&&await this.#T(o.botId,()=>this.#R(o.botId))}),this.#k(),this.registrationStatus(t)??this.status()):this.registrationStatus(t)}status(t){return this.#f({registration:this.#n.get(this.#p)??null,selectedBotId:t})}async bindCredentials({appId:t,appSecret:o,domain:i="feishu"}={}){this.#N();let e=typeof t=="string"?t.trim():"",a=typeof o=="string"?o.trim():"",A=i==="lark"?"lark":"feishu";if(!e||!a)throw new TypeError("Feishu App ID and App Secret are required");return this.#G(async()=>{this.#N();let r=await this.#A({appId:e,appSecret:a,domain:A});this.#N();let s=this.#r.list().find(f=>f.appId===e),g=s?.id??this.#c();if(typeof g!="string"||!/^[A-Za-z0-9_-]{1,128}$/.test(g)||!s&&this.#r.getBot(g))throw new Error("Bot id generator returned an invalid or duplicate id");let c=s?.secretRef??Jz(g),I=await this.#t.resolve(c).catch(()=>{}),d={...s,id:g,appId:e,secretRef:c,ownerOpenIds:s?.ownerOpenIds?.length?s.ownerOpenIds:[Mk],domain:A,botName:r.name,botOpenId:r.openId,activated:r.activated,deletionPending:!1,connectedAt:new Date().toISOString(),createdAt:s?.createdAt??new Date().toISOString()};await this.#t.set(c,a);let B;try{B=await this.#r.saveBot(d)}catch(f){throw await this.#b(c,I),f}return await this.#T(g,async()=>{try{await this.#m(B,a),this.#a.delete(g)}catch{this.#a.set(g,{code:"connection_failed",message:"\u673A\u5668\u4EBA\u5DF2\u7ECF\u7ED1\u5B9A\uFF0C\u4F46\u957F\u8FDE\u63A5\u672A\u5C31\u7EEA\uFF0C\u8BF7\u70B9\u51FB\u91CD\u8BD5\u3002"})}}),this.#k(),this.status(g)})}async reconnectBot(t){return this.#N(),this.#T(t,async()=>{let o=this.#M(t);if(o.deletionPending)return this.#a.set(t,{code:"deletion_pending",message:"\u673A\u5668\u4EBA\u6B63\u5728\u7B49\u5F85\u5B8C\u6210\u672C\u5730\u5220\u9664\uFF0C\u8BF7\u91CD\u8BD5\u79FB\u9664\u3002"}),this.status(t);if(Wy(Vy(this.#I.get(t))))return this.status(t);let i;try{i=await this.#t.resolve(o.secretRef)}catch{i=null}if(!i?.value)return this.#a.set(t,{code:"missing_credentials",message:"\u673A\u5668\u4EBA\u51ED\u636E\u7F3A\u5931\uFF0C\u8BF7\u5220\u9664\u540E\u91CD\u65B0\u626B\u7801\u63A5\u5165\u3002"}),this.#k(),this.status(t);try{await this.#m(o,i.value),this.#a.delete(t)}catch{this.#a.set(t,{code:"connection_failed",message:"\u673A\u5668\u4EBA\u6682\u65F6\u65E0\u6CD5\u8FDE\u63A5\u98DE\u4E66\uFF0C\u8BF7\u91CD\u8BD5\u3002"})}return this.#k(),this.status(t)})}async sendConnectionTest(t){return this.#N(),this.#T(t,async()=>{let o=this.#M(t),i=this.#I.get(t);if(!Wy(Vy(i))||typeof i.sendConnectionTest!="function"){let e=new Error("\u98DE\u4E66\u673A\u5668\u4EBA\u5C1A\u672A\u8FDE\u63A5");throw e.code="test-target-unavailable",e}return i.sendConnectionTest(Ea(`${o.botName}\uFF08${Vz(o.appId)}\uFF09`,"\u98DE\u4E66\u673A\u5668\u4EBA"))})}async disconnectBot(t){return this.#N(),this.#T(t,async()=>(this.#M(t),await this.#_(t),this.#a.delete(t),this.#k(),this.status(t)))}async updateGroupResponseMode(t,o){if(this.#N(),!My(o))throw new TypeError("Invalid Feishu group response mode");return this.#G(()=>this.#T(t,async()=>{let i=this.#M(t);if(o==="all"&&i.groupMessagePermissionGranted!==!0){let a=new Error("Authorize im:message.group_msg before enabling all group messages");throw a.code="group_message_permission_required",a}let e=await this.#r.saveBot({...i,groupResponseMode:o});return this.#I.get(t)?.setGroupResponseMode?.(e.groupResponseMode),this.#k(),this.status(t)}))}async deleteBot(t){return this.#N(),this.#G(()=>this.#T(t,async()=>(this.#M(t),await this.#R(t),this.#k(),this.status())))}async reconnect(){let t=this.#r.list()[0];return t?this.reconnectBot(t.id):this.status()}async disconnect(){let t=this.#r.list()[0];return t?this.deleteBot(t.id):this.status()}async close(){if(this.#B)return;this.#B=!0;let t=[];for(let o of this.#n.values()){let i=o.manager.status().state;jz.has(o.operation)&&i==="saving"?(o.manager.cancel(),o.processing&&t.push(o.processing)):zy.has(i)&&(o.cancelled=!0,o.manager.cancel())}await this.#d,await Promise.allSettled([...this.#E.values()]),await Promise.allSettled([...this.#I.keys()].map(o=>this.#_(o))),await Promise.allSettled(t),await this.#d,await Promise.allSettled([...this.#E.values()]),await Promise.allSettled([...this.#I.keys()].map(o=>this.#_(o)))}#f({registration:t,selectedBotId:o}={}){let i=this.#r.list().map(I=>{let d=Vy(this.#I.get(I.id)),B=Wy(d),f=this.#a.get(I.id)??null;return{botId:I.id,phase:aTe({connected:B,error:f,connection:d}),connected:B,configured:!0,groupResponseMode:Pi(I.groupResponseMode),groupMessagePermissionGranted:I.groupMessagePermissionGranted===!0,bot:rTe(I),connection:d,error:f}}),e=t?this.#y(t):{state:"idle",attempt:0,updatedAt:Date.now()},a=_k.has(e.state),A=e.state==="saving",r=!!t&&(a||A),s=i.find(I=>I.botId===o)??(r?null:i[0]??null),g=i.some(I=>I.connected),c=s?.phase??"unconfigured";return a?c="registering":A?c="connecting":e.state==="error"&&!s&&(c="error"),{schemaVersion:2,revision:this.#h,phase:c,connected:s?.connected??!1,configured:i.length>0,bot:s?.bot??null,connection:s?.connection??zz(),error:s?.error??e.error??null,registration:e,bots:i,totals:{configured:i.length,connected:i.filter(I=>I.connected).length},anyConnected:g}}#y(t){let o=t.manager.status();return{...o,attempt:t.id,...t.botId?{botId:t.botId}:{},...t.operation?{operation:t.operation}:{},...t.stage?{stage:t.stage}:{},...o.state==="error"&&t.publicError?{error:{...t.publicError}}:{}}}async#w(t,o){let i=o.client_id,e=o.client_secret,a=Xy(o.user_info?.open_id),A=o.user_info?.tenant_brand,r=t.target;if(t.cancelled)throw this.#Q(t,"abort","Group message permission update was cancelled before local activation.");if(i!==r.appId)throw this.#Q(t,"repair_app_mismatch","Feishu returned credentials for a different app.");if(!a)throw this.#Q(t,"repair_owner_missing","Feishu returned no permission operator identity.");if(A!==void 0&&A!==r.domain)throw this.#Q(t,"repair_domain_mismatch","Feishu returned credentials for a different account domain.");if(!r.ownerOpenIds.includes(Mk)&&!r.ownerOpenIds.includes(a))throw this.#Q(t,"repair_owner_mismatch","The Feishu permission operator is not an owner of this configured bot.");t.stage="verifying_identity";let s;try{s=await this.#A({appId:i,appSecret:e,domain:r.domain})}catch(g){throw this.#Q(t,"repair_credentials_invalid","Feishu could not verify the updated app credentials.",g)}if(r.botOpenId&&s?.openId!==r.botOpenId)throw this.#Q(t,"repair_bot_mismatch","The updated Feishu app belongs to a different bot identity.");await this.#G(()=>this.#T(t.botId,async()=>{let g=this.#r.getBot(t.botId);if(!g||g.deletionPending||Zy(g)!==t.targetFingerprint)throw this.#Q(t,"repair_target_changed","The Feishu bot changed while its permission update was in progress.");let c;try{c=await this.#t.resolve(g.secretRef)}catch(d){throw this.#Q(t,"credential_update_failed","Unable to read the current Feishu credential.",d)}if(c?.value!==e){t.stage="persisting_secret";try{await this.#t.set(g.secretRef,e)}catch(B){if((await this.#t.resolve(g.secretRef).catch(()=>null))?.value!==e)throw this.#Q(t,"credential_update_failed","Unable to store the updated Feishu credential.",B)}if((await this.#t.resolve(g.secretRef).catch(()=>null))?.value!==e)throw this.#Q(t,"credential_state_unknown","The updated Feishu credential could not be confirmed after writing.")}t.stage="enabling_all_messages";let I;try{I=await this.#r.saveBot({...g,groupMessagePermissionGranted:!0,groupResponseMode:"all"})}catch(d){throw this.#Q(t,"group_message_permission_save_failed","The permission was accepted, but all-message mode could not be saved.",d)}t.stage="restarting";try{await this.#m(I,e)}catch(d){throw this.#a.set(t.botId,{code:"connection_failed",message:"\u7FA4\u6D88\u606F\u6743\u9650\u5DF2\u5F00\u901A\uFF0C\u4F46\u673A\u5668\u4EBA\u957F\u8FDE\u63A5\u672A\u5C31\u7EEA\uFF0C\u8BF7\u70B9\u51FB\u91CD\u8BD5\u3002"}),this.#k(),this.#Q(t,"group_message_permission_connection_failed","The permission was accepted, but the Feishu runtime could not restart.",d)}this.#a.delete(t.botId),t.stage="verified",t.publicError=null,this.#k()}))}async#u(t,o){let i=o.client_id,e=o.client_secret,a=Xy(o.user_info?.open_id),A=o.user_info?.tenant_brand,r=t.target;if(t.cancelled)throw this.#Q(t,"abort","Callback repair was cancelled before local activation.");if(i!==r.appId)throw this.#Q(t,"repair_app_mismatch","Feishu returned credentials for a different app.");if(!a)throw this.#Q(t,"repair_owner_missing","Feishu returned no repair operator identity.");if(A!==void 0&&A!==r.domain)throw this.#Q(t,"repair_domain_mismatch","Feishu returned credentials for a different account domain.");if(t.initiator.actorOpenId&&t.initiator.actorOpenId!==a)throw this.#Q(t,"repair_owner_mismatch","The Feishu repair was confirmed by a different operator.");if(!r.ownerOpenIds.includes(Mk)&&!r.ownerOpenIds.includes(a))throw this.#Q(t,"repair_owner_mismatch","The Feishu repair operator is not an owner of this configured bot.");t.stage="verifying_identity";let s;try{s=await this.#A({appId:i,appSecret:e,domain:r.domain})}catch(c){throw this.#Q(t,"repair_credentials_invalid","Feishu could not verify the repaired app credentials.",c)}if(r.botOpenId&&s?.openId!==r.botOpenId)throw this.#Q(t,"repair_bot_mismatch","The repaired Feishu app belongs to a different bot identity.");let g=await this.#G(()=>this.#T(t.botId,async()=>{let c=this.#r.getBot(t.botId);if(!c||c.deletionPending||Zy(c)!==t.targetFingerprint)throw this.#Q(t,"repair_target_changed","The Feishu bot changed while its callback repair was in progress.");let I;try{I=await this.#t.resolve(c.secretRef)}catch(f){throw this.#Q(t,"credential_update_failed","Unable to read the current Feishu credential.",f)}if(I?.value!==e){t.stage="persisting_secret";try{await this.#t.set(c.secretRef,e)}catch(Q){if((await this.#t.resolve(c.secretRef).catch(()=>null))?.value!==e)throw this.#Q(t,"credential_update_failed","Unable to store the repaired Feishu credential.",Q)}if((await this.#t.resolve(c.secretRef).catch(()=>null))?.value!==e)throw this.#Q(t,"credential_state_unknown","The repaired Feishu credential could not be confirmed after writing.")}let B;t.stage="restarting";try{await this.#m(c,e),B=this.#I.get(t.botId)}catch(f){throw this.#a.set(t.botId,{code:"connection_failed",message:"\u673A\u5668\u4EBA\u56DE\u8C03\u4FEE\u590D\u5DF2\u4FDD\u5B58\uFF0C\u4F46\u957F\u8FDE\u63A5\u672A\u5C31\u7EEA\uFF0C\u8BF7\u70B9\u51FB\u91CD\u8BD5\u3002"}),this.#k(),this.#Q(t,"repair_connection_failed","The repaired Feishu runtime could not be started.",f)}if(!B)throw this.#Q(t,"repair_connection_failed","The repaired Feishu runtime is unavailable.");return this.#a.delete(t.botId),this.#k(),B}));if(typeof g.beginCardActionProbe!="function")throw this.#Q(t,"card_action_probe_unavailable","The Feishu runtime cannot verify card callbacks.");t.stage="awaiting_callback";try{if((await g.beginCardActionProbe({expectedOperatorOpenId:a,timeoutMs:this.#C,...t.initiator.chatId?{chatId:t.initiator.chatId}:{}}))?.verified!==!0){let I=new Error("Feishu runtime returned no callback proof");throw I.code="card_action_probe_failed",I}}catch(c){let I=c?.code==="card_action_probe_timeout"?"card_action_probe_timeout":c?.code==="card_action_probe_unavailable"?"card_action_probe_unavailable":c?.code==="card_action_probe_send_failed"?"card_action_probe_send_failed":"card_action_probe_failed";throw this.#Q(t,I,I==="card_action_probe_timeout"?"Timed out waiting for the Feishu callback verification button.":"The Feishu card callback probe failed.",c)}t.stage="verified",t.publicError=null,this.#k()}#Q(t,o,i,e){t.publicError={code:o,message:i};let a=new Error(i,e?{cause:e}:void 0);return a.code=o,a}async#O(t,o){if(t.cancelled)throw new Error("Registration was cancelled");let i=o.client_id,e=o.client_secret,a=o.user_info?.open_id,A=o.user_info?.tenant_brand==="lark"?"lark":"feishu";if(!a)throw new Error("Feishu registration returned no owner open_id");let r=await this.#A({appId:i,appSecret:e,domain:A});if(t.cancelled)throw new Error("Registration was cancelled");let s=this.#r.list().find(Q=>Q.appId===i),g=s?.id??this.#c();if(typeof g!="string"||!/^[A-Za-z0-9_-]{1,128}$/.test(g)||!s&&this.#r.getBot(g))throw new Error("Bot id generator returned an invalid or duplicate id");let c=s?.secretRef??Jz(g),I=this.#l.get(g),d=await this.#t.resolve(c).catch(()=>{});await this.#t.set(c,e);let B;try{B=await this.#r.saveBot({...s,id:g,appId:i,secretRef:c,ownerOpenIds:[...new Set([...s?.ownerOpenIds??[],a])],domain:A,botName:r.name,botOpenId:r.openId,activated:r.activated,deletionPending:!1,connectedAt:new Date().toISOString(),createdAt:s?.createdAt??new Date().toISOString()}),t.botId=g,t.createdNew=!s,this.#l.set(g,t.id)}catch(Q){try{await this.#b(c,d)}catch(y){throw new Error("Unable to restore the Feishu credential after a config failure.",{cause:y})}throw Q}if(t.cancelled)throw t.createdNew?await this.#T(g,()=>this.#R(g)):(await this.#r.saveBot(s),await this.#b(c,d),I?this.#l.set(g,I):this.#l.delete(g)),new Error("Registration was cancelled");let f=!1;try{if(await this.#T(g,()=>this.#m(B,e)),t.cancelled)throw t.createdNew?await this.#T(g,()=>this.#R(g)):(await this.#r.saveBot(s),await this.#b(c,d),I?this.#l.set(g,I):this.#l.delete(g),d?.value&&!s.deletionPending?await this.#T(g,()=>this.#m(s,d.value)):await this.#T(g,()=>this.#_(g))),f=!0,new Error("Registration was cancelled");this.#a.delete(g),this.#k()}catch(Q){if(t.cancelled)throw!f&&t.createdNew&&this.#r.getBot(g)?await this.#T(g,()=>this.#R(g)):!f&&s&&(await this.#r.saveBot(s),await this.#b(c,d),I?this.#l.set(g,I):this.#l.delete(g),!this.#B&&d?.value&&!s.deletionPending?await this.#T(g,()=>this.#m(s,d.value)):await this.#T(g,()=>this.#_(g))),this.#k(),Q;if(s&&d?.value)try{throw await this.#r.saveBot(s),await this.#b(c,d),I?this.#l.set(g,I):this.#l.delete(g),s.deletionPending?(await this.#T(g,()=>this.#_(g)),this.#a.set(g,{code:"deletion_pending",message:"\u673A\u5668\u4EBA\u6B63\u5728\u7B49\u5F85\u5B8C\u6210\u672C\u5730\u5220\u9664\uFF0C\u8BF7\u91CD\u8BD5\u79FB\u9664\u3002"})):(await this.#T(g,()=>this.#m(s,d.value)),this.#a.delete(g)),this.#k(),Q}catch(y){throw y===Q?Q:(this.#a.set(g,{code:"connection_failed",message:"\u673A\u5668\u4EBA\u8FDE\u63A5\u66F4\u65B0\u5931\u8D25\uFF0C\u4E14\u539F\u8FDE\u63A5\u65E0\u6CD5\u6062\u590D\uFF0C\u8BF7\u91CD\u8BD5\u3002"}),this.#k(),new Error("Unable to restore the previous Feishu bot connection.",{cause:y}))}throw this.#a.set(g,{code:"connection_failed",message:"\u673A\u5668\u4EBA\u5DF2\u7ECF\u521B\u5EFA\uFF0C\u4F46\u957F\u8FDE\u63A5\u672A\u5C31\u7EEA\uFF0C\u8BF7\u70B9\u51FB\u91CD\u8BD5\u3002"}),this.#k(),Q}}async#m(t,o){await this.#_(t.id);let i=await this.#o({botId:t.id,config:t,appSecret:o,repair:this.#S(t.id)});this.#I.set(t.id,i);try{await i.start()}catch(e){throw this.#I.get(t.id)===i&&this.#I.delete(t.id),await i.stop({preserveError:!0}).catch(()=>{}),e}}#S(t){let o=i=>{let e=this.#n.get(i);return e?.operation===BC&&e.botId===t?e:null};return Object.freeze({start:({actorOpenId:i,chatId:e}={})=>this.startCallbackRepair(t,{actorOpenId:i,chatId:e}),status:({attemptId:i}={})=>o(i)?this.registrationStatus(i):null,cancel:async({attemptId:i}={})=>o(i)?this.cancelRegistration(i):this.status(t)})}async#_(t){let o=this.#I.get(t);this.#I.delete(t),o&&await o.stop()}async#R(t){let o=this.#r.getBot(t);if(o){o.deletionPending||(o=await this.#r.saveBot({...o,deletionPending:!0})),await this.#_(t);try{await this.#t.unset(o.secretRef)}catch(i){throw this.#a.set(t,{code:"credential_removal_failed",message:"\u65E0\u6CD5\u5220\u9664\u673A\u5668\u4EBA\u51ED\u636E\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002"}),new Error("Unable to remove the Feishu credential.",{cause:i})}try{await this.#i({botId:t,config:o})}catch(i){throw this.#a.set(t,{code:"state_cleanup_failed",message:"\u65E0\u6CD5\u5220\u9664\u673A\u5668\u4EBA\u7684\u672C\u5730\u4F1A\u8BDD\u6570\u636E\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002"}),new Error("Unable to remove the Feishu bot session state.",{cause:i})}await this.#r.removeBot(t),this.#a.delete(t),this.#l.delete(t)}}async#b(t,o){o?.value?await this.#t.set(t,o.value):await this.#t.unset(t)}#M(t){let o=this.#r.getBot(t);if(!o)throw new Error("Unknown Feishu bot");return o}#N(){if(this.#B)throw new Error("The Feishu controller is closed")}#G(t){let o=this.#d.then(t,t);return this.#d=o.then(()=>{},()=>{}),o}#T(t,o){let e=(this.#E.get(t)??Promise.resolve()).then(o,o),a=e.then(()=>{},()=>{});return this.#E.set(t,a),a.finally(()=>{this.#E.get(t)===a&&this.#E.delete(t)}),e}#F(){if(!(this.#n.size<=32))for(let[t,o]of this.#n){if(t===this.#p)continue;let i=o.manager.status().state;if(!_k.has(i)&&i!=="saving"&&this.#n.delete(t),this.#n.size<=32)break}}#k(){this.#h+=1}};function gTe(n){for(let t of["https_proxy","HTTPS_PROXY","http_proxy","HTTP_PROXY"]){let o=n?.[t];if(typeof o=="string"&&o.trim())return o.trim()}}function cTe(n,t=o=>new Wz.default(o)){let o=gTe(n);return o?t(o):void 0}function ITe(n,t){if(t!==void 0)return new URL(t);let o=n?.port;if(!Number.isInteger(o)||o<1||o>65535)throw new Error("dsh-feishu requires an initialized DSH webServer port");return new URL(`http://127.0.0.1:${o}`)}function lTe(n){let t=Fg(n.dshHome??process.env.DSH_HOME??Rp(nTe(),".dsh")),o=Fg(n.dataDir??Rp(t,"integrations","dsh-feishu"));return{root:o,config:Fg(n.configPath??Rp(o,"config.json")),legacyState:Fg(n.statePath??Rp(o,"state.json")),bots:Fg(n.botsDir??Rp(o,"bots")),workspaces:Fg(n.workspacesPath??Rp(o,"workspaces.json"))}}async function Tk(n,t={},o={}){if(!n?.credentials)throw new TypeError("dsh-feishu requires ctx.credentials");if(!n?.webServer)throw new TypeError("dsh-feishu requires ctx.webServer");let i=o.lark??Ek,e=o.Controller??fC,a=o.ConfigStore??xy,A=o.StateStore??Oy,r=o.HarnessClient??Hy,s=o.FeishuRuntime??Uy,g=o.verifyFeishuApp??gz,c=we=>g({...we,httpInstance:i.defaultHttpInstance}),I=o.createConnectionSupervisor??Ck,d=typeof n.logger=="function"?n.logger("dsh-feishu"):n.logger??console,B=()=>Ba(n),f=lTe(t),Q=await new a(f.config).load(),y=Fg(t.workspace??process.cwd()),m=o.WorkspaceStore??Jr,_=o.workspaces??await new m(f.workspaces,{defaultWorkspace:y}).load(),N=typeof Q.list=="function",G=()=>N?Q.list():[],Y=G();N&&await _.reconcile(Y.map(we=>we.id)),await Promise.all(Y.map(we=>_.ensure(we.id,{defaultAgentPreset:t.agentPreset})));let j=typeof Q.removeBot=="function"?fa(Q,{workspaces:_,method:"removeBot",botIdFromRemoved:we=>we.id}):Q,x=new Map,q=we=>!we.id||!we.secretRef||we.secretRef===Yy?f.legacyState:Fg(f.bots,we.id,"state.json"),J=async we=>{let Be=we.id??"__legacy__",Pe=x.get(Be);return Pe||(Pe=await new A(q(we)).load(),x.set(Be,Pe)),Pe},F=async we=>{let Be=G().find(Pe=>Pe.id===we);if(!Be)throw new Error("Unknown Feishu bot");return J(Be)},P=ma(n,o.commandExecutor),{controlExecutor:V,sessionMaintenanceExecutor:K,fileIngressExecutor:T}=Sa(n,{controlExecutor:o.controlExecutor,sessionMaintenanceExecutor:o.sessionMaintenanceExecutor,fileIngressExecutor:o.fileIngressExecutor}),v=new r({baseUrl:ITe(n.webServer,t.harnessBaseUrl),workspace:y,autostart:!1,dshBin:t.dshBin??"dsh",...P?{commandExecutor:P}:{},...V?{controlExecutor:V}:{},...K?{sessionMaintenanceExecutor:K}:{},...T?{fileIngressExecutor:T}:{}}),W=o.proxyEnv??process.env,se=cTe(W,o.createProxyAgent),ye=new e({registerApp:we=>i.registerApp(we),verifyApp:c,credentials:n.credentials,configStore:j,createRuntime:async({botId:we,config:Be,appSecret:Pe,repair:Ve})=>{let rA=await J(Be),Fe=we??Be.id??Be.appId;await _.ensure(Fe,{defaultAgentPreset:t.agentPreset});let iA=Qa(v,{botId:Fe,workspaces:_,state:rA,agentPresetCatalog:B});return new s({lark:i,botId:Fe,repair:Ve,appId:Be.appId,appSecret:Pe,domain:Be.domain,botOpenId:Be.botOpenId,groupResponseMode:Be.groupResponseMode,ownerOpenIds:Be.ownerOpenIds??[Be.ownerOpenId],harness:iA.harness,state:iA.state,replyTimeoutMs:t.replyTimeoutMs??6e5,...se?{wsAgent:se}:{},logger:{error:(...Ce)=>d.error?.(`[${we??Be.id}]`,...Ce),warn:(...Ce)=>d.warn?.(`[${we??Be.id}]`,...Ce),info:(...Ce)=>d.info?.(`[${we??Be.id}]`,...Ce),debug:(...Ce)=>d.debug?.(`[${we??Be.id}]`,...Ce)}})},deleteState:async({botId:we,config:Be})=>{x.delete(we);try{await sTe(q(Be))}catch(Pe){if(Pe?.code!=="ENOENT")throw Pe}}}),Me=ya(ye,{workspaces:_,stateFor:F,agentPresetCatalog:B}),fe=I({controller:Me,harness:v,logger:d,retryDelaysMs:t.retryDelaysMs,healthyIntervalMs:t.healthyIntervalMs}).start();return{controller:Me,ready:fe.ready,async close(){await fe.close(),await Me.close(),v.stopManagedProcess(),se?.destroy?.()}}}import TTe from"qrcode";var vp=ze(Fk(),1);var bTe=ze(Fk(),1);var MTe=Object.freeze({$locale:"en",IM\u673A\u5668\u4EBA:"IM bots",IM\u673A\u5668\u4EBA\u8BBE\u7F6E:"IM bot settings","IM \u6E20\u9053":"IM channels","\u8BA9 DeepSeek Harness \u89E6\u624B\u53EF\u53CA":"DeepSeek Harness, always within reach","AI Office":"AI Office","\uFF08\u5B9E\u9A8C\u529F\u80FD\uFF09":"(Experimental)","AI Office \u8BBE\u7F6E":"AI Office settings","AI Office \u8BBE\u7F6E\u9875\u7F3A\u5C11 RPC \u8FDE\u63A5":"AI Office settings are missing an RPC connection","\u6B63\u5728\u8BFB\u53D6 AI Office Connector\u2026":"Loading AI Office Connector\u2026","\u672C\u673A\u4E3B\u52A8\u8FDE\u63A5\u516C\u7F51 Office\uFF1BHarness \u4E0D\u5F00\u653E\u7AEF\u53E3\u3002\u534F\u8BAE Hook \u56FA\u5B9A\u4E3A ":"This machine connects outward to the public Office; Harness exposes no port. Protocol hooks: ",\u5C1A\u672A\u914D\u7F6E:"Not configured","\u5DF2\u8FDE\u63A5 Office":"Connected to Office",\u5DF2\u914D\u7F6E:"Configured",\u7B49\u5F85\u91CD\u8FDE:"Waiting to reconnect",\u51ED\u636E\u7F3A\u5931:"Credential missing",\u6700\u8FD1\u5FC3\u8DF3:"Last heartbeat",\u6700\u8FD1\u4E8B\u4EF6:"Last event",\u91CD\u8FDE\u6B21\u6570:"Reconnects","\u8FD0\u884C Job":"Running Jobs","\u5B8C\u6210 Job":"Completed Jobs",\u5C1A\u65E0:"None yet",\u8BBE\u5907\u8FDE\u63A5:"Device connection","Token \u53EA\u5199\u5165\u672C\u673A\u51ED\u636E\u5B58\u50A8":"Token is written only to the local credential store","\u7C98\u8D34 Office \u4E00\u6B21\u6027\u51ED\u636E":"Paste the one-time Office credential","\u5DF2\u5B89\u5168\u4FDD\u5B58\uFF1B\u7559\u7A7A\u4FDD\u6301\u4E0D\u53D8":"Stored securely; leave blank to keep it",\u6700\u5927\u5E76\u53D1:"Max concurrency","Heartbeat \u79D2\u6570":"Heartbeat seconds","Workspace \u6620\u5C04":"Workspace mappings","\u6BCF\u884C alias=/\u672C\u673A/\u7EDD\u5BF9\u8DEF\u5F84\uFF1BOffice \u53EA\u80FD\u770B\u5230 alias\u3002":"One alias=/local/absolute/path per line; Office sees only aliases.","Instruction Preset \u6620\u5C04":"Instruction preset mappings","\u6BCF\u884C alias=\u6307\u4EE4\uFF1B\u65B0\u589E preset \u4E0D\u9700\u8981\u6539 Office \u4EE3\u7801\u3002":"One alias=instruction per line; new presets require no Office code change.",\u4FDD\u5B58\u5E76\u8FDE\u63A5:"Save and connect",\u6D4B\u8BD5\u8FDE\u63A5:"Test connection","\u6D4B\u8BD5\u4E2D\u2026":"Testing\u2026",\u91CD\u65B0\u8FDE\u63A5:"Reconnect",\u79FB\u9664\u8FDE\u63A5:"Remove connection","\u8FDE\u63A5\u6D4B\u8BD5\u901A\u8FC7\u3002":"Connection test passed.","\u914D\u7F6E\u5DF2\u4FDD\u5B58\u3002":"Configuration saved.","\u534F\u8BAE Hook \u9884\u89C8":"Protocol hook preview","\u7531 Base URL \u81EA\u52A8\u6D3E\u751F\uFF0C\u4E0D\u5355\u72EC\u586B\u5199":"Derived from Base URL; no separate input","Base URL \u65E0\u6548":"Invalid Base URL","Office Hook \u5C1A\u672A\u90E8\u7F72\u65F6\uFF0C\u914D\u7F6E\u4F1A\u5B89\u5168\u4FDD\u5B58\u5E76\u81EA\u52A8\u91CD\u8BD5\uFF1B\u51FA\u73B0 HTTP 404 \u4EE3\u8868\u534F\u8BAE\u7AEF\u70B9\u5F85\u4E0A\u7EBF\uFF0C\u4E0D\u4EE3\u8868 Harness \u6545\u969C\u3002":"Configuration is saved and retried while Office hooks are unavailable; HTTP 404 means the protocol endpoint is pending, not a Harness failure.","Workspace \u6620\u5C04\u6BCF\u884C\u5FC5\u987B\u4F7F\u7528 alias=value":"Each workspace mapping must use alias=value","Instruction Preset \u6620\u5C04\u6BCF\u884C\u5FC5\u987B\u4F7F\u7528 alias=value":"Each instruction preset mapping must use alias=value","action-items=\u8F6C\u6362\u4E3A\u8D1F\u8D23\u4EBA\u3001\u622A\u6B62\u548C\u9A8C\u6536\u660E\u786E\u7684\u5DE5\u5355":"action-items=Turn this into accountable tasks with deadlines and acceptance criteria","AI Office \u62D2\u7EDD\u4E86 Device Token\u3002":"AI Office rejected the Device Token.","AI Office Connector Hook \u5C1A\u672A\u5C31\u7EEA\u3002":"AI Office Connector hooks are not available yet.","AI Office Connector \u534F\u8BAE\u7248\u672C\u4E0D\u517C\u5BB9\u3002":"The AI Office Connector protocol is incompatible.","\u672C\u673A\u6682\u65F6\u65E0\u6CD5\u8BBF\u95EE AI Office\u3002":"AI Office cannot currently be reached from this machine.","AI Office \u8FDE\u63A5\u5DF2\u4E2D\u65AD\u3002":"The AI Office connection was interrupted.","\u5E2E\u52A9\u4E0E\u53CD\u9988 \xB7 \u524D\u5F80 GitHub":"Help & feedback \xB7 Open GitHub","\u8BF7\u6539\u7528 localhost \u91CD\u65B0\u6253\u5F00":"Reopen with localhost","\u9875\u9762\u4F1A\u5728\u5F53\u524D\u7AEF\u53E3\u91CD\u65B0\u6253\u5F00\uFF0C\u673A\u5668\u4EBA\u914D\u7F6E\u4E0D\u4F1A\u6539\u53D8\u3002":"The page will reopen on the current port. Your bot configuration will not change.","\u4F7F\u7528 localhost \u91CD\u65B0\u6253\u5F00":"Reopen with localhost","\u5F53\u524D\u5730\u5740\u4E0E\u6D4F\u89C8\u5668\u7684\u672C\u673A\u8BF7\u6C42\u6821\u9A8C\u4E0D\u517C\u5BB9\u3002\u8BF7\u4F7F\u7528\u4E0A\u65B9\u6309\u94AE\u6539\u7528 localhost \u91CD\u65B0\u6253\u5F00\u3002":"This address is incompatible with the browser\u2019s local-request checks. Use the button above to reopen with localhost.",\u5FAE\u4FE1:"WeChat",\u98DE\u4E66:"Feishu",\u9489\u9489:"DingTalk",\u4F01\u4E1A\u5FAE\u4FE1:"WeCom",\u5FAE\u4FE1\u673A\u5668\u4EBA:"WeChat bot",\u98DE\u4E66\u673A\u5668\u4EBA:"Feishu bot",\u9489\u9489\u673A\u5668\u4EBA:"DingTalk bot",\u4F01\u4E1A\u5FAE\u4FE1\u673A\u5668\u4EBA:"WeCom bot",QQ\u673A\u5668\u4EBA:"QQ bot",WhatsApp\u673A\u5668\u4EBA:"WhatsApp bot",WhatsApp\u8D26\u53F7:"WhatsApp account",\u5FAE\u4FE1\u8BBE\u7F6E:"WeChat settings",\u98DE\u4E66\u673A\u5668\u4EBA\u8BBE\u7F6E:"Feishu bot settings",\u7FA4\u804A\u54CD\u5E94\u65B9\u5F0F:"Group response mode","\u4EC5\u5728 @\u673A\u5668\u4EBA\u65F6\u54CD\u5E94\uFF08\u63A8\u8350\uFF09":"Only respond when @mentioned (recommended)",\u54CD\u5E94\u6240\u6709\u7FA4\u6D88\u606F:"Respond to all group messages","\u54CD\u5E94\u6240\u6709\u7FA4\u6D88\u606F\uFF08\u9700\u98DE\u4E66\u654F\u611F\u6743\u9650\uFF09":"Respond to all group messages (requires a sensitive Feishu scope)",\u91CD\u65B0\u6388\u6743:"Reauthorize",\u53BB\u6388\u6743:"Authorize",\u91CD\u65B0\u6388\u6743\u7FA4\u6D88\u606F\u6743\u9650:"Reauthorize group-message permission",\u6388\u6743\u7FA4\u6D88\u606F\u6743\u9650:"Authorize group-message permission","\u6B63\u5728\u51C6\u5907\u6388\u6743\u2026":"Preparing authorization\u2026","\u6B63\u5728\u51C6\u5907\u2026":"Preparing\u2026","\u79C1\u804A\u59CB\u7EC8\u54CD\u5E94\uFF1B\u7FA4\u804A\u4EC5\u5904\u7406\u660E\u786E @\u5F53\u524D\u673A\u5668\u4EBA\u7684\u6D88\u606F\u3002\u7FA4\u6D88\u606F\u6743\u9650\u5DF2\u5F00\u901A\uFF0C\u518D\u6B21\u5207\u6362\u65E0\u9700\u6388\u6743\u3002":"Direct messages always work; group chats require an explicit @mention of this bot. The group-message permission is already granted, so switching again needs no authorization.","\u79C1\u804A\u59CB\u7EC8\u54CD\u5E94\uFF1B\u7FA4\u804A\u4EC5\u5904\u7406\u660E\u786E @\u5F53\u524D\u673A\u5668\u4EBA\u7684\u6D88\u606F\u3002\u9009\u62E9\u5168\u90E8\u6D88\u606F\u540E\u4F1A\u6253\u5F00\u98DE\u4E66\u5B98\u65B9\u6388\u6743\u6D41\u7A0B\u3002":"Direct messages always work; group chats require an explicit @mention of this bot. Selecting all messages opens the official Feishu authorization flow.","\u5DF2\u5F00\u901A\u201C\u83B7\u53D6\u7FA4\u7EC4\u4E2D\u6240\u6709\u6D88\u606F\u201D\u6743\u9650\uFF08im:message.group_msg\uFF09\uFF1B\u673A\u5668\u4EBA\u4F1A\u5904\u7406\u7FA4\u804A\u4E2D\u7684\u6240\u6709\u53EF\u89C1\u6D88\u606F\u3002":"The \u201CRead all messages in associated group chat\u201D scope (im:message.group_msg) is granted; the bot processes every visible group message.","\u5C1A\u672A\u786E\u8BA4\u201C\u83B7\u53D6\u7FA4\u7EC4\u4E2D\u6240\u6709\u6D88\u606F\u201D\u6743\u9650\uFF0C\u8BF7\u5B8C\u6210\u98DE\u4E66\u6388\u6743\u3002":"The \u201CRead all messages in associated group chat\u201D scope has not been confirmed. Complete Feishu authorization.","\u79C1\u804A\u59CB\u7EC8\u54CD\u5E94\uFF1B\u7FA4\u804A\u4EC5\u5904\u7406\u660E\u786E @\u5F53\u524D\u673A\u5668\u4EBA\u7684\u6D88\u606F\u3002":"Direct messages always work; group chats require an explicit @mention of this bot.","\u9700\u5728\u98DE\u4E66\u4E3A\u8BE5\u673A\u5668\u4EBA\u5F00\u901A\u201C\u83B7\u53D6\u7FA4\u7EC4\u4E2D\u6240\u6709\u6D88\u606F\u201D\u6743\u9650\uFF08im:message.group_msg\uFF09\uFF1B\u5F00\u901A\u540E\uFF0C\u673A\u5668\u4EBA\u4F1A\u5904\u7406\u7FA4\u804A\u4E2D\u7684\u6240\u6709\u53EF\u89C1\u6D88\u606F\u3002":"Grant this bot the \u201CRead all messages in associated group chat\u201D Feishu scope (im:message.group_msg); once granted, it will process every visible group message.","\u7FA4\u804A\u54CD\u5E94\u65B9\u5F0F\u4FEE\u6539\u5931\u8D25\uFF0C\u8BF7\u91CD\u8BD5\u3002":"Could not update the group response mode. Try again.","\u7FA4\u6D88\u606F\u6743\u9650\u6388\u6743\u5931\u8D25\uFF0C\u8BF7\u91CD\u8BD5\u3002":"Could not authorize group-message permission. Try again.",\u9489\u9489\u8BBE\u7F6E:"DingTalk settings",\u4F01\u4E1A\u5FAE\u4FE1\u8BBE\u7F6E:"WeCom settings",\u626B\u7801\u63A5\u5165\u673A\u5668\u4EBA:"Scan QR code",\u6B63\u5728\u63A5\u5165:"Connecting",\u624B\u52A8\u63A5\u5165:"Manual setup",\u6536\u8D77\u51ED\u636E:"Hide credentials",\u6536\u8D77\u63A5\u5165:"Hide setup",\u63A5\u5165\u673A\u5668\u4EBA:"Connect bot",\u5F00\u59CB\u63A5\u5165:"Start setup",\u5728\u7EBF:"online",\u8FD0\u884C\u6B63\u5E38:"Connected",\u6B63\u5728\u8FDE\u63A5:"Connecting","\u6B63\u5728\u8FDE\u63A5\u2026":"Connecting\u2026",\u8FDE\u63A5\u672A\u5C31\u7EEA:"Not connected",\u8FDE\u63A5\u4E2D:"Connecting",\u8FDE\u63A5\u4E2D\u65AD:"Disconnected",\u9700\u8981\u5904\u7406:"Needs attention",\u72B6\u6001\u672A\u77E5:"Unknown status",\u79BB\u7EBF:"Offline",\u5DF2\u65AD\u5F00:"Disconnected",\u6D88\u606F\u901A\u9053:"Message channel",\u67E5\u770B\u6D88\u606F\u901A\u9053\u8BF4\u660E:"View message channel details",\u6700\u8FD1\u68C0\u67E5:"Last checked",\u5F53\u524D\u5DE5\u4F5C\u533A:"Current workspace",\u9009\u62E9\u76EE\u5F55:"Choose folder",\u9009\u62E9\u673A\u5668\u4EBA\u5DE5\u4F5C\u533A\u76EE\u5F55:"Select bot workspace folder",\u5F53\u524D\u76EE\u5F55:"Current folder",\u4E3B\u76EE\u5F55:"Home","\u6B63\u5728\u51C6\u5907\u76EE\u5F55\u9009\u62E9\u5668\u2026":"Preparing folder picker\u2026","\u6B63\u5728\u8BFB\u53D6\u76EE\u5F55\u2026":"Loading folders\u2026","\u8FD9\u4E2A\u76EE\u5F55\u4E2D\u6CA1\u6709\u5B50\u6587\u4EF6\u5939\u3002":"This folder has no subfolders.","\u6B64\u76EE\u5F55\u7684\u5B50\u6587\u4EF6\u5939\u8FC7\u591A\uFF0C\u4EC5\u663E\u793A\u524D\u4E00\u90E8\u5206\u3002":"This folder has too many subfolders; only the first group is shown.","\u65E0\u6CD5\u8BFB\u53D6\u76EE\u5F55\uFF0C\u8BF7\u91CD\u8BD5\u3002":"Could not load the folder. Try again.",\u91CD\u8BD5:"Retry",\u663E\u793A\u9690\u85CF\u6587\u4EF6\u5939:"Show hidden folders","\u5207\u6362\u540E\u4F1A\u6E05\u9664\u8FD9\u4E2A\u673A\u5668\u4EBA\u7684\u65E7\u4F1A\u8BDD\u6620\u5C04\u3002":"Switching clears this bot\u2019s previous session mappings.","\u5207\u6362\u4E2D\u2026":"Switching\u2026",\u9009\u62E9\u6B64\u76EE\u5F55:"Select this folder",\u5DE5\u4F5C\u533A\u7EDD\u5BF9\u8DEF\u5F84:"Absolute workspace path","/\u7EDD\u5BF9\u8DEF\u5F84/\u5230/\u5DE5\u4F5C\u533A":"/absolute/path/to/workspace",\u4FEE\u6539:"Change",\u4FDD\u5B58:"Save","\u4FDD\u5B58\u4E2D\u2026":"Saving\u2026",\u672A\u8BBE\u7F6E:"Not set","\u5DE5\u4F5C\u533A\u4FEE\u6539\u5931\u8D25\uFF0C\u8BF7\u91CD\u8BD5\u3002":"Could not update the workspace. Try again.","\u8BF7\u8F93\u5165\u5DE5\u4F5C\u533A\u7EDD\u5BF9\u8DEF\u5F84\u3002":"Enter an absolute workspace path.","\u5DE5\u4F5C\u533A\u5FC5\u987B\u662F\u7EDD\u5BF9\u8DEF\u5F84\u3002":"The workspace must be an absolute path.","\u5DE5\u4F5C\u533A\u8DEF\u5F84\u4E0D\u5B58\u5728\u3002":"The workspace path does not exist.","\u5DE5\u4F5C\u533A\u8DEF\u5F84\u5FC5\u987B\u6307\u5411\u4E00\u4E2A\u76EE\u5F55\u3002":"The workspace path must point to a directory.","\u627E\u4E0D\u5230\u8981\u4FEE\u6539\u7684\u673A\u5668\u4EBA\u3002":"The bot could not be found.","Agent Preset":"Agent Preset","\u67E5\u770B Agent Preset \u8BF4\u660E":"View Agent Preset help","\u8DDF\u968F Host \u9ED8\u8BA4":"Follow the Host default","\uFF08\u5DF2\u4E0D\u53EF\u7528\uFF09":" (unavailable)","\u53EA\u5F71\u54CD\u65B0\u5EFA\u4F1A\u8BDD\uFF1B\u82E5\u5F53\u524D\u804A\u5929\u5DF2\u6709\u4F1A\u8BDD\uFF0C\u5148\u53D1\u9001 /new\uFF0C\u518D\u53D1\u9001\u666E\u901A\u6D88\u606F\u751F\u6548\u3002":"This affects only new sessions. If the current chat already has a session, send /new, then send a regular message to apply it.","\u5F53\u524D Agent Preset \u5DF2\u4E0D\u53EF\u7528\uFF0C\u8BF7\u9009\u62E9\u5176\u4ED6 Preset \u6216\u8DDF\u968F Host \u9ED8\u8BA4\u3002":"The current Agent Preset is unavailable. Choose another preset or follow the Host default.","Agent Preset \u4FEE\u6539\u5931\u8D25\uFF0C\u8BF7\u91CD\u8BD5\u3002":"Could not update the Agent Preset. Try again.","\u8BF7\u9009\u62E9 Agent Preset\u3002":"Choose an Agent Preset.","Agent Preset \u65E0\u6548\u3002":"The Agent Preset is invalid.","Agent Preset \u4E0D\u5B58\u5728\u6216\u4E0D\u53EF\u7528\u3002":"The Agent Preset does not exist or is unavailable.",\u5C1A\u672A\u68C0\u67E5:"Not checked yet",\u521A\u521A:"Just now",\u68C0\u67E5\u8FDE\u63A5:"Check connection","\u68C0\u67E5\u4E2D\u2026":"Checking\u2026","\u8FDE\u63A5\u68C0\u67E5\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002":"Connection check failed. Try again later.","\u6D4B\u8BD5\u6D88\u606F\u5DF2\u53D1\u9001\uFF0C\u8BF7\u5230\u5BF9\u5E94\u673A\u5668\u4EBA\u4F1A\u8BDD\u4E2D\u786E\u8BA4\u3002":"Test message sent. Check the matching bot conversation.","\u8FDE\u63A5\u68C0\u67E5\u5B8C\u6210\u3002\u673A\u5668\u4EBA\u5C1A\u672A\u6536\u5230\u53EF\u7528\u4E8E\u6D4B\u8BD5\u7684\u79C1\u804A\u6D88\u606F\u3002":"Connection check completed. The bot has not received a direct message it can use for testing.","\u8FDE\u63A5\u68C0\u67E5\u5B8C\u6210\uFF0C\u4F46\u6D4B\u8BD5\u6D88\u606F\u53D1\u9001\u5931\u8D25\u3002":"Connection check completed, but the test message could not be sent.","\u6D4B\u8BD5\u6D88\u606F\u5DF2\u53D1\u9001\uFF0C\u8BF7\u5230\u98DE\u4E66\u4F1A\u8BDD\u4E2D\u786E\u8BA4\u3002":"Test message sent. Check the Feishu conversation.","\u6D4B\u8BD5\u6D88\u606F\u5DF2\u53D1\u9001\uFF0C\u8BF7\u5230 WhatsApp \u81EA\u804A\u4F1A\u8BDD\u4E2D\u786E\u8BA4\u3002":"Test message sent. Check the WhatsApp self-chat.","\u8FDE\u63A5\u68C0\u67E5\u5B8C\u6210\uFF0C\u4F46\u5F53\u524D\u6CA1\u6709\u53EF\u7528\u7684 WhatsApp \u81EA\u804A\u76EE\u6807\u3002":"Connection check completed, but no WhatsApp self-chat target is available.","\u9489\u9489\u8FDE\u63A5\u68C0\u67E5\u5B8C\u6210\uFF0C\u6D4B\u8BD5\u6D88\u606F\u5DF2\u53D1\u9001\u3002":"DingTalk connection check completed and the test message was sent.","\u9489\u9489\u8FDE\u63A5\u68C0\u67E5\u5B8C\u6210\uFF0C\u4F46\u6D4B\u8BD5\u6D88\u606F\u53D1\u9001\u5931\u8D25\u3002":"DingTalk connection check completed, but the test message could not be sent.","\u5FAE\u4FE1\u8FDE\u63A5\u68C0\u67E5\u5B8C\u6210\uFF0C\u6D4B\u8BD5\u6D88\u606F\u5DF2\u53D1\u9001\u3002":"WeChat connection check completed and the test message was sent.","\u5FAE\u4FE1\u8FDE\u63A5\u68C0\u67E5\u5B8C\u6210\uFF0C\u4F46\u6D4B\u8BD5\u6D88\u606F\u53D1\u9001\u5931\u8D25\u3002":"WeChat connection check completed, but the test message could not be sent.","\u4F01\u4E1A\u5FAE\u4FE1\u8FDE\u63A5\u68C0\u67E5\u5B8C\u6210\uFF0C\u6D4B\u8BD5\u6D88\u606F\u5DF2\u53D1\u9001\u3002":"WeCom connection check completed and the test message was sent.","\u4F01\u4E1A\u5FAE\u4FE1\u8FDE\u63A5\u68C0\u67E5\u5B8C\u6210\uFF0C\u4F46\u6D4B\u8BD5\u6D88\u606F\u53D1\u9001\u5931\u8D25\u3002":"WeCom connection check completed, but the test message could not be sent.",\u91CD\u8BD5\u8FDE\u63A5:"Reconnect","\u91CD\u8BD5\u4E2D\u2026":"Retrying\u2026",\u79FB\u9664\u63A5\u5165:"Remove connection",\u786E\u8BA4\u79FB\u9664\u63A5\u5165:"Remove connection",\u786E\u8BA4\u79FB\u9664:"Remove","\u6B63\u5728\u79FB\u9664\u2026":"Removing\u2026",\u4FDD\u7559\u673A\u5668\u4EBA:"Keep bot",\u4FDD\u7559\u8D26\u53F7:"Keep account",\u53D6\u6D88:"Cancel",\u5173\u95ED:"Close",\u7ACB\u5373\u91CD\u8BD5:"Retry now",\u91CD\u65B0\u8BFB\u53D6:"Reload",\u91CD\u65B0\u751F\u6210\u4E8C\u7EF4\u7801:"Generate a new QR code",\u91CD\u65B0\u751F\u6210\u4E8C\u7EF4\u7801\u540E\u7EE7\u7EED:"Generate a new QR code",\u5237\u65B0\u4E8C\u7EF4\u7801:"Refresh QR code","\u5237\u65B0\u4E2D\u2026":"Refreshing\u2026",\u6362\u4E00\u4E2A\u4E8C\u7EF4\u7801:"Get another QR code",\u7EE7\u7EED\u8FDE\u63A5:"Continue connecting",\u7ED1\u5B9A\u5E76\u8FDE\u63A5:"Connect","\u6B63\u5728\u7ED1\u5B9A\u2026":"Connecting\u2026",\u9A8C\u8BC1\u5E76\u8FDE\u63A5:"Verify and connect","\u6B63\u5728\u9A8C\u8BC1\u5E76\u8FDE\u63A5\u2026":"Verifying and connecting\u2026","\u6B63\u5728\u9A8C\u8BC1\u2026":"Verifying\u2026","\u64CD\u4F5C\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5":"The operation failed. Try again later.",\u8BF7\u7A0D\u540E\u91CD\u8BD5:"Try again later.",\u5F53\u524D\u4E8C\u7EF4\u7801\u6709\u6548\u65F6\u95F4:"QR code expires in",\u4E8C\u7EF4\u7801\u6709\u6548\u65F6\u95F4:"QR code expires in",\u4E8C\u7EF4\u7801\u5DF2\u8FC7\u671F:"QR code expired",\u4E8C\u7EF4\u7801\u5DF2\u5931\u6548:"QR code expired","\u4E8C\u7EF4\u7801\u5DF2\u8FC7\u671F\n\u8BF7\u91CD\u65B0\u751F\u6210":`QR code expired Generate a new one`,"\u4E8C\u7EF4\u7801\u56FE\u7247\u6B63\u5728\u751F\u6210\u2026":"Generating QR code\u2026","\u4E8C\u7EF4\u7801\u6B63\u5728\u751F\u6210\u2026":"Generating QR code\u2026","\u4E8C\u7EF4\u7801\u6B63\u5728\u81EA\u52A8\u5237\u65B0\u2026":"Refreshing QR code\u2026","\u4E8C\u7EF4\u7801\u672A\u5C31\u7EEA\uFF0C\u8BF7\u6253\u5F00\u6388\u6743\u94FE\u63A5":"The QR code is not ready. Open the authorization link.","\u4E8C\u7EF4\u7801\u56FE\u7247\u672A\u5C31\u7EEA\uFF0C\u8BF7\u4F7F\u7528\u5907\u7528\u94FE\u63A5\u3002":"The QR code is not ready. Use the alternate link.","\u4E8C\u7EF4\u7801\u56FE\u7247\u672A\u5C31\u7EEA\uFF0C\u8BF7\u91CD\u65B0\u751F\u6210\u3002":"The QR code is not ready. Generate a new one.",\u7B49\u5F85\u5237\u65B0:"Waiting to refresh",\u6B63\u5728\u5237\u65B0\u4E8C\u7EF4\u7801:"Refreshing QR code",\u6253\u5F00\u5907\u7528\u94FE\u63A5:"Open alternate link",\u751F\u6210\u4E8C\u7EF4\u7801:"Generate QR code",\u751F\u6210\u5FAE\u4FE1\u4E8C\u7EF4\u7801:"Generate WeChat QR code",\u751F\u6210\u98DE\u4E66\u4E8C\u7EF4\u7801:"Generate Feishu QR code",\u751F\u6210\u9489\u9489\u4E8C\u7EF4\u7801:"Generate DingTalk QR code",\u751F\u6210\u4F01\u4E1A\u5FAE\u4FE1\u4E8C\u7EF4\u7801:"Generate WeCom QR code","\u751F\u6210 QQ \u4E8C\u7EF4\u7801":"Generate QQ QR code","\u6B63\u5728\u751F\u6210\u4E8C\u7EF4\u7801\u2026":"Generating QR code\u2026",\u6B63\u5728\u51C6\u5907\u6388\u6743\u4E8C\u7EF4\u7801:"Preparing authorization QR code",\u6B63\u5728\u51C6\u5907\u6743\u9650\u6388\u6743\u4E8C\u7EF4\u7801:"Preparing permission authorization QR code",\u6B63\u5728\u51C6\u5907\u5FAE\u4FE1\u4E8C\u7EF4\u7801:"Preparing WeChat QR code",\u6B63\u5728\u6DFB\u52A0\u65B0\u673A\u5668\u4EBA:"Adding a new bot","\u6B63\u5728\u7533\u8BF7\u9489\u9489\u6388\u6743\u4E8C\u7EF4\u7801\u2026":"Requesting DingTalk authorization QR code\u2026","\u6B63\u5728\u7533\u8BF7\u4F01\u4E1A\u5FAE\u4FE1\u4E8C\u7EF4\u7801\u2026":"Requesting WeCom QR code\u2026","\u6B63\u5728\u7533\u8BF7 QQ \u4E8C\u7EF4\u7801\u2026":"Requesting QQ QR code\u2026","\u6B63\u5728\u751F\u6210 WhatsApp \u4E8C\u7EF4\u7801":"Generating WhatsApp QR code","\u626B\u7801\uFF0C\u521B\u5EFA\u7B2C\u4E00\u4E2A\u98DE\u4E66\u5165\u53E3":"Scan to create your first Feishu bot","\u626B\u7801\u53EA\u4F1A\u65B0\u589E\u4E00\u4E2A\u673A\u5668\u4EBA\uFF0C\u5DF2\u63A5\u5165\u7684\u673A\u5668\u4EBA\u4F1A\u7EE7\u7EED\u6B63\u5E38\u6536\u53D1\u6D88\u606F\u3002":"Scanning adds one bot. Existing bots will continue to send and receive messages.","\u65E0\u9700\u624B\u52A8\u586B\u5199 App ID\u3002\u4EE5\u540E\u8FD8\u53EF\u4EE5\u7EE7\u7EED\u6DFB\u52A0\u673A\u5668\u4EBA\uFF0C\u5206\u522B\u670D\u52A1\u4E0D\u540C\u56E2\u961F\u6216\u98DE\u4E66\u79DF\u6237\u3002":"No App ID is required. You can add more bots later for different teams or Feishu tenants.",\u4F7F\u7528\u98DE\u4E66\u626B\u7801\u521B\u5EFA\u673A\u5668\u4EBA:"Scan with Feishu to create a bot",\u5237\u65B0\u4E8C\u7EF4\u7801\u540E\u7EE7\u7EED:"Refresh the QR code to continue","\u6253\u5F00\u98DE\u4E66\u79FB\u52A8\u7AEF\uFF0C\u4F7F\u7528\u626B\u4E00\u626B\u8BFB\u53D6\u4E8C\u7EF4\u7801":"Open Feishu on your phone and scan the QR code","\u6838\u5BF9\u5E94\u7528\u540D\u79F0\u4E0E\u6743\u9650\u8303\u56F4\uFF0C\u5E76\u786E\u8BA4\u521B\u5EFA":"Review the app name and permissions, then confirm","\u4FDD\u6301\u672C\u9875\u6253\u5F00\uFF0C\u7B49\u5F85\u65B0\u673A\u5668\u4EBA\u7684\u957F\u8FDE\u63A5\u5C31\u7EEA":"Keep this page open until the bot connection is ready",\u5728\u98DE\u4E66\u4E2D\u6253\u5F00:"Open in Feishu",\u53D6\u6D88\u6DFB\u52A0:"Cancel",\u4F7F\u7528\u98DE\u4E66\u626B\u7801\u4FEE\u590D\u5361\u7247\u6309\u94AE:"Scan with Feishu to repair card buttons",\u4F7F\u7528\u98DE\u4E66\u786E\u8BA4\u7FA4\u6D88\u606F\u6743\u9650:"Confirm group-message permission with Feishu","\u626B\u7801\u4F1A\u66F4\u65B0\u73B0\u6709\u98DE\u4E66\u5E94\u7528\uFF0C\u53EA\u589E\u91CF\u5F00\u901A\u201C\u83B7\u53D6\u7FA4\u7EC4\u4E2D\u6240\u6709\u6D88\u606F\u201D\u6743\u9650\uFF1B\u4E0D\u4F1A\u521B\u5EFA\u65B0\u5E94\u7528\u3002\u786E\u8BA4\u540E\u4F1A\u81EA\u52A8\u542F\u7528\u201C\u54CD\u5E94\u6240\u6709\u7FA4\u6D88\u606F\u201D\uFF0C\u5176\u4ED6\u673A\u5668\u4EBA\u4E0D\u53D7\u5F71\u54CD\u3002":"Scanning updates the existing Feishu app with only the \u201CRead all messages in associated group chat\u201D scope. It does not create a new app. After confirmation, \u201CRespond to all group messages\u201D is enabled automatically; other bots are unaffected.","\u6838\u5BF9\u73B0\u6709\u5E94\u7528\uFF0C\u5E76\u786E\u8BA4\u201C\u83B7\u53D6\u7FA4\u7EC4\u4E2D\u6240\u6709\u6D88\u606F\u201D\u6743\u9650":"Review the existing app and confirm the \u201CRead all messages in associated group chat\u201D permission","\u4FDD\u6301\u672C\u9875\u6253\u5F00\uFF0C\u7B49\u5F85\u6743\u9650\u751F\u6548\u5E76\u81EA\u52A8\u5207\u6362\u54CD\u5E94\u65B9\u5F0F":"Keep this page open while the permission takes effect and the response mode switches automatically",\u53D6\u6D88\u6388\u6743:"Cancel authorization","\u5DF2\u786E\u8BA4\uFF0C\u6B63\u5728\u542F\u7528\u5168\u90E8\u6D88\u606F\u6A21\u5F0F":"Confirmed. Enabling all-message mode","\u6743\u9650\u914D\u7F6E\u5DF2\u63D0\u4EA4\uFF0C\u6B63\u5728\u4FDD\u5B58\u8BBE\u7F6E\u5E76\u91CD\u8FDE\u6B64\u673A\u5668\u4EBA\uFF1B\u6B64\u9636\u6BB5\u65E0\u6CD5\u53D6\u6D88\uFF0C\u5176\u4ED6\u673A\u5668\u4EBA\u4E0D\u4F1A\u4E2D\u65AD\u3002":"The permission update was submitted. Saving the setting and reconnecting this bot. This stage cannot be cancelled; other bots will not be interrupted.","\u6743\u9650\u914D\u7F6E\u5DF2\u63D0\u4EA4\uFF0C\u6B63\u5728\u542F\u7528\u5168\u90E8\u6D88\u606F\u6A21\u5F0F\u5E76\u91CD\u8FDE\u6B64\u673A\u5668\u4EBA\uFF1B\u6B64\u9636\u6BB5\u65E0\u6CD5\u53D6\u6D88\uFF0C\u5176\u4ED6\u673A\u5668\u4EBA\u4E0D\u4F1A\u4E2D\u65AD\u3002":"The permission update was submitted. Enabling all-message mode and reconnecting this bot. This stage cannot be cancelled; other bots will not be interrupted.","\u6B63\u5728\u4E3A\u73B0\u6709\u98DE\u4E66\u5E94\u7528\u7533\u8BF7\u7FA4\u6D88\u606F\u6743\u9650\u4E8C\u7EF4\u7801\uFF0C\u8BF7\u7A0D\u5019\u3002":"Requesting a group-message permission QR code for the existing Feishu app\u2026",\u7FA4\u6D88\u606F\u6743\u9650\u6CA1\u6709\u5F00\u901A\u5B8C\u6210:"Group-message permission was not granted","\u626B\u7801\u4F1A\u66F4\u65B0\u73B0\u6709\u98DE\u4E66\u5E94\u7528\uFF0C\u53EA\u589E\u91CF\u8865\u5145\u5361\u7247\u6309\u94AE\u56DE\u8C03\uFF1B\u4E0D\u4F1A\u521B\u5EFA\u65B0\u5E94\u7528\u3002\u786E\u8BA4\u540E\u6B64\u673A\u5668\u4EBA\u4F1A\u77ED\u6682\u91CD\u8FDE\uFF0C\u5176\u4ED6\u673A\u5668\u4EBA\u4E0D\u53D7\u5F71\u54CD\u3002":"Scanning updates the existing Feishu app with only the card-button callback. It does not create a new app. This bot reconnects briefly after confirmation; other bots are not affected.","\u6838\u5BF9\u73B0\u6709\u5E94\u7528\u540D\u79F0\uFF0C\u5E76\u786E\u8BA4\u53EA\u65B0\u589E\u5361\u7247\u56DE\u8C03":"Review the existing app name and confirm that only the card callback is added","\u4FDD\u6301\u672C\u9875\u6253\u5F00\uFF0C\u7B49\u5F85\u5361\u7247\u6309\u94AE\u4FEE\u590D\u5B8C\u6210":"Keep this page open until card-button repair finishes",\u53D6\u6D88\u4FEE\u590D:"Cancel repair","\u5DF2\u786E\u8BA4\uFF0C\u6B63\u5728\u5B8C\u6210\u5361\u7247\u6309\u94AE\u4FEE\u590D":"Confirmed. Finishing card-button repair",\u6B63\u5728\u51C6\u5907\u4FEE\u590D\u4E8C\u7EF4\u7801:"Preparing the repair QR code","\u914D\u7F6E\u5DF2\u63D0\u4EA4\uFF0C\u6B63\u5728\u9A8C\u8BC1\u5361\u7247\u6309\u94AE\u56DE\u8C03\u5E76\u91CD\u8FDE\u6B64\u673A\u5668\u4EBA\uFF1B\u6B64\u9636\u6BB5\u65E0\u6CD5\u53D6\u6D88\uFF0C\u5176\u4ED6\u673A\u5668\u4EBA\u4E0D\u4F1A\u4E2D\u65AD\u3002":"The update was submitted. Verifying the card callback and reconnecting this bot. This stage cannot be cancelled; other bots will not be interrupted.","\u6B63\u5728\u4E3A\u73B0\u6709\u98DE\u4E66\u5E94\u7528\u7533\u8BF7\u4E00\u6B21\u6027\u66F4\u65B0\u4E8C\u7EF4\u7801\uFF0C\u8BF7\u7A0D\u5019\u3002":"Requesting a one-time update QR code for the existing Feishu app\u2026",\u5361\u7247\u6309\u94AE\u6CA1\u6709\u4FEE\u590D\u5B8C\u6210:"Card-button repair did not finish",\u4FEE\u590D\u5361\u7247\u6309\u94AE:"Repair card buttons","\u7B49\u5F85\u626B\u7801\u2026":"Waiting for scan\u2026",\u98DE\u4E66\u670D\u52A1\u8FD4\u56DE\u4E86\u4E0D\u5339\u914D\u7684\u5361\u7247\u4FEE\u590D\u4E8C\u7EF4\u7801:"Feishu returned a repair QR code for a different bot",\u98DE\u4E66\u670D\u52A1\u8FD4\u56DE\u4E86\u4E0D\u5339\u914D\u7684\u7FA4\u6D88\u606F\u6743\u9650\u4E8C\u7EF4\u7801:"Feishu returned a group-message permission QR code for a different bot","\u98DE\u4E66\u670D\u52A1\u8FD4\u56DE\u7684\u4FEE\u590D\u4FE1\u606F\u7F3A\u5C11 botId":"Feishu repair status is missing the bot ID","\u98DE\u4E66\u670D\u52A1\u8FD4\u56DE\u7684\u5E94\u7528\u66F4\u65B0\u4FE1\u606F\u7F3A\u5C11 botId":"Feishu app-update status is missing the bot ID",\u98DE\u4E66\u670D\u52A1\u8FD4\u56DE\u4E86\u4E0D\u5339\u914D\u7684\u6CE8\u518C\u8FDB\u5EA6:"Feishu returned registration progress for a different operation",\u6B64\u673A\u5668\u4EBA:"this bot","\u7528\u4E8E\u4E3A${botName}\u5F00\u901A\u7FA4\u6D88\u606F\u6743\u9650\u7684\u4E00\u6B21\u6027\u6388\u6743\u4E8C\u7EF4\u7801":"One-time QR code for granting group-message permission to ${botName}","\u6B63\u5728\u4E3A\u300C${botName}\u300D\u5F00\u901A\u7FA4\u6D88\u606F\u6743\u9650":"Granting group-message permission to \u201C${botName}\u201D",'${botName ?? "\u673A\u5668\u4EBA"}\u7684\u4FEE\u590D\u4E8C\u7EF4\u7801\u5DF2\u751F\u6210\uFF0C\u8BF7\u4F7F\u7528\u98DE\u4E66\u626B\u7801\u3002':'Repair QR code generated for ${botName ?? "bot"}. Scan it with Feishu.','${botName ?? "\u673A\u5668\u4EBA"}\u7684\u7FA4\u6D88\u606F\u6743\u9650\u4E8C\u7EF4\u7801\u5DF2\u751F\u6210\uFF0C\u8BF7\u4F7F\u7528\u98DE\u4E66\u786E\u8BA4\u3002':'Group-message permission QR code generated for ${botName ?? "bot"}. Confirm it with Feishu.',"${targetBotName}\u5DF2\u5F00\u901A\u7FA4\u6D88\u606F\u6743\u9650\uFF0C\u5E76\u542F\u7528\u201C\u54CD\u5E94\u6240\u6709\u7FA4\u6D88\u606F\u201D\u3002":"${targetBotName} now has group-message permission and \u201CRespond to all group messages\u201D is enabled.","${targetBot.bot.name}\u5DF2\u5F00\u901A\u7FA4\u6D88\u606F\u6743\u9650\uFF0C\u5E76\u542F\u7528\u201C\u54CD\u5E94\u6240\u6709\u7FA4\u6D88\u606F\u201D\u3002":"${targetBot.bot.name} now has group-message permission and \u201CRespond to all group messages\u201D is enabled.","${targetBot.bot.name}\u5DF2\u8FDE\u63A5\uFF0C\u53EF\u4EE5\u5728\u98DE\u4E66\u4E2D\u5F00\u59CB\u804A\u5929\u3002":"${targetBot.bot.name} is connected and ready to chat in Feishu.","\u5DF2\u53D6\u6D88\u5361\u7247\u6309\u94AE\u4FEE\u590D\u3002":"Card-button repair was cancelled.","\u5DF2\u53D6\u6D88\u7FA4\u6D88\u606F\u6743\u9650\u6388\u6743\u3002":"Group-message permission authorization was cancelled.","\u5361\u7247\u6309\u94AE\u5DF2\u66F4\u65B0\uFF0C\u4F46\u6682\u65F6\u65E0\u6CD5\u786E\u8BA4\u673A\u5668\u4EBA\u8FDE\u63A5\u72B6\u6001":"The card callback was updated, but the bot connection could not be confirmed yet","\u7FA4\u6D88\u606F\u6743\u9650\u5DF2\u66F4\u65B0\uFF0C\u4F46\u6682\u65F6\u65E0\u6CD5\u786E\u8BA4\u673A\u5668\u4EBA\u8FDE\u63A5\u72B6\u6001":"The group-message permission was updated, but the bot connection could not be confirmed yet",\u98DE\u4E66\u5361\u7247\u6309\u94AE\u4FEE\u590D\u5931\u8D25:"Could not repair the Feishu card buttons",\u98DE\u4E66\u7FA4\u6D88\u606F\u6743\u9650\u5F00\u901A\u5931\u8D25:"Could not grant the Feishu group-message permission","\u8BF7\u5148\u5B8C\u6210\u5F53\u524D\u98DE\u4E66\u6388\u6743\u64CD\u4F5C\uFF0C\u518D\u5F00\u901A\u7FA4\u6D88\u606F\u6743\u9650\u3002":"Finish the current Feishu authorization before granting group-message permission.","\u5DF2\u786E\u8BA4\uFF0C\u6B63\u5728\u8FDE\u63A5\u65B0\u673A\u5668\u4EBA":"Confirmed. Connecting the new bot","\u6B63\u5728\u5B89\u5168\u4FDD\u5B58\u51ED\u636E\u5E76\u68C0\u67E5\u65B0\u673A\u5668\u4EBA\u7684\u6D88\u606F\u901A\u9053\uFF0C\u5176\u4ED6\u673A\u5668\u4EBA\u4E0D\u4F1A\u4E2D\u65AD\u3002":"Saving credentials and checking the new bot connection. Existing bots will not be interrupted.","\u6B63\u5728\u5411\u98DE\u4E66\u7533\u8BF7\u4E00\u6B21\u6027\u6388\u6743\u4E8C\u7EF4\u7801\uFF0C\u8BF7\u7A0D\u5019\u3002":"Requesting a one-time authorization QR code from Feishu\u2026",\u65B0\u673A\u5668\u4EBA\u6CA1\u6709\u6DFB\u52A0\u5B8C\u6210:"The new bot was not added","\u65B0\u98DE\u4E66\u673A\u5668\u4EBA\u5DF2\u8FDE\u63A5\uFF0C\u53EF\u4EE5\u5F00\u59CB\u804A\u5929\u3002":"The new Feishu bot is connected and ready to chat.",\u98DE\u4E66\u5E94\u7528\u521B\u5EFA\u5931\u8D25:"Could not create the Feishu app","\u673A\u5668\u4EBA\u5DF2\u7ECF\u521B\u5EFA\uFF0C\u4F46\u6682\u65F6\u65E0\u6CD5\u786E\u8BA4\u8FDE\u63A5\u72B6\u6001":"The bot was created, but its connection could not be confirmed yet",\u673A\u5668\u4EBA\u4ECD\u672A\u8FDE\u63A5:"The bot is still offline",\u673A\u5668\u4EBA\u5C1A\u672A\u8FDE\u63A5:"The bot is not connected yet",\u957F\u8FDE\u63A5\u8FD0\u884C\u6B63\u5E38:"Persistent connection is healthy",\u957F\u8FDE\u63A5:"Persistent connection",\u5E94\u7528\u6807\u8BC6\u5DF2\u5B89\u5168\u4FDD\u5B58:"App identifier stored securely",\u673A\u5668\u4EBA\u6807\u8BC6\u5DF2\u5B89\u5168\u4FDD\u5B58:"Bot identifier stored securely",\u5DF2\u5B89\u5168\u4FDD\u5B58:"Stored securely",\u5DF2\u63A5\u5165\u7684\u5FAE\u4FE1\u8D26\u53F7:"Connected WeChat accounts",\u5DF2\u63A5\u5165\u7684\u673A\u5668\u4EBA:"Connected bots",\u5DF2\u63A5\u5165\u7684\u9489\u9489\u673A\u5668\u4EBA:"Connected DingTalk bots",\u5DF2\u7ED1\u5B9A\u7684\u4F01\u4E1A\u5FAE\u4FE1\u673A\u5668\u4EBA:"Connected WeCom bots","\u5DF2\u7ED1\u5B9A\u7684 QQ \u673A\u5668\u4EBA":"Connected QQ bots","\u5DF2\u63A5\u5165\u7684 WhatsApp \u673A\u5668\u4EBA":"Connected WhatsApp accounts",\u4F7F\u7528\u624B\u673A\u5FAE\u4FE1\u626B\u63CF\u4E8C\u7EF4\u7801:"Scan with WeChat on your phone","\u626B\u4E00\u6B21\u7801\uFF0C\u5C31\u80FD\u5728\u5FAE\u4FE1\u91CC\u4F7F\u7528 Harness":"Scan once to use Harness in WeChat",\u6253\u5F00\u624B\u673A\u5FAE\u4FE1\u5E76\u626B\u63CF\u5DE6\u4FA7\u4E8C\u7EF4\u7801:"Open WeChat on your phone and scan the QR code",\u5728\u5FAE\u4FE1\u4E2D\u786E\u8BA4\u8FDE\u63A5\u8BE5\u673A\u5668\u4EBA:"Confirm the bot connection in WeChat","\u4FDD\u6301\u672C\u9875\u6253\u5F00\uFF0C\u7B49\u5F85\u673A\u5668\u4EBA\u81EA\u52A8\u8FDE\u63A5":"Keep this page open while the bot connects",\u7B49\u5F85\u5FAE\u4FE1\u626B\u7801:"Waiting for WeChat scan",\u9700\u8981\u914D\u5BF9\u7801:"Pairing code required",\u8F93\u5165\u624B\u673A\u5FAE\u4FE1\u663E\u793A\u7684\u6570\u5B57:"Enter the number shown in WeChat",\u5FAE\u4FE1\u914D\u5BF9\u7801:"WeChat pairing code","\u5DF2\u626B\u7801\uFF0C\u8BF7\u5728\u624B\u673A\u4E0A\u786E\u8BA4":"Scanned. Confirm on your phone","\u914D\u5BF9\u7801\u5DF2\u63D0\u4EA4\uFF0C\u6B63\u5728\u7B49\u5F85\u5FAE\u4FE1\u786E\u8BA4\u3002":"Pairing code submitted. Waiting for WeChat confirmation.","\u8FD9\u662F\u5FAE\u4FE1\u9644\u52A0\u7684\u5B89\u5168\u786E\u8BA4\u6B65\u9AA4\u3002\u914D\u5BF9\u7801\u53EA\u7528\u4E8E\u672C\u6B21\u626B\u7801\u8F6E\u8BE2\uFF0C\u4E0D\u4F1A\u5199\u5165\u914D\u7F6E\u6216\u65E5\u5FD7\u3002":"This is an additional WeChat confirmation step. The pairing code is used only for this connection and is never stored.","\u6B63\u5728\u4FDD\u5B58\u51ED\u636E\u5E76\u9A8C\u8BC1 Harness \u4E0E\u5FAE\u4FE1\u957F\u8F6E\u8BE2\u3002":"Saving credentials and verifying the WeChat connection.","\u5FAE\u4FE1\u5DF2\u786E\u8BA4\uFF0C\u6B63\u5728\u542F\u52A8\u6D88\u606F\u8FDE\u63A5":"Confirmed in WeChat. Starting the message connection","\u5FAE\u4FE1\u5DF2\u6388\u6743\uFF0C\u4F46\u65E0\u6CD5\u8BFB\u53D6\u73B0\u6709\u767B\u5F55\u51ED\u636E\u3002\u8BF7\u68C0\u67E5 DSH \u51ED\u636E\u5B58\u50A8\u3002":"WeChat was authorized, but the existing login credential could not be read. Check the DSH credential store.","\u5FAE\u4FE1\u5DF2\u6388\u6743\uFF0C\u4F46\u767B\u5F55\u51ED\u636E\u65E0\u6CD5\u5199\u5165 DSH \u51ED\u636E\u5B58\u50A8\u3002\u8BF7\u68C0\u67E5\u51ED\u636E\u5B58\u50A8\u662F\u5426\u53EF\u5199\u3002":"WeChat was authorized, but the login credential could not be written to the DSH credential store. Check that the store is writable.","\u5FAE\u4FE1\u5DF2\u6388\u6743\uFF0C\u4F46\u8D26\u53F7\u914D\u7F6E\u65E0\u6CD5\u5199\u5165\u672C\u673A\u3002\u8BF7\u68C0\u67E5 DSH_HOME \u76EE\u5F55\u6743\u9650\u3002":"WeChat was authorized, but the account configuration could not be saved locally. Check the DSH_HOME directory permissions.","\u5FAE\u4FE1\u5DF2\u6388\u6743\uFF0C\u4F46\u65E0\u6CD5\u521D\u59CB\u5316\u8D26\u53F7\u72B6\u6001\u6216\u5DE5\u4F5C\u533A\u3002\u8BF7\u68C0\u67E5 DSH_HOME \u548C\u5DE5\u4F5C\u533A\u76EE\u5F55\u3002":"WeChat was authorized, but the account state or workspace could not be initialized. Check DSH_HOME and the workspace directory.","\u5FAE\u4FE1\u5DF2\u6388\u6743\uFF0C\u4F46\u63D2\u4EF6\u65E0\u6CD5\u8FDE\u63A5\u672C\u673A Harness\u3002\u8BF7\u68C0\u67E5 dsh web \u5730\u5740\u548C\u7AEF\u53E3\u3002":"WeChat was authorized, but the plugin could not connect to the local Harness. Check the dsh web address and port.","\u5FAE\u4FE1\u5DF2\u6388\u6743\uFF0C\u4F46 Harness \u5065\u5EB7\u68C0\u67E5\u8D85\u65F6\u3002\u8BF7\u786E\u8BA4 dsh web \u672A\u963B\u585E\u3002":"WeChat was authorized, but the Harness health check timed out. Confirm that dsh web is not blocked.","\u5FAE\u4FE1\u5DF2\u6388\u6743\uFF0C\u4F46 Harness \u62D2\u7EDD\u4E86\u672C\u673A\u5065\u5EB7\u68C0\u67E5\u3002\u8BF7\u68C0\u67E5 Host \u4FE1\u4EFB\u914D\u7F6E\u3002":"WeChat was authorized, but Harness denied the local health check. Check the Host trust configuration.","\u5FAE\u4FE1\u5DF2\u6388\u6743\uFF0C\u4F46\u627E\u4E0D\u5230 Harness \u5065\u5EB7\u68C0\u67E5\u63A5\u53E3\u3002\u8BF7\u786E\u8BA4 Harness \u4E0E\u63D2\u4EF6\u7248\u672C\u517C\u5BB9\u3002":"WeChat was authorized, but the Harness health endpoint was not found. Confirm that Harness and the plugin are compatible.","\u5FAE\u4FE1\u5DF2\u6388\u6743\uFF0C\u4F46 Harness \u5065\u5EB7\u68C0\u67E5\u8FD4\u56DE\u670D\u52A1\u9519\u8BEF\u3002\u8BF7\u67E5\u770B dsh web \u65E5\u5FD7\u3002":"WeChat was authorized, but the Harness health check returned a service error. Check the dsh web logs.","\u5FAE\u4FE1\u5DF2\u6388\u6743\uFF0C\u4F46 Harness \u8FD4\u56DE\u4E86\u65E0\u6CD5\u8BC6\u522B\u7684\u54CD\u5E94\u3002\u8BF7\u786E\u8BA4 Harness \u4E0E\u63D2\u4EF6\u7248\u672C\u517C\u5BB9\u3002":"WeChat was authorized, but Harness returned an unrecognized response. Confirm that Harness and the plugin are compatible.","\u5FAE\u4FE1\u5DF2\u6388\u6743\uFF0C\u4F46 Harness \u62D2\u7EDD\u4E86\u5065\u5EB7\u68C0\u67E5\u8BF7\u6C42\u3002\u8BF7\u67E5\u770B dsh web \u65E5\u5FD7\u3002":"WeChat was authorized, but Harness rejected the health-check request. Check the dsh web logs.","\u5FAE\u4FE1\u5DF2\u6388\u6743\uFF0C\u4F46 Harness \u5065\u5EB7\u68C0\u67E5\u53D1\u751F\u672A\u77E5\u9519\u8BEF\u3002\u8BF7\u67E5\u770B dsh web \u65E5\u5FD7\u3002":"WeChat was authorized, but the Harness health check failed unexpectedly. Check the dsh web logs.","\u5FAE\u4FE1\u5DF2\u6388\u6743\uFF0C\u4F46\u6D88\u606F\u8FDE\u63A5\u521D\u59CB\u5316\u5931\u8D25\u3002\u8BF7\u67E5\u770B dsh web \u65E5\u5FD7\u540E\u91CD\u8BD5\u3002":"WeChat was authorized, but the message connection could not be initialized. Check the dsh web logs and try again.","\u5FAE\u4FE1\u5DF2\u6388\u6743\uFF0C\u4F46\u6FC0\u6D3B\u8FC7\u7A0B\u4E2D\u53D1\u751F\u672A\u77E5\u9519\u8BEF\u3002\u8BF7\u67E5\u770B dsh web \u65E5\u5FD7\u3002":"WeChat was authorized, but an unknown error occurred during activation. Check the dsh web logs.","\u5FAE\u4FE1\u5DF2\u7ED1\u5B9A\uFF0C\u53EF\u4EE5\u5F00\u59CB\u5411\u5DF2\u7ED1\u5B9A\u7684\u673A\u5668\u4EBA\u53D1\u6D88\u606F\u3002":"WeChat is connected and ready for messages.","\u8FD9\u4E2A\u5FAE\u4FE1\u8D26\u53F7\u5DF2\u7ECF\u7ED1\u5B9A\u5E76\u4FDD\u6301\u5728\u7EBF\u3002":"This WeChat account is connected and online.","\u5FAE\u4FE1\u8D26\u53F7\u53CA\u672C\u673A\u51ED\u636E\u5DF2\u79FB\u9664\u3002":"The WeChat account and local credentials were removed.","\u5DF2\u53D6\u6D88\u5FAE\u4FE1\u7ED1\u5B9A\u3002":"WeChat setup was cancelled.","\u6B63\u5728\u8054\u7CFB\u817E\u8BAF\u5FAE\u4FE1 iLink \u670D\u52A1\u3002":"Contacting the WeChat iLink service.","iLink \u957F\u8F6E\u8BE2":"iLink long polling","\u626B\u4E00\u6B21\u7801\uFF0C\u81EA\u52A8\u521B\u5EFA\u5E76\u8FDE\u63A5\u673A\u5668\u4EBA":"Scan once to create and connect a bot","\u4F7F\u7528\u9489\u9489 App \u5B8C\u6210\u673A\u5668\u4EBA\u6388\u6743":"Authorize the bot with the DingTalk app","\u4F7F\u7528\u5DF2\u52A0\u5165\u4F01\u4E1A/\u7EC4\u7EC7\u7684\u9489\u9489\u8D26\u53F7\u626B\u63CF\u5DE6\u4FA7\u4E8C\u7EF4\u7801":"Scan the QR code with a DingTalk account that belongs to an organization","\u5728\u6388\u6743\u9875\u70B9\u51FB\u201C\u4E00\u952E\u521B\u5EFA\u65B0\u673A\u5668\u4EBA\u201D":"Select \u201CCreate new bot\u201D on the authorization page","\u8BF7\u52FF\u5173\u95ED\u672C\u9875\uFF0C\u9489\u9489\u5B8C\u6210\u6388\u6743\u540E\u5C06\u81EA\u52A8\u7EE7\u7EED\u3002":"Keep this page open. Setup will continue after DingTalk authorization.",\u7B49\u5F85\u9489\u9489\u626B\u7801\u6388\u6743:"Waiting for DingTalk authorization","\u6388\u6743\u5DF2\u786E\u8BA4\uFF0C\u6B63\u5728\u521B\u5EFA\u9489\u9489\u673A\u5668\u4EBA":"Authorized. Creating the DingTalk bot",\u6B63\u5728\u786E\u8BA4\u9489\u9489\u6388\u6743:"Confirming DingTalk authorization","\u6B63\u5728\u68C0\u67E5\u9489\u9489 Stream \u957F\u8FDE\u63A5\uFF0C\u6210\u529F\u540E\u4F1A\u81EA\u52A8\u663E\u793A\u4E3A\u5728\u7EBF\u3002":"Checking the DingTalk Stream connection. It will appear online when ready.","\u9489\u9489\u673A\u5668\u4EBA\u5DF2\u63A5\u5165\uFF0C\u53EF\u4EE5\u5F00\u59CB\u53D1\u9001\u6D88\u606F\u3002":"The DingTalk bot is connected and ready for messages.","\u8FD9\u4E2A\u9489\u9489\u673A\u5668\u4EBA\u5DF2\u7ECF\u63A5\u5165\u5E76\u4FDD\u6301\u5728\u7EBF\u3002":"This DingTalk bot is connected and online.","Stream \u957F\u8FDE\u63A5":"Stream persistent connection","\u4F7F\u7528\u4F01\u4E1A\u5FAE\u4FE1 App \u626B\u7801\u521B\u5EFA\u667A\u80FD\u673A\u5668\u4EBA":"Scan with WeCom to create an AI bot","\u4F7F\u7528\u4F01\u4E1A\u5FAE\u4FE1 App \u5B8C\u6210\u667A\u80FD\u673A\u5668\u4EBA\u6388\u6743":"Authorize the AI bot with WeCom","\u6253\u5F00\u4F01\u4E1A\u5FAE\u4FE1 App\uFF0C\u626B\u63CF\u5DE6\u4FA7\u4E8C\u7EF4\u7801":"Open WeCom and scan the QR code",\u5728\u817E\u8BAF\u6388\u6743\u9875\u9762\u786E\u8BA4\u521B\u5EFA\u667A\u80FD\u673A\u5668\u4EBA:"Confirm bot creation on the Tencent authorization page",\u8FD4\u56DE\u8FD9\u91CC\u7B49\u5F85\u8FDE\u63A5\u5B8C\u6210:"Return here and wait for the connection to complete","\u7B49\u5F85\u4F01\u4E1A\u5FAE\u4FE1 App \u626B\u7801":"Waiting for WeCom scan","\u4F01\u4E1A\u5FAE\u4FE1\u5DF2\u6388\u6743\uFF0C\u6B63\u5728\u8FDE\u63A5\u673A\u5668\u4EBA":"Authorized in WeCom. Connecting the bot","\u51ED\u636E\u6B63\u5728\u5199\u5165\u672C\u673A\uFF0C\u5E76\u542F\u52A8\u4F01\u4E1A\u5FAE\u4FE1 WebSocket \u6D88\u606F\u8FDE\u63A5\u3002":"Saving credentials locally and starting the WeCom WebSocket connection.","WebSocket \u957F\u8FDE\u63A5":"WebSocket persistent connection","\u4F7F\u7528\u624B\u673A QQ \u626B\u7801\u521B\u5EFA\u5E76\u7ED1\u5B9A\u673A\u5668\u4EBA":"Scan with mobile QQ to create and connect a bot","\u4F7F\u7528\u624B\u673A QQ \u5B8C\u6210\u673A\u5668\u4EBA\u7ED1\u5B9A":"Complete bot setup with mobile QQ","\u6253\u5F00\u624B\u673A QQ\uFF0C\u626B\u63CF\u5DE6\u4FA7\u4E8C\u7EF4\u7801":"Open mobile QQ and scan the QR code",\u5728\u817E\u8BAF\u6388\u6743\u9875\u9762\u786E\u8BA4\u521B\u5EFA\u6216\u7ED1\u5B9A\u673A\u5668\u4EBA:"Confirm bot creation or connection on the Tencent authorization page","\u7B49\u5F85\u624B\u673A QQ \u626B\u7801":"Waiting for mobile QQ scan","QQ \u5DF2\u6388\u6743\uFF0C\u6B63\u5728\u8FDE\u63A5\u673A\u5668\u4EBA":"Authorized in QQ. Connecting the bot","\u51ED\u636E\u6B63\u5728\u5199\u5165\u672C\u673A\uFF0C\u5E76\u542F\u52A8 QQ WebSocket \u6D88\u606F\u8FDE\u63A5\u3002":"Saving credentials locally and starting the QQ WebSocket connection.","\u4F7F\u7528\u624B\u673A WhatsApp \u626B\u63CF\u4E8C\u7EF4\u7801\u5373\u53EF\u63A5\u5165\u3002":"Scan the QR code with WhatsApp to connect.","\u7528\u624B\u673A WhatsApp \u626B\u63CF\u4E8C\u7EF4\u7801":"Scan with WhatsApp on your phone","\u6253\u5F00 WhatsApp \u2192 \u8BBE\u7F6E \u2192 \u5DF2\u5173\u8054\u8BBE\u5907":"Open WhatsApp \u2192 Settings \u2192 Linked devices","\u70B9\u51FB\u201C\u5173\u8054\u8BBE\u5907\u201D\u5E76\u626B\u63CF\u5DE6\u4FA7\u4E8C\u7EF4\u7801":"Select \u201CLink a device\u201D and scan the QR code","\u7B49\u5F85 WhatsApp \u626B\u7801":"Waiting for WhatsApp scan","\u5DF2\u626B\u7801\uFF0C\u6B63\u5728\u8FDE\u63A5 WhatsApp":"Scanned. Connecting WhatsApp","\u6B63\u5728\u5EFA\u7ACB\u5B89\u5168\u7684\u5173\u8054\u8BBE\u5907\u4F1A\u8BDD\u3002":"Creating a secure linked-device session.","\u5173\u8054\u8BBE\u5907\u6B63\u5728\u63A5\u5165 DeepSeek Harness\u3002":"Linking the device to DeepSeek Harness.","WhatsApp Web \u5173\u8054\u8BBE\u5907\u8FD0\u884C\u6B63\u5E38":"WhatsApp linked device is healthy","\u67E5\u770B WhatsApp \u8BBF\u95EE\u6A21\u5F0F\u8BF4\u660E":"View WhatsApp access mode details","WhatsApp \u8BBF\u95EE\u6A21\u5F0F":"WhatsApp access mode",\u4EC5\u81EA\u5DF1\u6A21\u5F0F:"Only me",\u6307\u5B9A\u8054\u7CFB\u4EBA\u6A21\u5F0F:"Selected contacts",\u5F00\u653E\u54CD\u5E94\u6A21\u5F0F:"Open responses","\u4EC5\u81EA\u5DF1\u6A21\u5F0F\uFF08\u9ED8\u8BA4\uFF09":"Only me (default)","\u5DF2\u751F\u6548\uFF1A":"Active: ","\u53EA\u54CD\u5E94\u5DF2\u7ED1\u5B9A WhatsApp \u8D26\u53F7\u7684\u81EA\u804A\u6D88\u606F\u3002":"Only respond to self-chat messages from the linked WhatsApp account.","\u54CD\u5E94\u81EA\u804A\u548C\u767D\u540D\u5355\u8054\u7CFB\u4EBA\u7684\u79C1\u804A\uFF0C\u5FFD\u7565\u7FA4\u804A\u3002":"Respond to self-chat and allowlisted direct messages; ignore group messages.","\u54CD\u5E94\u6240\u6709\u79C1\u804A\uFF0C\u4EE5\u53CA\u7FA4\u804A\u4E2D\u7684\u63D0\u53CA\u6216\u56DE\u590D\u3002":"Respond to all direct messages and to group mentions or replies.","\u5141\u8BB8\u79C1\u804A\u7684 WhatsApp \u7535\u8BDD\u53F7\u7801":"WhatsApp phone numbers allowed to send direct messages",\u6BCF\u884C\u4E00\u4E2A\u542B\u56FD\u5BB6\u6216\u5730\u533A\u4EE3\u7801\u7684\u53F7\u7801:"One number with country or region code per line","\u53EF\u4EE5\u5305\u542B\u5F00\u5934\u7684 +\uFF0C\u4FDD\u5B58\u65F6\u4F1A\u81EA\u52A8\u79FB\u9664\u3002":"A leading + is allowed and removed when saved.","\u4EC5\u6307\u5B9A\u8054\u7CFB\u4EBA\u6A21\u5F0F\u4F7F\u7528\u767D\u540D\u5355\uFF0C\u5207\u6362\u6A21\u5F0F\u65F6\u4F1A\u4FDD\u7559\u3002":"Only Selected contacts uses the allowlist; it is retained when modes change.","\u767D\u540D\u5355\u4E3A\u7A7A\uFF1B\u4FDD\u5B58\u540E\u5C06\u53EA\u63A5\u53D7\u81EA\u804A\u6D88\u606F\u3002":"The allowlist is empty; only self-chat messages will be accepted after saving.","\u7535\u8BDD\u53F7\u7801\u5FC5\u987B\u5305\u542B\u56FD\u5BB6\u6216\u5730\u533A\u4EE3\u7801\uFF0C\u6BCF\u884C\u4E00\u4E2A\u3002":"Each phone number must include a country or region code on its own line.","WhatsApp \u8BBF\u95EE\u8BBE\u7F6E\u6682\u4E0D\u53EF\u7528\u3002":"WhatsApp access settings are currently unavailable.","WhatsApp \u8BBF\u95EE\u8BBE\u7F6E\u4FDD\u5B58\u5931\u8D25\u3002":"Could not save WhatsApp access settings.","Bot API \u957F\u8F6E\u8BE2":"Bot API long polling"," Gateway \u957F\u8FDE\u63A5":" Gateway persistent connection","Gateway \u957F\u8FDE\u63A5":"Gateway persistent connection"," Socket Mode \u957F\u8FDE\u63A5":" Socket Mode persistent connection","Socket Mode \u957F\u8FDE\u63A5":"Socket Mode persistent connection","\u63A5\u5165 Telegram \u673A\u5668\u4EBA":"Connect a Telegram bot","\u5148\u901A\u8FC7 @BotFather \u83B7\u53D6 Bot Token\uFF0C\u518D\u5728\u8FD9\u91CC\u5B8C\u6210\u63A5\u5165\u3002":"Get a Bot Token from @BotFather, then connect it here.","\u586B\u5199 @BotFather \u751F\u6210\u7684 Bot Token":"Enter the Bot Token from @BotFather",\u8BBF\u95EE\u6A21\u5F0F:"Access mode",\u8BBF\u95EE\u8BBE\u7F6E:"Access settings","Telegram \u8BBF\u95EE\u6A21\u5F0F":"Telegram access mode","\u67E5\u770B Telegram \u8BBF\u95EE\u6A21\u5F0F\u8BF4\u660E":"View Telegram access mode details","\u7FA4\u804A\u5168\u90E8\u5FFD\u7565\uFF0C\u79C1\u804A\u4EC5\u5141\u8BB8\u767D\u540D\u5355\u7528\u6237\u3002":"All group messages are ignored; only allowlisted users may send DMs.","\u4FDD\u6301\u539F\u6709\u884C\u4E3A\uFF1A\u79C1\u804A\u76F4\u63A5\u54CD\u5E94\uFF0C\u7FA4\u804A\u5728\u88AB\u63D0\u53CA\u6216\u56DE\u590D\u65F6\u54CD\u5E94\u3002":"Keep the original behavior: respond to DMs and to group mentions or replies.",\u5B89\u5168\u6A21\u5F0F:"Safe mode",\u517C\u5BB9\u6A21\u5F0F:"Compatible mode","\u5DF2\u751F\u6548\uFF1A\u5B89\u5168\u6A21\u5F0F":"Active: Safe mode","\u5DF2\u751F\u6548\uFF1A\u517C\u5BB9\u6A21\u5F0F":"Active: Compatible mode",\u6A21\u5F0F:"Mode","\u517C\u5BB9\u6A21\u5F0F\uFF08\u9ED8\u8BA4\uFF09":"Compatible mode (default)","\u5B89\u5168\u6A21\u5F0F\uFF08\u79C1\u804A\u767D\u540D\u5355\uFF09":"Safe mode (private-chat allowlist)","\u5141\u8BB8\u79C1\u804A\u7684 Telegram User ID":"Telegram User IDs allowed to send DMs","\u6BCF\u884C\u4E00\u4E2A\u6570\u5B57 User ID":"One numeric User ID per line","\u767D\u540D\u5355\u4EC5\u5C5E\u4E8E\u5F53\u524D\u673A\u5668\u4EBA\u3002":"This allowlist belongs only to the current bot.","\u517C\u5BB9\u6A21\u5F0F\u4E0B\u6682\u4E0D\u4F7F\u7528\u767D\u540D\u5355\uFF0C\u5207\u6362\u6A21\u5F0F\u65F6\u4F1A\u4FDD\u7559\u3002":"Compatible mode does not enforce the allowlist; it is retained when modes change.","\u767D\u540D\u5355\u4E3A\u7A7A\uFF1B\u4FDD\u5B58\u540E\u8BE5\u673A\u5668\u4EBA\u4F1A\u62D2\u7EDD\u6240\u6709\u5165\u7AD9\u6D88\u606F\u3002":"The allowlist is empty; this bot will reject all inbound messages after saving.","\u6B63\u5728\u4FDD\u5B58\u2026":"Saving\u2026",\u4FDD\u5B58\u8BBF\u95EE\u8BBE\u7F6E:"Save access settings","User ID \u5FC5\u987B\u662F 1\u201316 \u4F4D\u6B63\u6574\u6570\uFF0C\u6BCF\u884C\u4E00\u4E2A\u3002":"Each User ID must be a 1\u201316 digit positive integer on its own line.","Telegram \u8BBF\u95EE\u8BBE\u7F6E\u6682\u4E0D\u53EF\u7528\u3002":"Telegram access settings are currently unavailable.","Telegram \u8BBF\u95EE\u8BBE\u7F6E\u4FDD\u5B58\u5931\u8D25\u3002":"Could not save Telegram access settings.","\u63A5\u5165 Discord \u673A\u5668\u4EBA":"Connect a Discord bot","\u5148\u5728 Developer Portal \u521B\u5EFA Bot \u5E76\u9080\u8BF7\u5230\u670D\u52A1\u5668\uFF0C\u518D\u5728\u8FD9\u91CC\u5B8C\u6210\u63A5\u5165\u3002":"Create a bot in the Developer Portal and invite it to your server, then connect it here.","\u586B\u5199 Discord Developer Portal \u7684 Bot Token":"Enter the Bot Token from the Discord Developer Portal","\u63A5\u5165 Slack \u673A\u5668\u4EBA":"Connect a Slack bot","\u5148\u7528 Manifest \u521B\u5EFA\u5E76\u914D\u7F6E Slack App":"Create and configure a Slack app with the manifest","\u590D\u5236\u914D\u7F6E\u540E\uFF0C\u5728 Slack \u9009\u62E9 From a manifest\uFF1B\u521B\u5EFA\u5B8C\u6210\u540E\u751F\u6210 connections:write App Token\uFF0C\u5E76\u5C06\u5E94\u7528\u5B89\u88C5\u5230\u5DE5\u4F5C\u533A\u3002":"Copy the manifest and choose \u201CFrom a manifest\u201D in Slack. Then create a connections:write App Token and install the app to your workspace.","\u590D\u5236 Manifest":"Copy manifest","\u5DF2\u590D\u5236 Manifest":"Manifest copied","\u6253\u5F00 Slack \u521B\u5EFA\u9875":"Open Slack app creation","Bot Token \u6765\u81EA OAuth & Permissions\uFF1BApp Token \u6765\u81EA Basic Information\uFF0C\u5E76\u4E14\u5FC5\u987B\u5305\u542B connections:write\u3002":"Get the Bot Token from OAuth & Permissions and the App Token from Basic Information. The App Token must include connections:write.","\u4F7F\u7528\u5B98\u65B9 App Manifest \u5FEB\u901F\u914D\u7F6E\u673A\u5668\u4EBA\uFF0C\u518D\u586B\u5199 Bot Token \u4E0E App Token \u5EFA\u7ACB\u672C\u5730 Socket Mode \u8FDE\u63A5\u3002":"Configure the bot with the official app manifest, then enter the Bot Token and App Token to start a local Socket Mode connection.","Slack \u5DE5\u4F5C\u533A":"Slack workspace","Bot Token \u4E0E App Token":"Bot Token and App Token","\u586B\u5199 Bot Token":"Enter Bot Token",\u624B\u52A8\u63A5\u5165\u98DE\u4E66\u673A\u5668\u4EBA:"Connect Feishu bot manually",\u624B\u52A8\u63A5\u5165\u9489\u9489\u673A\u5668\u4EBA:"Connect DingTalk bot manually",\u624B\u52A8\u63A5\u5165\u4F01\u4E1A\u5FAE\u4FE1\u673A\u5668\u4EBA:"Connect WeCom bot manually",\u624B\u52A8\u63A5\u5165QQ\u673A\u5668\u4EBA:"Connect QQ bot manually","\u586B\u5199\u98DE\u4E66\u5F00\u653E\u5E73\u53F0 App ID":"Enter the Feishu Open Platform App ID","\u586B\u5199\u98DE\u4E66\u5F00\u653E\u5E73\u53F0 App Secret":"Enter the Feishu Open Platform App Secret","\u586B\u5199\u9489\u9489\u5E94\u7528 Client ID":"Enter the DingTalk Client ID","\u586B\u5199\u9489\u9489\u5E94\u7528 Client Secret":"Enter the DingTalk Client Secret","\u586B\u5199\u4F01\u4E1A\u5FAE\u4FE1\u667A\u80FD\u673A\u5668\u4EBA Bot ID":"Enter the WeCom AI Bot ID","\u586B\u5199\u4F01\u4E1A\u5FAE\u4FE1\u667A\u80FD\u673A\u5668\u4EBA Secret":"Enter the WeCom AI Bot Secret","\u586B\u5199 QQ \u5F00\u653E\u5E73\u53F0 AppID":"Enter the QQ Open Platform AppID","\u586B\u5199 QQ \u5F00\u653E\u5E73\u53F0 AppSecret":"Enter the QQ Open Platform AppSecret",\u626B\u7801\u63A5\u5165\u5FAE\u4FE1\u673A\u5668\u4EBA:"Connect WeChat bot by QR code",\u626B\u7801\u63A5\u5165\u98DE\u4E66\u673A\u5668\u4EBA:"Connect Feishu bot by QR code",\u626B\u7801\u63A5\u5165\u9489\u9489\u673A\u5668\u4EBA:"Connect DingTalk bot by QR code",\u626B\u7801\u63A5\u5165\u4F01\u4E1A\u5FAE\u4FE1\u673A\u5668\u4EBA:"Connect WeCom bot by QR code","\u626B\u7801\u63A5\u5165 QQ \u673A\u5668\u4EBA":"Connect QQ bot by QR code","\u626B\u7801\u63A5\u5165 WhatsApp \u673A\u5668\u4EBA":"Connect WhatsApp by QR code","\u626B\u7801\u7ED1\u5B9A WhatsApp \u673A\u5668\u4EBA":"Connect WhatsApp by QR code","\u4F7F\u7528 App ID \u548C App Secret \u7ED1\u5B9A\u98DE\u4E66\u673A\u5668\u4EBA":"Connect a Feishu bot with App ID and App Secret","\u4F7F\u7528 Client ID \u548C Client Secret \u7ED1\u5B9A\u9489\u9489\u673A\u5668\u4EBA":"Connect a DingTalk bot with Client ID and Client Secret","\u4F7F\u7528 Bot ID \u548C Secret \u7ED1\u5B9A\u4F01\u4E1A\u5FAE\u4FE1\u673A\u5668\u4EBA":"Connect a WeCom bot with Bot ID and Secret","\u4F7F\u7528 AppID \u548C AppSecret \u7ED1\u5B9A QQ \u673A\u5668\u4EBA":"Connect a QQ bot with AppID and AppSecret","\u4F7F\u7528 Manifest \u548C\u53CC Token \u63A5\u5165 Slack \u673A\u5668\u4EBA":"Connect a Slack bot with a manifest and two tokens","\u4F7F\u7528 Bot Token \u63A5\u5165 Telegram \u673A\u5668\u4EBA":"Connect a Telegram bot with a Bot Token","\u4F7F\u7528 Bot Token \u63A5\u5165 Discord \u673A\u5668\u4EBA":"Connect a Discord bot with a Bot Token",\u53D6\u6D88\u7ED1\u5B9A:"Cancel setup",\u53D6\u6D88\u63A5\u5165:"Cancel setup","\u4E8C\u7EF4\u7801\u7531\u817E\u8BAF\u5FAE\u4FE1 iLink \u670D\u52A1\u7B7E\u53D1\u3002\u7528\u624B\u673A\u5FAE\u4FE1\u626B\u63CF\u5E76\u786E\u8BA4\u540E\uFF0C\u8D26\u53F7\u51ED\u636E\u4F1A\u76F4\u63A5\u5199\u5165 Harness Host\uFF0C\u6D4F\u89C8\u5668\u4E0D\u4F1A\u6536\u5230 bot_token\u3002":"The QR code is issued by Tencent WeChat iLink. After you scan and confirm, account credentials are written directly to the Harness Host and are never exposed to the browser.","\u626B\u7801\u8D26\u53F7\u5FC5\u987B\u5DF2\u52A0\u5165\u4F01\u4E1A/\u7EC4\u7EC7\u3002\u5982\u679C\u9489\u9489\u63D0\u793A\u5C1A\u672A\u52A0\u5165\u7EC4\u7EC7\uFF0C\u8BF7\u5728\u63D0\u793A\u9875\u521B\u5EFA\u7EC4\u7EC7\uFF0C\u6216\u6362\u7528\u5DF2\u52A0\u5165\u7EC4\u7EC7\u7684\u8D26\u53F7\u3002":"The DingTalk account must belong to an organization. If prompted, create an organization or use an account that already belongs to one.","\u8BF7\u5728\u624B\u673A\u4E0A\u6838\u5BF9\u5E76\u786E\u8BA4\u6388\u6743\u3002\u90E8\u5206\u8D26\u53F7\u4F1A\u989D\u5916\u663E\u793A\u4E00\u4E2A\u914D\u5BF9\u6570\u5B57\uFF0C\u9875\u9762\u4F1A\u5728\u9700\u8981\u65F6\u63D0\u793A\u8F93\u5165\u3002":"Review and confirm authorization on your phone. Some accounts may also require a pairing number.","\u6388\u6743\u7531\u9489\u9489\u5B98\u65B9\u9875\u9762\u5B8C\u6210\u3002\u626B\u7801\u8D26\u53F7\u5FC5\u987B\u5DF2\u52A0\u5165\u4E00\u4E2A\u4F01\u4E1A/\u7EC4\u7EC7\u5E76\u6709\u6743\u521B\u5EFA\u673A\u5668\u4EBA\uFF1B\u521B\u5EFA\u6210\u529F\u540E\uFF0C\u5E94\u7528\u51ED\u636E\u4F1A\u76F4\u63A5\u5199\u5165 Harness Host\u3002":"Authorization is completed on DingTalk\u2019s official page. The account must belong to an organization and be allowed to create bots. Credentials are written directly to the Harness Host.","\u626B\u7801\u7531\u817E\u8BAF\u5B98\u65B9\u9875\u9762\u5B8C\u6210\uFF0C\u4E0D\u9700\u8981\u624B\u52A8\u586B\u5199 AppID \u6216 AppSecret\u3002\u626B\u7801\u6210\u529F\u540E\uFF0C\u673A\u5668\u4EBA\u4F1A\u81EA\u52A8\u8FDE\u63A5 DeepSeek Harness\u3002":"Scanning is completed on Tencent\u2019s official page. No AppID or AppSecret is required, and the bot connects automatically.","\u626B\u7801\u7531\u817E\u8BAF\u5B98\u65B9\u9875\u9762\u5B8C\u6210\uFF0C\u4E0D\u9700\u8981\u624B\u52A8\u586B\u5199 Bot ID \u6216 Secret\u3002\u521B\u5EFA\u6210\u529F\u540E\uFF0C\u673A\u5668\u4EBA\u4F1A\u81EA\u52A8\u8FDE\u63A5 DeepSeek Harness\u3002":"Scanning is completed on Tencent\u2019s official page. No Bot ID or Secret is required, and the bot connects automatically.","\u817E\u8BAF\u9875\u9762\u4F1A\u521B\u5EFA\u6216\u7ED1\u5B9A\u4E00\u4E2A QQ \u673A\u5668\u4EBA\uFF0C\u5E76\u628A\u8FDE\u63A5\u51ED\u636E\u5B89\u5168\u4EA4\u7ED9\u672C\u673A Harness Host\u3002":"Tencent will create or connect a QQ bot and securely deliver its credentials to the local Harness Host.","\u4F01\u4E1A\u5FAE\u4FE1\u5B98\u65B9\u9875\u9762\u4F1A\u521B\u5EFA\u4E00\u4E2A\u667A\u80FD\u673A\u5668\u4EBA\uFF0C\u5E76\u628A\u8FDE\u63A5\u51ED\u636E\u5B89\u5168\u4EA4\u7ED9\u672C\u673A Harness Host\u3002":"WeCom will create an AI bot and securely deliver its credentials to the local Harness Host.","\u4ECE\u6B64 Harness \u79FB\u9664\u8FD9\u4E2A\u5FAE\u4FE1\u8D26\u53F7\uFF1F":"Remove this WeChat account from Harness?","\u8FD9\u4F1A\u505C\u6B62\u6D88\u606F\u8FDE\u63A5\uFF0C\u5E76\u5220\u9664\u672C\u673A\u4FDD\u5B58\u7684 bot_token\u3001\u8D26\u53F7\u914D\u7F6E\u548C\u4F1A\u8BDD\u6620\u5C04\u3002\u5176\u4ED6\u5FAE\u4FE1\u8D26\u53F7\u4E0D\u53D7\u5F71\u54CD\u3002":"This stops the message connection and removes the locally stored bot_token, account configuration, and session mappings. Other WeChat accounts are not affected.","\u6B64\u64CD\u4F5C\u4F1A\u505C\u6B62\u8FD9\u4E2A\u673A\u5668\u4EBA\u7684\u8FDE\u63A5\uFF0C\u5E76\u5220\u9664\u4FDD\u5B58\u5728\u672C\u673A\u7684\u63A5\u5165\u914D\u7F6E\u548C\u51ED\u636E\u3002\u98DE\u4E66\u5F00\u653E\u5E73\u53F0\u4E2D\u7684\u5E94\u7528\u4E0D\u4F1A\u88AB\u81EA\u52A8\u5220\u9664\uFF0C\u5176\u4ED6\u673A\u5668\u4EBA\u4E5F\u4E0D\u53D7\u5F71\u54CD\u3002":"This stops the bot connection and removes the locally stored configuration and credentials. The app in Feishu Open Platform is not deleted, and other bots are not affected.","\u8FD9\u4F1A\u505C\u6B62\u6D88\u606F\u8FDE\u63A5\uFF0C\u5E76\u5220\u9664\u672C\u673A\u4FDD\u5B58\u7684\u5E94\u7528\u51ED\u636E\u3001\u673A\u5668\u4EBA\u914D\u7F6E\u53CA\u4F1A\u8BDD\u6620\u5C04\u3002\u9489\u9489\u5F00\u653E\u5E73\u53F0\u4E2D\u7684\u673A\u5668\u4EBA\u4E0D\u4F1A\u88AB\u81EA\u52A8\u5220\u9664\u3002":"This stops the message connection and removes the locally stored app credentials, bot configuration, and session mappings. The bot in DingTalk Open Platform is not deleted.","\u8FD9\u4F1A\u505C\u6B62\u6D88\u606F\u8FDE\u63A5\uFF0C\u5E76\u5220\u9664\u672C\u673A\u4FDD\u5B58\u7684\u5E94\u7528\u51ED\u636E\u3001\u673A\u5668\u4EBA\u914D\u7F6E\u53CA\u4F1A\u8BDD\u6620\u5C04\u3002\u4F01\u4E1A\u5FAE\u4FE1\u5E73\u53F0\u4E2D\u7684\u673A\u5668\u4EBA\u4E0D\u4F1A\u88AB\u81EA\u52A8\u5220\u9664\u3002":"This stops the message connection and removes the locally stored app credentials, bot configuration, and session mappings. The bot in WeCom is not deleted.","\u8FD9\u4F1A\u505C\u6B62\u6D88\u606F\u8FDE\u63A5\uFF0C\u5E76\u5220\u9664\u672C\u673A\u4FDD\u5B58\u7684\u5E94\u7528\u51ED\u636E\u3001\u673A\u5668\u4EBA\u914D\u7F6E\u53CA\u4F1A\u8BDD\u6620\u5C04\u3002\u817E\u8BAF\u5E73\u53F0\u4E2D\u7684\u673A\u5668\u4EBA\u4E0D\u4F1A\u88AB\u81EA\u52A8\u5220\u9664\u3002":"This stops the message connection and removes the locally stored app credentials, bot configuration, and session mappings. The bot on Tencent\u2019s platform is not deleted.","\u8FD9\u4F1A\u505C\u6B62\u6D88\u606F\u8FDE\u63A5\uFF0C\u5E76\u5220\u9664\u672C\u673A\u4FDD\u5B58\u7684 WhatsApp \u5173\u8054\u8BBE\u5907\u548C\u4F1A\u8BDD\u6620\u5C04\u3002":"This stops the message connection and removes the locally stored WhatsApp linked device and session mappings.",\u6B63\u5728\u8BFB\u53D6\u98DE\u4E66\u673A\u5668\u4EBA\u5217\u8868:"Loading Feishu bots","\u6B63\u5728\u8BFB\u53D6\u98DE\u4E66\u8FDE\u63A5\u72B6\u6001\u2026":"Loading Feishu connection status\u2026","\u6B63\u5728\u8BFB\u53D6\u5FAE\u4FE1\u8FDE\u63A5\u72B6\u6001\u2026":"Loading WeChat connection status\u2026","\u6B63\u5728\u8BFB\u53D6\u9489\u9489\u8FDE\u63A5\u72B6\u6001\u2026":"Loading DingTalk connection status\u2026","\u901A\u8FC7\u626B\u7801\u628A\u9489\u9489\u673A\u5668\u4EBA\u63A5\u5165 DeepSeek Harness":"Connect a DingTalk bot to DeepSeek Harness by QR code",\u9489\u9489\u670D\u52A1\u6CA1\u6709\u8FD4\u56DE\u626B\u7801\u7ED1\u5B9A\u8FDB\u5EA6:"DingTalk did not return QR setup progress",\u9489\u9489\u626B\u7801\u670D\u52A1\u6CA1\u6709\u8FD4\u56DE\u6709\u6548\u7684\u7ED1\u5B9A\u4EFB\u52A1:"DingTalk did not return a valid setup attempt","\u9489\u9489 Stream \u957F\u8FDE\u63A5\u8FD0\u884C\u6B63\u5E38":"DingTalk Stream connection is healthy",\u9489\u9489\u670D\u52A1\u6CA1\u6709\u8FD4\u56DE\u6709\u6548\u7684\u673A\u5668\u4EBA\u5217\u8868:"DingTalk did not return a valid bot list","${totals.connected} / ${totals.configured} \u5728\u7EBF":"${totals.connected} / ${totals.configured} online","\u7528\u4E8E\u628A\u9489\u9489\u673A\u5668\u4EBA\u63A5\u5165 DeepSeek Harness \u7684\u4E00\u6B21\u6027\u4E8C\u7EF4\u7801":"One-time QR code for connecting a DingTalk bot to DeepSeek Harness","\u4E8C\u7EF4\u7801\u5DF2\u8FC7\u671F\\n\u8BF7\u91CD\u65B0\u751F\u6210":"QR code expired\\nGenerate a new one","\u673A\u5668\u4EBA\u5DF2\u521B\u5EFA\uFF0C\u6B63\u5728\u5EFA\u7ACB\u6D88\u606F\u8FDE\u63A5":"Bot created. Starting the message connection",\u9489\u9489\u626B\u7801\u670D\u52A1\u6CA1\u6709\u8FD4\u56DE\u5B89\u5168\u7684\u4E8C\u7EF4\u7801:"DingTalk did not return a secure QR code","\u9489\u9489\u4E8C\u7EF4\u7801\u5DF2\u751F\u6210\uFF0C\u8BF7\u4F7F\u7528\u9489\u9489 App \u626B\u63CF\u3002":"DingTalk QR code generated. Scan it with the DingTalk app.","\u9489\u9489\u673A\u5668\u4EBA\u51ED\u636E\u5DF2\u7ED1\u5B9A\u3002":"DingTalk bot credentials connected.","\u5DF2\u53D6\u6D88\u9489\u9489\u673A\u5668\u4EBA\u63A5\u5165\u3002":"DingTalk bot setup cancelled.","\u9489\u9489\u673A\u5668\u4EBA\u53CA\u672C\u673A\u51ED\u636E\u5DF2\u79FB\u9664\u3002":"DingTalk bot and local credentials removed.",\u98DE\u4E66\u670D\u52A1\u6CA1\u6709\u8FD4\u56DE\u4E8C\u7EF4\u7801\u4FE1\u606F:"Feishu did not return QR code information",\u98DE\u4E66\u670D\u52A1\u8FD4\u56DE\u7684\u4E8C\u7EF4\u7801\u4FE1\u606F\u4E0D\u5B8C\u6574:"Feishu returned incomplete QR code information",\u98DE\u4E66\u670D\u52A1\u8FD4\u56DE\u4E86\u65E0\u6548\u7684\u673A\u5668\u4EBA\u72B6\u6001:"Feishu returned an invalid bot status","\u98DE\u4E66\u670D\u52A1\u8FD4\u56DE\u7684\u673A\u5668\u4EBA\u7F3A\u5C11 botId":"The Feishu bot is missing botId",\u98DE\u4E66\u670D\u52A1\u6CA1\u6709\u8FD4\u56DE\u8FDE\u63A5\u72B6\u6001:"Feishu did not return connection status",\u98DE\u4E66\u670D\u52A1\u6CA1\u6709\u8FD4\u56DE\u521B\u5EFA\u8FDB\u5EA6:"Feishu did not return creation progress",\u98DE\u4E66\u670D\u52A1\u8FD4\u56DE\u4E86\u672A\u77E5\u7684\u521B\u5EFA\u72B6\u6001:"Feishu returned an unknown creation status","\u5DF2\u63A5\u5165 ${totals.configured} \u4E2A\u673A\u5668\u4EBA\uFF0C\u5176\u4E2D ${totals.connected} \u4E2A\u5728\u7EBF":"${totals.connected} of ${totals.configured} bots online",\u5C1A\u672A\u63A5\u5165\u673A\u5668\u4EBA:"No bot connected yet","\u7528\u4E8E\u65B0\u589E DeepSeek Harness \u98DE\u4E66\u673A\u5668\u4EBA\u7684\u4E00\u6B21\u6027\u6388\u6743\u4E8C\u7EF4\u7801":"One-time authorization QR code for adding a Feishu bot to DeepSeek Harness",\u8BF7\u5237\u65B0\u540E\u91CD\u65B0\u626B\u7801:"Refresh and scan again",'${connected ? "\u68C0\u67E5\u8FDE\u63A5" : "\u91CD\u8BD5\u8FDE\u63A5"}${bot.name}':'${connected ? "Check connection" : "Reconnect"} ${bot.name}',\u65E0\u6CD5\u8BFB\u53D6\u98DE\u4E66\u673A\u5668\u4EBA:"Could not load Feishu bots","\u6388\u6743\u4E8C\u7EF4\u7801\u5DF2\u751F\u6210\uFF0C\u8BF7\u4F7F\u7528\u98DE\u4E66\u626B\u7801\u3002":"Authorization QR code generated. Scan it with Feishu.","\u98DE\u4E66\u673A\u5668\u4EBA\u51ED\u636E\u5DF2\u7ED1\u5B9A\u3002":"Feishu bot credentials connected.","\u5DF2\u53D6\u6D88\u6DFB\u52A0\u673A\u5668\u4EBA\u3002":"Adding the bot was cancelled.","${newBot.bot.name}\u5DF2\u8FDE\u63A5\uFF0C\u53EF\u4EE5\u5728\u98DE\u4E66\u4E2D\u5F00\u59CB\u804A\u5929\u3002":"${newBot.bot.name} is connected and ready to chat in Feishu.","${bot.name}\u64CD\u4F5C\u5931\u8D25\uFF0C\u8BF7\u67E5\u770B\u673A\u5668\u4EBA\u72B6\u6001\u3002":"${bot.name} operation failed. Check the bot status.","${bot.name}\u5DF2\u4ECE\u6B64 DeepSeek Harness \u79FB\u9664\uFF1B\u98DE\u4E66\u5F00\u653E\u5E73\u53F0\u4E2D\u7684\u5E94\u7528\u672A\u88AB\u5220\u9664\u3002":"${bot.name} was removed from this DeepSeek Harness. The app in Feishu Open Platform was not deleted.",\u65E0\u6CD5\u8BFB\u53D6\u8FDE\u63A5\u72B6\u6001:"Could not load connection status","QQ \u670D\u52A1\u6CA1\u6709\u8FD4\u56DE\u626B\u7801\u7ED1\u5B9A\u8FDB\u5EA6":"QQ did not return QR setup progress","QQ \u626B\u7801\u670D\u52A1\u6CA1\u6709\u8FD4\u56DE\u6709\u6548\u7684\u7ED1\u5B9A\u4EFB\u52A1":"QQ did not return a valid setup attempt","QQ WebSocket \u957F\u8FDE\u63A5\u8FD0\u884C\u6B63\u5E38":"QQ WebSocket connection is healthy","QQ \u670D\u52A1\u6CA1\u6709\u8FD4\u56DE\u6709\u6548\u7684\u673A\u5668\u4EBA\u5217\u8868":"QQ did not return a valid bot list","\u5C1A\u672A\u7ED1\u5B9A QQ \u673A\u5668\u4EBA":"No QQ bot connected yet","\u7528\u4E8E\u7ED1\u5B9A QQ \u673A\u5668\u4EBA\u7684\u4E00\u6B21\u6027\u4E8C\u7EF4\u7801":"One-time QR code for connecting a QQ bot","${channel}${connectionSummary}\u8FD0\u884C\u6B63\u5E38":"${channel}${connectionSummary} is healthy","${channel} \u670D\u52A1\u6CA1\u6709\u8FD4\u56DE\u6709\u6548\u7684\u673A\u5668\u4EBA\u5217\u8868":"${channel} did not return a valid bot list","\u4F7F\u7528 Bot Token \u63A5\u5165 ${channel} \u673A\u5668\u4EBA":"Connect a ${channel} bot with a Bot Token","${model.totals.connected} / ${model.totals.configured} \u5728\u7EBF":"${model.totals.connected}/${model.totals.configured} online"," Bot API \u957F\u8F6E\u8BE2":" Bot API long polling",\u4F01\u4E1A\u5FAE\u4FE1\u670D\u52A1\u6CA1\u6709\u8FD4\u56DE\u626B\u7801\u7ED1\u5B9A\u8FDB\u5EA6:"WeCom did not return QR setup progress",\u4F01\u4E1A\u5FAE\u4FE1\u626B\u7801\u670D\u52A1\u6CA1\u6709\u8FD4\u56DE\u6709\u6548\u7684\u7ED1\u5B9A\u4EFB\u52A1:"WeCom did not return a valid setup attempt","\u4F01\u4E1A\u5FAE\u4FE1 WebSocket \u957F\u8FDE\u63A5\u8FD0\u884C\u6B63\u5E38":"WeCom WebSocket connection is healthy",\u4F01\u4E1A\u5FAE\u4FE1\u670D\u52A1\u6CA1\u6709\u8FD4\u56DE\u6709\u6548\u7684\u673A\u5668\u4EBA\u5217\u8868:"WeCom did not return a valid bot list",\u5C1A\u672A\u7ED1\u5B9A\u4F01\u4E1A\u5FAE\u4FE1\u673A\u5668\u4EBA:"No WeCom bot connected yet",\u7528\u4E8E\u7ED1\u5B9A\u4F01\u4E1A\u5FAE\u4FE1\u673A\u5668\u4EBA\u7684\u4E00\u6B21\u6027\u4E8C\u7EF4\u7801:"One-time QR code for connecting a WeCom bot",\u5FAE\u4FE1\u626B\u7801\u670D\u52A1\u6CA1\u6709\u8FD4\u56DE\u6709\u6548\u7684\u7ED1\u5B9A\u4EFB\u52A1:"WeChat did not return a valid setup attempt",\u5FAE\u4FE1\u7ED1\u5B9A\u6CA1\u6709\u5B8C\u6210:"WeChat setup did not complete",\u5FAE\u4FE1\u8FDE\u63A5\u6B63\u5E38:"WeChat connection is healthy",\u5FAE\u4FE1\u8FDE\u63A5\u672A\u5C31\u7EEA:"WeChat connection is not ready","\u5F53\u524D\u6A21\u578B\u4E0D\u652F\u6301\u56FE\u7247\uFF0C\u8BF7\u7528 /models \u67E5\u770B\u53EF\u7528\u6A21\u578B\uFF0C\u518D\u7528 /model <\u5E8F\u53F7> \u5207\u6362\u540E\u91CD\u53D1\u3002":"The current model does not support images. Use /models to list models, then /model to switch and resend.","\u56FE\u7247\u8D85\u8FC7\u5BBF\u4E3B\u5141\u8BB8\u7684\u5927\u5C0F\uFF0C\u8BF7\u538B\u7F29\u540E\u91CD\u8BD5\u3002":"The image exceeds the Host size limit. Compress it and try again.","\u56FE\u7247\u5206\u8FA8\u7387\u8FC7\u9AD8\uFF0C\u8BF7\u538B\u7F29\u540E\u91CD\u8BD5\u3002":"The image resolution is too high. Compress it and try again.","\u56FE\u7247\u5185\u5BB9\u65E0\u6548\u6216\u683C\u5F0F\u4E0D\u53D7\u652F\u6301\uFF0C\u8BF7\u91CD\u65B0\u53D1\u9001\u3002":"The image is invalid or unsupported. Send it again.","\u672A\u80FD\u8BFB\u53D6\u56FE\u7247\u5185\u5BB9\uFF0C\u8BF7\u91CD\u65B0\u53D1\u9001\u3002":"The image could not be read. Send it again.","\u56FE\u7247\u683C\u5F0F\u4E0E\u5B9E\u9645\u5185\u5BB9\u4E0D\u4E00\u81F4\uFF0C\u8BF7\u91CD\u65B0\u53D1\u9001\u3002":"The declared image format does not match its content. Send it again.","\u4E00\u6B21\u53D1\u9001\u7684\u56FE\u7247\u6570\u91CF\u8D85\u8FC7\u5BBF\u4E3B\u9650\u5236\uFF0C\u8BF7\u51CF\u5C11\u540E\u91CD\u8BD5\u3002":"The message exceeds the Host image-count limit. Remove some images and try again.","\u56FE\u7247\u603B\u5927\u5C0F\u8D85\u8FC7\u5BBF\u4E3B\u9650\u5236\uFF0C\u8BF7\u51CF\u5C11\u56FE\u7247\u6216\u538B\u7F29\u540E\u91CD\u8BD5\u3002":"The images exceed the Host total-size limit. Remove or compress some images and try again.","\u56FE\u7247\u4E0B\u8F7D\u5730\u5740\u53D1\u751F\u4E86\u91CD\u5B9A\u5411\uFF0C\u6682\u65F6\u65E0\u6CD5\u8BFB\u53D6\u3002":"The image download redirected and cannot be read.","\u56FE\u7247\u8D85\u8FC7 5 MB\uFF0C\u8BF7\u538B\u7F29\u540E\u91CD\u8BD5\u3002":"The image exceeds 5 MB. Compress it and try again.","\u4E00\u6B21\u53D1\u9001\u7684\u56FE\u7247\u603B\u5927\u5C0F\u8FC7\u5927\uFF0C\u8BF7\u51CF\u5C11\u56FE\u7247\u6570\u91CF\u6216\u538B\u7F29\u540E\u91CD\u8BD5\u3002":"The images are too large in total. Remove or compress some images and try again.","\u56FE\u7247\u4E0B\u8F7D\u5931\u8D25\uFF0C\u8BF7\u91CD\u65B0\u53D1\u9001\u540E\u518D\u8BD5\u3002":"The image download failed. Send it again.","\u6682\u4E0D\u652F\u6301\u8BE5\u56FE\u7247\u683C\u5F0F\uFF0C\u8BF7\u53D1\u9001 JPEG\u3001PNG\u3001WebP \u6216 GIF \u56FE\u7247\u3002":"This image format is unsupported. Send a JPEG, PNG, WebP, or GIF image.","\u6D88\u606F\u5904\u7406\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002":"Message processing failed. Try again later.",\u5FAE\u4FE1\u670D\u52A1\u6CA1\u6709\u8FD4\u56DE\u6709\u6548\u7684\u8D26\u53F7\u5217\u8868:"WeChat did not return a valid account list",\u5C1A\u672A\u7ED1\u5B9A\u5FAE\u4FE1:"No WeChat account connected yet","\u7528\u4E8E\u628A\u5FAE\u4FE1\u673A\u5668\u4EBA\u7ED1\u5B9A\u5230 DeepSeek Harness \u7684\u4E00\u6B21\u6027\u4E8C\u7EF4\u7801":"One-time QR code for connecting a WeChat bot to DeepSeek Harness","\u4FDD\u6301\u672C\u9875\u6253\u5F00\uFF0C\u7B49\u5F85\u6D88\u606F\u957F\u8F6E\u8BE2\u53D8\u4E3A\u5728\u7EBF":"Keep this page open until long polling is online","\u5FAE\u4FE1\u4E8C\u7EF4\u7801\u5DF2\u751F\u6210\uFF0C\u8BF7\u4F7F\u7528\u624B\u673A\u5FAE\u4FE1\u626B\u63CF\u3002":"WeChat QR code generated. Scan it with WeChat on your phone.","\u79FB\u9664\u5931\u8D25\uFF1A${presentError(error).message}":"Removal failed: ${presentError(error).message}",\u65E0\u6CD5\u8BFB\u53D6\u5FAE\u4FE1\u72B6\u6001:"Could not load WeChat status","WhatsApp \u670D\u52A1\u6CA1\u6709\u8FD4\u56DE\u626B\u7801\u8FDB\u5EA6":"WhatsApp did not return QR setup progress","WhatsApp \u670D\u52A1\u6CA1\u6709\u8FD4\u56DE\u6709\u6548\u7684\u626B\u7801\u4EFB\u52A1":"WhatsApp did not return a valid setup attempt","WhatsApp \u670D\u52A1\u6CA1\u6709\u8FD4\u56DE\u6709\u6548\u7684\u673A\u5668\u4EBA\u5217\u8868":"WhatsApp did not return a valid account list","\u7528\u4E8E\u5173\u8054 WhatsApp \u8BBE\u5907\u7684\u4E00\u6B21\u6027\u4E8C\u7EF4\u7801":"One-time QR code for linking a WhatsApp device"});var waA=Object.freeze(Object.fromEntries(Object.keys(MTe).map(n=>[n,n==="$locale"?"zh":n])));var OaA=Object.freeze(["aria-label","alt","placeholder","title"]);var _Te=Object.freeze({defaultId:"",items:Object.freeze([])}),TaA=vp.createContext(_Te);var Lk="/feishu",Tt=Object.freeze({status:"connection.status",beginProvisioning:"provision.begin",beginCallbackRepair:"bot.callback-repair.begin",beginGroupMessagePermission:"bot.group-message-permission.begin",pollProvisioning:"provision.poll",cancelProvisioning:"provision.cancel",bindCredentials:"bot.bind-credentials",reconnectBot:"bot.reconnect",disconnectBot:"bot.disconnect",deleteBot:"bot.delete",setWorkspace:"bot.workspace.set",setAgentPreset:"bot.preset.set",setGroupResponseMode:"bot.group-response-mode.set",testConnection:"connection.test",disconnect:"connection.disconnect"}),PaA=Object.freeze({PROVISION:"provision",CALLBACK_REPAIR:"callback_repair",GROUP_MESSAGE_PERMISSION:"group_message_permission"});var BI=Object.freeze({reconnectBot:"bot.reconnect",disconnectBot:"bot.disconnect",deleteBot:"bot.delete"}),dV=Object.freeze([...new Set([...Object.values(Tt),...Object.values(BI)])]),NTe=new Set(["idle","starting","qr_ready","polling","slow_down","domain_switched","saving","succeeded","expired","cancelled","error"]),RTe=new Set(["provision","callback_repair","group_message_permission"]),hV="callback_repair",Hk="group_message_permission",im=new Set([hV,Hk]),kTe=new Set(["accounts.feishu.cn","accounts.larksuite.com","open.feishu.cn","open.larksuite.com"]),vTe=/^[A-Za-z0-9_-]{1,128}$/,PTe=/^cli_[A-Za-z0-9_-]+$/,cV=Object.freeze({abort:"Registration was cancelled.",access_denied:"Registration was denied.",expired_token:"The registration QR code expired.",invalid_credentials:"Feishu returned invalid app credentials.",credentials_callback_failed:"Unable to activate the Feishu connection.",registration_failed:"Unable to register the Feishu app.",connection_failed:"The bot was created, but its connection could not be started.",credential_removal_failed:"Unable to remove the Feishu credentials.",state_cleanup_failed:"Unable to remove the bot session data. Please retry.",deletion_pending:"Bot deletion is incomplete. Retry removal to finish cleanup.",missing_credentials:"The bot credentials are missing. Delete it and scan again.",repair_app_mismatch:"The authorized Feishu app does not match the selected bot.",repair_owner_missing:"Feishu did not return the authorizing account identity.",repair_domain_mismatch:"The authorized Feishu tenant does not match the selected bot.",repair_owner_mismatch:"The authorizing Feishu account is not an owner of the selected bot.",repair_credentials_invalid:"Feishu returned credentials that could not be verified for the selected bot.",repair_bot_mismatch:"The verified Feishu bot does not match the selected bot.",repair_target_changed:"The selected bot changed while repair was in progress. Start the repair again.",credential_update_failed:"Unable to store the repaired Feishu credentials.",credential_state_unknown:"The repaired Feishu credentials could not be confirmed after saving.",repair_connection_failed:"The callback update was accepted, but the selected bot could not reconnect.",group_message_permission_required:"Authorize access to all group messages before enabling this mode.",group_message_permission_save_failed:"Feishu granted the permission, but all-message mode could not be saved.",group_message_permission_connection_failed:"Feishu granted the permission, but the selected bot could not reconnect.",card_action_probe_unavailable:"The selected bot is not connected, so its card button cannot be verified.",card_action_probe_send_failed:"The callback update was accepted, but the verification card could not be sent.",card_action_probe_timeout:"Feishu accepted the update, but the card button was not verified in time. Start the repair again and click the test button within two minutes.",card_action_probe_failed:"Feishu accepted the update, but the card button verification failed."}),GTe=Object.freeze({idle:"pending",starting:"pending",qr_ready:"pending",polling:"pending",slow_down:"pending",domain_switched:"pending",saving:"connecting",succeeded:"connected",expired:"expired",cancelled:"failed",error:"failed"});function FTe(n){if(n===null||typeof n!="object"||Array.isArray(n))return!1;let t=Object.getPrototypeOf(n);return t===Object.prototype||t===null}function po(n,t){return FTe(n)&&Reflect.ownKeys(n).every(o=>typeof o=="string"&&t.has(o))}function yC(n){return Number.isFinite(n)?n:void 0}function zo(n){return typeof n=="string"&&vTe.test(n)}function IV(n,t){return typeof n=="string"&&n.trim().length>0&&n.length<=t}function xk(n){if(!n||typeof n!="object")return null;let t=typeof n.code=="string"&&Object.hasOwn(cV,n.code)?n.code:"registration_failed";return{code:t,message:cV[t]}}function kn(n){if(!n||typeof n!="object")return{state:"idle",attempt:0};let t=NTe.has(n.state)?n.state:"error",o=zo(n.attempt)?n.attempt:yC(n.attempt)??0,i={state:t,attempt:o};i.operation=RTe.has(n.operation)?n.operation:"provision";let e=yC(n.updatedAt),a=yC(n.expiresAt),A=yC(n.remainingSeconds),r=yC(n.pollIntervalSeconds);e!==void 0&&(i.updatedAt=e),typeof n.qrCodeUrl=="string"&&n.qrCodeUrl.length>0&&(i.qrCodeUrl=n.qrCodeUrl),a!==void 0&&(i.expiresAt=a),A!==void 0&&(i.remainingSeconds=A),r!==void 0&&(i.pollIntervalSeconds=r),zo(n.botId)&&(i.botId=n.botId);let s=xk(n.error);return s&&(i.error=s),i}function LTe(n,t,o){if(!(typeof n!="string"||n.length===0))try{let i=new URL(n);if(i.protocol!=="https:"||!kTe.has(i.hostname)||i.port||i.username||i.password)return;if(im.has(t)){let e=i.searchParams.getAll("clientID"),a=i.searchParams.getAll("tp"),A=i.searchParams.getAll("addons"),r=[...i.searchParams.values()].some(s=>s.includes("{{")||s.includes("}}"));if(e.length!==1||a.length!==1||a[0]!=="sdk"||!PTe.test(e[0]??"")||i.hostname!==o||i.searchParams.has("createOnly")||A.length!==1||!A[0]?.trim()||r)return}return i.toString()}catch{return}}function om(n){let t=n&&typeof n=="object"?n:{};return{connected:t.connected===!0||t.ready===!0&&t.feishuLongConnectionState==="connected"&&t.harnessReachable===!0,ready:t.ready===!0,harnessReachable:t.harnessReachable===!0}}function EV(n){let t=n&&typeof n=="object"?n:{},o={name:typeof t.name=="string"&&t.name.length>0?t.name:"\u98DE\u4E66\u673A\u5668\u4EBA"};return typeof t.avatarUrl=="string"&&(o.avatarUrl=t.avatarUrl),typeof t.appIdMasked=="string"&&(o.appIdMasked=t.appIdMasked),typeof t.tenantName=="string"&&(o.tenantName=t.tenantName),(t.domain==="feishu"||t.domain==="lark")&&(o.domain=t.domain),(typeof t.activated=="boolean"||typeof t.activated=="number")&&(o.activated=t.activated),o}function CV(n,t){return t?{status:"healthy",summary:"\u957F\u8FDE\u63A5\u8FD0\u884C\u6B63\u5E38",lastCheckedAt:Date.now()}:n?.configured===!0?{status:"offline",summary:"\u673A\u5668\u4EBA\u5C1A\u672A\u8FDE\u63A5",lastCheckedAt:Date.now()}:{status:"offline",summary:"\u5C1A\u672A\u63A5\u5165\u98DE\u4E66\u673A\u5668\u4EBA",lastCheckedAt:Date.now()}}function uV(n,t,o){return o?"connected":n?.phase==="error"||t.state==="error"?"error":n?.phase==="connecting"||t.state==="saving"?"connecting":n?.phase==="registering"||["starting","qr_ready","polling","slow_down","domain_switched"].includes(t.state)?"provisioning":"disconnected"}async function BV(n){return TTe.toDataURL(n,{errorCorrectionLevel:"M",margin:1,width:320,type:"image/png"})}async function UTe(n,t,o){let i=LTe(n.qrCodeUrl,n.operation,o),e={attemptId:String(n.attempt),operation:n.operation,...n.botId?{botId:n.botId}:{},expiresAt:n.expiresAt??Date.now()+5*6e4,pollIntervalMs:Math.max(800,Math.min(1e4,(n.pollIntervalSeconds??1.8)*1e3))};if(i)return{...e,verificationUrl:i,qrCodeDataUrl:await t(i)};if(n.state==="saving"&&im.has(n.operation)&&n.botId)return{...e,submitted:!0}}function HTe(n){let t=n&&typeof n=="object"?n:{};if(!zo(t.botId))return null;let o=om(t.connection),i=t.connected===!0||o.connected,e={state:"idle"},a={botId:t.botId,state:uV(t,e,i),connected:i,configured:t.configured===!0,agentPreset:hs(t.agentPreset),groupResponseMode:Pi(t.groupResponseMode),groupMessagePermissionGranted:t.groupMessagePermissionGranted===!0,bot:EV(t.bot),health:CV(t,i)};typeof t.workspace=="string"&&t.workspace&&(a.workspace=t.workspace);let A=xk(t.error);return A&&(a.error=A),a}async function Fa(n,{encodeQr:t=BV}={}){let o=n&&typeof n=="object"?n:{},i=kn(o.registration),e=om(o.connection),a=o.connected===!0||e.connected,r=(im.has(i.operation)&&i.botId&&Array.isArray(o.bots)?o.bots.find(d=>d?.botId===i.botId):void 0)?.bot?.domain==="lark"?"open.larksuite.com":"open.feishu.cn",s=await UTe(i,t,r),g=xk(o.error)??i.error??null,c=Array.isArray(o.bots)?o.bots.map(HTe).filter(Boolean):[],I={schemaVersion:o.schemaVersion===2?2:1,revision:Number.isSafeInteger(o.revision)&&o.revision>=0?o.revision:0,state:uV(o,i,a),connected:a,configured:o.configured===!0,bot:EV(o.bot),health:CV(o,a),bots:c,agentPresetCatalog:En(o.agentPresetCatalog),totals:{configured:c.length||(o.configured===!0?1:0),connected:c.length?c.filter(d=>d.connected).length:a?1:0}};return s&&(I.provisioning=s),g&&(I.error=g),I}function rm(n){return{ok:!1,error:{code:"bad-request",message:n,details:{issues:[]}}}}function am(){return{ok:!1,error:{code:"cancelled",message:"The Feishu request was cancelled.",details:{}}}}function KTe(){return{ok:!1,error:{code:"internal",message:"The Feishu integration operation failed.",details:{}}}}function xTe(n,t){return n===Tt.status?po(t,new Set)?null:"This endpoint accepts an empty payload only.":n===Tt.testConnection?po(t,new Set)?null:"This endpoint accepts an empty payload only.":n===Tt.beginProvisioning?po(t,new Set(["locale","replaceAttemptId"]))?t.locale!==void 0&&t.locale!=="zh-CN"?"The provisioning locale must be zh-CN.":t.replaceAttemptId!==void 0&&!zo(t.replaceAttemptId)?"replaceAttemptId must be a valid opaque id.":null:"Provisioning accepts locale and replaceAttemptId only.":n===Tt.beginCallbackRepair?po(t,new Set(["botId"]))&&zo(t.botId)?null:"Callback repair requires a single valid botId.":n===Tt.beginGroupMessagePermission?po(t,new Set(["botId"]))&&zo(t.botId)?null:"Group message permission update requires a single valid botId.":n===Tt.bindCredentials?po(t,new Set(["appId","appSecret"]))&&IV(t.appId,256)&&IV(t.appSecret,1024)?null:"Credential binding requires App ID and App Secret.":n===Tt.pollProvisioning||n===Tt.cancelProvisioning?po(t,new Set(["attemptId"]))&&zo(t.attemptId)?null:"A single valid attemptId is required.":n===Tt.disconnect?po(t,new Set(["removeCredentials"]))&&t.removeCredentials===!0?null:"Disconnect requires removeCredentials=true.":n===BI.reconnectBot?po(t,new Set(["botId","sendTest"]))&&zo(t.botId)&&(t.sendTest===void 0||typeof t.sendTest=="boolean")?null:"A valid botId and optional sendTest flag are required.":n===BI.disconnectBot?po(t,new Set(["botId"]))&&zo(t.botId)?null:"A single valid botId is required.":n===BI.deleteBot?po(t,new Set(["botId","confirm"]))&&zo(t.botId)&&t.confirm===!0?null:"Deleting a bot requires a valid botId and confirm=true.":n===Tt.setWorkspace?Da(t)?null:"\u8BF7\u8F93\u5165\u5DE5\u4F5C\u533A\u7EDD\u5BF9\u8DEF\u5F84\u3002":n===Tt.setAgentPreset?Oa(t)?null:"\u8BF7\u9009\u62E9 Agent Preset\u3002":n===Tt.setGroupResponseMode?po(t,new Set(["botId","groupResponseMode"]))&&zo(t.botId)&&My(t.groupResponseMode)?null:"\u8BF7\u9009\u62E9\u7FA4\u804A\u54CD\u5E94\u65B9\u5F0F\u3002":"Unknown Feishu endpoint."}function YTe(n,t){return new Promise((o,i)=>{if(t?.aborted){i(t.reason??new Error("aborted"));return}let e=setTimeout(a,n);e.unref?.();function a(){t?.removeEventListener("abort",A),o()}function A(){clearTimeout(e),i(t.reason??new Error("aborted"))}t?.addEventListener("abort",A,{once:!0})})}async function Kk(n,t){return typeof n.registrationStatus=="function"?n.registrationStatus(t):n.status()}async function Uk(n,t,o,i){let e=t,a=Date.now()+15e3;for(;;){let A=kn(e?.registration);if(A.qrCodeUrl)return e;if(["error","expired","cancelled"].includes(A.state))throw new Error("Provisioning stopped before the QR code was ready.");if(Date.now()>=a)throw new Error("Provisioning QR code timed out.");if(await YTe(50,i),e=await Kk(n,o),!e)throw new Error("The provisioning attempt is no longer active.")}}function lV(n,t){return String(kn(n?.registration).attempt)===t}function pV(n){let t=kn(n?.registration);return t.state==="succeeded"?t.botId&&(n?.connected===!0||om(n?.connection).connected)?"connected":"connecting":GTe[t.state]??"failed"}function jTe(n){if(!n||typeof n.status!="function"||typeof n.startRegistration!="function"||typeof n.cancelRegistration!="function"||typeof n.disconnect!="function")throw new TypeError("A Feishu controller with status/start/cancel/disconnect is required")}function fV(n,{encodeQr:t=BV}={}){jTe(n);let o=new Map,i=new Map,e=a=>{let A=o.get(a);return A||(o.size>=32&&o.delete(o.keys().next().value),A=Promise.resolve().then(()=>t(a)),o.set(a,A)),A};return async(a,A,r)=>{if(r?.aborted)return am();if(!dV.includes(a))return rm("Unknown Feishu endpoint.");let s=xTe(a,A);if(s)return rm(s);try{let g;if(a===Tt.status)g=await Fa(await n.status(),{encodeQr:e});else if(a===Tt.beginProvisioning){A.replaceAttemptId&&await n.cancelRegistration(A.replaceAttemptId);let c=await n.startRegistration({locale:A.locale}),I=String(kn(c?.registration).attempt),d=await Uk(n,c,I,r);if(g=(await Fa(d,{encodeQr:e})).provisioning,!g)throw new Error("Provisioning did not produce a QR code.");i.set(I,g.verificationUrl)}else if(a===Tt.beginCallbackRepair){if(typeof n.startCallbackRepair!="function")throw new Error("Feishu callback repair is unavailable.");let c=await n.startCallbackRepair(A.botId),I=String(kn(c?.registration).attempt),d=await Uk(n,c,I,r);if(g=(await Fa(d,{encodeQr:e})).provisioning,!g||g.operation!==hV||g.botId!==A.botId)throw new Error("Callback repair did not produce a safe QR code.");i.set(I,g.verificationUrl)}else if(a===Tt.beginGroupMessagePermission){if(typeof n.startGroupMessagePermission!="function")throw new Error("Feishu group message permission update is unavailable.");let c=await n.startGroupMessagePermission(A.botId),I=String(kn(c?.registration).attempt),d=await Uk(n,c,I,r);if(g=(await Fa(d,{encodeQr:e})).provisioning,!g||g.operation!==Hk||g.botId!==A.botId)throw new Error("Group message permission update did not produce a safe QR code.");i.set(I,g.verificationUrl)}else if(a===Tt.pollProvisioning){let c=await Kk(n,A.attemptId);if(!c||!lV(c,A.attemptId))return rm("The provisioning attempt is no longer active.");let I=kn(c.registration),d=await Fa(c,{encodeQr:e});if(g={status:pV(c),operation:I.operation,...I.botId?{botId:I.botId}:{},...d.provisioning?{provisioning:d.provisioning}:{},...I.botId&&d.connected?{connection:d}:{},...d.error?{message:d.error.message}:{}},["connected","expired","failed"].includes(g.status)){let B=i.get(A.attemptId);B&&o.delete(B),i.delete(A.attemptId)}}else if(a===Tt.cancelProvisioning){let c=await Kk(n,A.attemptId);if(!c||!lV(c,A.attemptId))return rm("The provisioning attempt is no longer active.");let I=typeof n.registrationStatus=="function",d=kn(c.registration),B;!I&&d.state==="saving"?B=await n.disconnect():B=await n.cancelRegistration(A.attemptId);let f=kn(B?.registration);if(im.has(d.operation)&&d.state==="saving"&&["saving","succeeded"].includes(f.state)&&(g={status:pV(B),operation:f.operation,...f.botId?{botId:f.botId}:{},message:d.operation===Hk?"The permission update was already submitted and is still being applied.":"Callback repair was already submitted and is still being verified."}),g?.status!=="connecting"){let Q=i.get(A.attemptId);Q&&o.delete(Q),i.delete(A.attemptId),g??={status:"failed",operation:d.operation,...d.botId?{botId:d.botId}:{},message:"Registration was cancelled."}}}else if(a===Tt.bindCredentials){if(typeof n.bindCredentials!="function")throw new Error("Credential binding is unavailable");g=await Fa(await n.bindCredentials(A),{encodeQr:e})}else if(a===Tt.testConnection){let c=await n.status(),d=c?.connected===!0||om(c?.connection).connected||typeof n.reconnect!="function"?c:await n.reconnect();g=await Fa(d,{encodeQr:e})}else if(a===Tt.disconnect)g=await Fa(await n.disconnect(),{encodeQr:e});else if(a===BI.reconnectBot){if(typeof n.reconnectBot!="function")throw new Error("Multi-bot reconnect is unavailable");let c=await n.reconnectBot(A.botId);if(r?.aborted)return am();if(g=await Fa(c,{encodeQr:e}),A.sendTest===!0){let I=null;if(!(c?.bots?.some(B=>B?.botId===A.botId&&B.connected===!0)===!0))I=new Error("Feishu bot is not connected"),I.code="test-target-unavailable";else try{if(typeof n.sendConnectionTest!="function"){let B=new Error("Connection test is unavailable");throw B.code="test-target-unavailable",B}await n.sendConnectionTest(A.botId)}catch(B){I=B}g={...g,testMessage:$t(I)}}}else if(a===BI.disconnectBot){if(typeof n.disconnectBot!="function")throw new Error("Multi-bot disconnect is unavailable");g=await Fa(await n.disconnectBot(A.botId),{encodeQr:e})}else if(a===Tt.setWorkspace){if(typeof n.updateWorkspace!="function")throw new Error("Workspace update is unavailable");g=await Fa(await n.updateWorkspace(A.botId,A.workspace),{encodeQr:e})}else if(a===Tt.setAgentPreset){if(typeof n.updateAgentPreset!="function")throw new Error("Agent preset update is unavailable");g=await Fa(await n.updateAgentPreset(A.botId,A.agentPreset),{encodeQr:e})}else if(a===Tt.setGroupResponseMode){if(typeof n.updateGroupResponseMode!="function")throw new Error("Group response mode update is unavailable");g=await Fa(await n.updateGroupResponseMode(A.botId,A.groupResponseMode),{encodeQr:e})}else{if(typeof n.deleteBot!="function")throw new Error("Multi-bot delete is unavailable");g=await Fa(await n.deleteBot(A.botId),{encodeQr:e})}return r?.aborted?am():{ok:!0,value:g}}catch(g){let c=wa(g);return r?.aborted?am():c?{ok:!1,error:{...c,details:{}}}:KTe()}}}function nm(n,t,o,i){if(!n?.connection?.rpc||typeof n.connection.rpc.handle!="function")throw new TypeError("DSH Host Connection RPC is required");return n.connection.rpc.handle(Lk,fV(t,o),{authority:fr(i)})}function JTe(n,t){if(t?.controller)return t.controller;if(typeof t?.createController=="function")return t.createController();if(typeof t?.createProvisioningManager=="function")return fM(t)}async function QV(n,t={}){let o=JTe(n,t);if(o)return nm(n,o,t.rpcOptions,t.rpcAuthority);let i=await Tk(n,t),e=nm(n,i.controller,t.rpcOptions,t.rpcAuthority);return n.effect(()=>async()=>{await i.close()},"dsh-feishu: close controller and live connection"),e}import{unlink as R0e}from"node:fs/promises";import{homedir as k0e}from"node:os";import{join as OC,resolve as yI}from"node:path";import{createHash as qTe}from"node:crypto";import{mkdir as zTe,readFile as VTe,rename as WTe,unlink as ZTe,writeFile as XTe}from"node:fs/promises";import{dirname as $Te}from"node:path";var Yk=Object.freeze({version:1,bots:Object.freeze([])});function Lg(n){return typeof n=="string"&&n.trim()?n.trim():null}function yV(n){let t=Lg(n);return t&&/^qq_[a-f0-9]{24}$/.test(t)?t:null}function e0e(n){let t=Lg(n);return t&&/^DSH_QQBOT_APP_SECRET_[A-F0-9]{24}$/.test(t)?t:null}function gm(n){let t=Lg(n);if(!t)throw new TypeError("appId is required");let o=qTe("sha256").update(t).digest("hex").slice(0,24);return{botId:`qq_${o}`,secretRef:`DSH_QQBOT_APP_SECRET_${o.toUpperCase()}`}}function jk(n){let t=Lg(n)??"";return t.length<=10?t?`${t.slice(0,3)}\u2022\u2022\u2022`:w("QQ\u673A\u5668\u4EBA"):`${t.slice(0,6)}\u2022\u2022\u2022\u2022${t.slice(-4)}`}function mV(n){if(!n||typeof n!="object")return null;let t=Lg(n.appId),o=Lg(n.ownerUserOpenid),i=yV(n.botId),e=e0e(n.secretRef);if(!t||!o||!i||!e)return null;let a=gm(t);return a.botId!==i||a.secretRef!==e?null:Object.freeze({botId:i,appId:t,secretRef:e,ownerUserOpenid:o,createdAt:Lg(n.createdAt)??new Date().toISOString(),connectedAt:Lg(n.connectedAt)})}function A0e(n){if(!n||n.version!==1||!Array.isArray(n.bots))return null;let t=n.bots.map(mV);if(t.some(a=>a===null))return null;let o=new Set,i=new Set,e=new Set;for(let a of t){if(o.has(a.botId)||i.has(a.appId)||e.has(a.secretRef))return null;o.add(a.botId),i.add(a.appId),e.add(a.secretRef)}return Object.freeze({version:1,bots:Object.freeze(t)})}var sm=class{#e;#A=Yk;#t=Promise.resolve();constructor(t){this.#e=t}async load(){try{let t=A0e(JSON.parse(await VTe(this.#e,"utf8")));if(!t)throw new Error("dsh-im QQ config contains invalid bot data");this.#A=t}catch(t){if(t?.code!=="ENOENT")throw t;this.#A=Yk}return this}list(){return structuredClone(this.#A.bots)}get(t){let o=this.#A.bots.find(i=>i.botId===t);return o?structuredClone(o):null}getByAppId(t){let o=this.#A.bots.find(i=>i.appId===t);return o?structuredClone(o):null}async save(t){let o=mV(t);if(!o)throw new Error("Refusing to persist incomplete QQ bot data");return this.#r(i=>{let e=i.find(r=>r.appId===o.appId&&r.botId!==o.botId),a=i.find(r=>r.secretRef===o.secretRef&&r.botId!==o.botId);if(e||a)throw new Error("Duplicate QQ bot identity");let A=i.findIndex(r=>r.botId===o.botId);return A===-1?i.push(o):i[A]=o,structuredClone(o)})}async remove(t){if(!yV(t))throw new TypeError("Invalid QQ bot id");return this.#r(o=>{let i=o.findIndex(a=>a.botId===t);if(i===-1)return null;let[e]=o.splice(i,1);return structuredClone(e)})}async clear(){let t=this.#t.then(async()=>{try{await ZTe(this.#e)}catch(o){if(o?.code!=="ENOENT")throw o}this.#A=Yk});this.#t=t.then(()=>{},()=>{}),await t}async#r(t){let o,i=this.#t.then(async()=>{let e=[...this.#A.bots];o=t(e);let a=Object.freeze({version:1,bots:Object.freeze(e)});await this.#o(a),this.#A=a});return this.#t=i.then(()=>{},()=>{}),await i,o}async#o(t){await zTe($Te(this.#e),{recursive:!0,mode:448});let o=`${this.#e}.tmp`;await XTe(o,`${JSON.stringify(t,null,2)} `,{encoding:"utf8",mode:384}),await WTe(o,this.#e)}};var cm=class extends gr{constructor(t){super({...t,rpcIdPrefix:"qq",logPrefix:"dsh-qq"})}};import{randomUUID as t0e}from"node:crypto";var SV=new Set(["starting","pending","refreshing","connecting"]),fI=new Set(["connected","failed","cancelled"]),r0e=5*6e4;function QI(n){return typeof n=="string"&&n.trim()?n.trim():null}function Vo(n,t){return Object.freeze({code:n,message:t})}function Im(n){return n?{attemptId:n.id,status:n.state,qrRevision:n.qrRevision,pollIntervalMs:1e3,...n.verificationUrl?{verificationUrl:n.verificationUrl}:{},...n.expiresAt?{expiresAt:n.expiresAt}:{},...n.botId?{botId:n.botId}:{},...n.error?{error:structuredClone(n.error)}:{}}:null}var mC=class{#e;#A;#t;#r;#o;#i;#c=new Map;#s=new Map;#I=new Map;#a=null;#n=new Map;#g=0;#l=!1;constructor({qrAuth:t,credentials:o,configStore:i,createRuntime:e,deleteState:a=async()=>{},logger:A=console}){if(!t||typeof t.start!="function")throw new TypeError("QQ QR auth is required");if(!o||typeof o.resolve!="function"||typeof o.set!="function"||typeof o.unset!="function")throw new TypeError("QqController requires the DSH credential provider");if(!i||typeof i.list!="function"||typeof i.save!="function"||typeof i.remove!="function")throw new TypeError("QqController requires a config store");if(typeof e!="function")throw new TypeError("createRuntime is required");this.#e=t,this.#A=o,this.#t=i,this.#r=e,this.#o=a,this.#i=A}async initialize(){if(this.#l)return this.status();for(let t of this.#t.list())await this.#f(t.botId,async()=>{if(this.#l||this.#c.get(t.botId)?.status?.ready)return;let o=await this.#C(t.secretRef);if(!o){this.#s.set(t.botId,Vo("missing-secret",w("QQ \u673A\u5668\u4EBA\u51ED\u636E\u7F3A\u5931\uFF0C\u8BF7\u79FB\u9664\u540E\u91CD\u65B0\u626B\u7801\u3002")));return}try{await this.#E(t,o),this.#s.delete(t.botId)}catch(i){this.#s.set(t.botId,Vo("connection-failed",w("QQ \u8FDE\u63A5\u672A\u5C31\u7EEA\uFF0C\u63D2\u4EF6\u4F1A\u81EA\u52A8\u91CD\u8BD5\u3002"))),this.#i.warn?.(`[dsh-im:qq] bot ${t.botId} failed to initialize:`,i)}finally{this.#y()}});return this.status()}async startProvisioning(){if(this.#l)throw new Error("QQ controller is closed");this.#a&&await this.cancelProvisioning(this.#a);let t,o,i=new Promise((a,A)=>{t=a,o=A}),e={id:t0e(),state:"starting",createdAt:Date.now(),expiresAt:null,qrRevision:0,verificationUrl:null,controller:new AbortController,dispose:null,task:null,error:null,botId:null};this.#I.set(e.id,e),this.#a=e.id,this.#y();try{return e.dispose=this.#e.start({onQrDisplayed:a=>{if(e.controller.signal.aborted||fI.has(e.state))return;let A=QI(a);A&&(e.verificationUrl=A,e.qrRevision+=1,e.expiresAt=Date.now()+r0e,e.state="pending",this.#y(),t())},onQrExpired:()=>{e.controller.signal.aborted||fI.has(e.state)||(e.state="refreshing",e.verificationUrl=null,e.expiresAt=null,this.#y())},onSuccess:a=>{e.controller.signal.aborted||fI.has(e.state)||(e.task=this.#p(e,a))},onFailure:a=>{e.controller.signal.aborted||fI.has(e.state)||(e.state="failed",e.error=Vo("qr-connect-failed",w("QQ \u626B\u7801\u670D\u52A1\u6682\u65F6\u4E0D\u53EF\u7528\uFF0C\u8BF7\u91CD\u65B0\u751F\u6210\u4E8C\u7EF4\u7801\u3002")),this.#a===e.id&&(this.#a=null),this.#y(),o(a))}},{signal:e.controller.signal}),await i,Im(e)}catch(a){throw e.controller.signal.aborted?(e.state="cancelled",e.error=Vo("cancelled",w("\u626B\u7801\u7ED1\u5B9A\u5DF2\u53D6\u6D88\u3002"))):fI.has(e.state)||(e.state="failed",e.error=Vo("qr-start-failed",w("\u65E0\u6CD5\u751F\u6210 QQ \u4E8C\u7EF4\u7801\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002"))),this.#a===e.id&&(this.#a=null),this.#y(),a}}registrationStatus(t){return Im(this.#I.get(t))}async bindCredentials({appId:t,appSecret:o}={}){if(this.#l)throw new Error("QQ controller is closed");let i=QI(t),e=QI(o);if(!i||!e)throw new TypeError("QQ AppID and AppSecret are required");if(this.#a&&await this.cancelProvisioning(this.#a),this.#l)throw new Error("QQ controller is closed");let a=gm(i);return await this.#f(a.botId,async()=>{if(this.#l)throw new Error("QQ controller is closed");let A=this.#t.getByAppId(i),r=await this.#A.resolve(a.secretRef).catch(()=>{});if(this.#l)throw new Error("QQ controller is closed");let s={botId:a.botId,appId:i,secretRef:a.secretRef,ownerUserOpenid:A?.ownerUserOpenid??"*",createdAt:A?.createdAt??new Date().toISOString(),connectedAt:new Date().toISOString()};await this.#A.set(a.secretRef,e);try{await this.#t.save(s)}catch(g){throw await this.#B(a.secretRef,r),g}try{await this.#E(s,e),this.#s.delete(a.botId)}catch(g){this.#s.set(a.botId,Vo("connection-failed",w("QQ \u673A\u5668\u4EBA\u5DF2\u7ED1\u5B9A\uFF0C\u6D88\u606F\u8FDE\u63A5\u6682\u672A\u5C31\u7EEA\u3002"))),this.#i.warn?.(`[dsh-im:qq] bot ${a.botId} credential connection failed:`,g)}this.#y()}),this.status()}async cancelProvisioning(t){let o=this.#I.get(t);return o?(fI.has(o.state)||(o.controller.abort(),o.dispose?.(),await o.task?.catch(()=>{}),fI.has(o.state)||(o.state="cancelled"),o.error??=Vo("cancelled",w("\u626B\u7801\u7ED1\u5B9A\u5DF2\u53D6\u6D88\u3002"))),this.#a===o.id&&(this.#a=null),this.#y(),Im(o)):null}async reconnectBot(t){let o=this.#t.get(t);if(!o)throw new Error("Unknown QQ bot");return await this.#f(t,async()=>{let i=await this.#C(o.secretRef);if(!i)throw new Error("QQ bot secret is missing");try{await this.#E(o,i),this.#s.delete(t)}catch(e){throw this.#s.set(t,Vo("connection-failed",w("QQ \u8FDE\u63A5\u4ECD\u672A\u5C31\u7EEA\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002"))),e}finally{this.#y()}}),this.status()}async sendConnectionTest(t){let o=this.#t.get(t);if(!o)throw new Error("Unknown QQ bot");return this.#f(t,async()=>{let i=this.#c.get(t);if(!i?.status?.ready||typeof i.sendConnectionTest!="function"){let e=new Error(w("QQ\u673A\u5668\u4EBA\u5C1A\u672A\u8FDE\u63A5"));throw e.code="test-target-unavailable",e}return await i.sendConnectionTest(Ea(w("QQ \u673A\u5668\u4EBA\uFF08{appId}\uFF09",{appId:jk(o.appId)}))),{sent:!0}})}async deleteBot(t){let o=this.#t.get(t);if(!o)throw new Error("Unknown QQ bot");return await this.#f(t,async()=>{let i=await this.#A.resolve(o.secretRef).catch(()=>{});await this.#h(t);try{await this.#A.unset(o.secretRef),await this.#t.remove(t)}catch(e){throw i?.value&&(await this.#A.set(o.secretRef,i.value).catch(()=>{}),await this.#E(o,i.value).catch(()=>{})),new Error("Unable to remove the QQ bot safely.",{cause:e})}await this.#o({botId:t,config:o}).catch(e=>{this.#i.warn?.(`[dsh-im:qq] bot ${t} state cleanup failed:`,e)}),this.#s.delete(t),this.#y()}),this.status()}status(){let t=this.#t.list().map(e=>{let a=this.#c.get(e.botId)?.status??null,A=a?.ready===!0&&a.qqConnectionState==="connected"&&a.harnessReachable===!0,r=A?"connected":a?.qqConnectionState==="connecting"?"connecting":this.#s.has(e.botId)||a?.qqConnectionState==="failed"?"error":"offline";return{botId:e.botId,state:r,connected:A,configured:!0,bot:{name:w("QQ\u673A\u5668\u4EBA"),appIdMasked:jk(e.appId)},health:{status:A?"healthy":r==="error"?"error":"offline",summary:A?w("QQ WebSocket \u957F\u8FDE\u63A5\u8FD0\u884C\u6B63\u5E38"):r==="error"?w("QQ \u8FDE\u63A5\u672A\u5C31\u7EEA\uFF0C\u63D2\u4EF6\u4F1A\u81EA\u52A8\u91CD\u8BD5"):w("QQ \u8FDE\u63A5\u5F53\u524D\u79BB\u7EBF"),lastCheckedAt:a?.lastCheckedAt??null,lastConnectedAt:a?.lastConnectedAt??null},stats:{messagesReceived:a?.messagesReceived??0,messagesReplied:a?.messagesReplied??0},error:structuredClone(this.#s.get(e.botId)??null)}}),o=t.filter(e=>e.connected).length,i=this.#a?this.#I.get(this.#a):null;return{schemaVersion:1,revision:this.#g,state:i&&SV.has(i.state)?"provisioning":t.length===0?"disconnected":o===t.length?"connected":o>0?"degraded":"offline",bots:t,totals:{configured:t.length,connected:o},...i&&SV.has(i.state)?{provisioning:Im(i)}:{}}}async close(){this.#l||(this.#l=!0,this.#a&&await this.cancelProvisioning(this.#a),await Promise.allSettled([...this.#n.values()]),await Promise.allSettled([...this.#c.keys()].map(t=>this.#h(t))))}async#p(t,o){try{t.state="connecting",t.verificationUrl=null,t.expiresAt=null,this.#y();let i=Array.isArray(o)?o[0]:null,e=QI(i?.appId),a=QI(i?.appSecret),A=QI(i?.userOpenid);if(!e||!a||!A)throw new Error("QQ authorization returned incomplete credentials");t.botId=await this.#d(t,{appId:e,appSecret:a,ownerUserOpenid:A}),t.state="connected",t.error=null}catch(i){t.controller.signal.aborted?(t.state="cancelled",t.error=Vo("cancelled",w("\u626B\u7801\u7ED1\u5B9A\u5DF2\u53D6\u6D88\u3002"))):(t.state="failed",t.error=Vo("activation-failed",w("QQ \u5DF2\u6388\u6743\uFF0C\u4F46\u65E0\u6CD5\u5B89\u5168\u4FDD\u5B58\u63A5\u5165\u914D\u7F6E\u3002")),this.#i.error?.("[dsh-im:qq] provisioning failed:",i))}finally{t.dispose?.(),this.#a===t.id&&(this.#a=null),this.#y()}}async#d(t,{appId:o,appSecret:i,ownerUserOpenid:e}){let a=gm(o),A=this.#t.getByAppId(o),r=await this.#A.resolve(a.secretRef).catch(()=>{}),s={botId:a.botId,appId:o,secretRef:a.secretRef,ownerUserOpenid:e,createdAt:A?.createdAt??new Date().toISOString(),connectedAt:new Date().toISOString()};return this.#f(a.botId,async()=>{await this.#A.set(a.secretRef,i);try{if(t.controller.signal.aborted)throw new DOMException("Cancelled","AbortError");await this.#t.save(s)}catch(g){throw await this.#B(a.secretRef,r),g}try{if(t.controller.signal.aborted)throw new DOMException("Cancelled","AbortError");await this.#E(s,i),this.#s.delete(a.botId)}catch(g){if(t.controller.signal.aborted)throw await this.#h(a.botId),A?await this.#t.save(A).catch(()=>{}):await this.#t.remove(a.botId).catch(()=>null)&&await this.#o({botId:a.botId,config:s}).catch(I=>{this.#i.warn?.("[dsh-im:qq] cancelled bot state cleanup failed:",I)}),await this.#B(a.secretRef,r),g;this.#s.set(a.botId,Vo("connection-failed",w("QQ \u673A\u5668\u4EBA\u5DF2\u7ED1\u5B9A\uFF0C\u6D88\u606F\u8FDE\u63A5\u6682\u672A\u5C31\u7EEA\u3002"))),this.#i.warn?.(`[dsh-im:qq] bot ${a.botId} activation connection failed:`,g)}return this.#y(),a.botId})}async#E(t,o){if(this.#l)throw new Error("QQ controller is closed");if(await this.#h(t.botId),this.#l)throw new Error("QQ controller is closed");let i=await this.#r({botId:t.botId,config:t,appSecret:o});if(!i||typeof i.start!="function"||typeof i.stop!="function")throw new TypeError("createRuntime returned an invalid QQ runtime");this.#c.set(t.botId,i);try{await i.start()}catch(e){throw await i.stop().catch(()=>{}),this.#c.delete(t.botId),e}}async#h(t){let o=this.#c.get(t);this.#c.delete(t),await o?.stop().catch(i=>{this.#i.warn?.(`[dsh-im:qq] bot ${t} failed to stop cleanly:`,i)})}async#C(t){let o=await this.#A.resolve(t).catch(()=>{});return QI(o?.value)}async#B(t,o){o?.value?await this.#A.set(t,o.value).catch(()=>{}):await this.#A.unset(t).catch(()=>{})}#f(t,o){let a=(this.#n.get(t)??Promise.resolve()).catch(()=>{}).then(o).finally(()=>{this.#n.get(t)===a&&this.#n.delete(t)});return this.#n.set(t,a),a}#y(){this.#g+=1}};import{QQBot as f0e,typingIndicator as Q0e}from"@tencent-connect/qqbot-nodejs";var DV=4500,a0e=/^```/,i0e=/^\|.+\|$/,o0e=Object.freeze({c2c:4,group:5}),n0e=()=>w("\u56DE\u7B54\u8F83\u957F\uFF0C\u540E\u7EED\u5185\u5BB9\u672A\u80FD\u901A\u8FC7 QQ \u5B8C\u6574\u53D1\u9001\uFF0C\u8BF7\u56DE\u590D\u201C\u7EE7\u7EED\u201D\u3002");function wV(n,t){let o=Math.min(t,n.length),i=n.charCodeAt(o-1),e=n.charCodeAt(o);return i>=55296&&i<=56319&&e>=56320&&e<=57343&&(o-=1),Math.max(1,o)}function s0e(n,t=DV){let o=typeof n=="string"?n:"",i=Number.isInteger(t)&&t>0?t:DV;if(o.length<=i)return o?[o]:[];let e=o.split(` `),a=[],A="",r=!1,s=[],g=d=>{if(d.length<=i){if(!A){A=d;return}let f=`${A} diff --git a/package-lock.json b/package-lock.json index b491c31..25c0f25 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@xmanrui/dsh-im", - "version": "2.1.0", + "version": "2.2.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@xmanrui/dsh-im", - "version": "2.1.0", + "version": "2.2.0", "license": "MIT", "dependencies": { "@tencent-connect/qqbot-connector": "1.2.0", diff --git a/package.json b/package.json index cd88073..bd62f03 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@xmanrui/dsh-im", - "version": "2.1.0", + "version": "2.2.0", "description": "把九种 IM 机器人和公网 AI Office 接入本机 DeepSeek Harness。 Connect nine IM channels and a public AI Office to a local DeepSeek Harness.", "keywords": [ "deepseek-harness",