diff --git a/lib/client.js b/lib/client.js index 24f5203..de52823 100644 --- a/lib/client.js +++ b/lib/client.js @@ -839,6 +839,7 @@ var EN = Object.freeze({ "$locale": "en", "IM\u673A\u5668\u4EBA": "IM bots", "IM\u673A\u5668\u4EBA\u8BBE\u7F6E": "IM bot settings", + "\u66F4\u591A\u673A\u5668\u4EBA\u8BBE\u7F6E": "More bot settings", "IM \u6E20\u9053": "IM channels", "\u8BA9 DeepSeek Harness \u89E6\u624B\u53EF\u53CA": "Connecting DeepSeek Harness", "\u5F53\u524D\u7248\u672C": "Current version", @@ -1580,7 +1581,6 @@ var EN = Object.freeze({ "\u6253\u5F00\u4E3B\u52A8\u6295\u9012\u4F7F\u7528\u6587\u6863": "Open the proactive delivery guide", "\u5F53\u524D\u6E20\u9053\u6682\u4E0D\u652F\u6301\u6295\u9012\u76EE\u6807\u3002": "Delivery targets are not supported for this channel.", "\u5DF2\u590D\u5236 Bot ID": "Bot ID copied", - "\u8C03\u7528\u6807\u8BC6": "Call identifiers", "\u590D\u5236": "Copy", "\u6295\u9012\u76EE\u6807": "Delivery targets", "\u673A\u5668\u4EBA\u5F53\u524D\u79BB\u7EBF\uFF1B\u4ECD\u53EF\u914D\u7F6E\u76EE\u6807\uFF0C\u6062\u590D\u8FDE\u63A5\u540E\u518D\u6D4B\u8BD5\u3002": "The bot is offline. You can still configure targets and test them after reconnection.", @@ -3089,7 +3089,7 @@ function BotSettingsButton({ channel: channel4, botId, botName, connected }) { type: "button", className: "dim-botSettingsButton", "data-delivery-channel": channel4, - "aria-label": "\u673A\u5668\u4EBA\u8BBE\u7F6E", + "aria-label": "\u66F4\u591A\u673A\u5668\u4EBA\u8BBE\u7F6E", "aria-describedby": tooltipId, onClick: () => openBotSettings?.({ channel: channel4, @@ -3102,7 +3102,7 @@ function BotSettingsButton({ channel: channel4, botId, botName, connected }) { id: tooltipId, className: "dim-botSettingsTooltip", role: "tooltip" - }, "\u673A\u5668\u4EBA\u8BBE\u7F6E") + }, "\u66F4\u591A\u673A\u5668\u4EBA\u8BBE\u7F6E") ); } function messageErrorTime(value) { @@ -12393,17 +12393,20 @@ function DeliveryTargetSettingsPage({ channel: channel4, account, rpcCall, onBac }, h2("span", null, "\u4F7F\u7528\u6587\u6863"), h2("span", { "aria-hidden": "true" }, "\u2197") - ), - h2("h2", null, account.botName || "\u673A\u5668\u4EBA\u8BBE\u7F6E") + ) ) ), h2( "section", - { className: "dim-deliveryIdentity", "aria-labelledby": "dim-delivery-identity-title" }, + { className: "dim-deliveryIdentity", "aria-labelledby": "dim-delivery-bot-title" }, h2( "div", null, - h2("h3", { id: "dim-delivery-identity-title" }, "\u8C03\u7528\u6807\u8BC6") + h2( + "h2", + { id: "dim-delivery-bot-title", className: "dim-deliveryBotName" }, + account.botName || "\u673A\u5668\u4EBA\u8BBE\u7F6E" + ) ), h2( "div", @@ -12911,7 +12914,6 @@ var CSS11 = String.raw` .dim-deliveryPage { min-width: 0; display: grid; gap: 14px; } .dim-deliveryHeader { min-width: 0; display: flex; align-items: center; justify-content: space-between; gap: 16px; } .dim-deliveryHeaderMeta { min-width: 0; display: flex; align-items: center; justify-content: flex-end; gap: 10px; text-align: right; } -.dim-deliveryHeader h2 { min-width: 0; overflow: hidden; margin: 0; font-size: 18px; line-height: 24px; font-weight: 680; text-overflow: ellipsis; white-space: nowrap; } .dim-deliveryDocsLink { min-height: 30px; flex: none; display: inline-flex; align-items: center; gap: 4px; padding: 5px 8px; border-radius: 7px; color: var(--dsw-alias-state-business-primary, #3370ff); font-size: 12px; line-height: 18px; text-decoration: none; white-space: nowrap; } .dim-deliveryDocsLink:hover { background: color-mix(in srgb, var(--dsw-alias-state-business-primary, #3370ff) 8%, transparent); } .dim-deliveryDocsLink:focus-visible { outline: 2px solid var(--dsw-alias-state-business-primary, #3370ff); outline-offset: 2px; } @@ -12923,7 +12925,7 @@ var CSS11 = String.raw` .dim-deliveryButton[data-kind="danger"] { color: var(--dsw-alias-state-error-primary, #d54941); } .dim-deliveryBack { flex: none; border-color: transparent; background: transparent; } .dim-deliveryIdentity, .dim-deliveryTargets { min-width: 0; padding: 16px; border: 1px solid var(--dsw-alias-border-l2, #dfe1e5); border-radius: 12px; background: var(--dsw-alias-bg-layer-3, #fff); } -.dim-deliveryIdentity > div:first-child h3, .dim-deliverySectionHeading h3 { margin: 0; font-size: 15px; line-height: 22px; font-weight: 650; } +.dim-deliveryBotName, .dim-deliverySectionHeading h3 { min-width: 0; overflow: hidden; margin: 0; font-size: 15px; line-height: 22px; font-weight: 650; text-overflow: ellipsis; white-space: nowrap; } .dim-deliveryIdentity > div:first-child p, .dim-deliverySectionHeading p { margin: 2px 0 0; color: var(--dsw-alias-label-secondary, #646a73); font-size: 12px; line-height: 18px; } .dim-deliveryBotId { min-width: 0; display: grid; grid-template-columns: max-content minmax(0, 1fr) max-content; align-items: center; gap: 10px; margin-top: 12px; padding: 10px 12px; border-radius: 9px; background: var(--dsw-alias-bg-module-platform, #f7f8fa); } .dim-deliveryBotId > span { color: var(--dsw-alias-label-secondary, #646a73); font-size: 12px; } diff --git a/lib/index.js b/lib/index.js index 8efe8d6..14d1a98 100644 --- a/lib/index.js +++ b/lib/index.js @@ -361,9 +361,9 @@ ID\uFF1A{id}`,{title:A,id:a?.sessionId??i}),w("\u53D1\u9001 /history \u67E5\u770 ${w("\u5185\u5BB9\u8F83\u957F\uFF0C\u751F\u6210\u5B8C\u6210\u540E\u5C06\u5206\u6BB5\u53D1\u9001\u5B8C\u6574\u56DE\u7B54\u3002")}`;return Vv(n,Cu-t.length)+t}function ARe(n){let t=[],o=n;for(;o.length>Cu;){let i=Vv(o,Cu),e=i.lastIndexOf(` `)+1;e{let c=String(g??"")||"\u2026";await this.#n(a,KW(c)),A=c}};await o.markdown(r);let s=ARe(A);for(let[g,c]of s.entries()){let I=g===0?a:await this.#a(t,i.replyTo);g>0&&e.push(I),await this.#n(I,c),await this.#o(I)}return{messageId:a.messageId,providerMessageIds:e.map(g=>g.messageId)}}catch(a){for(let A of e)await this.#l(A.messageId);throw a}}async sendFile(t,o,{replyTo:i,signal:e}={}){return this.#g(t,o,{replyTo:i,signal:e,messageType:"file",presentation:"feishu-file"})}async sendImage(t,o,{replyTo:i,signal:e}={}){return this.#g(t,o,{replyTo:i,signal:e,messageType:"image",presentation:"feishu-image"})}async#g(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 HW(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 In(o,y),y},{signal:e,timeoutMs:this.#t,stage:"upload"})}catch(Q){throw e?.aborted?zv(e):Eu("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 Eu("upload",void 0,r?.code);let g=$Ne(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 In(o,Q),Q},B;try{B=await HW(async Q=>{Q.throwIfAborted();let y;try{y=await d()}catch(m){if(jW(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?zv(e):Eu("message send",Q,void 0,{uncertain:!0})}if(Number.isFinite(Number(B?.code))&&Number(B.code)!==0)throw Eu("message send",void 0,B.code,{uncertain:!0});let f=B?.data?.message_id;if(typeof f!="string"||!f)throw Eu("message send",void 0,void 0,{uncertain:!0});return Wt({deliveryId:o.deliveryKey,presentation:A,providerMessageIds:[f],artifacts:[{artifactId:o.artifactId,outcome:"sent"}]})}async#a(t,o){let i=KW(this.#A),a=al("Feishu card.create",await this.#e.cardkit.v1.card.create({data:{type:"card_json",data:JSON.stringify(tRe(i))}}))?.data?.card_id;if(!a)throw new Error("Feishu card.create returned no card_id");let A=await this.#c(t,a,o);return{cardId:a,messageId:A,content:i,sequence:0}}async#n(t,o){if(o===t.content)return;let i=await this.#e.cardkit.v1.cardElement.content({path:{card_id:t.cardId,element_id:xW},data:{content:o,sequence:++t.sequence,uuid:`content_${t.cardId}_${t.sequence}`}});al("Feishu cardElement.content",i),t.content=o}async#o(t){let o=await this.#e.cardkit.v1.card.settings({path:{card_id:t.cardId},data:{settings:JSON.stringify({config:{streaming_mode:!1,summary:{content:eRe(t.content)||w("\u56DE\u7B54\u5B8C\u6210")}}}),sequence:++t.sequence,uuid:`settings_${t.cardId}_${t.sequence}`}});al("Feishu card.settings",o)}async#c(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}});al("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#l(t){try{let o=await this.#e.im.v1.message.delete({path:{message_id:t}});al("Feishu message delete",o)}catch(o){console.warn("[bridge] unable to recall a failed streaming card:",o.message)}}async addReaction(t,o){let e=al("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){al("Feishu reaction.delete",await this.#e.im.v1.messageReaction.delete({path:{message_id:t,reaction_id:o}}))}};var aRe=15e3,iRe="\u2705 \u4FEE\u590D\u5B8C\u6210\uFF1A\u5DF2\u5B9E\u6D4B\u6536\u5230 card.action.trigger\uFF0C\u83DC\u5355\u6309\u94AE\u73B0\u5728\u53EF\u7528\u3002",oRe="\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",Wv="\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",nRe="\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",sRe=new Set(["connected","connecting","reconnecting"]);function yn(n){return typeof n=="string"&&n.trim()?n.trim():null}function gRe(n){return yn(n?.operator?.open_id)??yn(n?.operator?.operator_id?.open_id)}function cRe(n,t){try{let o=n?.getConnectionStatus?.()?.state;return typeof o=="string"&&o?o:t}catch{return t}}function bd(n,t){let o=new Error(t);return o.code=n,o}function IRe(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 lRe({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 rS=class{#e;#A;#t;#r;#g;#a;#n;#o;#c;#l;#i;#I;#s;#p;#h;#d;#E;#C=null;#f=null;#B=null;#y=null;#S=null;#Q=null;#m=new Map;#u;constructor({lark:t,botId:o,appId:i,appSecret:e,domain:a="feishu",botOpenId:A,groupResponseMode:r,ownerOpenId:s,ownerOpenIds:g,harness:c,state:I,contextEnhancement:d,repair:B,replyTimeoutMs:f=6e5,connectTimeoutMs:Q=15e3,requestTimeoutMs:y=aRe,wsAgent:m,logger:_=console}){if(!t)throw new Error("FeishuRuntime requires the Feishu SDK");if(!i||!e)throw new Error("FeishuRuntime requires app credentials");let T=Array.isArray(g)?g:[s],R=[...new Set(T.filter(F=>typeof F=="string"&&F))];if(R.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(B!=null&&!yn(o))throw new TypeError("FeishuRuntime repair capability requires a botId");if(!Number.isFinite(y)||y<=0)throw new TypeError("FeishuRuntime requestTimeoutMs must be a positive number");this.#e=t,this.#A=yn(o),this.#t=i,this.#r=e,this.#g=a,this.#a=yn(A),this.#n=ro(r),this.#o=R,this.#c=c,this.#l=I,this.#i=d,this.#E=B??null,this.#I=f,this.#s=Q,this.#p=y,this.#h=m,this.#d=_,this.#u=lRe({allowedSenderCount:R.length})}get status(){return structuredClone(this.#u)}setGroupResponseMode(t){this.#n=ro(t),this.#f?.setGroupResponseMode(this.#n)}async start(){for(;;){for(;this.#S;)await this.#S;if(this.#y)return this.#y;let o=this.#B;if(o){let i=cRe(o,this.#u.feishuLongConnectionState);if(sRe.has(i))return this.status;await this.stop({preserveError:i==="failed"});continue}if(this.#C||this.#f||this.#Q){await this.stop({preserveError:this.#u.feishuLongConnectionState==="failed"});continue}break}let t;return t=this.#b().finally(()=>{this.#y===t&&(this.#y=null)}),this.#y=t,t}async#b(){let t=new AbortController;this.#Q=t;let{signal:o}=t,i=()=>o.reason??new DOMException("Feishu runtime stopped","AbortError"),e=()=>!o.aborted&&this.#Q===t,a=()=>{if(!e())throw i()};this.#u.startedAt=new Date().toISOString(),this.#u.feishuLongConnectionState="connecting",this.#u.lastError=null;try{await this.#c.ensureRunning({signal:o}),a(),this.#u.harnessReachable=!0;let A=this.#g==="lark"?this.#e.Domain.Lark:this.#e.Domain.Feishu,r={appId:this.#t,appSecret:this.#r,domain:A},s=IRe(this.#e.defaultHttpInstance,this.#p);s&&(r.httpInstance=s);let g=new this.#e.Client(r);this.#C=g;let c=new tS({client:g,initialText:w("\u5DF2\u8FDE\u63A5 DeepSeek Harness\uFF0C\u6B63\u5728\u601D\u8003\u2026")}),I=new eS({client:g,channel:c,harness:this.#c,state:this.#l,contextEnhancement:this.#i,status:this.#u,allowedSenderOpenIds:new Set(this.#o),botId:this.#A,appId:this.#t,botOpenId:this.#a,groupResponseMode:this.#n,repair:this.#E,replyTimeoutMs:this.#I,signal:o,logger:this.#d});this.#f=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.#u.cardActionsReceived+=1,this.#u.lastCardActionAt=new Date().toISOString(),this.#R(_)||I.onCardAction(_))}}),B,f,Q=new Promise((_,T)=>{let R=!1,F=()=>{f(i())},j=(q,z)=>{R||(R=!0,clearTimeout(L),o.removeEventListener("abort",F),q(z))},L=setTimeout(()=>{j(T,new Error(`Feishu WebSocket handshake timed out after ${this.#s}ms`))},this.#s);B=()=>{j(_)},f=q=>{j(T,q)},o.addEventListener("abort",F,{once:!0}),o.aborted&&F()});Q.catch(()=>{});let y=new this.#e.WSClient({...r,...this.#h?{agent:this.#h}:{},loggerLevel:this.#e.LoggerLevel.info,handshakeTimeoutMs:this.#s,onReady:()=>{e()&&(this.#u.feishuLongConnectionState="connected",this.#u.ready=!0,this.#u.lastError=null,B())},onError:_=>{e()&&(this.#u.feishuLongConnectionState="failed",this.#u.ready=!1,this.#u.lastError=_?.message??String(_),this.#d.error("[dsh-feishu] Feishu long connection failed:",this.#u.lastError),f(_))},onReconnecting:()=>{e()&&(this.#u.feishuLongConnectionState="reconnecting",this.#u.ready=!1)},onReconnected:()=>{e()&&(this.#u.feishuLongConnectionState="connected",this.#u.ready=!0,this.#u.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.#u.ready=!1,this.#u.feishuLongConnectionState="failed",this.#u.lastError=A?.message??String(A),await this.#M({preserveError:!0,abortController:t})),A}}async beginCardActionProbe({expectedOperatorOpenId:t,timeoutMs:o=9e4}={}){if(!this.#u.ready||!this.#C)throw bd("card_action_probe_unavailable","\u98DE\u4E66\u673A\u5668\u4EBA\u5C1A\u672A\u8FDE\u63A5");let i=yn(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=rRe().replaceAll("-",""),a;try{a=await this.#C.im.v1.message.create({params:{receive_id_type:"open_id"},data:{receive_id:i,msg_type:"interactive",content:wW(e)}})}catch{throw this.#D(i,w(Wv),"failure"),bd("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.#D(i,w(Wv),"failure"),bd("card_action_probe_send_failed","\u65E0\u6CD5\u53D1\u9001\u98DE\u4E66\u5361\u7247\u56DE\u8C03\u6D4B\u8BD5");let A=yn(a?.data?.message_id)??yn(a?.message_id);if(!A)throw this.#D(i,w(Wv),"failure"),bd("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.#m.get(A);!c||c.nonce!==e||(this.#m.delete(A),this.#D(i,w(oRe),"timeout"),s(bd("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.#m.set(A,{messageId:A,nonce:e,expectedOperatorOpenId:i,timeout:g,resolve:r,reject:s})})}#R(t){let o=yn(t?.context?.open_message_id);if(!o)return!1;let i=this.#m.get(o);if(!i)return!1;let e=t?.action?.value,a=gRe(t);return e?.action!=="repair_verify"||e?.nonce!==i.nonce||a!==i.expectedOperatorOpenId?!1:(clearTimeout(i.timeout),this.#m.delete(o),this.#u.cardActionProbesVerified+=1,this.#D(a,w(iRe),"success").finally(()=>{i.resolve({verified:!0,messageId:o,operatorOpenId:a})}),!0)}#D(t,o,i){let e=this.#C;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.#u.ready||!this.#C){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.#C.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.#o.find(e=>e!=="*");return i?(await o("open_id",i,t),{sent:!0}):Xg({state:this.#l,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 lr(w("\u98DE\u4E66\u673A\u5668\u4EBA"));await o("chat_id",A,a)}})}async sendProactiveText(t,o,{signal:i}={}){if(!this.#u.ready||!this.#C){let r=new Error("\u98DE\u4E66\u673A\u5668\u4EBA\u5C1A\u672A\u8FDE\u63A5");throw r.code="bot-not-connected",r}let e=t?.kind==="user"?"open_id":t?.kind==="group"?"chat_id":null,a=t?.kind==="user"?yn(t?.route?.openId):t?.kind==="group"?yn(t?.route?.chatId):null;if(!e||!a){let r=new TypeError("Invalid Feishu proactive delivery target");throw r.code="invalid-target",r}i?.throwIfAborted();let A=await this.#C.im.v1.message.create({params:{receive_id_type:e},data:{receive_id:a,msg_type:"text",content:JSON.stringify({text:o})}});if(A?.code&&A.code!==0){let r=new Error(`Feishu proactive delivery failed: ${A.msg||A.code}`);throw r.code="target-rejected",r}return{sent:!0}}stop(t={}){if(this.#S)return this.#S;let o;return o=this.#w(t).finally(()=>{this.#S===o&&(this.#S=null)}),this.#S=o,o}async#w({preserveError:t=!1}={}){let o=this.#Q;this.#Q===o&&(this.#Q=null),o?.abort(new DOMException("Feishu runtime stopped","AbortError"));let i=this.#y;return i&&await i.catch(()=>{}),this.#M({preserveError:t,abortController:o})}async#M({preserveError:t=!1,abortController:o}={}){let i=t?this.#u.lastError:null;this.#Q===o&&(this.#Q=null),o?.abort(new DOMException("Feishu runtime stopped","AbortError"));for(let A of this.#m.values())clearTimeout(A.timeout),this.#D(A.expectedOperatorOpenId,w(nRe),"abort"),A.reject(bd("abort","\u98DE\u4E66\u8FD0\u884C\u65F6\u5DF2\u505C\u6B62"));this.#m.clear(),this.#u.ready=!1;let e=this.#B;this.#B=null,e?.close({force:!0});let a=this.#f;return this.#f=null,a&&await a.waitForIdle(),this.#C=null,this.#u.feishuLongConnectionState=t?"failed":"idle",this.#u.lastError=i,this.status}};var aS=class extends pr{constructor(t){super({...t,rpcIdPrefix:"feishu",logPrefix:"dsh-feishu"})}};import{createHash as pRe}from"node:crypto";import{mkdir as dRe,readFile as hRe,rename as ERe,unlink as CRe,writeFile as uRe}from"node:fs/promises";import{dirname as BRe}from"node:path";var nS="DSH_FEISHU_APP_SECRET";function ps(n){return typeof n=="string"&&n.trim()?n.trim():null}function JW(n){let t=ps(n);return t&&/^[A-Za-z0-9_-]{1,128}$/.test(t)?t:null}function qW(n){return`bot_${pRe("sha256").update(n).digest("hex").slice(0,24)}`}function fRe(n){let t=Array.isArray(n.ownerOpenIds)?n.ownerOpenIds:[n.ownerOpenId];return[...new Set(t.map(ps).filter(Boolean))]}function iS(n,{legacy:t=!1}={}){if(!n||typeof n!="object")return null;let o=ps(n.appId),i=fRe(n);if(!o||i.length===0)return null;let e=JW(n.id)??(t?qW(o):null),a=ps(n.secretRef)??(t?nS: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:ps(n.botName),botOpenId:ps(n.botOpenId),activated:n.activated??null,groupResponseMode:ro(n.groupResponseMode),groupMessagePermissionGranted:n.groupMessagePermissionGranted===!0,deletionPending:n.deletionPending===!0,connectedAt:ps(n.connectedAt),createdAt:ps(n.createdAt)??ps(n.connectedAt)})}function QRe(n){if(!n||typeof n!="object")return null;if(n.version===2&&Array.isArray(n.bots)){let o=n.bots.map(A=>iS(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=iS(n,{legacy:!0});return t?{value:Object.freeze({version:2,bots:Object.freeze([t])}),migrated:!0}:null}var oS=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 hRe(this.#e,"utf8")),o=QRe(t);if(!o)throw new Error("dsh-feishu config is incomplete or invalid");this.#A=o.value,o.migrated&&await this.#a(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=qW(ps(o.appId)??"invalid")),o.secretRef||(o.secretRef=nS);let i=iS(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=iS(t);if(!o)throw new Error("Refusing to persist incomplete dsh-feishu bot configuration");return this.#g(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(!JW(t))throw new TypeError("Invalid Feishu bot id");return this.#g(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 CRe(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.#a(o),this.#A=o});this.#t=i.then(()=>{},()=>{}),await i}async#g(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.#a(a),this.#A=a});return this.#t=i.then(()=>{},()=>{}),await i,o}async#a(t){await dRe(BRe(this.#e),{recursive:!0,mode:448});let o=`${this.#e}.tmp`;await uRe(o,`${JSON.stringify(t,null,2)} -`,{encoding:"utf8",mode:384}),await ERe(o,this.#e)}};import{randomUUID as $W}from"node:crypto";var Zv=new Set(["starting","qr_ready","polling","slow_down","domain_switched","saving"]),yRe=new Set(["polling","slow_down","domain_switched"]),Ri=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 zW(n){return["access_denied","expired_token","abort"].includes(n?.code)?n.code:"registration_failed"}function Xv(n){let t=zW(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 mRe(n){let t=Number(n);if(!Number.isFinite(t)||t<=0)throw new TypeError("registerApp onQRCodeReady returned an invalid expireIn");return t}function SRe(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 Qg=class{#e;#A;#t;#r;#g;#a=0;#n=null;#o;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.#g=a,this.#o=this.#l(null,Ri.IDLE)}start(t={}){if(t===null||typeof t!="object"||Array.isArray(t))throw new TypeError("Registration options must be an object");this.#B();let o={id:++this.#a,controller:new AbortController,qrCodeUrl:null,expiresAt:null,pollIntervalSeconds:null,expiryTimer:null};this.#n=o,this.#o=this.#l(o,Ri.STARTING);let i={...t,signal:o.controller.signal,onQRCodeReady:a=>this.#I(o,a),onStatusChange:a=>this.#s(o,a)};return Promise.resolve().then(()=>this.#e(i)).then(a=>this.#p(o,a),a=>this.#h(o,a)),this.status()}status(){this.#d();let t={...this.#o};t.error&&(t.error={...t.error});let o=this.#n;return o&&o.expiresAt!==null&&Zv.has(t.state)&&(t.remainingSeconds=Math.max(0,Math.ceil((o.expiresAt-this.#t())/1e3))),t}cancel(){let t=this.#n;return t?(this.#C(t,Ri.CANCELLED,{error:{code:"abort",message:"Registration was cancelled."}}),t.controller.abort(),this.status()):this.status()}#c(t){return this.#n===t}#l(t,o,i={}){let e={state:o,attempt:t?.id??this.#a,updatedAt:this.#t(),...i};return t?.qrCodeUrl&&Zv.has(o)&&(e.qrCodeUrl=t.qrCodeUrl,e.expiresAt=t.expiresAt),t?.pollIntervalSeconds!==null&&Zv.has(o)&&(e.pollIntervalSeconds=t.pollIntervalSeconds),e}#i(t,o,i={}){this.#c(t)&&(this.#o=this.#l(t,o,i))}#I(t,o){if(!this.#c(t))return;if(typeof o?.url!="string"||!o.url)throw new TypeError("registerApp onQRCodeReady returned an invalid URL");let i=mRe(o.expireIn);t.qrCodeUrl=o.url,t.expiresAt=this.#t()+i*1e3,this.#f(t),t.expiryTimer=this.#r(()=>this.#E(t),i*1e3),t.expiryTimer?.unref?.(),this.#i(t,Ri.QR_READY)}#s(t,o){!this.#c(t)||!yRe.has(o?.status)||(o.status===Ri.SLOW_DOWN&&Number.isFinite(Number(o.interval))&&(t.pollIntervalSeconds=Number(o.interval)),this.#i(t,o.status))}async#p(t,o){if(!this.#c(t))return;let i=o?.client_id,e=o?.client_secret;if(typeof i!="string"||!i||typeof e!="string"||!e){this.#C(t,Ri.ERROR,{error:{code:"invalid_credentials",message:"Feishu registration returned invalid credentials."}});return}let a;try{a=SRe(o.user_info)}catch{this.#C(t,Ri.ERROR,{error:{code:"invalid_credentials",message:"Feishu registration returned invalid credentials."}});return}this.#f(t),t.qrCodeUrl=null,t.expiresAt=null,t.pollIntervalSeconds=null,this.#i(t,Ri.SAVING);try{await this.#A({client_id:i,client_secret:e,user_info:a})}catch{this.#c(t)&&this.#C(t,Ri.ERROR,{error:{code:"credentials_callback_failed",message:"Unable to store the Feishu credentials."}});return}this.#c(t)&&this.#C(t,Ri.SUCCEEDED)}#h(t,o){if(!this.#c(t))return;let i=zW(o);if(i==="expired_token"){this.#C(t,Ri.EXPIRED,{error:Xv(o)});return}if(i==="abort"){this.#C(t,Ri.CANCELLED,{error:Xv(o)});return}this.#C(t,Ri.ERROR,{error:Xv(o)})}#d(){let t=this.#n;t&&t.expiresAt!==null&&this.#t()>=t.expiresAt&&this.#E(t)}#E(t){this.#c(t)&&(this.#C(t,Ri.EXPIRED,{error:{code:"expired_token",message:"The registration QR code expired."}}),t.controller.abort())}#C(t,o,i={}){this.#c(t)&&(this.#f(t),this.#o=this.#l(t,o,i),this.#n=null)}#f(t){t.expiryTimer!==null&&(this.#g(t.expiryTimer),t.expiryTimer=null)}#B(){let t=this.#n;t&&(this.#f(t),this.#n=null,t.controller.abort())}};var wRe="card.action.trigger",DRe="im:message:readonly",ORe="im:resource",uu="callback_repair";function bRe(n){return n==="lark"?"accounts.larksuite.com":"accounts.feishu.cn"}function MRe(n){return n==="lark"?"open.larksuite.com":"open.feishu.cn"}function $v(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!==MRe(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 _Re(n,t,o="feishu"){return $v(n,t,o,"Feishu callback repair")}var sS=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 Qg({registerApp:a=>t({...a,onQRCodeReady:A=>{_Re(A?.url,this.#A,this.#t),a.onQRCodeReady(A)}}),onCredentials:o})}start(){return this.#e.start({source:"deepseek-harness-card-action-repair",domain:bRe(this.#t),appId:this.#A,addons:{preset:!1,scopes:{tenant:[DRe,ORe]},callbacks:{items:[wRe]}}})}status(){return this.#e.status()}cancel(){return this.#e.cancel()}};var TRe="im:message.group_msg",cS="group_message_permission";function NRe(n){return n==="lark"?"accounts.larksuite.com":"accounts.feishu.cn"}function RRe(n,t,o="feishu"){return $v(n,t,o,"Feishu group message permission update")}var gS=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 Qg({registerApp:a=>t({...a,onQRCodeReady:A=>{RRe(A?.url,this.#A,this.#t),a.onQRCodeReady(A)}}),onCredentials:o})}start(){return this.#e.start({source:"deepseek-harness-group-message-permission",domain:NRe(this.#t),appId:this.#A,addons:{preset:!1,scopes:{tenant:[TRe]}}})}status(){return this.#e.status()}cancel(){return this.#e.cancel()}};var VW=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 eP=new Set(["starting","qr_ready","polling","slow_down","domain_switched"]),IS=new Set([...eP,"saving"]),WW=new Set([uu,cS]),ZW="*",kRe=12e4,vRe=6e5;function e6(){return{ready:!1,feishuLongConnectionState:"idle",harnessReachable:!1}}function Bu(n){return n?n.status:e6()}function fu(n){return n.ready===!0&&n.feishuLongConnectionState==="connected"&&n.harnessReachable===!0}function A6(n){return n.length>12?`${n.slice(0,8)}\u2022\u2022\u2022\u2022${n.slice(-4)}`:"cli_\u2022\u2022\u2022\u2022"}function PRe(n){return{name:n.botName,appIdMasked:A6(n.appId),activated:n.activated,domain:n.domain}}function GRe({connected:n,error:t,connection:o}){return n?"connected":t||o.feishuLongConnectionState==="failed"?"error":"disconnected"}function FRe(){return`bot_${$W().replaceAll("-","")}`}function LRe(){return`reg_${$W().replaceAll("-","")}`}function XW(n){return`DSH_FEISHU_APP_SECRET_${n.slice(4).toUpperCase()}`}function lS(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:ro(n.groupResponseMode),groupMessagePermissionGranted:n.groupMessagePermissionGranted===!0,deletionPending:n.deletionPending===!0,connectedAt:n.connectedAt??null,createdAt:n.createdAt??null})}function pS(n){return typeof n=="string"&&n.trim()?n.trim():null}var Qu=class{#e;#A;#t;#r;#g;#a;#n;#o;#c=new Map;#l=new Map;#i=new Map;#I=new Map;#s=new Map;#p=null;#h=Promise.resolve();#d=new Map;#E=1;#C;#f=!1;constructor({registerApp:t,verifyApp:o,credentials:i,configStore:e,createRuntime:a,deleteState:A=async()=>{},createBotId:r=FRe,createRegistrationId:s=LRe,callbackProbeTimeoutMs:g=kRe}){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>vRe)throw new TypeError("callbackProbeTimeoutMs must be between 1 and 600000ms");this.#e=t,this.#A=o,this.#t=i,this.#r=e,this.#g=a,this.#a=A,this.#n=r,this.#o=s,this.#C=g}async initialize(){if(this.#f)return this.status();let t=this.#r.list(),o=!1;return await Promise.allSettled(t.map(i=>this.#T(i.id,async()=>{let e=Bu(this.#c.get(i.id));if(fu(e)||e.feishuLongConnectionState==="connecting"||e.feishuLongConnectionState==="reconnecting")return;if(o=!0,i.deletionPending){this.#l.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.#l.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.#l.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.#b(i,a.value),this.#l.delete(i.id)}catch{this.#l.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.#_();let t=this.#o();if(typeof t!="string"||!/^[A-Za-z0-9_-]{1,128}$/.test(t)||this.#i.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 Qg({registerApp:this.#e,onCredentials:i=>this.#L(()=>this.#u(o,i))}),this.#i.set(t,o),this.#p=t,this.#U(),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:[...VW]},events:{items:{tenant:["im.message.receive_v1"]}},callbacks:{items:["card.action.trigger"]}}}),this.#k(),this.registrationStatus(t)}startCallbackRepair(t,{actorOpenId:o,chatId:i}={}){this.#_();let e=this.#P(t);if(e.deletionPending)throw new Error("Cannot repair a Feishu bot pending deletion");let a=this.#I.get(t),A=a?this.#i.get(a):null;if(A&&IS.has(A.manager.status().state)){if(A.operation!==uu)throw new Error("Another Feishu app update is already active for this bot");return this.registrationStatus(A.id)}this.#I.delete(t);let r=this.#o();if(typeof r!="string"||!/^[A-Za-z0-9_-]{1,128}$/.test(r)||this.#i.has(r))throw new Error("Registration id generator returned an invalid or duplicate id");let s={id:r,operation:uu,manager:null,botId:t,createdNew:!1,cancelled:!1,remoteCommitted:!1,processing:null,publicError:null,stage:"authorizing",target:structuredClone(e),targetFingerprint:lS(e),initiator:{actorOpenId:pS(o),chatId:pS(i)}};return s.manager=new sS({registerApp:this.#e,appId:e.appId,domain:e.domain,onCredentials:g=>{s.remoteCommitted=!0;let I=this.#Q(s,g).finally(()=>{s.processing===I&&(s.processing=null)});return s.processing=I,I}}),this.#i.set(r,s),this.#I.set(t,r),this.#p=r,this.#U(),s.manager.start(),this.#k(),this.registrationStatus(r)}startGroupMessagePermission(t){this.#_();let o=this.#P(t);if(o.deletionPending)throw new Error("Cannot update permissions for a Feishu bot pending deletion");let i=this.#I.get(t),e=i?this.#i.get(i):null;if(e&&IS.has(e.manager.status().state)){if(e.operation!==cS)throw new Error("Another Feishu app update is already active for this bot");return this.registrationStatus(e.id)}this.#I.delete(t);let a=this.#o();if(typeof a!="string"||!/^[A-Za-z0-9_-]{1,128}$/.test(a)||this.#i.has(a))throw new Error("Registration id generator returned an invalid or duplicate id");let A={id:a,operation:cS,manager:null,botId:t,createdNew:!1,cancelled:!1,remoteCommitted:!1,processing:null,publicError:null,stage:"authorizing",target:structuredClone(o),targetFingerprint:lS(o),initiator:{actorOpenId:null,chatId:null}};return A.manager=new gS({registerApp:this.#e,appId:o.appId,domain:o.domain,onCredentials:r=>{A.remoteCommitted=!0;let g=this.#S(A,r).finally(()=>{A.processing===g&&(A.processing=null)});return A.processing=g,g}}),this.#i.set(a,A),this.#I.set(t,a),this.#p=a,this.#U(),A.manager.start(),this.#k(),this.registrationStatus(a)}hasRegistration(t){return this.#i.has(t)}registrationStatus(t){let o=this.#i.get(t);return o?this.#B({registration:o,selectedBotId:o.botId}):null}async cancelRegistration(t=this.#p){let o=this.#i.get(t);if(!o)return this.status();let i=o.manager.status().state;return WW.has(o.operation)&&i==="saving"?this.registrationStatus(t):IS.has(i)?(o.cancelled=!0,o.manager.cancel(),await this.#L(async()=>{o.createdNew&&o.botId&&this.#s.get(o.botId)===o.id&&this.#r.getBot(o.botId)&&await this.#T(o.botId,()=>this.#w(o.botId))}),this.#k(),this.registrationStatus(t)??this.status()):this.registrationStatus(t)}status(t){return this.#B({registration:this.#i.get(this.#p)??null,selectedBotId:t})}async bindCredentials({appId:t,appSecret:o,domain:i="feishu"}={}){this.#_();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.#L(async()=>{this.#_();let r=await this.#A({appId:e,appSecret:a,domain:A});this.#_();let s=this.#r.list().find(f=>f.appId===e),g=s?.id??this.#n();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??XW(g),I=await this.#t.resolve(c).catch(()=>{}),d={...s,id:g,appId:e,secretRef:c,ownerOpenIds:s?.ownerOpenIds?.length?s.ownerOpenIds:[ZW],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.#M(c,I),f}return await this.#T(g,async()=>{try{await this.#b(B,a),this.#l.delete(g)}catch{this.#l.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.#_(),this.#T(t,async()=>{let o=this.#P(t);if(o.deletionPending)return this.#l.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(fu(Bu(this.#c.get(t))))return this.status(t);let i;try{i=await this.#t.resolve(o.secretRef)}catch{i=null}if(!i?.value)return this.#l.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.#b(o,i.value),this.#l.delete(t)}catch{this.#l.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.#_(),this.#T(t,async()=>{let o=this.#P(t),i=this.#c.get(t);if(!fu(Bu(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(ba(`${o.botName}\uFF08${A6(o.appId)}\uFF09`,"\u98DE\u4E66\u673A\u5668\u4EBA"))})}async sendProactiveText(t,o,i,e={}){return this.#_(),this.#T(t,async()=>{this.#P(t);let a=this.#c.get(t);if(!fu(Bu(a))||typeof a.sendProactiveText!="function"){let A=new Error("\u98DE\u4E66\u673A\u5668\u4EBA\u5C1A\u672A\u8FDE\u63A5");throw A.code="bot-not-connected",A}return a.sendProactiveText(o,i,e)})}async disconnectBot(t){return this.#_(),this.#T(t,async()=>(this.#P(t),await this.#D(t),this.#l.delete(t),this.#k(),this.status(t)))}async updateGroupResponseMode(t,o){if(this.#_(),!zm(o))throw new TypeError("Invalid Feishu group response mode");return this.#L(()=>this.#T(t,async()=>{let i=this.#P(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.#c.get(t)?.setGroupResponseMode?.(e.groupResponseMode),this.#k(),this.status(t)}))}async deleteBot(t){return this.#_(),this.#L(()=>this.#T(t,async()=>(this.#P(t),await this.#w(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.#f)return;this.#f=!0;let t=[];for(let o of this.#i.values()){let i=o.manager.status().state;WW.has(o.operation)&&i==="saving"?(o.manager.cancel(),o.processing&&t.push(o.processing)):IS.has(i)&&(o.cancelled=!0,o.manager.cancel())}await this.#h,await Promise.allSettled([...this.#d.values()]),await Promise.allSettled([...this.#c.keys()].map(o=>this.#D(o))),await Promise.allSettled(t),await this.#h,await Promise.allSettled([...this.#d.values()]),await Promise.allSettled([...this.#c.keys()].map(o=>this.#D(o)))}#B({registration:t,selectedBotId:o}={}){let i=this.#r.list().map(I=>{let d=Bu(this.#c.get(I.id)),B=fu(d),f=this.#l.get(I.id)??null;return{botId:I.id,phase:GRe({connected:B,error:f,connection:d}),connected:B,configured:!0,groupResponseMode:ro(I.groupResponseMode),groupMessagePermissionGranted:I.groupMessagePermissionGranted===!0,bot:PRe(I),connection:d,lastMessageError:Vr(d.lastMessageError),error:f}}),e=t?this.#y(t):{state:"idle",attempt:0,updatedAt:Date.now()},a=eP.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.#E,phase:c,connected:s?.connected??!1,configured:i.length>0,bot:s?.bot??null,connection:s?.connection??e6(),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#S(t,o){let i=o.client_id,e=o.client_secret,a=pS(o.user_info?.open_id),A=o.user_info?.tenant_brand,r=t.target;if(t.cancelled)throw this.#m(t,"abort","Group message permission update was cancelled before local activation.");if(i!==r.appId)throw this.#m(t,"repair_app_mismatch","Feishu returned credentials for a different app.");if(!a)throw this.#m(t,"repair_owner_missing","Feishu returned no permission operator identity.");if(A!==void 0&&A!==r.domain)throw this.#m(t,"repair_domain_mismatch","Feishu returned credentials for a different account domain.");if(!r.ownerOpenIds.includes(ZW)&&!r.ownerOpenIds.includes(a))throw this.#m(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.#m(t,"repair_credentials_invalid","Feishu could not verify the updated app credentials.",g)}if(r.botOpenId&&s?.openId!==r.botOpenId)throw this.#m(t,"repair_bot_mismatch","The updated Feishu app belongs to a different bot identity.");await this.#L(()=>this.#T(t.botId,async()=>{let g=this.#r.getBot(t.botId);if(!g||g.deletionPending||lS(g)!==t.targetFingerprint)throw this.#m(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.#m(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.#m(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.#m(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.#m(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.#b(I,e)}catch(d){throw this.#l.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.#m(t,"group_message_permission_connection_failed","The permission was accepted, but the Feishu runtime could not restart.",d)}this.#l.delete(t.botId),t.stage="verified",t.publicError=null,this.#k()}))}async#Q(t,o){let i=o.client_id,e=o.client_secret,a=pS(o.user_info?.open_id),A=o.user_info?.tenant_brand,r=t.target;if(t.cancelled)throw this.#m(t,"abort","Callback repair was cancelled before local activation.");if(i!==r.appId)throw this.#m(t,"repair_app_mismatch","Feishu returned credentials for a different app.");if(!a)throw this.#m(t,"repair_owner_missing","Feishu returned no repair operator identity.");if(A!==void 0&&A!==r.domain)throw this.#m(t,"repair_domain_mismatch","Feishu returned credentials for a different account domain.");t.stage="verifying_identity";let s;try{s=await this.#A({appId:i,appSecret:e,domain:r.domain})}catch(c){throw this.#m(t,"repair_credentials_invalid","Feishu could not verify the repaired app credentials.",c)}if(r.botOpenId&&s?.openId!==r.botOpenId)throw this.#m(t,"repair_bot_mismatch","The repaired Feishu app belongs to a different bot identity.");let g=await this.#L(()=>this.#T(t.botId,async()=>{let c=this.#r.getBot(t.botId);if(!c||c.deletionPending||lS(c)!==t.targetFingerprint)throw this.#m(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.#m(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.#m(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.#m(t,"credential_state_unknown","The repaired Feishu credential could not be confirmed after writing.")}let B;t.stage="restarting";try{await this.#b(c,e),B=this.#c.get(t.botId)}catch(f){throw this.#l.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.#m(t,"repair_connection_failed","The repaired Feishu runtime could not be started.",f)}if(!B)throw this.#m(t,"repair_connection_failed","The repaired Feishu runtime is unavailable.");return this.#l.delete(t.botId),this.#k(),B}));if(typeof g.beginCardActionProbe!="function")throw this.#m(t,"card_action_probe_unavailable","The Feishu runtime cannot verify card callbacks.");t.stage="awaiting_callback";try{if((await g.beginCardActionProbe({expectedOperatorOpenId:t.initiator.actorOpenId??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.#m(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()}#m(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#u(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.#n();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??XW(g),I=this.#s.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.#s.set(g,t.id)}catch(Q){try{await this.#M(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.#w(g)):(await this.#r.saveBot(s),await this.#M(c,d),I?this.#s.set(g,I):this.#s.delete(g)),new Error("Registration was cancelled");let f=!1;try{if(await this.#T(g,()=>this.#b(B,e)),t.cancelled)throw t.createdNew?await this.#T(g,()=>this.#w(g)):(await this.#r.saveBot(s),await this.#M(c,d),I?this.#s.set(g,I):this.#s.delete(g),d?.value&&!s.deletionPending?await this.#T(g,()=>this.#b(s,d.value)):await this.#T(g,()=>this.#D(g))),f=!0,new Error("Registration was cancelled");this.#l.delete(g),this.#k()}catch(Q){if(t.cancelled)throw!f&&t.createdNew&&this.#r.getBot(g)?await this.#T(g,()=>this.#w(g)):!f&&s&&(await this.#r.saveBot(s),await this.#M(c,d),I?this.#s.set(g,I):this.#s.delete(g),!this.#f&&d?.value&&!s.deletionPending?await this.#T(g,()=>this.#b(s,d.value)):await this.#T(g,()=>this.#D(g))),this.#k(),Q;if(s&&d?.value)try{throw await this.#r.saveBot(s),await this.#M(c,d),I?this.#s.set(g,I):this.#s.delete(g),s.deletionPending?(await this.#T(g,()=>this.#D(g)),this.#l.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.#b(s,d.value)),this.#l.delete(g)),this.#k(),Q}catch(y){throw y===Q?Q:(this.#l.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.#l.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#b(t,o){await this.#D(t.id);let i=await this.#g({botId:t.id,config:t,appSecret:o,repair:this.#R(t.id)});this.#c.set(t.id,i);try{await i.start()}catch(e){throw this.#c.get(t.id)===i&&this.#c.delete(t.id),await i.stop({preserveError:!0}).catch(()=>{}),e}}#R(t){let o=i=>{let e=this.#i.get(i);return e?.operation===uu&&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#D(t){let o=this.#c.get(t);this.#c.delete(t),o&&await o.stop()}async#w(t){let o=this.#r.getBot(t);if(o){o.deletionPending||(o=await this.#r.saveBot({...o,deletionPending:!0})),await this.#D(t);try{await this.#t.unset(o.secretRef)}catch(i){throw this.#l.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.#a({botId:t,config:o})}catch(i){throw this.#l.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.#l.delete(t),this.#s.delete(t)}}async#M(t,o){o?.value?await this.#t.set(t,o.value):await this.#t.unset(t)}#P(t){let o=this.#r.getBot(t);if(!o)throw new Error("Unknown Feishu bot");return o}#_(){if(this.#f)throw new Error("The Feishu controller is closed")}#L(t){let o=this.#h.then(t,t);return this.#h=o.then(()=>{},()=>{}),o}#T(t,o){let e=(this.#d.get(t)??Promise.resolve()).then(o,o),a=e.then(()=>{},()=>{});return this.#d.set(t,a),a.finally(()=>{this.#d.get(t)===a&&this.#d.delete(t)}),e}#U(){if(!(this.#i.size<=32))for(let[t,o]of this.#i){if(t===this.#p)continue;let i=o.manager.status().state;if(!eP.has(i)&&i!=="saving"&&this.#i.delete(t),this.#i.size<=32)break}}#k(){this.#E+=1}};function KRe(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 xRe(n,t=o=>new t6.default(o)){let o=KRe(n);return o?t(o):void 0}function YRe(n){let t=mc(n.dshHome??process.env.DSH_HOME??Md(URe(),".dsh")),o=mc(n.dataDir??Md(t,"integrations","dsh-feishu"));return{root:o,config:mc(n.configPath??Md(o,"config.json")),legacyState:mc(n.statePath??Md(o,"state.json")),bots:mc(n.botsDir??Md(o,"bots")),workspaces:mc(n.workspacesPath??Md(o,"workspaces.json"))}}async function AP(n,t={},o={}){if(!n?.credentials)throw new TypeError("dsh-feishu requires ctx.credentials");let i=Aa(n,t),e=o.lark??Lv,a=o.Controller??Qu,A=o.ConfigStore??oS,r=o.StateStore??Jm,s=o.HarnessClient??aS,g=o.FeishuRuntime??rS,c=o.verifyFeishuApp??dW,I=fe=>c({...fe,httpInstance:e.defaultHttpInstance}),d=o.createConnectionSupervisor??Uv,B=typeof n.logger=="function"?n.logger("dsh-feishu"):n.logger??console,f=()=>Ra(n),Q=YRe(t),y=await new A(Q.config).load(),m=mc(t.workspace??process.cwd()),_=o.WorkspaceStore??ea,T=o.workspaces??await new _(Q.workspaces,{defaultWorkspace:m}).load(),R=typeof y.list=="function",F=()=>R?y.list():[],j=F();R&&await T.reconcile(j.map(fe=>fe.id)),await Promise.all(j.map(fe=>T.ensure(fe.id,{defaultAgentPreset:t.agentPreset})));let L=typeof y.removeBot=="function"?Pa(y,{workspaces:T,method:"removeBot",botIdFromRemoved:fe=>fe.id,saveMethod:"saveBot",botIdFromSave:fe=>fe?.id}):y,q=new Map,z=fe=>!fe.id||!fe.secretRef||fe.secretRef===nS?Q.legacyState:mc(Q.bots,fe.id,"state.json"),K=async fe=>{let Se=fe.id??"__legacy__",Ke=q.get(Se);return Ke||(Ke=await new r(z(fe)).load(),q.set(Se,Ke)),Ke},G=async fe=>{let Se=F().find(Ke=>Ke.id===fe);if(!Se)throw new Error("Unknown Feishu bot");return K(Se)},J=Ua(n,o.commandExecutor),{controlExecutor:U,sessionMaintenanceExecutor:N,fileIngressExecutor:k}=Ha(n,{controlExecutor:o.controlExecutor,sessionMaintenanceExecutor:o.sessionMaintenanceExecutor,fileIngressExecutor:o.fileIngressExecutor}),V=new s({...i,workspace:m,autostart:!1,dshBin:t.dshBin??"dsh",...J?{commandExecutor:J}:{},...U?{controlExecutor:U}:{},...N?{sessionMaintenanceExecutor:N}:{},...k?{fileIngressExecutor:k}:{}}),te=o.proxyEnv??process.env,ie=xRe(te,o.createProxyAgent),we=new a({registerApp:fe=>e.registerApp(fe),verifyApp:I,credentials:n.credentials,configStore:L,createRuntime:async({botId:fe,config:Se,appSecret:Ke,repair:rA})=>{let ve=await K(Se),aA=fe??Se.id??Se.appId;await T.ensure(aA,{defaultAgentPreset:t.agentPreset});let Ce=Ga(V,{botId:aA,workspaces:T,state:ve,agentPresetCatalog:f});return new g({lark:e,botId:aA,repair:rA,appId:Se.appId,appSecret:Ke,domain:Se.domain,botOpenId:Se.botOpenId,groupResponseMode:Se.groupResponseMode,ownerOpenIds:Se.ownerOpenIds??[Se.ownerOpenId],harness:Ce.harness,state:Ce.state,contextEnhancement:{botId:aA,getSettings:()=>T.contextEnhancementFor(aA)},replyTimeoutMs:t.replyTimeoutMs??6e5,...ie?{wsAgent:ie}:{},logger:{error:(...he)=>B.error?.(`[${fe??Se.id}]`,...he),warn:(...he)=>B.warn?.(`[${fe??Se.id}]`,...he),info:(...he)=>B.info?.(`[${fe??Se.id}]`,...he),debug:(...he)=>B.debug?.(`[${fe??Se.id}]`,...he)}})},deleteState:async({botId:fe,config:Se})=>{q.delete(fe);try{await HRe(z(Se))}catch(Ke){if(Ke?.code!=="ENOENT")throw Ke}}}),se=Fa(we,{workspaces:T,stateFor:G,agentPresetCatalog:f}),Ne=d({controller:se,harness:V,logger:B,retryDelaysMs:t.retryDelaysMs,healthyIntervalMs:t.healthyIntervalMs}).start();return{controller:se,deliveryAdapter:La({channel:"feishu",workspaces:T,coreController:we,stateFor:G}),ready:Ne.ready,async close(){await Ne.close(),await se.close(),V.stopManagedProcess(),ie?.destroy?.()}}}import gke from"qrcode";var Td=qe(sP(),1);var oke=qe(sP(),1);var nke=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":"Connecting DeepSeek Harness",\u5F53\u524D\u7248\u672C:"Current version","DSH-IM \u66F4\u65B0":"DSH-IM update",\u68C0\u67E5\u66F4\u65B0:"Check for updates",\u91CD\u65B0\u68C0\u67E5:"Check again",\u5237\u65B0\u72B6\u6001:"Refresh status",\u624B\u5DE5\u66F4\u65B0:"Manual update",\u624B\u5DE5\u66F4\u65B0\u547D\u4EE4:"Manual update command",\u590D\u5236\u547D\u4EE4:"Copy command","\u590D\u5236\u4E2D\u2026":"Copying\u2026",\u5DF2\u590D\u5236:"Copied","\u547D\u4EE4\u5DF2\u590D\u5236\u3002":"Command copied.","\u590D\u5236\u5931\u8D25\uFF0C\u8BF7\u9009\u4E2D\u547D\u4EE4\u540E\u6309 Ctrl+C \u6216 \u2318C \u590D\u5236\u3002":"Copy failed. Select the command and press Ctrl+C or \u2318C to copy it.","\u81EA\u52A8\u66F4\u65B0\u5931\u8D25\u53EF\u4EE5\u4F7F\u7528\u547D\u4EE4\u66F4\u65B0\uFF1A":"If the automatic update fails, update with this command:","\u5C1A\u672A\u786E\u8BA4\u76EE\u6807\u7248\u672C\uFF0C\u6B64\u547D\u4EE4\u5B89\u88C5\u6267\u884C\u65F6 npm \u7684 latest \u7248\u672C\u3002":"No target version has been confirmed. This command installs the npm latest version available when you run it.","\u8BF7\u5728\u5F53\u524D Desktop \u7684\u5185\u7F6E\u7EC8\u7AEF\u6267\u884C\uFF0C\u5B8C\u6210\u540E\u624B\u52A8\u91CD\u542F\u3002":"Run this in the current Desktop\u2019s built-in terminal, then restart manually.","\u8BF7\u5728\u8FD0\u884C\u5F53\u524D Harness \u7684\u540C\u4E00\u73AF\u5883\u6267\u884C\uFF0C\u4FDD\u6301 DSH_HOME \u4E00\u81F4\uFF0C\u5B8C\u6210\u540E\u624B\u52A8\u91CD\u542F\u3002":"Run this in the same environment as the current Harness, with the same DSH_HOME, then restart manually.","\u8BF7\u7B49\u5F85\u5F53\u524D\u64CD\u4F5C\u7ED3\u675F\uFF0C\u786E\u8BA4\u6CA1\u6709\u5B89\u88C5\u8FDB\u7A0B\u8FD0\u884C\u540E\u518D\u6267\u884C\u547D\u4EE4\u3002":"Wait for the current operation to finish and confirm no installer is running before using this command.","\u6E90\u7801\u6216\u94FE\u63A5\u5B89\u88C5\u8BF7\u6309\u539F\u5B89\u88C5\u65B9\u5F0F\u66F4\u65B0\uFF0C\u4E0D\u63D0\u4F9B\u8986\u76D6\u6E90\u7801\u7684 npm \u547D\u4EE4\u3002":"Update source or linked installations using their original method. No npm command is provided to overwrite the source.","\u65E0\u6CD5\u5B89\u5168\u751F\u6210\u5F53\u524D profile \u7684\u547D\u4EE4\uFF0C\u8BF7\u5728\u7EC8\u7AEF\u4E2D\u624B\u52A8\u786E\u8BA4 profile \u540E\u66F4\u65B0\u3002":"A safe command cannot be generated for this profile. Confirm the profile in your terminal before updating manually.",\u66F4\u65B0\u81F3:"Update to",\u5B89\u88C5\u66F4\u65B0:"Install update","\u6B63\u5728\u66F4\u65B0\u2026":"Updating\u2026",\u5F85\u624B\u52A8\u91CD\u542F:"Restart needed",\u8FD0\u884C\u7248\u672C:"Running version",\u5DF2\u5B89\u88C5\u7248\u672C:"Installed version","\u76EE\u6807 profile":"Target profile",\u76EE\u6807\u7248\u672C:"Target version",\u65E0\u6CD5\u786E\u8BA4:"Unknown",\u53D1\u73B0\u65B0\u7248\u672C:"Update available",\u5DF2\u662F\u6700\u65B0\u7248\u672C:"Up to date",\u5F53\u524D\u7248\u672C\u65E0\u9700\u66F4\u65B0:"No newer version available","\u5DF2\u83B7\u53D6 npm \u6700\u65B0\u7248\u672C":"Latest npm version retrieved","\u68C0\u67E5 npm \u6700\u65B0\u7248\u672C\uFF0C\u4E0D\u4F1A\u81EA\u52A8\u5B89\u88C5\u3002":"Check the latest npm version. Nothing is installed automatically.","\u6B63\u5728\u4ECE npm \u68C0\u67E5\u6700\u65B0\u7248\u672C\u2026":"Checking npm for the latest version\u2026","\u6B63\u5728\u5B89\u88C5\uFF0C\u8BF7\u7A0D\u5019\u2026":"Installing, please wait\u2026","\u6B63\u5728\u6821\u9A8C\u5B89\u88C5\u7ED3\u679C\u2026":"Verifying the installation\u2026","\u5DF2\u5B89\u88C5\uFF0C\u5F85\u624B\u52A8\u91CD\u542F":"Installed \u2014 manual restart needed",\u66F4\u65B0\u5DF2\u751F\u6548:"Updated version is active",\u66F4\u65B0\u5931\u8D25:"Update failed",\u66F4\u65B0\u8BF7\u6C42\u5931\u8D25:"Update request failed","\u4EC5\u66F4\u65B0 DSH-IM\u3002\u5B89\u88C5\u5B8C\u6210\u540E\u9700\u624B\u52A8\u91CD\u542F\u540E\u53F0\uFF1B\u672C\u529F\u80FD\u4E0D\u4F1A\u81EA\u52A8\u91CD\u542F\u6216\u4E3B\u52A8\u5237\u65B0\u9875\u9762\u3002":"Only DSH-IM will be updated. Restart the backend manually after installation. This feature does not automatically restart it or initiate a page refresh.","\u5F53\u524D\u662F\u6E90\u7801\u6216\u94FE\u63A5\u5B89\u88C5\uFF0C\u53EA\u80FD\u68C0\u67E5\u7248\u672C\uFF1B\u8BF7\u624B\u52A8\u66F4\u65B0\u6E90\u7801\uFF0C\u6216\u8FC1\u79FB\u5230 npm \u5B89\u88C5\u3002":"This is a source or linked installation. You can check versions, but must update the source manually or migrate to an npm installation.","\u65E0\u6CD5\u786E\u8BA4\u5F53\u524D profile\uFF0C\u8BF7\u5728\u5BF9\u5E94\u7684 Harness \u73AF\u5883\u4E2D\u624B\u52A8\u66F4\u65B0\u3002":"The current profile could not be identified. Update manually in the corresponding Harness environment.","\u5F53\u524D\u8FD0\u884C\u73AF\u5883\u4E0D\u652F\u6301\u6309\u94AE\u5B89\u88C5\uFF0C\u8BF7\u624B\u52A8\u66F4\u65B0\u63D2\u4EF6\u3002":"This runtime cannot install through this button. Update the plugin manually.","\u5F53\u524D npm \u6E90\u914D\u7F6E\u4E0E\u5B98\u65B9\u6E90\u4E0D\u4E00\u81F4\uFF0C\u8BF7\u5148\u68C0\u67E5 registry \u914D\u7F6E\u3002":"The npm registry configuration differs from the official registry. Check your registry settings first.","\u5F53\u524D Host \u7684 Node.js \u7248\u672C\u4E0D\u6EE1\u8DB3\u65B0\u7248\u8981\u6C42\uFF0C\u8BF7\u5148\u66F4\u65B0\u8FD0\u884C\u73AF\u5883\u3002":"The Host Node.js version does not meet the new version\u2019s requirements. Update the runtime first.","\u65B0\u7248\u672C\u5DF2\u5B89\u88C5\uFF0C\u8BF7\u5728\u65B9\u4FBF\u65F6\u624B\u52A8\u91CD\u542F\u5F53\u524D Harness \u6216 Desktop\u3002":"The new version is installed. Manually restart this Harness or Desktop when convenient.","\u4E0A\u6B21\u5B89\u88C5\u7ED3\u679C\u65E0\u6CD5\u786E\u8BA4\uFF0C\u8BF7\u5148\u68C0\u67E5\u6B64 profile \u7684\u63D2\u4EF6\u5B89\u88C5\u72B6\u6001\u3002":"The previous installation result is uncertain. Check this profile\u2019s plugin installation first.","\u65E0\u6CD5\u8BBF\u95EE npm \u6216\u8BF7\u6C42\u8D85\u65F6\uFF0C\u8BF7\u7A0D\u540E\u91CD\u65B0\u68C0\u67E5\u3002":"npm is unreachable or the request timed out. Check again later.","npm \u8FD4\u56DE\u7684\u7248\u672C\u4FE1\u606F\u65E0\u6548\uFF0C\u6682\u65F6\u65E0\u6CD5\u66F4\u65B0\u3002":"npm returned invalid release information. Updating is unavailable.","\u7248\u672C\u786E\u8BA4\u5DF2\u8FC7\u671F\uFF0C\u8BF7\u91CD\u65B0\u68C0\u67E5\u540E\u518D\u5B89\u88C5\u3002":"The version confirmation expired. Check again before installing.","\u63D2\u4EF6\u5B89\u88C5\u72B6\u6001\u5DF2\u53D1\u751F\u53D8\u5316\uFF0C\u8BF7\u91CD\u65B0\u68C0\u67E5\u3002":"The plugin installation changed. Check again.","\u6B64 profile \u6B63\u5728\u66F4\u65B0\uFF0C\u8BF7\u7A0D\u540E\u67E5\u770B\u72B6\u6001\u3002":"This profile is already updating. Check its status shortly.","\u5B89\u88C5\u5931\u8D25\uFF0C\u8BF7\u68C0\u67E5\u5F53\u524D\u5B89\u88C5\u72B6\u6001\u540E\u91CD\u8BD5\u3002":"Installation failed. Check the current installation before retrying.","\u5B89\u88C5\u7ED3\u679C\u6821\u9A8C\u5931\u8D25\uFF0C\u8BF7\u624B\u52A8\u68C0\u67E5\u63D2\u4EF6\u7248\u672C\u3002":"Installation verification failed. Check the plugin version manually.","\u65E0\u6CD5\u5B89\u5168\u4FDD\u5B58\u66F4\u65B0\u72B6\u6001\uFF0C\u8BF7\u5148\u68C0\u67E5\u5F53\u524D\u5B89\u88C5\u7ED3\u679C\u3002":"Update state could not be saved safely. Check the current installation result before retrying.","\u4E0A\u6B21\u66F4\u65B0\u5DF2\u4E2D\u65AD\uFF0C\u8BF7\u68C0\u67E5\u5B89\u88C5\u72B6\u6001\u540E\u91CD\u8BD5\u3002":"The previous update was interrupted. Check the installation before retrying.","\u66F4\u65B0\u670D\u52A1\u5DF2\u5173\u95ED\uFF0C\u8BF7\u624B\u52A8\u91CD\u65B0\u6253\u5F00\u8BBE\u7F6E\u9875\u3002":"The update service has closed. Reopen settings manually.","\u66F4\u65B0\u8BF7\u6C42\u65E0\u6548\uFF0C\u8BF7\u91CD\u65B0\u68C0\u67E5\u7248\u672C\u3002":"The update request is invalid. Check the version again.","\u5F53\u524D\u63D2\u4EF6\u5B89\u88C5\u4E0D\u5B8C\u6574\u6216\u4E0E profile \u4E0D\u7B26\uFF0C\u8BF7\u624B\u52A8\u68C0\u67E5\u5B89\u88C5\u914D\u7F6E\u3002":"The plugin installation is incomplete or does not match this profile. Check the installation configuration manually.","\u65E0\u6CD5\u786E\u8BA4\u5F53\u524D npm \u6E90\u914D\u7F6E\uFF0C\u6682\u65F6\u4E0D\u80FD\u5B89\u88C5\u66F4\u65B0\u3002":"The npm registry configuration could not be verified. Installation is unavailable.","\u5B89\u88C5\u8D85\u65F6\uFF0C\u8BF7\u5148\u786E\u8BA4\u5F53\u524D\u5B89\u88C5\u72B6\u6001\uFF0C\u518D\u51B3\u5B9A\u662F\u5426\u91CD\u8BD5\u3002":"Installation timed out. Check the current installation before retrying.","\u66F4\u65B0\u8BF7\u6C42\u5931\u8D25\uFF0C\u8BF7\u91CD\u8BD5\u3002":"The update request failed. Try again.","\u66F4\u65B0\u670D\u52A1\u8FD4\u56DE\u4E86\u65E0\u6CD5\u8BC6\u522B\u7684\u54CD\u5E94\u3002":"The update service returned an unrecognized response.","\u5F53\u524D Host \u4E0D\u652F\u6301\u66F4\u65B0\u63A5\u53E3\uFF0C\u8BF7\u5148\u624B\u52A8\u66F4\u65B0\u63D2\u4EF6\u5E76\u91CD\u542F\u3002":"This Host does not support the update API. Update the plugin manually and restart first.","\u5173\u95ED\u7A97\u53E3\u4E0D\u4F1A\u53D6\u6D88\u5B89\u88C5\u3002\u8BF7\u52FF\u540C\u65F6\u5728\u5176\u4ED6\u7A97\u53E3\u7BA1\u7406\u6B64 profile \u7684\u63D2\u4EF6\u3002":"Closing this window does not cancel installation. Do not manage this profile\u2019s plugins in another window at the same time.","\u9875\u9762\u7248\u672C\u4E0E\u8FD0\u884C\u7248\u672C\u4E0D\u540C\uFF0C\u8BF7\u624B\u52A8\u5237\u65B0\u9875\u9762\uFF1B\u82E5\u4ECD\u4E0D\u4E00\u81F4\uFF0C\u8BF7\u624B\u52A8\u91CD\u542F Harness \u6216 Desktop\u3002":"The page and running versions differ. Refresh the page manually; if they still differ, manually restart Harness or Desktop.","\u8BF7\u5728\u673A\u5668\u4EBA\u7A7A\u95F2\u65F6\u5B89\u88C5\uFF1B\u5B89\u88C5\u4F1A\u4FEE\u6539\u5F53\u524D profile \u7684\u4F9D\u8D56\uFF0C\u5B8C\u6210\u540E\u9700\u624B\u52A8\u91CD\u542F\u3002":"Install while bots are idle. This changes the current profile\u2019s dependencies and requires a manual restart afterward.","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",\u6700\u8FD1\u4E00\u6761\u6D88\u606F\u5904\u7406\u5931\u8D25:"Latest message failed",\u9519\u8BEF\u7801:"Code",\u53C2\u8003\u53F7:"Reference",\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",\u76F4\u63A5\u8F93\u5165\u8DEF\u5F84:"Enter a path directly","\u652F\u6301 Windows \u76D8\u7B26\u3001UNC \u4E0E POSIX \u7EDD\u5BF9\u8DEF\u5F84\u3002":"Supports Windows drives, UNC paths, and POSIX absolute paths.","\u8F93\u5165 Host \u4E0A\u7684\u5B8C\u6574\u7EDD\u5BF9\u8DEF\u5F84":"Enter a full absolute path on the Host",\u524D\u5F80:"Go","\u8BFB\u53D6\u4E2D\u2026":"Loading\u2026","\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",\u4E0A\u4E0B\u6587\u589E\u5F3A:"Context enhancement",\u672A\u5F00\u542F:"Not enabled",\u4EC5\u7FA4\u804A:"Groups only",\u4EC5\u79C1\u804A:"Direct only",\u7FA4\u804A\u548C\u79C1\u804A:"Groups and direct",\u5173\u95ED\u5F39\u7A97:"Close dialog",\u67E5\u770B\u4E0A\u4E0B\u6587\u589E\u5F3A\u8BF4\u660E:"View context enhancement details",\u542F\u7528\u8303\u56F4:"Enable in",\u7FA4\u804A\u4E2D\u542F\u7528:"Enable in group chats",\u79C1\u804A\u4E2D\u542F\u7528:"Enable in direct chats","\uFF08\u5F53\u524D\u6E20\u9053\u4E0D\u652F\u6301\u7FA4\u804A\uFF09":"(This channel does not support group chats)",\u6765\u6E90\u5B57\u6BB5:"Source fields",\u67E5\u770B\u6765\u6E90\u5B57\u6BB5\u8BF4\u660E:"View source field details",\u6E20\u9053:"Channel",\u4F1A\u8BDD\u7C7B\u578B:"Conversation type",\u53D1\u9001\u8005\u6807\u8BC6:"Sender ID",\u53D1\u9001\u8005\u6635\u79F0:"Sender name",\u67E5\u770B\u53D1\u9001\u8005\u6635\u79F0\u5B57\u6BB5\u8BF4\u660E:"View sender name field details","\u8BE5\u5B57\u6BB5\u4E0D\u662F\u6BCF\u4E2A\u6E20\u9053\u90FD\u80FD\u63D0\u4F9B\u3002\u5F53\u524D\u6D88\u606F\u6CA1\u6709\u53D1\u9001\u8005\u6635\u79F0\u65F6\uFF0C\u5373\u4F7F\u5DF2\u9009\u62E9\u8BE5\u5B57\u6BB5\uFF0C \u4E2D\u4E5F\u4F1A\u7701\u7565 senderName\u3002":"This field is not available on every channel. If the current message has no sender name, omits senderName even when the field is selected.",\u673A\u5668\u4EBA\u6807\u8BC6:"Bot ID",\u589E\u5F3A\u63D0\u793A\u8BCD:"Guidance",\u67E5\u770B\u589E\u5F3A\u63D0\u793A\u8BCD\u4F7F\u7528\u8BF4\u660E:"View guidance instructions",\u4F7F\u7528\u8BF4\u660E:"How to use","\u7528\u4E8E\u544A\u8BC9\u6A21\u578B\u5982\u4F55\u4F7F\u7528 \u4E2D\u5DF2\u9009\u62E9\u7684\u6765\u6E90\u5B57\u6BB5\u3002\u53EA\u586B\u5199\u6B63\u6587\uFF0C\u63D2\u4EF6\u4F1A\u81EA\u52A8\u6DFB\u52A0 \u6210\u5BF9\u6807\u7B7E\u3002":"Tell the model how to use the selected fields in . Enter only the body; the plugin adds paired tags.",\u751F\u6548\u89C4\u5219:"Behavior",\u9690\u79C1\u63D0\u793A:"Privacy",\u4F7F\u7528\u793A\u4F8B:"Example","\u4EC5\u4F9D\u636E\u5F53\u524D\u6D88\u606F\u7684 \u4E2D\u5B9E\u9645\u63D0\u4F9B\u7684\u5B57\u6BB5\u7406\u89E3\u6765\u6E90\uFF1B\u6CA1\u6709\u63D0\u4F9B\u7684\u5B57\u6BB5\u4E0D\u8981\u731C\u6D4B\u6216\u8865\u5168\u3002\nconversationType\u662F\u7FA4\u804A\u65F6\u56DE\u590D\u4E25\u8083\u4E00\u70B9\uFF0CconversationType\u662F\u79C1\u804A\u65F6\u56DE\u590D\u4E00\u5B9A\u8981\u5E7D\u9ED8\u641E\u7B11\uFF0C\u50CF\u5468\u661F\u9A70\u7684\u7535\u5F71\u4E00\u6837\u641E\u7B11":`Understand the source only from fields actually present in for the current message; do not guess or fill in missing fields. +`,{encoding:"utf8",mode:384}),await ERe(o,this.#e)}};import{randomUUID as $W}from"node:crypto";var Zv=new Set(["starting","qr_ready","polling","slow_down","domain_switched","saving"]),yRe=new Set(["polling","slow_down","domain_switched"]),Ri=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 zW(n){return["access_denied","expired_token","abort"].includes(n?.code)?n.code:"registration_failed"}function Xv(n){let t=zW(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 mRe(n){let t=Number(n);if(!Number.isFinite(t)||t<=0)throw new TypeError("registerApp onQRCodeReady returned an invalid expireIn");return t}function SRe(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 Qg=class{#e;#A;#t;#r;#g;#a=0;#n=null;#o;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.#g=a,this.#o=this.#l(null,Ri.IDLE)}start(t={}){if(t===null||typeof t!="object"||Array.isArray(t))throw new TypeError("Registration options must be an object");this.#B();let o={id:++this.#a,controller:new AbortController,qrCodeUrl:null,expiresAt:null,pollIntervalSeconds:null,expiryTimer:null};this.#n=o,this.#o=this.#l(o,Ri.STARTING);let i={...t,signal:o.controller.signal,onQRCodeReady:a=>this.#I(o,a),onStatusChange:a=>this.#s(o,a)};return Promise.resolve().then(()=>this.#e(i)).then(a=>this.#p(o,a),a=>this.#h(o,a)),this.status()}status(){this.#d();let t={...this.#o};t.error&&(t.error={...t.error});let o=this.#n;return o&&o.expiresAt!==null&&Zv.has(t.state)&&(t.remainingSeconds=Math.max(0,Math.ceil((o.expiresAt-this.#t())/1e3))),t}cancel(){let t=this.#n;return t?(this.#C(t,Ri.CANCELLED,{error:{code:"abort",message:"Registration was cancelled."}}),t.controller.abort(),this.status()):this.status()}#c(t){return this.#n===t}#l(t,o,i={}){let e={state:o,attempt:t?.id??this.#a,updatedAt:this.#t(),...i};return t?.qrCodeUrl&&Zv.has(o)&&(e.qrCodeUrl=t.qrCodeUrl,e.expiresAt=t.expiresAt),t?.pollIntervalSeconds!==null&&Zv.has(o)&&(e.pollIntervalSeconds=t.pollIntervalSeconds),e}#i(t,o,i={}){this.#c(t)&&(this.#o=this.#l(t,o,i))}#I(t,o){if(!this.#c(t))return;if(typeof o?.url!="string"||!o.url)throw new TypeError("registerApp onQRCodeReady returned an invalid URL");let i=mRe(o.expireIn);t.qrCodeUrl=o.url,t.expiresAt=this.#t()+i*1e3,this.#f(t),t.expiryTimer=this.#r(()=>this.#E(t),i*1e3),t.expiryTimer?.unref?.(),this.#i(t,Ri.QR_READY)}#s(t,o){!this.#c(t)||!yRe.has(o?.status)||(o.status===Ri.SLOW_DOWN&&Number.isFinite(Number(o.interval))&&(t.pollIntervalSeconds=Number(o.interval)),this.#i(t,o.status))}async#p(t,o){if(!this.#c(t))return;let i=o?.client_id,e=o?.client_secret;if(typeof i!="string"||!i||typeof e!="string"||!e){this.#C(t,Ri.ERROR,{error:{code:"invalid_credentials",message:"Feishu registration returned invalid credentials."}});return}let a;try{a=SRe(o.user_info)}catch{this.#C(t,Ri.ERROR,{error:{code:"invalid_credentials",message:"Feishu registration returned invalid credentials."}});return}this.#f(t),t.qrCodeUrl=null,t.expiresAt=null,t.pollIntervalSeconds=null,this.#i(t,Ri.SAVING);try{await this.#A({client_id:i,client_secret:e,user_info:a})}catch{this.#c(t)&&this.#C(t,Ri.ERROR,{error:{code:"credentials_callback_failed",message:"Unable to store the Feishu credentials."}});return}this.#c(t)&&this.#C(t,Ri.SUCCEEDED)}#h(t,o){if(!this.#c(t))return;let i=zW(o);if(i==="expired_token"){this.#C(t,Ri.EXPIRED,{error:Xv(o)});return}if(i==="abort"){this.#C(t,Ri.CANCELLED,{error:Xv(o)});return}this.#C(t,Ri.ERROR,{error:Xv(o)})}#d(){let t=this.#n;t&&t.expiresAt!==null&&this.#t()>=t.expiresAt&&this.#E(t)}#E(t){this.#c(t)&&(this.#C(t,Ri.EXPIRED,{error:{code:"expired_token",message:"The registration QR code expired."}}),t.controller.abort())}#C(t,o,i={}){this.#c(t)&&(this.#f(t),this.#o=this.#l(t,o,i),this.#n=null)}#f(t){t.expiryTimer!==null&&(this.#g(t.expiryTimer),t.expiryTimer=null)}#B(){let t=this.#n;t&&(this.#f(t),this.#n=null,t.controller.abort())}};var wRe="card.action.trigger",DRe="im:message:readonly",ORe="im:resource",uu="callback_repair";function bRe(n){return n==="lark"?"accounts.larksuite.com":"accounts.feishu.cn"}function MRe(n){return n==="lark"?"open.larksuite.com":"open.feishu.cn"}function $v(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!==MRe(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 _Re(n,t,o="feishu"){return $v(n,t,o,"Feishu callback repair")}var sS=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 Qg({registerApp:a=>t({...a,onQRCodeReady:A=>{_Re(A?.url,this.#A,this.#t),a.onQRCodeReady(A)}}),onCredentials:o})}start(){return this.#e.start({source:"deepseek-harness-card-action-repair",domain:bRe(this.#t),appId:this.#A,addons:{preset:!1,scopes:{tenant:[DRe,ORe]},callbacks:{items:[wRe]}}})}status(){return this.#e.status()}cancel(){return this.#e.cancel()}};var TRe="im:message.group_msg",cS="group_message_permission";function NRe(n){return n==="lark"?"accounts.larksuite.com":"accounts.feishu.cn"}function RRe(n,t,o="feishu"){return $v(n,t,o,"Feishu group message permission update")}var gS=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 Qg({registerApp:a=>t({...a,onQRCodeReady:A=>{RRe(A?.url,this.#A,this.#t),a.onQRCodeReady(A)}}),onCredentials:o})}start(){return this.#e.start({source:"deepseek-harness-group-message-permission",domain:NRe(this.#t),appId:this.#A,addons:{preset:!1,scopes:{tenant:[TRe]}}})}status(){return this.#e.status()}cancel(){return this.#e.cancel()}};var VW=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 eP=new Set(["starting","qr_ready","polling","slow_down","domain_switched"]),IS=new Set([...eP,"saving"]),WW=new Set([uu,cS]),ZW="*",kRe=12e4,vRe=6e5;function e6(){return{ready:!1,feishuLongConnectionState:"idle",harnessReachable:!1}}function Bu(n){return n?n.status:e6()}function fu(n){return n.ready===!0&&n.feishuLongConnectionState==="connected"&&n.harnessReachable===!0}function A6(n){return n.length>12?`${n.slice(0,8)}\u2022\u2022\u2022\u2022${n.slice(-4)}`:"cli_\u2022\u2022\u2022\u2022"}function PRe(n){return{name:n.botName,appIdMasked:A6(n.appId),activated:n.activated,domain:n.domain}}function GRe({connected:n,error:t,connection:o}){return n?"connected":t||o.feishuLongConnectionState==="failed"?"error":"disconnected"}function FRe(){return`bot_${$W().replaceAll("-","")}`}function LRe(){return`reg_${$W().replaceAll("-","")}`}function XW(n){return`DSH_FEISHU_APP_SECRET_${n.slice(4).toUpperCase()}`}function lS(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:ro(n.groupResponseMode),groupMessagePermissionGranted:n.groupMessagePermissionGranted===!0,deletionPending:n.deletionPending===!0,connectedAt:n.connectedAt??null,createdAt:n.createdAt??null})}function pS(n){return typeof n=="string"&&n.trim()?n.trim():null}var Qu=class{#e;#A;#t;#r;#g;#a;#n;#o;#c=new Map;#l=new Map;#i=new Map;#I=new Map;#s=new Map;#p=null;#h=Promise.resolve();#d=new Map;#E=1;#C;#f=!1;constructor({registerApp:t,verifyApp:o,credentials:i,configStore:e,createRuntime:a,deleteState:A=async()=>{},createBotId:r=FRe,createRegistrationId:s=LRe,callbackProbeTimeoutMs:g=kRe}){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>vRe)throw new TypeError("callbackProbeTimeoutMs must be between 1 and 600000ms");this.#e=t,this.#A=o,this.#t=i,this.#r=e,this.#g=a,this.#a=A,this.#n=r,this.#o=s,this.#C=g}async initialize(){if(this.#f)return this.status();let t=this.#r.list(),o=!1;return await Promise.allSettled(t.map(i=>this.#T(i.id,async()=>{let e=Bu(this.#c.get(i.id));if(fu(e)||e.feishuLongConnectionState==="connecting"||e.feishuLongConnectionState==="reconnecting")return;if(o=!0,i.deletionPending){this.#l.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.#l.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.#l.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.#b(i,a.value),this.#l.delete(i.id)}catch{this.#l.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.#_();let t=this.#o();if(typeof t!="string"||!/^[A-Za-z0-9_-]{1,128}$/.test(t)||this.#i.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 Qg({registerApp:this.#e,onCredentials:i=>this.#L(()=>this.#u(o,i))}),this.#i.set(t,o),this.#p=t,this.#U(),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:[...VW]},events:{items:{tenant:["im.message.receive_v1"]}},callbacks:{items:["card.action.trigger"]}}}),this.#k(),this.registrationStatus(t)}startCallbackRepair(t,{actorOpenId:o,chatId:i}={}){this.#_();let e=this.#P(t);if(e.deletionPending)throw new Error("Cannot repair a Feishu bot pending deletion");let a=this.#I.get(t),A=a?this.#i.get(a):null;if(A&&IS.has(A.manager.status().state)){if(A.operation!==uu)throw new Error("Another Feishu app update is already active for this bot");return this.registrationStatus(A.id)}this.#I.delete(t);let r=this.#o();if(typeof r!="string"||!/^[A-Za-z0-9_-]{1,128}$/.test(r)||this.#i.has(r))throw new Error("Registration id generator returned an invalid or duplicate id");let s={id:r,operation:uu,manager:null,botId:t,createdNew:!1,cancelled:!1,remoteCommitted:!1,processing:null,publicError:null,stage:"authorizing",target:structuredClone(e),targetFingerprint:lS(e),initiator:{actorOpenId:pS(o),chatId:pS(i)}};return s.manager=new sS({registerApp:this.#e,appId:e.appId,domain:e.domain,onCredentials:g=>{s.remoteCommitted=!0;let I=this.#Q(s,g).finally(()=>{s.processing===I&&(s.processing=null)});return s.processing=I,I}}),this.#i.set(r,s),this.#I.set(t,r),this.#p=r,this.#U(),s.manager.start(),this.#k(),this.registrationStatus(r)}startGroupMessagePermission(t){this.#_();let o=this.#P(t);if(o.deletionPending)throw new Error("Cannot update permissions for a Feishu bot pending deletion");let i=this.#I.get(t),e=i?this.#i.get(i):null;if(e&&IS.has(e.manager.status().state)){if(e.operation!==cS)throw new Error("Another Feishu app update is already active for this bot");return this.registrationStatus(e.id)}this.#I.delete(t);let a=this.#o();if(typeof a!="string"||!/^[A-Za-z0-9_-]{1,128}$/.test(a)||this.#i.has(a))throw new Error("Registration id generator returned an invalid or duplicate id");let A={id:a,operation:cS,manager:null,botId:t,createdNew:!1,cancelled:!1,remoteCommitted:!1,processing:null,publicError:null,stage:"authorizing",target:structuredClone(o),targetFingerprint:lS(o),initiator:{actorOpenId:null,chatId:null}};return A.manager=new gS({registerApp:this.#e,appId:o.appId,domain:o.domain,onCredentials:r=>{A.remoteCommitted=!0;let g=this.#S(A,r).finally(()=>{A.processing===g&&(A.processing=null)});return A.processing=g,g}}),this.#i.set(a,A),this.#I.set(t,a),this.#p=a,this.#U(),A.manager.start(),this.#k(),this.registrationStatus(a)}hasRegistration(t){return this.#i.has(t)}registrationStatus(t){let o=this.#i.get(t);return o?this.#B({registration:o,selectedBotId:o.botId}):null}async cancelRegistration(t=this.#p){let o=this.#i.get(t);if(!o)return this.status();let i=o.manager.status().state;return WW.has(o.operation)&&i==="saving"?this.registrationStatus(t):IS.has(i)?(o.cancelled=!0,o.manager.cancel(),await this.#L(async()=>{o.createdNew&&o.botId&&this.#s.get(o.botId)===o.id&&this.#r.getBot(o.botId)&&await this.#T(o.botId,()=>this.#w(o.botId))}),this.#k(),this.registrationStatus(t)??this.status()):this.registrationStatus(t)}status(t){return this.#B({registration:this.#i.get(this.#p)??null,selectedBotId:t})}async bindCredentials({appId:t,appSecret:o,domain:i="feishu"}={}){this.#_();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.#L(async()=>{this.#_();let r=await this.#A({appId:e,appSecret:a,domain:A});this.#_();let s=this.#r.list().find(f=>f.appId===e),g=s?.id??this.#n();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??XW(g),I=await this.#t.resolve(c).catch(()=>{}),d={...s,id:g,appId:e,secretRef:c,ownerOpenIds:s?.ownerOpenIds?.length?s.ownerOpenIds:[ZW],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.#M(c,I),f}return await this.#T(g,async()=>{try{await this.#b(B,a),this.#l.delete(g)}catch{this.#l.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.#_(),this.#T(t,async()=>{let o=this.#P(t);if(o.deletionPending)return this.#l.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(fu(Bu(this.#c.get(t))))return this.status(t);let i;try{i=await this.#t.resolve(o.secretRef)}catch{i=null}if(!i?.value)return this.#l.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.#b(o,i.value),this.#l.delete(t)}catch{this.#l.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.#_(),this.#T(t,async()=>{let o=this.#P(t),i=this.#c.get(t);if(!fu(Bu(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(ba(`${o.botName}\uFF08${A6(o.appId)}\uFF09`,"\u98DE\u4E66\u673A\u5668\u4EBA"))})}async sendProactiveText(t,o,i,e={}){return this.#_(),this.#T(t,async()=>{this.#P(t);let a=this.#c.get(t);if(!fu(Bu(a))||typeof a.sendProactiveText!="function"){let A=new Error("\u98DE\u4E66\u673A\u5668\u4EBA\u5C1A\u672A\u8FDE\u63A5");throw A.code="bot-not-connected",A}return a.sendProactiveText(o,i,e)})}async disconnectBot(t){return this.#_(),this.#T(t,async()=>(this.#P(t),await this.#D(t),this.#l.delete(t),this.#k(),this.status(t)))}async updateGroupResponseMode(t,o){if(this.#_(),!zm(o))throw new TypeError("Invalid Feishu group response mode");return this.#L(()=>this.#T(t,async()=>{let i=this.#P(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.#c.get(t)?.setGroupResponseMode?.(e.groupResponseMode),this.#k(),this.status(t)}))}async deleteBot(t){return this.#_(),this.#L(()=>this.#T(t,async()=>(this.#P(t),await this.#w(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.#f)return;this.#f=!0;let t=[];for(let o of this.#i.values()){let i=o.manager.status().state;WW.has(o.operation)&&i==="saving"?(o.manager.cancel(),o.processing&&t.push(o.processing)):IS.has(i)&&(o.cancelled=!0,o.manager.cancel())}await this.#h,await Promise.allSettled([...this.#d.values()]),await Promise.allSettled([...this.#c.keys()].map(o=>this.#D(o))),await Promise.allSettled(t),await this.#h,await Promise.allSettled([...this.#d.values()]),await Promise.allSettled([...this.#c.keys()].map(o=>this.#D(o)))}#B({registration:t,selectedBotId:o}={}){let i=this.#r.list().map(I=>{let d=Bu(this.#c.get(I.id)),B=fu(d),f=this.#l.get(I.id)??null;return{botId:I.id,phase:GRe({connected:B,error:f,connection:d}),connected:B,configured:!0,groupResponseMode:ro(I.groupResponseMode),groupMessagePermissionGranted:I.groupMessagePermissionGranted===!0,bot:PRe(I),connection:d,lastMessageError:Vr(d.lastMessageError),error:f}}),e=t?this.#y(t):{state:"idle",attempt:0,updatedAt:Date.now()},a=eP.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.#E,phase:c,connected:s?.connected??!1,configured:i.length>0,bot:s?.bot??null,connection:s?.connection??e6(),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#S(t,o){let i=o.client_id,e=o.client_secret,a=pS(o.user_info?.open_id),A=o.user_info?.tenant_brand,r=t.target;if(t.cancelled)throw this.#m(t,"abort","Group message permission update was cancelled before local activation.");if(i!==r.appId)throw this.#m(t,"repair_app_mismatch","Feishu returned credentials for a different app.");if(!a)throw this.#m(t,"repair_owner_missing","Feishu returned no permission operator identity.");if(A!==void 0&&A!==r.domain)throw this.#m(t,"repair_domain_mismatch","Feishu returned credentials for a different account domain.");if(!r.ownerOpenIds.includes(ZW)&&!r.ownerOpenIds.includes(a))throw this.#m(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.#m(t,"repair_credentials_invalid","Feishu could not verify the updated app credentials.",g)}if(r.botOpenId&&s?.openId!==r.botOpenId)throw this.#m(t,"repair_bot_mismatch","The updated Feishu app belongs to a different bot identity.");await this.#L(()=>this.#T(t.botId,async()=>{let g=this.#r.getBot(t.botId);if(!g||g.deletionPending||lS(g)!==t.targetFingerprint)throw this.#m(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.#m(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.#m(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.#m(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.#m(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.#b(I,e)}catch(d){throw this.#l.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.#m(t,"group_message_permission_connection_failed","The permission was accepted, but the Feishu runtime could not restart.",d)}this.#l.delete(t.botId),t.stage="verified",t.publicError=null,this.#k()}))}async#Q(t,o){let i=o.client_id,e=o.client_secret,a=pS(o.user_info?.open_id),A=o.user_info?.tenant_brand,r=t.target;if(t.cancelled)throw this.#m(t,"abort","Callback repair was cancelled before local activation.");if(i!==r.appId)throw this.#m(t,"repair_app_mismatch","Feishu returned credentials for a different app.");if(!a)throw this.#m(t,"repair_owner_missing","Feishu returned no repair operator identity.");if(A!==void 0&&A!==r.domain)throw this.#m(t,"repair_domain_mismatch","Feishu returned credentials for a different account domain.");t.stage="verifying_identity";let s;try{s=await this.#A({appId:i,appSecret:e,domain:r.domain})}catch(c){throw this.#m(t,"repair_credentials_invalid","Feishu could not verify the repaired app credentials.",c)}if(r.botOpenId&&s?.openId!==r.botOpenId)throw this.#m(t,"repair_bot_mismatch","The repaired Feishu app belongs to a different bot identity.");let g=await this.#L(()=>this.#T(t.botId,async()=>{let c=this.#r.getBot(t.botId);if(!c||c.deletionPending||lS(c)!==t.targetFingerprint)throw this.#m(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.#m(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.#m(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.#m(t,"credential_state_unknown","The repaired Feishu credential could not be confirmed after writing.")}let B;t.stage="restarting";try{await this.#b(c,e),B=this.#c.get(t.botId)}catch(f){throw this.#l.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.#m(t,"repair_connection_failed","The repaired Feishu runtime could not be started.",f)}if(!B)throw this.#m(t,"repair_connection_failed","The repaired Feishu runtime is unavailable.");return this.#l.delete(t.botId),this.#k(),B}));if(typeof g.beginCardActionProbe!="function")throw this.#m(t,"card_action_probe_unavailable","The Feishu runtime cannot verify card callbacks.");t.stage="awaiting_callback";try{if((await g.beginCardActionProbe({expectedOperatorOpenId:t.initiator.actorOpenId??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.#m(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()}#m(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#u(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.#n();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??XW(g),I=this.#s.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.#s.set(g,t.id)}catch(Q){try{await this.#M(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.#w(g)):(await this.#r.saveBot(s),await this.#M(c,d),I?this.#s.set(g,I):this.#s.delete(g)),new Error("Registration was cancelled");let f=!1;try{if(await this.#T(g,()=>this.#b(B,e)),t.cancelled)throw t.createdNew?await this.#T(g,()=>this.#w(g)):(await this.#r.saveBot(s),await this.#M(c,d),I?this.#s.set(g,I):this.#s.delete(g),d?.value&&!s.deletionPending?await this.#T(g,()=>this.#b(s,d.value)):await this.#T(g,()=>this.#D(g))),f=!0,new Error("Registration was cancelled");this.#l.delete(g),this.#k()}catch(Q){if(t.cancelled)throw!f&&t.createdNew&&this.#r.getBot(g)?await this.#T(g,()=>this.#w(g)):!f&&s&&(await this.#r.saveBot(s),await this.#M(c,d),I?this.#s.set(g,I):this.#s.delete(g),!this.#f&&d?.value&&!s.deletionPending?await this.#T(g,()=>this.#b(s,d.value)):await this.#T(g,()=>this.#D(g))),this.#k(),Q;if(s&&d?.value)try{throw await this.#r.saveBot(s),await this.#M(c,d),I?this.#s.set(g,I):this.#s.delete(g),s.deletionPending?(await this.#T(g,()=>this.#D(g)),this.#l.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.#b(s,d.value)),this.#l.delete(g)),this.#k(),Q}catch(y){throw y===Q?Q:(this.#l.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.#l.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#b(t,o){await this.#D(t.id);let i=await this.#g({botId:t.id,config:t,appSecret:o,repair:this.#R(t.id)});this.#c.set(t.id,i);try{await i.start()}catch(e){throw this.#c.get(t.id)===i&&this.#c.delete(t.id),await i.stop({preserveError:!0}).catch(()=>{}),e}}#R(t){let o=i=>{let e=this.#i.get(i);return e?.operation===uu&&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#D(t){let o=this.#c.get(t);this.#c.delete(t),o&&await o.stop()}async#w(t){let o=this.#r.getBot(t);if(o){o.deletionPending||(o=await this.#r.saveBot({...o,deletionPending:!0})),await this.#D(t);try{await this.#t.unset(o.secretRef)}catch(i){throw this.#l.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.#a({botId:t,config:o})}catch(i){throw this.#l.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.#l.delete(t),this.#s.delete(t)}}async#M(t,o){o?.value?await this.#t.set(t,o.value):await this.#t.unset(t)}#P(t){let o=this.#r.getBot(t);if(!o)throw new Error("Unknown Feishu bot");return o}#_(){if(this.#f)throw new Error("The Feishu controller is closed")}#L(t){let o=this.#h.then(t,t);return this.#h=o.then(()=>{},()=>{}),o}#T(t,o){let e=(this.#d.get(t)??Promise.resolve()).then(o,o),a=e.then(()=>{},()=>{});return this.#d.set(t,a),a.finally(()=>{this.#d.get(t)===a&&this.#d.delete(t)}),e}#U(){if(!(this.#i.size<=32))for(let[t,o]of this.#i){if(t===this.#p)continue;let i=o.manager.status().state;if(!eP.has(i)&&i!=="saving"&&this.#i.delete(t),this.#i.size<=32)break}}#k(){this.#E+=1}};function KRe(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 xRe(n,t=o=>new t6.default(o)){let o=KRe(n);return o?t(o):void 0}function YRe(n){let t=mc(n.dshHome??process.env.DSH_HOME??Md(URe(),".dsh")),o=mc(n.dataDir??Md(t,"integrations","dsh-feishu"));return{root:o,config:mc(n.configPath??Md(o,"config.json")),legacyState:mc(n.statePath??Md(o,"state.json")),bots:mc(n.botsDir??Md(o,"bots")),workspaces:mc(n.workspacesPath??Md(o,"workspaces.json"))}}async function AP(n,t={},o={}){if(!n?.credentials)throw new TypeError("dsh-feishu requires ctx.credentials");let i=Aa(n,t),e=o.lark??Lv,a=o.Controller??Qu,A=o.ConfigStore??oS,r=o.StateStore??Jm,s=o.HarnessClient??aS,g=o.FeishuRuntime??rS,c=o.verifyFeishuApp??dW,I=fe=>c({...fe,httpInstance:e.defaultHttpInstance}),d=o.createConnectionSupervisor??Uv,B=typeof n.logger=="function"?n.logger("dsh-feishu"):n.logger??console,f=()=>Ra(n),Q=YRe(t),y=await new A(Q.config).load(),m=mc(t.workspace??process.cwd()),_=o.WorkspaceStore??ea,T=o.workspaces??await new _(Q.workspaces,{defaultWorkspace:m}).load(),R=typeof y.list=="function",F=()=>R?y.list():[],j=F();R&&await T.reconcile(j.map(fe=>fe.id)),await Promise.all(j.map(fe=>T.ensure(fe.id,{defaultAgentPreset:t.agentPreset})));let L=typeof y.removeBot=="function"?Pa(y,{workspaces:T,method:"removeBot",botIdFromRemoved:fe=>fe.id,saveMethod:"saveBot",botIdFromSave:fe=>fe?.id}):y,q=new Map,z=fe=>!fe.id||!fe.secretRef||fe.secretRef===nS?Q.legacyState:mc(Q.bots,fe.id,"state.json"),K=async fe=>{let Se=fe.id??"__legacy__",Ke=q.get(Se);return Ke||(Ke=await new r(z(fe)).load(),q.set(Se,Ke)),Ke},G=async fe=>{let Se=F().find(Ke=>Ke.id===fe);if(!Se)throw new Error("Unknown Feishu bot");return K(Se)},J=Ua(n,o.commandExecutor),{controlExecutor:U,sessionMaintenanceExecutor:N,fileIngressExecutor:k}=Ha(n,{controlExecutor:o.controlExecutor,sessionMaintenanceExecutor:o.sessionMaintenanceExecutor,fileIngressExecutor:o.fileIngressExecutor}),V=new s({...i,workspace:m,autostart:!1,dshBin:t.dshBin??"dsh",...J?{commandExecutor:J}:{},...U?{controlExecutor:U}:{},...N?{sessionMaintenanceExecutor:N}:{},...k?{fileIngressExecutor:k}:{}}),te=o.proxyEnv??process.env,ie=xRe(te,o.createProxyAgent),we=new a({registerApp:fe=>e.registerApp(fe),verifyApp:I,credentials:n.credentials,configStore:L,createRuntime:async({botId:fe,config:Se,appSecret:Ke,repair:rA})=>{let ve=await K(Se),aA=fe??Se.id??Se.appId;await T.ensure(aA,{defaultAgentPreset:t.agentPreset});let Ce=Ga(V,{botId:aA,workspaces:T,state:ve,agentPresetCatalog:f});return new g({lark:e,botId:aA,repair:rA,appId:Se.appId,appSecret:Ke,domain:Se.domain,botOpenId:Se.botOpenId,groupResponseMode:Se.groupResponseMode,ownerOpenIds:Se.ownerOpenIds??[Se.ownerOpenId],harness:Ce.harness,state:Ce.state,contextEnhancement:{botId:aA,getSettings:()=>T.contextEnhancementFor(aA)},replyTimeoutMs:t.replyTimeoutMs??6e5,...ie?{wsAgent:ie}:{},logger:{error:(...he)=>B.error?.(`[${fe??Se.id}]`,...he),warn:(...he)=>B.warn?.(`[${fe??Se.id}]`,...he),info:(...he)=>B.info?.(`[${fe??Se.id}]`,...he),debug:(...he)=>B.debug?.(`[${fe??Se.id}]`,...he)}})},deleteState:async({botId:fe,config:Se})=>{q.delete(fe);try{await HRe(z(Se))}catch(Ke){if(Ke?.code!=="ENOENT")throw Ke}}}),se=Fa(we,{workspaces:T,stateFor:G,agentPresetCatalog:f}),Ne=d({controller:se,harness:V,logger:B,retryDelaysMs:t.retryDelaysMs,healthyIntervalMs:t.healthyIntervalMs}).start();return{controller:se,deliveryAdapter:La({channel:"feishu",workspaces:T,coreController:we,stateFor:G}),ready:Ne.ready,async close(){await Ne.close(),await se.close(),V.stopManagedProcess(),ie?.destroy?.()}}}import gke from"qrcode";var Td=qe(sP(),1);var oke=qe(sP(),1);var nke=Object.freeze({$locale:"en",IM\u673A\u5668\u4EBA:"IM bots",IM\u673A\u5668\u4EBA\u8BBE\u7F6E:"IM bot settings",\u66F4\u591A\u673A\u5668\u4EBA\u8BBE\u7F6E:"More bot settings","IM \u6E20\u9053":"IM channels","\u8BA9 DeepSeek Harness \u89E6\u624B\u53EF\u53CA":"Connecting DeepSeek Harness",\u5F53\u524D\u7248\u672C:"Current version","DSH-IM \u66F4\u65B0":"DSH-IM update",\u68C0\u67E5\u66F4\u65B0:"Check for updates",\u91CD\u65B0\u68C0\u67E5:"Check again",\u5237\u65B0\u72B6\u6001:"Refresh status",\u624B\u5DE5\u66F4\u65B0:"Manual update",\u624B\u5DE5\u66F4\u65B0\u547D\u4EE4:"Manual update command",\u590D\u5236\u547D\u4EE4:"Copy command","\u590D\u5236\u4E2D\u2026":"Copying\u2026",\u5DF2\u590D\u5236:"Copied","\u547D\u4EE4\u5DF2\u590D\u5236\u3002":"Command copied.","\u590D\u5236\u5931\u8D25\uFF0C\u8BF7\u9009\u4E2D\u547D\u4EE4\u540E\u6309 Ctrl+C \u6216 \u2318C \u590D\u5236\u3002":"Copy failed. Select the command and press Ctrl+C or \u2318C to copy it.","\u81EA\u52A8\u66F4\u65B0\u5931\u8D25\u53EF\u4EE5\u4F7F\u7528\u547D\u4EE4\u66F4\u65B0\uFF1A":"If the automatic update fails, update with this command:","\u5C1A\u672A\u786E\u8BA4\u76EE\u6807\u7248\u672C\uFF0C\u6B64\u547D\u4EE4\u5B89\u88C5\u6267\u884C\u65F6 npm \u7684 latest \u7248\u672C\u3002":"No target version has been confirmed. This command installs the npm latest version available when you run it.","\u8BF7\u5728\u5F53\u524D Desktop \u7684\u5185\u7F6E\u7EC8\u7AEF\u6267\u884C\uFF0C\u5B8C\u6210\u540E\u624B\u52A8\u91CD\u542F\u3002":"Run this in the current Desktop\u2019s built-in terminal, then restart manually.","\u8BF7\u5728\u8FD0\u884C\u5F53\u524D Harness \u7684\u540C\u4E00\u73AF\u5883\u6267\u884C\uFF0C\u4FDD\u6301 DSH_HOME \u4E00\u81F4\uFF0C\u5B8C\u6210\u540E\u624B\u52A8\u91CD\u542F\u3002":"Run this in the same environment as the current Harness, with the same DSH_HOME, then restart manually.","\u8BF7\u7B49\u5F85\u5F53\u524D\u64CD\u4F5C\u7ED3\u675F\uFF0C\u786E\u8BA4\u6CA1\u6709\u5B89\u88C5\u8FDB\u7A0B\u8FD0\u884C\u540E\u518D\u6267\u884C\u547D\u4EE4\u3002":"Wait for the current operation to finish and confirm no installer is running before using this command.","\u6E90\u7801\u6216\u94FE\u63A5\u5B89\u88C5\u8BF7\u6309\u539F\u5B89\u88C5\u65B9\u5F0F\u66F4\u65B0\uFF0C\u4E0D\u63D0\u4F9B\u8986\u76D6\u6E90\u7801\u7684 npm \u547D\u4EE4\u3002":"Update source or linked installations using their original method. No npm command is provided to overwrite the source.","\u65E0\u6CD5\u5B89\u5168\u751F\u6210\u5F53\u524D profile \u7684\u547D\u4EE4\uFF0C\u8BF7\u5728\u7EC8\u7AEF\u4E2D\u624B\u52A8\u786E\u8BA4 profile \u540E\u66F4\u65B0\u3002":"A safe command cannot be generated for this profile. Confirm the profile in your terminal before updating manually.",\u66F4\u65B0\u81F3:"Update to",\u5B89\u88C5\u66F4\u65B0:"Install update","\u6B63\u5728\u66F4\u65B0\u2026":"Updating\u2026",\u5F85\u624B\u52A8\u91CD\u542F:"Restart needed",\u8FD0\u884C\u7248\u672C:"Running version",\u5DF2\u5B89\u88C5\u7248\u672C:"Installed version","\u76EE\u6807 profile":"Target profile",\u76EE\u6807\u7248\u672C:"Target version",\u65E0\u6CD5\u786E\u8BA4:"Unknown",\u53D1\u73B0\u65B0\u7248\u672C:"Update available",\u5DF2\u662F\u6700\u65B0\u7248\u672C:"Up to date",\u5F53\u524D\u7248\u672C\u65E0\u9700\u66F4\u65B0:"No newer version available","\u5DF2\u83B7\u53D6 npm \u6700\u65B0\u7248\u672C":"Latest npm version retrieved","\u68C0\u67E5 npm \u6700\u65B0\u7248\u672C\uFF0C\u4E0D\u4F1A\u81EA\u52A8\u5B89\u88C5\u3002":"Check the latest npm version. Nothing is installed automatically.","\u6B63\u5728\u4ECE npm \u68C0\u67E5\u6700\u65B0\u7248\u672C\u2026":"Checking npm for the latest version\u2026","\u6B63\u5728\u5B89\u88C5\uFF0C\u8BF7\u7A0D\u5019\u2026":"Installing, please wait\u2026","\u6B63\u5728\u6821\u9A8C\u5B89\u88C5\u7ED3\u679C\u2026":"Verifying the installation\u2026","\u5DF2\u5B89\u88C5\uFF0C\u5F85\u624B\u52A8\u91CD\u542F":"Installed \u2014 manual restart needed",\u66F4\u65B0\u5DF2\u751F\u6548:"Updated version is active",\u66F4\u65B0\u5931\u8D25:"Update failed",\u66F4\u65B0\u8BF7\u6C42\u5931\u8D25:"Update request failed","\u4EC5\u66F4\u65B0 DSH-IM\u3002\u5B89\u88C5\u5B8C\u6210\u540E\u9700\u624B\u52A8\u91CD\u542F\u540E\u53F0\uFF1B\u672C\u529F\u80FD\u4E0D\u4F1A\u81EA\u52A8\u91CD\u542F\u6216\u4E3B\u52A8\u5237\u65B0\u9875\u9762\u3002":"Only DSH-IM will be updated. Restart the backend manually after installation. This feature does not automatically restart it or initiate a page refresh.","\u5F53\u524D\u662F\u6E90\u7801\u6216\u94FE\u63A5\u5B89\u88C5\uFF0C\u53EA\u80FD\u68C0\u67E5\u7248\u672C\uFF1B\u8BF7\u624B\u52A8\u66F4\u65B0\u6E90\u7801\uFF0C\u6216\u8FC1\u79FB\u5230 npm \u5B89\u88C5\u3002":"This is a source or linked installation. You can check versions, but must update the source manually or migrate to an npm installation.","\u65E0\u6CD5\u786E\u8BA4\u5F53\u524D profile\uFF0C\u8BF7\u5728\u5BF9\u5E94\u7684 Harness \u73AF\u5883\u4E2D\u624B\u52A8\u66F4\u65B0\u3002":"The current profile could not be identified. Update manually in the corresponding Harness environment.","\u5F53\u524D\u8FD0\u884C\u73AF\u5883\u4E0D\u652F\u6301\u6309\u94AE\u5B89\u88C5\uFF0C\u8BF7\u624B\u52A8\u66F4\u65B0\u63D2\u4EF6\u3002":"This runtime cannot install through this button. Update the plugin manually.","\u5F53\u524D npm \u6E90\u914D\u7F6E\u4E0E\u5B98\u65B9\u6E90\u4E0D\u4E00\u81F4\uFF0C\u8BF7\u5148\u68C0\u67E5 registry \u914D\u7F6E\u3002":"The npm registry configuration differs from the official registry. Check your registry settings first.","\u5F53\u524D Host \u7684 Node.js \u7248\u672C\u4E0D\u6EE1\u8DB3\u65B0\u7248\u8981\u6C42\uFF0C\u8BF7\u5148\u66F4\u65B0\u8FD0\u884C\u73AF\u5883\u3002":"The Host Node.js version does not meet the new version\u2019s requirements. Update the runtime first.","\u65B0\u7248\u672C\u5DF2\u5B89\u88C5\uFF0C\u8BF7\u5728\u65B9\u4FBF\u65F6\u624B\u52A8\u91CD\u542F\u5F53\u524D Harness \u6216 Desktop\u3002":"The new version is installed. Manually restart this Harness or Desktop when convenient.","\u4E0A\u6B21\u5B89\u88C5\u7ED3\u679C\u65E0\u6CD5\u786E\u8BA4\uFF0C\u8BF7\u5148\u68C0\u67E5\u6B64 profile \u7684\u63D2\u4EF6\u5B89\u88C5\u72B6\u6001\u3002":"The previous installation result is uncertain. Check this profile\u2019s plugin installation first.","\u65E0\u6CD5\u8BBF\u95EE npm \u6216\u8BF7\u6C42\u8D85\u65F6\uFF0C\u8BF7\u7A0D\u540E\u91CD\u65B0\u68C0\u67E5\u3002":"npm is unreachable or the request timed out. Check again later.","npm \u8FD4\u56DE\u7684\u7248\u672C\u4FE1\u606F\u65E0\u6548\uFF0C\u6682\u65F6\u65E0\u6CD5\u66F4\u65B0\u3002":"npm returned invalid release information. Updating is unavailable.","\u7248\u672C\u786E\u8BA4\u5DF2\u8FC7\u671F\uFF0C\u8BF7\u91CD\u65B0\u68C0\u67E5\u540E\u518D\u5B89\u88C5\u3002":"The version confirmation expired. Check again before installing.","\u63D2\u4EF6\u5B89\u88C5\u72B6\u6001\u5DF2\u53D1\u751F\u53D8\u5316\uFF0C\u8BF7\u91CD\u65B0\u68C0\u67E5\u3002":"The plugin installation changed. Check again.","\u6B64 profile \u6B63\u5728\u66F4\u65B0\uFF0C\u8BF7\u7A0D\u540E\u67E5\u770B\u72B6\u6001\u3002":"This profile is already updating. Check its status shortly.","\u5B89\u88C5\u5931\u8D25\uFF0C\u8BF7\u68C0\u67E5\u5F53\u524D\u5B89\u88C5\u72B6\u6001\u540E\u91CD\u8BD5\u3002":"Installation failed. Check the current installation before retrying.","\u5B89\u88C5\u7ED3\u679C\u6821\u9A8C\u5931\u8D25\uFF0C\u8BF7\u624B\u52A8\u68C0\u67E5\u63D2\u4EF6\u7248\u672C\u3002":"Installation verification failed. Check the plugin version manually.","\u65E0\u6CD5\u5B89\u5168\u4FDD\u5B58\u66F4\u65B0\u72B6\u6001\uFF0C\u8BF7\u5148\u68C0\u67E5\u5F53\u524D\u5B89\u88C5\u7ED3\u679C\u3002":"Update state could not be saved safely. Check the current installation result before retrying.","\u4E0A\u6B21\u66F4\u65B0\u5DF2\u4E2D\u65AD\uFF0C\u8BF7\u68C0\u67E5\u5B89\u88C5\u72B6\u6001\u540E\u91CD\u8BD5\u3002":"The previous update was interrupted. Check the installation before retrying.","\u66F4\u65B0\u670D\u52A1\u5DF2\u5173\u95ED\uFF0C\u8BF7\u624B\u52A8\u91CD\u65B0\u6253\u5F00\u8BBE\u7F6E\u9875\u3002":"The update service has closed. Reopen settings manually.","\u66F4\u65B0\u8BF7\u6C42\u65E0\u6548\uFF0C\u8BF7\u91CD\u65B0\u68C0\u67E5\u7248\u672C\u3002":"The update request is invalid. Check the version again.","\u5F53\u524D\u63D2\u4EF6\u5B89\u88C5\u4E0D\u5B8C\u6574\u6216\u4E0E profile \u4E0D\u7B26\uFF0C\u8BF7\u624B\u52A8\u68C0\u67E5\u5B89\u88C5\u914D\u7F6E\u3002":"The plugin installation is incomplete or does not match this profile. Check the installation configuration manually.","\u65E0\u6CD5\u786E\u8BA4\u5F53\u524D npm \u6E90\u914D\u7F6E\uFF0C\u6682\u65F6\u4E0D\u80FD\u5B89\u88C5\u66F4\u65B0\u3002":"The npm registry configuration could not be verified. Installation is unavailable.","\u5B89\u88C5\u8D85\u65F6\uFF0C\u8BF7\u5148\u786E\u8BA4\u5F53\u524D\u5B89\u88C5\u72B6\u6001\uFF0C\u518D\u51B3\u5B9A\u662F\u5426\u91CD\u8BD5\u3002":"Installation timed out. Check the current installation before retrying.","\u66F4\u65B0\u8BF7\u6C42\u5931\u8D25\uFF0C\u8BF7\u91CD\u8BD5\u3002":"The update request failed. Try again.","\u66F4\u65B0\u670D\u52A1\u8FD4\u56DE\u4E86\u65E0\u6CD5\u8BC6\u522B\u7684\u54CD\u5E94\u3002":"The update service returned an unrecognized response.","\u5F53\u524D Host \u4E0D\u652F\u6301\u66F4\u65B0\u63A5\u53E3\uFF0C\u8BF7\u5148\u624B\u52A8\u66F4\u65B0\u63D2\u4EF6\u5E76\u91CD\u542F\u3002":"This Host does not support the update API. Update the plugin manually and restart first.","\u5173\u95ED\u7A97\u53E3\u4E0D\u4F1A\u53D6\u6D88\u5B89\u88C5\u3002\u8BF7\u52FF\u540C\u65F6\u5728\u5176\u4ED6\u7A97\u53E3\u7BA1\u7406\u6B64 profile \u7684\u63D2\u4EF6\u3002":"Closing this window does not cancel installation. Do not manage this profile\u2019s plugins in another window at the same time.","\u9875\u9762\u7248\u672C\u4E0E\u8FD0\u884C\u7248\u672C\u4E0D\u540C\uFF0C\u8BF7\u624B\u52A8\u5237\u65B0\u9875\u9762\uFF1B\u82E5\u4ECD\u4E0D\u4E00\u81F4\uFF0C\u8BF7\u624B\u52A8\u91CD\u542F Harness \u6216 Desktop\u3002":"The page and running versions differ. Refresh the page manually; if they still differ, manually restart Harness or Desktop.","\u8BF7\u5728\u673A\u5668\u4EBA\u7A7A\u95F2\u65F6\u5B89\u88C5\uFF1B\u5B89\u88C5\u4F1A\u4FEE\u6539\u5F53\u524D profile \u7684\u4F9D\u8D56\uFF0C\u5B8C\u6210\u540E\u9700\u624B\u52A8\u91CD\u542F\u3002":"Install while bots are idle. This changes the current profile\u2019s dependencies and requires a manual restart afterward.","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",\u6700\u8FD1\u4E00\u6761\u6D88\u606F\u5904\u7406\u5931\u8D25:"Latest message failed",\u9519\u8BEF\u7801:"Code",\u53C2\u8003\u53F7:"Reference",\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",\u76F4\u63A5\u8F93\u5165\u8DEF\u5F84:"Enter a path directly","\u652F\u6301 Windows \u76D8\u7B26\u3001UNC \u4E0E POSIX \u7EDD\u5BF9\u8DEF\u5F84\u3002":"Supports Windows drives, UNC paths, and POSIX absolute paths.","\u8F93\u5165 Host \u4E0A\u7684\u5B8C\u6574\u7EDD\u5BF9\u8DEF\u5F84":"Enter a full absolute path on the Host",\u524D\u5F80:"Go","\u8BFB\u53D6\u4E2D\u2026":"Loading\u2026","\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",\u4E0A\u4E0B\u6587\u589E\u5F3A:"Context enhancement",\u672A\u5F00\u542F:"Not enabled",\u4EC5\u7FA4\u804A:"Groups only",\u4EC5\u79C1\u804A:"Direct only",\u7FA4\u804A\u548C\u79C1\u804A:"Groups and direct",\u5173\u95ED\u5F39\u7A97:"Close dialog",\u67E5\u770B\u4E0A\u4E0B\u6587\u589E\u5F3A\u8BF4\u660E:"View context enhancement details",\u542F\u7528\u8303\u56F4:"Enable in",\u7FA4\u804A\u4E2D\u542F\u7528:"Enable in group chats",\u79C1\u804A\u4E2D\u542F\u7528:"Enable in direct chats","\uFF08\u5F53\u524D\u6E20\u9053\u4E0D\u652F\u6301\u7FA4\u804A\uFF09":"(This channel does not support group chats)",\u6765\u6E90\u5B57\u6BB5:"Source fields",\u67E5\u770B\u6765\u6E90\u5B57\u6BB5\u8BF4\u660E:"View source field details",\u6E20\u9053:"Channel",\u4F1A\u8BDD\u7C7B\u578B:"Conversation type",\u53D1\u9001\u8005\u6807\u8BC6:"Sender ID",\u53D1\u9001\u8005\u6635\u79F0:"Sender name",\u67E5\u770B\u53D1\u9001\u8005\u6635\u79F0\u5B57\u6BB5\u8BF4\u660E:"View sender name field details","\u8BE5\u5B57\u6BB5\u4E0D\u662F\u6BCF\u4E2A\u6E20\u9053\u90FD\u80FD\u63D0\u4F9B\u3002\u5F53\u524D\u6D88\u606F\u6CA1\u6709\u53D1\u9001\u8005\u6635\u79F0\u65F6\uFF0C\u5373\u4F7F\u5DF2\u9009\u62E9\u8BE5\u5B57\u6BB5\uFF0C \u4E2D\u4E5F\u4F1A\u7701\u7565 senderName\u3002":"This field is not available on every channel. If the current message has no sender name, omits senderName even when the field is selected.",\u673A\u5668\u4EBA\u6807\u8BC6:"Bot ID",\u589E\u5F3A\u63D0\u793A\u8BCD:"Guidance",\u67E5\u770B\u589E\u5F3A\u63D0\u793A\u8BCD\u4F7F\u7528\u8BF4\u660E:"View guidance instructions",\u4F7F\u7528\u8BF4\u660E:"How to use","\u7528\u4E8E\u544A\u8BC9\u6A21\u578B\u5982\u4F55\u4F7F\u7528 \u4E2D\u5DF2\u9009\u62E9\u7684\u6765\u6E90\u5B57\u6BB5\u3002\u53EA\u586B\u5199\u6B63\u6587\uFF0C\u63D2\u4EF6\u4F1A\u81EA\u52A8\u6DFB\u52A0 \u6210\u5BF9\u6807\u7B7E\u3002":"Tell the model how to use the selected fields in . Enter only the body; the plugin adds paired tags.",\u751F\u6548\u89C4\u5219:"Behavior",\u9690\u79C1\u63D0\u793A:"Privacy",\u4F7F\u7528\u793A\u4F8B:"Example","\u4EC5\u4F9D\u636E\u5F53\u524D\u6D88\u606F\u7684 \u4E2D\u5B9E\u9645\u63D0\u4F9B\u7684\u5B57\u6BB5\u7406\u89E3\u6765\u6E90\uFF1B\u6CA1\u6709\u63D0\u4F9B\u7684\u5B57\u6BB5\u4E0D\u8981\u731C\u6D4B\u6216\u8865\u5168\u3002\nconversationType\u662F\u7FA4\u804A\u65F6\u56DE\u590D\u4E25\u8083\u4E00\u70B9\uFF0CconversationType\u662F\u79C1\u804A\u65F6\u56DE\u590D\u4E00\u5B9A\u8981\u5E7D\u9ED8\u641E\u7B11\uFF0C\u50CF\u5468\u661F\u9A70\u7684\u7535\u5F71\u4E00\u6837\u641E\u7B11":`Understand the source only from fields actually present in for the current message; do not guess or fill in missing fields. When conversationType is group, reply more seriously. When conversationType is direct, make the reply humorous and funny.`,\u586B\u5165\u793A\u4F8B:"Use example",\u6E05\u7A7A:"Clear","\u9009\u62E9\u5728\u54EA\u4E9B\u4F1A\u8BDD\u4E2D\u542F\u7528\u3001\u63D0\u4F9B\u54EA\u4E9B\u6765\u6E90\u5B57\u6BB5\uFF0C\u4EE5\u53CA\u5982\u4F55\u4F7F\u7528\u8FD9\u4E9B\u4FE1\u606F\u3002\u4EC5\u4F7F\u7528\u5DF2\u6709\u6D88\u606F\u5143\u6570\u636E\uFF0C\u4E0D\u67E5\u8BE2\u5E73\u53F0 API\u3002":"Choose which conversations to enhance, which source fields to include, and how to use them. Only existing message metadata is used; no platform APIs are queried.","\u589E\u5F3A\u63D0\u793A\u8BCD\u4E2D\u8BF7\u4F7F\u7528\u5B57\u6BB5\u540D\uFF08\u5982 senderId\u3001conversationType\uFF09\u5F15\u7528\u8FD9\u4E9B\u4FE1\u606F\u3002\u53EA\u53D1\u9001\u52FE\u9009\u4E14\u5F53\u524D\u6D88\u606F\u4E2D\u53EF\u7528\u7684\u5B57\u6BB5\uFF0C\u4E0D\u4F1A\u989D\u5916\u67E5\u8BE2\u6216\u8865\u5168\u3002":"Reference these values by field name (such as senderId or conversationType) in the guidance. Only selected fields available in the current message are sent; no extra lookups are made.","\u53EA\u9700\u586B\u5199\u6B63\u6587\uFF0C\u63D2\u4EF6\u81EA\u52A8\u6DFB\u52A0 \u6210\u5BF9\u6807\u7B7E\u3002\u6E05\u7A7A\u5E76\u4FDD\u5B58\u540E\uFF0C\u4E0D\u518D\u9644\u52A0\u589E\u5F3A\u63D0\u793A\u8BCD\uFF0C\u5DF2\u9009\u6765\u6E90\u5B57\u6BB5\u4ECD\u6309\u5F00\u5173\u8BBE\u7F6E\u53D1\u9001\u3002":"Enter only the body; the plugin adds paired tags. Clear and save to omit guidance. Selected source fields still follow the conversation switches.","\u53D1\u9001\u8005\u6807\u8BC6\u53EF\u80FD\u5305\u542B\u5E73\u53F0\u7528\u6237 ID \u6216\u7535\u8BDD\u53F7\u7801\u5F62\u5F0F\u7684\u6807\u8BC6\u3002\u5173\u95ED\u5F00\u5173\u4E0D\u4F1A\u5220\u9664\u5DF2\u7ECF\u5199\u5165\u4F1A\u8BDD\u5386\u53F2\u7684\u4FE1\u606F\u3002":"Sender IDs may contain platform user IDs or phone-number-like identifiers. Turning this off does not remove information already saved in conversation history.","\u4E0A\u4E0B\u6587\u589E\u5F3A\u4FDD\u5B58\u5931\u8D25\uFF0C\u8BF7\u91CD\u8BD5\u3002":"Could not save context enhancement. Try again.","\u8BF7\u63D0\u4EA4\u5B8C\u6574\u7684\u4E0A\u4E0B\u6587\u589E\u5F3A\u8BBE\u7F6E\u3002":"Submit the complete context enhancement settings.","\u7FA4\u804A\u548C\u79C1\u804A\u5F00\u5173\u5FC5\u987B\u662F\u5E03\u5C14\u503C\u3002":"Group and direct switches must be booleans.","\u6765\u6E90\u5B57\u6BB5\u53EA\u80FD\u9009\u62E9\u5DF2\u5B9A\u4E49\u7684\u4E94\u4E2A\u5B57\u6BB5\u3002":"Source fields must be chosen from the five defined fields.","\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\u8865\u5168\u6743\u9650:"Scan with Feishu to complete permissions",\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\u6700\u591A\u589E\u91CF\u8865\u5145\u5361\u7247\u6309\u94AE\u56DE\u8C03\u3001\u8BFB\u53D6\u7528\u6237\u6D88\u606F\u5185\u56FE\u7247\u6216\u6587\u4EF6\u6240\u9700\u7684 im:message:readonly\uFF08\u98DE\u4E66\u663E\u793A\u4E3A\u201C\u83B7\u53D6\u5355\u804A\u3001\u7FA4\u7EC4\u6D88\u606F\u201D\uFF09\uFF0C\u4EE5\u53CA\u4E0A\u4F20\u673A\u5668\u4EBA\u56FE\u7247\u6216\u6587\u4EF6\u6240\u9700\u7684 im:resource\uFF1B\u4E0D\u4F1A\u521B\u5EFA\u65B0\u5E94\u7528\u3002\u786E\u8BA4\u9875\u53EA\u663E\u793A\u5F53\u524D\u7F3A\u5C11\u9879\uFF0C\u5B8C\u6210\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 up to three missing items: the card-button callback, im:message:readonly for reading images or files in user messages (shown by Feishu as \u201CRead direct and group messages\u201D), and im:resource for uploading images or files sent by the bot. It does not create a new app. The confirmation page shows only missing items; this bot reconnects briefly afterward, while other bots are unaffected.","\u6838\u5BF9\u73B0\u6709\u5E94\u7528\u540D\u79F0\uFF0C\u5E76\u786E\u8BA4\u53EA\u65B0\u589E\u5F53\u524D\u7F3A\u5C11\u7684\u4E0A\u8FF0\u914D\u7F6E":"Review the existing app name and confirm that only the missing items described above are added","\u4FDD\u6301\u672C\u9875\u6253\u5F00\uFF0C\u7B49\u5F85\u6743\u9650\u4E0E\u56DE\u8C03\u8865\u5168\u5B8C\u6210":"Keep this page open until permissions and the callback are complete",\u53D6\u6D88\u8865\u5168:"Cancel setup","\u5DF2\u786E\u8BA4\uFF0C\u6B63\u5728\u5B8C\u6210\u6743\u9650\u4E0E\u56DE\u8C03\u914D\u7F6E":"Confirmed. Completing permissions and callback setup",\u6B63\u5728\u51C6\u5907\u6743\u9650\u8865\u5168\u4E8C\u7EF4\u7801:"Preparing the permission-completion QR code","\u914D\u7F6E\u5DF2\u63D0\u4EA4\uFF0C\u6B63\u5728\u4FDD\u5B58\u6743\u9650\u3001\u9A8C\u8BC1\u5361\u7247\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. Saving permissions, 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",\u6743\u9650\u4E0E\u56DE\u8C03\u6CA1\u6709\u8865\u5168\u5B8C\u6210:"Permissions and callback setup did not finish",\u8865\u5168\u6743\u9650:"Complete permissions",\u8865\u5168\u8303\u56F4:"Completion scope","\u6700\u591A\u589E\u91CF\u6DFB\u52A0\u5361\u7247\u56DE\u8C03 card.action.trigger\u3001\u8BFB\u53D6\u6D88\u606F\u5185\u56FE\u7247\u6216\u6587\u4EF6\u6240\u9700\u7684 im:message:readonly\uFF08\u98DE\u4E66\u663E\u793A\u4E3A\u201C\u83B7\u53D6\u5355\u804A\u3001\u7FA4\u7EC4\u6D88\u606F\u201D\uFF09\uFF0C\u4EE5\u53CA\u4E0A\u4F20\u673A\u5668\u4EBA\u56FE\u7247\u6216\u6587\u4EF6\u6240\u9700\u7684 im:resource\uFF1B\u786E\u8BA4\u9875\u53EA\u663E\u793A\u5F53\u524D\u7F3A\u5C11\u9879\uFF0C\u4E0D\u4F1A\u521B\u5EFA\u65B0\u5E94\u7528\u3002":"Adds up to the missing card callback card.action.trigger, im:message:readonly for reading images or files in messages (shown by Feishu as \u201CRead direct and group messages\u201D), and im:resource for uploading images or files sent by the bot. The confirmation page shows only missing items; no new app is created.","\u7B49\u5F85\u626B\u7801\u2026":"Waiting for scan\u2026",\u98DE\u4E66\u670D\u52A1\u8FD4\u56DE\u4E86\u4E0D\u5339\u914D\u7684\u6743\u9650\u8865\u5168\u4E8C\u7EF4\u7801:"Feishu returned a permission-completion 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\u6743\u9650\u8865\u5168\u4E8C\u7EF4\u7801\u5DF2\u751F\u6210\uFF0C\u8BF7\u4F7F\u7528\u98DE\u4E66\u626B\u7801\u3002':'Permission-completion 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\u8865\u5168\u6743\u9650\u4E0E\u56DE\u8C03\u3002":"Completing permissions and the callback was cancelled.","\u5DF2\u53D6\u6D88\u7FA4\u6D88\u606F\u6743\u9650\u6388\u6743\u3002":"Group-message permission authorization was cancelled.","\u6743\u9650\u4E0E\u56DE\u8C03\u5DF2\u66F4\u65B0\uFF0C\u4F46\u6682\u65F6\u65E0\u6CD5\u786E\u8BA4\u673A\u5668\u4EBA\u8FDE\u63A5\u72B6\u6001":"Permissions and the callback were 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\u6743\u9650\u4E0E\u56DE\u8C03\u8865\u5168\u5931\u8D25:"Could not complete Feishu permissions and callback setup",\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\u3001\u5DF2\u7ED1\u5B9A\u8D26\u53F7\u81EA\u5DF1\u53D1\u51FA\u7684\u7FA4\u804A\u6D88\u606F\uFF0C\u4EE5\u53CA\u5176\u4ED6\u7FA4\u6210\u5458\u7684\u63D0\u53CA\u6216\u56DE\u590D\u3002":"Respond to all direct messages, group messages sent by the linked account, and mentions or replies from other group members.","\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 \u8FDE\u63A5\u672A\u5C31\u7EEA\uFF0C\u63D2\u4EF6\u4F1A\u81EA\u52A8\u91CD\u8BD5\u3002":"The QQ connection is not ready; the plugin will retry automatically.","QQ \u8FDE\u63A5\u672A\u5C31\u7EEA\uFF0C\u63D2\u4EF6\u4F1A\u81EA\u52A8\u91CD\u8BD5":"The QQ connection is not ready; the plugin will retry automatically","QQ \u8FDE\u63A5\u5F53\u524D\u79BB\u7EBF":"The QQ connection is currently offline","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",\u7528\u6237:"User","\u5FAE\u4FE1\u7528\u6237 ID":"WeChat user ID","\u586B\u5199\u63A5\u6536\u6D88\u606F\u7684\u7528\u6237 ID":"Enter the recipient user ID",\u79C1\u804A:"Direct message",\u7FA4\u804A:"Group","\u7FA4 Chat ID":"Group Chat ID","\u7528\u6237 ID":"User ID","\u586B\u5199\u9489\u9489\u7528\u6237 ID":"Enter the DingTalk user ID","\u7FA4 Open Conversation ID":"Group Open Conversation ID","\u586B\u5199\u4F01\u4E1A\u5FAE\u4FE1\u7528\u6237 ID":"Enter the WeCom user ID","\u586B\u5199\u7FA4 chatid":"Enter the group chatid",\u5355\u804A:"Direct message","\u7528\u6237 Open ID":"User Open ID","\u586B\u5199 user_openid":"Enter the user_openid","\u7FA4 Open ID":"Group Open ID","\u586B\u5199 group_openid":"Enter the group_openid",\u4F1A\u8BDD:"Conversation",\u7EBF\u7A0B:"Thread","Thread \u65F6\u95F4\u6233":"Thread timestamp",\u804A\u5929:"Chat",\u8BDD\u9898:"Topic",\u9891\u9053\u6216\u79C1\u4FE1:"Channel or DM","\u586B\u5199\u53EF\u53D1\u6D88\u606F\u7684 Channel ID":"Enter a Channel ID the bot can message","\u7528\u6237 JID":"User JID","\u7FA4 JID":"Group JID","\u8BF7\u6C42\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002":"Request failed. Try again later.","\u5F53\u524D\u6D4F\u89C8\u5668\u4E0D\u652F\u6301\u81EA\u52A8\u590D\u5236\uFF0C\u8BF7\u624B\u52A8\u9009\u62E9\u590D\u5236\u3002":"Automatic copy is unavailable. Select and copy the value manually.","\u76EE\u6807\u4FDD\u5B58\u5931\u8D25\uFF0C\u8BF7\u68C0\u67E5\u540E\u91CD\u8BD5\u3002":"Could not save the target. Check it and try again.","\u65E0\u6CD5\u751F\u6210\u672A\u5360\u7528\u7684 Target ID\uFF0C\u8BF7\u91CD\u8BD5\u3002":"Could not generate an unused Target ID. Try again.",\u7F16\u8F91\u6295\u9012\u76EE\u6807:"Edit delivery target",\u65B0\u5EFA\u6295\u9012\u76EE\u6807:"New delivery target","\u5DF2\u4ECE\u4F1A\u8BDD\u81EA\u52A8\u586B\u5165\u76EE\u6807\u4FE1\u606F\uFF1B\u786E\u8BA4\u540E\u518D\u4FDD\u5B58\u3002":"Target details were filled from the conversation. Review them before saving.","\u8BF7\u624B\u52A8\u586B\u5199\u4ECE\u5BF9\u5E94\u5E73\u53F0\u53D6\u5F97\u7684\u539F\u751F\u6807\u8BC6\u3002":"Enter the native identifier from the platform manually.","\u4F8B\u5982 daily-report":"For example, daily-report","\u4F7F\u7528\u5927\u5C0F\u5199\u5B57\u6BCD\u3001\u6570\u5B57\u3001\u70B9\u3001\u4E0B\u5212\u7EBF\u3001\u5192\u53F7\u3001@ \u6216\u8FDE\u5B57\u7B26\u3002":"Use letters, numbers, dots, underscores, colons, @, or hyphens.","\u663E\u793A\u540D\u79F0\uFF08\u53EF\u9009\uFF09":"Display name (optional)","\u4F8B\u5982 \u6BCF\u65E5\u6C47\u62A5\u7FA4":"For example, Daily reports",\u76EE\u6807\u7C7B\u578B:"Target type",\u4FDD\u5B58\u76EE\u6807:"Save target",\u8BF7\u5148\u5B8C\u6210\u6295\u9012\u76EE\u6807\u8BFB\u53D6:"Wait for delivery targets to finish loading",\u4ECE\u5DF2\u804A\u8FC7\u7684\u4F1A\u8BDD\u9009\u62E9:"Choose from conversations",\u5DF2\u804A\u4F1A\u8BDD:"Conversation",\u4ECE\u4F1A\u8BDD\u9009\u62E9targetID:"Select a targetID from conversations","\u9009\u62E9\u540E\u4F1A\u81EA\u52A8\u586B\u5199\u76EE\u6807\u4FE1\u606F\u548C\u8C03\u7528\u522B\u540D\uFF0C\u786E\u8BA4\u540E\u518D\u4FDD\u5B58\u3002":"Selecting a conversation fills the target details and call alias. Review them before saving.","\u6B63\u5728\u5237\u65B0\u2026":"Refreshing\u2026",\u5237\u65B0:"Refresh","\u6B63\u5728\u8BFB\u53D6\u5DF2\u804A\u4F1A\u8BDD\u2026":"Loading known conversations\u2026","\u65E0\u6CD5\u8BFB\u53D6\u5DF2\u804A\u4F1A\u8BDD\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002":"Could not load known conversations. Try again later.",\u8FD8\u6CA1\u6709\u53EF\u9009\u62E9\u7684\u4F1A\u8BDD:"No conversations to choose from","\u5148\u5728\u5BF9\u5E94\u5E73\u53F0\u4E0E\u673A\u5668\u4EBA\u804A\u4E00\u6761\u6D88\u606F\uFF0C\u518D\u5237\u65B0\u3002":"Send the bot a message on the platform, then refresh.",\u5DF2\u6DFB\u52A0:"Added","\u624B\u52A8\u586B\u5199\uFF08\u9AD8\u7EA7\uFF09":"Enter manually (advanced)","\u6D4B\u8BD5\u6D88\u606F\u5DF2\u53D1\u9001\uFF0C\u8BF7\u5230\u76EE\u6807\u4F1A\u8BDD\u786E\u8BA4\u3002":"Test message sent. Confirm it in the target conversation.","\u6D4B\u8BD5\u53D1\u9001\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002":"Test delivery failed. Try again later.",\u5DF2\u590D\u5236\u8C03\u7528\u53C2\u6570:"Call parameters copied","\u590D\u5236\u5931\u8D25\u3002":"Copy failed.","\u5220\u9664\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002":"Could not delete the target. Try again later.",\u590D\u5236\u8C03\u7528\u53C2\u6570:"Copy call parameters",\u673A\u5668\u4EBA\u79BB\u7EBF\u65F6\u4E0D\u53EF\u53D1\u9001\u6D4B\u8BD5\u6D88\u606F:"Test delivery is unavailable while the bot is offline",\u6D4B\u8BD5\u6295\u9012\u76EE\u6807:"Test delivery target",\u6D4B\u8BD5:"Test",\u7F16\u8F91:"Edit",\u5220\u9664:"Delete","\u5220\u9664 ":"Delete ","\uFF1F\u4F7F\u7528\u8FD9\u4E2A targetId \u7684\u5916\u90E8\u8C03\u7528\u5C06\u8FD4\u56DE unknown-target\u3002":"? External calls using this targetId will return unknown-target.","\u6B63\u5728\u5220\u9664\u2026":"Deleting\u2026",\u786E\u8BA4\u5220\u9664:"Delete target","\u6295\u9012\u76EE\u6807\u8BBE\u7F6E\u6682\u4E0D\u53EF\u7528\u3002":"Delivery target settings are unavailable.","\u65E0\u6CD5\u8BFB\u53D6\u6295\u9012\u76EE\u6807\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002":"Could not load delivery targets. Try again later.","\u2190 \u8FD4\u56DE\u673A\u5668\u4EBA\u5217\u8868":"\u2190 Back to bots",\u4F7F\u7528\u6587\u6863:"User guide",\u6253\u5F00\u4E3B\u52A8\u6295\u9012\u4F7F\u7528\u6587\u6863:"Open the proactive delivery guide","\u5F53\u524D\u6E20\u9053\u6682\u4E0D\u652F\u6301\u6295\u9012\u76EE\u6807\u3002":"Delivery targets are not supported for this channel.","\u5DF2\u590D\u5236 Bot ID":"Bot ID copied",\u8C03\u7528\u6807\u8BC6:"Call identifiers",\u590D\u5236:"Copy",\u6295\u9012\u76EE\u6807:"Delivery targets","\u673A\u5668\u4EBA\u5F53\u524D\u79BB\u7EBF\uFF1B\u4ECD\u53EF\u914D\u7F6E\u76EE\u6807\uFF0C\u6062\u590D\u8FDE\u63A5\u540E\u518D\u6D4B\u8BD5\u3002":"The bot is offline. You can still configure targets and test them after reconnection.",\u65B0\u5EFA\u76EE\u6807:"New target","\u6B63\u5728\u8BFB\u53D6\u6295\u9012\u76EE\u6807\u2026":"Loading delivery targets\u2026",\u5C1A\u672A\u914D\u7F6E\u6295\u9012\u76EE\u6807:"No delivery targets yet","\u70B9\u51FB\u201C\u65B0\u5EFA\u76EE\u6807\u201D\u53EF\u4ECE\u5DF2\u804A\u8FC7\u7684\u4F1A\u8BDD\u9009\u62E9\uFF0C\u4E5F\u53EF\u624B\u52A8\u586B\u5199\u3002":"Select New target to choose a conversation or enter the details manually."});var gcA=Object.freeze(Object.fromEntries(Object.keys(nke).map(n=>[n,n==="$locale"?"zh":n])));var ccA=Object.freeze(["aria-label","alt","placeholder","title"]);var ske=Object.freeze({defaultId:"",items:Object.freeze([])}),dcA=Td.createContext(ske);var gP="/feishu",Ot=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",setContextEnhancement:"bot.context-enhancement.set",setGroupResponseMode:"bot.group-response-mode.set",testConnection:"connection.test",disconnect:"connection.disconnect"}),mcA=Object.freeze({PROVISION:"provision",CALLBACK_REPAIR:"callback_repair",GROUP_MESSAGE_PERMISSION:"group_message_permission"});var il=Object.freeze({reconnectBot:"bot.reconnect",disconnectBot:"bot.disconnect",deleteBot:"bot.delete"}),f6=Object.freeze([...new Set([...Object.values(Ot),...Object.values(il)])]),cke=new Set(["idle","starting","qr_ready","polling","slow_down","domain_switched","saving","succeeded","expired","cancelled","error"]),Ike=new Set(["provision","callback_repair","group_message_permission"]),Q6="callback_repair",IP="group_message_permission",fS=new Set([Q6,IP]),lke=new Set(["accounts.feishu.cn","accounts.larksuite.com","open.feishu.cn","open.larksuite.com"]),pke=/^[A-Za-z0-9_-]{1,128}$/,dke=/^cli_[A-Za-z0-9_-]+$/,E6=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."}),hke=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 Eke(n){if(n===null||typeof n!="object"||Array.isArray(n))return!1;let t=Object.getPrototypeOf(n);return t===Object.prototype||t===null}function Fo(n,t){return Eke(n)&&Reflect.ownKeys(n).every(o=>typeof o=="string"&&t.has(o))}function mu(n){return Number.isFinite(n)?n:void 0}function mn(n){return typeof n=="string"&&pke.test(n)}function C6(n,t){return typeof n=="string"&&n.trim().length>0&&n.length<=t}function pP(n){if(!n||typeof n!="object")return null;let t=typeof n.code=="string"&&Object.hasOwn(E6,n.code)?n.code:"registration_failed";return{code:t,message:E6[t]}}function ds(n){if(!n||typeof n!="object")return{state:"idle",attempt:0};let t=cke.has(n.state)?n.state:"error",o=mn(n.attempt)?n.attempt:mu(n.attempt)??0,i={state:t,attempt:o};i.operation=Ike.has(n.operation)?n.operation:"provision";let e=mu(n.updatedAt),a=mu(n.expiresAt),A=mu(n.remainingSeconds),r=mu(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),mn(n.botId)&&(i.botId=n.botId);let s=pP(n.error);return s&&(i.error=s),i}function Cke(n,t,o){if(!(typeof n!="string"||n.length===0))try{let i=new URL(n);if(i.protocol!=="https:"||!lke.has(i.hostname)||i.port||i.username||i.password)return;if(fS.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"||!dke.test(e[0]??"")||i.hostname!==o||i.searchParams.has("createOnly")||A.length!==1||!A[0]?.trim()||r)return}return i.toString()}catch{return}}function QS(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 y6(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 m6(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 S6(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 w6(n){return gke.toDataURL(n,{errorCorrectionLevel:"M",margin:1,width:320,type:"image/png"})}async function uke(n,t,o){let i=Cke(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"&&fS.has(n.operation)&&n.botId)return{...e,submitted:!0}}function Bke(n){let t=n&&typeof n=="object"?n:{};if(!mn(t.botId))return null;let o=QS(t.connection),i=t.connected===!0||o.connected,e={state:"idle"},a={botId:t.botId,state:S6(t,e,i),connected:i,configured:t.configured===!0,agentPreset:$s(t.agentPreset),contextEnhancement:Bp(t.contextEnhancement),groupResponseMode:ro(t.groupResponseMode),groupMessagePermissionGranted:t.groupMessagePermissionGranted===!0,bot:y6(t.bot),health:m6(t,i)};typeof t.workspace=="string"&&t.workspace&&(a.workspace=t.workspace);let A=Vr(t.lastMessageError);A&&(a.lastMessageError=A);let r=pP(t.error);return r&&(a.error=r),a}async function Wa(n,{encodeQr:t=w6}={}){let o=n&&typeof n=="object"?n:{},i=ds(o.registration),e=QS(o.connection),a=o.connected===!0||e.connected,r=(fS.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 uke(i,t,r),g=pP(o.error)??i.error??null,c=Array.isArray(o.bots)?o.bots.map(Bke).filter(Boolean):[],I={schemaVersion:o.schemaVersion===2?2:1,revision:Number.isSafeInteger(o.revision)&&o.revision>=0?o.revision:0,state:S6(o,i,a),connected:a,configured:o.configured===!0,bot:y6(o.bot),health:m6(o,a),bots:c,agentPresetCatalog:Jn(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 uS(n){return{ok:!1,error:{code:"bad-request",message:n,details:{issues:[]}}}}function BS(){return{ok:!1,error:{code:"cancelled",message:"The Feishu request was cancelled.",details:{}}}}function fke(){return{ok:!1,error:{code:"internal",message:"The Feishu integration operation failed.",details:{}}}}function Qke(n,t){return n===Ot.status?Fo(t,new Set)?null:"This endpoint accepts an empty payload only.":n===Ot.testConnection?Fo(t,new Set)?null:"This endpoint accepts an empty payload only.":n===Ot.beginProvisioning?Fo(t,new Set(["locale","replaceAttemptId"]))?t.locale!==void 0&&t.locale!=="zh-CN"?"The provisioning locale must be zh-CN.":t.replaceAttemptId!==void 0&&!mn(t.replaceAttemptId)?"replaceAttemptId must be a valid opaque id.":null:"Provisioning accepts locale and replaceAttemptId only.":n===Ot.beginCallbackRepair?Fo(t,new Set(["botId"]))&&mn(t.botId)?null:"Callback repair requires a single valid botId.":n===Ot.beginGroupMessagePermission?Fo(t,new Set(["botId"]))&&mn(t.botId)?null:"Group message permission update requires a single valid botId.":n===Ot.bindCredentials?Fo(t,new Set(["appId","appSecret"]))&&C6(t.appId,256)&&C6(t.appSecret,1024)?null:"Credential binding requires App ID and App Secret.":n===Ot.pollProvisioning||n===Ot.cancelProvisioning?Fo(t,new Set(["attemptId"]))&&mn(t.attemptId)?null:"A single valid attemptId is required.":n===Ot.disconnect?Fo(t,new Set(["removeCredentials"]))&&t.removeCredentials===!0?null:"Disconnect requires removeCredentials=true.":n===il.reconnectBot?Fo(t,new Set(["botId","sendTest"]))&&mn(t.botId)&&(t.sendTest===void 0||typeof t.sendTest=="boolean")?null:"A valid botId and optional sendTest flag are required.":n===il.disconnectBot?Fo(t,new Set(["botId"]))&&mn(t.botId)?null:"A single valid botId is required.":n===il.deleteBot?Fo(t,new Set(["botId","confirm"]))&&mn(t.botId)&&t.confirm===!0?null:"Deleting a bot requires a valid botId and confirm=true.":n===Ot.setWorkspace?xa(t)?null:"\u8BF7\u8F93\u5165\u5DE5\u4F5C\u533A\u7EDD\u5BF9\u8DEF\u5F84\u3002":n===Ot.setAgentPreset?ja(t)?null:"\u8BF7\u9009\u62E9 Agent Preset\u3002":n===Ot.setContextEnhancement?Ka(t)?null:"\u8BF7\u63D0\u4EA4\u6709\u6548\u7684\u4E0A\u4E0B\u6587\u589E\u5F3A\u8BBE\u7F6E\u3002":n===Ot.setGroupResponseMode?Fo(t,new Set(["botId","groupResponseMode"]))&&mn(t.botId)&&zm(t.groupResponseMode)?null:"\u8BF7\u9009\u62E9\u7FA4\u804A\u54CD\u5E94\u65B9\u5F0F\u3002":"Unknown Feishu endpoint."}function yke(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 lP(n,t){return typeof n.registrationStatus=="function"?n.registrationStatus(t):n.status()}async function cP(n,t,o,i){let e=t,a=Date.now()+15e3;for(;;){let A=ds(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 yke(50,i),e=await lP(n,o),!e)throw new Error("The provisioning attempt is no longer active.")}}function u6(n,t){return String(ds(n?.registration).attempt)===t}function B6(n){let t=ds(n?.registration);return t.state==="succeeded"?t.botId&&(n?.connected===!0||QS(n?.connection).connected)?"connected":"connecting":hke[t.state]??"failed"}function mke(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 D6(n,{encodeQr:t=w6}={}){mke(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 BS();if(!f6.includes(a))return uS("Unknown Feishu endpoint.");let s=Qke(a,A);if(s)return uS(s);try{let g;if(a===Ot.status)g=await Wa(await n.status(),{encodeQr:e});else if(a===Ot.beginProvisioning){A.replaceAttemptId&&await n.cancelRegistration(A.replaceAttemptId);let c=await n.startRegistration({locale:A.locale}),I=String(ds(c?.registration).attempt),d=await cP(n,c,I,r);if(g=(await Wa(d,{encodeQr:e})).provisioning,!g)throw new Error("Provisioning did not produce a QR code.");i.set(I,g.verificationUrl)}else if(a===Ot.beginCallbackRepair){if(typeof n.startCallbackRepair!="function")throw new Error("Feishu callback repair is unavailable.");let c=await n.startCallbackRepair(A.botId),I=String(ds(c?.registration).attempt),d=await cP(n,c,I,r);if(g=(await Wa(d,{encodeQr:e})).provisioning,!g||g.operation!==Q6||g.botId!==A.botId)throw new Error("Callback repair did not produce a safe QR code.");i.set(I,g.verificationUrl)}else if(a===Ot.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(ds(c?.registration).attempt),d=await cP(n,c,I,r);if(g=(await Wa(d,{encodeQr:e})).provisioning,!g||g.operation!==IP||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===Ot.pollProvisioning){let c=await lP(n,A.attemptId);if(!c||!u6(c,A.attemptId))return uS("The provisioning attempt is no longer active.");let I=ds(c.registration),d=await Wa(c,{encodeQr:e});if(g={status:B6(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===Ot.cancelProvisioning){let c=await lP(n,A.attemptId);if(!c||!u6(c,A.attemptId))return uS("The provisioning attempt is no longer active.");let I=typeof n.registrationStatus=="function",d=ds(c.registration),B;!I&&d.state==="saving"?B=await n.disconnect():B=await n.cancelRegistration(A.attemptId);let f=ds(B?.registration);if(fS.has(d.operation)&&d.state==="saving"&&["saving","succeeded"].includes(f.state)&&(g={status:B6(B),operation:f.operation,...f.botId?{botId:f.botId}:{},message:d.operation===IP?"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===Ot.bindCredentials){if(typeof n.bindCredentials!="function")throw new Error("Credential binding is unavailable");g=await Wa(await n.bindCredentials(A),{encodeQr:e})}else if(a===Ot.testConnection){let c=await n.status(),d=c?.connected===!0||QS(c?.connection).connected||typeof n.reconnect!="function"?c:await n.reconnect();g=await Wa(d,{encodeQr:e})}else if(a===Ot.disconnect)g=await Wa(await n.disconnect(),{encodeQr:e});else if(a===il.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 BS();if(g=await Wa(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:ir(I)}}}else if(a===il.disconnectBot){if(typeof n.disconnectBot!="function")throw new Error("Multi-bot disconnect is unavailable");g=await Wa(await n.disconnectBot(A.botId),{encodeQr:e})}else if(a===Ot.setWorkspace){if(typeof n.updateWorkspace!="function")throw new Error("Workspace update is unavailable");g=await Wa(await n.updateWorkspace(A.botId,A.workspace),{encodeQr:e})}else if(a===Ot.setContextEnhancement){if(typeof n.updateContextEnhancement!="function")throw new Error("Context enhancement update is unavailable");g=await n.updateContextEnhancement(A.botId,A.config,c=>Wa(c,{encodeQr:e}))}else if(a===Ot.setAgentPreset){if(typeof n.updateAgentPreset!="function")throw new Error("Agent preset update is unavailable");g=await Wa(await n.updateAgentPreset(A.botId,A.agentPreset),{encodeQr:e})}else if(a===Ot.setGroupResponseMode){if(typeof n.updateGroupResponseMode!="function")throw new Error("Group response mode update is unavailable");g=await Wa(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 Wa(await n.deleteBot(A.botId),{encodeQr:e})}return r?.aborted?BS():{ok:!0,value:g}}catch(g){let c=Ya(g);return r?.aborted?BS():c?{ok:!1,error:{...c,details:{}}}:fke()}}}function yS(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(gP,D6(t,o),{authority:Er(i)})}function Ske(n,t){if(t?.controller)return t.controller;if(typeof t?.createController=="function")return t.createController();if(typeof t?.createProvisioningManager=="function")return x_(t)}async function O6(n,t={}){let o=Ske(n,t);if(o)return yS(n,o,t.rpcOptions,t.rpcAuthority);let i=await AP(n,t),e=t.deliveryService&&i.deliveryAdapter?t.deliveryService.registerAdapter(i.deliveryAdapter):void 0,a=yS(n,i.controller,t.rpcOptions,t.rpcAuthority);return n.effect(()=>async()=>{await e?.(),await i.close()},"dsh-feishu: close controller and live connection"),a}import{unlink as fve}from"node:fs/promises";import{homedir as Qve}from"node:os";import{join as bu,resolve as sl}from"node:path";import{createHash as wke}from"node:crypto";import{mkdir as Dke,readFile as Oke,rename as bke,unlink as Mke,writeFile as _ke}from"node:fs/promises";import{dirname as Tke}from"node:path";var dP=Object.freeze({version:1,bots:Object.freeze([])});function Sc(n){return typeof n=="string"&&n.trim()?n.trim():null}function b6(n){let t=Sc(n);return t&&/^qq_[a-f0-9]{24}$/.test(t)?t:null}function Nke(n){let t=Sc(n);return t&&/^DSH_QQBOT_APP_SECRET_[A-F0-9]{24}$/.test(t)?t:null}function SS(n){let t=Sc(n);if(!t)throw new TypeError("appId is required");let o=wke("sha256").update(t).digest("hex").slice(0,24);return{botId:`qq_${o}`,secretRef:`DSH_QQBOT_APP_SECRET_${o.toUpperCase()}`}}function hP(n){let t=Sc(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 M6(n){if(!n||typeof n!="object")return null;let t=Sc(n.appId),o=Sc(n.ownerUserOpenid),i=b6(n.botId),e=Nke(n.secretRef);if(!t||!o||!i||!e)return null;let a=SS(t);return a.botId!==i||a.secretRef!==e?null:Object.freeze({botId:i,appId:t,secretRef:e,ownerUserOpenid:o,createdAt:Sc(n.createdAt)??new Date().toISOString(),connectedAt:Sc(n.connectedAt)})}function Rke(n){if(!n||n.version!==1||!Array.isArray(n.bots))return null;let t=n.bots.map(M6);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 mS=class{#e;#A=dP;#t=Promise.resolve();constructor(t){this.#e=t}async load(){try{let t=Rke(JSON.parse(await Oke(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=dP}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=M6(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(!b6(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 Mke(this.#e)}catch(o){if(o?.code!=="ENOENT")throw o}this.#A=dP});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.#g(a),this.#A=a});return this.#t=i.then(()=>{},()=>{}),await i,o}async#g(t){await Dke(Tke(this.#e),{recursive:!0,mode:448});let o=`${this.#e}.tmp`;await _ke(o,`${JSON.stringify(t,null,2)} +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\u8865\u5168\u6743\u9650:"Scan with Feishu to complete permissions",\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\u6700\u591A\u589E\u91CF\u8865\u5145\u5361\u7247\u6309\u94AE\u56DE\u8C03\u3001\u8BFB\u53D6\u7528\u6237\u6D88\u606F\u5185\u56FE\u7247\u6216\u6587\u4EF6\u6240\u9700\u7684 im:message:readonly\uFF08\u98DE\u4E66\u663E\u793A\u4E3A\u201C\u83B7\u53D6\u5355\u804A\u3001\u7FA4\u7EC4\u6D88\u606F\u201D\uFF09\uFF0C\u4EE5\u53CA\u4E0A\u4F20\u673A\u5668\u4EBA\u56FE\u7247\u6216\u6587\u4EF6\u6240\u9700\u7684 im:resource\uFF1B\u4E0D\u4F1A\u521B\u5EFA\u65B0\u5E94\u7528\u3002\u786E\u8BA4\u9875\u53EA\u663E\u793A\u5F53\u524D\u7F3A\u5C11\u9879\uFF0C\u5B8C\u6210\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 up to three missing items: the card-button callback, im:message:readonly for reading images or files in user messages (shown by Feishu as \u201CRead direct and group messages\u201D), and im:resource for uploading images or files sent by the bot. It does not create a new app. The confirmation page shows only missing items; this bot reconnects briefly afterward, while other bots are unaffected.","\u6838\u5BF9\u73B0\u6709\u5E94\u7528\u540D\u79F0\uFF0C\u5E76\u786E\u8BA4\u53EA\u65B0\u589E\u5F53\u524D\u7F3A\u5C11\u7684\u4E0A\u8FF0\u914D\u7F6E":"Review the existing app name and confirm that only the missing items described above are added","\u4FDD\u6301\u672C\u9875\u6253\u5F00\uFF0C\u7B49\u5F85\u6743\u9650\u4E0E\u56DE\u8C03\u8865\u5168\u5B8C\u6210":"Keep this page open until permissions and the callback are complete",\u53D6\u6D88\u8865\u5168:"Cancel setup","\u5DF2\u786E\u8BA4\uFF0C\u6B63\u5728\u5B8C\u6210\u6743\u9650\u4E0E\u56DE\u8C03\u914D\u7F6E":"Confirmed. Completing permissions and callback setup",\u6B63\u5728\u51C6\u5907\u6743\u9650\u8865\u5168\u4E8C\u7EF4\u7801:"Preparing the permission-completion QR code","\u914D\u7F6E\u5DF2\u63D0\u4EA4\uFF0C\u6B63\u5728\u4FDD\u5B58\u6743\u9650\u3001\u9A8C\u8BC1\u5361\u7247\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. Saving permissions, 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",\u6743\u9650\u4E0E\u56DE\u8C03\u6CA1\u6709\u8865\u5168\u5B8C\u6210:"Permissions and callback setup did not finish",\u8865\u5168\u6743\u9650:"Complete permissions",\u8865\u5168\u8303\u56F4:"Completion scope","\u6700\u591A\u589E\u91CF\u6DFB\u52A0\u5361\u7247\u56DE\u8C03 card.action.trigger\u3001\u8BFB\u53D6\u6D88\u606F\u5185\u56FE\u7247\u6216\u6587\u4EF6\u6240\u9700\u7684 im:message:readonly\uFF08\u98DE\u4E66\u663E\u793A\u4E3A\u201C\u83B7\u53D6\u5355\u804A\u3001\u7FA4\u7EC4\u6D88\u606F\u201D\uFF09\uFF0C\u4EE5\u53CA\u4E0A\u4F20\u673A\u5668\u4EBA\u56FE\u7247\u6216\u6587\u4EF6\u6240\u9700\u7684 im:resource\uFF1B\u786E\u8BA4\u9875\u53EA\u663E\u793A\u5F53\u524D\u7F3A\u5C11\u9879\uFF0C\u4E0D\u4F1A\u521B\u5EFA\u65B0\u5E94\u7528\u3002":"Adds up to the missing card callback card.action.trigger, im:message:readonly for reading images or files in messages (shown by Feishu as \u201CRead direct and group messages\u201D), and im:resource for uploading images or files sent by the bot. The confirmation page shows only missing items; no new app is created.","\u7B49\u5F85\u626B\u7801\u2026":"Waiting for scan\u2026",\u98DE\u4E66\u670D\u52A1\u8FD4\u56DE\u4E86\u4E0D\u5339\u914D\u7684\u6743\u9650\u8865\u5168\u4E8C\u7EF4\u7801:"Feishu returned a permission-completion 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\u6743\u9650\u8865\u5168\u4E8C\u7EF4\u7801\u5DF2\u751F\u6210\uFF0C\u8BF7\u4F7F\u7528\u98DE\u4E66\u626B\u7801\u3002':'Permission-completion 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\u8865\u5168\u6743\u9650\u4E0E\u56DE\u8C03\u3002":"Completing permissions and the callback was cancelled.","\u5DF2\u53D6\u6D88\u7FA4\u6D88\u606F\u6743\u9650\u6388\u6743\u3002":"Group-message permission authorization was cancelled.","\u6743\u9650\u4E0E\u56DE\u8C03\u5DF2\u66F4\u65B0\uFF0C\u4F46\u6682\u65F6\u65E0\u6CD5\u786E\u8BA4\u673A\u5668\u4EBA\u8FDE\u63A5\u72B6\u6001":"Permissions and the callback were 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\u6743\u9650\u4E0E\u56DE\u8C03\u8865\u5168\u5931\u8D25:"Could not complete Feishu permissions and callback setup",\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\u3001\u5DF2\u7ED1\u5B9A\u8D26\u53F7\u81EA\u5DF1\u53D1\u51FA\u7684\u7FA4\u804A\u6D88\u606F\uFF0C\u4EE5\u53CA\u5176\u4ED6\u7FA4\u6210\u5458\u7684\u63D0\u53CA\u6216\u56DE\u590D\u3002":"Respond to all direct messages, group messages sent by the linked account, and mentions or replies from other group members.","\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 \u8FDE\u63A5\u672A\u5C31\u7EEA\uFF0C\u63D2\u4EF6\u4F1A\u81EA\u52A8\u91CD\u8BD5\u3002":"The QQ connection is not ready; the plugin will retry automatically.","QQ \u8FDE\u63A5\u672A\u5C31\u7EEA\uFF0C\u63D2\u4EF6\u4F1A\u81EA\u52A8\u91CD\u8BD5":"The QQ connection is not ready; the plugin will retry automatically","QQ \u8FDE\u63A5\u5F53\u524D\u79BB\u7EBF":"The QQ connection is currently offline","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",\u7528\u6237:"User","\u5FAE\u4FE1\u7528\u6237 ID":"WeChat user ID","\u586B\u5199\u63A5\u6536\u6D88\u606F\u7684\u7528\u6237 ID":"Enter the recipient user ID",\u79C1\u804A:"Direct message",\u7FA4\u804A:"Group","\u7FA4 Chat ID":"Group Chat ID","\u7528\u6237 ID":"User ID","\u586B\u5199\u9489\u9489\u7528\u6237 ID":"Enter the DingTalk user ID","\u7FA4 Open Conversation ID":"Group Open Conversation ID","\u586B\u5199\u4F01\u4E1A\u5FAE\u4FE1\u7528\u6237 ID":"Enter the WeCom user ID","\u586B\u5199\u7FA4 chatid":"Enter the group chatid",\u5355\u804A:"Direct message","\u7528\u6237 Open ID":"User Open ID","\u586B\u5199 user_openid":"Enter the user_openid","\u7FA4 Open ID":"Group Open ID","\u586B\u5199 group_openid":"Enter the group_openid",\u4F1A\u8BDD:"Conversation",\u7EBF\u7A0B:"Thread","Thread \u65F6\u95F4\u6233":"Thread timestamp",\u804A\u5929:"Chat",\u8BDD\u9898:"Topic",\u9891\u9053\u6216\u79C1\u4FE1:"Channel or DM","\u586B\u5199\u53EF\u53D1\u6D88\u606F\u7684 Channel ID":"Enter a Channel ID the bot can message","\u7528\u6237 JID":"User JID","\u7FA4 JID":"Group JID","\u8BF7\u6C42\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002":"Request failed. Try again later.","\u5F53\u524D\u6D4F\u89C8\u5668\u4E0D\u652F\u6301\u81EA\u52A8\u590D\u5236\uFF0C\u8BF7\u624B\u52A8\u9009\u62E9\u590D\u5236\u3002":"Automatic copy is unavailable. Select and copy the value manually.","\u76EE\u6807\u4FDD\u5B58\u5931\u8D25\uFF0C\u8BF7\u68C0\u67E5\u540E\u91CD\u8BD5\u3002":"Could not save the target. Check it and try again.","\u65E0\u6CD5\u751F\u6210\u672A\u5360\u7528\u7684 Target ID\uFF0C\u8BF7\u91CD\u8BD5\u3002":"Could not generate an unused Target ID. Try again.",\u7F16\u8F91\u6295\u9012\u76EE\u6807:"Edit delivery target",\u65B0\u5EFA\u6295\u9012\u76EE\u6807:"New delivery target","\u5DF2\u4ECE\u4F1A\u8BDD\u81EA\u52A8\u586B\u5165\u76EE\u6807\u4FE1\u606F\uFF1B\u786E\u8BA4\u540E\u518D\u4FDD\u5B58\u3002":"Target details were filled from the conversation. Review them before saving.","\u8BF7\u624B\u52A8\u586B\u5199\u4ECE\u5BF9\u5E94\u5E73\u53F0\u53D6\u5F97\u7684\u539F\u751F\u6807\u8BC6\u3002":"Enter the native identifier from the platform manually.","\u4F8B\u5982 daily-report":"For example, daily-report","\u4F7F\u7528\u5927\u5C0F\u5199\u5B57\u6BCD\u3001\u6570\u5B57\u3001\u70B9\u3001\u4E0B\u5212\u7EBF\u3001\u5192\u53F7\u3001@ \u6216\u8FDE\u5B57\u7B26\u3002":"Use letters, numbers, dots, underscores, colons, @, or hyphens.","\u663E\u793A\u540D\u79F0\uFF08\u53EF\u9009\uFF09":"Display name (optional)","\u4F8B\u5982 \u6BCF\u65E5\u6C47\u62A5\u7FA4":"For example, Daily reports",\u76EE\u6807\u7C7B\u578B:"Target type",\u4FDD\u5B58\u76EE\u6807:"Save target",\u8BF7\u5148\u5B8C\u6210\u6295\u9012\u76EE\u6807\u8BFB\u53D6:"Wait for delivery targets to finish loading",\u4ECE\u5DF2\u804A\u8FC7\u7684\u4F1A\u8BDD\u9009\u62E9:"Choose from conversations",\u5DF2\u804A\u4F1A\u8BDD:"Conversation",\u4ECE\u4F1A\u8BDD\u9009\u62E9targetID:"Select a targetID from conversations","\u9009\u62E9\u540E\u4F1A\u81EA\u52A8\u586B\u5199\u76EE\u6807\u4FE1\u606F\u548C\u8C03\u7528\u522B\u540D\uFF0C\u786E\u8BA4\u540E\u518D\u4FDD\u5B58\u3002":"Selecting a conversation fills the target details and call alias. Review them before saving.","\u6B63\u5728\u5237\u65B0\u2026":"Refreshing\u2026",\u5237\u65B0:"Refresh","\u6B63\u5728\u8BFB\u53D6\u5DF2\u804A\u4F1A\u8BDD\u2026":"Loading known conversations\u2026","\u65E0\u6CD5\u8BFB\u53D6\u5DF2\u804A\u4F1A\u8BDD\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002":"Could not load known conversations. Try again later.",\u8FD8\u6CA1\u6709\u53EF\u9009\u62E9\u7684\u4F1A\u8BDD:"No conversations to choose from","\u5148\u5728\u5BF9\u5E94\u5E73\u53F0\u4E0E\u673A\u5668\u4EBA\u804A\u4E00\u6761\u6D88\u606F\uFF0C\u518D\u5237\u65B0\u3002":"Send the bot a message on the platform, then refresh.",\u5DF2\u6DFB\u52A0:"Added","\u624B\u52A8\u586B\u5199\uFF08\u9AD8\u7EA7\uFF09":"Enter manually (advanced)","\u6D4B\u8BD5\u6D88\u606F\u5DF2\u53D1\u9001\uFF0C\u8BF7\u5230\u76EE\u6807\u4F1A\u8BDD\u786E\u8BA4\u3002":"Test message sent. Confirm it in the target conversation.","\u6D4B\u8BD5\u53D1\u9001\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002":"Test delivery failed. Try again later.",\u5DF2\u590D\u5236\u8C03\u7528\u53C2\u6570:"Call parameters copied","\u590D\u5236\u5931\u8D25\u3002":"Copy failed.","\u5220\u9664\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002":"Could not delete the target. Try again later.",\u590D\u5236\u8C03\u7528\u53C2\u6570:"Copy call parameters",\u673A\u5668\u4EBA\u79BB\u7EBF\u65F6\u4E0D\u53EF\u53D1\u9001\u6D4B\u8BD5\u6D88\u606F:"Test delivery is unavailable while the bot is offline",\u6D4B\u8BD5\u6295\u9012\u76EE\u6807:"Test delivery target",\u6D4B\u8BD5:"Test",\u7F16\u8F91:"Edit",\u5220\u9664:"Delete","\u5220\u9664 ":"Delete ","\uFF1F\u4F7F\u7528\u8FD9\u4E2A targetId \u7684\u5916\u90E8\u8C03\u7528\u5C06\u8FD4\u56DE unknown-target\u3002":"? External calls using this targetId will return unknown-target.","\u6B63\u5728\u5220\u9664\u2026":"Deleting\u2026",\u786E\u8BA4\u5220\u9664:"Delete target","\u6295\u9012\u76EE\u6807\u8BBE\u7F6E\u6682\u4E0D\u53EF\u7528\u3002":"Delivery target settings are unavailable.","\u65E0\u6CD5\u8BFB\u53D6\u6295\u9012\u76EE\u6807\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002":"Could not load delivery targets. Try again later.","\u2190 \u8FD4\u56DE\u673A\u5668\u4EBA\u5217\u8868":"\u2190 Back to bots",\u4F7F\u7528\u6587\u6863:"User guide",\u6253\u5F00\u4E3B\u52A8\u6295\u9012\u4F7F\u7528\u6587\u6863:"Open the proactive delivery guide","\u5F53\u524D\u6E20\u9053\u6682\u4E0D\u652F\u6301\u6295\u9012\u76EE\u6807\u3002":"Delivery targets are not supported for this channel.","\u5DF2\u590D\u5236 Bot ID":"Bot ID copied",\u590D\u5236:"Copy",\u6295\u9012\u76EE\u6807:"Delivery targets","\u673A\u5668\u4EBA\u5F53\u524D\u79BB\u7EBF\uFF1B\u4ECD\u53EF\u914D\u7F6E\u76EE\u6807\uFF0C\u6062\u590D\u8FDE\u63A5\u540E\u518D\u6D4B\u8BD5\u3002":"The bot is offline. You can still configure targets and test them after reconnection.",\u65B0\u5EFA\u76EE\u6807:"New target","\u6B63\u5728\u8BFB\u53D6\u6295\u9012\u76EE\u6807\u2026":"Loading delivery targets\u2026",\u5C1A\u672A\u914D\u7F6E\u6295\u9012\u76EE\u6807:"No delivery targets yet","\u70B9\u51FB\u201C\u65B0\u5EFA\u76EE\u6807\u201D\u53EF\u4ECE\u5DF2\u804A\u8FC7\u7684\u4F1A\u8BDD\u9009\u62E9\uFF0C\u4E5F\u53EF\u624B\u52A8\u586B\u5199\u3002":"Select New target to choose a conversation or enter the details manually."});var gcA=Object.freeze(Object.fromEntries(Object.keys(nke).map(n=>[n,n==="$locale"?"zh":n])));var ccA=Object.freeze(["aria-label","alt","placeholder","title"]);var ske=Object.freeze({defaultId:"",items:Object.freeze([])}),dcA=Td.createContext(ske);var gP="/feishu",Ot=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",setContextEnhancement:"bot.context-enhancement.set",setGroupResponseMode:"bot.group-response-mode.set",testConnection:"connection.test",disconnect:"connection.disconnect"}),mcA=Object.freeze({PROVISION:"provision",CALLBACK_REPAIR:"callback_repair",GROUP_MESSAGE_PERMISSION:"group_message_permission"});var il=Object.freeze({reconnectBot:"bot.reconnect",disconnectBot:"bot.disconnect",deleteBot:"bot.delete"}),f6=Object.freeze([...new Set([...Object.values(Ot),...Object.values(il)])]),cke=new Set(["idle","starting","qr_ready","polling","slow_down","domain_switched","saving","succeeded","expired","cancelled","error"]),Ike=new Set(["provision","callback_repair","group_message_permission"]),Q6="callback_repair",IP="group_message_permission",fS=new Set([Q6,IP]),lke=new Set(["accounts.feishu.cn","accounts.larksuite.com","open.feishu.cn","open.larksuite.com"]),pke=/^[A-Za-z0-9_-]{1,128}$/,dke=/^cli_[A-Za-z0-9_-]+$/,E6=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."}),hke=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 Eke(n){if(n===null||typeof n!="object"||Array.isArray(n))return!1;let t=Object.getPrototypeOf(n);return t===Object.prototype||t===null}function Fo(n,t){return Eke(n)&&Reflect.ownKeys(n).every(o=>typeof o=="string"&&t.has(o))}function mu(n){return Number.isFinite(n)?n:void 0}function mn(n){return typeof n=="string"&&pke.test(n)}function C6(n,t){return typeof n=="string"&&n.trim().length>0&&n.length<=t}function pP(n){if(!n||typeof n!="object")return null;let t=typeof n.code=="string"&&Object.hasOwn(E6,n.code)?n.code:"registration_failed";return{code:t,message:E6[t]}}function ds(n){if(!n||typeof n!="object")return{state:"idle",attempt:0};let t=cke.has(n.state)?n.state:"error",o=mn(n.attempt)?n.attempt:mu(n.attempt)??0,i={state:t,attempt:o};i.operation=Ike.has(n.operation)?n.operation:"provision";let e=mu(n.updatedAt),a=mu(n.expiresAt),A=mu(n.remainingSeconds),r=mu(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),mn(n.botId)&&(i.botId=n.botId);let s=pP(n.error);return s&&(i.error=s),i}function Cke(n,t,o){if(!(typeof n!="string"||n.length===0))try{let i=new URL(n);if(i.protocol!=="https:"||!lke.has(i.hostname)||i.port||i.username||i.password)return;if(fS.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"||!dke.test(e[0]??"")||i.hostname!==o||i.searchParams.has("createOnly")||A.length!==1||!A[0]?.trim()||r)return}return i.toString()}catch{return}}function QS(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 y6(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 m6(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 S6(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 w6(n){return gke.toDataURL(n,{errorCorrectionLevel:"M",margin:1,width:320,type:"image/png"})}async function uke(n,t,o){let i=Cke(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"&&fS.has(n.operation)&&n.botId)return{...e,submitted:!0}}function Bke(n){let t=n&&typeof n=="object"?n:{};if(!mn(t.botId))return null;let o=QS(t.connection),i=t.connected===!0||o.connected,e={state:"idle"},a={botId:t.botId,state:S6(t,e,i),connected:i,configured:t.configured===!0,agentPreset:$s(t.agentPreset),contextEnhancement:Bp(t.contextEnhancement),groupResponseMode:ro(t.groupResponseMode),groupMessagePermissionGranted:t.groupMessagePermissionGranted===!0,bot:y6(t.bot),health:m6(t,i)};typeof t.workspace=="string"&&t.workspace&&(a.workspace=t.workspace);let A=Vr(t.lastMessageError);A&&(a.lastMessageError=A);let r=pP(t.error);return r&&(a.error=r),a}async function Wa(n,{encodeQr:t=w6}={}){let o=n&&typeof n=="object"?n:{},i=ds(o.registration),e=QS(o.connection),a=o.connected===!0||e.connected,r=(fS.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 uke(i,t,r),g=pP(o.error)??i.error??null,c=Array.isArray(o.bots)?o.bots.map(Bke).filter(Boolean):[],I={schemaVersion:o.schemaVersion===2?2:1,revision:Number.isSafeInteger(o.revision)&&o.revision>=0?o.revision:0,state:S6(o,i,a),connected:a,configured:o.configured===!0,bot:y6(o.bot),health:m6(o,a),bots:c,agentPresetCatalog:Jn(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 uS(n){return{ok:!1,error:{code:"bad-request",message:n,details:{issues:[]}}}}function BS(){return{ok:!1,error:{code:"cancelled",message:"The Feishu request was cancelled.",details:{}}}}function fke(){return{ok:!1,error:{code:"internal",message:"The Feishu integration operation failed.",details:{}}}}function Qke(n,t){return n===Ot.status?Fo(t,new Set)?null:"This endpoint accepts an empty payload only.":n===Ot.testConnection?Fo(t,new Set)?null:"This endpoint accepts an empty payload only.":n===Ot.beginProvisioning?Fo(t,new Set(["locale","replaceAttemptId"]))?t.locale!==void 0&&t.locale!=="zh-CN"?"The provisioning locale must be zh-CN.":t.replaceAttemptId!==void 0&&!mn(t.replaceAttemptId)?"replaceAttemptId must be a valid opaque id.":null:"Provisioning accepts locale and replaceAttemptId only.":n===Ot.beginCallbackRepair?Fo(t,new Set(["botId"]))&&mn(t.botId)?null:"Callback repair requires a single valid botId.":n===Ot.beginGroupMessagePermission?Fo(t,new Set(["botId"]))&&mn(t.botId)?null:"Group message permission update requires a single valid botId.":n===Ot.bindCredentials?Fo(t,new Set(["appId","appSecret"]))&&C6(t.appId,256)&&C6(t.appSecret,1024)?null:"Credential binding requires App ID and App Secret.":n===Ot.pollProvisioning||n===Ot.cancelProvisioning?Fo(t,new Set(["attemptId"]))&&mn(t.attemptId)?null:"A single valid attemptId is required.":n===Ot.disconnect?Fo(t,new Set(["removeCredentials"]))&&t.removeCredentials===!0?null:"Disconnect requires removeCredentials=true.":n===il.reconnectBot?Fo(t,new Set(["botId","sendTest"]))&&mn(t.botId)&&(t.sendTest===void 0||typeof t.sendTest=="boolean")?null:"A valid botId and optional sendTest flag are required.":n===il.disconnectBot?Fo(t,new Set(["botId"]))&&mn(t.botId)?null:"A single valid botId is required.":n===il.deleteBot?Fo(t,new Set(["botId","confirm"]))&&mn(t.botId)&&t.confirm===!0?null:"Deleting a bot requires a valid botId and confirm=true.":n===Ot.setWorkspace?xa(t)?null:"\u8BF7\u8F93\u5165\u5DE5\u4F5C\u533A\u7EDD\u5BF9\u8DEF\u5F84\u3002":n===Ot.setAgentPreset?ja(t)?null:"\u8BF7\u9009\u62E9 Agent Preset\u3002":n===Ot.setContextEnhancement?Ka(t)?null:"\u8BF7\u63D0\u4EA4\u6709\u6548\u7684\u4E0A\u4E0B\u6587\u589E\u5F3A\u8BBE\u7F6E\u3002":n===Ot.setGroupResponseMode?Fo(t,new Set(["botId","groupResponseMode"]))&&mn(t.botId)&&zm(t.groupResponseMode)?null:"\u8BF7\u9009\u62E9\u7FA4\u804A\u54CD\u5E94\u65B9\u5F0F\u3002":"Unknown Feishu endpoint."}function yke(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 lP(n,t){return typeof n.registrationStatus=="function"?n.registrationStatus(t):n.status()}async function cP(n,t,o,i){let e=t,a=Date.now()+15e3;for(;;){let A=ds(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 yke(50,i),e=await lP(n,o),!e)throw new Error("The provisioning attempt is no longer active.")}}function u6(n,t){return String(ds(n?.registration).attempt)===t}function B6(n){let t=ds(n?.registration);return t.state==="succeeded"?t.botId&&(n?.connected===!0||QS(n?.connection).connected)?"connected":"connecting":hke[t.state]??"failed"}function mke(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 D6(n,{encodeQr:t=w6}={}){mke(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 BS();if(!f6.includes(a))return uS("Unknown Feishu endpoint.");let s=Qke(a,A);if(s)return uS(s);try{let g;if(a===Ot.status)g=await Wa(await n.status(),{encodeQr:e});else if(a===Ot.beginProvisioning){A.replaceAttemptId&&await n.cancelRegistration(A.replaceAttemptId);let c=await n.startRegistration({locale:A.locale}),I=String(ds(c?.registration).attempt),d=await cP(n,c,I,r);if(g=(await Wa(d,{encodeQr:e})).provisioning,!g)throw new Error("Provisioning did not produce a QR code.");i.set(I,g.verificationUrl)}else if(a===Ot.beginCallbackRepair){if(typeof n.startCallbackRepair!="function")throw new Error("Feishu callback repair is unavailable.");let c=await n.startCallbackRepair(A.botId),I=String(ds(c?.registration).attempt),d=await cP(n,c,I,r);if(g=(await Wa(d,{encodeQr:e})).provisioning,!g||g.operation!==Q6||g.botId!==A.botId)throw new Error("Callback repair did not produce a safe QR code.");i.set(I,g.verificationUrl)}else if(a===Ot.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(ds(c?.registration).attempt),d=await cP(n,c,I,r);if(g=(await Wa(d,{encodeQr:e})).provisioning,!g||g.operation!==IP||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===Ot.pollProvisioning){let c=await lP(n,A.attemptId);if(!c||!u6(c,A.attemptId))return uS("The provisioning attempt is no longer active.");let I=ds(c.registration),d=await Wa(c,{encodeQr:e});if(g={status:B6(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===Ot.cancelProvisioning){let c=await lP(n,A.attemptId);if(!c||!u6(c,A.attemptId))return uS("The provisioning attempt is no longer active.");let I=typeof n.registrationStatus=="function",d=ds(c.registration),B;!I&&d.state==="saving"?B=await n.disconnect():B=await n.cancelRegistration(A.attemptId);let f=ds(B?.registration);if(fS.has(d.operation)&&d.state==="saving"&&["saving","succeeded"].includes(f.state)&&(g={status:B6(B),operation:f.operation,...f.botId?{botId:f.botId}:{},message:d.operation===IP?"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===Ot.bindCredentials){if(typeof n.bindCredentials!="function")throw new Error("Credential binding is unavailable");g=await Wa(await n.bindCredentials(A),{encodeQr:e})}else if(a===Ot.testConnection){let c=await n.status(),d=c?.connected===!0||QS(c?.connection).connected||typeof n.reconnect!="function"?c:await n.reconnect();g=await Wa(d,{encodeQr:e})}else if(a===Ot.disconnect)g=await Wa(await n.disconnect(),{encodeQr:e});else if(a===il.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 BS();if(g=await Wa(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:ir(I)}}}else if(a===il.disconnectBot){if(typeof n.disconnectBot!="function")throw new Error("Multi-bot disconnect is unavailable");g=await Wa(await n.disconnectBot(A.botId),{encodeQr:e})}else if(a===Ot.setWorkspace){if(typeof n.updateWorkspace!="function")throw new Error("Workspace update is unavailable");g=await Wa(await n.updateWorkspace(A.botId,A.workspace),{encodeQr:e})}else if(a===Ot.setContextEnhancement){if(typeof n.updateContextEnhancement!="function")throw new Error("Context enhancement update is unavailable");g=await n.updateContextEnhancement(A.botId,A.config,c=>Wa(c,{encodeQr:e}))}else if(a===Ot.setAgentPreset){if(typeof n.updateAgentPreset!="function")throw new Error("Agent preset update is unavailable");g=await Wa(await n.updateAgentPreset(A.botId,A.agentPreset),{encodeQr:e})}else if(a===Ot.setGroupResponseMode){if(typeof n.updateGroupResponseMode!="function")throw new Error("Group response mode update is unavailable");g=await Wa(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 Wa(await n.deleteBot(A.botId),{encodeQr:e})}return r?.aborted?BS():{ok:!0,value:g}}catch(g){let c=Ya(g);return r?.aborted?BS():c?{ok:!1,error:{...c,details:{}}}:fke()}}}function yS(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(gP,D6(t,o),{authority:Er(i)})}function Ske(n,t){if(t?.controller)return t.controller;if(typeof t?.createController=="function")return t.createController();if(typeof t?.createProvisioningManager=="function")return x_(t)}async function O6(n,t={}){let o=Ske(n,t);if(o)return yS(n,o,t.rpcOptions,t.rpcAuthority);let i=await AP(n,t),e=t.deliveryService&&i.deliveryAdapter?t.deliveryService.registerAdapter(i.deliveryAdapter):void 0,a=yS(n,i.controller,t.rpcOptions,t.rpcAuthority);return n.effect(()=>async()=>{await e?.(),await i.close()},"dsh-feishu: close controller and live connection"),a}import{unlink as fve}from"node:fs/promises";import{homedir as Qve}from"node:os";import{join as bu,resolve as sl}from"node:path";import{createHash as wke}from"node:crypto";import{mkdir as Dke,readFile as Oke,rename as bke,unlink as Mke,writeFile as _ke}from"node:fs/promises";import{dirname as Tke}from"node:path";var dP=Object.freeze({version:1,bots:Object.freeze([])});function Sc(n){return typeof n=="string"&&n.trim()?n.trim():null}function b6(n){let t=Sc(n);return t&&/^qq_[a-f0-9]{24}$/.test(t)?t:null}function Nke(n){let t=Sc(n);return t&&/^DSH_QQBOT_APP_SECRET_[A-F0-9]{24}$/.test(t)?t:null}function SS(n){let t=Sc(n);if(!t)throw new TypeError("appId is required");let o=wke("sha256").update(t).digest("hex").slice(0,24);return{botId:`qq_${o}`,secretRef:`DSH_QQBOT_APP_SECRET_${o.toUpperCase()}`}}function hP(n){let t=Sc(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 M6(n){if(!n||typeof n!="object")return null;let t=Sc(n.appId),o=Sc(n.ownerUserOpenid),i=b6(n.botId),e=Nke(n.secretRef);if(!t||!o||!i||!e)return null;let a=SS(t);return a.botId!==i||a.secretRef!==e?null:Object.freeze({botId:i,appId:t,secretRef:e,ownerUserOpenid:o,createdAt:Sc(n.createdAt)??new Date().toISOString(),connectedAt:Sc(n.connectedAt)})}function Rke(n){if(!n||n.version!==1||!Array.isArray(n.bots))return null;let t=n.bots.map(M6);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 mS=class{#e;#A=dP;#t=Promise.resolve();constructor(t){this.#e=t}async load(){try{let t=Rke(JSON.parse(await Oke(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=dP}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=M6(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(!b6(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 Mke(this.#e)}catch(o){if(o?.code!=="ENOENT")throw o}this.#A=dP});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.#g(a),this.#A=a});return this.#t=i.then(()=>{},()=>{}),await i,o}async#g(t){await Dke(Tke(this.#e),{recursive:!0,mode:448});let o=`${this.#e}.tmp`;await _ke(o,`${JSON.stringify(t,null,2)} `,{encoding:"utf8",mode:384}),await bke(o,this.#e)}};var wS=class extends pr{constructor(t){super({...t,rpcIdPrefix:"qq",logPrefix:"dsh-qq"})}};import{randomUUID as kke}from"node:crypto";var _6=new Set(["starting","pending","refreshing","connecting"]),ol=new Set(["connected","failed","cancelled"]),vke=5*6e4;function nl(n){return typeof n=="string"&&n.trim()?n.trim():null}function Sn(n,t){return Object.freeze({code:n,message:t})}function DS(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 Su=class{#e;#A;#t;#r;#g;#a;#n=new Map;#o=new Map;#c=new Map;#l=null;#i=new Map;#I=0;#s=!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.#g=a,this.#a=A}async initialize(){if(this.#s)return this.status();for(let t of this.#t.list())await this.#B(t.botId,async()=>{if(this.#s||this.#n.get(t.botId)?.status?.ready)return;let o=await this.#C(t.secretRef);if(!o){this.#o.set(t.botId,Sn("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.#d(t,o),this.#o.delete(t.botId)}catch(i){this.#o.set(t.botId,Sn("connection-failed",w("QQ \u8FDE\u63A5\u672A\u5C31\u7EEA\uFF0C\u63D2\u4EF6\u4F1A\u81EA\u52A8\u91CD\u8BD5\u3002"))),this.#a.warn?.(`[dsh-im:qq] bot ${t.botId} failed to initialize:`,i)}finally{this.#y()}});return this.status()}async startProvisioning(){if(this.#s)throw new Error("QQ controller is closed");this.#l&&await this.cancelProvisioning(this.#l);let t,o,i=new Promise((a,A)=>{t=a,o=A}),e={id:kke(),state:"starting",createdAt:Date.now(),expiresAt:null,qrRevision:0,verificationUrl:null,controller:new AbortController,dispose:null,task:null,error:null,botId:null};this.#c.set(e.id,e),this.#l=e.id,this.#y();try{return e.dispose=this.#e.start({onQrDisplayed:a=>{if(e.controller.signal.aborted||ol.has(e.state))return;let A=nl(a);A&&(e.verificationUrl=A,e.qrRevision+=1,e.expiresAt=Date.now()+vke,e.state="pending",this.#y(),t())},onQrExpired:()=>{e.controller.signal.aborted||ol.has(e.state)||(e.state="refreshing",e.verificationUrl=null,e.expiresAt=null,this.#y())},onSuccess:a=>{e.controller.signal.aborted||ol.has(e.state)||(e.task=this.#p(e,a))},onFailure:a=>{e.controller.signal.aborted||ol.has(e.state)||(e.state="failed",e.error=Sn("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.#l===e.id&&(this.#l=null),this.#y(),o(a))}},{signal:e.controller.signal}),await i,DS(e)}catch(a){throw e.controller.signal.aborted?(e.state="cancelled",e.error=Sn("cancelled",w("\u626B\u7801\u7ED1\u5B9A\u5DF2\u53D6\u6D88\u3002"))):ol.has(e.state)||(e.state="failed",e.error=Sn("qr-start-failed",w("\u65E0\u6CD5\u751F\u6210 QQ \u4E8C\u7EF4\u7801\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002"))),this.#l===e.id&&(this.#l=null),this.#y(),a}}registrationStatus(t){return DS(this.#c.get(t))}async bindCredentials({appId:t,appSecret:o}={}){if(this.#s)throw new Error("QQ controller is closed");let i=nl(t),e=nl(o);if(!i||!e)throw new TypeError("QQ AppID and AppSecret are required");if(this.#l&&await this.cancelProvisioning(this.#l),this.#s)throw new Error("QQ controller is closed");let a=SS(i);return await this.#B(a.botId,async()=>{if(this.#s)throw new Error("QQ controller is closed");let A=this.#t.getByAppId(i),r=await this.#A.resolve(a.secretRef).catch(()=>{});if(this.#s)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.#f(a.secretRef,r),g}try{await this.#d(s,e),this.#o.delete(a.botId)}catch(g){this.#o.set(a.botId,Sn("connection-failed",w("QQ \u673A\u5668\u4EBA\u5DF2\u7ED1\u5B9A\uFF0C\u6D88\u606F\u8FDE\u63A5\u6682\u672A\u5C31\u7EEA\u3002"))),this.#a.warn?.(`[dsh-im:qq] bot ${a.botId} credential connection failed:`,g)}this.#y()}),this.status()}async cancelProvisioning(t){let o=this.#c.get(t);return o?(ol.has(o.state)||(o.controller.abort(),o.dispose?.(),await o.task?.catch(()=>{}),ol.has(o.state)||(o.state="cancelled"),o.error??=Sn("cancelled",w("\u626B\u7801\u7ED1\u5B9A\u5DF2\u53D6\u6D88\u3002"))),this.#l===o.id&&(this.#l=null),this.#y(),DS(o)):null}async reconnectBot(t){let o=this.#t.get(t);if(!o)throw new Error("Unknown QQ bot");return await this.#B(t,async()=>{let i=await this.#C(o.secretRef);if(!i)throw new Error("QQ bot secret is missing");try{await this.#d(o,i),this.#o.delete(t)}catch(e){throw this.#o.set(t,Sn("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.#B(t,async()=>{let i=this.#n.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(ba(w("QQ \u673A\u5668\u4EBA\uFF08{appId}\uFF09",{appId:hP(o.appId)}))),{sent:!0}})}async sendProactiveText(t,o,i,e={}){if(!this.#t.get(t))throw new Error("Unknown QQ bot");return this.#B(t,async()=>{let A=this.#n.get(t);if(!A?.status?.ready||typeof A.sendProactiveText!="function"){let r=new Error(w("QQ\u673A\u5668\u4EBA\u5C1A\u672A\u8FDE\u63A5"));throw r.code="bot-not-connected",r}return A.sendProactiveText(o,i,e)})}async deleteBot(t){let o=this.#t.get(t);if(!o)throw new Error("Unknown QQ bot");return await this.#B(t,async()=>{let i=await this.#A.resolve(o.secretRef).catch(()=>{});await this.#E(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.#d(o,i.value).catch(()=>{})),new Error("Unable to remove the QQ bot safely.",{cause:e})}await this.#g({botId:t,config:o}).catch(e=>{this.#a.warn?.(`[dsh-im:qq] bot ${t} state cleanup failed:`,e)}),this.#o.delete(t),this.#y()}),this.status()}status(){let t=this.#t.list().map(e=>{let a=this.#n.get(e.botId)?.status??null,A=a?.ready===!0&&a.qqConnectionState==="connected"&&a.harnessReachable===!0,r=A?"connected":a?.qqConnectionState==="connecting"?"connecting":this.#o.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:hP(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},lastMessageError:Vr(a?.lastMessageError),error:structuredClone(this.#o.get(e.botId)??null)}}),o=t.filter(e=>e.connected).length,i=this.#l?this.#c.get(this.#l):null;return{schemaVersion:1,revision:this.#I,state:i&&_6.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&&_6.has(i.state)?{provisioning:DS(i)}:{}}}async close(){this.#s||(this.#s=!0,this.#l&&await this.cancelProvisioning(this.#l),await Promise.allSettled([...this.#i.values()]),await Promise.allSettled([...this.#n.keys()].map(t=>this.#E(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=nl(i?.appId),a=nl(i?.appSecret),A=nl(i?.userOpenid);if(!e||!a||!A)throw new Error("QQ authorization returned incomplete credentials");t.botId=await this.#h(t,{appId:e,appSecret:a,ownerUserOpenid:A}),t.state="connected",t.error=null}catch(i){t.controller.signal.aborted?(t.state="cancelled",t.error=Sn("cancelled",w("\u626B\u7801\u7ED1\u5B9A\u5DF2\u53D6\u6D88\u3002"))):(t.state="failed",t.error=Sn("activation-failed",w("QQ \u5DF2\u6388\u6743\uFF0C\u4F46\u65E0\u6CD5\u5B89\u5168\u4FDD\u5B58\u63A5\u5165\u914D\u7F6E\u3002")),this.#a.error?.("[dsh-im:qq] provisioning failed:",i))}finally{t.dispose?.(),this.#l===t.id&&(this.#l=null),this.#y()}}async#h(t,{appId:o,appSecret:i,ownerUserOpenid:e}){let a=SS(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.#B(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.#f(a.secretRef,r),g}try{if(t.controller.signal.aborted)throw new DOMException("Cancelled","AbortError");await this.#d(s,i),this.#o.delete(a.botId)}catch(g){if(t.controller.signal.aborted)throw await this.#E(a.botId),A?await this.#t.save(A).catch(()=>{}):await this.#t.remove(a.botId).catch(()=>null)&&await this.#g({botId:a.botId,config:s}).catch(I=>{this.#a.warn?.("[dsh-im:qq] cancelled bot state cleanup failed:",I)}),await this.#f(a.secretRef,r),g;this.#o.set(a.botId,Sn("connection-failed",w("QQ \u673A\u5668\u4EBA\u5DF2\u7ED1\u5B9A\uFF0C\u6D88\u606F\u8FDE\u63A5\u6682\u672A\u5C31\u7EEA\u3002"))),this.#a.warn?.(`[dsh-im:qq] bot ${a.botId} activation connection failed:`,g)}return this.#y(),a.botId})}async#d(t,o){if(this.#s)throw new Error("QQ controller is closed");if(await this.#E(t.botId),this.#s)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.#n.set(t.botId,i);try{await i.start()}catch(e){throw await i.stop().catch(()=>{}),this.#n.delete(t.botId),e}}async#E(t){let o=this.#n.get(t);this.#n.delete(t),await o?.stop().catch(i=>{this.#a.warn?.(`[dsh-im:qq] bot ${t} failed to stop cleanly:`,i)})}async#C(t){let o=await this.#A.resolve(t).catch(()=>{});return nl(o?.value)}async#f(t,o){o?.value?await this.#A.set(t,o.value).catch(()=>{}):await this.#A.unset(t).catch(()=>{})}#B(t,o){let a=(this.#i.get(t)??Promise.resolve()).catch(()=>{}).then(o).finally(()=>{this.#i.get(t)===a&&this.#i.delete(t)});return this.#i.set(t,a),a}#y(){this.#I+=1}};import{QQBot as nve,typingIndicator as sve}from"@tencent-connect/qqbot-nodejs";import{ApiError as Pke}from"@tencent-connect/qqbot-nodejs";var T6=4500,Gke=/^( {0,3})(`{3,}|~{3,})(.*)$/,Fke=new Set([40034090]),Lke=Object.freeze({c2c:4,group:5}),Uke=()=>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 CP(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 k6(n){let t=n.endsWith("\r")?n.slice(0,-1):n,o=Gke.exec(t);return!o||o[2][0]==="`"&&o[3].includes("`")?null:{delimiter:o[2],info:o[3],indent:o[1].length}}function Hke(n,t){let o=/^ {0,3}(`{3,}|~{3,})[ \t]*$/.exec(n);return!!(o&&o[1][0]===t.delimiter[0]&&o[1].length>=t.delimiter.length)}function N6(n,t){let o=0;for(let i of n.split(` `)){let e=0;for(;e<3&&i[e]===" ";)e+=1;let a=0;for(;i[e+a]===t;)a+=1;o=Math.max(o,a)}return o}function Kke(n,t){let o="`".repeat(Math.max(3,N6(n,"`")+1)),i="~".repeat(Math.max(3,N6(n,"~")+1));return t.includes("`")?i:o.length<=i.length?o:i}function xke(n,t){let o=0,i=0,e=t;for(;e>0&&oxke(o,t))}function EP(n,t){if(n.length<=t)return[n];let o=[],i=n;for(;i.length>t;){let e=CP(i,t),a=i.lastIndexOf(` `,e-1);a>=0&&(e=a+1),o.push(i.slice(0,e)),i=i.slice(e)}return(i||o.length===0)&&o.push(i),o}function uP(n,t,o){if(o<8)return EP(n,o).map(A=>({markdown:A,plain:A}));let i=Kke(n,t),e=`${i}${t}`;e.length+i.length+2>=o&&(e=i);let a=o-e.length-i.length-2;return a<1?EP(n,o).map(A=>({markdown:A,plain:A})):EP(n,a).map(A=>({markdown:`${e} diff --git a/plugin-src/client/channel-card-meta.js b/plugin-src/client/channel-card-meta.js index 21791ce..5860dbc 100644 --- a/plugin-src/client/channel-card-meta.js +++ b/plugin-src/client/channel-card-meta.js @@ -30,7 +30,7 @@ export function BotSettingsButton({ channel, botId, botName, connected }) { type: 'button', className: 'dim-botSettingsButton', 'data-delivery-channel': channel, - 'aria-label': '机器人设置', + 'aria-label': '更多机器人设置', 'aria-describedby': tooltipId, onClick: () => openBotSettings?.({ channel, @@ -43,7 +43,7 @@ export function BotSettingsButton({ channel, botId, botName, connected }) { id: tooltipId, className: 'dim-botSettingsTooltip', role: 'tooltip', - }, '机器人设置')); + }, '更多机器人设置')); } function messageErrorTime(value) { diff --git a/plugin-src/client/delivery-settings.js b/plugin-src/client/delivery-settings.js index 42ce239..b6dcae0 100644 --- a/plugin-src/client/delivery-settings.js +++ b/plugin-src/client/delivery-settings.js @@ -669,11 +669,11 @@ export function DeliveryTargetSettingsPage({ channel, account, rpcCall, onBack } 'aria-label': '打开主动投递使用文档', }, h('span', null, '使用文档'), - h('span', { 'aria-hidden': 'true' }, '↗')), - h('h2', null, account.botName || '机器人设置'))), - h('section', { className: 'dim-deliveryIdentity', 'aria-labelledby': 'dim-delivery-identity-title' }, + h('span', { 'aria-hidden': 'true' }, '↗')))), + h('section', { className: 'dim-deliveryIdentity', 'aria-labelledby': 'dim-delivery-bot-title' }, h('div', null, - h('h3', { id: 'dim-delivery-identity-title' }, '调用标识')), + h('h2', { id: 'dim-delivery-bot-title', className: 'dim-deliveryBotName' }, + account.botName || '机器人设置')), h('div', { className: 'dim-deliveryBotId' }, h('span', null, 'Bot ID'), h('code', { title: account.botId }, account.botId), diff --git a/plugin-src/client/i18n.js b/plugin-src/client/i18n.js index 19f6990..a22ef9c 100644 --- a/plugin-src/client/i18n.js +++ b/plugin-src/client/i18n.js @@ -6,6 +6,7 @@ const EN = Object.freeze({ '$locale': 'en', 'IM机器人': 'IM bots', 'IM机器人设置': 'IM bot settings', + '更多机器人设置': 'More bot settings', 'IM 渠道': 'IM channels', '让 DeepSeek Harness 触手可及': 'Connecting DeepSeek Harness', '当前版本': 'Current version', @@ -747,7 +748,6 @@ const EN = Object.freeze({ '打开主动投递使用文档': 'Open the proactive delivery guide', '当前渠道暂不支持投递目标。': 'Delivery targets are not supported for this channel.', '已复制 Bot ID': 'Bot ID copied', - '调用标识': 'Call identifiers', '复制': 'Copy', '投递目标': 'Delivery targets', '机器人当前离线;仍可配置目标,恢复连接后再测试。': 'The bot is offline. You can still configure targets and test them after reconnection.', diff --git a/plugin-src/client/styles.js b/plugin-src/client/styles.js index 8aab5f3..b5ace6b 100644 --- a/plugin-src/client/styles.js +++ b/plugin-src/client/styles.js @@ -367,7 +367,6 @@ const CSS = String.raw` .dim-deliveryPage { min-width: 0; display: grid; gap: 14px; } .dim-deliveryHeader { min-width: 0; display: flex; align-items: center; justify-content: space-between; gap: 16px; } .dim-deliveryHeaderMeta { min-width: 0; display: flex; align-items: center; justify-content: flex-end; gap: 10px; text-align: right; } -.dim-deliveryHeader h2 { min-width: 0; overflow: hidden; margin: 0; font-size: 18px; line-height: 24px; font-weight: 680; text-overflow: ellipsis; white-space: nowrap; } .dim-deliveryDocsLink { min-height: 30px; flex: none; display: inline-flex; align-items: center; gap: 4px; padding: 5px 8px; border-radius: 7px; color: var(--dsw-alias-state-business-primary, #3370ff); font-size: 12px; line-height: 18px; text-decoration: none; white-space: nowrap; } .dim-deliveryDocsLink:hover { background: color-mix(in srgb, var(--dsw-alias-state-business-primary, #3370ff) 8%, transparent); } .dim-deliveryDocsLink:focus-visible { outline: 2px solid var(--dsw-alias-state-business-primary, #3370ff); outline-offset: 2px; } @@ -379,7 +378,7 @@ const CSS = String.raw` .dim-deliveryButton[data-kind="danger"] { color: var(--dsw-alias-state-error-primary, #d54941); } .dim-deliveryBack { flex: none; border-color: transparent; background: transparent; } .dim-deliveryIdentity, .dim-deliveryTargets { min-width: 0; padding: 16px; border: 1px solid var(--dsw-alias-border-l2, #dfe1e5); border-radius: 12px; background: var(--dsw-alias-bg-layer-3, #fff); } -.dim-deliveryIdentity > div:first-child h3, .dim-deliverySectionHeading h3 { margin: 0; font-size: 15px; line-height: 22px; font-weight: 650; } +.dim-deliveryBotName, .dim-deliverySectionHeading h3 { min-width: 0; overflow: hidden; margin: 0; font-size: 15px; line-height: 22px; font-weight: 650; text-overflow: ellipsis; white-space: nowrap; } .dim-deliveryIdentity > div:first-child p, .dim-deliverySectionHeading p { margin: 2px 0 0; color: var(--dsw-alias-label-secondary, #646a73); font-size: 12px; line-height: 18px; } .dim-deliveryBotId { min-width: 0; display: grid; grid-template-columns: max-content minmax(0, 1fr) max-content; align-items: center; gap: 10px; margin-top: 12px; padding: 10px 12px; border-radius: 9px; background: var(--dsw-alias-bg-module-platform, #f7f8fa); } .dim-deliveryBotId > span { color: var(--dsw-alias-label-secondary, #646a73); font-size: 12px; } diff --git a/test/client-delivery-settings.test.mjs b/test/client-delivery-settings.test.mjs index ea83e2f..9a6b985 100644 --- a/test/client-delivery-settings.test.mjs +++ b/test/client-delivery-settings.test.mjs @@ -121,10 +121,10 @@ test('all nine robot cards add one accessible settings gear beside existing cont for (const [channel, Card, props] of cards) { const markup = renderToStaticMarkup(React.createElement(Card, props)); - assert.equal((markup.match(/aria-label="机器人设置"/g) ?? []).length, 1); + assert.equal((markup.match(/aria-label="更多机器人设置"/g) ?? []).length, 1); assert.match(markup, /class="dim-botCardTools"/); assert.match(markup, new RegExp(`data-delivery-channel="${channel}"`)); - assert.match(markup, /role="tooltip"[^>]*>机器人设置]*>更多机器人设置 { - card.findByProps({ 'aria-label': '机器人设置' }).props.onClick(); + card.findByProps({ 'aria-label': '更多机器人设置' }).props.onClick(); await flush(); }); const page = renderer.root.findByProps({ className: 'dim-deliveryPage' }); assert.match(textOf(page), /微信通知助手/); + assert.doesNotMatch(textOf(page), /调用标识/); assert.equal( page.findByProps({ className: 'dim-deliveryHeader' }).findAllByType('span').length, 2, ); + assert.equal( + page.findByProps({ className: 'dim-deliveryHeader' }).findAllByType('h2').length, + 0, + ); + assert.equal( + textOf(page.findByProps({ className: 'dim-deliveryIdentity' }).findByType('h2')), + '微信通知助手', + ); const docsLink = page.findByProps({ className: 'dim-deliveryDocsLink' }); assert.equal(textOf(docsLink), '使用文档↗'); assert.equal(