diff --git a/lib/client.js b/lib/client.js index 334b10d..9c5083b 100644 --- a/lib/client.js +++ b/lib/client.js @@ -571,7 +571,7 @@ var React24 = __toESM(require("react"), 1); // package.json var package_default = { name: "dsh-im-ops", - version: "4.9.1-ops.6", + version: "4.9.1-ops.7", description: "Ops fork of dsh-im (all channels kept). Based on @xmanrui/dsh-im@4.9.1 \u2014 access/session policies owned here.", keywords: [ "deepseek-harness", @@ -852,6 +852,8 @@ var EN = Object.freeze({ "\u673A\u5668\u4EBA\u8BBE\u7F6E\u9875\u7B7E": "Bot settings tabs", "\u6295\u9012\u8BBE\u7F6E": "Delivery settings", "\u8BBF\u95EE\u8BBE\u7F6E": "Access settings", + "\u65E0\u6CD5\u8BFB\u53D6\u8BBF\u95EE\u6388\u6743\uFF0C\u8BF7\u8FD4\u56DE\u5237\u65B0\u540E\u91CD\u8BD5\u3002": "Could not load the access grant. Go back, refresh, and try again.", + "\u6B63\u5728\u8BFB\u53D6\u5206\u7EA7\u8BBF\u95EE\u8BBE\u7F6E\u2026": "Loading graded access settings\u2026", "\u52A0\u672C\u7FA4": "Add to group", "\u5DF2\u5728\u672C\u7FA4": "Already in group", "\u52A0\u79C1\u804A": "Add to DMs", @@ -3544,7 +3546,15 @@ function SettingsGlyph() { h2("path", { d: "M19.4 15a1.7 1.7 0 0 0 .34 1.88l.06.06-2.83 2.83-.06-.06a1.7 1.7 0 0 0-1.88-.34 1.7 1.7 0 0 0-1.03 1.55V21h-4v-.08A1.7 1.7 0 0 0 8.97 19.4a1.7 1.7 0 0 0-1.88.34l-.06.06-2.83-2.83.06-.06A1.7 1.7 0 0 0 4.6 15a1.7 1.7 0 0 0-1.52-1.03H3v-4h.08A1.7 1.7 0 0 0 4.6 8.97a1.7 1.7 0 0 0-.34-1.88l-.06-.06L7.03 4.2l.06.06a1.7 1.7 0 0 0 1.88.34A1.7 1.7 0 0 0 10 3.08V3h4v.08a1.7 1.7 0 0 0 1.03 1.52 1.7 1.7 0 0 0 1.88-.34l.06-.06 2.83 2.83-.06.06a1.7 1.7 0 0 0-.34 1.88A1.7 1.7 0 0 0 20.92 10H21v4h-.08A1.7 1.7 0 0 0 19.4 15Z" }) ); } -function BotSettingsButton({ channel: channel4, botId, botName, connected, accessPolicy }) { +function BotSettingsButton({ + channel: channel4, + botId, + botName, + connected, + accessPolicy, + accessGrant, + groupSessionScope +}) { const { openBotSettings } = React9.useContext(BotSettingsContext); const tooltipId = React9.useId(); return h2( @@ -3561,7 +3571,9 @@ function BotSettingsButton({ channel: channel4, botId, botName, connected, acces botId, botName, connected: Boolean(connected), - accessPolicy + accessPolicy, + accessGrant, + groupSessionScope }) }, h2(SettingsGlyph)), h2("span", { @@ -11698,7 +11710,9 @@ function WhatsappAccountCard({ botId: account.botId, botName: account.bot.name, connected: account.connected, - accessPolicy: account.accessPolicy + accessPolicy: account.accessPolicy, + accessGrant: account.accessGrant, + groupSessionScope: account.groupSessionScope }) ) ), @@ -12737,10 +12751,43 @@ function AccessGrantSettingsPage({ channel: channel4, account, rpcCall, onSaved const [saving, setSaving] = React21.useState(false); const [feedback, setFeedback] = React21.useState(null); const [newGroupJid, setNewGroupJid] = React21.useState(""); + const [loadingGrant, setLoadingGrant] = React21.useState(!initialGrant); React21.useEffect(() => { setDraft(cloneGrant(normalizeAccessGrant(account?.accessGrant), ownerPhone)); setGroupSessionScope(normalizeGroupSessionScope(account?.groupSessionScope)); }, [account?.botId, initialKey, account?.groupSessionScope, ownerPhone]); + React21.useEffect(() => { + if (typeof rpcCall !== "function" || !account?.botId) return void 0; + let cancelled = false; + setLoadingGrant(true); + void (async () => { + try { + const value = unwrapRpcResult11(await rpcCall("connection.status", {})); + if (cancelled) return; + const bot = Array.isArray(value?.bots) ? value.bots.find((entry) => entry?.botId === account.botId) : null; + const grant = normalizeAccessGrant(bot?.accessGrant); + if (grant) { + setDraft(cloneGrant(grant, ownerPhone)); + onSaved?.(grant); + } + if (bot?.groupSessionScope) { + setGroupSessionScope(normalizeGroupSessionScope(bot.groupSessionScope)); + } + } catch (error) { + if (!cancelled) { + setFeedback({ + tone: "error", + message: error?.message || "\u65E0\u6CD5\u8BFB\u53D6\u8BBF\u95EE\u6388\u6743\uFF0C\u8BF7\u8FD4\u56DE\u5237\u65B0\u540E\u91CD\u8BD5\u3002" + }); + } + } finally { + if (!cancelled) setLoadingGrant(false); + } + })(); + return () => { + cancelled = true; + }; + }, [account?.botId, rpcCall, ownerPhone]); const contacts = draft.contacts ?? []; const knownGroupJids = React21.useMemo(() => { const set = new Set(Object.keys(draft.groups ?? {})); @@ -12826,6 +12873,7 @@ function AccessGrantSettingsPage({ channel: channel4, account, rpcCall, onSaved className: "dim-accessPage", onSubmit: (event) => void save(event) }, + loadingGrant ? h2("div", { className: "dim-accessState", "aria-busy": "true" }, "\u6B63\u5728\u8BFB\u53D6\u5206\u7EA7\u8BBF\u95EE\u8BBE\u7F6E\u2026") : null, h2( "p", { className: "dim-accessUsersEmpty" }, diff --git a/lib/index.js b/lib/index.js index d25cab3..8306e11 100644 --- a/lib/index.js +++ b/lib/index.js @@ -169,7 +169,7 @@ ${n}`:n)}function v_(n,t,o){return{cardParamMap:{flowStatus:t,msgContent:gu(n,o) ${iEe(I.text,s)}`);g=Sc([i,...c,A.join(` `)].join(` -`)),s=Math.floor(s/2)}while(s>0&&(g.message.length>3e3||g.messages.length>3));return g}function oEe(n){let t=n?.code??n?.failure?.code;return t==="session-not-found"?w("\u5F53\u524D\u804A\u5929\u7ED1\u5B9A\u7684\u4F1A\u8BDD\u5DF2\u4E0D\u5B58\u5728\uFF0C\u8BF7\u91CD\u65B0\u7ED1\u5B9A\u4F1A\u8BDD\u3002"):t===Mi||t==="workspace-bot-not-found"||t==="session-binding-changed"?w("\u4F1A\u8BDD\u3001\u5DE5\u4F5C\u533A\u6216\u673A\u5668\u4EBA\u72B6\u6001\u5DF2\u53D1\u751F\u53D8\u5316\uFF0C\u8BF7\u91CD\u65B0\u6267\u884C /history\u3002"):t==="harness-api-not-found"?w("\u5F53\u524D Harness \u6682\u4E0D\u652F\u6301\u8BFB\u53D6\u4F1A\u8BDD\u5386\u53F2\u3002"):n?.name==="AbortError"?w("\u5386\u53F2\u8BFB\u53D6\u5DF2\u53D6\u6D88\u3002"):n?.name==="TimeoutError"||t==="harness-timeout"?w("\u8BFB\u53D6\u5386\u53F2\u8D85\u65F6\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002"):w("\u6682\u65F6\u65E0\u6CD5\u8BFB\u53D6\u4F1A\u8BDD\u5386\u53F2\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002")}function Yi(n){return typeof n=="string"&&o1.test(n.trim())}async function so(n,t,o,a,{signal:e,isDirect:i=!1,hasImages:A=!1,hasFiles:r=!1}={}){if(!Yi(n))return null;let s=o1.exec(n.trim())[1].trim();if(s&&(!/^\d+$/u.test(s)||/^0+$/u.test(s)))return Sc(w($he));let g=s?Math.min(Number(s),eEe):3;if(!i)return Sc(w("\u8BF7\u5728\u4E0E\u673A\u5668\u4EBA\u7684\u79C1\u804A\u4E2D\u4F7F\u7528 /history\u3002"));if(A||r)return Sc(w("/history \u4EC5\u652F\u6301\u6587\u5B57\u547D\u4EE4\uFF0C\u8BF7\u79FB\u9664\u56FE\u7247\u6216\u6587\u4EF6\u540E\u91CD\u8BD5\u3002"));let c=o?.sessionFor?.(a);if(typeof c!="string"||!c)return Sc(w("\u5F53\u524D\u804A\u5929\u5C1A\u672A\u7ED1\u5B9A\u4F1A\u8BDD\uFF0C\u8BF7\u5148\u53D1\u9001\u6D88\u606F\u6216\u4F7F\u7528 /session \u7ED1\u5B9A\u4F1A\u8BDD\u3002"));try{let I=t?.workspaceSession?.(c);if(typeof I?.readHistory!="function")return Sc(w("\u5F53\u524D Harness \u6682\u4E0D\u652F\u6301\u8BFB\u53D6\u4F1A\u8BDD\u5386\u53F2\u3002"));let d=AbortSignal.timeout(a1),B=e?AbortSignal.any([e,d]):d,f=Date.now()+a1,Q=new Map,y,m,_=[],T=!1;for(let R=0;R=f)throw new DOMException("History read timed out","TimeoutError");let L=await I.readHistory({maxMessages:AEe,...y===void 0?{}:{beforeSeq:y},timeoutMs:Math.max(1,f-Date.now()),signal:B});if(B.throwIfAborted(),Date.now()>=f)throw new DOMException("History read timed out","TimeoutError");if(o.sessionFor(a)!==c){let z=new Error("Session binding changed during history read");throw z.code="session-binding-changed",z}if(!L||!Array.isArray(L.events)||typeof L.hasMore!="boolean")throw new TypeError("Invalid history page");let U=y??1/0;for(let z of L.events){let J=z?.event;if(!J||!Number.isSafeInteger(J.seq)||J.seq<0||typeof J.type!="string"||!J.type)throw new TypeError("Invalid history event");if(m!==void 0&&J.seq>m)continue;let K=Q.get(J.seq);if(K){if(!Xhe(K,J))throw new TypeError("Conflicting history events")}else{if(y!==void 0&&J.seq>=y)throw new TypeError("Invalid history cursor");Q.set(J.seq,J)}U=Math.min(U,J.seq)}let F=[...Q.values()].sort((z,J)=>z.seq-J.seq);if(m??=F.at(-1)?.seq,T=L.hasMore,T&&(!Number.isFinite(U)||U===y))throw new TypeError("History cursor did not advance");if(_=rEe(F).slice(-g),_.length>=g||!T)break;y=U}return _.length===0?Sc(T?w("\u672C\u6B21\u6709\u9650\u8BFB\u53D6\u4E2D\u672A\u627E\u5230\u53EF\u9884\u89C8\u7684\u5386\u53F2\u6D88\u606F\u3002"):w("\u5F53\u524D\u4F1A\u8BDD\u6682\u65E0\u53EF\u9884\u89C8\u7684\u5386\u53F2\u6D88\u606F\u3002")):aEe(c,_,g,T)}catch(I){return Sc(oEe(I))}}var WQ={name:"dsh-im-ops",version:"4.9.1-ops.6",description:"Ops fork of dsh-im (all channels kept). Based on @xmanrui/dsh-im@4.9.1 \u2014 access/session policies owned here.",keywords:["deepseek-harness","dsh","dsh-plugin","ai-agent","im","instant-messaging","chatbot","feishu","lark","wechat","wecom","dingtalk","qq","slack","telegram","discord","whatsapp","ai-office","ops","fork"],author:"xmanrui (https://github.com/xmanrui)",contributors:[{name:"C3H3-AI",url:"https://github.com/C3H3-AI"},{name:"divingleee",url:"https://github.com/divingleee"},{name:"Chan-0312",url:"https://github.com/Chan-0312"}],license:"MIT",type:"module",repository:{type:"git",url:"git+https://github.com/hansjone/dsh-im-ops.git"},homepage:"https://github.com/hansjone/dsh-im-ops#readme",bugs:{url:"https://github.com/hansjone/dsh-im-ops/issues"},bin:{"dsh-im":"bin/dsh-im.mjs"},main:"./lib/index.js",exports:{".":"./lib/index.js","./client":"./lib/client.js","./package.json":"./package.json"},files:["assets","bin","cordis.patch.yml","lib","plugin-src","scripts","src","PROACTIVE_DELIVERY.md","PROACTIVE_DELIVERY.en.md","LICENSE","README.md","README.en.md","THIRD_PARTY_NOTICES.md"],dsh:{bundle:{patch:"./cordis.patch.yml"},client:{inject:["@deepseek-ai/dsh-client-connection","@deepseek-ai/dsh-client-runtime","@deepseek-ai/dsh-client-ui-settings","@deepseek-ai/dsh-client-ui-slots","@deepseek-ai/dsh-client-locale"],platform:"web"}},scripts:{build:"node plugin-src/client/build.mjs && node plugin-src/host/build.mjs",test:"node --test test/*.test.mjs test/channels/*/*.test.mjs",check:"npm run build && npm test && node scripts/verify-package.mjs"},engines:{node:">=22.19"},dependencies:{"@tencent-connect/qqbot-connector":"1.2.0","@tencent-connect/qqbot-nodejs":"1.0.4","@wecom/aibot-node-sdk":"1.0.7","dingtalk-stream":"2.1.4",qrcode:"1.5.4",undici:"7.29.0"},devDependencies:{"@deepseek-ai/cordis":"4.0.1","@larksuiteoapi/node-sdk":"1.73.0","@whiskeysockets/baileys":"7.0.0-rc14",esbuild:"0.25.9","https-proxy-agent":"5.0.1",react:"18.3.1","react-dom":"18.3.1","react-test-renderer":"18.3.1",semver:"7.8.5"},directories:{doc:"docs",lib:"lib",test:"test"}};var sEe=/^\/(?:stop|steer|version)(?=$|\s)/iu,gEe=/^\/stop(?=$|\s)/iu,cEe=/^\/version(?=$|\s)/iu,IEe="\u7528\u6CD5\uFF1A/stop\uFF08\u4E0D\u5E26\u53C2\u6570\uFF09",lEe="\u7528\u6CD5\uFF1A/version\uFF08\u4E0D\u5E26\u53C2\u6570\uFF09",dEe="\u7528\u6CD5\uFF1A/steer <\u8865\u5145\u6307\u4EE4>",pEe="\u63A7\u5236\u547D\u4EE4\u4EC5\u652F\u6301\u7EAF\u6587\u5B57\uFF0C\u8BF7\u79FB\u9664\u56FE\u7247\u540E\u91CD\u8BD5\u3002";function Po(n,t={}){return{message:n,...t}}function s1(n){return n?{signal:n}:{}}function g1(n,t,o){if(typeof t?.sessionFor!="function")return null;let a=t.sessionFor(o);if(typeof a!="string"||!a)return null;if(typeof n?.workspaceSession!="function")throw new TypeError("Harness does not support workspace sessions");let e=n.workspaceSession(a);if(!e||typeof e!="object")throw new TypeError("Harness returned an invalid workspace session");return e}function pa(n){return typeof n=="string"&&sEe.test(n.trim())}async function va(n,t,o,a,{signal:e,hasImages:i=!1,pendingInteraction:A=!1,control:r}={}){if(!pa(n))return null;let s=n.trim(),g=gEe.test(s),c=cEe.test(s);if(i)return Po(w(pEe));if(c)return/^\/version$/iu.test(s)?Po(`dsh-im v${WQ.version}`):Po(w(lEe));if(g){if(!/^\/stop$/iu.test(s))return Po(w(IEe));let Q=g1(t,o,a);if(!Q)return Po(w("\u5F53\u524D\u804A\u5929\u6CA1\u6709\u6B63\u5728\u8FD0\u884C\u7684\u4EFB\u52A1\u3002"));if(typeof Q.stopActiveTurn!="function")throw new TypeError("Harness session does not support stopping active turns");return await Q.stopActiveTurn(r,s1(e))?Po(w("\u5DF2\u8BF7\u6C42\u505C\u6B62\u5F53\u524D\u4EFB\u52A1\u3002"),{stopped:!0}):Po(w("\u5F53\u524D\u804A\u5929\u6CA1\u6709\u6B63\u5728\u8FD0\u884C\u7684\u4EFB\u52A1\u3002"))}let d=/^\/steer(?:\s+([\s\S]*))?$/iu.exec(s)?.[1]?.trim()??"";if(!d)return Po(w(dEe));if(A)return Po([w("\u5F53\u524D\u4EFB\u52A1\u6B63\u5728\u7B49\u5F85\u4F60\u7684\u56DE\u7B54\u6216\u5BA1\u6279\u3002"),"",w("\u8BF7\u5148\u5904\u7406\u5F53\u524D\u8BF7\u6C42\uFF0C\u6216\u8005\u53D1\u9001 /stop \u505C\u6B62\u4EFB\u52A1\u3002")].join(` +`)),s=Math.floor(s/2)}while(s>0&&(g.message.length>3e3||g.messages.length>3));return g}function oEe(n){let t=n?.code??n?.failure?.code;return t==="session-not-found"?w("\u5F53\u524D\u804A\u5929\u7ED1\u5B9A\u7684\u4F1A\u8BDD\u5DF2\u4E0D\u5B58\u5728\uFF0C\u8BF7\u91CD\u65B0\u7ED1\u5B9A\u4F1A\u8BDD\u3002"):t===Mi||t==="workspace-bot-not-found"||t==="session-binding-changed"?w("\u4F1A\u8BDD\u3001\u5DE5\u4F5C\u533A\u6216\u673A\u5668\u4EBA\u72B6\u6001\u5DF2\u53D1\u751F\u53D8\u5316\uFF0C\u8BF7\u91CD\u65B0\u6267\u884C /history\u3002"):t==="harness-api-not-found"?w("\u5F53\u524D Harness \u6682\u4E0D\u652F\u6301\u8BFB\u53D6\u4F1A\u8BDD\u5386\u53F2\u3002"):n?.name==="AbortError"?w("\u5386\u53F2\u8BFB\u53D6\u5DF2\u53D6\u6D88\u3002"):n?.name==="TimeoutError"||t==="harness-timeout"?w("\u8BFB\u53D6\u5386\u53F2\u8D85\u65F6\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002"):w("\u6682\u65F6\u65E0\u6CD5\u8BFB\u53D6\u4F1A\u8BDD\u5386\u53F2\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002")}function Yi(n){return typeof n=="string"&&o1.test(n.trim())}async function so(n,t,o,a,{signal:e,isDirect:i=!1,hasImages:A=!1,hasFiles:r=!1}={}){if(!Yi(n))return null;let s=o1.exec(n.trim())[1].trim();if(s&&(!/^\d+$/u.test(s)||/^0+$/u.test(s)))return Sc(w($he));let g=s?Math.min(Number(s),eEe):3;if(!i)return Sc(w("\u8BF7\u5728\u4E0E\u673A\u5668\u4EBA\u7684\u79C1\u804A\u4E2D\u4F7F\u7528 /history\u3002"));if(A||r)return Sc(w("/history \u4EC5\u652F\u6301\u6587\u5B57\u547D\u4EE4\uFF0C\u8BF7\u79FB\u9664\u56FE\u7247\u6216\u6587\u4EF6\u540E\u91CD\u8BD5\u3002"));let c=o?.sessionFor?.(a);if(typeof c!="string"||!c)return Sc(w("\u5F53\u524D\u804A\u5929\u5C1A\u672A\u7ED1\u5B9A\u4F1A\u8BDD\uFF0C\u8BF7\u5148\u53D1\u9001\u6D88\u606F\u6216\u4F7F\u7528 /session \u7ED1\u5B9A\u4F1A\u8BDD\u3002"));try{let I=t?.workspaceSession?.(c);if(typeof I?.readHistory!="function")return Sc(w("\u5F53\u524D Harness \u6682\u4E0D\u652F\u6301\u8BFB\u53D6\u4F1A\u8BDD\u5386\u53F2\u3002"));let d=AbortSignal.timeout(a1),B=e?AbortSignal.any([e,d]):d,f=Date.now()+a1,Q=new Map,y,m,_=[],T=!1;for(let R=0;R=f)throw new DOMException("History read timed out","TimeoutError");let L=await I.readHistory({maxMessages:AEe,...y===void 0?{}:{beforeSeq:y},timeoutMs:Math.max(1,f-Date.now()),signal:B});if(B.throwIfAborted(),Date.now()>=f)throw new DOMException("History read timed out","TimeoutError");if(o.sessionFor(a)!==c){let z=new Error("Session binding changed during history read");throw z.code="session-binding-changed",z}if(!L||!Array.isArray(L.events)||typeof L.hasMore!="boolean")throw new TypeError("Invalid history page");let U=y??1/0;for(let z of L.events){let J=z?.event;if(!J||!Number.isSafeInteger(J.seq)||J.seq<0||typeof J.type!="string"||!J.type)throw new TypeError("Invalid history event");if(m!==void 0&&J.seq>m)continue;let K=Q.get(J.seq);if(K){if(!Xhe(K,J))throw new TypeError("Conflicting history events")}else{if(y!==void 0&&J.seq>=y)throw new TypeError("Invalid history cursor");Q.set(J.seq,J)}U=Math.min(U,J.seq)}let F=[...Q.values()].sort((z,J)=>z.seq-J.seq);if(m??=F.at(-1)?.seq,T=L.hasMore,T&&(!Number.isFinite(U)||U===y))throw new TypeError("History cursor did not advance");if(_=rEe(F).slice(-g),_.length>=g||!T)break;y=U}return _.length===0?Sc(T?w("\u672C\u6B21\u6709\u9650\u8BFB\u53D6\u4E2D\u672A\u627E\u5230\u53EF\u9884\u89C8\u7684\u5386\u53F2\u6D88\u606F\u3002"):w("\u5F53\u524D\u4F1A\u8BDD\u6682\u65E0\u53EF\u9884\u89C8\u7684\u5386\u53F2\u6D88\u606F\u3002")):aEe(c,_,g,T)}catch(I){return Sc(oEe(I))}}var WQ={name:"dsh-im-ops",version:"4.9.1-ops.7",description:"Ops fork of dsh-im (all channels kept). Based on @xmanrui/dsh-im@4.9.1 \u2014 access/session policies owned here.",keywords:["deepseek-harness","dsh","dsh-plugin","ai-agent","im","instant-messaging","chatbot","feishu","lark","wechat","wecom","dingtalk","qq","slack","telegram","discord","whatsapp","ai-office","ops","fork"],author:"xmanrui (https://github.com/xmanrui)",contributors:[{name:"C3H3-AI",url:"https://github.com/C3H3-AI"},{name:"divingleee",url:"https://github.com/divingleee"},{name:"Chan-0312",url:"https://github.com/Chan-0312"}],license:"MIT",type:"module",repository:{type:"git",url:"git+https://github.com/hansjone/dsh-im-ops.git"},homepage:"https://github.com/hansjone/dsh-im-ops#readme",bugs:{url:"https://github.com/hansjone/dsh-im-ops/issues"},bin:{"dsh-im":"bin/dsh-im.mjs"},main:"./lib/index.js",exports:{".":"./lib/index.js","./client":"./lib/client.js","./package.json":"./package.json"},files:["assets","bin","cordis.patch.yml","lib","plugin-src","scripts","src","PROACTIVE_DELIVERY.md","PROACTIVE_DELIVERY.en.md","LICENSE","README.md","README.en.md","THIRD_PARTY_NOTICES.md"],dsh:{bundle:{patch:"./cordis.patch.yml"},client:{inject:["@deepseek-ai/dsh-client-connection","@deepseek-ai/dsh-client-runtime","@deepseek-ai/dsh-client-ui-settings","@deepseek-ai/dsh-client-ui-slots","@deepseek-ai/dsh-client-locale"],platform:"web"}},scripts:{build:"node plugin-src/client/build.mjs && node plugin-src/host/build.mjs",test:"node --test test/*.test.mjs test/channels/*/*.test.mjs",check:"npm run build && npm test && node scripts/verify-package.mjs"},engines:{node:">=22.19"},dependencies:{"@tencent-connect/qqbot-connector":"1.2.0","@tencent-connect/qqbot-nodejs":"1.0.4","@wecom/aibot-node-sdk":"1.0.7","dingtalk-stream":"2.1.4",qrcode:"1.5.4",undici:"7.29.0"},devDependencies:{"@deepseek-ai/cordis":"4.0.1","@larksuiteoapi/node-sdk":"1.73.0","@whiskeysockets/baileys":"7.0.0-rc14",esbuild:"0.25.9","https-proxy-agent":"5.0.1",react:"18.3.1","react-dom":"18.3.1","react-test-renderer":"18.3.1",semver:"7.8.5"},directories:{doc:"docs",lib:"lib",test:"test"}};var sEe=/^\/(?:stop|steer|version)(?=$|\s)/iu,gEe=/^\/stop(?=$|\s)/iu,cEe=/^\/version(?=$|\s)/iu,IEe="\u7528\u6CD5\uFF1A/stop\uFF08\u4E0D\u5E26\u53C2\u6570\uFF09",lEe="\u7528\u6CD5\uFF1A/version\uFF08\u4E0D\u5E26\u53C2\u6570\uFF09",dEe="\u7528\u6CD5\uFF1A/steer <\u8865\u5145\u6307\u4EE4>",pEe="\u63A7\u5236\u547D\u4EE4\u4EC5\u652F\u6301\u7EAF\u6587\u5B57\uFF0C\u8BF7\u79FB\u9664\u56FE\u7247\u540E\u91CD\u8BD5\u3002";function Po(n,t={}){return{message:n,...t}}function s1(n){return n?{signal:n}:{}}function g1(n,t,o){if(typeof t?.sessionFor!="function")return null;let a=t.sessionFor(o);if(typeof a!="string"||!a)return null;if(typeof n?.workspaceSession!="function")throw new TypeError("Harness does not support workspace sessions");let e=n.workspaceSession(a);if(!e||typeof e!="object")throw new TypeError("Harness returned an invalid workspace session");return e}function pa(n){return typeof n=="string"&&sEe.test(n.trim())}async function va(n,t,o,a,{signal:e,hasImages:i=!1,pendingInteraction:A=!1,control:r}={}){if(!pa(n))return null;let s=n.trim(),g=gEe.test(s),c=cEe.test(s);if(i)return Po(w(pEe));if(c)return/^\/version$/iu.test(s)?Po(`dsh-im v${WQ.version}`):Po(w(lEe));if(g){if(!/^\/stop$/iu.test(s))return Po(w(IEe));let Q=g1(t,o,a);if(!Q)return Po(w("\u5F53\u524D\u804A\u5929\u6CA1\u6709\u6B63\u5728\u8FD0\u884C\u7684\u4EFB\u52A1\u3002"));if(typeof Q.stopActiveTurn!="function")throw new TypeError("Harness session does not support stopping active turns");return await Q.stopActiveTurn(r,s1(e))?Po(w("\u5DF2\u8BF7\u6C42\u505C\u6B62\u5F53\u524D\u4EFB\u52A1\u3002"),{stopped:!0}):Po(w("\u5F53\u524D\u804A\u5929\u6CA1\u6709\u6B63\u5728\u8FD0\u884C\u7684\u4EFB\u52A1\u3002"))}let d=/^\/steer(?:\s+([\s\S]*))?$/iu.exec(s)?.[1]?.trim()??"";if(!d)return Po(w(dEe));if(A)return Po([w("\u5F53\u524D\u4EFB\u52A1\u6B63\u5728\u7B49\u5F85\u4F60\u7684\u56DE\u7B54\u6216\u5BA1\u6279\u3002"),"",w("\u8BF7\u5148\u5904\u7406\u5F53\u524D\u8BF7\u6C42\uFF0C\u6216\u8005\u53D1\u9001 /stop \u505C\u6B62\u4EFB\u52A1\u3002")].join(` `));let B=g1(t,o,a);if(!B)return Po(w("\u5F53\u524D\u804A\u5929\u6CA1\u6709\u7ED1\u5B9A\u4F1A\u8BDD\uFF0C\u65E0\u6CD5\u8865\u5145\u6307\u4EE4\u3002\u8BF7\u5148\u7ED1\u5B9A\u4F1A\u8BDD\u3002"));if(typeof B.steerActiveTurn!="function")throw new TypeError("Harness session does not support steering active turns");let f=await B.steerActiveTurn(d,r,s1(e));return Po(f?w("\u5DF2\u63D0\u4EA4\u8865\u5145\u6307\u4EE4\uFF0CAgent \u4F1A\u5728\u4E0B\u4E00\u6B65\u8BFB\u53D6\u3002"):w("\u4EFB\u52A1\u5DF2\u7ED3\u675F\uFF0C\u6CA1\u6709\u6B63\u5728\u8FD0\u884C\u7684\u4EFB\u52A1\uFF0C\u65E0\u6CD5\u8865\u5145\u6307\u4EE4\u3002\u8BF7\u76F4\u63A5\u53D1\u9001\u6D88\u606F\u5F00\u59CB\u65B0\u4EFB\u52A1\u3002"))}var hEe=/^\/model(?=$|\s)/i,C1=/^\/models(?=$|\s)/i,B1=/^\/reasoning(?=$|\s)/i,f1=/^\/reasonings(?=$|\s)/i,Q1=/^\/reasoninglist(?=$|\s)/i,c1="\u7528\u6CD5\uFF1A/model <\u5E8F\u53F7\u6216 provider/model> [\u63A8\u7406\u7B49\u7EA7ID]",EEe="\u7528\u6CD5\uFF1A/models\uFF08\u4E0D\u5E26\u53C2\u6570\uFF09",uEe="\u7528\u6CD5\uFF1A/reasoning [\u5E8F\u53F7\u3001\u7B49\u7EA7ID\u6216 --default]",CEe="\u7528\u6CD5\uFF1A/reasoninglist \u6216 /reasonings\uFF08\u4E0D\u5E26\u53C2\u6570\uFF09",y1="session-binding-changed",m1="model-selection-mismatch",BEe=/[\p{Cc}\p{Cf}\p{Zl}\p{Zp}]+/gu;function Ct(n){return{handled:!0,message:n,messages:ug(n)}}function oi(n){return typeof n!="string"?"":n.replace(BEe," ").replace(/\s+/gu," ").trim()}function fEe(n){return n?{signal:n}:{}}function QEe(n){if(n===void 0)return;if(!n||typeof n!="object"||!Array.isArray(n.efforts)||n.efforts.length===0)throw new TypeError("Harness returned invalid model reasoning metadata");let t=n.efforts.map(o=>{if(!o||typeof o!="object"||typeof o.id!="string"||!o.id||typeof o.name!="string"||!o.name||o.description!==void 0&&typeof o.description!="string")throw new TypeError("Harness returned an invalid reasoning effort");return{id:o.id,name:o.name,...o.description===void 0?{}:{description:o.description}}});if(n.defaultEffort!==void 0&&(typeof n.defaultEffort!="string"||!n.defaultEffort))throw new TypeError("Harness returned an invalid default reasoning effort");return{efforts:t,...n.defaultEffort===void 0?{}:{defaultEffort:n.defaultEffort}}}function S1(n,{requireCurrent:t=!1}={}){if(!n||typeof n!="object"||!Array.isArray(n.groups)||!Array.isArray(n.failures))throw new TypeError("Harness returned an invalid model catalog");let o=n.groups.map(i=>{if(!i||typeof i!="object"||typeof i.id!="string"||!i.id||typeof i.name!="string"||!i.name||!Array.isArray(i.models))throw new TypeError("Harness returned an invalid model provider group");return{id:i.id,name:i.name,models:i.models.map(A=>{if(!A||typeof A!="object"||typeof A.id!="string"||!A.id||typeof A.name!="string"||!A.name||A.description!==void 0&&typeof A.description!="string")throw new TypeError("Harness returned an invalid model");return{id:A.id,name:A.name,...A.description===void 0?{}:{description:A.description},...A.reasoning===void 0?{}:{reasoning:QEe(A.reasoning)}}})}}),a=n.failures.map(i=>{if(!i||typeof i!="object"||typeof i.id!="string"||!i.id||typeof i.name!="string"||!i.name)throw new TypeError("Harness returned an invalid model provider failure");return{id:i.id,name:i.name}}),e=null;if(n.current!==void 0){if(!n.current||typeof n.current!="object"||typeof n.current.provider!="string"||!n.current.provider||typeof n.current.model!="string"||!n.current.model||n.current.reasoningEffort!==void 0&&(typeof n.current.reasoningEffort!="string"||!n.current.reasoningEffort))throw new TypeError("Harness returned an invalid current model");e={provider:n.current.provider,model:n.current.model,...n.current.reasoningEffort===void 0?{}:{reasoningEffort:n.current.reasoningEffort}}}else if(t)throw new TypeError("Harness returned no current model");return{groups:o,failures:a,current:e}}function Cg(n,t){return`${n}/${t}`}function w1(n,t){return n?.provider===t?.provider&&n?.model===t?.model}function yEe(n,t){return w1(n,t)&&n?.reasoningEffort===t?.reasoningEffort}function mEe(n,t){return w1(n,t)&&(t.reasoningEffort===void 0||n?.reasoningEffort===t.reasoningEffort)}function AT(n){if(!n?.provider||!n?.model)return"";let t=Cg(n.provider,n.model);return n.reasoningEffort===void 0?t:`${t} \xB7 reasoningEffort=${oi(n.reasoningEffort)}`}function I1(n,t,o){let a=new Error(`Harness ${o} did not confirm the selected model`);return a.code=m1,a.expected=n,a.actual=t,a.source=o,a}function D1(){let n=new Error("Conversation binding changed during model selection");return n.code=y1,n}function l1(n,t,o){if((typeof n?.sessionFor=="function"?n.sessionFor(t):null)!==o)throw D1()}function SEe(n,t){for(let o of n.groups)for(let a of o.models)if(Cg(o.id,a.id)===t)return{provider:o.id,model:a.id};return null}function wEe(n,t){let o=0;for(let a of n.groups)for(let e of a.models)if(o+=1,o===t)return{provider:a.id,model:e.id};return null}function d1(n){if(!/^\d+$/u.test(n))return null;let t=Number(n);return{index:Number.isSafeInteger(t)&&t>0?t:null}}function ZQ(n,t){return t?n.groups.find(({id:a})=>a===t.provider)?.models.find(({id:a})=>a===t.model)??null:null}function DEe(n,t){return n?.reasoning?.efforts?.[t-1]??null}function tT(n,t){return n?.reasoning?.efforts?.find(({id:o})=>o===t)??null}function XQ(n,t){return n?.reasoningEffort??t?.reasoning?.defaultEffort}function Iu(n,t){if(t===void 0)return w("Default\uFF08\u7531\u6A21\u578B\u6216 Provider \u51B3\u5B9A\uFF09");let o=tT(n,t);if(!o)return oi(t);let a=oi(o.name),e=oi(o.id);return a===e?e:`${a} (${e})`}function O1(n){let t=ZQ(n,n.current);return Iu(t,XQ(n.current,t))}function OEe(n,t,o){return n===t&&n===o?w("\uFF08\u5F53\u524D\u3001\u9ED8\u8BA4\uFF09"):n===t?w("\uFF08\u5F53\u524D\uFF09"):n===o?w("\uFF08\u9ED8\u8BA4\uFF09"):""}function p1(n){return[w("\u6A21\u578B\u5E8F\u53F7\u65E0\u6548\uFF1A{input}",{input:oi(n)}),"",w("\u8BF7\u53D1\u9001 /models \u67E5\u770B\u5E76\u8F93\u5165\u6709\u6548\u7684\u6B63\u6574\u6570\u5E8F\u53F7\u3002")].join(` `)}function h1(n){return[w("\u63A8\u7406\u7B49\u7EA7\u5E8F\u53F7\u65E0\u6548\uFF1A{input}",{input:oi(n)}),"",w("\u8BF7\u53D1\u9001 /reasoninglist \u67E5\u770B\u5E76\u8F93\u5165\u6709\u6548\u7684\u6B63\u6574\u6570\u5E8F\u53F7\u3002")].join(` `)}function X_(n,t,o){let a=[w("\u6A21\u578B\u4E0D\u652F\u6301\u63A8\u7406\u7B49\u7EA7\uFF1A{effort}",{effort:oi(t)}),"",oi(AT(n))],e=o?.reasoning?.efforts?.map(({id:i})=>oi(i))??[];return e.length>0?a.push(w("\u53EF\u7528\u63A8\u7406\u7B49\u7EA7\uFF1A{efforts}",{efforts:e.join(", ")})):a.push(w("\u8BE5\u6A21\u578B\u4E0D\u63D0\u4F9B\u53EF\u5207\u6362\u7684\u63A8\u7406\u7B49\u7EA7\u3002")),a.join(` @@ -378,7 +378,7 @@ ${w("\u5185\u5BB9\u8F83\u957F\uFF0C\u751F\u6210\u5B8C\u6210\u540E\u5C06\u5206\u6 `)+1;e(A&&(i=await this.#o(t,a.replyTo),e.push(i),A=!1),i),g={get messageId(){return i.messageId},rotate:async()=>{if(!A){A=!0;try{await this.#g(i,`${dG(r)} ${w("\u2935\uFE0F \u6700\u7EC8\u7ED3\u679C\u89C1\u4E0B\u65B9")}`),await this.#i(i)}catch(I){console.warn("[dsh-feishu] unable to finalize the superseded stream card:",I.message)}}},setContent:async I=>{let d=String(I??"")||"\u2026",B=await s();await this.#g(B,dG(d)),r=d}};await o.markdown(g);let c=mGe(r);for(let[I,d]of c.entries()){let B=I===0?await s():await this.#o(t,a.replyTo);I>0&&e.push(B),await this.#g(B,d),await this.#i(B)}return{messageId:e[0].messageId,providerMessageIds:e.map(I=>I.messageId)}}catch(r){for(let s of e)await this.#s(s.messageId);throw r}}async sendFile(t,o,{replyTo:a,signal:e}={}){return this.#I(t,o,{replyTo:a,signal:e,messageType:"file",presentation:"feishu-file"})}async sendImage(t,o,{replyTo:a,signal:e}={}){return this.#I(t,o,{replyTo:a,signal:e,messageType:"image",presentation:"feishu-image"})}async#I(t,o,{replyTo:a,signal:e,messageType:i,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 dZ(Q=>{Q.throwIfAborted();let y=i==="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 On(o,y),y},{signal:e,timeoutMs:this.#t,stage:"upload"})}catch(Q){throw e?.aborted?pG(e):eB("upload",Q)}e?.throwIfAborted();let s=i==="image"?r?.image_key??r?.data?.image_key:r?.file_key??r?.data?.file_key;if(typeof s!="string"||!s)throw eB("upload",void 0,r?.code);let g=QGe(o,t,i),c=JSON.stringify(i==="image"?{image_key:s}:{file_key:s}),I=a?{path:{message_id:a},data:{msg_type:i,content:c,uuid:g}}:{params:{receive_id_type:"chat_id"},data:{receive_id:t,msg_type:i,content:c,uuid:g}},d=()=>{let Q=a?this.#e.im.v1.message.reply(I):this.#e.im.v1.message.create(I);return On(o,Q),Q},B;try{B=await dZ(async Q=>{Q.throwIfAborted();let y;try{y=await d()}catch(m){if(EZ(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?pG(e):eB("message send",Q,void 0,{uncertain:!0})}if(Number.isFinite(Number(B?.code))&&Number(B.code)!==0)throw eB("message send",void 0,B.code,{uncertain:!0});let f=B?.data?.message_id;if(typeof f!="string"||!f)throw eB("message send",void 0,void 0,{uncertain:!0});return rr({deliveryId:o.deliveryKey,presentation:A,providerMessageIds:[f],artifacts:[{artifactId:o.artifactId,outcome:"sent"}]})}async#o(t,o){let a=dG(this.#A),i=Pl("Feishu card.create",await this.#e.cardkit.v1.card.create({data:{type:"card_json",data:JSON.stringify(SGe(a))}}))?.data?.card_id;if(!i)throw new Error("Feishu card.create returned no card_id");let A=await this.#a(t,i,o);return{cardId:i,messageId:A,content:a,sequence:0}}async#g(t,o){if(o===t.content)return;let a=await this.#e.cardkit.v1.cardElement.content({path:{card_id:t.cardId,element_id:pZ},data:{content:o,sequence:++t.sequence,uuid:`content_${t.cardId}_${t.sequence}`}});Pl("Feishu cardElement.content",a),t.content=o}async#i(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:yGe(t.content)||w("\u56DE\u7B54\u5B8C\u6210")}}}),sequence:++t.sequence,uuid:`settings_${t.cardId}_${t.sequence}`}});Pl("Feishu card.settings",o)}async#a(t,o,a){let e=JSON.stringify({type:"card",data:{card_id:o}}),i=a?await this.#e.im.v1.message.reply({path:{message_id:a},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}});Pl("Feishu message send",i);let A=i?.data?.message_id;if(!A)throw new Error("Feishu message send returned no message_id");return A}async#s(t){try{let o=await this.#e.im.v1.message.delete({path:{message_id:t}});Pl("Feishu message delete",o)}catch(o){console.warn("[bridge] unable to recall a failed streaming card:",o.message)}}async addReaction(t,o){let e=Pl("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){Pl("Feishu reaction.delete",await this.#e.im.v1.messageReaction.delete({path:{message_id:t,reaction_id:o}}))}};var CZ="/open-apis/application/v7/app_slash_commands",wGe=new Set(["99991640","99991672"]),XS=Object.freeze(["application:app_slash_command:read","application:app_slash_command:write"]),BZ="ai-agent_outlined",EG=Object.freeze([{command:"menu",icon:"skill_outlined",default:"\u6253\u5F00\u529F\u80FD\u83DC\u5355",en_us:"Open the feature menu"},{command:"new",icon:"ai-deepthink_outlined",default:"\u5F00\u542F\u5168\u65B0\u4F1A\u8BDD",en_us:"Start a fresh session"},{command:"help",icon:"promptword_outlined",default:"\u67E5\u770B\u5E2E\u52A9",en_us:"Show help"},{command:"status",icon:"ai-functions_outlined",default:"\u67E5\u770B\u673A\u5668\u4EBA\u72B6\u6001",en_us:"Show bot status"},{command:"compact",icon:"ai-block_outlined",default:"\u538B\u7F29\u5F53\u524D\u4F1A\u8BDD\u4E0A\u4E0B\u6587",en_us:"Compact the current session"},{command:"sessionlist",icon:"chat-ai_outlined",default:"\u5217\u51FA\u4F1A\u8BDD",en_us:"List sessions"},{command:"workspacelist",icon:"folder_outlined",default:"\u5217\u51FA\u5DE5\u4F5C\u533A",en_us:"List workspaces"},{command:"workspaces",icon:"folder_outlined",default:"\u5217\u51FA\u5DE5\u4F5C\u533A",en_us:"List workspaces"},{command:"wsl",icon:"folder_outlined",default:"\u5217\u51FA\u5DE5\u4F5C\u533A",en_us:"List workspaces"},{command:"ws",icon:"folder_outlined",default:"\u5207\u6362\u5DE5\u4F5C\u533A",en_us:"Switch workspace"},{command:"watch",icon:"flag_outlined",default:"\u5173\u6CE8\u4E00\u4E2A\u4F1A\u8BDD",en_us:"Watch a session"},{command:"unwatch",icon:"clear_outlined",default:"\u53D6\u6D88\u5173\u6CE8\u4F1A\u8BDD",en_us:"Unwatch a session"},{command:"watchlist",icon:"flag_outlined",default:"\u67E5\u770B\u5173\u6CE8\u5217\u8868",en_us:"List watched sessions"},{command:"archived",icon:"folder_outlined",default:"\u8BBE\u7F6E\u5F52\u6863\u4F1A\u8BDD\u663E\u9690\uFF08on/off\uFF09",en_us:"Show or hide archived sessions (on/off)"}]);function uG(n,t){let o=n==="lark"?"https://open.larksuite.com":"https://open.feishu.cn";return new URL(t,o)}function uZ(n,t){if(!n||typeof n!="object"||Array.isArray(n))throw new Error(`${t} returned a non-JSON response`);if(n.code!==0){let o=new Error(`${t} failed: ${n.msg||`code ${n.code}`}`);throw o.code=String(n.code),o.msg=n.msg,o}return n}function CG(n,t){let o=AbortSignal.timeout(t);return n?AbortSignal.any([n,o]):o}async function BG(n,t,o){try{return uZ(await n.request(t),o)}catch(a){let e=a?.response?.data;if(e&&typeof e=="object"&&!Array.isArray(e)&&Object.hasOwn(e,"code"))return uZ(e,o);throw a}}async function DGe({appId:n,appSecret:t,domain:o,httpInstance:a,timeoutMs:e,signal:i}){if(!n||!t)throw new Error("Feishu slash registration requires app credentials");if(!a||typeof a.request!="function")throw new TypeError("Feishu slash registration requires an HTTP instance");let A=await BG(a,{method:"POST",url:uG(o,"/open-apis/auth/v3/tenant_access_token/internal").href,headers:{"content-type":"application/json; charset=utf-8"},data:{app_id:n,app_secret:t},signal:CG(i,e),timeout:e},"Feishu authentication");if(!A.tenant_access_token)throw new Error("Feishu authentication returned no tenant access token");return A.tenant_access_token}async function OGe({tenantAccessToken:n,domain:t,httpInstance:o,timeoutMs:a,signal:e}){let i=await BG(o,{method:"GET",url:uG(t,CZ).href,headers:{authorization:`Bearer ${n}`,"content-type":"application/json; charset=utf-8"},signal:CG(e,a),timeout:a},"Feishu slash command list");return Array.isArray(i.data?.items)?i.data.items:[]}async function bGe({tenantAccessToken:n,domain:t,httpInstance:o,timeoutMs:a,signal:e,command:i,description:A,icon:r=BZ}){let s={command:i};return A&&(A.default_value||A.i18n)?s.description=A:typeof A=="string"&&A.trim()&&(s.description={default_value:A.trim()}),r&&(s.description={...s.description??{},icon:{icon_key:r}}),(await BG(o,{method:"POST",url:uG(t,CZ).href,headers:{authorization:`Bearer ${n}`,"content-type":"application/json; charset=utf-8"},data:s,signal:CG(e,a),timeout:a},`Feishu slash command create (/${i})`)).data?.command_id??null}async function fZ({appId:n,appSecret:t,domain:o="feishu",httpInstance:a,timeoutMs:e=15e3,signal:i,manifest:A=EG}){let r=await DGe({appId:n,appSecret:t,domain:o,httpInstance:a,timeoutMs:e,signal:i}),s=new Set((await OGe({tenantAccessToken:r,domain:o,httpInstance:a,timeoutMs:e,signal:i})).map(I=>I.command)),g=[],c=[];for(let I of A){let d=String(I.command??"").replace(/^\//,"");if(d&&!s.has(d))try{let B={default_value:I.default??I.en_us??d,i18n:{zh_cn:I.default??d,en_us:I.en_us??I.default??d}},f=await bGe({tenantAccessToken:r,domain:o,httpInstance:a,timeoutMs:e,signal:i,command:d,description:B,icon:I.icon??BZ});g.push({command:d,command_id:f})}catch(B){if(B?.code==="40000000"&&/already exists/i.test(B?.msg??"")){s.add(d);continue}if(wGe.has(B?.code)||/(?:lacks permission|access denied)/i.test(B?.msg??"")){c.push({command:d,error:B});break}c.push({command:d,error:B?.message??String(B)})}}return{created:g,existing:[...s].filter(I=>I!=null),failed:c}}var _Ge=15e3,TGe="\u2705 \u4FEE\u590D\u5B8C\u6210\uFF1A\u5DF2\u5B9E\u6D4B\u6536\u5230 card.action.trigger\uFF0C\u83DC\u5355\u6309\u94AE\u73B0\u5728\u53EF\u7528\u3002",NGe="\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",fG="\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",RGe="\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",kGe=new Set(["connected","connecting","reconnecting"]);function Un(n){return typeof n=="string"&&n.trim()?n.trim():null}function vGe(n){return Un(n?.operator?.open_id)??Un(n?.operator?.operator_id?.open_id)}function PGe(n,t){try{let o=n?.getConnectionStatus?.()?.state;return typeof o=="string"&&o?o:t}catch{return t}}function ph(n,t){let o=new Error(t);return o.code=n,o}function GGe(n,t){if(!n||typeof n.request!="function")return;let o=a=>({...a??{},timeout:a?.timeout??t});return{request:a=>n.request(o(a)),get:(a,e)=>n.get(a,o(e)),delete:(a,e)=>n.delete(a,o(e)),head:(a,e)=>n.head(a,o(e)),options:(a,e)=>n.options(a,o(e)),post:(a,e,i)=>n.post(a,e,o(i)),put:(a,e,i)=>n.put(a,e,o(i)),patch:(a,e,i)=>n.patch(a,e,o(i))}}function FGe({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,slashCommandRegistration:"idle",slashCommandsRegistered:0,slashCommandsExisting:0,slashCommandsFailed:0,slashCommandsError:null}}var $S=class{#e;#A;#t;#r;#I;#o;#g;#i;#a;#s;#l;#c;#d;#n;#p;#E;#u;#C;#B=null;#f=null;#y=null;#w=null;#m=null;#Q=null;#D=new Map;#h;#k=!0;constructor({lark:t,botId:o,appId:a,appSecret:e,domain:i="feishu",botOpenId:A,groupResponseMode:r,ownerOpenId:s,ownerOpenIds:g,harness:c,state:I,contextEnhancement:d,accessPolicy:B,repair:f,replyTimeoutMs:Q=6e5,connectTimeoutMs:y=15e3,requestTimeoutMs:m=_Ge,slashCommands:_=!0,wsAgent:T,logger:R=console}){if(!t)throw new Error("FeishuRuntime requires the Feishu SDK");if(!a||!e)throw new Error("FeishuRuntime requires app credentials");let L=Array.isArray(g)?g:[s],U=[...new Set(L.filter(F=>typeof F=="string"&&F))];if(U.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(f!=null&&!Un(o))throw new TypeError("FeishuRuntime repair capability requires a botId");if(!Number.isFinite(m)||m<=0)throw new TypeError("FeishuRuntime requestTimeoutMs must be a positive number");this.#e=t,this.#A=Un(o),this.#t=a,this.#r=e,this.#I=i,this.#o=Un(A),this.#g=Bo(r),this.#i=U,this.#a=c,this.#s=I,this.#l=d,this.#c=B,this.#C=f??null,this.#d=Q,this.#n=y,this.#p=m,this.#k=!!_,this.#E=T,this.#u=R,this.#h=FGe({allowedSenderCount:U.length})}get status(){return structuredClone(this.#h)}setGroupResponseMode(t){this.#g=Bo(t),this.#f?.setGroupResponseMode(this.#g)}async start(){for(;;){for(;this.#m;)await this.#m;if(this.#w)return this.#w;let o=this.#y;if(o){let a=PGe(o,this.#h.feishuLongConnectionState);if(kGe.has(a))return this.status;await this.stop({preserveError:a==="failed"});continue}if(this.#B||this.#f||this.#Q){await this.stop({preserveError:this.#h.feishuLongConnectionState==="failed"});continue}break}let t;return t=this.#M().finally(()=>{this.#w===t&&(this.#w=null)}),this.#w=t,t}async#M(){let t=new AbortController;this.#Q=t;let{signal:o}=t,a=()=>o.reason??new DOMException("Feishu runtime stopped","AbortError"),e=()=>!o.aborted&&this.#Q===t,i=()=>{if(!e())throw a()};this.#h.startedAt=new Date().toISOString(),this.#h.feishuLongConnectionState="connecting",this.#h.lastError=null;try{await this.#a.ensureRunning({signal:o}),i(),this.#h.harnessReachable=!0;let A=this.#I==="lark"?this.#e.Domain.Lark:this.#e.Domain.Feishu,r={appId:this.#t,appSecret:this.#r,domain:A},s=GGe(this.#e.defaultHttpInstance,this.#p);s&&(r.httpInstance=s);let g=new this.#e.Client(r);this.#B=g;let c=new ZS({client:g,initialText:w("\u5DF2\u8FDE\u63A5 DeepSeek Harness\uFF0C\u6B63\u5728\u601D\u8003\u2026")}),I=new VS({client:g,channel:c,harness:this.#a,state:this.#s,contextEnhancement:this.#l,accessPolicy:this.#c,status:this.#h,allowedSenderOpenIds:new Set(this.#i),botId:this.#A,appId:this.#t,botOpenId:this.#o,groupResponseMode:this.#g,repair:this.#C,replyTimeoutMs:this.#d,interactionCards:!["0","false","no","off"].includes(String(process.env.DSH_IM_INTERACTION_CARDS??"").trim().toLowerCase()),signal:o,logger:this.#u});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.#h.cardActionsReceived+=1,this.#h.lastCardActionAt=new Date().toISOString(),this.#O(_)||I.onCardAction(_))}}),B,f,Q=new Promise((_,T)=>{let R=!1,L=()=>{f(a())},U=(z,J)=>{R||(R=!0,clearTimeout(F),o.removeEventListener("abort",L),z(J))},F=setTimeout(()=>{U(T,new Error(`Feishu WebSocket handshake timed out after ${this.#n}ms`))},this.#n);B=()=>{U(_)},f=z=>{U(T,z)},o.addEventListener("abort",L,{once:!0}),o.aborted&&L()});Q.catch(()=>{});let y=new this.#e.WSClient({...r,...this.#E?{agent:this.#E}:{},loggerLevel:this.#e.LoggerLevel.info,handshakeTimeoutMs:this.#n,onReady:()=>{e()&&(this.#h.feishuLongConnectionState="connected",this.#h.ready=!0,this.#h.lastError=null,B())},onError:_=>{e()&&(this.#h.feishuLongConnectionState="failed",this.#h.ready=!1,this.#h.lastError=_?.message??String(_),this.#u.error("[dsh-feishu] Feishu long connection failed:",this.#h.lastError),f(_))},onReconnecting:()=>{e()&&(this.#h.feishuLongConnectionState="reconnecting",this.#h.ready=!1)},onReconnected:()=>{e()&&(this.#h.feishuLongConnectionState="connected",this.#h.ready=!0,this.#h.lastError=null)}});this.#y=y;let m=Promise.resolve().then(()=>y.start({eventDispatcher:d})).catch(_=>{throw f(_),_});return await Promise.all([m,Q]),i(),this.#k&&s&&this.#T(s,e,o),this.status}catch(A){throw o.aborted||(this.#h.ready=!1,this.#h.feishuLongConnectionState="failed",this.#h.lastError=A?.message??String(A),await this.#P({preserveError:!0,abortController:t})),A}}async beginCardActionProbe({expectedOperatorOpenId:t,timeoutMs:o=9e4}={}){if(!this.#h.ready||!this.#B)throw ph("card_action_probe_unavailable","\u98DE\u4E66\u673A\u5668\u4EBA\u5C1A\u672A\u8FDE\u63A5");let a=Un(t);if(!a||a==="*")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=MGe().replaceAll("-",""),i;try{i=await this.#B.im.v1.message.create({params:{receive_id_type:"open_id"},data:{receive_id:a,msg_type:"interactive",content:z5(e)}})}catch{throw this.#S(a,w(fG),"failure"),ph("card_action_probe_send_failed","\u65E0\u6CD5\u53D1\u9001\u98DE\u4E66\u5361\u7247\u56DE\u8C03\u6D4B\u8BD5")}if(i?.code&&i.code!==0)throw this.#S(a,w(fG),"failure"),ph("card_action_probe_send_failed","\u65E0\u6CD5\u53D1\u9001\u98DE\u4E66\u5361\u7247\u56DE\u8C03\u6D4B\u8BD5");let A=Un(i?.data?.message_id)??Un(i?.message_id);if(!A)throw this.#S(a,w(fG),"failure"),ph("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.#D.get(A);!c||c.nonce!==e||(this.#D.delete(A),this.#S(a,w(NGe),"timeout"),s(ph("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.#D.set(A,{messageId:A,nonce:e,expectedOperatorOpenId:a,timeout:g,resolve:r,reject:s})})}#O(t){let o=Un(t?.context?.open_message_id);if(!o)return!1;let a=this.#D.get(o);if(!a)return!1;let e=t?.action?.value,i=vGe(t);return e?.action!=="repair_verify"||e?.nonce!==a.nonce||i!==a.expectedOperatorOpenId?!1:(clearTimeout(a.timeout),this.#D.delete(o),this.#h.cardActionProbesVerified+=1,this.#S(i,w(TGe),"success").finally(()=>{a.resolve({verified:!0,messageId:o,operatorOpenId:i})}),!0)}#S(t,o,a){let e=this.#B;return e?Promise.resolve().then(async()=>{let i=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(i?.code&&i.code!==0)throw new Error("Feishu callback repair notice failed");return!0}).catch(()=>(this.#u.warn?.(`[dsh-feishu] unable to send the callback repair ${a} notice`),!1)):(this.#u.warn?.(`[dsh-feishu] unable to send the callback repair ${a} notice`),Promise.resolve(!1))}async sendConnectionTest(t){if(!this.#h.ready||!this.#B){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,i,A)=>{let r=await this.#B.im.v1.message.create({params:{receive_id_type:e},data:{receive_id:i,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}`)},a=this.#i.find(e=>e!=="*");return a?(await o("open_id",a,t),{sent:!0}):Qc({state:this.#s,text:t,channelLabel:w("\u98DE\u4E66\u673A\u5668\u4EBA"),send:async(e,i)=>{let A=typeof e?.chatId=="string"?e.chatId.trim():"";if(!A)throw Qr(w("\u98DE\u4E66\u673A\u5668\u4EBA"));await o("chat_id",A,i)}})}async sendProactiveText(t,o,{signal:a}={}){if(!this.#h.ready||!this.#B){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,i=t?.kind==="user"?Un(t?.route?.openId):t?.kind==="group"?Un(t?.route?.chatId):null;if(!e||!i){let r=new TypeError("Invalid Feishu proactive delivery target");throw r.code="invalid-target",r}a?.throwIfAborted();let A=await this.#B.im.v1.message.create({params:{receive_id_type:e},data:{receive_id:i,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}}async#T(t,o,a){this.#h.slashCommandRegistration="registering",this.#h.slashCommandsError=null;try{let e=await fZ({appId:this.#t,appSecret:this.#r,domain:this.#I,httpInstance:t,signal:a,manifest:EG});if(!o())return;this.#h.slashCommandRegistration="done",this.#h.slashCommandsRegistered=e.created.length,this.#h.slashCommandsExisting=e.existing.length,this.#h.slashCommandsFailed=e.failed.length,this.#h.slashCommandsError=e.failed.length>0?e.failed.map(i=>`/${i.command}: ${i.error?.message??String(i.error)}`).join("; "):null,e.created.length>0&&this.#u.info?.(`[dsh-feishu] registered ${e.created.length} slash command(s)`),e.failed.length>0&&this.#u.warn?.(`[dsh-feishu] ${e.failed.length} slash command(s) failed to register: ${this.#h.slashCommandsError}`)}catch(e){if(!o())return;this.#h.slashCommandRegistration="failed",this.#h.slashCommandsError=e?.message??String(e),this.#u.warn?.(`[dsh-feishu] slash command registration skipped: ${this.#h.slashCommandsError}`)}}stop(t={}){if(this.#m)return this.#m;let o;return o=this.#N(t).finally(()=>{this.#m===o&&(this.#m=null)}),this.#m=o,o}async#N({preserveError:t=!1}={}){let o=this.#Q;this.#Q===o&&(this.#Q=null),o?.abort(new DOMException("Feishu runtime stopped","AbortError"));let a=this.#w;return a&&await a.catch(()=>{}),this.#P({preserveError:t,abortController:o})}async#P({preserveError:t=!1,abortController:o}={}){let a=t?this.#h.lastError:null;this.#Q===o&&(this.#Q=null),o?.abort(new DOMException("Feishu runtime stopped","AbortError"));for(let A of this.#D.values())clearTimeout(A.timeout),this.#S(A.expectedOperatorOpenId,w(RGe),"abort"),A.reject(ph("abort","\u98DE\u4E66\u8FD0\u884C\u65F6\u5DF2\u505C\u6B62"));this.#D.clear(),this.#h.ready=!1;let e=this.#y;this.#y=null,e?.close({force:!0});let i=this.#f;return this.#f=null,i&&await i.waitForIdle(),this.#B=null,this.#h.feishuLongConnectionState=t?"failed":"idle",this.#h.slashCommandRegistration="idle",this.#h.lastError=a,this.status}};var ew=class extends yr{constructor(t){super({...t,rpcIdPrefix:"feishu",logPrefix:"dsh-feishu"})}};import{createHash as LGe}from"node:crypto";import{mkdir as UGe,readFile as HGe,rename as KGe,unlink as xGe,writeFile as YGe}from"node:fs/promises";import{dirname as jGe}from"node:path";var rw="DSH_FEISHU_APP_SECRET";function ks(n){return typeof n=="string"&&n.trim()?n.trim():null}function QZ(n){let t=ks(n);return t&&/^[A-Za-z0-9_-]{1,128}$/.test(t)?t:null}function yZ(n){return`bot_${LGe("sha256").update(n).digest("hex").slice(0,24)}`}function JGe(n){let t=Array.isArray(n.ownerOpenIds)?n.ownerOpenIds:[n.ownerOpenId];return[...new Set(t.map(ks).filter(Boolean))]}function Aw(n,{legacy:t=!1}={}){if(!n||typeof n!="object")return null;let o=ks(n.appId),a=JGe(n);if(!o||a.length===0)return null;let e=QZ(n.id)??(t?yZ(o):null),i=ks(n.secretRef)??(t?rw:null);if(!e||!i||!/^[A-Za-z_][A-Za-z0-9_]*$/.test(i))return null;let A=n.domain==="lark"?"lark":"feishu";return Object.freeze({id:e,appId:o,secretRef:i,ownerOpenIds:Object.freeze(a),domain:A,botName:ks(n.botName),botOpenId:ks(n.botOpenId),activated:n.activated??null,groupResponseMode:Bo(n.groupResponseMode),groupMessagePermissionGranted:n.groupMessagePermissionGranted===!0,deletionPending:n.deletionPending===!0,connectedAt:ks(n.connectedAt),createdAt:ks(n.createdAt)??ks(n.connectedAt)})}function qGe(n){if(!n||typeof n!="object")return null;if(n.version===2&&Array.isArray(n.bots)){let o=n.bots.map(A=>Aw(A));if(o.some(A=>A===null))throw new Error("dsh-feishu config contains an invalid bot entry");let a=new Set,e=new Set,i=new Set;for(let A of o){if(a.has(A.id)||e.has(A.secretRef)||i.has(A.appId))throw new Error("dsh-feishu config contains duplicate bot identities");a.add(A.id),e.add(A.secretRef),i.add(A.appId)}return{value:Object.freeze({version:2,bots:Object.freeze(o)}),migrated:!1}}let t=Aw(n,{legacy:!0});return t?{value:Object.freeze({version:2,bots:Object.freeze([t])}),migrated:!0}:null}var tw=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 HGe(this.#e,"utf8")),o=qGe(t);if(!o)throw new Error("dsh-feishu config is incomplete or invalid");this.#A=o.value,o.migrated&&await this.#o(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(a=>a.id===t);return o?structuredClone(o):null}async save(t){let o={...t};o.id||(o.id=yZ(ks(o.appId)??"invalid")),o.secretRef||(o.secretRef=rw);let a=Aw(o);if(!a)throw new Error("Refusing to persist incomplete dsh-feishu configuration");return await this.#r([a]),this.get()}async saveBot(t){let o=Aw(t);if(!o)throw new Error("Refusing to persist incomplete dsh-feishu bot configuration");return this.#I(a=>{if(a.find(r=>r.secretRef===o.secretRef&&r.id!==o.id))throw new Error("Refusing to share a credential reference between Feishu bots");if(a.find(r=>r.appId===o.appId&&r.id!==o.id))throw new Error("Refusing to persist the same Feishu app twice");let A=a.findIndex(r=>r.id===o.id);return A===-1?a.push(o):a[A]=o,structuredClone(o)})}async removeBot(t){if(!QZ(t))throw new TypeError("Invalid Feishu bot id");return this.#I(o=>{let a=o.findIndex(i=>i.id===t);if(a===-1)return null;let[e]=o.splice(a,1);return structuredClone(e)})}async clear(){let t=this.#t.then(async()=>{try{await xGe(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])}),a=this.#t.then(async()=>{await this.#o(o),this.#A=o});this.#t=a.then(()=>{},()=>{}),await a}async#I(t){let o,a=this.#t.then(async()=>{let e=[...this.#A.bots];o=t(e);let i=Object.freeze({version:2,bots:Object.freeze(e)});await this.#o(i),this.#A=i});return this.#t=a.then(()=>{},()=>{}),await a,o}async#o(t){await UGe(jGe(this.#e),{recursive:!0,mode:448});let o=`${this.#e}.tmp`;await YGe(o,`${JSON.stringify(t,null,2)} -`,{encoding:"utf8",mode:384}),await KGe(o,this.#e)}};import{randomUUID as bZ}from"node:crypto";var QG=new Set(["starting","qr_ready","polling","slow_down","domain_switched","saving"]),zGe=new Set(["polling","slow_down","domain_switched"]),Va=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 mZ(n){return["access_denied","expired_token","abort"].includes(n?.code)?n.code:"registration_failed"}function yG(n){let t=mZ(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 VGe(n){let t=Number(n);if(!Number.isFinite(t)||t<=0)throw new TypeError("registerApp onQRCodeReady returned an invalid expireIn");return t}function WGe(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 xg=class{#e;#A;#t;#r;#I;#o=0;#g=null;#i;constructor({registerApp:t,onCredentials:o,now:a=Date.now,setTimeout:e=globalThis.setTimeout,clearTimeout:i=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 a!="function"||typeof e!="function"||typeof i!="function")throw new TypeError("RegistrationManager clock dependencies must be functions");this.#e=t,this.#A=o,this.#t=a,this.#r=e,this.#I=i,this.#i=this.#s(null,Va.IDLE)}start(t={}){if(t===null||typeof t!="object"||Array.isArray(t))throw new TypeError("Registration options must be an object");this.#f();let o={id:++this.#o,controller:new AbortController,qrCodeUrl:null,expiresAt:null,pollIntervalSeconds:null,expiryTimer:null};this.#g=o,this.#i=this.#s(o,Va.STARTING);let a={...t,signal:o.controller.signal,onQRCodeReady:i=>this.#c(o,i),onStatusChange:i=>this.#d(o,i)};return Promise.resolve().then(()=>this.#e(a)).then(i=>this.#n(o,i),i=>this.#p(o,i)),this.status()}status(){this.#E();let t={...this.#i};t.error&&(t.error={...t.error});let o=this.#g;return o&&o.expiresAt!==null&&QG.has(t.state)&&(t.remainingSeconds=Math.max(0,Math.ceil((o.expiresAt-this.#t())/1e3))),t}cancel(){let t=this.#g;return t?(this.#C(t,Va.CANCELLED,{error:{code:"abort",message:"Registration was cancelled."}}),t.controller.abort(),this.status()):this.status()}#a(t){return this.#g===t}#s(t,o,a={}){let e={state:o,attempt:t?.id??this.#o,updatedAt:this.#t(),...a};return t?.qrCodeUrl&&QG.has(o)&&(e.qrCodeUrl=t.qrCodeUrl,e.expiresAt=t.expiresAt),t?.pollIntervalSeconds!==null&&QG.has(o)&&(e.pollIntervalSeconds=t.pollIntervalSeconds),e}#l(t,o,a={}){this.#a(t)&&(this.#i=this.#s(t,o,a))}#c(t,o){if(!this.#a(t))return;if(typeof o?.url!="string"||!o.url)throw new TypeError("registerApp onQRCodeReady returned an invalid URL");let a=VGe(o.expireIn);t.qrCodeUrl=o.url,t.expiresAt=this.#t()+a*1e3,this.#B(t),t.expiryTimer=this.#r(()=>this.#u(t),a*1e3),t.expiryTimer?.unref?.(),this.#l(t,Va.QR_READY)}#d(t,o){!this.#a(t)||!zGe.has(o?.status)||(o.status===Va.SLOW_DOWN&&Number.isFinite(Number(o.interval))&&(t.pollIntervalSeconds=Number(o.interval)),this.#l(t,o.status))}async#n(t,o){if(!this.#a(t))return;let a=o?.client_id,e=o?.client_secret;if(typeof a!="string"||!a||typeof e!="string"||!e){this.#C(t,Va.ERROR,{error:{code:"invalid_credentials",message:"Feishu registration returned invalid credentials."}});return}let i;try{i=WGe(o.user_info)}catch{this.#C(t,Va.ERROR,{error:{code:"invalid_credentials",message:"Feishu registration returned invalid credentials."}});return}this.#B(t),t.qrCodeUrl=null,t.expiresAt=null,t.pollIntervalSeconds=null,this.#l(t,Va.SAVING);try{await this.#A({client_id:a,client_secret:e,user_info:i})}catch{this.#a(t)&&this.#C(t,Va.ERROR,{error:{code:"credentials_callback_failed",message:"Unable to store the Feishu credentials."}});return}this.#a(t)&&this.#C(t,Va.SUCCEEDED)}#p(t,o){if(!this.#a(t))return;let a=mZ(o);if(a==="expired_token"){this.#C(t,Va.EXPIRED,{error:yG(o)});return}if(a==="abort"){this.#C(t,Va.CANCELLED,{error:yG(o)});return}this.#C(t,Va.ERROR,{error:yG(o)})}#E(){let t=this.#g;t&&t.expiresAt!==null&&this.#t()>=t.expiresAt&&this.#u(t)}#u(t){this.#a(t)&&(this.#C(t,Va.EXPIRED,{error:{code:"expired_token",message:"The registration QR code expired."}}),t.controller.abort())}#C(t,o,a={}){this.#a(t)&&(this.#B(t),this.#i=this.#s(t,o,a),this.#g=null)}#B(t){t.expiryTimer!==null&&(this.#I(t.expiryTimer),t.expiryTimer=null)}#f(){let t=this.#g;t&&(this.#B(t),this.#g=null,t.controller.abort())}};var ZGe="card.action.trigger",XGe="im:message:readonly",$Ge="im:resource",tB="callback_repair";function eFe(n){return n==="lark"?"accounts.larksuite.com":"accounts.feishu.cn"}function AFe(n){return n==="lark"?"open.larksuite.com":"open.feishu.cn"}function mG(n,t,o="feishu",a="Feishu app update"){let e;try{e=new URL(n)}catch{throw new Error(`${a} returned an invalid verification URL`)}let i=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(!i||e.protocol!=="https:"||e.hostname!==AFe(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(`${a} returned an unsafe verification URL`);return e.toString()}function tFe(n,t,o="feishu"){return mG(n,t,o,"Feishu callback repair")}var iw=class{#e;#A;#t;constructor({registerApp:t,onCredentials:o,appId:a,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 a!="string"||!a.trim())throw new TypeError("appId is required");if(e!=="feishu"&&e!=="lark")throw new TypeError("domain is invalid");this.#A=a.trim(),this.#t=e,this.#e=new xg({registerApp:i=>t({...i,onQRCodeReady:A=>{tFe(A?.url,this.#A,this.#t),i.onQRCodeReady(A)}}),onCredentials:o})}start(){return this.#e.start({source:"deepseek-harness-card-action-repair",domain:eFe(this.#t),appId:this.#A,addons:{preset:!1,scopes:{tenant:[XGe,$Ge,...XS]},callbacks:{items:[ZGe]}}})}status(){return this.#e.status()}cancel(){return this.#e.cancel()}};var rFe="im:message.group_msg",ow="group_message_permission";function iFe(n){return n==="lark"?"accounts.larksuite.com":"accounts.feishu.cn"}function aFe(n,t,o="feishu"){return mG(n,t,o,"Feishu group message permission update")}var aw=class{#e;#A;#t;constructor({registerApp:t,onCredentials:o,appId:a,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 a!="string"||!a.trim())throw new TypeError("appId is required");if(e!=="feishu"&&e!=="lark")throw new TypeError("domain is invalid");this.#A=a.trim(),this.#t=e,this.#e=new xg({registerApp:i=>t({...i,onQRCodeReady:A=>{aFe(A?.url,this.#A,this.#t),i.onQRCodeReady(A)}}),onCredentials:o})}start(){return this.#e.start({source:"deepseek-harness-group-message-permission",domain:iFe(this.#t),appId:this.#A,addons:{preset:!1,scopes:{tenant:[rFe]}}})}status(){return this.#e.status()}cancel(){return this.#e.cancel()}};var SZ=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",...XS]);var SG=new Set(["starting","qr_ready","polling","slow_down","domain_switched"]),nw=new Set([...SG,"saving"]),wZ=new Set([tB,ow]),DZ="*",oFe=12e4,nFe=6e5;function MZ(){return{ready:!1,feishuLongConnectionState:"idle",harnessReachable:!1}}function rB(n){return n?n.status:MZ()}function iB(n){return n.ready===!0&&n.feishuLongConnectionState==="connected"&&n.harnessReachable===!0}function _Z(n){return n.length>12?`${n.slice(0,8)}\u2022\u2022\u2022\u2022${n.slice(-4)}`:"cli_\u2022\u2022\u2022\u2022"}function sFe(n){return{name:n.botName,appIdMasked:_Z(n.appId),activated:n.activated,domain:n.domain}}function gFe({connected:n,error:t,connection:o}){return n?"connected":t||o.feishuLongConnectionState==="failed"?"error":"disconnected"}function cFe(){return`bot_${bZ().replaceAll("-","")}`}function IFe(){return`reg_${bZ().replaceAll("-","")}`}function OZ(n){return`DSH_FEISHU_APP_SECRET_${n.slice(4).toUpperCase()}`}function sw(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:Bo(n.groupResponseMode),groupMessagePermissionGranted:n.groupMessagePermissionGranted===!0,deletionPending:n.deletionPending===!0,connectedAt:n.connectedAt??null,createdAt:n.createdAt??null})}function gw(n){return typeof n=="string"&&n.trim()?n.trim():null}var aB=class{#e;#A;#t;#r;#I;#o;#g;#i;#a=new Map;#s=new Map;#l=new Map;#c=new Map;#d=new Map;#n=null;#p=Promise.resolve();#E=new Map;#u=1;#C;#B=!1;constructor({registerApp:t,verifyApp:o,credentials:a,configStore:e,createRuntime:i,deleteState:A=async()=>{},createBotId:r=cFe,createRegistrationId:s=IFe,callbackProbeTimeoutMs:g=oFe}){if(typeof t!="function")throw new Error("registerApp is required");if(typeof o!="function")throw new Error("verifyApp is required");if(!a)throw new Error("credentials service is required");if(!e||typeof e.list!="function")throw new Error("multi-bot config store is required");if(typeof i!="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>nFe)throw new TypeError("callbackProbeTimeoutMs must be between 1 and 600000ms");this.#e=t,this.#A=o,this.#t=a,this.#r=e,this.#I=i,this.#o=A,this.#g=r,this.#i=s,this.#C=g}async initialize(){if(this.#B)return this.status();let t=this.#r.list(),o=!1;return await Promise.allSettled(t.map(a=>this.#_(a.id,async()=>{let e=rB(this.#a.get(a.id));if(iB(e)||e.feishuLongConnectionState==="connecting"||e.feishuLongConnectionState==="reconnecting")return;if(o=!0,a.deletionPending){this.#s.set(a.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 i;try{i=await this.#t.resolve(a.secretRef)}catch{this.#s.set(a.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(!i?.value){this.#s.set(a.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.#h(a,i.value),this.#s.delete(a.id)}catch{this.#s.set(a.id,{code:"connection_failed",message:"\u673A\u5668\u4EBA\u6682\u65F6\u65E0\u6CD5\u8FDE\u63A5\u98DE\u4E66\uFF0C\u8BF7\u91CD\u8BD5\u3002"})}}))),o&&this.#R(),this.status()}startRegistration(){this.#N();let t=this.#i();if(typeof t!="string"||!/^[A-Za-z0-9_-]{1,128}$/.test(t)||this.#l.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 xg({registerApp:this.#e,onCredentials:a=>this.#P(()=>this.#D(o,a))}),this.#l.set(t,o),this.#n=t,this.#G(),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:[...SZ]},events:{items:{tenant:["im.message.receive_v1"]}},callbacks:{items:["card.action.trigger"]}}}),this.#R(),this.registrationStatus(t)}startCallbackRepair(t,{actorOpenId:o,chatId:a}={}){this.#N();let e=this.#T(t);if(e.deletionPending)throw new Error("Cannot repair a Feishu bot pending deletion");let i=this.#c.get(t),A=i?this.#l.get(i):null;if(A&&nw.has(A.manager.status().state)){if(A.operation!==tB)throw new Error("Another Feishu app update is already active for this bot");return this.registrationStatus(A.id)}this.#c.delete(t);let r=this.#i();if(typeof r!="string"||!/^[A-Za-z0-9_-]{1,128}$/.test(r)||this.#l.has(r))throw new Error("Registration id generator returned an invalid or duplicate id");let s={id:r,operation:tB,manager:null,botId:t,createdNew:!1,cancelled:!1,remoteCommitted:!1,processing:null,publicError:null,stage:"authorizing",target:structuredClone(e),targetFingerprint:sw(e),initiator:{actorOpenId:gw(o),chatId:gw(a)}};return s.manager=new iw({registerApp:this.#e,appId:e.appId,domain:e.domain,onCredentials:g=>{s.remoteCommitted=!0;let I=this.#m(s,g).finally(()=>{s.processing===I&&(s.processing=null)});return s.processing=I,I}}),this.#l.set(r,s),this.#c.set(t,r),this.#n=r,this.#G(),s.manager.start(),this.#R(),this.registrationStatus(r)}startGroupMessagePermission(t){this.#N();let o=this.#T(t);if(o.deletionPending)throw new Error("Cannot update permissions for a Feishu bot pending deletion");let a=this.#c.get(t),e=a?this.#l.get(a):null;if(e&&nw.has(e.manager.status().state)){if(e.operation!==ow)throw new Error("Another Feishu app update is already active for this bot");return this.registrationStatus(e.id)}this.#c.delete(t);let i=this.#i();if(typeof i!="string"||!/^[A-Za-z0-9_-]{1,128}$/.test(i)||this.#l.has(i))throw new Error("Registration id generator returned an invalid or duplicate id");let A={id:i,operation:ow,manager:null,botId:t,createdNew:!1,cancelled:!1,remoteCommitted:!1,processing:null,publicError:null,stage:"authorizing",target:structuredClone(o),targetFingerprint:sw(o),initiator:{actorOpenId:null,chatId:null}};return A.manager=new aw({registerApp:this.#e,appId:o.appId,domain:o.domain,onCredentials:r=>{A.remoteCommitted=!0;let g=this.#w(A,r).finally(()=>{A.processing===g&&(A.processing=null)});return A.processing=g,g}}),this.#l.set(i,A),this.#c.set(t,i),this.#n=i,this.#G(),A.manager.start(),this.#R(),this.registrationStatus(i)}hasRegistration(t){return this.#l.has(t)}registrationStatus(t){let o=this.#l.get(t);return o?this.#f({registration:o,selectedBotId:o.botId}):null}async cancelRegistration(t=this.#n){let o=this.#l.get(t);if(!o)return this.status();let a=o.manager.status().state;return wZ.has(o.operation)&&a==="saving"?this.registrationStatus(t):nw.has(a)?(o.cancelled=!0,o.manager.cancel(),await this.#P(async()=>{o.createdNew&&o.botId&&this.#d.get(o.botId)===o.id&&this.#r.getBot(o.botId)&&await this.#_(o.botId,()=>this.#O(o.botId))}),this.#R(),this.registrationStatus(t)??this.status()):this.registrationStatus(t)}status(t){return this.#f({registration:this.#l.get(this.#n)??null,selectedBotId:t})}async bindCredentials({appId:t,appSecret:o,domain:a="feishu"}={}){this.#N();let e=typeof t=="string"?t.trim():"",i=typeof o=="string"?o.trim():"",A=a==="lark"?"lark":"feishu";if(!e||!i)throw new TypeError("Feishu App ID and App Secret are required");return this.#P(async()=>{this.#N();let r=await this.#A({appId:e,appSecret:i,domain:A});this.#N();let s=this.#r.list().find(f=>f.appId===e),g=s?.id??this.#g();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??OZ(g),I=await this.#t.resolve(c).catch(()=>{}),d={...s,id:g,appId:e,secretRef:c,ownerOpenIds:s?.ownerOpenIds?.length?s.ownerOpenIds:[DZ],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,i);let B;try{B=await this.#r.saveBot(d)}catch(f){throw await this.#S(c,I),f}return await this.#_(g,async()=>{try{await this.#h(B,i),this.#s.delete(g)}catch{this.#s.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.#R(),this.status(g)})}async reconnectBot(t){return this.#N(),this.#_(t,async()=>{let o=this.#T(t);if(o.deletionPending)return this.#s.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(iB(rB(this.#a.get(t))))return this.status(t);let a;try{a=await this.#t.resolve(o.secretRef)}catch{a=null}if(!a?.value)return this.#s.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.#R(),this.status(t);try{await this.#h(o,a.value),this.#s.delete(t)}catch{this.#s.set(t,{code:"connection_failed",message:"\u673A\u5668\u4EBA\u6682\u65F6\u65E0\u6CD5\u8FDE\u63A5\u98DE\u4E66\uFF0C\u8BF7\u91CD\u8BD5\u3002"})}return this.#R(),this.status(t)})}async sendConnectionTest(t){return this.#N(),this.#_(t,async()=>{let o=this.#T(t),a=this.#a.get(t);if(!iB(rB(a))||typeof a.sendConnectionTest!="function"){let e=new Error("\u98DE\u4E66\u673A\u5668\u4EBA\u5C1A\u672A\u8FDE\u63A5");throw e.code="test-target-unavailable",e}return a.sendConnectionTest(Ki(`${o.botName}\uFF08${_Z(o.appId)}\uFF09`,"\u98DE\u4E66\u673A\u5668\u4EBA"))})}async sendProactiveText(t,o,a,e={}){return this.#N(),this.#_(t,async()=>{this.#T(t);let i=this.#a.get(t);if(!iB(rB(i))||typeof i.sendProactiveText!="function"){let A=new Error("\u98DE\u4E66\u673A\u5668\u4EBA\u5C1A\u672A\u8FDE\u63A5");throw A.code="bot-not-connected",A}return i.sendProactiveText(o,a,e)})}async disconnectBot(t){return this.#N(),this.#_(t,async()=>(this.#T(t),await this.#M(t),this.#s.delete(t),this.#R(),this.status(t)))}async updateGroupResponseMode(t,o){if(this.#N(),!YS(o))throw new TypeError("Invalid Feishu group response mode");return this.#P(()=>this.#_(t,async()=>{let a=this.#T(t);if(o==="all"&&a.groupMessagePermissionGranted!==!0){let i=new Error("Authorize im:message.group_msg before enabling all group messages");throw i.code="group_message_permission_required",i}let e=await this.#r.saveBot({...a,groupResponseMode:o});return this.#a.get(t)?.setGroupResponseMode?.(e.groupResponseMode),this.#R(),this.status(t)}))}async deleteBot(t){return this.#N(),this.#P(()=>this.#_(t,async()=>(this.#T(t),await this.#O(t),this.#R(),this.status())))}async reconnect(){let t=this.#r.list()[0];return t?this.reconnectBot(t.id):this.status()}async disconnect(){let t=this.#r.list()[0];return t?this.deleteBot(t.id):this.status()}async close(){if(this.#B)return;this.#B=!0;let t=[];for(let o of this.#l.values()){let a=o.manager.status().state;wZ.has(o.operation)&&a==="saving"?(o.manager.cancel(),o.processing&&t.push(o.processing)):nw.has(a)&&(o.cancelled=!0,o.manager.cancel())}await this.#p,await Promise.allSettled([...this.#E.values()]),await Promise.allSettled([...this.#a.keys()].map(o=>this.#M(o))),await Promise.allSettled(t),await this.#p,await Promise.allSettled([...this.#E.values()]),await Promise.allSettled([...this.#a.keys()].map(o=>this.#M(o)))}#f({registration:t,selectedBotId:o}={}){let a=this.#r.list().map(I=>{let d=rB(this.#a.get(I.id)),B=iB(d),f=this.#s.get(I.id)??null;return{botId:I.id,phase:gFe({connected:B,error:f,connection:d}),connected:B,configured:!0,groupResponseMode:Bo(I.groupResponseMode),groupMessagePermissionGranted:I.groupMessagePermissionGranted===!0,bot:sFe(I),connection:d,lastMessageError:ii(d.lastMessageError),error:f}}),e=t?this.#y(t):{state:"idle",attempt:0,updatedAt:Date.now()},i=SG.has(e.state),A=e.state==="saving",r=!!t&&(i||A),s=a.find(I=>I.botId===o)??(r?null:a[0]??null),g=a.some(I=>I.connected),c=s?.phase??"unconfigured";return i?c="registering":A?c="connecting":e.state==="error"&&!s&&(c="error"),{schemaVersion:2,revision:this.#u,phase:c,connected:s?.connected??!1,configured:a.length>0,bot:s?.bot??null,connection:s?.connection??MZ(),error:s?.error??e.error??null,registration:e,bots:a,totals:{configured:a.length,connected:a.filter(I=>I.connected).length},anyConnected:g}}#y(t){let o=t.manager.status();return{...o,attempt:t.id,...t.botId?{botId:t.botId}:{},...t.operation?{operation:t.operation}:{},...t.stage?{stage:t.stage}:{},...o.state==="error"&&t.publicError?{error:{...t.publicError}}:{}}}async#w(t,o){let a=o.client_id,e=o.client_secret,i=gw(o.user_info?.open_id),A=o.user_info?.tenant_brand,r=t.target;if(t.cancelled)throw this.#Q(t,"abort","Group message permission update was cancelled before local activation.");if(a!==r.appId)throw this.#Q(t,"repair_app_mismatch","Feishu returned credentials for a different app.");if(!i)throw this.#Q(t,"repair_owner_missing","Feishu returned no permission operator identity.");if(A!==void 0&&A!==r.domain)throw this.#Q(t,"repair_domain_mismatch","Feishu returned credentials for a different account domain.");if(!r.ownerOpenIds.includes(DZ)&&!r.ownerOpenIds.includes(i))throw this.#Q(t,"repair_owner_mismatch","The Feishu permission operator is not an owner of this configured bot.");t.stage="verifying_identity";let s;try{s=await this.#A({appId:a,appSecret:e,domain:r.domain})}catch(g){throw this.#Q(t,"repair_credentials_invalid","Feishu could not verify the updated app credentials.",g)}if(r.botOpenId&&s?.openId!==r.botOpenId)throw this.#Q(t,"repair_bot_mismatch","The updated Feishu app belongs to a different bot identity.");await this.#P(()=>this.#_(t.botId,async()=>{let g=this.#r.getBot(t.botId);if(!g||g.deletionPending||sw(g)!==t.targetFingerprint)throw this.#Q(t,"repair_target_changed","The Feishu bot changed while its permission update was in progress.");let c;try{c=await this.#t.resolve(g.secretRef)}catch(d){throw this.#Q(t,"credential_update_failed","Unable to read the current Feishu credential.",d)}if(c?.value!==e){t.stage="persisting_secret";try{await this.#t.set(g.secretRef,e)}catch(B){if((await this.#t.resolve(g.secretRef).catch(()=>null))?.value!==e)throw this.#Q(t,"credential_update_failed","Unable to store the updated Feishu credential.",B)}if((await this.#t.resolve(g.secretRef).catch(()=>null))?.value!==e)throw this.#Q(t,"credential_state_unknown","The updated Feishu credential could not be confirmed after writing.")}t.stage="enabling_all_messages";let I;try{I=await this.#r.saveBot({...g,groupMessagePermissionGranted:!0,groupResponseMode:"all"})}catch(d){throw this.#Q(t,"group_message_permission_save_failed","The permission was accepted, but all-message mode could not be saved.",d)}t.stage="restarting";try{await this.#h(I,e)}catch(d){throw this.#s.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.#R(),this.#Q(t,"group_message_permission_connection_failed","The permission was accepted, but the Feishu runtime could not restart.",d)}this.#s.delete(t.botId),t.stage="verified",t.publicError=null,this.#R()}))}async#m(t,o){let a=o.client_id,e=o.client_secret,i=gw(o.user_info?.open_id),A=o.user_info?.tenant_brand,r=t.target;if(t.cancelled)throw this.#Q(t,"abort","Callback repair was cancelled before local activation.");if(a!==r.appId)throw this.#Q(t,"repair_app_mismatch","Feishu returned credentials for a different app.");if(!i)throw this.#Q(t,"repair_owner_missing","Feishu returned no repair operator identity.");if(A!==void 0&&A!==r.domain)throw this.#Q(t,"repair_domain_mismatch","Feishu returned credentials for a different account domain.");t.stage="verifying_identity";let s;try{s=await this.#A({appId:a,appSecret:e,domain:r.domain})}catch(c){throw this.#Q(t,"repair_credentials_invalid","Feishu could not verify the repaired app credentials.",c)}if(r.botOpenId&&s?.openId!==r.botOpenId)throw this.#Q(t,"repair_bot_mismatch","The repaired Feishu app belongs to a different bot identity.");let g=await this.#P(()=>this.#_(t.botId,async()=>{let c=this.#r.getBot(t.botId);if(!c||c.deletionPending||sw(c)!==t.targetFingerprint)throw this.#Q(t,"repair_target_changed","The Feishu bot changed while its callback repair was in progress.");let I;try{I=await this.#t.resolve(c.secretRef)}catch(f){throw this.#Q(t,"credential_update_failed","Unable to read the current Feishu credential.",f)}if(I?.value!==e){t.stage="persisting_secret";try{await this.#t.set(c.secretRef,e)}catch(Q){if((await this.#t.resolve(c.secretRef).catch(()=>null))?.value!==e)throw this.#Q(t,"credential_update_failed","Unable to store the repaired Feishu credential.",Q)}if((await this.#t.resolve(c.secretRef).catch(()=>null))?.value!==e)throw this.#Q(t,"credential_state_unknown","The repaired Feishu credential could not be confirmed after writing.")}let B;t.stage="restarting";try{await this.#h(c,e),B=this.#a.get(t.botId)}catch(f){throw this.#s.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.#R(),this.#Q(t,"repair_connection_failed","The repaired Feishu runtime could not be started.",f)}if(!B)throw this.#Q(t,"repair_connection_failed","The repaired Feishu runtime is unavailable.");return this.#s.delete(t.botId),this.#R(),B}));if(typeof g.beginCardActionProbe!="function")throw this.#Q(t,"card_action_probe_unavailable","The Feishu runtime cannot verify card callbacks.");t.stage="awaiting_callback";try{if((await g.beginCardActionProbe({expectedOperatorOpenId:t.initiator.actorOpenId??i,timeoutMs:this.#C,...t.initiator.chatId?{chatId:t.initiator.chatId}:{}}))?.verified!==!0){let I=new Error("Feishu runtime returned no callback proof");throw I.code="card_action_probe_failed",I}}catch(c){let I=c?.code==="card_action_probe_timeout"?"card_action_probe_timeout":c?.code==="card_action_probe_unavailable"?"card_action_probe_unavailable":c?.code==="card_action_probe_send_failed"?"card_action_probe_send_failed":"card_action_probe_failed";throw this.#Q(t,I,I==="card_action_probe_timeout"?"Timed out waiting for the Feishu callback verification button.":"The Feishu card callback probe failed.",c)}t.stage="verified",t.publicError=null,this.#R()}#Q(t,o,a,e){t.publicError={code:o,message:a};let i=new Error(a,e?{cause:e}:void 0);return i.code=o,i}async#D(t,o){if(t.cancelled)throw new Error("Registration was cancelled");let a=o.client_id,e=o.client_secret,i=o.user_info?.open_id,A=o.user_info?.tenant_brand==="lark"?"lark":"feishu";if(!i)throw new Error("Feishu registration returned no owner open_id");let r=await this.#A({appId:a,appSecret:e,domain:A});if(t.cancelled)throw new Error("Registration was cancelled");let s=this.#r.list().find(Q=>Q.appId===a),g=s?.id??this.#g();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??OZ(g),I=this.#d.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:a,secretRef:c,ownerOpenIds:[...new Set([...s?.ownerOpenIds??[],i])],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.#d.set(g,t.id)}catch(Q){try{await this.#S(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.#_(g,()=>this.#O(g)):(await this.#r.saveBot(s),await this.#S(c,d),I?this.#d.set(g,I):this.#d.delete(g)),new Error("Registration was cancelled");let f=!1;try{if(await this.#_(g,()=>this.#h(B,e)),t.cancelled)throw t.createdNew?await this.#_(g,()=>this.#O(g)):(await this.#r.saveBot(s),await this.#S(c,d),I?this.#d.set(g,I):this.#d.delete(g),d?.value&&!s.deletionPending?await this.#_(g,()=>this.#h(s,d.value)):await this.#_(g,()=>this.#M(g))),f=!0,new Error("Registration was cancelled");this.#s.delete(g),this.#R()}catch(Q){if(t.cancelled)throw!f&&t.createdNew&&this.#r.getBot(g)?await this.#_(g,()=>this.#O(g)):!f&&s&&(await this.#r.saveBot(s),await this.#S(c,d),I?this.#d.set(g,I):this.#d.delete(g),!this.#B&&d?.value&&!s.deletionPending?await this.#_(g,()=>this.#h(s,d.value)):await this.#_(g,()=>this.#M(g))),this.#R(),Q;if(s&&d?.value)try{throw await this.#r.saveBot(s),await this.#S(c,d),I?this.#d.set(g,I):this.#d.delete(g),s.deletionPending?(await this.#_(g,()=>this.#M(g)),this.#s.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.#_(g,()=>this.#h(s,d.value)),this.#s.delete(g)),this.#R(),Q}catch(y){throw y===Q?Q:(this.#s.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.#R(),new Error("Unable to restore the previous Feishu bot connection.",{cause:y}))}throw this.#s.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.#R(),Q}}async#h(t,o){await this.#M(t.id);let a=await this.#I({botId:t.id,config:t,appSecret:o,repair:this.#k(t.id)});this.#a.set(t.id,a);try{await a.start()}catch(e){throw this.#a.get(t.id)===a&&this.#a.delete(t.id),await a.stop({preserveError:!0}).catch(()=>{}),e}}#k(t){let o=a=>{let e=this.#l.get(a);return e?.operation===tB&&e.botId===t?e:null};return Object.freeze({start:({actorOpenId:a,chatId:e}={})=>this.startCallbackRepair(t,{actorOpenId:a,chatId:e}),status:({attemptId:a}={})=>o(a)?this.registrationStatus(a):null,cancel:async({attemptId:a}={})=>o(a)?this.cancelRegistration(a):this.status(t)})}async#M(t){let o=this.#a.get(t);this.#a.delete(t),o&&await o.stop()}async#O(t){let o=this.#r.getBot(t);if(o){o.deletionPending||(o=await this.#r.saveBot({...o,deletionPending:!0})),await this.#M(t);try{await this.#t.unset(o.secretRef)}catch(a){throw this.#s.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:a})}try{await this.#o({botId:t,config:o})}catch(a){throw this.#s.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:a})}await this.#r.removeBot(t),this.#s.delete(t),this.#d.delete(t)}}async#S(t,o){o?.value?await this.#t.set(t,o.value):await this.#t.unset(t)}#T(t){let o=this.#r.getBot(t);if(!o)throw new Error("Unknown Feishu bot");return o}#N(){if(this.#B)throw new Error("The Feishu controller is closed")}#P(t){let o=this.#p.then(t,t);return this.#p=o.then(()=>{},()=>{}),o}#_(t,o){let e=(this.#E.get(t)??Promise.resolve()).then(o,o),i=e.then(()=>{},()=>{});return this.#E.set(t,i),i.finally(()=>{this.#E.get(t)===i&&this.#E.delete(t)}),e}#G(){if(!(this.#l.size<=32))for(let[t,o]of this.#l){if(t===this.#n)continue;let a=o.manager.status().state;if(!SG.has(a)&&a!=="saving"&&this.#l.delete(t),this.#l.size<=32)break}}#R(){this.#u+=1}};var pFe=["open.feishu.cn","open.larksuite.com"];function hFe(n,t){if(t==="*")return!0;let o=t.startsWith(".")?t.slice(1):t;return o?n===o||n.endsWith(`.${o}`):!1}function EFe(n){for(let t of["no_proxy","NO_PROXY"]){let o=n?.[t];if(typeof o!="string"||!o.trim())continue;let a=o.split(",").map(e=>e.trim().toLowerCase()).filter(Boolean);if(pFe.some(e=>a.some(i=>hFe(e,i))))return!0}return!1}function uFe(n){if(!EFe(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 CFe(n,t=o=>new TZ.default(o)){let o=uFe(n);return o?t(o):void 0}function BFe(n){let t=Xc(n.dshHome??process.env.DSH_HOME??hh(lFe(),".dsh")),o=Xc(n.dataDir??hh(t,"integrations","dsh-feishu"));return{root:o,config:Xc(n.configPath??hh(o,"config.json")),legacyState:Xc(n.statePath??hh(o,"state.json")),bots:Xc(n.botsDir??hh(o,"bots")),workspaces:Xc(n.workspacesPath??hh(o,"workspaces.json"))}}async function wG(n,t={},o={}){if(!n?.credentials)throw new TypeError("dsh-feishu requires ctx.credentials");let a=ci(n,t),e=o.lark??rG,i=o.Controller??aB,A=o.ConfigStore??tw,r=o.StateStore??KS,s=o.HarnessClient??ew,g=o.FeishuRuntime??$S,c=o.verifyFeishuApp??R5,I=Be=>c({...Be,httpInstance:e.defaultHttpInstance}),d=o.createConnectionSupervisor??iG,B=typeof n.logger=="function"?n.logger("dsh-feishu"):n.logger??console,f=()=>ji(n),Q=BFe(t),y=await new A(Q.config).load(),m=Xc(t.workspace??process.cwd()),_=o.WorkspaceStore??gi,T=o.workspaces??await new _(Q.workspaces,{defaultWorkspace:m}).load(),R=typeof y.list=="function",L=()=>R?y.list():[],U=L();R&&await T.reconcile(U.map(Be=>Be.id)),await Promise.all(U.map(Be=>T.ensure(Be.id,{defaultAgentPreset:t.agentPreset,initialAccessPolicy:pr("feishu",Be)})));let F=typeof y.removeBot=="function"?Ji(y,{workspaces:T,method:"removeBot",botIdFromRemoved:Be=>Be.id,saveMethod:"saveBot",botIdFromSave:Be=>Be?.id}):y,z=new Map,J=Be=>!Be.id||!Be.secretRef||Be.secretRef===rw?Q.legacyState:Xc(Q.bots,Be.id,"state.json"),K=async Be=>{let Re=Be.id??"__legacy__",Ne=z.get(Re);return Ne||(Ne=await new r(J(Be)).load(),z.set(Re,Ne)),Ne},G=async Be=>{let Re=L().find(Ne=>Ne.id===Be);if(!Re)throw new Error("Unknown Feishu bot");return K(Re)},V=Wi(n,o.commandExecutor),{controlExecutor:H,sessionMaintenanceExecutor:N,fileIngressExecutor:k}=Zi(n,{controlExecutor:o.controlExecutor,sessionMaintenanceExecutor:o.sessionMaintenanceExecutor,fileIngressExecutor:o.fileIngressExecutor}),q=new s({...a,workspace:m,autostart:!1,dshBin:t.dshBin??"dsh",...V?{commandExecutor:V}:{},...H?{controlExecutor:H}:{},...N?{sessionMaintenanceExecutor:N}:{},...k?{fileIngressExecutor:k}:{}}),X=o.proxyEnv??process.env,ie=CFe(X,o.createProxyAgent),De=new i({registerApp:Be=>e.registerApp(Be),verifyApp:I,credentials:n.credentials,configStore:F,createRuntime:async({botId:Be,config:Re,appSecret:Ne,repair:Je})=>{let ve=await K(Re),tA=Be??Re.id??Re.appId;await T.ensure(tA,{defaultAgentPreset:t.agentPreset,initialAccessPolicy:pr("feishu",Re)});let fe=qi(q,{botId:tA,workspaces:T,state:ve,agentPresetCatalog:f});return new g({lark:e,botId:tA,repair:Je,appId:Re.appId,appSecret:Ne,domain:Re.domain,botOpenId:Re.botOpenId,groupResponseMode:Re.groupResponseMode,ownerOpenIds:Re.ownerOpenIds??[Re.ownerOpenId],harness:fe.harness,state:fe.state,contextEnhancement:{botId:tA,getSettings:()=>T.contextEnhancementFor(tA)},accessPolicy:Xi(T,tA,{channel:"feishu",config:Re}),groupSessionScope:{getScope:()=>T.groupSessionScopeFor(tA)},replyTimeoutMs:t.replyTimeoutMs??6e5,slashCommands:t.slashCommands!==!1,...ie?{wsAgent:ie}:{},logger:{error:(...Ie)=>B.error?.(`[${Be??Re.id}]`,...Ie),warn:(...Ie)=>B.warn?.(`[${Be??Re.id}]`,...Ie),info:(...Ie)=>B.info?.(`[${Be??Re.id}]`,...Ie),debug:(...Ie)=>B.debug?.(`[${Be??Re.id}]`,...Ie)}})},deleteState:async({botId:Be,config:Re})=>{z.delete(Be);try{await dFe(J(Re))}catch(Ne){if(Ne?.code!=="ENOENT")throw Ne}}}),oe=zi(De,{workspaces:T,stateFor:G,agentPresetCatalog:f}),Se=d({controller:oe,harness:q,logger:B,retryDelaysMs:t.retryDelaysMs,healthyIntervalMs:t.healthyIntervalMs}).start();return{controller:oe,deliveryAdapter:Vi({channel:"feishu",workspaces:T,coreController:De,stateFor:G}),ready:Se.ready,async close(){await Se.close(),await oe.close(),q.stopManagedProcess(),ie?.destroy?.()}}}import FFe from"qrcode";var uh=ze(NG(),1);var vFe=ze(NG(),1);var PFe=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",\u673A\u5668\u4EBA\u8BBE\u7F6E:"Bot settings",\u673A\u5668\u4EBA\u8BBE\u7F6E\u9875\u7B7E:"Bot settings tabs",\u6295\u9012\u8BBE\u7F6E:"Delivery settings",\u8BBF\u95EE\u8BBE\u7F6E:"Access settings",\u52A0\u672C\u7FA4:"Add to group",\u5DF2\u5728\u672C\u7FA4:"Already in group",\u52A0\u79C1\u804A:"Add to DMs",\u5DF2\u5728\u79C1\u804A:"Already in DMs","\u5DF2\u52A0\u5165\u672C\u7FA4\u6388\u6743\uFF0C\u8BB0\u5F97\u70B9\u4FDD\u5B58\u3002":"Added to this group. Remember to save.","\u5DF2\u52A0\u5165\u79C1\u804A\u6388\u6743\uFF0C\u8BB0\u5F97\u70B9\u4FDD\u5B58\u3002":"Added to DM access. Remember to save.","\u6682\u65E0\u8054\u7CFB\u4EBA\u3002\u6709\u4EBA\u79C1\u804A\u6216 @ \u673A\u5668\u4EBA\u540E\u4F1A\u51FA\u73B0\u5728\u6B64\u3002":"No contacts yet. They appear here after someone DMs or @mentions the bot.","\u4EC5\u8BB0\u5F55\u79C1\u804A\u673A\u5668\u4EBA\uFF0C\u6216\u5728\u7FA4\u91CC @ \u673A\u5668\u4EBA\u7684\u4EBA\u3002\u7535\u8BDD\u662F\u552F\u4E00\u6388\u6743\u952E\uFF0C\u53EF\u4E00\u952E\u52A0\u5165\u79C1\u804A/\u672C\u7FA4\u6388\u6743\u3002":"Only people who DM the bot or @mention it in a group are recorded. Phone is the sole auth key; use one-click to grant DM or group access.","WhatsApp \u6309\u7535\u8BDD\u53F7\u7801\u6388\u6743\uFF1A\u5168\u5C40\u7BA1\u7406\u5458\u7BA1\u79C1\u804A\uFF1B\u7FA4\u7BA1\u7406\u5458\u53EA\u6279\u672C\u7FA4\u3002\u6210\u5458\u4E0D\u53EF\u8DE8\u7FA4\u3001\u6709\u7FA4\u6743\u4E5F\u4E0D\u81EA\u52A8\u83B7\u5F97\u79C1\u804A\u6743\u3002":"WhatsApp authorizes by phone number: global admins manage DMs; group admins approve only their group. Members do not cross groups, and group access does not grant DMs.",\u4FDD\u5B58\u5206\u7EA7\u8BBF\u95EE\u8BBE\u7F6E:"Save graded access settings",\u4FDD\u5B58\u8BBF\u95EE\u4E0E\u4F1A\u8BDD\u8BBE\u7F6E:"Save access and session settings",\u5168\u5C40\u7BA1\u7406\u5458:"Global admins","\u5206\u7EA7\u8BBF\u95EE\u8BBE\u7F6E\u5DF2\u4FDD\u5B58\u3002":"Graded access settings saved.","\u5BA1\u6279\u5931\u8D25\u3002":"Approval failed.","\u5C1A\u65E0\u5DF2\u77E5\u7FA4\u3002\u53EF\u5728\u4E0B\u65B9\u7C98\u8D34\u7FA4 JID\uFF08\u2026@g.us\uFF09\uFF0C\u6216\u7B49\u7FA4\u5185\u6709\u4EBA @ \u673A\u5668\u4EBA\u540E\u81EA\u52A8\u51FA\u73B0\u3002":"No known groups yet. Paste a group JID (\u2026@g.us) below, or wait until someone @mentions the bot in a group.","\u5DF2\u6279\u51C6\u7533\u8BF7\u3002":"Request approved.","\u5DF2\u62D2\u7EDD\u7533\u8BF7\u3002":"Request denied.","\u5F53\u524D\u6E20\u9053\u4ECD\u4F7F\u7528\u65E7\u7248\u8BBF\u95EE\u8BBE\u7F6E\u3002":"This channel still uses the legacy access settings.",\u5F85\u5BA1\u6279:"Pending approval",\u5F85\u8865\u7535\u8BDD:"Phone pending",\u6279\u51C6:"Approve",\u62D2\u7EDD:"Deny","\u6309\u53D1\u8A00\u4EBA\u62C6\u5206\uFF08\u63A8\u8350\uFF09":"Split by speaker (recommended)","\u6574\u7FA4\u5171\u4EAB\u4E00\u4E2A Session":"Share one session for the whole group",\u65B0\u589E\u7BA1\u7406\u5458:"Add admin",\u6682\u65E0\u5F85\u6279\u7533\u8BF7:"No pending requests","\u6682\u65E0\u8054\u7CFB\u4EBA\u3002\u79C1\u804A\u6216\u7FA4\u5185\u89E6\u53D1\u540E\u4F1A\u51FA\u73B0\u5728\u6B64\uFF0C\u4FBF\u4E8E\u8865\u9F50\u7535\u8BDD\u4E0E\u6635\u79F0\u3002":"No contacts yet. People who DM or trigger the bot in a group appear here so you can fill in phones and names.","\u6700\u8FD1\u8054\u7CFB\u4EBA\uFF08\u81EA\u52A8\u6C89\u6DC0\uFF09":"Recent contacts (auto-collected)","\u670D\u52A1\u6CA1\u6709\u8FD4\u56DE\u5DF2\u4FDD\u5B58\u7684\u8BBF\u95EE\u6388\u6743\u3002":"The service did not return the saved access grant.",\u672A\u547D\u540D:"Unnamed","\u672A\u914D\u7F6E\u65F6\uFF0C\u672C\u7FA4\u7533\u8BF7\u56DE\u843D\u7ED9\u5168\u5C40\u7BA1\u7406\u5458\u5BA1\u6279\uFF08\u4ECD\u53EA\u6388\u4E88\u672C\u7FA4\u6743\uFF09\u3002":"When unset, this group's requests fall back to global admins (still grants only this group).",\u672C\u7FA4\u6388\u6743\u6210\u5458:"Group members",\u672C\u7FA4\u7BA1\u7406\u5458:"Group admins",\u67E5\u770B\u7FA4\u4F1A\u8BDD\u7B56\u7565\u8BF4\u660E:"View group session policy details",\u6DFB\u52A0\u7FA4:"Add group","\u6DFB\u52A0\u7FA4 JID":"Add group JID",\u7535\u8BDD:"Phone",\u79C1\u804A\u6388\u6743\u7528\u6237:"DM members","\u7ED1\u5B9A\u8D26\u53F7\u81EA\u52A8\u4E3A\u5168\u5C40\u7BA1\u7406\u5458\uFF0C\u81F3\u5C11\u4FDD\u7559\u4E00\u4F4D\u3002":"The linked account is a global admin automatically. Keep at least one.","\u7ED1\u5B9A\u8D26\u53F7\uFF08\u5168\u5C40\u7BA1\u7406\u5458\uFF09":"Linked account (global admin)","\u7F3A\u5C11\u53EF\u7528\u4E8E\u5BA1\u6279\u7684\u5168\u5C40\u7BA1\u7406\u5458\u7535\u8BDD\u3002":"No global admin phone is available for approval.","\u7FA4 JID \u683C\u5F0F\u65E0\u6548\u3002":"Invalid group JID.",\u7FA4\u4F1A\u8BDD\u7B56\u7565:"Group session policy","\u7FA4\u5185 Session \u7ED1\u5B9A":"In-group session binding",\u7FA4\u5907\u6CE8\u540D:"Group display name",\u7FA4\u6388\u6743:"Group grants","\u8BBF\u95EE\u4E0E\u7FA4\u4F1A\u8BDD\u8BBE\u7F6E\u5DF2\u4FDD\u5B58\u3002":"Access and group session settings saved.","\u8BBF\u95EE\u6388\u6743\u4FDD\u5B58\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002":"Could not save the access grant. Try again later.","\u8BBF\u95EE\u6388\u6743\u6682\u4E0D\u53EF\u7528\u3002":"Access grant settings are currently unavailable.","\u8FD0\u7EF4\u9ED8\u8BA4\u6309\u53D1\u8A00\u4EBA\u62C6\u5206 Session\uFF0C\u907F\u514D\u540C\u7FA4\u591A\u4EBA\u4E92\u76F8\u6253\u65AD\uFF1B\u53EF\u9009\u6539\u56DE\u6574\u7FA4\u5171\u4EAB Session\u3002":"Ops defaults to one session per speaker so group members do not interrupt each other. You can switch back to one shared group session.","\uFF08\u7535\u8BDD\u672A\u89E3\u6790\uFF0C\u8BF7\u5148\u5728\u8054\u7CFB\u4EBA\u4E2D\u786E\u8BA4\uFF09":"(Phone unresolved \u2014 confirm it in contacts first)",\u67E5\u770B\u8BBF\u95EE\u6743\u9650\u8BF4\u660E:"View access permission details",\u5141\u8BB8\u6240\u6709\u7528\u6237:"Allow all users",\u4EC5\u767D\u540D\u5355\u7528\u6237:"Allowlisted users only",\u9ED8\u8BA4\u547D\u4EE4\u6743\u9650:"Default command permission",\u547D\u4EE4\u6743\u9650:"Command permission",\u53EF\u4EE5\u6267\u884C\u547D\u4EE4:"Can run commands",\u4E0D\u53EF\u4EE5\u6267\u884C\u547D\u4EE4:"Cannot run commands",\u767D\u540D\u5355\u7528\u6237:"Allowlisted users",\u67E5\u770B\u767D\u540D\u5355\u8BF4\u660E:"View allowlist details",\u547D\u4EE4\u6743\u9650\u4F8B\u5916:"Command permission exceptions","\u5F53\u524D\u6CA1\u6709\u767D\u540D\u5355\u7528\u6237\uFF0C\u4FDD\u5B58\u540E\u666E\u901A\u7528\u6237\u5C06\u65E0\u6CD5\u4F7F\u7528\u673A\u5668\u4EBA\u3002":"There are currently no allowlisted users. After saving, regular users will not be able to use the bot.",\u65B0\u589E\u7528\u6237:"Add user",\u5C1A\u672A\u6DFB\u52A0\u7528\u6237:"No users added",\u5F53\u524D\u6E20\u9053\u4E0D\u652F\u6301\u7FA4\u804A:"Group chat is not supported by this channel","\u539F\u6240\u6709\u8005\u6216\u626B\u7801\u63A5\u5165\u8005\u59CB\u7EC8\u53EF\u4EE5\u8BBF\u95EE\u5E76\u6267\u884C\u547D\u4EE4\uFF1B\u4EE5\u4E0B\u8BBE\u7F6E\u4EC5\u7EA6\u675F\u5176\u4ED6\u7528\u6237\u3002":"The original owner or QR-code operator can always access the bot and run commands; the settings below apply only to other users.","\u6B64\u533A\u57DF\u65E0\u9700\u914D\u7F6E\uFF0C\u4FDD\u5B58\u79C1\u804A\u8BBE\u7F6E\u65F6\u4F1A\u4FDD\u7559\u73B0\u6709\u7FA4\u804A\u7B56\u7565\u3002":"No setup is needed here. Saving direct-message settings keeps the existing group policy.","\u8BBF\u95EE\u8BBE\u7F6E\u5DF2\u4FDD\u5B58\u3002":"Access settings saved.","\u8BBF\u95EE\u8BBE\u7F6E\u6682\u4E0D\u53EF\u7528\u3002":"Access settings are currently unavailable.","\u8BBF\u95EE\u8BBE\u7F6E\u4FDD\u5B58\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002":"Could not save access settings. Try again later.","\u670D\u52A1\u6CA1\u6709\u8FD4\u56DE\u5DF2\u4FDD\u5B58\u7684\u8BBF\u95EE\u7B56\u7565\uFF0C\u8BF7\u5237\u65B0\u540E\u91CD\u8BD5\u3002":"The service did not return the saved access policy. Refresh and try again.","\u8BBF\u95EE\u7B56\u7565\u5C1A\u672A\u5C31\u7EEA\uFF0C\u8BF7\u8FD4\u56DE\u673A\u5668\u4EBA\u5217\u8868\u5237\u65B0\u540E\u91CD\u8BD5\u3002":"The access policy is not ready. Return to the bot list, refresh, and try again.","\u5F53\u524D\u6E20\u9053\u6682\u4E0D\u652F\u6301\u8BBF\u95EE\u8BBE\u7F6E\u3002":"Access settings are not supported by this channel yet.","\u7528\u6237\u6807\u8BC6\u65E0\u6548\u3002":"The user ID is invalid.","\u7528\u6237\u6807\u8BC6\u5FC5\u987B\u662F\u5B57\u7B26\u4E32\u3002":"The user ID must be a string.","\u7528\u6237\u6807\u8BC6\u4E0D\u80FD\u4E3A\u7A7A\u3001\u5305\u542B\u63A7\u5236\u5B57\u7B26\u6216\u8D85\u8FC7 256 \u4E2A\u5B57\u7B26\u3002":"The user ID cannot be empty, contain control characters, or exceed 256 characters.","\u7528\u6237\u6761\u76EE\u5FC5\u987B\u5305\u542B\u7528\u6237\u6807\u8BC6\u548C\u547D\u4EE4\u6743\u9650\u3002":"Each user entry must include a user ID and command permission.","\u547D\u4EE4\u6743\u9650\u5FC5\u987B\u662F\u5E03\u5C14\u503C\u3002":"Command permission must be a boolean.","\u8BBF\u95EE\u6A21\u5F0F\u53EA\u80FD\u662F open \u6216 allowlist\u3002":"Access mode must be open or allowlist.","\u5F00\u653E\u6A21\u5F0F\u8BBE\u7F6E\u5FC5\u987B\u5B8C\u6574\u3002":"Open-mode settings must be complete.","\u5F00\u653E\u6A21\u5F0F\u9ED8\u8BA4\u547D\u4EE4\u6743\u9650\u5FC5\u987B\u662F\u5E03\u5C14\u503C\u3002":"The open-mode default command permission must be a boolean.","\u5F00\u653E\u6A21\u5F0F\u547D\u4EE4\u6743\u9650\u8986\u76D6\u7528\u6237\u5FC5\u987B\u662F\u6570\u7EC4\u3002":"Open-mode command permission overrides must be an array.","\u5F00\u653E\u6A21\u5F0F\u547D\u4EE4\u6743\u9650\u8986\u76D6\u7528\u6237\u4E0D\u80FD\u5305\u542B\u91CD\u590D\u7684\u7528\u6237\u6807\u8BC6\u3002":"Open-mode command permission overrides cannot contain duplicate user IDs.","\u767D\u540D\u5355\u6A21\u5F0F\u8BBE\u7F6E\u5FC5\u987B\u5B8C\u6574\u3002":"Allowlist-mode settings must be complete.","\u767D\u540D\u5355\u6A21\u5F0F\u7528\u6237\u5FC5\u987B\u662F\u6570\u7EC4\u3002":"Allowlist-mode users must be an array.","\u767D\u540D\u5355\u6A21\u5F0F\u7528\u6237\u4E0D\u80FD\u5305\u542B\u91CD\u590D\u7684\u7528\u6237\u6807\u8BC6\u3002":"Allowlist-mode users cannot contain duplicate user IDs.","\u8BBF\u95EE\u573A\u666F\u8BBE\u7F6E\u5FC5\u987B\u540C\u65F6\u5305\u542B\u6A21\u5F0F\u3001\u5F00\u653E\u6A21\u5F0F\u8BBE\u7F6E\u548C\u767D\u540D\u5355\u6A21\u5F0F\u8BBE\u7F6E\u3002":"Each access context must include its mode, open-mode settings, and allowlist-mode settings.","\u8BF7\u540C\u65F6\u63D0\u4EA4\u5B8C\u6574\u7684\u79C1\u804A\u548C\u7FA4\u804A\u8BBF\u95EE\u8BBE\u7F6E\u3002":"Submit complete direct-message and group access settings together.","\u586B\u5199\u5FAE\u4FE1\u7528\u6237 ID":"Enter a WeChat user ID","\u98DE\u4E66 Open ID":"Feishu Open ID","\u7FA4\u6210\u5458 Open ID":"Group member Open ID","\u9489\u9489\u7528\u6237 ID":"DingTalk user ID","\u586B\u5199 senderStaffId \u6216 senderId":"Enter senderStaffId or senderId","\u7FA4\u6210\u5458\u7528\u6237 ID":"Group member user ID","\u4F01\u4E1A\u5FAE\u4FE1\u7528\u6237 ID":"WeCom user ID","\u586B\u5199 userid":"Enter userid","\u586B\u5199 member_openid":"Enter member_openid","QQ User Open ID":"QQ User Open ID","\u7FA4\u6210\u5458 User ID":"Group member User ID","\u586B\u5199\u6570\u5B57 User ID":"Enter a numeric user ID","WhatsApp \u7535\u8BDD\u53F7\u7801\u6216 JID":"WhatsApp phone number or JID","\u7FA4\u6210\u5458\u7535\u8BDD\u53F7\u7801\u6216 JID":"Group member phone number or JID","8613800000000 \u6216\u5B8C\u6574 JID":"8613800000000 or a full JID","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",\u4E0A\u4E0B\u6587\u589E\u5F3A\u8303\u56F4:"Context enhancement scope",\u542F\u7528\u8303\u56F4:"Enable in",\u542F\u7528:"Enabled","\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",\u67E5\u770B\u7FA4\u804A\u6765\u6E90\u5B57\u6BB5\u8BF4\u660E:"View group source field details",\u67E5\u770B\u79C1\u804A\u6765\u6E90\u5B57\u6BB5\u8BF4\u660E:"View direct 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",\u67E5\u770B\u7FA4\u804A\u53D1\u9001\u8005\u6635\u79F0\u5B57\u6BB5\u8BF4\u660E:"View group sender name field details",\u67E5\u770B\u79C1\u804A\u53D1\u9001\u8005\u6635\u79F0\u5B57\u6BB5\u8BF4\u660E:"View direct 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.",\u4F1A\u8BDD\u6807\u9898:"Conversation title",\u67E5\u770B\u7FA4\u804A\u4F1A\u8BDD\u6807\u9898\u5B57\u6BB5\u8BF4\u660E:"View group conversation title field details",\u67E5\u770B\u79C1\u804A\u4F1A\u8BDD\u6807\u9898\u5B57\u6BB5\u8BF4\u660E:"View direct conversation title field details","\u8BE5\u5B57\u6BB5\u4E0D\u662F\u6BCF\u4E2A\u6E20\u9053\u90FD\u80FD\u63D0\u4F9B\u3002\u9489\u9489\u7FA4\u804A\u4F1A\u5E26\u4E0A\u7FA4\u540D\u3002\u5F53\u524D\u6D88\u606F\u6CA1\u6709\u4F1A\u8BDD\u6807\u9898\u65F6\uFF0C\u5373\u4F7F\u5DF2\u9009\u62E9\u8BE5\u5B57\u6BB5\uFF0C \u4E2D\u4E5F\u4F1A\u7701\u7565 conversationTitle\u3002":"This field is not available on every channel. DingTalk group chats include the group name. If the current message has no conversation title, omits conversationTitle even when the field is selected.",\u4F1A\u8BDD\u6807\u8BC6:"Chat ID",\u67E5\u770B\u7FA4\u804A\u4F1A\u8BDD\u6807\u8BC6\u5B57\u6BB5\u8BF4\u660E:"View group chat ID field details",\u67E5\u770B\u79C1\u804A\u4F1A\u8BDD\u6807\u8BC6\u5B57\u6BB5\u8BF4\u660E:"View direct chat ID field details","\u8BE5\u5B57\u6BB5\u4E0D\u662F\u6BCF\u4E2A\u6E20\u9053\u90FD\u80FD\u63D0\u4F9B\u3002\u4F1A\u8BDD\u6807\u8BC6\u7528\u4E8E\u533A\u5206\u4E0D\u540C\u7684\u7FA4\u7EC4\u6216\u79C1\u804A\uFF0C\u98DE\u4E66\u7FA4\u804A\u4F1A\u5E26\u4E0A\u7FA4 ID\u3002\u5F53\u524D\u6D88\u606F\u6CA1\u6709\u4F1A\u8BDD\u6807\u8BC6\u65F6\uFF0C\u5373\u4F7F\u5DF2\u9009\u62E9\u8BE5\u5B57\u6BB5\uFF0C \u4E2D\u4E5F\u4F1A\u7701\u7565 chatId\u3002":"This field is not available on every channel. The chat ID distinguishes different groups or direct chats, and Feishu group chats include the group ID. If the current message has no chat ID, omits chatId even when the field is selected.",\u8BDD\u9898\u6807\u8BC6:"Topic ID",\u67E5\u770B\u7FA4\u804A\u8BDD\u9898\u6807\u8BC6\u5B57\u6BB5\u8BF4\u660E:"View group topic ID field details",\u67E5\u770B\u79C1\u804A\u8BDD\u9898\u6807\u8BC6\u5B57\u6BB5\u8BF4\u660E:"View direct topic ID field details","\u8BE5\u5B57\u6BB5\u4E0D\u662F\u6BCF\u4E2A\u6E20\u9053\u90FD\u80FD\u63D0\u4F9B\u3002\u98DE\u4E66\u8BDD\u9898\u7FA4\u7684\u6D88\u606F\u4F1A\u5E26\u4E0A\u8BDD\u9898 ID\uFF0C\u7528\u4E8E\u533A\u5206\u540C\u4E00\u7FA4\u7EC4\u5185\u7684\u4E0D\u540C\u8BDD\u9898\uFF1B\u5F53\u524D\u6D88\u606F\u4E0D\u5728\u8BDD\u9898\u4E2D\u65F6\uFF0C\u5373\u4F7F\u5DF2\u9009\u62E9\u8BE5\u5B57\u6BB5\uFF0C \u4E2D\u4E5F\u4F1A\u7701\u7565 threadId\u3002":"This field is not available on every channel. Messages in a Feishu topic chat carry the topic ID, which distinguishes different topics inside the same group. If the current message is not inside a topic, omits threadId 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",\u67E5\u770B\u7FA4\u804A\u589E\u5F3A\u63D0\u793A\u8BCD\u4F7F\u7528\u8BF4\u660E:"View group guidance instructions",\u67E5\u770B\u79C1\u804A\u589E\u5F3A\u63D0\u793A\u8BCD\u4F7F\u7528\u8BF4\u660E:"View direct 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 KGe(o,this.#e)}};import{randomUUID as bZ}from"node:crypto";var QG=new Set(["starting","qr_ready","polling","slow_down","domain_switched","saving"]),zGe=new Set(["polling","slow_down","domain_switched"]),Va=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 mZ(n){return["access_denied","expired_token","abort"].includes(n?.code)?n.code:"registration_failed"}function yG(n){let t=mZ(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 VGe(n){let t=Number(n);if(!Number.isFinite(t)||t<=0)throw new TypeError("registerApp onQRCodeReady returned an invalid expireIn");return t}function WGe(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 xg=class{#e;#A;#t;#r;#I;#o=0;#g=null;#i;constructor({registerApp:t,onCredentials:o,now:a=Date.now,setTimeout:e=globalThis.setTimeout,clearTimeout:i=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 a!="function"||typeof e!="function"||typeof i!="function")throw new TypeError("RegistrationManager clock dependencies must be functions");this.#e=t,this.#A=o,this.#t=a,this.#r=e,this.#I=i,this.#i=this.#s(null,Va.IDLE)}start(t={}){if(t===null||typeof t!="object"||Array.isArray(t))throw new TypeError("Registration options must be an object");this.#f();let o={id:++this.#o,controller:new AbortController,qrCodeUrl:null,expiresAt:null,pollIntervalSeconds:null,expiryTimer:null};this.#g=o,this.#i=this.#s(o,Va.STARTING);let a={...t,signal:o.controller.signal,onQRCodeReady:i=>this.#c(o,i),onStatusChange:i=>this.#d(o,i)};return Promise.resolve().then(()=>this.#e(a)).then(i=>this.#n(o,i),i=>this.#p(o,i)),this.status()}status(){this.#E();let t={...this.#i};t.error&&(t.error={...t.error});let o=this.#g;return o&&o.expiresAt!==null&&QG.has(t.state)&&(t.remainingSeconds=Math.max(0,Math.ceil((o.expiresAt-this.#t())/1e3))),t}cancel(){let t=this.#g;return t?(this.#C(t,Va.CANCELLED,{error:{code:"abort",message:"Registration was cancelled."}}),t.controller.abort(),this.status()):this.status()}#a(t){return this.#g===t}#s(t,o,a={}){let e={state:o,attempt:t?.id??this.#o,updatedAt:this.#t(),...a};return t?.qrCodeUrl&&QG.has(o)&&(e.qrCodeUrl=t.qrCodeUrl,e.expiresAt=t.expiresAt),t?.pollIntervalSeconds!==null&&QG.has(o)&&(e.pollIntervalSeconds=t.pollIntervalSeconds),e}#l(t,o,a={}){this.#a(t)&&(this.#i=this.#s(t,o,a))}#c(t,o){if(!this.#a(t))return;if(typeof o?.url!="string"||!o.url)throw new TypeError("registerApp onQRCodeReady returned an invalid URL");let a=VGe(o.expireIn);t.qrCodeUrl=o.url,t.expiresAt=this.#t()+a*1e3,this.#B(t),t.expiryTimer=this.#r(()=>this.#u(t),a*1e3),t.expiryTimer?.unref?.(),this.#l(t,Va.QR_READY)}#d(t,o){!this.#a(t)||!zGe.has(o?.status)||(o.status===Va.SLOW_DOWN&&Number.isFinite(Number(o.interval))&&(t.pollIntervalSeconds=Number(o.interval)),this.#l(t,o.status))}async#n(t,o){if(!this.#a(t))return;let a=o?.client_id,e=o?.client_secret;if(typeof a!="string"||!a||typeof e!="string"||!e){this.#C(t,Va.ERROR,{error:{code:"invalid_credentials",message:"Feishu registration returned invalid credentials."}});return}let i;try{i=WGe(o.user_info)}catch{this.#C(t,Va.ERROR,{error:{code:"invalid_credentials",message:"Feishu registration returned invalid credentials."}});return}this.#B(t),t.qrCodeUrl=null,t.expiresAt=null,t.pollIntervalSeconds=null,this.#l(t,Va.SAVING);try{await this.#A({client_id:a,client_secret:e,user_info:i})}catch{this.#a(t)&&this.#C(t,Va.ERROR,{error:{code:"credentials_callback_failed",message:"Unable to store the Feishu credentials."}});return}this.#a(t)&&this.#C(t,Va.SUCCEEDED)}#p(t,o){if(!this.#a(t))return;let a=mZ(o);if(a==="expired_token"){this.#C(t,Va.EXPIRED,{error:yG(o)});return}if(a==="abort"){this.#C(t,Va.CANCELLED,{error:yG(o)});return}this.#C(t,Va.ERROR,{error:yG(o)})}#E(){let t=this.#g;t&&t.expiresAt!==null&&this.#t()>=t.expiresAt&&this.#u(t)}#u(t){this.#a(t)&&(this.#C(t,Va.EXPIRED,{error:{code:"expired_token",message:"The registration QR code expired."}}),t.controller.abort())}#C(t,o,a={}){this.#a(t)&&(this.#B(t),this.#i=this.#s(t,o,a),this.#g=null)}#B(t){t.expiryTimer!==null&&(this.#I(t.expiryTimer),t.expiryTimer=null)}#f(){let t=this.#g;t&&(this.#B(t),this.#g=null,t.controller.abort())}};var ZGe="card.action.trigger",XGe="im:message:readonly",$Ge="im:resource",tB="callback_repair";function eFe(n){return n==="lark"?"accounts.larksuite.com":"accounts.feishu.cn"}function AFe(n){return n==="lark"?"open.larksuite.com":"open.feishu.cn"}function mG(n,t,o="feishu",a="Feishu app update"){let e;try{e=new URL(n)}catch{throw new Error(`${a} returned an invalid verification URL`)}let i=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(!i||e.protocol!=="https:"||e.hostname!==AFe(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(`${a} returned an unsafe verification URL`);return e.toString()}function tFe(n,t,o="feishu"){return mG(n,t,o,"Feishu callback repair")}var iw=class{#e;#A;#t;constructor({registerApp:t,onCredentials:o,appId:a,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 a!="string"||!a.trim())throw new TypeError("appId is required");if(e!=="feishu"&&e!=="lark")throw new TypeError("domain is invalid");this.#A=a.trim(),this.#t=e,this.#e=new xg({registerApp:i=>t({...i,onQRCodeReady:A=>{tFe(A?.url,this.#A,this.#t),i.onQRCodeReady(A)}}),onCredentials:o})}start(){return this.#e.start({source:"deepseek-harness-card-action-repair",domain:eFe(this.#t),appId:this.#A,addons:{preset:!1,scopes:{tenant:[XGe,$Ge,...XS]},callbacks:{items:[ZGe]}}})}status(){return this.#e.status()}cancel(){return this.#e.cancel()}};var rFe="im:message.group_msg",ow="group_message_permission";function iFe(n){return n==="lark"?"accounts.larksuite.com":"accounts.feishu.cn"}function aFe(n,t,o="feishu"){return mG(n,t,o,"Feishu group message permission update")}var aw=class{#e;#A;#t;constructor({registerApp:t,onCredentials:o,appId:a,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 a!="string"||!a.trim())throw new TypeError("appId is required");if(e!=="feishu"&&e!=="lark")throw new TypeError("domain is invalid");this.#A=a.trim(),this.#t=e,this.#e=new xg({registerApp:i=>t({...i,onQRCodeReady:A=>{aFe(A?.url,this.#A,this.#t),i.onQRCodeReady(A)}}),onCredentials:o})}start(){return this.#e.start({source:"deepseek-harness-group-message-permission",domain:iFe(this.#t),appId:this.#A,addons:{preset:!1,scopes:{tenant:[rFe]}}})}status(){return this.#e.status()}cancel(){return this.#e.cancel()}};var SZ=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",...XS]);var SG=new Set(["starting","qr_ready","polling","slow_down","domain_switched"]),nw=new Set([...SG,"saving"]),wZ=new Set([tB,ow]),DZ="*",oFe=12e4,nFe=6e5;function MZ(){return{ready:!1,feishuLongConnectionState:"idle",harnessReachable:!1}}function rB(n){return n?n.status:MZ()}function iB(n){return n.ready===!0&&n.feishuLongConnectionState==="connected"&&n.harnessReachable===!0}function _Z(n){return n.length>12?`${n.slice(0,8)}\u2022\u2022\u2022\u2022${n.slice(-4)}`:"cli_\u2022\u2022\u2022\u2022"}function sFe(n){return{name:n.botName,appIdMasked:_Z(n.appId),activated:n.activated,domain:n.domain}}function gFe({connected:n,error:t,connection:o}){return n?"connected":t||o.feishuLongConnectionState==="failed"?"error":"disconnected"}function cFe(){return`bot_${bZ().replaceAll("-","")}`}function IFe(){return`reg_${bZ().replaceAll("-","")}`}function OZ(n){return`DSH_FEISHU_APP_SECRET_${n.slice(4).toUpperCase()}`}function sw(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:Bo(n.groupResponseMode),groupMessagePermissionGranted:n.groupMessagePermissionGranted===!0,deletionPending:n.deletionPending===!0,connectedAt:n.connectedAt??null,createdAt:n.createdAt??null})}function gw(n){return typeof n=="string"&&n.trim()?n.trim():null}var aB=class{#e;#A;#t;#r;#I;#o;#g;#i;#a=new Map;#s=new Map;#l=new Map;#c=new Map;#d=new Map;#n=null;#p=Promise.resolve();#E=new Map;#u=1;#C;#B=!1;constructor({registerApp:t,verifyApp:o,credentials:a,configStore:e,createRuntime:i,deleteState:A=async()=>{},createBotId:r=cFe,createRegistrationId:s=IFe,callbackProbeTimeoutMs:g=oFe}){if(typeof t!="function")throw new Error("registerApp is required");if(typeof o!="function")throw new Error("verifyApp is required");if(!a)throw new Error("credentials service is required");if(!e||typeof e.list!="function")throw new Error("multi-bot config store is required");if(typeof i!="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>nFe)throw new TypeError("callbackProbeTimeoutMs must be between 1 and 600000ms");this.#e=t,this.#A=o,this.#t=a,this.#r=e,this.#I=i,this.#o=A,this.#g=r,this.#i=s,this.#C=g}async initialize(){if(this.#B)return this.status();let t=this.#r.list(),o=!1;return await Promise.allSettled(t.map(a=>this.#_(a.id,async()=>{let e=rB(this.#a.get(a.id));if(iB(e)||e.feishuLongConnectionState==="connecting"||e.feishuLongConnectionState==="reconnecting")return;if(o=!0,a.deletionPending){this.#s.set(a.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 i;try{i=await this.#t.resolve(a.secretRef)}catch{this.#s.set(a.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(!i?.value){this.#s.set(a.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.#h(a,i.value),this.#s.delete(a.id)}catch{this.#s.set(a.id,{code:"connection_failed",message:"\u673A\u5668\u4EBA\u6682\u65F6\u65E0\u6CD5\u8FDE\u63A5\u98DE\u4E66\uFF0C\u8BF7\u91CD\u8BD5\u3002"})}}))),o&&this.#R(),this.status()}startRegistration(){this.#N();let t=this.#i();if(typeof t!="string"||!/^[A-Za-z0-9_-]{1,128}$/.test(t)||this.#l.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 xg({registerApp:this.#e,onCredentials:a=>this.#P(()=>this.#D(o,a))}),this.#l.set(t,o),this.#n=t,this.#G(),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:[...SZ]},events:{items:{tenant:["im.message.receive_v1"]}},callbacks:{items:["card.action.trigger"]}}}),this.#R(),this.registrationStatus(t)}startCallbackRepair(t,{actorOpenId:o,chatId:a}={}){this.#N();let e=this.#T(t);if(e.deletionPending)throw new Error("Cannot repair a Feishu bot pending deletion");let i=this.#c.get(t),A=i?this.#l.get(i):null;if(A&&nw.has(A.manager.status().state)){if(A.operation!==tB)throw new Error("Another Feishu app update is already active for this bot");return this.registrationStatus(A.id)}this.#c.delete(t);let r=this.#i();if(typeof r!="string"||!/^[A-Za-z0-9_-]{1,128}$/.test(r)||this.#l.has(r))throw new Error("Registration id generator returned an invalid or duplicate id");let s={id:r,operation:tB,manager:null,botId:t,createdNew:!1,cancelled:!1,remoteCommitted:!1,processing:null,publicError:null,stage:"authorizing",target:structuredClone(e),targetFingerprint:sw(e),initiator:{actorOpenId:gw(o),chatId:gw(a)}};return s.manager=new iw({registerApp:this.#e,appId:e.appId,domain:e.domain,onCredentials:g=>{s.remoteCommitted=!0;let I=this.#m(s,g).finally(()=>{s.processing===I&&(s.processing=null)});return s.processing=I,I}}),this.#l.set(r,s),this.#c.set(t,r),this.#n=r,this.#G(),s.manager.start(),this.#R(),this.registrationStatus(r)}startGroupMessagePermission(t){this.#N();let o=this.#T(t);if(o.deletionPending)throw new Error("Cannot update permissions for a Feishu bot pending deletion");let a=this.#c.get(t),e=a?this.#l.get(a):null;if(e&&nw.has(e.manager.status().state)){if(e.operation!==ow)throw new Error("Another Feishu app update is already active for this bot");return this.registrationStatus(e.id)}this.#c.delete(t);let i=this.#i();if(typeof i!="string"||!/^[A-Za-z0-9_-]{1,128}$/.test(i)||this.#l.has(i))throw new Error("Registration id generator returned an invalid or duplicate id");let A={id:i,operation:ow,manager:null,botId:t,createdNew:!1,cancelled:!1,remoteCommitted:!1,processing:null,publicError:null,stage:"authorizing",target:structuredClone(o),targetFingerprint:sw(o),initiator:{actorOpenId:null,chatId:null}};return A.manager=new aw({registerApp:this.#e,appId:o.appId,domain:o.domain,onCredentials:r=>{A.remoteCommitted=!0;let g=this.#w(A,r).finally(()=>{A.processing===g&&(A.processing=null)});return A.processing=g,g}}),this.#l.set(i,A),this.#c.set(t,i),this.#n=i,this.#G(),A.manager.start(),this.#R(),this.registrationStatus(i)}hasRegistration(t){return this.#l.has(t)}registrationStatus(t){let o=this.#l.get(t);return o?this.#f({registration:o,selectedBotId:o.botId}):null}async cancelRegistration(t=this.#n){let o=this.#l.get(t);if(!o)return this.status();let a=o.manager.status().state;return wZ.has(o.operation)&&a==="saving"?this.registrationStatus(t):nw.has(a)?(o.cancelled=!0,o.manager.cancel(),await this.#P(async()=>{o.createdNew&&o.botId&&this.#d.get(o.botId)===o.id&&this.#r.getBot(o.botId)&&await this.#_(o.botId,()=>this.#O(o.botId))}),this.#R(),this.registrationStatus(t)??this.status()):this.registrationStatus(t)}status(t){return this.#f({registration:this.#l.get(this.#n)??null,selectedBotId:t})}async bindCredentials({appId:t,appSecret:o,domain:a="feishu"}={}){this.#N();let e=typeof t=="string"?t.trim():"",i=typeof o=="string"?o.trim():"",A=a==="lark"?"lark":"feishu";if(!e||!i)throw new TypeError("Feishu App ID and App Secret are required");return this.#P(async()=>{this.#N();let r=await this.#A({appId:e,appSecret:i,domain:A});this.#N();let s=this.#r.list().find(f=>f.appId===e),g=s?.id??this.#g();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??OZ(g),I=await this.#t.resolve(c).catch(()=>{}),d={...s,id:g,appId:e,secretRef:c,ownerOpenIds:s?.ownerOpenIds?.length?s.ownerOpenIds:[DZ],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,i);let B;try{B=await this.#r.saveBot(d)}catch(f){throw await this.#S(c,I),f}return await this.#_(g,async()=>{try{await this.#h(B,i),this.#s.delete(g)}catch{this.#s.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.#R(),this.status(g)})}async reconnectBot(t){return this.#N(),this.#_(t,async()=>{let o=this.#T(t);if(o.deletionPending)return this.#s.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(iB(rB(this.#a.get(t))))return this.status(t);let a;try{a=await this.#t.resolve(o.secretRef)}catch{a=null}if(!a?.value)return this.#s.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.#R(),this.status(t);try{await this.#h(o,a.value),this.#s.delete(t)}catch{this.#s.set(t,{code:"connection_failed",message:"\u673A\u5668\u4EBA\u6682\u65F6\u65E0\u6CD5\u8FDE\u63A5\u98DE\u4E66\uFF0C\u8BF7\u91CD\u8BD5\u3002"})}return this.#R(),this.status(t)})}async sendConnectionTest(t){return this.#N(),this.#_(t,async()=>{let o=this.#T(t),a=this.#a.get(t);if(!iB(rB(a))||typeof a.sendConnectionTest!="function"){let e=new Error("\u98DE\u4E66\u673A\u5668\u4EBA\u5C1A\u672A\u8FDE\u63A5");throw e.code="test-target-unavailable",e}return a.sendConnectionTest(Ki(`${o.botName}\uFF08${_Z(o.appId)}\uFF09`,"\u98DE\u4E66\u673A\u5668\u4EBA"))})}async sendProactiveText(t,o,a,e={}){return this.#N(),this.#_(t,async()=>{this.#T(t);let i=this.#a.get(t);if(!iB(rB(i))||typeof i.sendProactiveText!="function"){let A=new Error("\u98DE\u4E66\u673A\u5668\u4EBA\u5C1A\u672A\u8FDE\u63A5");throw A.code="bot-not-connected",A}return i.sendProactiveText(o,a,e)})}async disconnectBot(t){return this.#N(),this.#_(t,async()=>(this.#T(t),await this.#M(t),this.#s.delete(t),this.#R(),this.status(t)))}async updateGroupResponseMode(t,o){if(this.#N(),!YS(o))throw new TypeError("Invalid Feishu group response mode");return this.#P(()=>this.#_(t,async()=>{let a=this.#T(t);if(o==="all"&&a.groupMessagePermissionGranted!==!0){let i=new Error("Authorize im:message.group_msg before enabling all group messages");throw i.code="group_message_permission_required",i}let e=await this.#r.saveBot({...a,groupResponseMode:o});return this.#a.get(t)?.setGroupResponseMode?.(e.groupResponseMode),this.#R(),this.status(t)}))}async deleteBot(t){return this.#N(),this.#P(()=>this.#_(t,async()=>(this.#T(t),await this.#O(t),this.#R(),this.status())))}async reconnect(){let t=this.#r.list()[0];return t?this.reconnectBot(t.id):this.status()}async disconnect(){let t=this.#r.list()[0];return t?this.deleteBot(t.id):this.status()}async close(){if(this.#B)return;this.#B=!0;let t=[];for(let o of this.#l.values()){let a=o.manager.status().state;wZ.has(o.operation)&&a==="saving"?(o.manager.cancel(),o.processing&&t.push(o.processing)):nw.has(a)&&(o.cancelled=!0,o.manager.cancel())}await this.#p,await Promise.allSettled([...this.#E.values()]),await Promise.allSettled([...this.#a.keys()].map(o=>this.#M(o))),await Promise.allSettled(t),await this.#p,await Promise.allSettled([...this.#E.values()]),await Promise.allSettled([...this.#a.keys()].map(o=>this.#M(o)))}#f({registration:t,selectedBotId:o}={}){let a=this.#r.list().map(I=>{let d=rB(this.#a.get(I.id)),B=iB(d),f=this.#s.get(I.id)??null;return{botId:I.id,phase:gFe({connected:B,error:f,connection:d}),connected:B,configured:!0,groupResponseMode:Bo(I.groupResponseMode),groupMessagePermissionGranted:I.groupMessagePermissionGranted===!0,bot:sFe(I),connection:d,lastMessageError:ii(d.lastMessageError),error:f}}),e=t?this.#y(t):{state:"idle",attempt:0,updatedAt:Date.now()},i=SG.has(e.state),A=e.state==="saving",r=!!t&&(i||A),s=a.find(I=>I.botId===o)??(r?null:a[0]??null),g=a.some(I=>I.connected),c=s?.phase??"unconfigured";return i?c="registering":A?c="connecting":e.state==="error"&&!s&&(c="error"),{schemaVersion:2,revision:this.#u,phase:c,connected:s?.connected??!1,configured:a.length>0,bot:s?.bot??null,connection:s?.connection??MZ(),error:s?.error??e.error??null,registration:e,bots:a,totals:{configured:a.length,connected:a.filter(I=>I.connected).length},anyConnected:g}}#y(t){let o=t.manager.status();return{...o,attempt:t.id,...t.botId?{botId:t.botId}:{},...t.operation?{operation:t.operation}:{},...t.stage?{stage:t.stage}:{},...o.state==="error"&&t.publicError?{error:{...t.publicError}}:{}}}async#w(t,o){let a=o.client_id,e=o.client_secret,i=gw(o.user_info?.open_id),A=o.user_info?.tenant_brand,r=t.target;if(t.cancelled)throw this.#Q(t,"abort","Group message permission update was cancelled before local activation.");if(a!==r.appId)throw this.#Q(t,"repair_app_mismatch","Feishu returned credentials for a different app.");if(!i)throw this.#Q(t,"repair_owner_missing","Feishu returned no permission operator identity.");if(A!==void 0&&A!==r.domain)throw this.#Q(t,"repair_domain_mismatch","Feishu returned credentials for a different account domain.");if(!r.ownerOpenIds.includes(DZ)&&!r.ownerOpenIds.includes(i))throw this.#Q(t,"repair_owner_mismatch","The Feishu permission operator is not an owner of this configured bot.");t.stage="verifying_identity";let s;try{s=await this.#A({appId:a,appSecret:e,domain:r.domain})}catch(g){throw this.#Q(t,"repair_credentials_invalid","Feishu could not verify the updated app credentials.",g)}if(r.botOpenId&&s?.openId!==r.botOpenId)throw this.#Q(t,"repair_bot_mismatch","The updated Feishu app belongs to a different bot identity.");await this.#P(()=>this.#_(t.botId,async()=>{let g=this.#r.getBot(t.botId);if(!g||g.deletionPending||sw(g)!==t.targetFingerprint)throw this.#Q(t,"repair_target_changed","The Feishu bot changed while its permission update was in progress.");let c;try{c=await this.#t.resolve(g.secretRef)}catch(d){throw this.#Q(t,"credential_update_failed","Unable to read the current Feishu credential.",d)}if(c?.value!==e){t.stage="persisting_secret";try{await this.#t.set(g.secretRef,e)}catch(B){if((await this.#t.resolve(g.secretRef).catch(()=>null))?.value!==e)throw this.#Q(t,"credential_update_failed","Unable to store the updated Feishu credential.",B)}if((await this.#t.resolve(g.secretRef).catch(()=>null))?.value!==e)throw this.#Q(t,"credential_state_unknown","The updated Feishu credential could not be confirmed after writing.")}t.stage="enabling_all_messages";let I;try{I=await this.#r.saveBot({...g,groupMessagePermissionGranted:!0,groupResponseMode:"all"})}catch(d){throw this.#Q(t,"group_message_permission_save_failed","The permission was accepted, but all-message mode could not be saved.",d)}t.stage="restarting";try{await this.#h(I,e)}catch(d){throw this.#s.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.#R(),this.#Q(t,"group_message_permission_connection_failed","The permission was accepted, but the Feishu runtime could not restart.",d)}this.#s.delete(t.botId),t.stage="verified",t.publicError=null,this.#R()}))}async#m(t,o){let a=o.client_id,e=o.client_secret,i=gw(o.user_info?.open_id),A=o.user_info?.tenant_brand,r=t.target;if(t.cancelled)throw this.#Q(t,"abort","Callback repair was cancelled before local activation.");if(a!==r.appId)throw this.#Q(t,"repair_app_mismatch","Feishu returned credentials for a different app.");if(!i)throw this.#Q(t,"repair_owner_missing","Feishu returned no repair operator identity.");if(A!==void 0&&A!==r.domain)throw this.#Q(t,"repair_domain_mismatch","Feishu returned credentials for a different account domain.");t.stage="verifying_identity";let s;try{s=await this.#A({appId:a,appSecret:e,domain:r.domain})}catch(c){throw this.#Q(t,"repair_credentials_invalid","Feishu could not verify the repaired app credentials.",c)}if(r.botOpenId&&s?.openId!==r.botOpenId)throw this.#Q(t,"repair_bot_mismatch","The repaired Feishu app belongs to a different bot identity.");let g=await this.#P(()=>this.#_(t.botId,async()=>{let c=this.#r.getBot(t.botId);if(!c||c.deletionPending||sw(c)!==t.targetFingerprint)throw this.#Q(t,"repair_target_changed","The Feishu bot changed while its callback repair was in progress.");let I;try{I=await this.#t.resolve(c.secretRef)}catch(f){throw this.#Q(t,"credential_update_failed","Unable to read the current Feishu credential.",f)}if(I?.value!==e){t.stage="persisting_secret";try{await this.#t.set(c.secretRef,e)}catch(Q){if((await this.#t.resolve(c.secretRef).catch(()=>null))?.value!==e)throw this.#Q(t,"credential_update_failed","Unable to store the repaired Feishu credential.",Q)}if((await this.#t.resolve(c.secretRef).catch(()=>null))?.value!==e)throw this.#Q(t,"credential_state_unknown","The repaired Feishu credential could not be confirmed after writing.")}let B;t.stage="restarting";try{await this.#h(c,e),B=this.#a.get(t.botId)}catch(f){throw this.#s.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.#R(),this.#Q(t,"repair_connection_failed","The repaired Feishu runtime could not be started.",f)}if(!B)throw this.#Q(t,"repair_connection_failed","The repaired Feishu runtime is unavailable.");return this.#s.delete(t.botId),this.#R(),B}));if(typeof g.beginCardActionProbe!="function")throw this.#Q(t,"card_action_probe_unavailable","The Feishu runtime cannot verify card callbacks.");t.stage="awaiting_callback";try{if((await g.beginCardActionProbe({expectedOperatorOpenId:t.initiator.actorOpenId??i,timeoutMs:this.#C,...t.initiator.chatId?{chatId:t.initiator.chatId}:{}}))?.verified!==!0){let I=new Error("Feishu runtime returned no callback proof");throw I.code="card_action_probe_failed",I}}catch(c){let I=c?.code==="card_action_probe_timeout"?"card_action_probe_timeout":c?.code==="card_action_probe_unavailable"?"card_action_probe_unavailable":c?.code==="card_action_probe_send_failed"?"card_action_probe_send_failed":"card_action_probe_failed";throw this.#Q(t,I,I==="card_action_probe_timeout"?"Timed out waiting for the Feishu callback verification button.":"The Feishu card callback probe failed.",c)}t.stage="verified",t.publicError=null,this.#R()}#Q(t,o,a,e){t.publicError={code:o,message:a};let i=new Error(a,e?{cause:e}:void 0);return i.code=o,i}async#D(t,o){if(t.cancelled)throw new Error("Registration was cancelled");let a=o.client_id,e=o.client_secret,i=o.user_info?.open_id,A=o.user_info?.tenant_brand==="lark"?"lark":"feishu";if(!i)throw new Error("Feishu registration returned no owner open_id");let r=await this.#A({appId:a,appSecret:e,domain:A});if(t.cancelled)throw new Error("Registration was cancelled");let s=this.#r.list().find(Q=>Q.appId===a),g=s?.id??this.#g();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??OZ(g),I=this.#d.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:a,secretRef:c,ownerOpenIds:[...new Set([...s?.ownerOpenIds??[],i])],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.#d.set(g,t.id)}catch(Q){try{await this.#S(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.#_(g,()=>this.#O(g)):(await this.#r.saveBot(s),await this.#S(c,d),I?this.#d.set(g,I):this.#d.delete(g)),new Error("Registration was cancelled");let f=!1;try{if(await this.#_(g,()=>this.#h(B,e)),t.cancelled)throw t.createdNew?await this.#_(g,()=>this.#O(g)):(await this.#r.saveBot(s),await this.#S(c,d),I?this.#d.set(g,I):this.#d.delete(g),d?.value&&!s.deletionPending?await this.#_(g,()=>this.#h(s,d.value)):await this.#_(g,()=>this.#M(g))),f=!0,new Error("Registration was cancelled");this.#s.delete(g),this.#R()}catch(Q){if(t.cancelled)throw!f&&t.createdNew&&this.#r.getBot(g)?await this.#_(g,()=>this.#O(g)):!f&&s&&(await this.#r.saveBot(s),await this.#S(c,d),I?this.#d.set(g,I):this.#d.delete(g),!this.#B&&d?.value&&!s.deletionPending?await this.#_(g,()=>this.#h(s,d.value)):await this.#_(g,()=>this.#M(g))),this.#R(),Q;if(s&&d?.value)try{throw await this.#r.saveBot(s),await this.#S(c,d),I?this.#d.set(g,I):this.#d.delete(g),s.deletionPending?(await this.#_(g,()=>this.#M(g)),this.#s.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.#_(g,()=>this.#h(s,d.value)),this.#s.delete(g)),this.#R(),Q}catch(y){throw y===Q?Q:(this.#s.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.#R(),new Error("Unable to restore the previous Feishu bot connection.",{cause:y}))}throw this.#s.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.#R(),Q}}async#h(t,o){await this.#M(t.id);let a=await this.#I({botId:t.id,config:t,appSecret:o,repair:this.#k(t.id)});this.#a.set(t.id,a);try{await a.start()}catch(e){throw this.#a.get(t.id)===a&&this.#a.delete(t.id),await a.stop({preserveError:!0}).catch(()=>{}),e}}#k(t){let o=a=>{let e=this.#l.get(a);return e?.operation===tB&&e.botId===t?e:null};return Object.freeze({start:({actorOpenId:a,chatId:e}={})=>this.startCallbackRepair(t,{actorOpenId:a,chatId:e}),status:({attemptId:a}={})=>o(a)?this.registrationStatus(a):null,cancel:async({attemptId:a}={})=>o(a)?this.cancelRegistration(a):this.status(t)})}async#M(t){let o=this.#a.get(t);this.#a.delete(t),o&&await o.stop()}async#O(t){let o=this.#r.getBot(t);if(o){o.deletionPending||(o=await this.#r.saveBot({...o,deletionPending:!0})),await this.#M(t);try{await this.#t.unset(o.secretRef)}catch(a){throw this.#s.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:a})}try{await this.#o({botId:t,config:o})}catch(a){throw this.#s.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:a})}await this.#r.removeBot(t),this.#s.delete(t),this.#d.delete(t)}}async#S(t,o){o?.value?await this.#t.set(t,o.value):await this.#t.unset(t)}#T(t){let o=this.#r.getBot(t);if(!o)throw new Error("Unknown Feishu bot");return o}#N(){if(this.#B)throw new Error("The Feishu controller is closed")}#P(t){let o=this.#p.then(t,t);return this.#p=o.then(()=>{},()=>{}),o}#_(t,o){let e=(this.#E.get(t)??Promise.resolve()).then(o,o),i=e.then(()=>{},()=>{});return this.#E.set(t,i),i.finally(()=>{this.#E.get(t)===i&&this.#E.delete(t)}),e}#G(){if(!(this.#l.size<=32))for(let[t,o]of this.#l){if(t===this.#n)continue;let a=o.manager.status().state;if(!SG.has(a)&&a!=="saving"&&this.#l.delete(t),this.#l.size<=32)break}}#R(){this.#u+=1}};var pFe=["open.feishu.cn","open.larksuite.com"];function hFe(n,t){if(t==="*")return!0;let o=t.startsWith(".")?t.slice(1):t;return o?n===o||n.endsWith(`.${o}`):!1}function EFe(n){for(let t of["no_proxy","NO_PROXY"]){let o=n?.[t];if(typeof o!="string"||!o.trim())continue;let a=o.split(",").map(e=>e.trim().toLowerCase()).filter(Boolean);if(pFe.some(e=>a.some(i=>hFe(e,i))))return!0}return!1}function uFe(n){if(!EFe(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 CFe(n,t=o=>new TZ.default(o)){let o=uFe(n);return o?t(o):void 0}function BFe(n){let t=Xc(n.dshHome??process.env.DSH_HOME??hh(lFe(),".dsh")),o=Xc(n.dataDir??hh(t,"integrations","dsh-feishu"));return{root:o,config:Xc(n.configPath??hh(o,"config.json")),legacyState:Xc(n.statePath??hh(o,"state.json")),bots:Xc(n.botsDir??hh(o,"bots")),workspaces:Xc(n.workspacesPath??hh(o,"workspaces.json"))}}async function wG(n,t={},o={}){if(!n?.credentials)throw new TypeError("dsh-feishu requires ctx.credentials");let a=ci(n,t),e=o.lark??rG,i=o.Controller??aB,A=o.ConfigStore??tw,r=o.StateStore??KS,s=o.HarnessClient??ew,g=o.FeishuRuntime??$S,c=o.verifyFeishuApp??R5,I=Be=>c({...Be,httpInstance:e.defaultHttpInstance}),d=o.createConnectionSupervisor??iG,B=typeof n.logger=="function"?n.logger("dsh-feishu"):n.logger??console,f=()=>ji(n),Q=BFe(t),y=await new A(Q.config).load(),m=Xc(t.workspace??process.cwd()),_=o.WorkspaceStore??gi,T=o.workspaces??await new _(Q.workspaces,{defaultWorkspace:m}).load(),R=typeof y.list=="function",L=()=>R?y.list():[],U=L();R&&await T.reconcile(U.map(Be=>Be.id)),await Promise.all(U.map(Be=>T.ensure(Be.id,{defaultAgentPreset:t.agentPreset,initialAccessPolicy:pr("feishu",Be)})));let F=typeof y.removeBot=="function"?Ji(y,{workspaces:T,method:"removeBot",botIdFromRemoved:Be=>Be.id,saveMethod:"saveBot",botIdFromSave:Be=>Be?.id}):y,z=new Map,J=Be=>!Be.id||!Be.secretRef||Be.secretRef===rw?Q.legacyState:Xc(Q.bots,Be.id,"state.json"),K=async Be=>{let Re=Be.id??"__legacy__",Ne=z.get(Re);return Ne||(Ne=await new r(J(Be)).load(),z.set(Re,Ne)),Ne},G=async Be=>{let Re=L().find(Ne=>Ne.id===Be);if(!Re)throw new Error("Unknown Feishu bot");return K(Re)},V=Wi(n,o.commandExecutor),{controlExecutor:H,sessionMaintenanceExecutor:N,fileIngressExecutor:k}=Zi(n,{controlExecutor:o.controlExecutor,sessionMaintenanceExecutor:o.sessionMaintenanceExecutor,fileIngressExecutor:o.fileIngressExecutor}),q=new s({...a,workspace:m,autostart:!1,dshBin:t.dshBin??"dsh",...V?{commandExecutor:V}:{},...H?{controlExecutor:H}:{},...N?{sessionMaintenanceExecutor:N}:{},...k?{fileIngressExecutor:k}:{}}),X=o.proxyEnv??process.env,ie=CFe(X,o.createProxyAgent),De=new i({registerApp:Be=>e.registerApp(Be),verifyApp:I,credentials:n.credentials,configStore:F,createRuntime:async({botId:Be,config:Re,appSecret:Ne,repair:Je})=>{let ve=await K(Re),tA=Be??Re.id??Re.appId;await T.ensure(tA,{defaultAgentPreset:t.agentPreset,initialAccessPolicy:pr("feishu",Re)});let fe=qi(q,{botId:tA,workspaces:T,state:ve,agentPresetCatalog:f});return new g({lark:e,botId:tA,repair:Je,appId:Re.appId,appSecret:Ne,domain:Re.domain,botOpenId:Re.botOpenId,groupResponseMode:Re.groupResponseMode,ownerOpenIds:Re.ownerOpenIds??[Re.ownerOpenId],harness:fe.harness,state:fe.state,contextEnhancement:{botId:tA,getSettings:()=>T.contextEnhancementFor(tA)},accessPolicy:Xi(T,tA,{channel:"feishu",config:Re}),groupSessionScope:{getScope:()=>T.groupSessionScopeFor(tA)},replyTimeoutMs:t.replyTimeoutMs??6e5,slashCommands:t.slashCommands!==!1,...ie?{wsAgent:ie}:{},logger:{error:(...Ie)=>B.error?.(`[${Be??Re.id}]`,...Ie),warn:(...Ie)=>B.warn?.(`[${Be??Re.id}]`,...Ie),info:(...Ie)=>B.info?.(`[${Be??Re.id}]`,...Ie),debug:(...Ie)=>B.debug?.(`[${Be??Re.id}]`,...Ie)}})},deleteState:async({botId:Be,config:Re})=>{z.delete(Be);try{await dFe(J(Re))}catch(Ne){if(Ne?.code!=="ENOENT")throw Ne}}}),oe=zi(De,{workspaces:T,stateFor:G,agentPresetCatalog:f}),Se=d({controller:oe,harness:q,logger:B,retryDelaysMs:t.retryDelaysMs,healthyIntervalMs:t.healthyIntervalMs}).start();return{controller:oe,deliveryAdapter:Vi({channel:"feishu",workspaces:T,coreController:De,stateFor:G}),ready:Se.ready,async close(){await Se.close(),await oe.close(),q.stopManagedProcess(),ie?.destroy?.()}}}import FFe from"qrcode";var uh=ze(NG(),1);var vFe=ze(NG(),1);var PFe=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",\u673A\u5668\u4EBA\u8BBE\u7F6E:"Bot settings",\u673A\u5668\u4EBA\u8BBE\u7F6E\u9875\u7B7E:"Bot settings tabs",\u6295\u9012\u8BBE\u7F6E:"Delivery settings",\u8BBF\u95EE\u8BBE\u7F6E:"Access settings","\u65E0\u6CD5\u8BFB\u53D6\u8BBF\u95EE\u6388\u6743\uFF0C\u8BF7\u8FD4\u56DE\u5237\u65B0\u540E\u91CD\u8BD5\u3002":"Could not load the access grant. Go back, refresh, and try again.","\u6B63\u5728\u8BFB\u53D6\u5206\u7EA7\u8BBF\u95EE\u8BBE\u7F6E\u2026":"Loading graded access settings\u2026",\u52A0\u672C\u7FA4:"Add to group",\u5DF2\u5728\u672C\u7FA4:"Already in group",\u52A0\u79C1\u804A:"Add to DMs",\u5DF2\u5728\u79C1\u804A:"Already in DMs","\u5DF2\u52A0\u5165\u672C\u7FA4\u6388\u6743\uFF0C\u8BB0\u5F97\u70B9\u4FDD\u5B58\u3002":"Added to this group. Remember to save.","\u5DF2\u52A0\u5165\u79C1\u804A\u6388\u6743\uFF0C\u8BB0\u5F97\u70B9\u4FDD\u5B58\u3002":"Added to DM access. Remember to save.","\u6682\u65E0\u8054\u7CFB\u4EBA\u3002\u6709\u4EBA\u79C1\u804A\u6216 @ \u673A\u5668\u4EBA\u540E\u4F1A\u51FA\u73B0\u5728\u6B64\u3002":"No contacts yet. They appear here after someone DMs or @mentions the bot.","\u4EC5\u8BB0\u5F55\u79C1\u804A\u673A\u5668\u4EBA\uFF0C\u6216\u5728\u7FA4\u91CC @ \u673A\u5668\u4EBA\u7684\u4EBA\u3002\u7535\u8BDD\u662F\u552F\u4E00\u6388\u6743\u952E\uFF0C\u53EF\u4E00\u952E\u52A0\u5165\u79C1\u804A/\u672C\u7FA4\u6388\u6743\u3002":"Only people who DM the bot or @mention it in a group are recorded. Phone is the sole auth key; use one-click to grant DM or group access.","WhatsApp \u6309\u7535\u8BDD\u53F7\u7801\u6388\u6743\uFF1A\u5168\u5C40\u7BA1\u7406\u5458\u7BA1\u79C1\u804A\uFF1B\u7FA4\u7BA1\u7406\u5458\u53EA\u6279\u672C\u7FA4\u3002\u6210\u5458\u4E0D\u53EF\u8DE8\u7FA4\u3001\u6709\u7FA4\u6743\u4E5F\u4E0D\u81EA\u52A8\u83B7\u5F97\u79C1\u804A\u6743\u3002":"WhatsApp authorizes by phone number: global admins manage DMs; group admins approve only their group. Members do not cross groups, and group access does not grant DMs.",\u4FDD\u5B58\u5206\u7EA7\u8BBF\u95EE\u8BBE\u7F6E:"Save graded access settings",\u4FDD\u5B58\u8BBF\u95EE\u4E0E\u4F1A\u8BDD\u8BBE\u7F6E:"Save access and session settings",\u5168\u5C40\u7BA1\u7406\u5458:"Global admins","\u5206\u7EA7\u8BBF\u95EE\u8BBE\u7F6E\u5DF2\u4FDD\u5B58\u3002":"Graded access settings saved.","\u5BA1\u6279\u5931\u8D25\u3002":"Approval failed.","\u5C1A\u65E0\u5DF2\u77E5\u7FA4\u3002\u53EF\u5728\u4E0B\u65B9\u7C98\u8D34\u7FA4 JID\uFF08\u2026@g.us\uFF09\uFF0C\u6216\u7B49\u7FA4\u5185\u6709\u4EBA @ \u673A\u5668\u4EBA\u540E\u81EA\u52A8\u51FA\u73B0\u3002":"No known groups yet. Paste a group JID (\u2026@g.us) below, or wait until someone @mentions the bot in a group.","\u5DF2\u6279\u51C6\u7533\u8BF7\u3002":"Request approved.","\u5DF2\u62D2\u7EDD\u7533\u8BF7\u3002":"Request denied.","\u5F53\u524D\u6E20\u9053\u4ECD\u4F7F\u7528\u65E7\u7248\u8BBF\u95EE\u8BBE\u7F6E\u3002":"This channel still uses the legacy access settings.",\u5F85\u5BA1\u6279:"Pending approval",\u5F85\u8865\u7535\u8BDD:"Phone pending",\u6279\u51C6:"Approve",\u62D2\u7EDD:"Deny","\u6309\u53D1\u8A00\u4EBA\u62C6\u5206\uFF08\u63A8\u8350\uFF09":"Split by speaker (recommended)","\u6574\u7FA4\u5171\u4EAB\u4E00\u4E2A Session":"Share one session for the whole group",\u65B0\u589E\u7BA1\u7406\u5458:"Add admin",\u6682\u65E0\u5F85\u6279\u7533\u8BF7:"No pending requests","\u6682\u65E0\u8054\u7CFB\u4EBA\u3002\u79C1\u804A\u6216\u7FA4\u5185\u89E6\u53D1\u540E\u4F1A\u51FA\u73B0\u5728\u6B64\uFF0C\u4FBF\u4E8E\u8865\u9F50\u7535\u8BDD\u4E0E\u6635\u79F0\u3002":"No contacts yet. People who DM or trigger the bot in a group appear here so you can fill in phones and names.","\u6700\u8FD1\u8054\u7CFB\u4EBA\uFF08\u81EA\u52A8\u6C89\u6DC0\uFF09":"Recent contacts (auto-collected)","\u670D\u52A1\u6CA1\u6709\u8FD4\u56DE\u5DF2\u4FDD\u5B58\u7684\u8BBF\u95EE\u6388\u6743\u3002":"The service did not return the saved access grant.",\u672A\u547D\u540D:"Unnamed","\u672A\u914D\u7F6E\u65F6\uFF0C\u672C\u7FA4\u7533\u8BF7\u56DE\u843D\u7ED9\u5168\u5C40\u7BA1\u7406\u5458\u5BA1\u6279\uFF08\u4ECD\u53EA\u6388\u4E88\u672C\u7FA4\u6743\uFF09\u3002":"When unset, this group's requests fall back to global admins (still grants only this group).",\u672C\u7FA4\u6388\u6743\u6210\u5458:"Group members",\u672C\u7FA4\u7BA1\u7406\u5458:"Group admins",\u67E5\u770B\u7FA4\u4F1A\u8BDD\u7B56\u7565\u8BF4\u660E:"View group session policy details",\u6DFB\u52A0\u7FA4:"Add group","\u6DFB\u52A0\u7FA4 JID":"Add group JID",\u7535\u8BDD:"Phone",\u79C1\u804A\u6388\u6743\u7528\u6237:"DM members","\u7ED1\u5B9A\u8D26\u53F7\u81EA\u52A8\u4E3A\u5168\u5C40\u7BA1\u7406\u5458\uFF0C\u81F3\u5C11\u4FDD\u7559\u4E00\u4F4D\u3002":"The linked account is a global admin automatically. Keep at least one.","\u7ED1\u5B9A\u8D26\u53F7\uFF08\u5168\u5C40\u7BA1\u7406\u5458\uFF09":"Linked account (global admin)","\u7F3A\u5C11\u53EF\u7528\u4E8E\u5BA1\u6279\u7684\u5168\u5C40\u7BA1\u7406\u5458\u7535\u8BDD\u3002":"No global admin phone is available for approval.","\u7FA4 JID \u683C\u5F0F\u65E0\u6548\u3002":"Invalid group JID.",\u7FA4\u4F1A\u8BDD\u7B56\u7565:"Group session policy","\u7FA4\u5185 Session \u7ED1\u5B9A":"In-group session binding",\u7FA4\u5907\u6CE8\u540D:"Group display name",\u7FA4\u6388\u6743:"Group grants","\u8BBF\u95EE\u4E0E\u7FA4\u4F1A\u8BDD\u8BBE\u7F6E\u5DF2\u4FDD\u5B58\u3002":"Access and group session settings saved.","\u8BBF\u95EE\u6388\u6743\u4FDD\u5B58\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002":"Could not save the access grant. Try again later.","\u8BBF\u95EE\u6388\u6743\u6682\u4E0D\u53EF\u7528\u3002":"Access grant settings are currently unavailable.","\u8FD0\u7EF4\u9ED8\u8BA4\u6309\u53D1\u8A00\u4EBA\u62C6\u5206 Session\uFF0C\u907F\u514D\u540C\u7FA4\u591A\u4EBA\u4E92\u76F8\u6253\u65AD\uFF1B\u53EF\u9009\u6539\u56DE\u6574\u7FA4\u5171\u4EAB Session\u3002":"Ops defaults to one session per speaker so group members do not interrupt each other. You can switch back to one shared group session.","\uFF08\u7535\u8BDD\u672A\u89E3\u6790\uFF0C\u8BF7\u5148\u5728\u8054\u7CFB\u4EBA\u4E2D\u786E\u8BA4\uFF09":"(Phone unresolved \u2014 confirm it in contacts first)",\u67E5\u770B\u8BBF\u95EE\u6743\u9650\u8BF4\u660E:"View access permission details",\u5141\u8BB8\u6240\u6709\u7528\u6237:"Allow all users",\u4EC5\u767D\u540D\u5355\u7528\u6237:"Allowlisted users only",\u9ED8\u8BA4\u547D\u4EE4\u6743\u9650:"Default command permission",\u547D\u4EE4\u6743\u9650:"Command permission",\u53EF\u4EE5\u6267\u884C\u547D\u4EE4:"Can run commands",\u4E0D\u53EF\u4EE5\u6267\u884C\u547D\u4EE4:"Cannot run commands",\u767D\u540D\u5355\u7528\u6237:"Allowlisted users",\u67E5\u770B\u767D\u540D\u5355\u8BF4\u660E:"View allowlist details",\u547D\u4EE4\u6743\u9650\u4F8B\u5916:"Command permission exceptions","\u5F53\u524D\u6CA1\u6709\u767D\u540D\u5355\u7528\u6237\uFF0C\u4FDD\u5B58\u540E\u666E\u901A\u7528\u6237\u5C06\u65E0\u6CD5\u4F7F\u7528\u673A\u5668\u4EBA\u3002":"There are currently no allowlisted users. After saving, regular users will not be able to use the bot.",\u65B0\u589E\u7528\u6237:"Add user",\u5C1A\u672A\u6DFB\u52A0\u7528\u6237:"No users added",\u5F53\u524D\u6E20\u9053\u4E0D\u652F\u6301\u7FA4\u804A:"Group chat is not supported by this channel","\u539F\u6240\u6709\u8005\u6216\u626B\u7801\u63A5\u5165\u8005\u59CB\u7EC8\u53EF\u4EE5\u8BBF\u95EE\u5E76\u6267\u884C\u547D\u4EE4\uFF1B\u4EE5\u4E0B\u8BBE\u7F6E\u4EC5\u7EA6\u675F\u5176\u4ED6\u7528\u6237\u3002":"The original owner or QR-code operator can always access the bot and run commands; the settings below apply only to other users.","\u6B64\u533A\u57DF\u65E0\u9700\u914D\u7F6E\uFF0C\u4FDD\u5B58\u79C1\u804A\u8BBE\u7F6E\u65F6\u4F1A\u4FDD\u7559\u73B0\u6709\u7FA4\u804A\u7B56\u7565\u3002":"No setup is needed here. Saving direct-message settings keeps the existing group policy.","\u8BBF\u95EE\u8BBE\u7F6E\u5DF2\u4FDD\u5B58\u3002":"Access settings saved.","\u8BBF\u95EE\u8BBE\u7F6E\u6682\u4E0D\u53EF\u7528\u3002":"Access settings are currently unavailable.","\u8BBF\u95EE\u8BBE\u7F6E\u4FDD\u5B58\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002":"Could not save access settings. Try again later.","\u670D\u52A1\u6CA1\u6709\u8FD4\u56DE\u5DF2\u4FDD\u5B58\u7684\u8BBF\u95EE\u7B56\u7565\uFF0C\u8BF7\u5237\u65B0\u540E\u91CD\u8BD5\u3002":"The service did not return the saved access policy. Refresh and try again.","\u8BBF\u95EE\u7B56\u7565\u5C1A\u672A\u5C31\u7EEA\uFF0C\u8BF7\u8FD4\u56DE\u673A\u5668\u4EBA\u5217\u8868\u5237\u65B0\u540E\u91CD\u8BD5\u3002":"The access policy is not ready. Return to the bot list, refresh, and try again.","\u5F53\u524D\u6E20\u9053\u6682\u4E0D\u652F\u6301\u8BBF\u95EE\u8BBE\u7F6E\u3002":"Access settings are not supported by this channel yet.","\u7528\u6237\u6807\u8BC6\u65E0\u6548\u3002":"The user ID is invalid.","\u7528\u6237\u6807\u8BC6\u5FC5\u987B\u662F\u5B57\u7B26\u4E32\u3002":"The user ID must be a string.","\u7528\u6237\u6807\u8BC6\u4E0D\u80FD\u4E3A\u7A7A\u3001\u5305\u542B\u63A7\u5236\u5B57\u7B26\u6216\u8D85\u8FC7 256 \u4E2A\u5B57\u7B26\u3002":"The user ID cannot be empty, contain control characters, or exceed 256 characters.","\u7528\u6237\u6761\u76EE\u5FC5\u987B\u5305\u542B\u7528\u6237\u6807\u8BC6\u548C\u547D\u4EE4\u6743\u9650\u3002":"Each user entry must include a user ID and command permission.","\u547D\u4EE4\u6743\u9650\u5FC5\u987B\u662F\u5E03\u5C14\u503C\u3002":"Command permission must be a boolean.","\u8BBF\u95EE\u6A21\u5F0F\u53EA\u80FD\u662F open \u6216 allowlist\u3002":"Access mode must be open or allowlist.","\u5F00\u653E\u6A21\u5F0F\u8BBE\u7F6E\u5FC5\u987B\u5B8C\u6574\u3002":"Open-mode settings must be complete.","\u5F00\u653E\u6A21\u5F0F\u9ED8\u8BA4\u547D\u4EE4\u6743\u9650\u5FC5\u987B\u662F\u5E03\u5C14\u503C\u3002":"The open-mode default command permission must be a boolean.","\u5F00\u653E\u6A21\u5F0F\u547D\u4EE4\u6743\u9650\u8986\u76D6\u7528\u6237\u5FC5\u987B\u662F\u6570\u7EC4\u3002":"Open-mode command permission overrides must be an array.","\u5F00\u653E\u6A21\u5F0F\u547D\u4EE4\u6743\u9650\u8986\u76D6\u7528\u6237\u4E0D\u80FD\u5305\u542B\u91CD\u590D\u7684\u7528\u6237\u6807\u8BC6\u3002":"Open-mode command permission overrides cannot contain duplicate user IDs.","\u767D\u540D\u5355\u6A21\u5F0F\u8BBE\u7F6E\u5FC5\u987B\u5B8C\u6574\u3002":"Allowlist-mode settings must be complete.","\u767D\u540D\u5355\u6A21\u5F0F\u7528\u6237\u5FC5\u987B\u662F\u6570\u7EC4\u3002":"Allowlist-mode users must be an array.","\u767D\u540D\u5355\u6A21\u5F0F\u7528\u6237\u4E0D\u80FD\u5305\u542B\u91CD\u590D\u7684\u7528\u6237\u6807\u8BC6\u3002":"Allowlist-mode users cannot contain duplicate user IDs.","\u8BBF\u95EE\u573A\u666F\u8BBE\u7F6E\u5FC5\u987B\u540C\u65F6\u5305\u542B\u6A21\u5F0F\u3001\u5F00\u653E\u6A21\u5F0F\u8BBE\u7F6E\u548C\u767D\u540D\u5355\u6A21\u5F0F\u8BBE\u7F6E\u3002":"Each access context must include its mode, open-mode settings, and allowlist-mode settings.","\u8BF7\u540C\u65F6\u63D0\u4EA4\u5B8C\u6574\u7684\u79C1\u804A\u548C\u7FA4\u804A\u8BBF\u95EE\u8BBE\u7F6E\u3002":"Submit complete direct-message and group access settings together.","\u586B\u5199\u5FAE\u4FE1\u7528\u6237 ID":"Enter a WeChat user ID","\u98DE\u4E66 Open ID":"Feishu Open ID","\u7FA4\u6210\u5458 Open ID":"Group member Open ID","\u9489\u9489\u7528\u6237 ID":"DingTalk user ID","\u586B\u5199 senderStaffId \u6216 senderId":"Enter senderStaffId or senderId","\u7FA4\u6210\u5458\u7528\u6237 ID":"Group member user ID","\u4F01\u4E1A\u5FAE\u4FE1\u7528\u6237 ID":"WeCom user ID","\u586B\u5199 userid":"Enter userid","\u586B\u5199 member_openid":"Enter member_openid","QQ User Open ID":"QQ User Open ID","\u7FA4\u6210\u5458 User ID":"Group member User ID","\u586B\u5199\u6570\u5B57 User ID":"Enter a numeric user ID","WhatsApp \u7535\u8BDD\u53F7\u7801\u6216 JID":"WhatsApp phone number or JID","\u7FA4\u6210\u5458\u7535\u8BDD\u53F7\u7801\u6216 JID":"Group member phone number or JID","8613800000000 \u6216\u5B8C\u6574 JID":"8613800000000 or a full JID","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",\u4E0A\u4E0B\u6587\u589E\u5F3A\u8303\u56F4:"Context enhancement scope",\u542F\u7528\u8303\u56F4:"Enable in",\u542F\u7528:"Enabled","\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",\u67E5\u770B\u7FA4\u804A\u6765\u6E90\u5B57\u6BB5\u8BF4\u660E:"View group source field details",\u67E5\u770B\u79C1\u804A\u6765\u6E90\u5B57\u6BB5\u8BF4\u660E:"View direct 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",\u67E5\u770B\u7FA4\u804A\u53D1\u9001\u8005\u6635\u79F0\u5B57\u6BB5\u8BF4\u660E:"View group sender name field details",\u67E5\u770B\u79C1\u804A\u53D1\u9001\u8005\u6635\u79F0\u5B57\u6BB5\u8BF4\u660E:"View direct 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.",\u4F1A\u8BDD\u6807\u9898:"Conversation title",\u67E5\u770B\u7FA4\u804A\u4F1A\u8BDD\u6807\u9898\u5B57\u6BB5\u8BF4\u660E:"View group conversation title field details",\u67E5\u770B\u79C1\u804A\u4F1A\u8BDD\u6807\u9898\u5B57\u6BB5\u8BF4\u660E:"View direct conversation title field details","\u8BE5\u5B57\u6BB5\u4E0D\u662F\u6BCF\u4E2A\u6E20\u9053\u90FD\u80FD\u63D0\u4F9B\u3002\u9489\u9489\u7FA4\u804A\u4F1A\u5E26\u4E0A\u7FA4\u540D\u3002\u5F53\u524D\u6D88\u606F\u6CA1\u6709\u4F1A\u8BDD\u6807\u9898\u65F6\uFF0C\u5373\u4F7F\u5DF2\u9009\u62E9\u8BE5\u5B57\u6BB5\uFF0C \u4E2D\u4E5F\u4F1A\u7701\u7565 conversationTitle\u3002":"This field is not available on every channel. DingTalk group chats include the group name. If the current message has no conversation title, omits conversationTitle even when the field is selected.",\u4F1A\u8BDD\u6807\u8BC6:"Chat ID",\u67E5\u770B\u7FA4\u804A\u4F1A\u8BDD\u6807\u8BC6\u5B57\u6BB5\u8BF4\u660E:"View group chat ID field details",\u67E5\u770B\u79C1\u804A\u4F1A\u8BDD\u6807\u8BC6\u5B57\u6BB5\u8BF4\u660E:"View direct chat ID field details","\u8BE5\u5B57\u6BB5\u4E0D\u662F\u6BCF\u4E2A\u6E20\u9053\u90FD\u80FD\u63D0\u4F9B\u3002\u4F1A\u8BDD\u6807\u8BC6\u7528\u4E8E\u533A\u5206\u4E0D\u540C\u7684\u7FA4\u7EC4\u6216\u79C1\u804A\uFF0C\u98DE\u4E66\u7FA4\u804A\u4F1A\u5E26\u4E0A\u7FA4 ID\u3002\u5F53\u524D\u6D88\u606F\u6CA1\u6709\u4F1A\u8BDD\u6807\u8BC6\u65F6\uFF0C\u5373\u4F7F\u5DF2\u9009\u62E9\u8BE5\u5B57\u6BB5\uFF0C \u4E2D\u4E5F\u4F1A\u7701\u7565 chatId\u3002":"This field is not available on every channel. The chat ID distinguishes different groups or direct chats, and Feishu group chats include the group ID. If the current message has no chat ID, omits chatId even when the field is selected.",\u8BDD\u9898\u6807\u8BC6:"Topic ID",\u67E5\u770B\u7FA4\u804A\u8BDD\u9898\u6807\u8BC6\u5B57\u6BB5\u8BF4\u660E:"View group topic ID field details",\u67E5\u770B\u79C1\u804A\u8BDD\u9898\u6807\u8BC6\u5B57\u6BB5\u8BF4\u660E:"View direct topic ID field details","\u8BE5\u5B57\u6BB5\u4E0D\u662F\u6BCF\u4E2A\u6E20\u9053\u90FD\u80FD\u63D0\u4F9B\u3002\u98DE\u4E66\u8BDD\u9898\u7FA4\u7684\u6D88\u606F\u4F1A\u5E26\u4E0A\u8BDD\u9898 ID\uFF0C\u7528\u4E8E\u533A\u5206\u540C\u4E00\u7FA4\u7EC4\u5185\u7684\u4E0D\u540C\u8BDD\u9898\uFF1B\u5F53\u524D\u6D88\u606F\u4E0D\u5728\u8BDD\u9898\u4E2D\u65F6\uFF0C\u5373\u4F7F\u5DF2\u9009\u62E9\u8BE5\u5B57\u6BB5\uFF0C \u4E2D\u4E5F\u4F1A\u7701\u7565 threadId\u3002":"This field is not available on every channel. Messages in a Feishu topic chat carry the topic ID, which distinguishes different topics inside the same group. If the current message is not inside a topic, omits threadId 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",\u67E5\u770B\u7FA4\u804A\u589E\u5F3A\u63D0\u793A\u8BCD\u4F7F\u7528\u8BF4\u660E:"View group guidance instructions",\u67E5\u770B\u79C1\u804A\u589E\u5F3A\u63D0\u793A\u8BCD\u4F7F\u7528\u8BF4\u660E:"View direct 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.`,"\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\n\u5F53\u524D\u6D88\u606F\u6765\u81EA\u7FA4\u804A\uFF0C\u8BF7\u4F7F\u7528\u4E25\u8083\u3001\u514B\u5236\u3001\u7B80\u6D01\u7684\u8868\u8FBE\u65B9\u5F0F\u3002":`Understand the source only from fields actually present in for the current message; do not guess or fill in missing fields. This message is from a group chat. Use a serious, restrained, and concise style.`,"\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\n\u5F53\u524D\u6D88\u606F\u6765\u81EA\u79C1\u804A\uFF0C\u53EF\u4EE5\u4F7F\u7528\u66F4\u8F7B\u677E\u3001\u5E7D\u9ED8\u3001\u8BE6\u7EC6\u7684\u8868\u8FBE\u65B9\u5F0F\u3002":`Understand the source only from fields actually present in for the current message; do not guess or fill in missing fields. This message is from a direct chat. You may use a lighter, more humorous, and detailed style.`,\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.","\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\u5F53\u524D\u4F1A\u8BDD\u4E2D\u52FE\u9009\u4E14\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 fields selected and available in the current conversation are sent; no extra lookups are made.","\u7528\u4E8E\u544A\u8BC9\u6A21\u578B\u5982\u4F55\u4F7F\u7528\u5F53\u524D\u7FA4\u804A\u6D88\u606F\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 fields for the current group message. Enter only the body; the plugin adds paired tags.","\u7528\u4E8E\u544A\u8BC9\u6A21\u578B\u5982\u4F55\u4F7F\u7528\u5F53\u524D\u79C1\u804A\u6D88\u606F\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 fields for the current direct message. Enter only the body; the plugin adds paired tags.","\u4EC5\u5728\u7FA4\u804A\u5F00\u5173\u5F00\u542F\u65F6\u4F7F\u7528\u3002\u6E05\u7A7A\u5E76\u4FDD\u5B58\u540E\u4E0D\u518D\u9644\u52A0\u7FA4\u804A\u589E\u5F3A\u63D0\u793A\u8BCD\uFF1B\u6240\u9009\u6765\u6E90\u5B57\u6BB5\u4ECD\u6309\u5F53\u524D\u573A\u666F\u8BBE\u7F6E\u53D1\u9001\u3002":"Used only when group enhancement is enabled. Clear and save to omit group guidance; selected source fields still follow the group settings.","\u4EC5\u5728\u79C1\u804A\u5F00\u5173\u5F00\u542F\u65F6\u4F7F\u7528\u3002\u6E05\u7A7A\u5E76\u4FDD\u5B58\u540E\u4E0D\u518D\u9644\u52A0\u79C1\u804A\u589E\u5F3A\u63D0\u793A\u8BCD\uFF1B\u6240\u9009\u6765\u6E90\u5B57\u6BB5\u4ECD\u6309\u5F53\u524D\u573A\u666F\u8BBE\u7F6E\u53D1\u9001\u3002":"Used only when direct enhancement is enabled. Clear and save to omit direct guidance; selected source fields still follow the direct settings.","\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\u516B\u4E2A\u5B57\u6BB5\u3002":"Source fields must be chosen from the eight 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.","\u673A\u5668\u4EBA\u5DF2\u4FDD\u5B58\uFF0C\u4F46\u8FDE\u63A5\u672A\u5C31\u7EEA":"The bot was saved, but the connection is not ready",\u67E5\u770B\u5DF2\u4FDD\u5B58\u7684\u673A\u5668\u4EBA:"View saved bot","\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 diff --git a/package.json b/package.json index 75e2683..95c08bb 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "dsh-im-ops", - "version": "4.9.1-ops.6", + "version": "4.9.1-ops.7", "description": "Ops fork of dsh-im (all channels kept). Based on @xmanrui/dsh-im@4.9.1 — access/session policies owned here.", "keywords": [ "deepseek-harness", diff --git a/plugin-src/client/access-grant-settings.js b/plugin-src/client/access-grant-settings.js index 69165fb..b83df7b 100644 --- a/plugin-src/client/access-grant-settings.js +++ b/plugin-src/client/access-grant-settings.js @@ -221,12 +221,47 @@ export function AccessGrantSettingsPage({ channel, account, rpcCall, onSaved }) const [saving, setSaving] = React.useState(false); const [feedback, setFeedback] = React.useState(null); const [newGroupJid, setNewGroupJid] = React.useState(''); + const [loadingGrant, setLoadingGrant] = React.useState(!initialGrant); React.useEffect(() => { setDraft(cloneGrant(normalizeAccessGrant(account?.accessGrant), ownerPhone)); setGroupSessionScope(normalizeGroupSessionScope(account?.groupSessionScope)); }, [account?.botId, initialKey, account?.groupSessionScope, ownerPhone]); + // Settings open payload historically omitted accessGrant; always refresh from status. + React.useEffect(() => { + if (typeof rpcCall !== 'function' || !account?.botId) return undefined; + let cancelled = false; + setLoadingGrant(true); + void (async () => { + try { + const value = unwrapRpcResult(await rpcCall('connection.status', {})); + if (cancelled) return; + const bot = Array.isArray(value?.bots) + ? value.bots.find((entry) => entry?.botId === account.botId) + : null; + const grant = normalizeAccessGrant(bot?.accessGrant); + if (grant) { + setDraft(cloneGrant(grant, ownerPhone)); + onSaved?.(grant); + } + if (bot?.groupSessionScope) { + setGroupSessionScope(normalizeGroupSessionScope(bot.groupSessionScope)); + } + } catch (error) { + if (!cancelled) { + setFeedback({ + tone: 'error', + message: error?.message || '无法读取访问授权,请返回刷新后重试。', + }); + } + } finally { + if (!cancelled) setLoadingGrant(false); + } + })(); + return () => { cancelled = true; }; + }, [account?.botId, rpcCall, ownerPhone]); + const contacts = draft.contacts ?? []; const knownGroupJids = React.useMemo(() => { const set = new Set(Object.keys(draft.groups ?? {})); @@ -319,6 +354,9 @@ export function AccessGrantSettingsPage({ channel, account, rpcCall, onSaved }) className: 'dim-accessPage', onSubmit: (event) => void save(event), }, + loadingGrant + ? h('div', { className: 'dim-accessState', 'aria-busy': 'true' }, '正在读取分级访问设置…') + : null, h('p', { className: 'dim-accessUsersEmpty' }, 'WhatsApp 按电话号码授权:全局管理员管私聊;群管理员只批本群。成员不可跨群、有群权也不自动获得私聊权。'), h(AdminPhones, { diff --git a/plugin-src/client/channel-card-meta.js b/plugin-src/client/channel-card-meta.js index e073fba..926e770 100644 --- a/plugin-src/client/channel-card-meta.js +++ b/plugin-src/client/channel-card-meta.js @@ -22,7 +22,15 @@ function SettingsGlyph() { h('path', { d: 'M19.4 15a1.7 1.7 0 0 0 .34 1.88l.06.06-2.83 2.83-.06-.06a1.7 1.7 0 0 0-1.88-.34 1.7 1.7 0 0 0-1.03 1.55V21h-4v-.08A1.7 1.7 0 0 0 8.97 19.4a1.7 1.7 0 0 0-1.88.34l-.06.06-2.83-2.83.06-.06A1.7 1.7 0 0 0 4.6 15a1.7 1.7 0 0 0-1.52-1.03H3v-4h.08A1.7 1.7 0 0 0 4.6 8.97a1.7 1.7 0 0 0-.34-1.88l-.06-.06L7.03 4.2l.06.06a1.7 1.7 0 0 0 1.88.34A1.7 1.7 0 0 0 10 3.08V3h4v.08a1.7 1.7 0 0 0 1.03 1.52 1.7 1.7 0 0 0 1.88-.34l.06-.06 2.83 2.83-.06.06a1.7 1.7 0 0 0-.34 1.88A1.7 1.7 0 0 0 20.92 10H21v4h-.08A1.7 1.7 0 0 0 19.4 15Z' })); } -export function BotSettingsButton({ channel, botId, botName, connected, accessPolicy }) { +export function BotSettingsButton({ + channel, + botId, + botName, + connected, + accessPolicy, + accessGrant, + groupSessionScope, +}) { const { openBotSettings } = React.useContext(BotSettingsContext); const tooltipId = React.useId(); return h('span', { className: 'dim-botSettingsAction' }, @@ -38,6 +46,8 @@ export function BotSettingsButton({ channel, botId, botName, connected, accessPo botName, connected: Boolean(connected), accessPolicy, + accessGrant, + groupSessionScope, }), }, h(SettingsGlyph)), h('span', { diff --git a/plugin-src/client/channels/whatsapp/index.js b/plugin-src/client/channels/whatsapp/index.js index a7e4c03..cf88ded 100644 --- a/plugin-src/client/channels/whatsapp/index.js +++ b/plugin-src/client/channels/whatsapp/index.js @@ -220,6 +220,8 @@ export function WhatsappAccountCard({ botName: account.bot.name, connected: account.connected, accessPolicy: account.accessPolicy, + accessGrant: account.accessGrant, + groupSessionScope: account.groupSessionScope, }))), h(WorkspaceEditor, { workspace: account.workspace, diff --git a/plugin-src/client/i18n.js b/plugin-src/client/i18n.js index 98950db..1a2cbc9 100644 --- a/plugin-src/client/i18n.js +++ b/plugin-src/client/i18n.js @@ -11,6 +11,10 @@ const EN = Object.freeze({ '机器人设置页签': 'Bot settings tabs', '投递设置': 'Delivery settings', '访问设置': 'Access settings', + "无法读取访问授权,请返回刷新后重试。": "Could not load the access grant. Go back, refresh, and try again.", + + "正在读取分级访问设置…": "Loading graded access settings…", + "加本群": "Add to group", "已在本群": "Already in group",