diff --git a/lib/client.js b/lib/client.js index 8fdd557..399a90e 100644 --- a/lib/client.js +++ b/lib/client.js @@ -1122,6 +1122,10 @@ var EN = Object.freeze({ "\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.", "\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", @@ -1149,7 +1153,7 @@ var EN = Object.freeze({ "\u4E0A\u4E0B\u6587\u589E\u5F3A\u4FDD\u5B58\u5931\u8D25\uFF0C\u8BF7\u91CD\u8BD5\u3002": "Could not save context enhancement. Try again.", "\u8BF7\u63D0\u4EA4\u5B8C\u6574\u7684\u4E0A\u4E0B\u6587\u589E\u5F3A\u8BBE\u7F6E\u3002": "Submit the complete context enhancement settings.", "\u7FA4\u804A\u548C\u79C1\u804A\u5F00\u5173\u5FC5\u987B\u662F\u5E03\u5C14\u503C\u3002": "Group and direct switches must be booleans.", - "\u6765\u6E90\u5B57\u6BB5\u53EA\u80FD\u9009\u62E9\u5DF2\u5B9A\u4E49\u7684\u4E94\u4E2A\u5B57\u6BB5\u3002": "Source fields must be chosen from the five defined fields.", + "\u6765\u6E90\u5B57\u6BB5\u53EA\u80FD\u9009\u62E9\u5DF2\u5B9A\u4E49\u7684\u516D\u4E2A\u5B57\u6BB5\u3002": "Source fields must be chosen from the six 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.", @@ -2075,6 +2079,7 @@ var CONTEXT_ENHANCEMENT_FIELDS = Object.freeze([ "conversationType", "senderId", "senderName", + "conversationTitle", "botId" ]); var CONTEXT_ENHANCEMENT_GUIDANCE_MAX_LENGTH = 8e3; @@ -2114,7 +2119,7 @@ function validateContextEnhancementScope(input) { throw invalidConfig("\u7FA4\u804A\u548C\u79C1\u804A\u5F00\u5173\u5FC5\u987B\u662F\u5E03\u5C14\u503C\u3002"); } if (!Array.isArray(fields) || ![...fields].every((field) => CONTEXT_ENHANCEMENT_FIELDS.includes(field))) { - throw invalidConfig("\u6765\u6E90\u5B57\u6BB5\u53EA\u80FD\u9009\u62E9\u5DF2\u5B9A\u4E49\u7684\u4E94\u4E2A\u5B57\u6BB5\u3002"); + throw invalidConfig("\u6765\u6E90\u5B57\u6BB5\u53EA\u80FD\u9009\u62E9\u5DF2\u5B9A\u4E49\u7684\u516D\u4E2A\u5B57\u6BB5\u3002"); } if (typeof guidance !== "string" || guidance.length > CONTEXT_ENHANCEMENT_GUIDANCE_MAX_LENGTH) { throw invalidConfig(`\u589E\u5F3A\u63D0\u793A\u8BCD\u4E0D\u5F97\u8D85\u8FC7 ${CONTEXT_ENHANCEMENT_GUIDANCE_MAX_LENGTH} \u4E2A\u5B57\u7B26\u3002`); @@ -2895,14 +2900,26 @@ var FIELD_LABELS = Object.freeze({ conversationType: "\u4F1A\u8BDD\u7C7B\u578B", senderId: "\u53D1\u9001\u8005\u6807\u8BC6", senderName: "\u53D1\u9001\u8005\u6635\u79F0", + conversationTitle: "\u4F1A\u8BDD\u6807\u9898", botId: "\u673A\u5668\u4EBA\u6807\u8BC6" }); +var FIELD_HELP = Object.freeze({ + senderName: Object.freeze({ + labelKey: "senderNameHelpLabel", + text: "\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" + }), + conversationTitle: Object.freeze({ + labelKey: "conversationTitleHelpLabel", + text: "\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" + }) +}); var SCOPE_COPY = Object.freeze({ group: Object.freeze({ title: "\u7FA4\u804A", enable: "\u542F\u7528", fieldsHelpLabel: "\u67E5\u770B\u7FA4\u804A\u6765\u6E90\u5B57\u6BB5\u8BF4\u660E", senderNameHelpLabel: "\u67E5\u770B\u7FA4\u804A\u53D1\u9001\u8005\u6635\u79F0\u5B57\u6BB5\u8BF4\u660E", + conversationTitleHelpLabel: "\u67E5\u770B\u7FA4\u804A\u4F1A\u8BDD\u6807\u9898\u5B57\u6BB5\u8BF4\u660E", guidanceLabel: "\u589E\u5F3A\u63D0\u793A\u8BCD", guidanceHelpLabel: "\u67E5\u770B\u7FA4\u804A\u589E\u5F3A\u63D0\u793A\u8BCD\u4F7F\u7528\u8BF4\u660E", guidanceUsage: "\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", @@ -2913,6 +2930,7 @@ var SCOPE_COPY = Object.freeze({ enable: "\u542F\u7528", fieldsHelpLabel: "\u67E5\u770B\u79C1\u804A\u6765\u6E90\u5B57\u6BB5\u8BF4\u660E", senderNameHelpLabel: "\u67E5\u770B\u79C1\u804A\u53D1\u9001\u8005\u6635\u79F0\u5B57\u6BB5\u8BF4\u660E", + conversationTitleHelpLabel: "\u67E5\u770B\u79C1\u804A\u4F1A\u8BDD\u6807\u9898\u5B57\u6BB5\u8BF4\u660E", guidanceLabel: "\u589E\u5F3A\u63D0\u793A\u8BCD", guidanceHelpLabel: "\u67E5\u770B\u79C1\u804A\u589E\u5F3A\u63D0\u793A\u8BCD\u4F7F\u7528\u8BF4\u660E", guidanceUsage: "\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", @@ -2953,7 +2971,6 @@ function ContextEnhancementScopeEditor({ const copy = SCOPE_COPY[kind]; const unavailableId = `${idPrefix}-${kind}-unavailable`; const fieldsHelpId = `${idPrefix}-${kind}-fields-help`; - const senderNameHelpId = `${idPrefix}-${kind}-sender-name-help`; const guidanceId = `${idPrefix}-${kind}-guidance`; const guidanceHelpId = `${idPrefix}-${kind}-guidance-help`; const disabled = busy || !supported; @@ -3030,21 +3047,21 @@ function ContextEnhancementScopeEditor({ "span", { className: "dim-contextFieldText" }, h2("label", { className: "dim-contextFieldName", htmlFor: fieldId }, FIELD_LABELS[field]), - field === "senderName" ? h2( + FIELD_HELP[field] ? h2( "span", { className: "dim-contextHelp dim-contextFieldHelp" }, h2("button", { type: "button", className: "dim-contextHelpButton dim-contextFieldHelpButton", disabled, - "aria-label": copy.senderNameHelpLabel, - "aria-describedby": senderNameHelpId + "aria-label": copy[FIELD_HELP[field].labelKey], + "aria-describedby": `${idPrefix}-${kind}-${field}-help` }, h2("span", { "aria-hidden": "true" }, "?")), h2("span", { - id: senderNameHelpId, + id: `${idPrefix}-${kind}-${field}-help`, className: "dim-contextTooltip dim-contextFieldTooltip", role: "tooltip" - }, "\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") + }, FIELD_HELP[field].text) ) : null, h2("label", { className: "dim-contextFieldKey", htmlFor: fieldId }, field) ) diff --git a/lib/index.js b/lib/index.js index b37d260..4d1f98e 100644 --- a/lib/index.js +++ b/lib/index.js @@ -195,7 +195,7 @@ ${Fpe(I.text,s)}`);g=cc([a,...c,A.join(` `)}function bde(n){return[w("\u5F53\u524D\u673A\u5668\u4EBA\u7528\u4E8E\u65B0\u4F1A\u8BDD\u7684 Agent Preset \u5DF2\u8BBE\u7F6E\u4E3A\uFF1A"),d_(n),"",w("\u5DF2\u6709\u4F1A\u8BDD\u4E0D\u53D8\u3002\u82E5\u5F53\u524D\u804A\u5929\u5DF2\u6709\u4F1A\u8BDD\uFF0C\u8BF7\u5148\u53D1\u9001 /new\uFF0C\u518D\u53D1\u9001\u666E\u901A\u6D88\u606F\uFF0C\u624D\u4F1A\u4F7F\u7528\u65B0\u8BBE\u7F6E\u521B\u5EFA\u4F1A\u8BDD\u3002")].join(` `)}function yY(n,{create:t=!1}={}){if((typeof n!="object"||n===null)&&typeof n!="function")return null;let o=uY.get(n);return!o&&t&&(o=new Map,uY.set(n,o)),o??null}function Mde(n,t){for(let[o,i]of n)i.expiresAt<=t&&n.delete(o)}function _de(n,t,o){let i=yY(n,{create:!0});if(!i)return;let e=Date.now();for(Mde(i,e),i.delete(t),i.set(t,{expiresAt:e+Qde,ids:o.map(a=>a.id)});i.size>yde;){let a=i.keys().next();if(a.done)break;i.delete(a.value)}}function Tde(n,t){let o=yY(n),i=o?.get(t);return!o||!i?null:i.expiresAt<=Date.now()?(o.delete(t),null):(o.delete(t),o.set(t,i),i.ids)}function Nde(n,t,o){if(!/^\d+$/u.test(o))return{numeric:!1,id:null};let i=Number(o);if(!Number.isSafeInteger(i)||i<1)return{numeric:!0,error:w("Agent Preset \u5E8F\u53F7\u65E0\u6548\uFF0C\u8BF7\u5148\u6267\u884C /presetlist\u3002")};let e=Tde(n,t);if(!e)return{numeric:!0,error:w("\u8BF7\u5148\u6267\u884C /presetlist\uFF0C\u518D\u6309\u5217\u8868\u5E8F\u53F7\u9009\u62E9 Agent Preset\u3002")};let a=e[i-1];return a?{numeric:!0,id:a}:{numeric:!0,error:w("Agent Preset \u5E8F\u53F7\u4E0D\u5B58\u5728\uFF0C\u8BF7\u91CD\u65B0\u6267\u884C /presetlist\u3002")}}function Rde(n){return n?.code??n?.failure?.code}function I_(n,t){let o=Rde(n);return o==="agent-preset-invalid"?w(`Agent Preset ID \u683C\u5F0F\u65E0\u6548\u3002 {usage}`,{usage:w(l_)}):o==="agent-preset-unavailable"?w("Agent Preset \u4E0D\u5B58\u5728\u6216\u5F53\u524D\u4E0D\u53EF\u7528\uFF0C\u8BF7\u91CD\u65B0\u6267\u884C /presetlist\u3002"):o===Ga||o==="workspace-bot-not-found"?w("\u5DE5\u4F5C\u533A\u6216\u673A\u5668\u4EBA\u72B6\u6001\u5DF2\u53D1\u751F\u53D8\u5316\uFF0C\u8BF7\u91CD\u8BD5\u3002"):o==="cancelled"||n?.name==="AbortError"?t==="list"?w("\u83B7\u53D6 Agent Preset \u5217\u8868\u5DF2\u53D6\u6D88\u3002"):t==="current"?w("\u83B7\u53D6 Agent Preset \u8BBE\u7F6E\u5DF2\u53D6\u6D88\u3002"):w("Agent Preset \u4FEE\u6539\u5DF2\u53D6\u6D88\u3002"):t==="list"?w("\u6682\u65F6\u65E0\u6CD5\u83B7\u53D6 Agent Preset \u5217\u8868\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002"):t==="current"?w("\u6682\u65F6\u65E0\u6CD5\u83B7\u53D6 Agent Preset \u8BBE\u7F6E\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002"):w("Agent Preset \u4FEE\u6539\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002")}async function BY(n,t){if(typeof n?.agentPresetSettings!="function")throw new TypeError("Harness does not support Agent Preset settings");return QY(await n.agentPresetSettings(t))}async function kde(n,t,o){if(typeof n?.updateAgentPreset!="function")throw new TypeError("Harness does not support updating Agent Preset settings");return QY(await n.updateAgentPreset(t,o))}function gi(n){if(typeof n!="string")return!1;let t=n.trim();return fY.test(t)||ude.test(t)}async function _i(n,t,o,i,e={}){if(!gi(n))return null;let a=n.trim();if(e.hasImages)return Cn(w("Agent Preset \u547D\u4EE4\u4EC5\u652F\u6301\u7EAF\u6587\u5B57\uFF0C\u8BF7\u79FB\u9664\u56FE\u7247\u540E\u91CD\u8BD5\u3002"));let A=Sde(e.signal);if(fY.test(a)){if(!/^\/(?:presetlist|presets)[ \t]*$/iu.test(a))return Cn(w(Bde));try{let c=await BY(t,A);return _de(o,i,c.agentPresetCatalog.items),Cn(Ode(c))}catch(c){return Cn(I_(c,"list"))}}let r=/^\/preset(?:[ \t]+([^\s]+))?[ \t]*$/iu.exec(a);if(!r)return Cn(w(l_));let s=r[1];if(!s)try{return Cn(Dde(await BY(t,A)))}catch(c){return Cn(I_(c,"current"))}let g;if(s.toLowerCase()==="--default")g=null;else{let c=/^id:(\d+)$/iu.exec(s);if(c)g=c[1];else{let I=Nde(o,i,s);if(I.numeric){if(I.error)return Cn(I.error);g=I.id}else if(g=ng(s),!g)return Cn(w(`Agent Preset ID \u683C\u5F0F\u65E0\u6548\u3002 -{usage}`,{usage:w(l_)}))}}try{return await ag(o,i,async()=>Cn(bde(await kde(t,g,A))))}catch(c){return Cn(I_(c,"update"))}}var mY=Object.freeze(["channel","conversationType","senderId","senderName","botId"]),SY=8e3;var h_=Object.freeze({group:Object.freeze({enabled:!1,fields:Object.freeze(["senderId"]),guidance:""}),direct:Object.freeze({enabled:!1,fields:Object.freeze(["senderId"]),guidance:""})}),vde=["group","direct"],Pde=["enabled","fields","guidance"],Gde=["groupEnabled","directEnabled","fields","guidance"],Fde=new Set(["wecom","weixin","feishu","dingtalk","qq","slack","telegram","discord","whatsapp"]),Lde={channel:16,conversationType:6,senderId:256,senderName:256,botId:128},Ude=/[\u0000-\u001f\u007f-\u009f\u202a-\u202e\u2066-\u2069]/g;function Np(n){let t=new TypeError(n);return t.code="context-enhancement-invalid",t}function E_(n,t){return n&&typeof n=="object"&&!Array.isArray(n)&&[Object.prototype,null].includes(Object.getPrototypeOf(n))&&Reflect.ownKeys(n).length===t.length&&t.every(o=>Object.hasOwn(n,o))}function wY(n){if(!E_(n,Pde))throw Np("\u8BF7\u63D0\u4EA4\u5B8C\u6574\u7684\u4E0A\u4E0B\u6587\u589E\u5F3A\u8BBE\u7F6E\u3002");let{enabled:t,fields:o,guidance:i}=n;if(typeof t!="boolean")throw Np("\u7FA4\u804A\u548C\u79C1\u804A\u5F00\u5173\u5FC5\u987B\u662F\u5E03\u5C14\u503C\u3002");if(!Array.isArray(o)||![...o].every(e=>mY.includes(e)))throw Np("\u6765\u6E90\u5B57\u6BB5\u53EA\u80FD\u9009\u62E9\u5DF2\u5B9A\u4E49\u7684\u4E94\u4E2A\u5B57\u6BB5\u3002");if(typeof i!="string"||i.length>SY)throw Np(`\u589E\u5F3A\u63D0\u793A\u8BCD\u4E0D\u5F97\u8D85\u8FC7 ${SY} \u4E2A\u5B57\u7B26\u3002`);return Object.freeze({enabled:t,fields:Object.freeze(mY.filter(e=>o.includes(e))),guidance:i.trim()?i:""})}function kI(n){if(!E_(n,vde))throw Np("\u8BF7\u63D0\u4EA4\u5B8C\u6574\u7684\u4E0A\u4E0B\u6587\u589E\u5F3A\u8BBE\u7F6E\u3002");return Object.freeze({group:wY(n.group),direct:wY(n.direct)})}function Hde(n){if(!E_(n,Gde))throw Np("\u8BF7\u63D0\u4EA4\u5B8C\u6574\u7684\u4E0A\u4E0B\u6587\u589E\u5F3A\u8BBE\u7F6E\u3002");return kI({group:{enabled:n.groupEnabled,fields:n.fields,guidance:n.guidance},direct:{enabled:n.directEnabled,fields:n.fields,guidance:n.guidance}})}function Rp(n){try{return kI(n)}catch{try{return Hde(n)}catch{return h_}}}function Aa(n,t){if(t!=="group"&&t!=="direct")return null;try{let o=n?.getSettings?.(),i=t==="group"?"groupEnabled":"directEnabled";if((Object.hasOwn(o??{},t)?o?.[t]?.enabled:o?.[i])!==!0)return null;let A=Rp(o)[t];return A.enabled!==!0?null:Object.freeze({config:A,botId:n.botId,conversationType:t})}catch{return null}}function Kde(n,t){if(t==="senderId"&&(typeof n=="bigint"||Number.isFinite(n))&&(n=String(n)),typeof n!="string")return;let o=n.replace(Ude,"").trim().slice(0,Lde[t]);if(!(!o||t==="channel"&&!Fde.has(o)))return o}function xde(n,t){let{fields:o}=n.config,e=o.some(r=>["channel","senderId","senderName"].includes(r))?t?.():null,a={};for(let r of o){let s=r==="botId"||r==="conversationType"?n[r]:e?.[r],g=Kde(s,r);g!==void 0&&(a[r]=g)}return Object.keys(a).length===0?"":`${JSON.stringify(a).replace(/[<>&]/g,r=>({"<":"\\u003c",">":"\\u003e","&":"\\u0026"})[r])}`}function Yde(n){return n.trim()?` +{usage}`,{usage:w(l_)}))}}try{return await ag(o,i,async()=>Cn(bde(await kde(t,g,A))))}catch(c){return Cn(I_(c,"update"))}}var mY=Object.freeze(["channel","conversationType","senderId","senderName","conversationTitle","botId"]),SY=8e3;var h_=Object.freeze({group:Object.freeze({enabled:!1,fields:Object.freeze(["senderId"]),guidance:""}),direct:Object.freeze({enabled:!1,fields:Object.freeze(["senderId"]),guidance:""})}),vde=["group","direct"],Pde=["enabled","fields","guidance"],Gde=["groupEnabled","directEnabled","fields","guidance"],Fde=new Set(["wecom","weixin","feishu","dingtalk","qq","slack","telegram","discord","whatsapp"]),Lde={channel:16,conversationType:6,senderId:256,senderName:256,conversationTitle:256,botId:128},Ude=/[\u0000-\u001f\u007f-\u009f\u202a-\u202e\u2066-\u2069]/g;function Np(n){let t=new TypeError(n);return t.code="context-enhancement-invalid",t}function E_(n,t){return n&&typeof n=="object"&&!Array.isArray(n)&&[Object.prototype,null].includes(Object.getPrototypeOf(n))&&Reflect.ownKeys(n).length===t.length&&t.every(o=>Object.hasOwn(n,o))}function wY(n){if(!E_(n,Pde))throw Np("\u8BF7\u63D0\u4EA4\u5B8C\u6574\u7684\u4E0A\u4E0B\u6587\u589E\u5F3A\u8BBE\u7F6E\u3002");let{enabled:t,fields:o,guidance:i}=n;if(typeof t!="boolean")throw Np("\u7FA4\u804A\u548C\u79C1\u804A\u5F00\u5173\u5FC5\u987B\u662F\u5E03\u5C14\u503C\u3002");if(!Array.isArray(o)||![...o].every(e=>mY.includes(e)))throw Np("\u6765\u6E90\u5B57\u6BB5\u53EA\u80FD\u9009\u62E9\u5DF2\u5B9A\u4E49\u7684\u516D\u4E2A\u5B57\u6BB5\u3002");if(typeof i!="string"||i.length>SY)throw Np(`\u589E\u5F3A\u63D0\u793A\u8BCD\u4E0D\u5F97\u8D85\u8FC7 ${SY} \u4E2A\u5B57\u7B26\u3002`);return Object.freeze({enabled:t,fields:Object.freeze(mY.filter(e=>o.includes(e))),guidance:i.trim()?i:""})}function kI(n){if(!E_(n,vde))throw Np("\u8BF7\u63D0\u4EA4\u5B8C\u6574\u7684\u4E0A\u4E0B\u6587\u589E\u5F3A\u8BBE\u7F6E\u3002");return Object.freeze({group:wY(n.group),direct:wY(n.direct)})}function Hde(n){if(!E_(n,Gde))throw Np("\u8BF7\u63D0\u4EA4\u5B8C\u6574\u7684\u4E0A\u4E0B\u6587\u589E\u5F3A\u8BBE\u7F6E\u3002");return kI({group:{enabled:n.groupEnabled,fields:n.fields,guidance:n.guidance},direct:{enabled:n.directEnabled,fields:n.fields,guidance:n.guidance}})}function Rp(n){try{return kI(n)}catch{try{return Hde(n)}catch{return h_}}}function Aa(n,t){if(t!=="group"&&t!=="direct")return null;try{let o=n?.getSettings?.(),i=t==="group"?"groupEnabled":"directEnabled";if((Object.hasOwn(o??{},t)?o?.[t]?.enabled:o?.[i])!==!0)return null;let A=Rp(o)[t];return A.enabled!==!0?null:Object.freeze({config:A,botId:n.botId,conversationType:t})}catch{return null}}function Kde(n,t){if(t==="senderId"&&(typeof n=="bigint"||Number.isFinite(n))&&(n=String(n)),typeof n!="string")return;let o=n.replace(Ude,"").trim().slice(0,Lde[t]);if(!(!o||t==="channel"&&!Fde.has(o)))return o}function xde(n,t){let{fields:o}=n.config,e=o.some(r=>["channel","senderId","senderName","conversationTitle"].includes(r))?t?.():null,a={};for(let r of o){let s=r==="botId"||r==="conversationType"?n[r]:e?.[r],g=Kde(s,r);g!==void 0&&(a[r]=g)}return Object.keys(a).length===0?"":`${JSON.stringify(a).replace(/[<>&]/g,r=>({"<":"\\u003c",">":"\\u003e","&":"\\u0026"})[r])}`}function Yde(n){return n.trim()?` ${n.replace(/<\/?dsh_im_source_guidance\b[^>]*(?:>|$)/gi,o=>o.replace(//g,">"))} `:""}function To(n,t,o){if(!t)return n;try{let i=[xde(t,o),Yde(t.config.guidance)].filter(Boolean);if(i.length===0)return n;let e=i.join(` @@ -218,7 +218,7 @@ ${o}`);return[w("\u4EE5\u4E0B\u662F\u7528\u6237\u901A\u8FC7\u6279\u91CF\u8F93\u5 ${o}`:o}function ko(n){return n instanceof Ro?n.userMessage:null}import{createHash as FY,randomUUID as LY}from"node:crypto";import{constants as KE}from"node:fs";import{copyFile as ahe,lstat as RY,mkdtemp as ihe,open as UY,realpath as ohe,unlink as HY}from"node:fs/promises";import{tmpdir as nhe}from"node:os";import{basename as she,extname as ghe,isAbsolute as che,join as KY,resolve as Ihe}from"node:path";var OQ="dsh_im_return_file",DQ="dsh-im-outbound-artifact",B_=64*1024,lhe=new Map([[".csv","text/csv"],[".doc","application/msword"],[".docx","application/vnd.openxmlformats-officedocument.wordprocessingml.document"],[".gif","image/gif"],[".html","text/html"],[".jpeg","image/jpeg"],[".jpg","image/jpeg"],[".json","application/json"],[".md","text/markdown"],[".pdf","application/pdf"],[".png","image/png"],[".rar","application/vnd.rar"],[".txt","text/plain"],[".webp","image/webp"],[".xls","application/vnd.ms-excel"],[".xlsx","application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"],[".xml","application/xml"],[".zip","application/zip"]]),cg=new WeakMap,xY=new WeakMap,xE=new WeakMap,kY;function phe(){return kY??=ihe(KY(nhe(),"dsh-im-outbound-")),kY}function gg(n,t){let o=new Error(t);return o.code=n,o}function vY(n){let t=n?.session?.events;if(!Array.isArray(t))return null;let o=null;for(let i of t)i?.type==="turn/start"?o=Number.isInteger(i.data?.turn)?i.data.turn:null:i?.type==="turn/end"&&i.data?.turn===o&&(o=null);return Number.isInteger(o)&&o>=0?o:null}function PY(n){let t=n?.id??n?.header?.id;return typeof t=="string"&&t?t:null}function sg(n,t){return`${n}\0${t}`}function GY(n,t){return`${n}\0${t}`}function dhe(n){let t=String(n??"").replace(/[\u0000-\u001f\u007f]/g," ").replace(new RegExp("\\p{Cf}","gu"),"").replace(/\s+/g," ").trim();return t?[...t].slice(0,255).join(""):"result.bin"}function hhe(n){return lhe.get(ghe(n).toLowerCase())??"application/octet-stream"}function Ehe(n){return FY("sha256").update(n).digest("hex")}function Che(n,t){return typeof n?.dev=="bigint"&&typeof n?.ino=="bigint"&&typeof n?.size=="bigint"&&typeof n?.mtimeNs=="bigint"&&typeof n?.ctimeNs=="bigint"&&n.dev===t?.dev&&n.ino===t?.ino&&n.size===t?.size&&n.mtimeNs===t?.mtimeNs&&n.ctimeNs===t?.ctimeNs}async function uhe(n,t){let o;try{o=await UY(n,KE.O_RDONLY);let i=FY("sha256"),e=o.createReadStream({autoClose:!1,highWaterMark:B_,...t?{signal:t}:{}});for await(let a of e)t?.throwIfAborted(),i.update(a);return i.digest("hex")}finally{await o?.close().catch(()=>{})}}async function Bhe(n,t,{signal:o,errorCode:i="artifact-changed",errorMessage:e="The result file changed while it was being read."}={}){let a=()=>gg(i,e);if(!Number.isSafeInteger(t)||t<0)throw a();o?.throwIfAborted();let A;try{A=Buffer.allocUnsafe(t)}catch{throw a()}if(typeof n?.createReadStream=="function"){let g=n.createReadStream({autoClose:!1,start:0,end:t,highWaterMark:B_,...o?{signal:o}:{}}),c=0;for await(let I of g){o?.throwIfAborted();let d=Buffer.isBuffer(I)?I:Buffer.from(I);if(c+d.length>t)throw a();d.copy(A,c),c+=d.length}if(c!==t)throw a();return A}let r=0;for(;rg)throw a();r+=I}o?.throwIfAborted();let s=Buffer.allocUnsafe(1);if((await n.read(s,0,1,t))?.bytesRead!==0)throw a();return A}async function fhe(n,t,o){o?.throwIfAborted();let i;try{let e=che(t)?t:Ihe(n,t),a=await ohe(e);if(!(await RY(a,{bigint:!0})).isFile())throw gg("artifact-not-file","The requested path is not a file.");let r=await phe();i=KY(r,`${LY()}.artifact`),await ahe(a,i,KE.COPYFILE_EXCL),o?.throwIfAborted();let s=await RY(i,{bigint:!0}),g=Number(s.size);if(!s.isFile()||!Number.isSafeInteger(g)||g<0)throw gg("artifact-unavailable","The file could not be prepared for delivery.");let c=dhe(she(e));return Object.freeze({fileName:c,mediaType:hhe(c),size:g,digest:await uhe(i,o),storagePath:i})}catch(e){throw i&&await HY(i).catch(()=>{}),e?.code?.startsWith?.("artifact-")?e:o?.aborted?o.reason??e:gg("artifact-unavailable","The requested file is unavailable.")}}function YY(n){return Object.freeze({artifactId:n.artifactId,fileName:n.fileName,size:n.size})}function wQ(n){return n.artifactId}function As(n){let t=cg.get(n);if(!t)return;if(t.releaseRequested=!0,t.materializing>0){t.cleanupRequested=!0;return}let o=[...xE.get(n)??[]];if(o.length>0){t.cleanupDeferred||(t.cleanupDeferred=!0,Promise.allSettled(o).finally(()=>{t.cleanupDeferred=!1,As(n)}));return}cg.delete(n),xE.delete(n),t.onCleanup?.(),HY(t.path).catch(()=>{})}var f_=class{#e=new Map;#A=new Map;#t=new Map;#r=new Map;#l=new Map;#o=new Map;#i=new Map;#a=new Map;#n;constructor({uuid:t=LY}={}){if(typeof t!="function")throw new TypeError("uuid must be a function");this.#n=t}openConsumer(t,o){if(typeof t!="string"||!t||typeof o!="string"||!o)throw new TypeError("sessionId and promptRpcId are required");let i=GY(t,o),e={sessionId:t,promptRpcId:o,turn:null,released:!1};return this.#o.set(i,e),()=>{if(!e.released&&(e.released=!0,this.#o.get(i)===e&&this.#o.delete(i),e.turn!==null)){let a=sg(t,e.turn);this.#i.get(a)===e&&this.#i.delete(a),this.discard(t,e.turn)}}}observeSessionEvent(t,o){let i=PY(t);if(!i||!o||typeof o!="object")return;if(o.type==="turn/start"){let A=o.data?.turn;Number.isInteger(A)&&A>=0&&this.#a.set(i,A);return}if(o.type==="user/message"){let A=o.data?.source?.rpcId,r=this.#a.get(i)??vY({session:t});if(typeof A!="string"||!A||!Number.isInteger(r))return;this.#a.set(i,r);let s=this.#o.get(GY(i,A));if(!s||s.released)return;s.turn=r,this.#i.set(sg(i,r),s);return}if(o.type!=="turn/end")return;let e=o.data?.turn;if(!Number.isInteger(e)||e<0)return;this.#a.get(i)===e&&this.#a.delete(i);let a=this.#i.get(sg(i,e));(!a||a.released)&&this.discard(i,e)}disposeSession(t){let o=PY(t);if(!o)return;let i=`${o}\0`,e=new Set;for(let a of[this.#e,this.#A])for(let[A,r]of a)if(A.startsWith(i)){for(let s of r.values())e.add(s);a.delete(A)}for(let[a,A]of this.#o)a.startsWith(i)&&(A.released=!0,this.#o.delete(a));for(let a of this.#i.keys())a.startsWith(i)&&this.#i.delete(a);this.#a.delete(o);for(let a of e)As(a)}async stage(t,o){let i=t?.path;if(typeof i!="string"||!i.trim())throw new TypeError("A file path is required.");let e=o?.agent,a=e?.session?.header?.id,A=e?.session?.header?.cwd,r=vY(e);if(typeof a!="string"||!a||typeof A!="string"||!A||r===null)throw gg("artifact-context-required","A live Harness Session is required to return a file.");let s=await fhe(A,i,o?.signal),{storagePath:g,...c}=s,I=Object.freeze({kind:DQ,schemaVersion:1,artifactId:this.#n(),deliveryKey:this.#n(),...c,source:"managed-temp",registeredBy:Object.freeze({kind:"tool-result",eventId:typeof o?.callId=="string"?o.callId:"unknown",toolName:OQ}),origin:Object.freeze({sessionId:a,turn:r,callId:typeof o?.callId=="string"?o.callId:null}),createdAt:Date.now()});cg.set(I,{path:g,materializing:0,materialized:!1,releaseRequested:!1,cleanupRequested:!1,cleanupDeferred:!1,onCleanup:()=>this.#c(I)});let d=sg(a,r),B=this.#A.get(d);return B||(B=new Map,this.#A.set(d,B)),B.set(wQ(I),I),I}commit(t){if(t?.kind!==DQ||!cg.has(t))return null;let o=sg(t.origin.sessionId,t.origin.turn),i=wQ(t),e=this.#A.get(o);if(e?.get(i)!==t)return null;e.delete(i),e.size===0&&this.#A.delete(o);let a=this.#e.get(o);return a||(a=new Map,this.#e.set(o,a)),a.set(i,t),YY(t)}release(t){if(t?.kind!==DQ)return;let o=sg(t.origin.sessionId,t.origin.turn),i=wQ(t),e=this.#A.get(o);e?.get(i)===t&&e.delete(i),e?.size===0&&this.#A.delete(o),As(t)}take(t,o,{signal:i}={}){let e=sg(t,o),a=this.#e.get(e);if(this.#e.delete(e),!a)return[];if(i?.aborted){for(let s of a.values())As(s);return[]}let A=this.#t.get(e)??new Map;this.#t.set(e,A);let r=[];for(let[s,g]of a)cg.has(g)&&(A.set(s,g),r.push(g));if(A.size===0)this.#t.delete(e);else if(!this.#s(e,i))return[];return r}discard(t,o){if(typeof t!="string"||!Number.isInteger(o))return;let i=sg(t,o),e=new Set([...this.#e.get(i)?.values()??[],...this.#A.get(i)?.values()??[]]);this.#e.delete(i),this.#A.delete(i);for(let a of e)As(a)}clear(){let t=new Set;for(let o of this.#e.values())for(let i of o.values())t.add(i);for(let o of this.#A.values())for(let i of o.values())t.add(i);for(let o of this.#t.values())for(let i of o.values())t.add(i);for(let o of t)As(o);this.#e.clear(),this.#A.clear(),this.#t.clear();for(let o of this.#r.keys())this.#p(o);for(let o of this.#o.values())o.released=!0;this.#o.clear(),this.#i.clear(),this.#a.clear()}#s(t,o){if(!o)return!0;this.#p(t);let i=this.#l.get(o);return i||(i={turnKeys:new Set,onAbort:null},i.onAbort=()=>{for(let e of[...i.turnKeys])for(let a of this.#t.get(e)?.values()??[])As(a)},this.#l.set(o,i),o.addEventListener("abort",i.onAbort,{once:!0})),i.turnKeys.add(t),this.#r.set(t,o),o.aborted?(i.onAbort(),!1):!0}#p(t){let o=this.#r.get(t);if(!o)return;this.#r.delete(t);let i=this.#l.get(o);i?.turnKeys.delete(t),i?.turnKeys.size===0&&(o.removeEventListener("abort",i.onAbort),this.#l.delete(o))}#c(t){let o=sg(t.origin.sessionId,t.origin.turn),i=wQ(t),e=this.#e.get(o);e?.get(i)===t&&e.delete(i),e?.size===0&&this.#e.delete(o);let a=this.#A.get(o);a?.get(i)===t&&a.delete(i),a?.size===0&&this.#A.delete(o);let A=this.#t.get(o);A?.get(i)===t&&A.delete(i),A?.size===0&&(this.#t.delete(o),this.#p(o))}},vI=new f_;function Qhe({registry:n=vI}={}){let t=new WeakMap,o=new Map,i=(A,r)=>{let s=o.get(A);s||(s={artifacts:[]},o.set(A,s)),s.artifacts.push(r)},e=Object.freeze({name:OQ,description:"Send a readable file or generated image to the user through the current conversation. Existing and newly created files are both valid.",parameters:{type:"object",additionalProperties:!1,properties:{path:{type:"string",description:"Absolute path, or a path relative to the current workspace."}},required:["path"]},output:{schema:{type:"object",additionalProperties:!1,properties:{artifactId:{type:"string"},fileName:{type:"string"},size:{type:"number"}},required:["artifactId","fileName","size"]},render:(A,r)=>[{type:"text",text:`Registered ${r.fileName} (${r.size} bytes) for IM delivery.`}]},async execute(A,r){let s=await n.stage(A,r);return t.set(r,s),YY(s)}});return Object.freeze({definition:e,onResult:(A,r)=>{if(A?.name===OQ){let g=t.get(A);if(!g)return;if(t.delete(A),r?.isError){n.release(g);return}A.parent===void 0?n.commit(g):i(A.parent,g);return}let s=o.get(A?.token);if(s){if(o.delete(A.token),r?.isError){for(let g of s.artifacts)n.release(g);return}if(A.parent!==void 0){for(let g of s.artifacts)i(A.parent,g);return}for(let g of s.artifacts)n.commit(g)}}})}function Q_(n,{registry:t=vI}={}){if(typeof n?.tools?.register!="function"||typeof n?.systemPrompt?.section!="function"||typeof n?.on!="function")return!1;let o=Qhe({registry:t});return n.tools.register(o.definition),n.on("tools/result",o.onResult),n.on("session/event",(i,e)=>t.observeSessionEvent(i,e)),n.on("session/disposed",i=>t.disposeSession(i)),n.systemPrompt.section({name:"dsh-im:return-file",order:115,text:`When the user asks to receive a file or generated image, call ${OQ} with its path. Existing files can be sent directly; do not recreate or rename a file solely for delivery.`}),!0}async function jY(n,{signal:t}={}){if(t?.aborted&&(As(n),t.throwIfAborted()),n?.kind!==DQ||n.schemaVersion!==1||!cg.has(n)||typeof n.digest!="string"||!Number.isSafeInteger(n.size)||n.size<0)throw gg("artifact-invalid","The file registration is invalid.");let o=cg.get(n);o.materializing+=1;let i,e=!1;try{let a=Number.isInteger(KE.O_NOFOLLOW)?KE.O_NOFOLLOW:0;i=await UY(o.path,KE.O_RDONLY|a);let A=await i.stat({bigint:!0});if(!A.isFile()||A.size!==BigInt(n.size))throw gg("artifact-invalid","The file registration is invalid.");let r=await Bhe(i,n.size,{signal:t,errorCode:"artifact-invalid",errorMessage:"The file registration is invalid."}),s=await i.stat({bigint:!0});if(!Che(A,s)||r.byteLength!==n.size||Ehe(r)!==n.digest)throw gg("artifact-invalid","The file registration is invalid.");t?.throwIfAborted(),e=!0;let g=Object.freeze({artifactId:n.artifactId,deliveryKey:n.deliveryKey,fileName:n.fileName,mediaType:n.mediaType,size:n.size,bytes:r});return xY.set(g,n),o.materialized=!0,g}catch(a){throw a?.code?.startsWith?.("artifact-")?a:t?.aborted?t.reason??a:gg("artifact-invalid","The file registration is invalid.")}finally{await i?.close().catch(()=>{}),o.materializing-=1,(!e||o.cleanupRequested)&&As(n)}}function un(n,t){let o=xY.get(n);if(!o||!cg.has(o)||!t||typeof t.then!="function")return t;let i=xE.get(o)??new Set,e=Promise.resolve(t).then(()=>{},()=>{});return i.add(e),xE.set(o,i),e.finally(()=>{i.delete(e),i.size===0&&xE.delete(o)}),t}function y_(n){let t=cg.get(n);t&&(t.releaseRequested=!0),As(n)}var yhe=new Set(["sent","rejected","failed","unknown"]),mhe=new Set(["sent","failed","unknown"]),She=new Set(["plain","markdown"]),whe=new Set(["artifact-changed","artifact-context-required","artifact-empty","artifact-invalid","artifact-not-file","artifact-permission-required","artifact-provider-rejected","artifact-too-large","artifact-unavailable"]);function Ua(n){if(!n||typeof n!="object")return[];let t=Array.isArray(n.providerMessageIds)?n.providerMessageIds.filter(e=>typeof e=="string"&&e.trim()||Number.isSafeInteger(e)).map(String):[],i=[n.message_id,n.messageId,n.id,n.ts,n.message?.message_id,n.message?.messageId,n.message?.id,n.message?.ts,n.key?.id,n.data?.message_id,n.body?.msgid,n.body?.message_id].find(e=>typeof e=="string"&&e.trim()||Number.isSafeInteger(e));return i!==void 0&&t.push(String(i)),[...new Set(t)]}function vp(n,t){if(typeof n!="string"||!n.trim())throw new TypeError(`${t} must be a non-empty string`);return n}function ts(n,t="plain"){let o=typeof n=="string"?{kind:"text",text:n,format:t}:n;if(!o||typeof o!="object"||Array.isArray(o)||o.kind!=="text"||typeof o.text!="string"||!o.text.trim())throw new TypeError("text delivery block must contain non-empty text");if(!She.has(o.format))throw new TypeError("text delivery format must be plain or markdown");return Object.freeze({kind:"text",text:o.text,format:o.format})}function Dhe(n){if(!Array.isArray(n))throw new TypeError("providerMessageIds must be an array");let t=[],o=new Set;for(let i of n){let e=vp(i,"providerMessageId");o.has(e)||(o.add(e),t.push(e))}return Object.freeze(t)}function Ohe(n){if(!Array.isArray(n))throw new TypeError("artifacts must be an array");return Object.freeze(n.map(t=>{if(!t||typeof t!="object")throw new TypeError("artifact result must be an object");let o=vp(t.artifactId,"artifactId");if(!yhe.has(t.outcome))throw new TypeError("artifact outcome must be sent, rejected, failed, or unknown");let i=t.reason===void 0?void 0:vp(t.reason,"artifact reason");return Object.freeze({artifactId:o,outcome:t.outcome,...i===void 0?{}:{reason:i}})}))}function bhe(n){let t=typeof n=="string"?n:n?.code;return t==="artifact-delivery-uncertain"?"unknown":whe.has(t)?"rejected":"failed"}function Zt({deliveryId:n,presentation:t,providerMessageIds:o=[],artifacts:i=[],deliveryOutcome:e,reason:a}){if(e!==void 0&&!mhe.has(e))throw new TypeError("deliveryOutcome must be sent, failed, or unknown");let A=a===void 0?void 0:vp(a,"delivery reason");return Object.freeze({schemaVersion:1,deliveryId:vp(n,"deliveryId"),presentation:vp(t,"presentation"),providerMessageIds:Dhe(o),...e===void 0?{}:{deliveryOutcome:e},...A===void 0?{}:{reason:A},artifacts:Ohe(i)})}function JY({artifactId:n,deliveryId:t,error:o,presentation:i="text-fallback",providerMessageIds:e=[]}){let a=typeof o=="string"?o:o?.code,A=typeof a=="string"&&a?a:"artifact-provider-failed";return Zt({deliveryId:t,presentation:i,providerMessageIds:e,artifacts:[{artifactId:n,outcome:bhe(o),reason:A}]})}function qY({deliveryId:n,presentation:t,receipts:o}){if(!Array.isArray(o)||o.length===0)throw new TypeError("receipts must contain at least one delivery receipt");let i=[],e=new Map,a,A;for(let r of o){if(!r||r.schemaVersion!==1)throw new TypeError("receipt must use DeliveryReceipt schema version 1");i.push(...r.providerMessageIds??[]),a===void 0&&r.deliveryOutcome!==void 0&&(a=r.deliveryOutcome,A=r.reason);for(let s of r.artifacts??[])e.set(s.artifactId,s)}return Zt({deliveryId:n,presentation:t,providerMessageIds:i,deliveryOutcome:a,reason:A,artifacts:[...e.values()]})}function Mhe(){let n=new Error("Native file delivery is unavailable");return n.code="artifact-provider-unavailable",n}function m_(n,t){return t?.aborted||n?.name==="AbortError"||n?.code==="ABORT_ERR"}function zY(n){return Array.isArray(n)?[...new Set(n.filter(t=>typeof t=="string"&&t.trim()||Number.isSafeInteger(t)).map(String))]:Ua(n)}async function _he(n,{sendFile:t,sendImage:o,signal:i}){if(n.mediaType?.startsWith("image/")&&typeof o=="function")try{return{presentation:"image",result:await o(n)}}catch(e){if(m_(e,i)||e?.code==="artifact-delivery-uncertain")throw e}if(i?.throwIfAborted(),typeof t!="function")throw Mhe();return{presentation:"file",result:await t(n)}}async function vo({artifacts:n=[],baseReceipt:t=null,deliveryId:o,aggregatePresentation:i,alwaysMerge:e=!1,channelKey:a,signal:A,sendFile:r,sendImage:s,sendFailureNotice:g,onFailure:c,logger:I}){let d=t?[t]:[],B=!!t&&t.deliveryOutcome!=="failed",f=!1,Q=0,y=0,m=0;try{for(;m0&&(T=qY({deliveryId:o??t?.deliveryId??n[0]?.deliveryKey,presentation:i??`${a}-${t?"text-and-files":"files"}`,receipts:d})),{receipt:T,userVisible:B,failureNoticeVisible:f,artifactsSent:Q,artifactSendErrors:y}}var The=Object.freeze(["open","allowlist"]),Nhe=Object.freeze(["direct","group"]),VY=256,Rhe=["direct","group"],khe=["mode","open","allowlist"],vhe=["defaultCanExecuteCommands","commandPermissionOverrides"],Phe=["users"],Ghe=["id","canExecuteCommands"],Fhe=/[\u0000-\u001f\u007f-\u009f\u202a-\u202e\u2066-\u2069]/;function ro(n){let t=new TypeError(n);return t.code="access-policy-invalid",t}function YE(n,t){return n&&typeof n=="object"&&!Array.isArray(n)&&[Object.prototype,null].includes(Object.getPrototypeOf(n))&&Reflect.ownKeys(n).length===t.length&&t.every(o=>Object.hasOwn(n,o))}function $Y(n){if(typeof n=="number"){if(!Number.isFinite(n))throw ro("\u7528\u6237\u6807\u8BC6\u65E0\u6548\u3002");n=String(n)}else typeof n=="bigint"&&(n=String(n));if(typeof n!="string")throw ro("\u7528\u6237\u6807\u8BC6\u5FC5\u987B\u662F\u5B57\u7B26\u4E32\u3002");let t=n.trim();if(!t||t.length>VY||Fhe.test(t))throw ro(`\u7528\u6237\u6807\u8BC6\u4E0D\u80FD\u4E3A\u7A7A\u3001\u5305\u542B\u63A7\u5236\u5B57\u7B26\u6216\u8D85\u8FC7 ${VY} \u4E2A\u5B57\u7B26\u3002`);return t}function Lhe(n){if(!YE(n,Ghe))throw ro("\u7528\u6237\u6761\u76EE\u5FC5\u987B\u5305\u542B\u7528\u6237\u6807\u8BC6\u548C\u547D\u4EE4\u6743\u9650\u3002");if(typeof n.canExecuteCommands!="boolean")throw ro("\u547D\u4EE4\u6743\u9650\u5FC5\u987B\u662F\u5E03\u5C14\u503C\u3002");return Object.freeze({id:$Y(n.id),canExecuteCommands:n.canExecuteCommands})}function e1(n,{listMessage:t,duplicateMessage:o}){if(!Array.isArray(n))throw ro(t);let i=n.map(Lhe);if(new Set(i.map(({id:e})=>e)).size!==i.length)throw ro(o);return Object.freeze(i)}function Uhe(n){if(!YE(n,vhe))throw ro("\u5F00\u653E\u6A21\u5F0F\u8BBE\u7F6E\u5FC5\u987B\u5B8C\u6574\u3002");if(typeof n.defaultCanExecuteCommands!="boolean")throw ro("\u5F00\u653E\u6A21\u5F0F\u9ED8\u8BA4\u547D\u4EE4\u6743\u9650\u5FC5\u987B\u662F\u5E03\u5C14\u503C\u3002");return Object.freeze({defaultCanExecuteCommands:n.defaultCanExecuteCommands,commandPermissionOverrides:e1(n.commandPermissionOverrides,{listMessage:"\u5F00\u653E\u6A21\u5F0F\u547D\u4EE4\u6743\u9650\u8986\u76D6\u7528\u6237\u5FC5\u987B\u662F\u6570\u7EC4\u3002",duplicateMessage:"\u5F00\u653E\u6A21\u5F0F\u547D\u4EE4\u6743\u9650\u8986\u76D6\u7528\u6237\u4E0D\u80FD\u5305\u542B\u91CD\u590D\u7684\u7528\u6237\u6807\u8BC6\u3002"})})}function Hhe(n){if(!YE(n,Phe))throw ro("\u767D\u540D\u5355\u6A21\u5F0F\u8BBE\u7F6E\u5FC5\u987B\u5B8C\u6574\u3002");return Object.freeze({users:e1(n.users,{listMessage:"\u767D\u540D\u5355\u6A21\u5F0F\u7528\u6237\u5FC5\u987B\u662F\u6570\u7EC4\u3002",duplicateMessage:"\u767D\u540D\u5355\u6A21\u5F0F\u7528\u6237\u4E0D\u80FD\u5305\u542B\u91CD\u590D\u7684\u7528\u6237\u6807\u8BC6\u3002"})})}function S_(n){if(!YE(n,khe))throw ro("\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");if(!The.includes(n.mode))throw ro("\u8BBF\u95EE\u6A21\u5F0F\u53EA\u80FD\u662F open \u6216 allowlist\u3002");return Object.freeze({mode:n.mode,open:Uhe(n.open),allowlist:Hhe(n.allowlist)})}function Ic(n){if(!YE(n,Rhe))throw ro("\u8BF7\u540C\u65F6\u63D0\u4EA4\u5B8C\u6574\u7684\u79C1\u804A\u548C\u7FA4\u804A\u8BBF\u95EE\u8BBE\u7F6E\u3002");return Object.freeze({direct:S_(n.direct),group:S_(n.group)})}function Pp(n){try{return Ic(n)}catch{return null}}function bQ(n){return S_(n===void 0?{mode:"allowlist",open:{defaultCanExecuteCommands:!1,commandPermissionOverrides:[]},allowlist:{users:[]}}:n)}var WY=bQ(),ZY=Object.freeze({direct:WY,group:WY});function Ig({direct:n=ZY.direct,group:t=ZY.group}={}){return Ic({direct:n,group:t})}var Khe=Object.freeze({allowed:!0,reason:"allowed"}),xhe=Object.freeze({allowed:!1,reason:"policy-unavailable"}),XY=Object.freeze({allowed:!1,reason:"invalid-context"}),Yhe=Object.freeze({allowed:!1,reason:"sender-unavailable"}),jhe=Object.freeze({allowed:!1,reason:"sender-not-allowed"}),Jhe=Object.freeze({allowed:!1,reason:"command-not-allowed"});function A1(n,{conversationType:t,senderIds:o,isCommand:i=!1,equals:e=(a,A)=>a===A}={}){let a=Pp(n);if(!a)return xhe;if(!Nhe.includes(t)||typeof i!="boolean"||typeof e!="function")return XY;let A=(Array.isArray(o)?o:[o]).flatMap(c=>{try{return[$Y(c)]}catch{return[]}});if(A.length===0)return Yhe;let r=a[t],s=r.mode==="open"?r.open.commandPermissionOverrides:r.allowlist.users,g;try{g=s.filter(c=>A.some(I=>e(I,c.id)===!0))}catch{return XY}return r.mode==="allowlist"&&g.length===0?jhe:i&&!(r.mode==="open"?g.length>0?g.every(I=>I.canExecuteCommands):r.open.defaultCanExecuteCommands:g.every(I=>I.canExecuteCommands))?Jhe:Khe}var qhe=new Set(["/help","/status","/new"]);function MQ(n,{hasImages:t=!1,hasFiles:o=!1}={}){if(typeof n!="string")return!1;let i=n.trim();return i?Ni(i)||Fa(i)||!o&&(ni(i)||si(i)||gi(i))?!0:t||o?!1:qhe.has(i.toLowerCase())||a_(i)||e_(i):!1}var ao="\u4F60\u53EF\u4EE5\u53D1\u9001\u666E\u901A\u6D88\u606F\uFF0C\u4F46\u6CA1\u6709\u6267\u884C\u547D\u4EE4\u7684\u6743\u9650\u3002",zhe=Object.freeze({allowed:!0,reason:"policy-not-configured"}),Vhe=Object.freeze({allowed:!0,reason:"privileged-sender"});function Ba(n,{conversationType:t,senderIds:o,text:i="",hasImages:e=!1,hasFiles:a=!1,isCommand:A=MQ(i,{hasImages:e,hasFiles:a})}={}){if(!n)return zhe;try{if(typeof n.isPrivileged=="function"&&n.isPrivileged(o,t)===!0)return Vhe}catch{}let r=null;try{r=n.getSettings()}catch{}return A1(r,{conversationType:t,senderIds:o,isCommand:A,...typeof n.equals=="function"?{equals:n.equals}:{}})}var Whe="\u5DF2\u8FDE\u63A5 DeepSeek Harness\uFF0C\u6B63\u5728\u601D\u8003\u2026",w_="\u8FD9\u4E2A\u95EE\u9898\u5DF2\u5728\u5176\u4ED6\u5BA2\u6237\u7AEF\u5904\u7406\uFF0C\u65E0\u9700\u518D\u6B21\u56DE\u7B54\u3002",Zhe=["\u9489\u9489\u673A\u5668\u4EBA\u5DF2\u8FDE\u63A5 DeepSeek Harness\u3002","","\u76F4\u63A5\u53D1\u9001\u6587\u5B57\u3001\u56FE\u7247\u6216\u6587\u4EF6\u5373\u53EF\u7EE7\u7EED\u5F53\u524D\u4F1A\u8BDD\u3002","/new \u5F00\u542F\u4E00\u4E2A\u5168\u65B0\u4F1A\u8BDD","/compact \u538B\u7F29\u5F53\u524D\u4F1A\u8BDD\u7684\u8F83\u65E9\u4E0A\u4E0B\u6587","/history [\u6570\u91CF] \u67E5\u770B\u6700\u8FD1\u5386\u53F2\u6D88\u606F\uFF08\u9ED8\u8BA4 3 \u6761\uFF0C\u6700\u591A 5 \u6761\uFF09","/workspace \u5DE5\u4F5C\u533A\u5E8F\u53F7\u6216\u7EDD\u5BF9\u8DEF\u5F84 \u5207\u6362\u5DE5\u4F5C\u533A","/workspacelist \u5217\u51FA\u5DE5\u4F5C\u533A\u7EDD\u5BF9\u8DEF\u5F84","/sessionlist \u6216 /sessions [\u5DE5\u4F5C\u533A\u5E8F\u53F7\u6216\u7EDD\u5BF9\u8DEF\u5F84] \u5217\u51FA\u4F1A\u8BDD ID \u548C\u6807\u9898","/session Session ID \u6216\u5F53\u524D\u5DE5\u4F5C\u533A\u5E8F\u53F7 \u5C06\u5F53\u524D\u804A\u5929\u7ED1\u5B9A\u5230\u6307\u5B9A\u4F1A\u8BDD","/models \u6309\u5E8F\u53F7\u5217\u51FA\u6240\u6709\u53EF\u7528\u6A21\u578B","/reasoninglist \u6216 /reasonings \u6309\u5E8F\u53F7\u5217\u51FA\u5F53\u524D\u6A21\u578B\u53EF\u7528\u63A8\u7406\u7B49\u7EA7","/reasoning [\u5E8F\u53F7\u3001\u7B49\u7EA7ID\u6216 --default] \u67E5\u770B\u6216\u5207\u6362\u5F53\u524D\u63A8\u7406\u7B49\u7EA7","/model [\u5E8F\u53F7\u6216\u5B8C\u6574\u6A21\u578BID] [\u63A8\u7406\u7B49\u7EA7ID] \u67E5\u770B\u6216\u5207\u6362\u5F53\u524D\u4F1A\u8BDD\u6A21\u578B","\u793A\u4F8B\uFF1A\u5148\u53D1 /models\uFF0C\u518D\u53D1 /model 2 [\u63A8\u7406\u7B49\u7EA7ID]","/presetlist \u6216 /presets \u6309\u5E8F\u53F7\u5217\u51FA\u53EF\u7528 Agent Preset","/preset [\u5E8F\u53F7\u6216\u5B8C\u6574ID] \u67E5\u770B\u6216\u8BBE\u7F6E\u5F53\u524D\u673A\u5668\u4EBA Agent Preset","\u7EAF\u6570\u5B57 ID\uFF1A/preset id:","/preset --default \u8DDF\u968F Host \u9ED8\u8BA4","/stop \u505C\u6B62\u5F53\u524D\u4EFB\u52A1","/steer \u8865\u5145\u6307\u4EE4 \u7EA0\u504F\u5F53\u524D\u4EFB\u52A1","/batch \u5F00\u59CB\u6279\u91CF\u8F93\u5165\uFF08\u4EC5\u79C1\u804A\uFF0C\u6700\u591A 10 \u6761\u6587\u5B57\uFF09","/send \u63D0\u4EA4\u5F53\u524D\u6279\u6B21","/cancel \u53D6\u6D88\u5F53\u524D\u6279\u6B21","/status \u68C0\u67E5\u8FDE\u63A5\u72B6\u6001","/version \u67E5\u770B\u63D2\u4EF6\u7248\u672C","/help \u663E\u793A\u672C\u5E2E\u52A9"];function Xhe(){return Zhe.map(n=>w(n)).join(` `)}function mt(n){return typeof n=="string"&&n.trim()?n.trim():null}function $he(n){let t=Ua(n),o=mt(n?.processQueryKey);return o&&!t.includes(o)&&t.push(o),t}function _Q(n){let t=[],o=new Set,i=n;for(;i&&typeof i=="object"&&t.length<3&&!o.has(i);){o.add(i);let e=mt(i.name)?.slice(0,80),a=mt(i.code)?.slice(0,80),A=mt(i.providerCode)?.slice(0,160),r=Number.isInteger(i.status)?i.status:void 0;t.push({...e?{name:e}:{},...a?{code:a}:{},...A?{providerCode:A}:{},...r?{status:r}:{}}),i=i.cause}return t}function eEe(n){let t=n,o=new Set;for(;t&&typeof t=="object"&&!o.has(t);){if(o.add(t),t.code==="image-download-address-failed")return w("\u9489\u9489\u672A\u80FD\u6362\u53D6\u56FE\u7247\u4E0B\u8F7D\u5730\u5740\uFF0C\u8BF7\u91CD\u65B0\u53D1\u9001\uFF1B\u82E5\u6301\u7EED\u5931\u8D25\uFF0C\u8BF7\u68C0\u67E5\u673A\u5668\u4EBA\u7684\u201C\u4F01\u4E1A\u5185\u673A\u5668\u4EBA\u53D1\u9001\u6D88\u606F\u6743\u9650\u201D\u3002");if(t.code==="invalid-image-download")return w("\u9489\u9489\u6CA1\u6709\u8FD4\u56DE\u56FE\u7247\u4E0B\u8F7D\u5730\u5740\uFF0C\u8BF7\u91CD\u65B0\u53D1\u9001\u3002");if(t.code==="image-content-download-failed")return w("\u9489\u9489\u8FD4\u56DE\u7684\u56FE\u7247\u4E34\u65F6\u5730\u5740\u65E0\u6CD5\u8BFB\u53D6\uFF0C\u8BF7\u91CD\u65B0\u53D1\u9001\u3002");t=t.cause}return bo(n)}function t1(n){return mt(n?.senderStaffId)??mt(n?.senderId)}function AEe(n){if(n?.content&&typeof n.content=="object")return n.content;if(typeof n?.content!="string")return null;try{let t=JSON.parse(n.content);return t&&typeof t=="object"?t:null}catch{return null}}function tEe(n){let t=n?.richText??n?.rich_text;return Array.isArray(t)?t:[]}function rEe(n){return typeof n?.text=="string"?mt(n.text):typeof n?.text?.content=="string"?mt(n.text.content):String(n?.type).toLowerCase()==="text"&&typeof n?.content=="string"?mt(n.content):null}function D_(n){return mt(n?.downloadCode)??mt(n?.pictureDownloadCode)}function O_(n,{api:t,clientId:o,clientSecret:i}={}){let e=String(n?.msgtype??"").toLowerCase(),a=AEe(n),A=e==="richtext"?tEe(a):[],r=e==="text"?mt(n?.text?.content)??"":A.map(rEe).filter(Boolean).join(` -`),s=[];if(e==="picture"){let c=D_(a);c&&s.push(c)}else if(e==="richtext")for(let c of A){if(String(c?.type??"").toLowerCase()!=="picture")continue;let I=D_(c);I&&s.push(I)}let g=e==="file"?D_(a):null;return{content:r,images:s.map((c,I)=>({name:I===0?"image":`image-${I+1}`,load:({signal:d,maxBytes:B})=>{if(typeof t?.downloadImage!="function")throw new Error("DingTalk API does not support image downloads");return t.downloadImage({clientId:o,clientSecret:i,robotCode:n?.robotCode,downloadCode:c,signal:d,maxBytes:B})}})),files:g?[{name:mt(a?.fileName??a?.file_name)??"file",load:({signal:c}={})=>{if(typeof t?.downloadFile!="function")throw new Error("DingTalk API does not support file downloads");return t.downloadFile({clientId:o,clientSecret:i,robotCode:n?.robotCode,downloadCode:g,signal:c})}}]:[]}}function aEe(n,t){if(String(n?.conversationType)==="2"){let o=mt(n?.conversationId);if(!o)throw new Error("DingTalk group message has no conversation id");return`group:${o}`}return`p2p:${t}`}function iEe(n,t){return String(n?.conversationType)==="2"?{type:"group",openConversationId:mt(n?.conversationId),atUserIds:{[t]:mt(n?.senderNick)??t}}:{type:"user",userId:t}}function oEe(n,t,o){let i=mt(n?.robotCode)??o;return String(n?.conversationType)==="2"?{type:"group",openConversationId:mt(n?.conversationId),robotCode:i}:{type:"user",userId:t,robotCode:i}}function nEe(n,t){let o=String(n??w("\u7ED3\u679C\u6587\u4EF6")).replace(/[\r\n]+/g," ").trim()||w("\u7ED3\u679C\u6587\u4EF6");switch(t?.code){case"artifact-delivery-uncertain":return w("\u7ED3\u679C\u6587\u4EF6\u300C{name}\u300D\u53D1\u9001\u7ED3\u679C\u672A\u80FD\u786E\u8BA4\uFF0C\u8BF7\u5148\u68C0\u67E5\u804A\u5929\u5185\u662F\u5426\u5DF2\u6536\u5230\uFF0C\u4E0D\u8981\u7ACB\u5373\u91CD\u8BD5\u3002",{name:o});case"artifact-permission-required":return w("\u7ED3\u679C\u6587\u4EF6\u300C{name}\u300D\u5DF2\u751F\u6210\uFF0C\u4F46\u9489\u9489\u5E94\u7528\u6216\u673A\u5668\u4EBA\u7F3A\u5C11\u6587\u4EF6\u6D88\u606F\u6743\u9650\u3002\u8BF7\u5F00\u901A\u5E94\u7528 qyapi_base \u6743\u9650\uFF0C\u5E76\u786E\u8BA4\u673A\u5668\u4EBA\u5177\u5907\u6587\u4EF6\u6D88\u606F\u53D1\u9001\u80FD\u529B\u3002",{name:o});case"artifact-too-large":return w("\u7ED3\u679C\u6587\u4EF6\u300C{name}\u300D\u8D85\u8FC7\u5F53\u524D\u9489\u9489\u673A\u5668\u4EBA\u53EF\u53D1\u9001\u7684\u6587\u4EF6\u5927\u5C0F\uFF0C\u672A\u53D1\u9001\u3002",{name:o});case"artifact-rate-limited":return w("\u7ED3\u679C\u6587\u4EF6\u300C{name}\u300D\u6682\u65F6\u88AB\u9489\u9489\u9650\u6D41\uFF0C\u672A\u80FD\u53D1\u9001\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002",{name:o});case"artifact-provider-rejected":return w("\u7ED3\u679C\u6587\u4EF6\u300C{name}\u300D\u5DF2\u751F\u6210\uFF0C\u4F46\u9489\u9489\u62D2\u7EDD\u4E86\u8BE5\u6587\u4EF6\u6D88\u606F\uFF0C\u8BF7\u68C0\u67E5\u6587\u4EF6\u7C7B\u578B\u548C\u673A\u5668\u4EBA\u6587\u4EF6\u6D88\u606F\u914D\u7F6E\u3002",{name:o});case"artifact-invalid":case"artifact-changed":case"artifact-unavailable":return w("\u7ED3\u679C\u6587\u4EF6\u300C{name}\u300D\u6682\u65F6\u65E0\u6CD5\u8BFB\u53D6\u6216\u51C6\u5907\u53D1\u9001\uFF0C\u8BF7\u786E\u8BA4\u6587\u4EF6\u4ECD\u53EF\u8BBF\u95EE\u540E\u91CD\u8BD5\u3002",{name:o});default:return w("\u7ED3\u679C\u6587\u4EF6\u300C{name}\u300D\u5DF2\u751F\u6210\uFF0C\u4F46\u6682\u65F6\u672A\u80FD\u901A\u8FC7\u9489\u9489\u53D1\u9001\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002",{name:o})}}function sEe(n){return n?.type==="text"&&mt(n.text)?n.text:n?.type==="tool"?n.name==="web_search"?w("_\u6B63\u5728\u641C\u7D22\u7F51\u7EDC\u5E76\u6574\u7406\u4FE1\u606F\u2026_"):w("_\u6B63\u5728\u4F7F\u7528 {name}\u2026_",{name:mt(n.name)??w("\u5DE5\u5177")}):w("_{text}_",{text:mt(n?.text)??w("\u6B63\u5728\u5904\u7406\u2026")})}function gEe(n,t,o){if(t.needsPresentation||!t.questions[t.index]||t.actor!==o||String(n?.conversationType)==="2"&&n?.isInAtList!==!0||n?.msgtype!=="text"||!mt(n?.text?.content))return!1;try{return gc(n.sessionWebhook),!0}catch{return!1}}function cEe(n){n.stats??={};for(let t of["messagesReceived","messagesReplied","messagesRejected","messagesIgnored","reactionsAdded","reactionsRemoved","reactionErrors"])n[t]??=0,n.stats[t]=n[t];n.pendingSenders??=[]}function Lr(n,t){n[t]=(n[t]??0)+1,n.stats??={},n.stats[t]=n[t]}function b_({pendingSenders:n=[]}={}){return{messagesReceived:0,messagesReplied:0,messagesRejected:0,messagesIgnored:0,reactionsAdded:0,reactionsRemoved:0,reactionErrors:0,lastMessageAt:null,lastReplyAt:null,lastRejectedAt:null,lastError:null,lastMessageError:null,pendingSenders:structuredClone(n),stats:{messagesReceived:0,messagesReplied:0,messagesRejected:0,messagesIgnored:0,reactionsAdded:0,reactionsRemoved:0,reactionErrors:0}}}var TQ=class{#e;#A;#t;#r;#l;#o;#i;#a;#n;#s;#p;#c;#g;#I=new Map;#d=new Map;#h=new Map;#C=new Set;#u=new Set;#B=new Map;#f;#Q=new Ti;constructor({api:t,clientId:o,clientSecret:i,harness:e,state:a,contextEnhancement:A,accessPolicy:r,status:s=b_(),logger:g=console,replyTimeoutMs:c=6e5,reactionTimeoutMs:I=5e3,maxMessageChars:d=4e3,signal:B}){if(!t||typeof t.sendText!="function")throw new TypeError("DingTalk API is required");if(!mt(o)||!mt(i))throw new TypeError("DingTalk app credentials are required");if(!e||!a)throw new TypeError("Harness client and state store are required");this.#e=t,this.#A=o.trim(),this.#t=i.trim(),this.#r=e,this.#l=a,this.#o=A,this.#i=r,this.#a=s,this.#n=g,this.#f=new Di({label:"DingTalk",logger:g}),this.#s=c,this.#p=Number.isFinite(I)&&I>0?Math.floor(I):5e3,this.#c=d,this.#g=B,cEe(this.#a),this.#U()}get status(){return this.#U(),structuredClone(this.#a)}accept(t,{contextSnapshot:o}={}){if(this.#g?.aborted)return Promise.resolve();let i=mt(t?.msgId),e=t1(t);if(!i||!e||this.#l.hasSeen(i)||this.#B.has(i))return Promise.resolve();let a=String(t.conversationType)==="2"?"group":String(t.conversationType)==="1"?"direct":null,A;try{A=aEe(t,e)}catch{return Lr(this.#a,"messagesRejected"),this.#a.lastRejectedAt=new Date().toISOString(),Promise.resolve()}let r=null;try{r=gc(t.sessionWebhook)}catch{}let s=this.#d.get(A),g=O_(t,{api:this.#e,clientId:this.#A,clientSecret:this.#t}),c=mt(g.content)??"",I=String(t.conversationType)!=="2"||t?.isInAtList===!0,d=String(t.conversationType)!=="2";if(I){let _=Ba(this.#i,{conversationType:a,senderIds:e,text:c,hasImages:Tt(g),hasFiles:wt(g)});if(!_.allowed)return this.#B.set(i,null),this.#T(t,i,r,_)}this.#B.set(i,o===void 0?Aa(this.#o,a):o),r&&d&&So(this.#l,{sessionWebhook:r});let B=r&&I?this.#y(t):null,f=_=>Promise.resolve(_).then(R=>(this.#m(B,this.#g?.aborted?"clear":"success"),R),R=>{throw this.#m(B,this.#g?.aborted||R?.name==="AbortError"||R?.code==="turn-stopped"?"clear":"error"),R}),Q=String(t?.msgtype).toLowerCase()==="text"&&Ni(c),y=this.#Q.status(A);if(Q&&!d&&r&&I)return f(this.#N(i,r,{message:es()},B));if(d&&r&&(Q||y.phase==="collecting")){let R=/^\/batch$/iu.test(c)&&y.phase==="idle"&&(this.#I.has(A)||s||this.#f.hasPending(A))?{handled:!0,kind:"busy",message:No()}:this.#Q.handle(A,c,{plainText:!!c&&String(t?.msgtype).toLowerCase()==="text"&&!wt(g)&&!Tt(g)});if(R.handled)return R.kind==="submit"?f(this.#D({...t,msgtype:"text",text:{content:R.prompt}},i,e,A,{batchSubmission:R,statusReaction:B})):f(this.#N(i,r,R,B))}let m=Fa(c)?Ao:wt(g)?null:ni(c)?Mi:si(c)?to:gi(c)?_i:null;if(m&&r&&I){let _;return _=this.#E(t,i,A,r,g,m).catch(R=>{if(R?.code==="turn-stopped"||this.#g?.aborted){this.#m(B,"clear");return}this.#m(B,"error"),this.#a.lastError=R?.message??String(R);let K=At(this.#a,R);return this.#n.error?.(`[dsh-dingtalk] failed to process a command [${K.referenceId}]`,_Q(R)),this.#v(r,dt(K),this.#L(t)).catch(()=>{})}).finally(()=>{this.#B.delete(i),this.#u.delete(_)}),this.#u.add(_),f(_)}let T=this.#f.claimReply({key:A,actor:e,messageId:i,text:r&&t?.msgtype==="text"?mt(t?.text?.content)??"":"",addressed:String(t?.conversationType)!=="2"||t?.isInAtList===!0,hasPendingQuestion:!!s,questionCompletion:s?.submitting||s?.claimedReplyMessageId?s.queue:null,isQuestionPending:()=>this.#d.has(A),send:r?_=>this.#v(r,_,this.#L(t)):async()=>{}});if(T){let _;return _=T.process(async()=>this.#l.hasSeen(i)?!1:(await this.#l.markSeen(i),Lr(this.#a,"messagesReceived"),this.#a.lastMessageAt=new Date().toISOString(),r||(Lr(this.#a,"messagesRejected"),this.#a.lastRejectedAt=new Date().toISOString(),this.#a.lastError=w("\u9489\u9489\u6D88\u606F\u6CA1\u6709\u5B89\u5168\u7684\u56DE\u590D\u5730\u5740\u3002")),!0)).catch(R=>{if(this.#g?.aborted){this.#m(B,"clear");return}this.#m(B,"error"),this.#a.lastError=w("\u9489\u9489\u5BA1\u6279\u5904\u7406\u5931\u8D25\u3002"),this.#n.error?.("[dsh-dingtalk] failed to process an approval reply",R)}).finally(()=>{this.#B.delete(i),this.#C.delete(_)}),this.#C.add(_),f(_)}if(s&&s.actor!==e)return f(this.#D(t,i,e,A,{statusReaction:B}));if(s?.submitting||s?.claimedReplyMessageId)return f(this.#D(t,i,e,A,{statusReaction:B}));if(s){gEe(t,s,e)&&(s.claimedReplyMessageId=i);let R=(s.queue??Promise.resolve()).catch(()=>{}).then(()=>this.#w(t,i,e,A,s,B)).finally(()=>{this.#B.delete(i),s.claimedReplyMessageId===i&&(s.claimedReplyMessageId=null),s.queue===R&&(s.queue=null)});return s.queue=R,f(R)}return f(this.#D(t,i,e,A,{statusReaction:B}))}#S(t,o,i,e){let a=new AbortController,A=Promise.resolve().then(()=>this.#e[t]({clientId:this.#A,clientSecret:this.#t,...o,reactionName:i,signal:a.signal})),r,s=new Promise((g,c)=>{r=setTimeout(()=>{let I=new DOMException("DingTalk reaction timed out","TimeoutError");a.abort(I),c(I)},this.#p),r.unref?.()});return Promise.race([A,s]).then(()=>(Lr(this.#a,e==="add"?"reactionsAdded":"reactionsRemoved"),!0)).catch(g=>(Lr(this.#a,"reactionErrors"),this.#n.debug?.(`[dsh-dingtalk] ${t} failed`,_Q(g)),!1)).finally(()=>clearTimeout(r))}#y(t){if(typeof this.#e.addReaction!="function"||typeof this.#e.recallReaction!="function")return null;let o=mt(t?.msgId),i=mt(t?.conversationId);if(!o||!i)return null;let e={messageId:o,conversationId:i,robotCode:mt(t?.robotCode)??this.#A};return{target:e,attached:this.#S("addReaction",e,TI,"add"),terminal:!1}}#m(t,o){if(!t||t.terminal)return;t.terminal=!0;let i=o==="success"?wx:o==="error"?Dx:null;t.attached.then(async e=>{let a=await this.#S("recallReaction",t.target,TI,"remove");(!e||!a)&&(await new Promise(A=>{setTimeout(A,Math.min(1e3,this.#p)).unref?.()}),a=await this.#S("recallReaction",t.target,TI,"remove")||a),!(!a||!i||this.#g?.aborted)&&await this.#S("addReaction",t.target,i,"add")}).catch(()=>{})}#D(t,o,i,e,{releaseMessageId:a=!0,alreadyRecorded:A=!1,batchSubmission:r=null,statusReaction:s=null}={}){let g=!1;try{gc(t.sessionWebhook),g=!0}catch{}let c=String(t.conversationType)!=="2"||t.isInAtList===!0,I=g&&c?kp(O_(t,{api:this.#e,clientId:this.#A,clientSecret:this.#t}),{signal:this.#g}):void 0,B=(this.#I.get(e)??Promise.resolve()).catch(()=>{}).then(()=>this.#O(t,o,i,e,{alreadyRecorded:A,preparedMessage:I,batchSubmission:r,statusReaction:s})).finally(()=>{a&&this.#B.delete(o),this.#I.get(e)===B&&this.#I.delete(e)});return this.#I.set(e,B),B}async waitForIdle(){await Promise.allSettled([...this.#I.values(),...[...this.#d.values()].flatMap(t=>t.queue?[t.queue]:[]),...this.#C,...this.#u])}async#E(t,o,i,e,a,A){if(this.#g?.throwIfAborted(),this.#l.hasSeen(o))return;await this.#l.markSeen(o),Lr(this.#a,"messagesReceived"),this.#a.lastMessageAt=new Date().toISOString();let r=await A(mt(a.content)??"",this.#r,this.#l,i,{signal:this.#g,isDirect:String(t.conversationType)==="1",hasImages:Tt(a),hasFiles:wt(a),pendingInteraction:this.#d.has(i)||this.#f.hasPending(i),control:{owner:this,key:i}});r?.stopped&&await Promise.allSettled([this.#H(i),this.#f.closeRoute(i)]);for(let s of r?.messages??[r?.message])s&&await this.#v(e,s,this.#L(t));this.#a.lastError=null}#N(t,o,i,e){let a;return a=Promise.resolve().then(async()=>{this.#l.hasSeen(t)||(await this.#l.markSeen(t),Lr(this.#a,"messagesReceived"),this.#a.lastMessageAt=new Date().toISOString(),i.message&&await this.#v(o,i.message),this.#a.lastError=null)}).catch(async A=>{if(this.#g?.aborted){this.#m(e,"clear");return}this.#m(e,"error"),this.#a.lastError=A?.message??String(A);let r=At(this.#a,A);this.#n.error?.(`[dsh-dingtalk] failed to process a batch input message [${r.referenceId}]`,_Q(A)),await this.#v(o,dt(r)).catch(()=>{})}).finally(()=>{this.#B.delete(t),this.#u.delete(a)}),this.#u.add(a),a}#T(t,o,i,e){let a;return a=Promise.resolve().then(async()=>{this.#l.hasSeen(o)||(await this.#l.markSeen(o),e.reason==="command-not-allowed"&&i?(Lr(this.#a,"messagesReceived"),this.#a.lastMessageAt=new Date().toISOString(),await this.#v(i,w(ao),this.#L(t)),Lr(this.#a,"messagesReplied"),this.#a.lastReplyAt=new Date().toISOString()):(Lr(this.#a,"messagesRejected"),this.#a.lastRejectedAt=new Date().toISOString()),this.#a.lastError=null)}).catch(A=>{this.#g?.aborted||(this.#a.lastError=A?.message??String(A),this.#n.error?.("[dsh-dingtalk] failed to apply inbound access policy",A))}).finally(()=>{this.#B.delete(o),this.#u.delete(a)}),this.#u.add(a),a}async#O(t,o,i,e,{alreadyRecorded:a=!1,preparedMessage:A,batchSubmission:r=null,statusReaction:s=null}={}){if(this.#g?.throwIfAborted(),!a){if(this.#l.hasSeen(o))return;await this.#l.markSeen(o),Lr(this.#a,"messagesReceived"),this.#a.lastMessageAt=new Date().toISOString()}if(String(t.conversationType)==="2"&&t.isInAtList!==!0){Lr(this.#a,"messagesIgnored");return}let g;try{g=gc(t.sessionWebhook)}catch{Lr(this.#a,"messagesRejected"),this.#a.lastRejectedAt=new Date().toISOString(),this.#a.lastError=w("\u9489\u9489\u6D88\u606F\u6CA1\u6709\u5B89\u5168\u7684\u56DE\u590D\u5730\u5740\u3002");return}let c=A??O_(t,{api:this.#e,clientId:this.#A,clientSecret:this.#t}),I=c.content,d=Tt(c),B=wt(c),f=String(t?.msgtype).toLowerCase()==="text",Q=null,y=!1,m=r===null;try{if(!I&&!d&&!B){await this.#v(g,w("\u76EE\u524D\u652F\u6301\u6587\u5B57\u3001\u56FE\u7247\u548C\u6587\u4EF6\u6D88\u606F\u3002"),this.#L(t));return}let T=I.toLowerCase();if(f&&!d&&!B&&T==="/help"){await this.#v(g,Xhe(),this.#L(t));return}if(f&&!d&&!B&&T==="/status"){await this.#r.ensureRunning({signal:this.#g}),await this.#v(g,w("\u9489\u9489\u673A\u5668\u4EBA\u4E0E DeepSeek Harness \u8FDE\u63A5\u6B63\u5E38\u3002"),this.#L(t));return}if(f&&!d&&!B&&T==="/new"){await this.#l.clearSession(e),await this.#v(g,w("\u5DF2\u5F00\u542F\u65B0\u4F1A\u8BDD\u3002\u8BF7\u53D1\u9001\u4F60\u7684\u95EE\u9898\u3002"),this.#L(t));return}let _=f&&!d&&!B?await Mo(I,this.#r,e):null;if(_){for(let N of _.messages??[_.message])await this.#v(g,N,this.#L(t));return}let R=f&&!d&&!B?await bi(I,this.#r,this.#l,e,{signal:this.#g}):null;if(R){await this.#v(g,R.message,this.#L(t));return}let K=d?await Oo(c,{signal:this.#g}):void 0,L=this.#B.get(o);L&&(K=To(K??I,L,()=>({channel:"dingtalk",senderId:i,senderName:t.senderNick}))),typeof this.#e.createAiCard=="function"&&typeof this.#e.updateAiCard=="function"&&typeof this.#e.finishAiCard=="function"&&(Q=Tx({api:this.#e,clientId:this.#A,clientSecret:this.#t,target:iEe(t,i),signal:this.#g,logger:this.#n}),y=await Q.start(w(Whe)));let{answer:F,artifacts:q=[]}=await Oi({harness:this.#r,state:this.#l,key:e,...K!==void 0?{content:K}:{text:I},createOptions:{signal:this.#g},existsOptions:{signal:this.#g},askOptions:{timeoutMs:this.#s,signal:this.#g,control:{owner:this,key:e},onUpdate:y?N=>Q.push(sEe(N)):void 0,onInteraction:N=>this.#R(N,{key:e,actor:i,sessionWebhook:g,requiresMention:String(t.conversationType)==="2"}),onInteractionResolved:N=>this.#_(N),files:c.files}});r&&(this.#Q.complete(e,r.token),m=!0);let V=typeof F=="string"&&F.trim()?F:q.length>0?w("\u7ED3\u679C\u6587\u4EF6\u5DF2\u751F\u6210\u3002"):F,x=null,G=null,J=!1;try{J=y&&await Q.finish(V),J?G=Zt({deliveryId:o,presentation:"dingtalk-card"}):G=Zt({deliveryId:o,presentation:"dingtalk-text",providerMessageIds:await this.#v(g,V,this.#L(t))})}catch(N){x=ka(N)}let U=await this.#K(oEe(t,i,this.#A),g,o,q,G);if(x&&!U.userVisible)throw x;return x&&U.artifactSendErrors===0&&At(this.#a,x),Lr(this.#a,"messagesReplied"),this.#a.lastReplyAt=new Date().toISOString(),this.#a.lastError=null,!x&&U.artifactSendErrors===0&&wo(this.#a),U.receipt}catch(T){let _=null;if(!m&&r&&(T?.code==="turn-stopped"?this.#Q.complete(e,r.token):_=this.#Q.fail(e,r.token).message??null,m=!0),T?.code==="turn-stopped"){this.#m(s,"clear"),y&&await Q.finish(w("\u5DF2\u505C\u6B62\u3002")).catch(()=>{});return}if(this.#g?.aborted){this.#m(s,"clear");return}this.#m(s,"error"),this.#a.lastError=T?.message??String(T);let R=ko(T)??eEe(T),K=At(this.#a,T,{userMessage:R,reason:eo(T)?.reason});this.#n.error?.(`[dsh-dingtalk] failed to process an inbound message [${K.referenceId}]`,_Q(T));try{let L=dt(K),F=_?`${L} +`),s=[];if(e==="picture"){let c=D_(a);c&&s.push(c)}else if(e==="richtext")for(let c of A){if(String(c?.type??"").toLowerCase()!=="picture")continue;let I=D_(c);I&&s.push(I)}let g=e==="file"?D_(a):null;return{content:r,images:s.map((c,I)=>({name:I===0?"image":`image-${I+1}`,load:({signal:d,maxBytes:B})=>{if(typeof t?.downloadImage!="function")throw new Error("DingTalk API does not support image downloads");return t.downloadImage({clientId:o,clientSecret:i,robotCode:n?.robotCode,downloadCode:c,signal:d,maxBytes:B})}})),files:g?[{name:mt(a?.fileName??a?.file_name)??"file",load:({signal:c}={})=>{if(typeof t?.downloadFile!="function")throw new Error("DingTalk API does not support file downloads");return t.downloadFile({clientId:o,clientSecret:i,robotCode:n?.robotCode,downloadCode:g,signal:c})}}]:[]}}function aEe(n,t){if(String(n?.conversationType)==="2"){let o=mt(n?.conversationId);if(!o)throw new Error("DingTalk group message has no conversation id");return`group:${o}`}return`p2p:${t}`}function iEe(n,t){return String(n?.conversationType)==="2"?{type:"group",openConversationId:mt(n?.conversationId),atUserIds:{[t]:mt(n?.senderNick)??t}}:{type:"user",userId:t}}function oEe(n,t,o){let i=mt(n?.robotCode)??o;return String(n?.conversationType)==="2"?{type:"group",openConversationId:mt(n?.conversationId),robotCode:i}:{type:"user",userId:t,robotCode:i}}function nEe(n,t){let o=String(n??w("\u7ED3\u679C\u6587\u4EF6")).replace(/[\r\n]+/g," ").trim()||w("\u7ED3\u679C\u6587\u4EF6");switch(t?.code){case"artifact-delivery-uncertain":return w("\u7ED3\u679C\u6587\u4EF6\u300C{name}\u300D\u53D1\u9001\u7ED3\u679C\u672A\u80FD\u786E\u8BA4\uFF0C\u8BF7\u5148\u68C0\u67E5\u804A\u5929\u5185\u662F\u5426\u5DF2\u6536\u5230\uFF0C\u4E0D\u8981\u7ACB\u5373\u91CD\u8BD5\u3002",{name:o});case"artifact-permission-required":return w("\u7ED3\u679C\u6587\u4EF6\u300C{name}\u300D\u5DF2\u751F\u6210\uFF0C\u4F46\u9489\u9489\u5E94\u7528\u6216\u673A\u5668\u4EBA\u7F3A\u5C11\u6587\u4EF6\u6D88\u606F\u6743\u9650\u3002\u8BF7\u5F00\u901A\u5E94\u7528 qyapi_base \u6743\u9650\uFF0C\u5E76\u786E\u8BA4\u673A\u5668\u4EBA\u5177\u5907\u6587\u4EF6\u6D88\u606F\u53D1\u9001\u80FD\u529B\u3002",{name:o});case"artifact-too-large":return w("\u7ED3\u679C\u6587\u4EF6\u300C{name}\u300D\u8D85\u8FC7\u5F53\u524D\u9489\u9489\u673A\u5668\u4EBA\u53EF\u53D1\u9001\u7684\u6587\u4EF6\u5927\u5C0F\uFF0C\u672A\u53D1\u9001\u3002",{name:o});case"artifact-rate-limited":return w("\u7ED3\u679C\u6587\u4EF6\u300C{name}\u300D\u6682\u65F6\u88AB\u9489\u9489\u9650\u6D41\uFF0C\u672A\u80FD\u53D1\u9001\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002",{name:o});case"artifact-provider-rejected":return w("\u7ED3\u679C\u6587\u4EF6\u300C{name}\u300D\u5DF2\u751F\u6210\uFF0C\u4F46\u9489\u9489\u62D2\u7EDD\u4E86\u8BE5\u6587\u4EF6\u6D88\u606F\uFF0C\u8BF7\u68C0\u67E5\u6587\u4EF6\u7C7B\u578B\u548C\u673A\u5668\u4EBA\u6587\u4EF6\u6D88\u606F\u914D\u7F6E\u3002",{name:o});case"artifact-invalid":case"artifact-changed":case"artifact-unavailable":return w("\u7ED3\u679C\u6587\u4EF6\u300C{name}\u300D\u6682\u65F6\u65E0\u6CD5\u8BFB\u53D6\u6216\u51C6\u5907\u53D1\u9001\uFF0C\u8BF7\u786E\u8BA4\u6587\u4EF6\u4ECD\u53EF\u8BBF\u95EE\u540E\u91CD\u8BD5\u3002",{name:o});default:return w("\u7ED3\u679C\u6587\u4EF6\u300C{name}\u300D\u5DF2\u751F\u6210\uFF0C\u4F46\u6682\u65F6\u672A\u80FD\u901A\u8FC7\u9489\u9489\u53D1\u9001\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002",{name:o})}}function sEe(n){return n?.type==="text"&&mt(n.text)?n.text:n?.type==="tool"?n.name==="web_search"?w("_\u6B63\u5728\u641C\u7D22\u7F51\u7EDC\u5E76\u6574\u7406\u4FE1\u606F\u2026_"):w("_\u6B63\u5728\u4F7F\u7528 {name}\u2026_",{name:mt(n.name)??w("\u5DE5\u5177")}):w("_{text}_",{text:mt(n?.text)??w("\u6B63\u5728\u5904\u7406\u2026")})}function gEe(n,t,o){if(t.needsPresentation||!t.questions[t.index]||t.actor!==o||String(n?.conversationType)==="2"&&n?.isInAtList!==!0||n?.msgtype!=="text"||!mt(n?.text?.content))return!1;try{return gc(n.sessionWebhook),!0}catch{return!1}}function cEe(n){n.stats??={};for(let t of["messagesReceived","messagesReplied","messagesRejected","messagesIgnored","reactionsAdded","reactionsRemoved","reactionErrors"])n[t]??=0,n.stats[t]=n[t];n.pendingSenders??=[]}function Lr(n,t){n[t]=(n[t]??0)+1,n.stats??={},n.stats[t]=n[t]}function b_({pendingSenders:n=[]}={}){return{messagesReceived:0,messagesReplied:0,messagesRejected:0,messagesIgnored:0,reactionsAdded:0,reactionsRemoved:0,reactionErrors:0,lastMessageAt:null,lastReplyAt:null,lastRejectedAt:null,lastError:null,lastMessageError:null,pendingSenders:structuredClone(n),stats:{messagesReceived:0,messagesReplied:0,messagesRejected:0,messagesIgnored:0,reactionsAdded:0,reactionsRemoved:0,reactionErrors:0}}}var TQ=class{#e;#A;#t;#r;#l;#o;#i;#a;#n;#s;#p;#c;#g;#I=new Map;#d=new Map;#h=new Map;#C=new Set;#u=new Set;#B=new Map;#f;#Q=new Ti;constructor({api:t,clientId:o,clientSecret:i,harness:e,state:a,contextEnhancement:A,accessPolicy:r,status:s=b_(),logger:g=console,replyTimeoutMs:c=6e5,reactionTimeoutMs:I=5e3,maxMessageChars:d=4e3,signal:B}){if(!t||typeof t.sendText!="function")throw new TypeError("DingTalk API is required");if(!mt(o)||!mt(i))throw new TypeError("DingTalk app credentials are required");if(!e||!a)throw new TypeError("Harness client and state store are required");this.#e=t,this.#A=o.trim(),this.#t=i.trim(),this.#r=e,this.#l=a,this.#o=A,this.#i=r,this.#a=s,this.#n=g,this.#f=new Di({label:"DingTalk",logger:g}),this.#s=c,this.#p=Number.isFinite(I)&&I>0?Math.floor(I):5e3,this.#c=d,this.#g=B,cEe(this.#a),this.#U()}get status(){return this.#U(),structuredClone(this.#a)}accept(t,{contextSnapshot:o}={}){if(this.#g?.aborted)return Promise.resolve();let i=mt(t?.msgId),e=t1(t);if(!i||!e||this.#l.hasSeen(i)||this.#B.has(i))return Promise.resolve();let a=String(t.conversationType)==="2"?"group":String(t.conversationType)==="1"?"direct":null,A;try{A=aEe(t,e)}catch{return Lr(this.#a,"messagesRejected"),this.#a.lastRejectedAt=new Date().toISOString(),Promise.resolve()}let r=null;try{r=gc(t.sessionWebhook)}catch{}let s=this.#d.get(A),g=O_(t,{api:this.#e,clientId:this.#A,clientSecret:this.#t}),c=mt(g.content)??"",I=String(t.conversationType)!=="2"||t?.isInAtList===!0,d=String(t.conversationType)!=="2";if(I){let _=Ba(this.#i,{conversationType:a,senderIds:e,text:c,hasImages:Tt(g),hasFiles:wt(g)});if(!_.allowed)return this.#B.set(i,null),this.#T(t,i,r,_)}this.#B.set(i,o===void 0?Aa(this.#o,a):o),r&&d&&So(this.#l,{sessionWebhook:r});let B=r&&I?this.#y(t):null,f=_=>Promise.resolve(_).then(R=>(this.#m(B,this.#g?.aborted?"clear":"success"),R),R=>{throw this.#m(B,this.#g?.aborted||R?.name==="AbortError"||R?.code==="turn-stopped"?"clear":"error"),R}),Q=String(t?.msgtype).toLowerCase()==="text"&&Ni(c),y=this.#Q.status(A);if(Q&&!d&&r&&I)return f(this.#N(i,r,{message:es()},B));if(d&&r&&(Q||y.phase==="collecting")){let R=/^\/batch$/iu.test(c)&&y.phase==="idle"&&(this.#I.has(A)||s||this.#f.hasPending(A))?{handled:!0,kind:"busy",message:No()}:this.#Q.handle(A,c,{plainText:!!c&&String(t?.msgtype).toLowerCase()==="text"&&!wt(g)&&!Tt(g)});if(R.handled)return R.kind==="submit"?f(this.#D({...t,msgtype:"text",text:{content:R.prompt}},i,e,A,{batchSubmission:R,statusReaction:B})):f(this.#N(i,r,R,B))}let m=Fa(c)?Ao:wt(g)?null:ni(c)?Mi:si(c)?to:gi(c)?_i:null;if(m&&r&&I){let _;return _=this.#E(t,i,A,r,g,m).catch(R=>{if(R?.code==="turn-stopped"||this.#g?.aborted){this.#m(B,"clear");return}this.#m(B,"error"),this.#a.lastError=R?.message??String(R);let K=At(this.#a,R);return this.#n.error?.(`[dsh-dingtalk] failed to process a command [${K.referenceId}]`,_Q(R)),this.#v(r,dt(K),this.#L(t)).catch(()=>{})}).finally(()=>{this.#B.delete(i),this.#u.delete(_)}),this.#u.add(_),f(_)}let T=this.#f.claimReply({key:A,actor:e,messageId:i,text:r&&t?.msgtype==="text"?mt(t?.text?.content)??"":"",addressed:String(t?.conversationType)!=="2"||t?.isInAtList===!0,hasPendingQuestion:!!s,questionCompletion:s?.submitting||s?.claimedReplyMessageId?s.queue:null,isQuestionPending:()=>this.#d.has(A),send:r?_=>this.#v(r,_,this.#L(t)):async()=>{}});if(T){let _;return _=T.process(async()=>this.#l.hasSeen(i)?!1:(await this.#l.markSeen(i),Lr(this.#a,"messagesReceived"),this.#a.lastMessageAt=new Date().toISOString(),r||(Lr(this.#a,"messagesRejected"),this.#a.lastRejectedAt=new Date().toISOString(),this.#a.lastError=w("\u9489\u9489\u6D88\u606F\u6CA1\u6709\u5B89\u5168\u7684\u56DE\u590D\u5730\u5740\u3002")),!0)).catch(R=>{if(this.#g?.aborted){this.#m(B,"clear");return}this.#m(B,"error"),this.#a.lastError=w("\u9489\u9489\u5BA1\u6279\u5904\u7406\u5931\u8D25\u3002"),this.#n.error?.("[dsh-dingtalk] failed to process an approval reply",R)}).finally(()=>{this.#B.delete(i),this.#C.delete(_)}),this.#C.add(_),f(_)}if(s&&s.actor!==e)return f(this.#D(t,i,e,A,{statusReaction:B}));if(s?.submitting||s?.claimedReplyMessageId)return f(this.#D(t,i,e,A,{statusReaction:B}));if(s){gEe(t,s,e)&&(s.claimedReplyMessageId=i);let R=(s.queue??Promise.resolve()).catch(()=>{}).then(()=>this.#w(t,i,e,A,s,B)).finally(()=>{this.#B.delete(i),s.claimedReplyMessageId===i&&(s.claimedReplyMessageId=null),s.queue===R&&(s.queue=null)});return s.queue=R,f(R)}return f(this.#D(t,i,e,A,{statusReaction:B}))}#S(t,o,i,e){let a=new AbortController,A=Promise.resolve().then(()=>this.#e[t]({clientId:this.#A,clientSecret:this.#t,...o,reactionName:i,signal:a.signal})),r,s=new Promise((g,c)=>{r=setTimeout(()=>{let I=new DOMException("DingTalk reaction timed out","TimeoutError");a.abort(I),c(I)},this.#p),r.unref?.()});return Promise.race([A,s]).then(()=>(Lr(this.#a,e==="add"?"reactionsAdded":"reactionsRemoved"),!0)).catch(g=>(Lr(this.#a,"reactionErrors"),this.#n.debug?.(`[dsh-dingtalk] ${t} failed`,_Q(g)),!1)).finally(()=>clearTimeout(r))}#y(t){if(typeof this.#e.addReaction!="function"||typeof this.#e.recallReaction!="function")return null;let o=mt(t?.msgId),i=mt(t?.conversationId);if(!o||!i)return null;let e={messageId:o,conversationId:i,robotCode:mt(t?.robotCode)??this.#A};return{target:e,attached:this.#S("addReaction",e,TI,"add"),terminal:!1}}#m(t,o){if(!t||t.terminal)return;t.terminal=!0;let i=o==="success"?wx:o==="error"?Dx:null;t.attached.then(async e=>{let a=await this.#S("recallReaction",t.target,TI,"remove");(!e||!a)&&(await new Promise(A=>{setTimeout(A,Math.min(1e3,this.#p)).unref?.()}),a=await this.#S("recallReaction",t.target,TI,"remove")||a),!(!a||!i||this.#g?.aborted)&&await this.#S("addReaction",t.target,i,"add")}).catch(()=>{})}#D(t,o,i,e,{releaseMessageId:a=!0,alreadyRecorded:A=!1,batchSubmission:r=null,statusReaction:s=null}={}){let g=!1;try{gc(t.sessionWebhook),g=!0}catch{}let c=String(t.conversationType)!=="2"||t.isInAtList===!0,I=g&&c?kp(O_(t,{api:this.#e,clientId:this.#A,clientSecret:this.#t}),{signal:this.#g}):void 0,B=(this.#I.get(e)??Promise.resolve()).catch(()=>{}).then(()=>this.#O(t,o,i,e,{alreadyRecorded:A,preparedMessage:I,batchSubmission:r,statusReaction:s})).finally(()=>{a&&this.#B.delete(o),this.#I.get(e)===B&&this.#I.delete(e)});return this.#I.set(e,B),B}async waitForIdle(){await Promise.allSettled([...this.#I.values(),...[...this.#d.values()].flatMap(t=>t.queue?[t.queue]:[]),...this.#C,...this.#u])}async#E(t,o,i,e,a,A){if(this.#g?.throwIfAborted(),this.#l.hasSeen(o))return;await this.#l.markSeen(o),Lr(this.#a,"messagesReceived"),this.#a.lastMessageAt=new Date().toISOString();let r=await A(mt(a.content)??"",this.#r,this.#l,i,{signal:this.#g,isDirect:String(t.conversationType)==="1",hasImages:Tt(a),hasFiles:wt(a),pendingInteraction:this.#d.has(i)||this.#f.hasPending(i),control:{owner:this,key:i}});r?.stopped&&await Promise.allSettled([this.#H(i),this.#f.closeRoute(i)]);for(let s of r?.messages??[r?.message])s&&await this.#v(e,s,this.#L(t));this.#a.lastError=null}#N(t,o,i,e){let a;return a=Promise.resolve().then(async()=>{this.#l.hasSeen(t)||(await this.#l.markSeen(t),Lr(this.#a,"messagesReceived"),this.#a.lastMessageAt=new Date().toISOString(),i.message&&await this.#v(o,i.message),this.#a.lastError=null)}).catch(async A=>{if(this.#g?.aborted){this.#m(e,"clear");return}this.#m(e,"error"),this.#a.lastError=A?.message??String(A);let r=At(this.#a,A);this.#n.error?.(`[dsh-dingtalk] failed to process a batch input message [${r.referenceId}]`,_Q(A)),await this.#v(o,dt(r)).catch(()=>{})}).finally(()=>{this.#B.delete(t),this.#u.delete(a)}),this.#u.add(a),a}#T(t,o,i,e){let a;return a=Promise.resolve().then(async()=>{this.#l.hasSeen(o)||(await this.#l.markSeen(o),e.reason==="command-not-allowed"&&i?(Lr(this.#a,"messagesReceived"),this.#a.lastMessageAt=new Date().toISOString(),await this.#v(i,w(ao),this.#L(t)),Lr(this.#a,"messagesReplied"),this.#a.lastReplyAt=new Date().toISOString()):(Lr(this.#a,"messagesRejected"),this.#a.lastRejectedAt=new Date().toISOString()),this.#a.lastError=null)}).catch(A=>{this.#g?.aborted||(this.#a.lastError=A?.message??String(A),this.#n.error?.("[dsh-dingtalk] failed to apply inbound access policy",A))}).finally(()=>{this.#B.delete(o),this.#u.delete(a)}),this.#u.add(a),a}async#O(t,o,i,e,{alreadyRecorded:a=!1,preparedMessage:A,batchSubmission:r=null,statusReaction:s=null}={}){if(this.#g?.throwIfAborted(),!a){if(this.#l.hasSeen(o))return;await this.#l.markSeen(o),Lr(this.#a,"messagesReceived"),this.#a.lastMessageAt=new Date().toISOString()}if(String(t.conversationType)==="2"&&t.isInAtList!==!0){Lr(this.#a,"messagesIgnored");return}let g;try{g=gc(t.sessionWebhook)}catch{Lr(this.#a,"messagesRejected"),this.#a.lastRejectedAt=new Date().toISOString(),this.#a.lastError=w("\u9489\u9489\u6D88\u606F\u6CA1\u6709\u5B89\u5168\u7684\u56DE\u590D\u5730\u5740\u3002");return}let c=A??O_(t,{api:this.#e,clientId:this.#A,clientSecret:this.#t}),I=c.content,d=Tt(c),B=wt(c),f=String(t?.msgtype).toLowerCase()==="text",Q=null,y=!1,m=r===null;try{if(!I&&!d&&!B){await this.#v(g,w("\u76EE\u524D\u652F\u6301\u6587\u5B57\u3001\u56FE\u7247\u548C\u6587\u4EF6\u6D88\u606F\u3002"),this.#L(t));return}let T=I.toLowerCase();if(f&&!d&&!B&&T==="/help"){await this.#v(g,Xhe(),this.#L(t));return}if(f&&!d&&!B&&T==="/status"){await this.#r.ensureRunning({signal:this.#g}),await this.#v(g,w("\u9489\u9489\u673A\u5668\u4EBA\u4E0E DeepSeek Harness \u8FDE\u63A5\u6B63\u5E38\u3002"),this.#L(t));return}if(f&&!d&&!B&&T==="/new"){await this.#l.clearSession(e),await this.#v(g,w("\u5DF2\u5F00\u542F\u65B0\u4F1A\u8BDD\u3002\u8BF7\u53D1\u9001\u4F60\u7684\u95EE\u9898\u3002"),this.#L(t));return}let _=f&&!d&&!B?await Mo(I,this.#r,e):null;if(_){for(let N of _.messages??[_.message])await this.#v(g,N,this.#L(t));return}let R=f&&!d&&!B?await bi(I,this.#r,this.#l,e,{signal:this.#g}):null;if(R){await this.#v(g,R.message,this.#L(t));return}let K=d?await Oo(c,{signal:this.#g}):void 0,L=this.#B.get(o);L&&(K=To(K??I,L,()=>({channel:"dingtalk",senderId:i,senderName:t.senderNick,conversationTitle:t.conversationTitle}))),typeof this.#e.createAiCard=="function"&&typeof this.#e.updateAiCard=="function"&&typeof this.#e.finishAiCard=="function"&&(Q=Tx({api:this.#e,clientId:this.#A,clientSecret:this.#t,target:iEe(t,i),signal:this.#g,logger:this.#n}),y=await Q.start(w(Whe)));let{answer:F,artifacts:q=[]}=await Oi({harness:this.#r,state:this.#l,key:e,...K!==void 0?{content:K}:{text:I},createOptions:{signal:this.#g},existsOptions:{signal:this.#g},askOptions:{timeoutMs:this.#s,signal:this.#g,control:{owner:this,key:e},onUpdate:y?N=>Q.push(sEe(N)):void 0,onInteraction:N=>this.#R(N,{key:e,actor:i,sessionWebhook:g,requiresMention:String(t.conversationType)==="2"}),onInteractionResolved:N=>this.#_(N),files:c.files}});r&&(this.#Q.complete(e,r.token),m=!0);let V=typeof F=="string"&&F.trim()?F:q.length>0?w("\u7ED3\u679C\u6587\u4EF6\u5DF2\u751F\u6210\u3002"):F,x=null,G=null,J=!1;try{J=y&&await Q.finish(V),J?G=Zt({deliveryId:o,presentation:"dingtalk-card"}):G=Zt({deliveryId:o,presentation:"dingtalk-text",providerMessageIds:await this.#v(g,V,this.#L(t))})}catch(N){x=ka(N)}let U=await this.#K(oEe(t,i,this.#A),g,o,q,G);if(x&&!U.userVisible)throw x;return x&&U.artifactSendErrors===0&&At(this.#a,x),Lr(this.#a,"messagesReplied"),this.#a.lastReplyAt=new Date().toISOString(),this.#a.lastError=null,!x&&U.artifactSendErrors===0&&wo(this.#a),U.receipt}catch(T){let _=null;if(!m&&r&&(T?.code==="turn-stopped"?this.#Q.complete(e,r.token):_=this.#Q.fail(e,r.token).message??null,m=!0),T?.code==="turn-stopped"){this.#m(s,"clear"),y&&await Q.finish(w("\u5DF2\u505C\u6B62\u3002")).catch(()=>{});return}if(this.#g?.aborted){this.#m(s,"clear");return}this.#m(s,"error"),this.#a.lastError=T?.message??String(T);let R=ko(T)??eEe(T),K=At(this.#a,T,{userMessage:R,reason:eo(T)?.reason});this.#n.error?.(`[dsh-dingtalk] failed to process an inbound message [${K.referenceId}]`,_Q(T));try{let L=dt(K),F=_?`${L} ${_}`:L;y&&await Q.finish(F)||await this.#v(g,F,this.#L(t))}catch{this.#n.error?.("[dsh-dingtalk] failed to send the safe error reply")}}finally{await this.#H(e),await this.#f.closeRoute(e)}}async#w(t,o,i,e,a,A){this.#g?.throwIfAborted();let r=this.#d.get(e),s=a.claimedReplyMessageId===o;if(!r||r!==a||r.submitting)return s&&(!r||r!==a)?this.#k(t,o):this.#D(t,o,i,e,{releaseMessageId:!1,statusReaction:A});if(this.#l.hasSeen(o))return;if(await this.#l.markSeen(o),Lr(this.#a,"messagesReceived"),this.#a.lastMessageAt=new Date().toISOString(),String(t.conversationType)==="2"&&t.isInAtList!==!0){Lr(this.#a,"messagesIgnored");return}let g;try{g=gc(t.sessionWebhook)}catch{Lr(this.#a,"messagesRejected"),this.#a.lastRejectedAt=new Date().toISOString(),this.#a.lastError=w("\u9489\u9489\u6D88\u606F\u6CA1\u6709\u5B89\u5168\u7684\u56DE\u590D\u5730\u5740\u3002");return}let c=t?.msgtype==="text"?mt(t?.text?.content):null;if(!c){try{await this.#v(g,w("\u8BF7\u7528\u6587\u5B57\u56DE\u7B54\u5F53\u524D\u95EE\u9898\u3002"),this.#L(t))}catch{this.#n.error?.("[dsh-dingtalk] failed to reject a non-text interaction reply")}return}let I=this.#d.get(e);if(!I||I!==a||I.submitting){if(s&&(!I||I!==a)){try{await this.#v(g,w(w_),this.#L(t))}catch{this.#n.error?.("[dsh-dingtalk] failed to send an expired interaction notice")}return}return this.#D(t,o,i,e,{releaseMessageId:!1,alreadyRecorded:!0,statusReaction:A})}if(I.sessionWebhook=g,I.needsPresentation){try{await this.#G(I)}catch{this.#m(A,"error"),this.#a.lastError=w("\u9489\u9489\u4EA4\u4E92\u95EE\u9898\u53D1\u9001\u5931\u8D25\u3002"),this.#n.error?.("[dsh-dingtalk] failed to retry an interaction question"),I.interaction.reconnect?.()}return}let d=I.questions[I.index];if(d){if(I.answers.push(wi(d,c)),I.index+=1,I.indexthis.#v(e,c)})||t?.kind!=="question")return;let A=t?.payload?.questions,r=typeof t?.interactionId=="string"?t.interactionId:t?.rpcId;if(typeof t.rpcId!="string"||typeof r!="string"||typeof t.sessionId!="string"||!Array.isArray(A)||A.length===0||A.some(c=>!mi(c))){this.#n.warn?.("[dsh-dingtalk] ignored an invalid Harness question interaction");return}if(t.recovered===!0){await t.respond({ok:!1,error:{code:"cancelled",message:"DingTalk safely cancelled an interaction left by an earlier client.",details:{}}});try{await this.#v(e,w("\u68C0\u6D4B\u5230\u8FD9\u4E2A Session \u4E2D\u9057\u7559\u7684\u5F85\u56DE\u7B54\u95EE\u9898\uFF0C\u5DF2\u5B89\u5168\u53D6\u6D88\u5E76\u7EE7\u7EED\u5904\u7406\u4F60\u521A\u624D\u7684\u6D88\u606F\u3002"))}catch{this.#n.error?.("[dsh-dingtalk] failed to send an interaction recovery notice")}return}let s=this.#d.get(o);if(s?.interactionId===r){s.interaction=t,s.needsPresentation&&await this.#G(s);return}if(this.#h.has(r))return;if(s){this.#n.warn?.("[dsh-dingtalk] cancelled a second pending Harness question"),await t.respond({ok:!1,error:{code:"cancelled",message:"DingTalk is already handling another user interaction.",details:{}}});return}let g={kind:"question",interactionId:r,sessionId:t.sessionId,interaction:t,actor:i,requiresMention:a,questions:A,answers:[],index:0,sessionWebhook:e,queue:null,claimedReplyMessageId:null,submitting:!1,needsPresentation:!0};this.#d.set(o,g),this.#h.set(g.interactionId,o),await this.#G(g)}async#_(t){if(await this.#f.handleResolved(t))return;let o=t?.interactionId;if(t?.kind!=="question"||typeof o!="string")return;let i=this.#h.get(o);i&&this.#P(i,o)}async#G(t){let o=t.questions[t.index];o&&(await this.#v(t.sessionWebhook,Si(o,t.index,t.questions.length,{requiresMention:t.requiresMention})),t.needsPresentation=!1)}async#k(t,o){if(this.#l.hasSeen(o))return;await this.#l.markSeen(o),Lr(this.#a,"messagesReceived"),this.#a.lastMessageAt=new Date().toISOString();let i;try{i=gc(t.sessionWebhook)}catch{Lr(this.#a,"messagesRejected"),this.#a.lastRejectedAt=new Date().toISOString();return}try{await this.#v(i,w(w_),this.#L(t))}catch{this.#n.error?.("[dsh-dingtalk] failed to send an expired interaction notice")}}#F(t,o){let i=this.#d.get(t);return!i||o!==void 0&&i.interactionId!==o?null:(this.#d.delete(t),this.#h.delete(i.interactionId),i)}#P(t,o){return this.#F(t,o)!==null}async#H(t){let o=this.#F(t);if(!(!o||o.kind!=="question"))try{await o.interaction.respond({ok:!1,error:{code:"cancelled",message:"The DingTalk interaction ended before the user answered.",details:{}}},{signal:AbortSignal.timeout(5e3)})}catch(i){i?.code!=="interaction-not-pending"&&this.#n.warn?.("[dsh-dingtalk] failed to cancel a pending Harness interaction")}}#U(){typeof this.#l.pendingSenders=="function"&&(this.#a.pendingSenders=this.#l.pendingSenders())}#L(t){let o=t1(t);return String(t?.conversationType)==="2"&&o?{atUserIds:[o]}:void 0}async#v(t,o,i){let e=[];for(let a of bx(o,this.#c)){this.#g?.throwIfAborted();let A=await this.#e.sendText({clientId:this.#A,clientSecret:this.#t,sessionWebhook:t,text:a,at:i,signal:this.#g});e.push(...Ua(A))}return e}async#K(t,o,i,e,a){let A=async(s,g)=>$he(await this.#e[s]({clientId:this.#A,clientSecret:this.#t,target:t,file:g,signal:this.#g})),r=await vo({artifacts:e,baseReceipt:a,deliveryId:i,aggregatePresentation:a?"dingtalk-text-and-files":"dingtalk-files",channelKey:"dingtalk",signal:this.#g,sendImage:typeof this.#e.sendImage=="function"?s=>A("sendImage",s):void 0,sendFile:typeof this.#e.sendFile=="function"?s=>A("sendFile",s):void 0,onFailure:(s,g)=>At(this.#a,g,{userMessage:nEe(s?.fileName,g),reason:g?.code}),sendFailureNotice:(s,g,c)=>this.#v(o,dt(c)),logger:this.#n});return this.#a.artifactsSent=(this.#a.artifactsSent??0)+r.artifactsSent,this.#a.artifactSendErrors=(this.#a.artifactSendErrors??0)+r.artifactSendErrors,{receipt:r.receipt,userVisible:r.userVisible,artifactSendErrors:r.artifactSendErrors}}};function NQ(n){return typeof n=="string"&&n.trim()?n.trim():null}function r1(n){let t=Array.isArray(n?.approvedSenders)?n.approvedSenders:n?.approvedSenders instanceof Set?[...n.approvedSenders]:[];return new Set(t.map(o=>NQ(typeof o=="string"?o:o?.staffId)).filter(Boolean))}function IEe(n){return r1(n).size}function a1(n){return n?.connected===!0||n?.socket?.readyState===1}function lEe(n,t){return new Promise((o,i)=>{if(t.aborted){i(t.reason);return}let e=()=>i(t.reason);t.addEventListener("abort",e,{once:!0}),Promise.resolve(n).then(a=>{t.removeEventListener("abort",e),o(a)},a=>{t.removeEventListener("abort",e),i(a)})})}async function pEe(n,t,o){for(;;){if(o?.throwIfAborted(),a1(n))return;await new Promise((i,e)=>{let a=setTimeout(()=>{o?.removeEventListener("abort",A),i()},t),A=()=>{clearTimeout(a),e(o.reason??new DOMException("Aborted","AbortError"))};o?.addEventListener("abort",A,{once:!0})})}}async function dEe(n,t,o,i){let e=AbortSignal.timeout(t),a=AbortSignal.any([i,e]),A=!1,r=Promise.resolve().then(()=>n.connect()).finally(()=>{A=!0});try{await lEe(r,a),await pEe(n,o,a)}catch(s){throw a.aborted?(A||r.then(()=>n.disconnect()).catch(()=>{}),i.aborted?i.reason:new Error(`DingTalk Stream handshake timed out after ${t}ms`)):s}}async function hEe({clientId:n,clientSecret:t}){let{DWClient:o,TOPIC_ROBOT:i}=await import("dingtalk-stream");return{client:new o({clientId:n,clientSecret:t,endpoint:"https://api.dingtalk.com",autoReconnect:!1,keepAlive:!0,debug:!1}),topic:i}}function EEe({pendingSenders:n=[],approvedSenders:t=0}={}){return{startedAt:null,ready:!1,dingtalkStreamState:"idle",harnessReachable:!1,lastConnectedAt:null,lastCheckedAt:null,lastCallbackAt:null,authorizationMode:"sender-staff-id-approval",approvedSenderCount:t,...b_({pendingSenders:n})}}var jE=class{#e;#A;#t;#r;#l;#o;#i;#a;#n;#s;#p;#c;#g;#I;#d=null;#h=null;#C=null;#u=null;#B=null;#f=null;#Q=new Set;constructor({config:t,clientSecret:o,harness:i,state:e,contextEnhancement:a,accessPolicy:A,logger:r=console,replyTimeoutMs:s=6e5,maxMessageChars:g=4e3,connectTimeoutMs:c=15e3,connectPollIntervalMs:I=25,api:d=Mx(),streamFactory:B=hEe}){if(!t||!NQ(t.clientId)||!NQ(o))throw new TypeError("DingtalkRuntime requires app credentials");if(!i||!e)throw new TypeError("DingtalkRuntime requires Harness and state");if(typeof B!="function")throw new TypeError("streamFactory must be a function");this.#e=t,this.#A=o.trim(),this.#t=i,this.#r=e,this.#l=a,this.#o=A,this.#i=r,this.#a=s,this.#n=g,this.#s=c,this.#p=I,this.#c=d,this.#g=B,this.#I=EEe({pendingSenders:this.#y(),approvedSenders:IEe(t)})}get status(){if(this.#h){let t=this.#h.status;Object.assign(this.#I,t)}else this.#I.pendingSenders=this.#y();return structuredClone(this.#I)}pendingSender(t){return typeof this.#r.pendingSender=="function"?this.#r.pendingSender(t):null}pendingSenders(){return this.#y()}async start(){return this.#d&&this.#I.ready?this.status:this.#u?this.#u:(this.#u=this.#S().finally(()=>{this.#u=null}),this.#u)}async#S(){await this.stop();let t=new AbortController;this.#f=t;let{signal:o}=t;this.#I.startedAt=new Date().toISOString(),this.#I.dingtalkStreamState="connecting",this.#I.lastError=null;try{if(await this.#t.ensureRunning({signal:o}),this.#I.harnessReachable=!0,typeof this.#r.removePendingSenderByStaffId=="function"){for(let A of r1(this.#e))await this.#r.removePendingSenderByStaffId(A);this.#I.pendingSenders=this.#y()}this.#h=new TQ({api:this.#c,clientId:this.#e.clientId,clientSecret:this.#A,approvedSenders:this.#e.approvedSenders,harness:this.#t,state:this.#r,contextEnhancement:this.#l,accessPolicy:this.#o,status:this.#I,logger:this.#i,replyTimeoutMs:this.#a,maxMessageChars:this.#n,signal:o});let i=await this.#g({clientId:this.#e.clientId,clientSecret:this.#A});if(o.throwIfAborted(),this.#d=i?.client??i,this.#C=i?.topic??i?.TOPIC_ROBOT??"/v1.0/im/bot/messages/get",!this.#d||typeof this.#d.registerCallbackListener!="function"||typeof this.#d.connect!="function"||typeof this.#d.disconnect!="function"||typeof this.#d.socketCallBackResponse!="function")throw new TypeError("streamFactory returned an invalid DingTalk Stream client");let e=this.#d,a=this.#h;return e.registerCallbackListener(this.#C,A=>{if(this.#d!==e||this.#h!==a)return;let r=NQ(A?.headers?.messageId);if(r)try{e.socketCallBackResponse(r,{success:!0})}catch{this.#i.warn?.("[dsh-dingtalk] unable to acknowledge an inbound callback")}let s=this.#l,g;try{g=s?.getSettings?.()}catch{}let c=Promise.resolve().then(async()=>{if(this.#h!==a)return;let I;try{I=typeof A?.data=="string"?JSON.parse(A.data):A?.data}catch{this.#I.lastError=w("\u9489\u9489\u6D88\u606F\u683C\u5F0F\u65E0\u6548\u3002"),this.#i.warn?.("[dsh-dingtalk] ignored an invalid callback payload");return}if(!I||typeof I!="object")return;this.#I.lastCallbackAt=Date.now();let d=Aa({getSettings:()=>g,get botId(){return s?.botId}},I.conversationType==="1"||I.conversationType===1?"direct":I.conversationType==="2"||I.conversationType===2?"group":null);await a.accept(I,{contextSnapshot:d})}).catch(()=>{o.aborted||this.#h!==a||(this.#I.lastError=w("\u9489\u9489\u6D88\u606F\u5904\u7406\u5931\u8D25\u3002"),this.#i.error?.("[dsh-dingtalk] callback processing failed"))}).finally(()=>this.#Q.delete(c));this.#Q.add(c)}),await dEe(e,this.#s,this.#p,o),this.#I.ready=!0,this.#I.dingtalkStreamState="connected",this.#I.lastConnectedAt=Date.now(),this.#I.lastCheckedAt=Date.now(),this.#I.lastError=null,this.#B=setInterval(()=>{let A=a1(e);this.#I.ready=A,this.#I.dingtalkStreamState=A?"connected":"reconnecting",this.#I.lastCheckedAt=Date.now(),A&&(this.#I.lastError=null)},1e3),this.#B.unref?.(),this.status}catch(i){let e=o.aborted;throw this.#I.ready=!1,this.#I.dingtalkStreamState=e?"idle":"failed",this.#I.lastError=e?null:i?.message??String(i),await this.stop({preserveError:!e}),i}}async stop({preserveError:t=!1}={}){let o=t?this.#I.lastError:null,i=this.#f;this.#f=null,i?.abort(new DOMException("DingTalk runtime stopped","AbortError")),this.#B&&clearInterval(this.#B),this.#B=null,this.#I.ready=!1;let e=this.#d;if(this.#d=null,this.#C=null,e)try{await e.disconnect()}catch{this.#i.warn?.("[dsh-dingtalk] DingTalk Stream disconnect failed")}return await Promise.allSettled([...this.#Q]),this.#Q.clear(),this.#h&&await this.#h.waitForIdle(),this.#h=null,this.#I.dingtalkStreamState=t?"failed":"idle",this.#I.lastError=o,this.status}async sendConnectionTest(t){return nc({state:this.#r,text:t,channelLabel:w("\u9489\u9489\u673A\u5668\u4EBA"),send:async({sessionWebhook:o},i)=>{if(!this.#I.ready||!this.#f)throw new Error("DingTalk runtime is not connected");await this.#c.sendText({clientId:this.#e.clientId,clientSecret:this.#A,sessionWebhook:o,text:i,signal:this.#f.signal})}})}async sendProactiveText(t,o,{signal:i}={}){let e=typeof t?.route?.userId=="string"?t.route.userId.trim():"",a=typeof t?.route?.openConversationId=="string"?t.route.openConversationId.trim():"";if(t?.kind==="user"&&(!e||a)||t?.kind==="group"&&(!a||e)||t?.kind!=="user"&&t?.kind!=="group"){let A=new TypeError("Invalid DingTalk proactive delivery target");throw A.code="invalid-target",A}if(!this.#I.ready||!this.#f){let A=new Error("DingTalk runtime is not connected");throw A.code="bot-not-connected",A}i?.throwIfAborted();try{await this.#c.sendRobotText({clientId:this.#e.clientId,clientSecret:this.#A,target:{type:t.kind,robotCode:this.#e.clientId,...t.kind==="user"?{userId:e}:{openConversationId:a}},text:o,signal:i??this.#f.signal})}catch(A){if(A?.code!=="send-rejected")throw A;let r=new Error("DingTalk rejected the proactive delivery target",{cause:A});throw r.code="target-rejected",r}return{sent:!0}}#y(){return typeof this.#r.pendingSenders=="function"?this.#r.pendingSenders():[]}};import{spawn as DEe}from"node:child_process";import{randomUUID as M_}from"node:crypto";import{isAbsolute as OEe}from"node:path";import{isAbsolute as CEe}from"node:path";var uEe=256,BEe=/[\p{White_Space}\p{Cc}\p{Cf}\p{Zl}\p{Zp}]/u,fEe=/[\p{Cc}\p{Cf}\p{Zl}\p{Zp}]/u;function JE(n,t){let o=new Error(t);return o.code=n,o}function QEe(n){if(typeof n!="string"||!n||n.length>uEe||BEe.test(n))throw JE("session-id-invalid","A non-empty, safe session id is required");return n}function yEe(n,t){if(!Array.isArray(t?.items)||!Array.isArray(t?.archivedSessionIds)||t.archivedSessionIds.some(i=>typeof i!="string"||!i))throw new Error("Harness returned an invalid response for workspace.list");let o=[];for(let i of t.items){if(typeof i?.workspaceId!="string"||!i.workspaceId||typeof i.path!="string"||!CEe(i.path)||!Array.isArray(i.sessionIds)||i.sessionIds.some(e=>typeof e!="string"||!e))throw new Error("Harness returned an invalid response for workspace.list");for(let e of i.sessionIds)e===n&&o.push(i)}if(o.length===0)throw JE("session-not-registered","The session is not registered to a Harness workspace");if(o.length!==1)throw JE("session-workspace-ambiguous","The session is registered to more than one Harness workspace");if(fEe.test(o[0].path))throw new Error("Harness returned an unsafe workspace path for the session");return{workspace:o[0],archived:t.archivedSessionIds.includes(n)}}function mEe(n,t){if(!Array.isArray(t?.items)||t.items.some(a=>typeof a?.sessionId!="string"||!a.sessionId))throw new Error("Harness returned an invalid response for session.list");let o=t.items.filter(a=>a.sessionId===n);if(o.length===0)throw JE("session-summary-unavailable","The session is no longer available from Harness");if(o.length!==1)throw new Error("Harness returned duplicate session summaries for session.list");let[i]=o;if(i.origin==="subagent")throw JE("session-subagent-unsupported","Subagent sessions cannot be adopted as a bot conversation");if(i.origin!==void 0)throw new Error("Harness returned an invalid session origin for session.list");let e=i.projections?.values?.title;if(e!=null&&typeof e!="string")throw new Error("Harness returned an invalid session title for session.list");return{title:typeof e=="string"?e:null}}async function i1(n,t,o={},i=3e4){let e=QEe(t);await n.ensureRunning(o);let a=await n.rpc("workspace.list",{},i,o),{workspace:A,archived:r}=yEe(e,a),s=mEe(e,await n.rpc("session.list",{},i,o)),g=await n.rpc("session.create",{workspaceId:A.workspaceId,sessionId:e},i,o);if(!g||g.sessionId!==e)throw new Error("Harness returned an invalid response for session.create");return{sessionId:e,workspace:A.path,title:s.title,archived:r}}function qE(n,t,o){try{let i=n?.(t);i&&typeof i.then=="function"&&Promise.resolve(i).catch(o)}catch(i){o(i)}}async function SEe({apiProxy:n,rpcId:t,signal:o,onOpen:i,onEnvelope:e}){let a=new AbortController,A=()=>a.abort(o.reason),r,s,g,c=I=>{a.signal.aborted||(g=I,A())};o.addEventListener("abort",A,{once:!0});try{for(r=n.events.mux({rpcId:t,payload:{}},a.signal)[Symbol.asyncIterator](),s=Promise.resolve(r.next()),a.signal.aborted||qE(i,A,c);!a.signal.aborted;){let{value:I,done:d}=await s;if(d||a.signal.aborted)break;qE(e,{type:"server-request",rpcId:I?.rpcId,method:I?.payload?.type,payload:I?.payload},c),a.signal.aborted||(s=Promise.resolve(r.next()))}}catch(I){c(I)}finally{let I=a.signal.aborted;o.removeEventListener("abort",A),A(),await s?.catch(()=>{});try{await r?.return?.()}catch(d){I||(g??=d)}}if(g)throw g}function wEe({baseUrl:n,createWebSocket:t,signal:o,onOpen:i,onEnvelope:e,onMalformed:a}){let A=new URL("/api/events.mux",n);return A.protocol=A.protocol==="https:"?"wss:":"ws:",new Promise((r,s)=>{let g=t(A.toString()),c=!1,I=!1,d=_=>{if(!I){I=!0,g.removeEventListener("open",f),g.removeEventListener("message",Q),g.removeEventListener("close",y),g.removeEventListener("error",m),o.removeEventListener("abort",T);try{(g.readyState===0||g.readyState===1)&&g.close()}catch{}_&&!o.aborted?s(_):r()}},B=()=>d(),f=()=>{I||c||(c=!0,qE(i,B,d))},Q=_=>{if(I)return;let R;try{if(typeof _.data!="string")throw new Error("binary WebSocket frame");R=JSON.parse(_.data)}catch(K){qE(a,K,()=>{});return}qE(e,R,d)},y=()=>d(c?void 0:new Error("Harness event mux WebSocket closed before opening")),m=()=>d(new Error(c?"Harness event mux WebSocket failed":"Harness event mux WebSocket failed before opening")),T=()=>d();g.addEventListener("open",f),g.addEventListener("message",Q),g.addEventListener("close",y,{once:!0}),g.addEventListener("error",m,{once:!0}),o.addEventListener("abort",T,{once:!0}),o.aborted&&T()})}async function o1(n){if(!n.signal.aborted)return n.baseUrl!==void 0&&n.baseUrl!==null?wEe(n):SEe(n)}var bEe=new Map,MEe=new WeakMap,_Ee=64;async function TEe(n){let t=n?.body;if(!t||typeof t.getReader!="function")return null;let o=t.getReader(),i=[],e=0;try{for(;;){let{done:r,value:s}=await o.read();if(r)break;if(!(s instanceof Uint8Array)||e+s.byteLength>_Ee)return null;i.push(s),e+=s.byteLength}}catch{return null}finally{try{await o.cancel()}catch{}}let a=new Uint8Array(e),A=0;for(let r of i)a.set(r,A),A+=r.byteLength;return new TextDecoder().decode(a)}function NEe(n){if(n==="localhost"||n==="[::1]")return!0;let t=n.split(".");return t.length===4&&t[0]==="127"&&t.every(o=>/^\d{1,3}$/.test(o)&&Number(o)<=255)}async function REe(n,t){return n.status===401?"harness-auth-required":n.status===407?"harness-proxy-auth-required":n.status===403?(await TEe(n))?.trim()!=="forbidden"?"harness-request-forbidden":NEe(t)?"harness-loopback-forbidden":"harness-host-untrusted":n.status===404?"harness-api-not-found":"harness-http-failed"}function l1(n){let t=typeof n=="string"?bEe:MEe,o=t.get(n);return o||(o={ownerships:new Map,claims:new Map,controls:new WeakMap,nextOrder:0},t.set(n,o)),o}function n1(n,t){return new Promise((o,i)=>{let e=()=>t.removeEventListener("abort",a),a=()=>{e(),i(t.reason)};if(t.aborted){a();return}t.addEventListener("abort",a,{once:!0}),Promise.resolve().then(()=>(t.throwIfAborted(),n())).then(A=>{e(),o(A)},A=>{e(),i(A)})})}function s1(n){let t=typeof n?.owner;return t!=="object"&&t!=="function"||n.owner===null||typeof n.key!="string"||!n.key?null:{owner:n.owner,key:n.key}}function __(n){return n!==null&&typeof n=="object"&&typeof n.provider=="string"&&!!n.provider&&typeof n.model=="string"&&!!n.model&&(n.reasoningEffort===void 0||typeof n.reasoningEffort=="string"&&!!n.reasoningEffort)}function kEe(n){return n!==null&&typeof n=="object"&&Array.isArray(n.efforts)&&n.efforts.length>0&&n.efforts.every(t=>t!==null&&typeof t=="object"&&typeof t.id=="string"&&!!t.id&&typeof t.name=="string"&&!!t.name&&(t.description===void 0||typeof t.description=="string"))&&(n.defaultEffort===void 0||typeof n.defaultEffort=="string"&&!!n.defaultEffort)}function g1(n,t,{session:o=!1}={}){if(!n||typeof n!="object"||!Array.isArray(n.groups)||!Array.isArray(n.failures))throw new Error(`Harness returned an invalid response for ${t}`);for(let i of n.groups){if(!i||typeof i!="object"||typeof i.id!="string"||!i.id||typeof i.name!="string"||!i.name||!Array.isArray(i.models))throw new Error(`Harness returned an invalid response for ${t}`);for(let e of i.models)if(!e||typeof e!="object"||typeof e.id!="string"||!e.id||typeof e.name!="string"||!e.name||e.description!==void 0&&typeof e.description!="string"||e.reasoning!==void 0&&!kEe(e.reasoning))throw new Error(`Harness returned an invalid response for ${t}`)}for(let i of n.failures)if(!i||typeof i!="object"||typeof i.id!="string"||!i.id||typeof i.name!="string"||!i.name||i.message!==void 0&&typeof i.message!="string")throw new Error(`Harness returned an invalid response for ${t}`);if(o&&(!__(n.current)||typeof n.routable!="boolean"))throw new Error(`Harness returned an invalid response for ${t}`);return n}function c1(){let n=new Error("Harness turn was stopped before producing a text reply");return n.code="turn-stopped",n}function vEe(n){return Array.isArray(n?.items)?n.items.flatMap(t=>typeof t?.path=="string"&&OEe(t.path)?[t.path]:[]):[]}function PEe(n,t){if(!Array.isArray(t?.items)||!Array.isArray(t?.archivedSessionIds))throw new Error("Harness returned an invalid response for workspace.list");let o=t.items.find(i=>i?.path===n);if(!o)return null;if(!Array.isArray(o.sessionIds)||o.sessionIds.some(i=>typeof i!="string"))throw new Error("Harness returned invalid session IDs for workspace.list");return o}function GEe(n){if(typeof n=="number"&&Number.isFinite(n))return n<1e12?n*1e3:n;if(typeof n=="string"&&n){let t=Date.parse(n);if(!Number.isNaN(t))return t}return null}function FEe(n){if(!n||typeof n!="object")return null;let t=[n?.header?.lastActivityAt,n?.header?.updatedAt,n?.header?.createdAt,n?.projections?.values?.lastActivityAt,n?.projections?.values?.updatedAt,n?.projections?.values?.createdAt,n?.lastActivityAt,n?.updatedAt,n?.createdAt];for(let o of t){let i=GEe(o);if(i!==null)return i}return null}function LEe(n,t,o){if(!Array.isArray(o?.items))throw new Error("Harness returned an invalid response for session.list");let i=new Set(t),e=new Map(o.items.flatMap(a=>typeof a?.sessionId=="string"?[[a.sessionId,a]]:[]));return{workspace:n.path,sessions:n.sessionIds.map(a=>{let A=e.get(a),r=A?.projections?.values?.title,s={sessionId:a,title:typeof r=="string"?r:null,archived:i.has(a),blank:A?.blank===!0,origin:A?.origin==="subagent"?"subagent":null,summaryAvailable:A!==void 0},g=A?.projections?.asOfSeq;Number.isSafeInteger(g)&&g>=-1&&(s.lastSeq=g);let c=FEe(A);return c!==null&&(s.time=c),s})}}function zE(n,t){return new Promise((o,i)=>{if(t?.aborted){i(t.reason??new DOMException("Aborted","AbortError"));return}let e=setTimeout(()=>{t?.removeEventListener("abort",a),o()},n),a=()=>{clearTimeout(e),i(t.reason??new DOMException("Aborted","AbortError"))};t?.addEventListener("abort",a,{once:!0})})}function UEe(n){return(n?.data?.message?.content??[]).filter(t=>t.type==="text"&&typeof t.text=="string").map(t=>t.text).join(` `).trim()}function Ri(n){return typeof n=="string"&&n.trim()?n.trim():null}function HEe(n){if(!n||typeof n!="object")return null;let t=Ri(n.message);if(t)return t;let o=Ri(n.name),i=Ri(n.code);return o||i?[o??"Error",i].filter(Boolean).join(": "):null}function p1(n,t){let o=[...t].map(i=>i?.event??i).filter(Boolean).sort((i,e)=>(i.seq??-1)-(e.seq??-1));for(let i of o){let e=i.seq??-1;if(e<=n.lastSeq)continue;if(n.lastSeq=e,i.type==="turn/start"){let A=i.data?.turn??null;n.active&&A!==n.turn&&(n.active=!1),n.turn!==null&&A!==n.turn&&(n.completed=!0),n.openTurn=A;continue}if(i.type==="user/message"&&i.data?.source?.rpcId===n.promptRpcId){n.active=!0,n.started=!0,n.completed=!1,n.turn=i.data?.turn??n.openTurn;continue}if(i.type==="turn/end"&&i.data?.turn===n.turn){n.active=!1,n.completed=!0;continue}let a=null;if(i.type==="tool/call"&&n.active&&i.data?.turn===n.turn&&typeof i.data?.callId=="string"&&i.data.callId)a={callId:i.data.callId,name:i.data?.name,arguments:i.data?.arguments};else if(i.type==="tool/code-dispatch-start"&&n.active&&typeof i.data?.subCallId=="string"&&i.data.subCallId){let A;try{A=JSON.stringify(i.data?.arguments)}catch{A=void 0}a={callId:i.data.subCallId,name:i.data?.name,arguments:A}}a&&n.toolCalls.set(a.callId,Object.freeze(a))}}function d1(n,t,o=[]){if(!n||!["object","function","string"].includes(typeof n)||typeof t!="string"||!t)return!1;let i=l1(n).ownerships.get(t);if(!i||i.size===0)return!1;for(let e of i)p1(e,o);return[...i].some(e=>e.active&&!e.completed&&typeof e.reconnect=="function")}var Gp=class{#e;#A;#t=null;#r=null;#l=new Map;#o="";#i=!1;#a=null;#n=new Map;#s=null;constructor({promptRpcId:t,afterSeq:o=-1}){this.#e=t,this.#A=o}get finished(){return this.#i}get answer(){return this.#o.trim()}get reason(){return this.#a}get tracking(){return this.#r!==null&&!this.#i}get turn(){return this.#r}consumeAll(t){let o=[],i=a=>{if(a.type==="text"&&o.length>0&&o[o.length-1].type==="text"){o[o.length-1]=a;return}o.push(a)},e=[...t].map(a=>a?.event??a).filter(Boolean).sort((a,A)=>(a.seq??-1)-(A.seq??-1));for(let a of e){let A=a.seq??-1;if(!(A<=this.#A)){if(this.#A=A,a.type==="turn/start"&&(this.#t=a.data?.turn??null),a.type==="user/message"&&a.data?.source?.rpcId===this.#e){this.#r=this.#t;continue}if(this.#r!==null){if(a.type==="turn/end"){if(a.data?.turn!==this.#r)continue;this.#i=!0,this.#a=a.data?.reason??null,this.#t=null;continue}if(a.data?.turn===this.#r){if(a.type==="assistant/chunk"&&a.data?.chunk?.type==="text-delta"){let r=a.data?.step??0,s=a.data.chunk.index??0,g=`${r}:${s}`;this.#l.set(g,(this.#l.get(g)??"")+a.data.chunk.text);let c=`${r}:`,I=[...this.#l.entries()].filter(([d])=>d.startsWith(c)).sort(([d],[B])=>Number(d.split(":")[1])-Number(B.split(":")[1])).map(([,d])=>d).join(` @@ -226,7 +226,7 @@ ${_}`:L;y&&await Q.finish(F)||await this.#v(g,F,this.#L(t))}catch{this.#n.error? `,o=this.#t.then(async()=>{await YEe(VEe(this.#e),{recursive:!0,mode:448});let i=`${this.#e}.tmp`;await zEe(i,t,{encoding:"utf8",mode:384}),await JEe(i,this.#e)});this.#t=o.then(()=>{},()=>{}),await o}};import{mkdir as XEe,readFile as $Ee,realpath as eCe,rename as ACe,stat as tCe,unlink as rCe,writeFile as aCe}from"node:fs/promises";import{dirname as iCe,isAbsolute as u1,resolve as WE}from"node:path";var V$e=Object.freeze({version:1,workspaces:Object.freeze({})});function PI(n){let t=new Error(n);return t.code=Ga,t}async function N_(n){return WE(await eCe(n))}async function oCe(n,t){if(n===t)return!0;try{return await N_(n)===await N_(t)}catch{return!1}}function xt(n){if(typeof n!="string"||!/^[A-Za-z0-9_-]{1,128}$/.test(n))throw new TypeError("Invalid bot id");return n}function ci(n,t,o){let i=new Error(t,o);return i.code=n,i}function PQ(n){if(typeof n!="string"||!/^[A-Za-z0-9._:@-]{1,128}$/.test(n))throw ci("invalid-target","Invalid target id");return n}function nCe(n){if(!n||typeof n!="object"||Array.isArray(n))throw ci("invalid-target","Invalid target route");try{let t=JSON.stringify(n);if(t===void 0)throw new TypeError("route is not JSON");let o=JSON.parse(t);if(!o||typeof o!="object"||Array.isArray(o))throw new TypeError("route is not an object");return o}catch(t){throw ci("invalid-target","Invalid target route",{cause:t})}}function GI(n,{targetId:t}={}){if(!n||typeof n!="object"||Array.isArray(n))throw ci("invalid-target","Invalid delivery target");let o=t===void 0?new Set(["targetId","name","kind","route"]):new Set(["name","kind","route"]);if(Object.keys(n).some(a=>!o.has(a)))throw ci("invalid-target","Invalid delivery target");let i=PQ(t??n.targetId);if(typeof n.kind!="string"||!/^[a-z][a-z0-9-]{0,31}$/.test(n.kind))throw ci("invalid-target","Invalid target kind");let e;if(n.name!==void 0){if(typeof n.name!="string"||!n.name.trim()||n.name.trim().length>80)throw ci("invalid-target","Invalid target name");e=n.name.trim()}return{targetId:i,...e===void 0?{}:{name:e},kind:n.kind,route:nCe(n.route)}}function sCe(n){let t=Object.create(null);if(n===void 0)return t;if(!n||typeof n!="object"||Array.isArray(n))return null;try{for(let[o,i]of Object.entries(n)){if(xt(o),!i||typeof i!="object"||Array.isArray(i))return null;let e=Object.create(null);for(let[a,A]of Object.entries(i)){let r=GI(A,{targetId:a}),{targetId:s,...g}=r;e[a]=g}t[o]=e}}catch{return null}return t}function gCe(n,t){let o=Object.create(null);if(n===void 0)return o;if(!n||typeof n!="object"||Array.isArray(n)){for(let i of Object.keys(t))o[i]=null;return o}for(let[i,e]of Object.entries(n))try{xt(i),o[i]=Pp(e)}catch{}return o}function cCe(n){if(!n||![1,2].includes(n.version)||!n.workspaces||typeof n.workspaces!="object"||Array.isArray(n.workspaces))return null;let t={};for(let[r,s]of Object.entries(n.workspaces)){if(!/^[A-Za-z0-9_-]{1,128}$/.test(r)||typeof s!="string"||!u1(s))return null;t[r]=WE(s)}let o={};if(n.agentPresets!==void 0){if(!n.agentPresets||typeof n.agentPresets!="object"||Array.isArray(n.agentPresets))return null;for(let[r,s]of Object.entries(n.agentPresets)){if(!/^[A-Za-z0-9_-]{1,128}$/.test(r))return null;try{let g=Tp(s);if(!g)return null;o[r]=g}catch{return null}}}let i=Object.create(null);if(n.contextEnhancement&&typeof n.contextEnhancement=="object"&&!Array.isArray(n.contextEnhancement))for(let[r,s]of Object.entries(n.contextEnhancement))/^[A-Za-z0-9_-]{1,128}$/.test(r)&&(i[r]=Rp(s));if(n.version===1&&n.deliveryTargets!==void 0)return null;let e=sCe(n.deliveryTargets);if(!e)return null;let a=gCe(n.accessPolicies,t);return{version:n.accessPolicies===void 0?n.version:2,workspaces:t,agentPresets:o,contextEnhancement:i,deliveryTargets:e,accessPolicies:a}}function ICe({version:n,workspaces:t,agentPresets:o,contextEnhancement:i,deliveryTargets:e,accessPolicies:a}){let A={version:n,workspaces:t};return Object.keys(o).length>0&&(A.agentPresets=o),Object.keys(i).length>0&&(A.contextEnhancement=i),n>=2&&Object.keys(e).length>0&&(A.deliveryTargets=e),n>=2&&Object.keys(a).length>0&&(A.accessPolicies=a),A}async function lCe(n,t){await XEe(iCe(n),{recursive:!0,mode:448});let o=`${n}.tmp`;await aCe(o,`${JSON.stringify(t,null,2)} `,{encoding:"utf8",mode:384}),await ACe(o,n)}async function E1(n){if(typeof n!="string"||!n.trim()||!u1(n.trim())){let i=new Error("\u5DE5\u4F5C\u533A\u5FC5\u987B\u662F\u7EDD\u5BF9\u8DEF\u5F84\u3002");throw i.code="workspace-not-absolute",i}let t=WE(n.trim()),o;try{o=await tCe(t)}catch(i){let e=new Error("\u5DE5\u4F5C\u533A\u8DEF\u5F84\u4E0D\u5B58\u5728\u3002",{cause:i});throw e.code="workspace-not-found",e}if(!o.isDirectory()){let i=new Error("\u5DE5\u4F5C\u533A\u8DEF\u5F84\u5FC5\u987B\u6307\u5411\u4E00\u4E2A\u76EE\u5F55\u3002");throw i.code="workspace-not-directory",i}return t}var ra=class{#e;#A;#t=1;#r={};#l={};#o={};#i=Object.create(null);#a=Object.create(null);#n=new Map;#s=1;#p=new Map;#c=1;#g=new Map;#I=new WeakMap;#d=new Set;#h=Promise.resolve();#C=new Map;constructor(t,{defaultWorkspace:o=process.cwd()}={}){if(typeof t!="string"||!t)throw new TypeError("workspace store path is required");this.#e=t,this.#A=WE(o)}async load(){try{let t=cCe(JSON.parse(await $Ee(this.#e,"utf8")));if(!t)throw new Error("dsh-im workspace config is invalid");this.#t=t.version,this.#r=t.workspaces,this.#l=t.agentPresets,this.#o=t.contextEnhancement,this.#i=t.deliveryTargets,this.#a=t.accessPolicies}catch(t){if(t?.code!=="ENOENT")throw t;this.#t=1,this.#r={},this.#l={},this.#o={},this.#i=Object.create(null),this.#a=Object.create(null)}this.#n.clear(),this.#s=1,this.#p.clear(),this.#c=1,this.#g.clear(),this.#d.clear();for(let t of Object.keys(this.#r))this.#n.set(t,this.#u()),this.#p.set(t,this.#B());return this}has(t){let o=xt(t);return Object.hasOwn(this.#r,o)&&!this.#g.has(o)}incarnationFor(t){return this.#p.get(xt(t))??null}workspaceFor(t){return this.#r[xt(t)]??this.#A}agentPresetFor(t){return this.#l[xt(t)]??null}contextEnhancementFor(t){let o=xt(t);return this.has(o)&&Object.hasOwn(this.#o,o)?this.#o[o]:h_}accessPolicyFor(t){let o=xt(t);return this.has(o)&&Object.hasOwn(this.#a,o)?this.#a[o]:null}listDeliveryTargets(t){let o=xt(t);if(!this.has(o))throw ci("unknown-bot","Unknown bot");return Object.entries(this.#i[o]??{}).map(([i,e])=>GI(e,{targetId:i})).sort((i,e)=>i.targetId.localeCompare(e.targetId))}deliveryTargetFor(t,o){let i=xt(t),e=PQ(o);if(!this.has(i))throw ci("unknown-bot","Unknown bot");let a=this.#i[i]?.[e];return a?GI(a,{targetId:e}):null}async createDeliveryTarget(t,o){let i=xt(t),e=GI(o);return this.#S(i,async()=>{if(!this.has(i))throw ci("unknown-bot","Unknown bot");if(Object.hasOwn(this.#i[i]??{},e.targetId))throw ci("target-conflict","Target already exists");let{targetId:a,...A}=e,r={...this.#i,[i]:{...this.#i[i]??{},[a]:A}};return await this.#y(this.#o,r,2),this.#i=r,this.#t=2,GI(A,{targetId:a})})}async updateDeliveryTarget(t,o,i){let e=xt(t),a=PQ(o),A=GI(i,{targetId:a});return this.#S(e,async()=>{if(!this.has(e))throw ci("unknown-bot","Unknown bot");if(!Object.hasOwn(this.#i[e]??{},a))throw ci("unknown-target","Unknown target");let{targetId:r,...s}=A,g={...this.#i,[e]:{...this.#i[e],[a]:s}};return await this.#y(this.#o,g,2),this.#i=g,this.#t=2,GI(s,{targetId:a})})}async deleteDeliveryTarget(t,o){let i=xt(t),e=PQ(o);return this.#S(i,async()=>{if(!this.has(i))throw ci("unknown-bot","Unknown bot");if(!Object.hasOwn(this.#i[i]??{},e))throw ci("unknown-target","Unknown target");let a={...this.#i[i]};delete a[e];let A={...this.#i};return Object.keys(a).length>0?A[i]=a:delete A[i],await this.#y(this.#o,A,2),this.#i=A,this.#t=2,!0})}generationFor(t){return this.#n.get(xt(t))??null}async whenIdle(){await this.#h}async whenBotIdle(t){let o=xt(t);for(;;){let i=this.#C.get(o);if(!i||(await i,this.#C.get(o)===i))return}}async ensure(t,{workspace:o=this.#A,defaultAgentPreset:i,initialAccessPolicy:e}={}){let a=xt(t),A=WE(o);return this.#S(a,async()=>{let r=!this.#r[a],s=e!==void 0&&!Object.hasOwn(this.#a,a);if(r||s){let g=s?Ic(e):void 0,c=r?Tp(i):null,I=Object.hasOwn(this.#l,a),d=this.#l[a],B=s?{...this.#a,[a]:g}:this.#a;r&&(this.#r[a]=A,c&&(this.#l[a]=c),this.#n.set(a,this.#u()),this.#p.set(a,this.#B()));let f=s?2:this.#t;try{await this.#y(this.#o,this.#i,f,B)}catch(Q){throw r&&(delete this.#r[a],I?this.#l[a]=d:delete this.#l[a],this.#n.delete(a),this.#p.delete(a)),Q}this.#a=B,this.#t=f}else this.#n.has(a)||this.#n.set(a,this.#u());return this.#r[a]})}async setWorkspace(t,o,{clearSessions:i,incarnation:e}={}){let a=xt(t);if(!this.has(a)||e!==void 0&&e!==this.incarnationFor(a)){let r=new Error("\u627E\u4E0D\u5230\u8981\u4FEE\u6539\u7684\u673A\u5668\u4EBA\u3002");throw r.code="workspace-bot-not-found",r}let A=await E1(o);return this.#S(a,async()=>{if(!this.has(a)||e!==void 0&&e!==this.incarnationFor(a)){let s=new Error("\u627E\u4E0D\u5230\u8981\u4FEE\u6539\u7684\u673A\u5668\u4EBA\u3002");throw s.code="workspace-bot-not-found",s}if(A===this.workspaceFor(a))return A;let r=this.#r[a];this.#n.set(a,this.#u()),await i?.(),this.#r[a]=A;try{await this.#y()}catch(s){throw this.#r[a]=r,s}return A})}async setAgentPreset(t,o,{incarnation:i}={}){let e=xt(t);if(!this.has(e)||i!==void 0&&i!==this.incarnationFor(e)){let A=new Error("\u627E\u4E0D\u5230\u8981\u4FEE\u6539\u7684\u673A\u5668\u4EBA\u3002");throw A.code="workspace-bot-not-found",A}let a=Tp(o);return this.#S(e,async()=>{if(!this.has(e)||i!==void 0&&i!==this.incarnationFor(e)){let r=new Error("\u627E\u4E0D\u5230\u8981\u4FEE\u6539\u7684\u673A\u5668\u4EBA\u3002");throw r.code="workspace-bot-not-found",r}let A=this.#l[e]??null;if(A===a)return a;a?this.#l[e]=a:delete this.#l[e];try{await this.#y()}catch(r){throw A?this.#l[e]=A:delete this.#l[e],r}return a})}async setContextEnhancement(t,o,{incarnation:i}={}){let e=xt(t),a=i===void 0?this.incarnationFor(e):i,A=kI(o);return this.#S(e,async()=>{if(!this.has(e)||a!==this.incarnationFor(e)){let s=new Error("\u627E\u4E0D\u5230\u8981\u4FEE\u6539\u7684\u673A\u5668\u4EBA\u3002");throw s.code="workspace-bot-not-found",s}let r={...this.#o,[e]:A};return await this.#y(r),this.#o=r,A})}async setAccessPolicy(t,o,{incarnation:i}={}){let e=xt(t),a=i===void 0?this.incarnationFor(e):i,A=Ic(o);return this.#S(e,async()=>{if(!this.has(e)||a!==this.incarnationFor(e)){let s=new Error("\u627E\u4E0D\u5230\u8981\u4FEE\u6539\u7684\u673A\u5668\u4EBA\u3002");throw s.code="workspace-bot-not-found",s}let r={...this.#a,[e]:A};return await this.#y(this.#o,this.#i,2,r),this.#a=r,this.#t=2,A})}async bindWorkspaceSession(t,o,{conversationKey:i,sessionId:e,clearSessions:a,setSession:A,incarnation:r,expectedGeneration:s}={}){let g=xt(t);if(typeof i!="string"||!i||typeof e!="string"||!e)throw new TypeError("conversationKey and sessionId are required");if(typeof a!="function"||typeof A!="function")throw new TypeError("session state callbacks are required");if(!this.has(g)||r!==void 0&&r!==this.incarnationFor(g)){let I=new Error("\u627E\u4E0D\u5230\u8981\u4FEE\u6539\u7684\u673A\u5668\u4EBA\u3002");throw I.code="workspace-bot-not-found",I}let c=await N_(await E1(o));return this.#S(g,async()=>{if(!this.has(g)||r!==void 0&&r!==this.incarnationFor(g)){let I=new Error("\u627E\u4E0D\u5230\u8981\u4FEE\u6539\u7684\u673A\u5668\u4EBA\u3002");throw I.code="workspace-bot-not-found",I}if(s!==void 0&&s!==this.generationFor(g))throw PI("The bot workspace changed before the session binding could be committed.");if(!await oCe(c,this.workspaceFor(g))){let I=this.#r[g];this.#n.set(g,this.#u()),await a(),this.#r[g]=c;try{await this.#y()}catch(d){throw this.#r[g]=I,d}}return await A(i,e),{workspace:c,sessionId:e,generation:this.#n.get(g)}})}async invalidateSessions(t,{clearSessions:o}={}){let i=xt(t);return this.#S(i,async()=>{this.#n.set(i,this.#u()),await o?.()})}async beginRemoval(t,{clearSessions:o}={}){let i=xt(t);return this.#S(i,async()=>{let e=this.#g.get(i);if(e)return e;let a=Object.freeze({});this.#g.set(i,a),this.#I.set(a,{botId:i,incarnation:this.incarnationFor(i)}),this.#n.set(i,this.#u());try{await o?.()}catch(A){throw this.#g.get(i)===a&&this.#g.delete(i),A}return a})}async abortRemoval(t){let{botId:o}=this.#f(t);return this.#S(o,async()=>this.#g.get(o)!==t?!1:(this.#g.delete(o),Object.hasOwn(this.#r,o)&&(this.#n.set(o,this.#u()),this.#p.has(o)||this.#p.set(o,this.#B())),!0))}async finishRemoval(t){let{botId:o,incarnation:i}=this.#f(t);return this.#S(o,async()=>this.#g.get(o)!==t?{removed:!1,persisted:!0,error:null,stale:!0}:this.incarnationFor(o)!==i?(this.#g.delete(o),{removed:!1,persisted:!0,error:null,stale:!0}):(this.#g.delete(o),this.#Q(o)))}async retireAfterConfigCommit(t){let o=xt(t);return this.#S(o,async()=>(this.#g.delete(o),this.#Q(o)))}flushPendingRemoval(t){if(this.#d.has(t))return this.#S(t,async()=>{this.#d.has(t)&&await this.#m()})}async remove(t){let o=await this.retireAfterConfigCommit(t);if(o.error)throw o.error;return o.removed}async reconcile(t){let o=new Set([...t].map(xt)),i=new Set([...Object.keys(this.#r),...Object.keys(this.#l),...Object.keys(this.#o),...Object.keys(this.#i),...Object.keys(this.#a),...this.#d]);for(let e of i)o.has(e)||await this.remove(e)}decorateStatus(t){return!t||typeof t!="object"||!Array.isArray(t.bots)?t:{...t,bots:t.bots.map(o=>o?.botId?{...o,workspace:this.workspaceFor(o.botId),agentPreset:this.agentPresetFor(o.botId),contextEnhancement:this.contextEnhancementFor(o.botId),accessPolicy:this.accessPolicyFor(o.botId)}:o)}}#u(){let t=this.#s;return this.#s+=1,t}#B(){let t=this.#c;return this.#c+=1,t}#f(t){if(!t||typeof t!="object")throw new TypeError("Invalid workspace removal transaction");let o=this.#I.get(t);if(!o)throw new TypeError("Invalid workspace removal transaction");return o}async#Q(t){let o=Object.hasOwn(this.#r,t),i=Object.hasOwn(this.#l,t),e=Object.hasOwn(this.#o,t),a=Object.hasOwn(this.#i,t),A=Object.hasOwn(this.#a,t),r=o||i||e||a||A||this.#d.has(t);if(delete this.#r[t],delete this.#l[t],delete this.#o[t],delete this.#i[t],delete this.#a[t],this.#n.delete(t),this.#p.delete(t),!r)return{removed:!1,persisted:!0,error:null,stale:!1};try{return await this.#m(),{removed:o,persisted:!0,error:null,stale:!1}}catch(s){return this.#d.add(t),{removed:o,persisted:!1,error:s,stale:!1}}}async#S(t,o){let i=this.#h.then(o,o),e=i.then(()=>{},()=>{});return this.#h=e,this.#C.set(t,e),e.finally(()=>{this.#C.get(t)===e&&this.#C.delete(t)}),i}async#y(t=this.#o,o=this.#i,i=this.#t,e=this.#a){await lCe(this.#e,ICe({version:i,workspaces:this.#r,agentPresets:this.#l,contextEnhancement:t,deliveryTargets:o,accessPolicies:e})),this.#d.clear()}async#m(){if(Object.keys(this.#r).length>0||Object.keys(this.#l).length>0||Object.keys(this.#o).length>0||Object.keys(this.#i).length>0||Object.keys(this.#a).length>0){await this.#y();return}try{await rCe(this.#e),this.#d.clear()}catch(t){if(t?.code!=="ENOENT")throw t;this.#d.clear()}}};function VE(n){if(!n)return null;let t=typeof n=="function"?n():n;return t&&typeof t.then=="function"?t.then($n):$n(t)}function B1(){let n=new Error("Agent Preset \u4E0D\u5B58\u5728\u6216\u4E0D\u53EF\u7528\u3002");return n.code="agent-preset-unavailable",n}function Lp(n){if(n())return;let t=new Error("\u627E\u4E0D\u5230\u8981\u4FEE\u6539\u7684\u673A\u5668\u4EBA\u3002");throw t.code="workspace-bot-not-found",t}function C1(n,t,o){let i=e=>{let a=n.decorateStatus(e);if(!o||!a||typeof a!="object")return a;let A=s=>s?{...a,agentPresetCatalog:s}:a,r=VE(o);return r&&typeof r.then=="function"?r.then(A):A(r)};return t&&typeof t.then=="function"?t.then(i):i(t)}function pCe(n){return Promise.resolve(n.status())}function Ha(n,{workspaces:t,method:o="remove",botIdFromRemoved:i=A=>A?.botId,saveMethod:e="save",botIdFromSave:a=A=>A?.botId}){if(!n||!t||typeof n[o]!="function")throw new TypeError("configStore removal observer dependencies are required");return new Proxy(n,{get(A,r){let s=Reflect.get(A,r,A);return r===o?async(...g)=>{let c=await s.apply(A,g),I=c?i(c,g):null;return I&&await t.retireAfterConfigCommit(I),c}:r===e&&typeof s=="function"?(...g)=>{let c=t.flushPendingRemoval(a(g[0],g));return c?c.then(()=>s.apply(A,g)):s.apply(A,g)}:typeof s=="function"?s.bind(A):s}})}function Ka(n,{botId:t,workspaces:o,state:i,agentPresetCatalog:e}={}){if(!n||!o||!i)throw new TypeError("harness, workspaces, and state are required");let a=o.incarnationFor(t),A=()=>o.has(t)&&o.incarnationFor(t)===a,r=async(I=e)=>{let d;try{d=await VE(I)??$n(null)}catch(B){throw Lp(A),B}return Lp(A),{agentPreset:o.agentPresetFor(t),agentPresetCatalog:d}},s=new Map,g=new Proxy(n,{get(I,d){if(d==="agentPresetSettings")return async(f={})=>{f?.signal?.throwIfAborted(),Lp(A);let Q=await r();return f?.signal?.throwIfAborted(),Q};if(d==="updateAgentPreset")return async(f,Q={})=>{Q?.signal?.throwIfAborted(),Lp(A);let y=f==="--default"?null:Tp(f),m=null;if(y&&({agentPresetCatalog:m}=await r(),Q?.signal?.throwIfAborted(),!m.items.some(T=>T.id===y)))throw B1();if(await o.setAgentPreset(t,y,{incarnation:a}),Lp(A),m)return{agentPreset:o.agentPresetFor(t),agentPresetCatalog:m};try{return await r()}catch(T){if(T?.code==="workspace-bot-not-found")throw T;return Lp(A),{agentPreset:o.agentPresetFor(t),agentPresetCatalog:$n(null)}}};if(d==="currentWorkspace")return()=>{if(!A()){let f=new Error("\u627E\u4E0D\u5230\u8981\u4FEE\u6539\u7684\u673A\u5668\u4EBA\u3002");throw f.code="workspace-bot-not-found",f}return o.workspaceFor(t)};if(d==="assertWorkspaceScope")return()=>{if(!A()){let f=new Error("\u627E\u4E0D\u5230\u8981\u4FEE\u6539\u7684\u673A\u5668\u4EBA\u3002");throw f.code="workspace-bot-not-found",f}};if((d==="listWorkspaces"||d==="listWorkspaceSessions"||d==="listModels")&&typeof I[d]=="function")return async(...f)=>{if(!A()){let y=new Error("\u627E\u4E0D\u5230\u8981\u4FEE\u6539\u7684\u673A\u5668\u4EBA\u3002");throw y.code="workspace-bot-not-found",y}let Q=await I[d](...f);if(!A()){let y=new Error("\u627E\u4E0D\u5230\u8981\u4FEE\u6539\u7684\u673A\u5668\u4EBA\u3002");throw y.code="workspace-bot-not-found",y}return Q};if(d==="switchWorkspace")return f=>{if(!A()){let Q=new Error("\u627E\u4E0D\u5230\u8981\u4FEE\u6539\u7684\u673A\u5668\u4EBA\u3002");return Q.code="workspace-bot-not-found",Promise.reject(Q)}return o.setWorkspace(t,f,{clearSessions:()=>i.clearSessions(),incarnation:a})};if(d==="bindWorkspaceSession")return async(f,Q)=>{if(typeof f!="string"||!f||typeof Q!="string"||!Q)throw new TypeError("conversationKey and sessionId are required");if(!A()){let _=new Error("\u627E\u4E0D\u5230\u8981\u4FEE\u6539\u7684\u673A\u5668\u4EBA\u3002");throw _.code="workspace-bot-not-found",_}if(typeof I.adoptWorkspaceSession!="function")throw new TypeError("Harness does not support adopting workspace sessions");let y=o.generationFor(t),m=await I.adoptWorkspaceSession(Q);if(!A()){let _=new Error("\u627E\u4E0D\u5230\u8981\u4FEE\u6539\u7684\u673A\u5668\u4EBA\u3002");throw _.code="workspace-bot-not-found",_}if(y!==o.generationFor(t))throw PI("The bot workspace changed while the session was being adopted.");if(!m||typeof m!="object"||m.sessionId!==Q||typeof m.workspace!="string")throw new TypeError("Harness returned an invalid adopted workspace session");let T=await o.bindWorkspaceSession(t,m.workspace,{conversationKey:f,sessionId:Q,clearSessions:()=>i.clearSessions(),setSession:(_,R)=>i.setSession(_,R),incarnation:a,expectedGeneration:y});if(!A()){let _=new Error("\u627E\u4E0D\u5230\u8981\u4FEE\u6539\u7684\u673A\u5668\u4EBA\u3002");throw _.code="workspace-bot-not-found",_}if(T.generation!==o.generationFor(t))throw PI("The bot workspace changed before the session binding completed.");return s.set(Q,T.generation),{...m,workspace:T.workspace,sessionId:T.sessionId}};if(d==="createSession")return async(f={})=>{if(await o.whenBotIdle(t),!A()){let T=new Error("\u627E\u4E0D\u5230\u8981\u4FEE\u6539\u7684\u673A\u5668\u4EBA\u3002");throw T.code="workspace-bot-not-found",T}let Q=o.generationFor(t),y=o.agentPresetFor(t),m=await I.createSession({...f,workspace:o.workspaceFor(t),...y==null?{}:{agentPreset:y}});return s.set(m,Q),m};if(d==="workspaceSession")return f=>{if(typeof f!="string"||!f)throw new TypeError("sessionId is required");let Q=s.get(f)??o.generationFor(t);s.delete(f);let y=()=>A()&&Q===o.generationFor(t),m=async(_,R,K)=>{if(!y())throw PI(`The bot workspace changed before this ${K} started.`);let L=await I[_](f,...R);if(!y())throw PI(`The bot workspace changed while this ${K} was running.`);return L},T=async(_,R,K)=>{if(!y())throw PI(`The bot workspace changed before this ${K} started.`);return I[_](f,...R)};return Object.freeze({sessionId:f,async sessionExists(..._){if(!y())return!1;let R=await I.sessionExists(f,..._);return y()&&R},models(..._){return m("getSessionModels",_,"model listing")},readHistory(..._){return m("readSessionHistory",_,"history read")},selectModel(..._){return m("selectSessionModel",_,"model selection")},isRunning(..._){return m("isSessionRunning",_,"run-state check")},hasActiveTurn(..._){return m("hasActiveTurn",_,"turn ownership check")},stopActiveTurn(..._){return T("stopActiveTurn",_,"turn stop")},steerActiveTurn(..._){return T("steerActiveTurn",_,"turn steering")},ask(..._){if(!y())throw PI("The bot workspace changed before this prompt started.");return I.ask(f,..._)}})};if(d==="sessionExists")return(f,...Q)=>{if(!A())return!1;let y=s.get(f);return y!==void 0&&y!==o.generationFor(t)?(s.delete(f),!1):I.sessionExists(f,...Q)};if(d==="ask")return(f,...Q)=>{let y=s.get(f);if(s.delete(f),!A()||y!==void 0&&y!==o.generationFor(t)){let m=new Error("The bot workspace changed before this prompt started.");throw m.code=Ga,m}return I.ask(f,...Q)};if(d==="executeCommand"&&typeof I.executeCommand=="function")return(f,...Q)=>{let y=s.get(f);if(s.delete(f),!A()||y!==void 0&&y!==o.generationFor(t)){let m=new Error("The bot workspace changed before this command started.");throw m.code=Ga,m}return I.executeCommand(f,...Q)};let B=Reflect.get(I,d,I);return typeof B=="function"?B.bind(I):B}}),c=new Proxy(i,{get(I,d){if(d===KM)return I;if(d==="sessionFor")return(f,...Q)=>{if(!A())return null;let y=I.sessionFor(f,...Q);return y&&!s.has(y)&&s.set(y,o.generationFor(t)),y};if(d==="setSession")return(f,Q,...y)=>{let m=s.get(Q);return!A()||m!==void 0&&m!==o.generationFor(t)?(s.delete(Q),!1):I.setSession(f,Q,...y)};let B=Reflect.get(I,d,I);return typeof B=="function"?B.bind(I):B}});return Object.freeze({harness:g,state:c})}function xa(n,{workspaces:t,stateFor:o,agentPresetCatalog:i}={}){if(!n||!t||typeof o!="function")throw new TypeError("controller, workspaces, and stateFor are required");let e=new Map,a=(d,B)=>{let Q=(e.get(d)??Promise.resolve()).catch(()=>{}).then(B);return e.set(d,Q),Q.finally(()=>{e.get(d)===Q&&e.delete(d)})},A=d=>C1(t,d,i),r=(d,B)=>{let f=t.incarnationFor(d);return a(d,async()=>{if(!(await n.status())?.bots?.some(m=>m?.botId===d)){let m=new Error("\u627E\u4E0D\u5230\u8981\u4FEE\u6539\u7684\u673A\u5668\u4EBA\u3002");throw m.code="workspace-bot-not-found",m}let y=await o(d);return await t.setWorkspace(d,B,{clearSessions:()=>y.clearSessions(),incarnation:f}),A(await n.status())})},s=(d,B)=>{let f=t.incarnationFor(d),Q=Tp(B);return a(d,async()=>{if(!(await n.status())?.bots?.some(T=>T?.botId===d)){let T=new Error("\u627E\u4E0D\u5230\u8981\u4FEE\u6539\u7684\u673A\u5668\u4EBA\u3002");throw T.code="workspace-bot-not-found",T}let m=Q&&i?await VE(i):null;if(Q&&i&&!m?.items.some(T=>T.id===Q))throw B1();return await t.setAgentPreset(d,Q,{incarnation:f}),C1(t,await n.status(),m??i)})},g=(d,B,f)=>{let Q=t.incarnationFor(d),y=kI(B);return a(d,async()=>{let m=await n.status();if(!m?.bots?.some(L=>L?.botId===d)){let L=new Error("\u627E\u4E0D\u5230\u8981\u4FEE\u6539\u7684\u673A\u5668\u4EBA\u3002");throw L.code="workspace-bot-not-found",L}let T=await VE(i),_=t.decorateStatus(m),R={..._,bots:_.bots.map(L=>L?.botId===d?{...L,contextEnhancement:y}:L),...T?{agentPresetCatalog:T}:{}},K=f?await f(R):R;return await t.setContextEnhancement(d,y,{incarnation:Q}),K})},c=(d,B,f)=>{let Q=t.incarnationFor(d),y=Ic(B);return a(d,async()=>{let m=await n.status();if(!m?.bots?.some(L=>L?.botId===d)){let L=new Error("\u627E\u4E0D\u5230\u8981\u4FEE\u6539\u7684\u673A\u5668\u4EBA\u3002");throw L.code="workspace-bot-not-found",L}let T=await VE(i),_=t.decorateStatus(m),R={..._,bots:_.bots.map(L=>L?.botId===d?{...L,accessPolicy:y}:L),...T?{agentPresetCatalog:T}:{}},K=f?await f(R):R;return await t.setAccessPolicy(d,y,{incarnation:Q}),K})},I=(d,B)=>a(d,async()=>{let f=await t.beginRemoval(d,{clearSessions:async()=>{try{let Q=await o(d);if(!Q||typeof Q.clearSessions!="function")throw new TypeError("bot state does not support session cleanup");await Q.clearSessions()}catch(Q){console.warn(`[dsh-im] ignored session cleanup failure while deleting bot ${d}:`,Q?.message??Q)}}});try{let Q=await B();return await t.finishRemoval(f),A(Q)}catch(Q){let y=await pCe(n).catch(()=>null);throw Array.isArray(y?.bots)&&!y.bots.some(T=>T?.botId===d)?await t.finishRemoval(f):await t.abortRemoval(f),Q}});return new Proxy(n,{get(d,B){if(B==="updateWorkspace")return r;if(B==="updateAgentPreset")return s;if(B==="updateContextEnhancement")return g;if(B==="updateAccessPolicy")return c;let f=Reflect.get(d,B,d);return typeof f!="function"?f:B==="deleteBot"?(Q,...y)=>I(Q,()=>f.call(d,Q,...y)):B==="disconnect"?async(...Q)=>{let m=(await d.status())?.bots?.[0]?.botId;return m?I(m,()=>f.apply(d,Q)):A(f.apply(d,Q))}:(...Q)=>A(f.apply(d,Q))}})}var f1=new Set(["weixin","feishu","dingtalk","wecom","qq","slack","telegram","discord","whatsapp"]);function dCe(n){return n!==null&&typeof n=="object"&&!Array.isArray(n)}function hCe(n){return typeof n=="string"&&n.length>0&&n.length<=512&&n.trim()===n&&!/[\s:\u0000-\u001f\u007f]/u.test(n)}function R_(n,t){let o=`${t}:`;if(!n.startsWith(o))return null;let i=n.slice(o.length);return hCe(i)?i:null}function ZE(n,t){for(let[o,i,e]of t){let a=R_(n,o);if(a)return{kind:i,route:{[e]:a}}}return null}function ECe(n){let t=R_(n,"p2p");return t?.startsWith("ou_")?{kind:"user",route:{openId:t}}:ZE(n,[["group","group","chatId"]])}function CCe(n){let t=R_(n,"direct");if(t&&/^[A-Za-z0-9_-]{1,128}$/.test(t))return{kind:"conversation",route:{channelId:t}};let o=/^group:([^:]+):(\d{1,20}(?:\.\d{1,20})?)$/.exec(n);return!o||!/^[A-Za-z0-9_-]{1,128}$/.test(o[1])?null:{kind:"thread",route:{channelId:o[1],threadTs:o[2]}}}function uCe(n){let t=/^(direct|group):(-?\d+)(?::([1-9]\d*))?$/.exec(n);if(!t)return null;let o=Number(t[2]);if(!Number.isSafeInteger(o)||t[1]==="direct"&&t[3]!==void 0)return null;if(t[3]===void 0)return{kind:"chat",route:{chatId:t[2]}};let i=Number(t[3]);return!Number.isSafeInteger(i)||i<=0?null:{kind:"topic",route:{chatId:t[2],messageThreadId:i}}}function BCe(n){let t=/^(?:direct|group):(\d{1,32})$/.exec(n);return t?{kind:"channel",route:{channelId:t[1]}}:null}function fCe(n){let t=/^direct:(\d{5,32}@(s\.whatsapp\.net|lid))$/.exec(n);if(t)return{kind:"user",route:{jid:t[1]}};let o=/^group:(\d{5,32}(?:-\d{1,32})?@g\.us)$/.exec(n);return o?{kind:"group",route:{jid:o[1]}}:null}function QCe(n,t){if(!f1.has(n)||typeof t!="string")return null;switch(n){case"weixin":return ZE(t,[["p2p","user","toUserId"]]);case"feishu":return ECe(t);case"dingtalk":return ZE(t,[["p2p","user","userId"],["group","group","openConversationId"]]);case"wecom":return ZE(t,[["direct","user","chatId"],["group","group","chatId"]]);case"qq":return ZE(t,[["c2c","user","userOpenId"],["group","group","groupOpenId"]]);case"slack":return CCe(t);case"telegram":return uCe(t);case"discord":return BCe(t);case"whatsapp":return fCe(t);default:return null}}function Q1(n,t){if(!f1.has(n)||!dCe(t))return[];let o=[],i=new Set;for(let e of Object.keys(t)){let a=QCe(n,e);if(!a)continue;let A=JSON.stringify(a);i.has(A)||(i.add(A),o.push(a))}return o}var yCe=new Set(["weixin","feishu","dingtalk","wecom","qq","slack","telegram","discord","whatsapp"]);function FQ(n){return yCe.has(n)}function pc(n){let t=new Error(n);return t.code="invalid-target",t}function mCe(n){return n!==null&&typeof n=="object"&&!Array.isArray(n)}function k_(n,t,o){if(!mCe(n))throw pc(`${o} must be an object`);if(Object.keys(n).find(e=>!t.includes(e))!==void 0)throw pc(`${o} contains an unknown field`)}function GQ(n,t){if(typeof n!="string"||!n||n.trim()!==n)throw pc(`${t} must be a non-empty string without surrounding whitespace`);return n}function SCe(n){if(typeof n!="string"||!n.trim()||n.trim().length>80)throw pc("target.name must contain 1 to 80 characters");return n.trim()}function lc(n,t){k_(n,t,"route");let o={};for(let i of t)o[i]=GQ(n[i],`route.${i}`);return o}function lg(n,t){if(!t.includes(n))throw pc("target kind is not supported by this channel");return n}function wCe(n,t,o){switch(n){case"weixin":return lg(t,["user"]),lc(o,["toUserId"]);case"feishu":return lg(t,["user","group"]),lc(o,t==="user"?["openId"]:["chatId"]);case"dingtalk":return lg(t,["user","group"]),lc(o,t==="user"?["userId"]:["openConversationId"]);case"wecom":return lg(t,["user","group"]),lc(o,["chatId"]);case"qq":return lg(t,["user","group"]),lc(o,t==="user"?["userOpenId"]:["groupOpenId"]);case"slack":return lg(t,["conversation","thread"]),lc(o,t==="conversation"?["channelId"]:["channelId","threadTs"]);case"telegram":{lg(t,["chat","topic"]),k_(o,t==="chat"?["chatId"]:["chatId","messageThreadId"],"route");let i=GQ(o.chatId,"route.chatId");if(!/^-?\d+$/.test(i))throw pc("route.chatId must be a decimal string");if(t==="chat")return{chatId:i};if(!Number.isSafeInteger(o.messageThreadId)||o.messageThreadId<=0)throw pc("route.messageThreadId must be a positive integer");return{chatId:i,messageThreadId:o.messageThreadId}}case"discord":return lg(t,["channel"]),lc(o,["channelId"]);case"whatsapp":{lg(t,["user","group"]);let i=lc(o,["jid"]);if(!(t==="user"?/^\d{5,32}@(s\.whatsapp\.net|lid)$/.test(i.jid):/^\d{5,32}(?:-\d{1,32})?@g\.us$/.test(i.jid)))throw pc(`route.jid must be a ${t} WhatsApp JID`);return i}default:throw new TypeError(`Unsupported delivery channel: ${n}`)}}function Up(n,t,{targetIdRequired:o=!0}={}){if(!FQ(n))throw new TypeError(`Unsupported delivery channel: ${n}`);k_(t,o?["targetId","name","kind","route"]:["name","kind","route"],"target");let i={};return o&&(i.targetId=GQ(t.targetId,"target.targetId")),t.name!==void 0&&(i.name=SCe(t.name)),i.kind=GQ(t.kind,"target.kind"),i.route=wCe(n,i.kind,t.route),i}function Ya({channel:n,workspaces:t,coreController:o,stateFor:i}){if(!FQ(n))throw new TypeError(`Unsupported delivery channel: ${n}`);if(!t||typeof t!="object")throw new TypeError("delivery adapter requires a workspace store");if(!o||typeof o!="object")throw new TypeError("delivery adapter requires a proactive text controller");if(typeof i!="function")throw new TypeError("delivery adapter requires a bot state getter");return Object.freeze({channel:n,ownsBot:e=>t.has(e),listTargets:e=>t.listDeliveryTargets(e),async listSuggestions(e){let a=await i(e);if(!a||typeof a.snapshot!="function")throw new TypeError("delivery suggestion state cannot be inspected");return Q1(n,a.snapshot()?.sessions).map(r=>Up(n,r,{targetIdRequired:!1}))},createTarget:(e,a)=>t.createDeliveryTarget(e,Up(n,a)),updateTarget:(e,a,A)=>t.updateDeliveryTarget(e,a,Up(n,A,{targetIdRequired:!1})),deleteTarget:(e,a)=>t.deleteDeliveryTarget(e,a),async sendText(e,a,A,r={}){let s=Up(n,a);if(typeof o.sendProactiveText!="function")throw new TypeError("delivery controller cannot send proactive text");return await o.sendProactiveText(e,s,A,r),{sent:!0}}})}var y1=Object.freeze([250,1e3,3e3,5e3,1e4,3e4]);function DCe(n){if(!Array.isArray(n)||n.length===0)return[...y1];let t=n.filter(o=>Number.isFinite(o)&&o>=0);return t.length>0?t:[...y1]}var LQ=class{#e;#A;#t;#r;#l;#o;#i;#a=null;#n=null;#s=0;#p=!1;#c=!1;#g;#I;constructor({controller:t,harness:o,logger:i=console,retryDelaysMs:e,healthyIntervalMs:a=15e3,setTimeoutImpl:A=setTimeout,clearTimeoutImpl:r=clearTimeout}){if(!t||typeof t.initialize!="function"||typeof t.status!="function")throw new TypeError("ConnectionSupervisor requires a controller");if(!o||typeof o.ensureRunning!="function")throw new TypeError("ConnectionSupervisor requires a Harness client");this.#e=t,this.#A=o,this.#t=i,this.#r=DCe(e),this.#l=Number.isFinite(a)&&a>=0?a:15e3,this.#o=A,this.#i=r,this.#g=new Promise(s=>{this.#I=s})}get ready(){return this.#g}start(){return this.#c||this.#p?this:(this.#c=!0,this.#d(0),this)}async close(){this.#p||(this.#p=!0,this.#a!==null&&this.#i(this.#a),this.#a=null,await this.#n?.catch(()=>{}),this.#I?.(null),this.#I=null)}#d(t){this.#p||(this.#a=this.#o(()=>{this.#a=null,this.#h()},t),this.#a?.unref?.())}async#h(){if(this.#p||this.#n)return;let t=this.#C();this.#n=t;try{await t}finally{this.#n===t&&(this.#n=null)}}async#C(){try{if(await this.#A.ensureRunning(),this.#p)return;let t=await this.#e.initialize();if(this.#p)return;this.#I?.(t),this.#I=null;let{configured:o,connected:i}=t.totals;if(i{let A={namespace:"commands",method:"execute",args:{agentId:i,line:e,images:[]},signal:a.signal};try{return await o.invoke(A)}catch(r){if(r?.name!=="TypertGatewayError"||r.code!=="arguments-invalid"||r.endpoint!=="commands/execute"||r.message!=='typert gateway: commands/execute: args fields do not match the descriptor: unexpected "images"')throw r;return a.signal?.throwIfAborted(),o.invoke({...A,args:{agentId:i,line:e}})}}}}import{randomUUID as P_}from"node:crypto";var UQ=new WeakMap;function OCe(n){let t=n?.failure;return t&&typeof t=="object"&&typeof t.code=="string"&&typeof t.message=="string"?{code:t.code,message:t.message,details:t.details&&typeof t.details=="object"?t.details:{}}:n?.name==="AbortError"||n?.name==="RemoteInvocationCancelled"?{code:"cancelled",message:n instanceof Error?n.message:"Harness request was cancelled",details:{}}:{code:"internal",message:n instanceof Error?n.message:String(n),details:{}}}function fn(n,t){return Promise.resolve().then(t).then(o=>({rpcId:n.rpcId,result:{ok:!0,value:o}}),o=>({rpcId:n.rpcId,result:{ok:!1,error:OCe(o)}}))}function m1(n,t,o,i){return{namespace:n,method:t,args:o,...i===void 0?{}:{signal:i}}}function HQ(n,t){let o=new Error(n);return o.name="UserQuestionError",o.code=t,o}function bCe(n,t){return!n||typeof n!="object"||n.sessionId!==t.sessionId||!n.answer||typeof n.answer!="object"||!Array.isArray(n.answer.answers)||n.answer.answers.length!==t.questions.length?!1:n.answer.answers.every((o,i)=>{let e=t.questions[i];if(!o||typeof o!="object"||o.id!==e.id||!Array.isArray(o.selected)||o.selected.some(r=>typeof r!="string")||new Set(o.selected).size!==o.selected.length||o.custom!==void 0&&typeof o.custom!="string")return!1;let a=o.custom?.trim();if(a!==void 0&&!a||e.multiSelect!==!0&&(a!==void 0&&o.selected.length>0||o.selected.length>1))return!1;let A=new Set(e.options?.map(r=>r.label)??[]);return o.selected.every(r=>A.has(r))})}function MCe(n){if(n?.type==="event"&&n.event&&typeof n.event=="object")return[{event:n.event}];let t=n?.type==="chunks"?n.event:null;if(!t||typeof t!="object")throw new Error("Harness returned an invalid session history record");let{data:o}=t,i=t.type,e=i==="chunkrow/tool-call-chunks"?o?.args:o?.texts;if(!o||!Array.isArray(e)||e.length===0||e.some(A=>typeof A!="string")||!Array.isArray(o.dt)||o.dt.length!==e.length-1)throw new Error("Harness returned an invalid packed session chunk");let a=t.time;return e.map((A,r)=>{r>0&&(a+=o.dt[r-1]);let s;if(i==="chunkrow/text-chunks")s={type:"text-delta",index:o.index,text:A};else if(i==="chunkrow/reasoning-chunks")s={type:"reasoning-delta",index:o.index,text:A};else if(i==="chunkrow/tool-call-chunks")s={type:"tool-call-delta",index:o.index,id:o.id,...Object.hasOwn(o,"name")?{name:o.name}:{},argumentsDelta:A};else throw new Error(`Harness returned an unsupported packed session chunk: ${String(i)}`);return{event:{type:"assistant/chunk",seq:t.seq+r,time:a,data:{turn:o.turn,step:o.step,chunk:s}}}})}function S1(n){if(!Array.isArray(n))throw new Error("Harness returned invalid session history records");return n.flatMap(MCe)}var G_=class{#e=[];#A=null;#t=!1;#r;#l;#o;constructor(t,o){this.#r=t,this.#o=o,this.#l=()=>this.close(),t?.addEventListener("abort",this.#l,{once:!0}),t?.aborted&&this.close()}push(t){if(!this.#t)if(this.#A){let o=this.#A;this.#A=null,o({value:t,done:!1})}else this.#e.push(t)}next(){return this.#e.length>0?Promise.resolve({value:this.#e.shift(),done:!1}):this.#t?Promise.resolve({value:void 0,done:!0}):new Promise(t=>{this.#A=t})}return(){return this.close(),Promise.resolve({value:void 0,done:!0})}close(){if(!this.#t&&(this.#t=!0,this.#r?.removeEventListener("abort",this.#l),this.#o?.(),this.#o=null,this.#A)){let t=this.#A;this.#A=null,t({value:void 0,done:!0})}}[Symbol.asyncIterator](){return this}},F_=class{#e;#A;#t=new Set;#r=new Map;#l=new Map;#o=new Map;#i=[];#a=!1;constructor(t,o,i){this.#e=o,this.#A=i,this.host=Object.freeze({describe:e=>fn(e,()=>({ready:!0,transport:"typert"}))}),this.workspace=Object.freeze({list:(e,a)=>fn(e,()=>this.#p(a)),create:(e,a)=>fn(e,()=>this.#n("workspace","create",{request:e.payload},a))}),this.sessions=Object.freeze({list:(e,a)=>fn(e,()=>this.#n("session","list",{_request:e.payload},a)),create:(e,a)=>fn(e,()=>this.#n("session","create",{request:e.payload},a)),history:(e,a)=>fn(e,()=>this.#g(e.payload,a)),prompt:(e,a)=>fn(e,()=>this.#n("session","prompt",{request:{requestId:e.rpcId,...e.payload}},a)),cancel:(e,a)=>fn(e,()=>this.#n("session","cancel",{request:{sessionId:e.payload.sessionId}},a)),models:(e,a)=>fn(e,()=>this.#h(e.payload.sessionId,a)),selectModel:(e,a)=>fn(e,()=>this.#n("session","selectModel",{request:e.payload},a))}),this.llm=Object.freeze({models:(e,a)=>fn(e,async()=>{let A=await this.#d(a);return{groups:A.groups,failures:A.failures}})}),this.events=Object.freeze({mux:(e,a)=>this.#C(a)}),this.respond=e=>Promise.resolve(this.#m(e)),typeof t?.on=="function"&&(this.#i.push(t.on("session/event",(e,a)=>{let A=e?.id;typeof A!="string"||!a||typeof a!="object"||(Number.isSafeInteger(a.seq)&&this.#I(A,a.seq),this.#u({type:"session/event",sessionId:A,event:a}))},{global:!0})),this.#i.push(t.on("approval/request",(e,a)=>this.#y(e,a),{global:!0,prepend:!0})),this.#i.push(t.on("user-questions/request",(e,a)=>this.#Q(e,a),{global:!0,prepend:!0})))}async#n(t,o,i,e){return this.#e.invoke(m1(t,o,i,e))}async#s(t,o,i,e){let a=new AbortController,A=e?AbortSignal.any([e,a.signal]):a.signal,r;try{r=(await this.#e.stream(m1(t,o,i,A)))[Symbol.asyncIterator]();let g=await r.next();if(g.done)throw new Error(`Harness ${t}.${o} stream ended before its baseline`);return g.value}finally{a.abort(new DOMException("Baseline received","AbortError")),await Promise.resolve(r?.return?.()).catch(()=>{})}}async#p(t){let o=await this.#s("workspace","follow",{},t);if(o?.type!=="baseline"||!o.value||typeof o.value!="object")throw new Error("Harness workspace.follow returned no baseline");return o.value}async#c(t,o,i){let e=await this.#s("session","follow",{request:{address:{kind:"session",sessionId:t},maxMessages:o}},i);if(e?.type!=="snapshot"||!Number.isSafeInteger(e.cursor))throw new Error("Harness session.follow returned no snapshot");return this.#I(t,e.cursor),e}async#g(t,o){let{sessionId:i,maxMessages:e=50,beforeSeq:a}=t,A=this.#o.get(i);if(A===void 0){let s=await this.#c(i,e,o);if(A=this.#o.get(i)??s.cursor,a===void 0&&A===s.cursor)return{events:S1(s.records),hasMore:s.hasMore===!0,...s.projections===void 0?{}:{projections:s.projections}}}let r=await this.#n("session","page",{request:{address:{kind:"session",sessionId:i},throughSeq:A,maxMessages:e,...a===void 0?{}:{beforeSeq:a}}},o);return{events:S1(r.records),hasMore:r.hasMore===!0}}#I(t,o){let i=this.#o.get(t);(i===void 0||o>i)&&this.#o.set(t,o)}#d(t){return this.#n("session","modelCatalog",{},t)}async#h(t,o){let[i,e]=await Promise.all([this.#d(o),this.#n("session","list",{_request:{}},o)]),a=e?.items?.find(s=>s?.sessionId===t);if(!a){let s=new Error(`session "${t}" not found`);throw s.failure={code:"session-not-found",message:s.message,details:{sessionId:t}},s}let A=a.projections?.values?.modelSelection,r=A?.next??A?.lastUsed??i.default;return{current:r,routable:i.routableProviders.includes(r.provider),groups:i.groups,failures:i.failures}}#C(t){let o;o=new G_(t,()=>this.#t.delete(o)),this.#t.add(o);for(let i of this.#r.values())o.push(this.#f(i));for(let i of this.#l.values())o.push(this.#S(i));return o}#u(t,o=P_()){let i={rpcId:o,payload:t};for(let e of this.#t)e.push(i)}#B(t){let o=t?.session?.id??t?.id;return typeof o!="string"||!t?.session||!Array.isArray(t.session.events)?null:d1(this.#A,o,t.session.events)?{sessionId:o,session:t.session}:null}#f(t){return{rpcId:t.rpcId,payload:{type:"question/requested",sessionId:t.sessionId,questions:t.questions}}}#Q(t,o){let i=this.#B(t?.agent);return i?t.signal?.aborted?Promise.reject(HQ("ask_user_question was aborted before the user answered","ASK_ABORTED")):new Promise((e,a)=>{let A={rpcId:P_(),sessionId:i.sessionId,questions:t.questions,signal:t.signal,settle:(s,g)=>{this.#r.delete(A.rpcId)&&(t.signal?.removeEventListener("abort",r),this.#u({type:"question/resolved",sessionId:A.sessionId,questionRpcId:A.rpcId,outcome:s}),s==="answered"?e(g):a(g))}},r=()=>A.settle("cancelled",HQ("ask_user_question was aborted before the user answered","ASK_ABORTED"));this.#r.set(A.rpcId,A),t.signal?.addEventListener("abort",r,{once:!0}),this.#u(this.#f(A).payload,A.rpcId)}):o()}#S(t){return{rpcId:t.rpcId,payload:{type:"approval/requested",sessionId:t.sessionId,approvalId:t.approvalId,toolName:t.toolName,...t.callId===void 0?{}:{callId:t.callId},...t.reason===void 0?{}:{reason:t.reason}}}}#y(t,o){let i=this.#B(t?.agent);if(!i)return o();if(t.signal?.aborted)return Promise.resolve("cancelled");let e=new Set([...this.#l.values()].map(r=>r.approvalId)),a=new Set,A;for(let r=i.session.events.length-1;r>=0;r-=1){let s=i.session.events[r];if(s.type==="approval/decided")a.add(s.data?.id);else if(s.type==="approval/asked"){let g=s.data?.id;if(!g||a.has(g)||e.has(g)||(t.callId??null)!==(s.data?.callId??null))continue;A=g;break}}return A===void 0?o():new Promise(r=>{let s={rpcId:P_(),sessionId:i.sessionId,approvalId:A,toolName:t.toolName,callId:t.callId,reason:t.reason,settle:c=>{this.#l.delete(s.rpcId)&&(t.signal?.removeEventListener("abort",g),this.#u({type:"approval/resolved",sessionId:s.sessionId,approvalId:s.approvalId,outcome:c}),r(c))}},g=()=>s.settle("cancelled");this.#l.set(s.rpcId,s),t.signal?.addEventListener("abort",g,{once:!0}),this.#u(this.#S(s).payload,s.rpcId)})}#m(t){let o=this.#l.get(t?.rpcId);if(o){let a=t?.result?.value;return t?.result?.ok!==!0||!a||typeof a!="object"||a.sessionId!==o.sessionId||a.approvalId!==o.approvalId||a.outcome!=="allowed-once"&&a.outcome!=="rejected"?{accepted:!1,reason:"bad-response"}:(o.settle(a.outcome),{accepted:!0})}let i=this.#r.get(t?.rpcId);if(!i)return{accepted:!1,reason:"not-pending"};if(t?.result?.ok!==!0)return t?.result?.error?.code!=="cancelled"?{accepted:!1,reason:"bad-response"}:(i.settle("cancelled",HQ("the user cancelled ask_user_question","ASK_CANCELLED")),{accepted:!0});if(!bCe(t.result.value,i))return{accepted:!1,reason:"bad-response"};let e={answers:t.result.value.answer.answers.map(a=>({id:a.id,selected:[...a.selected],...a.custom===void 0?{}:{custom:a.custom}}))};return i.settle("answered",e),{accepted:!0}}dispose(){if(!this.#a){this.#a=!0;for(let t of[...this.#t])t.close();for(let t of[...this.#l.values()])t.settle("cancelled");for(let t of[...this.#r.values()])t.settle("cancelled",HQ("dsh-im interaction adapter was disposed","ASK_ABORTED"));for(let t of this.#i.splice(0).reverse())t?.()}}};function w1(n){let t=n?.root??n;if(!t||!["object","function"].includes(typeof t))throw new TypeError("dsh-im requires a Cordis Host context");let o=UQ.get(t);if(o)return o;let i=n?.typertGateway;if(!i||typeof i.invoke!="function"||typeof i.stream!="function")throw new TypeError("dsh-im requires the modern Host Typert gateway");let e=new F_(n,i,t);return UQ.set(t,e),typeof n.effect=="function"&&n.effect(()=>()=>{UQ.get(t)===e&&UQ.delete(t),e.dispose()},"dsh-im: modern Harness compatibility API"),e}function _Ce(n,t){return n&&Object.hasOwn(n,t)?n[t]:typeof n?.get=="function"?n.get(t):void 0}function aa(n,t={}){return t.harnessBaseUrl!==void 0?{baseUrl:new URL(t.harnessBaseUrl)}:{apiProxy:_Ce(n,"apiProxy")??w1(n),interactionScope:n.root??n}}import{randomUUID as TCe}from"node:crypto";function NCe(n){if(typeof n?.get!="function")return;let t;try{t=n.get("agents")}catch{return}if(t!=null){if(typeof t.get!="function")throw new TypeError('dsh-im requires a callable AgentRegistry when ctx.get("agents") is present');return t}}function RCe(n,t,o){if(n?.status!=="running")return!1;let i=n?.session?.events;if(!Array.isArray(i))return!1;let e=null,a=!1;for(let A of i){if(A?.type==="turn/start"){e=A.data?.turn??null,a=!1;continue}if(A?.type==="turn/end"&&A.data?.turn===e){e=null,a=!1;continue}e===t&&A?.type==="user/message"&&A.data?.source?.rpcId===o&&(a=!0)}return e===t&&a}function D1(n){if(!n||typeof n!="object"||Object.isFrozen(n))return n;for(let t of Object.values(n))D1(t);return Object.freeze(n)}function kCe(n){return D1({id:TCe(),role:"user",content:[{type:"text",text:n}],source:{kind:"user"}})}function vCe(n){let t=new Error("Session is busy with an active turn or maintenance task",{cause:n});return t.code="agent-busy",t}function PCe(n){return({sessionId:t,expectedTurn:o,promptRpcId:i,action:e,text:a})=>{let A=n.get(t);if(A){if(!RCe(A,o,i))return!1;if(e==="stop")return A.cancel({kind:"user"},{keepInbox:!0}),!0;if(e==="steer")return typeof a!="string"||!a.trim()?!1:(A.inject(kCe(a)),!0);throw new TypeError(`Unsupported Harness control action: ${String(e)}`)}}}function GCe(n){return({sessionId:t,operation:o})=>{if(typeof o!="function")throw new TypeError("maintenance operation is required");let i=n.get(t);if(!i)return o();try{return i.runMaintenance(e=>{if(n.get(t)!==i){let a=new Error("Session agent changed before maintenance started");throw a.code="agent-unavailable",a}return o(e)})}catch(e){throw vCe(e)}}}function FCe(n){return({sessionId:t,workspace:o,files:i,signal:e})=>{let A=n.get(t)?.session?.header?.cwd,r=typeof A=="string"&&A?A:o;if(typeof r!="string"||!r)throw new Ro("inbound-file-workspace-unavailable","The Harness Session workspace is unavailable for inbound files.");return TY({files:i},{workspace:r,signal:e})}}function Ja(n,t={}){let{controlExecutor:o,sessionMaintenanceExecutor:i,fileIngressExecutor:e}=t;if(o!==void 0&&typeof o!="function")throw new TypeError("controlExecutor must be a function");if(i!==void 0&&typeof i!="function")throw new TypeError("sessionMaintenanceExecutor must be a function");if(e!==void 0&&typeof e!="function")throw new TypeError("fileIngressExecutor must be a function");let a=o&&i&&e?void 0:NCe(n);return{controlExecutor:o??(a?PCe(a):void 0),sessionMaintenanceExecutor:i??(a?GCe(a):void 0),fileIngressExecutor:e??FCe(a??{get:()=>{}})}}function O1(n){return n.map(t=>({id:t,canExecuteCommands:!0}))}function pg(n=[]){return bQ({mode:"open",open:{defaultCanExecuteCommands:!0,commandPermissionOverrides:[]},allowlist:{users:O1(n)}})}function dc(n=[]){return bQ({mode:"allowlist",open:{defaultCanExecuteCommands:!1,commandPermissionOverrides:[]},allowlist:{users:O1(n)}})}function dg(n){return[...new Set((Array.isArray(n)?n:[n]).filter(t=>typeof t=="string"||typeof t=="number"||typeof t=="bigint").map(t=>String(t).trim()).filter(Boolean))]}function LCe(n){return dg(n).map(t=>`${t.replace(/^\+/,"")}@s.whatsapp.net`)}function nr(n,t={}){let o=String(n??"").trim().toLowerCase();if(o==="weixin")return Ig({direct:dc(),group:dc()});if(o==="feishu"){let e=dg(t.ownerOpenIds??t.ownerOpenId).includes("*")?pg():dc();return Ig({direct:e,group:e})}if(o==="qq"){let i=dg(t.ownerUserOpenid);return Ig({direct:i.includes("*")?pg():dc(),group:pg()})}if(o==="telegram"){let i=dg(t.allowedUsers);return(t.accessMode??"compatible")==="private-allowlist"?Ig({direct:dc(i),group:dc()}):Ig({direct:pg(i),group:pg()})}if(o==="whatsapp"){let i=t.accessMode??"self-only",e=LCe(t.allowedNumbers);return i==="open"?Ig({direct:pg(e),group:pg()}):Ig({direct:dc(i==="private-allowlist"?e:[]),group:dc()})}if(["dingtalk","wecom","slack","discord"].includes(o))return Ig({direct:pg(),group:pg()});throw new TypeError(`Unsupported access-policy channel: ${n}`)}function UCe(n,t={}){let o=String(n??"").trim().toLowerCase();if(o==="weixin")return dg(t.ownerUserId);if(o==="feishu")return dg(t.ownerOpenIds??t.ownerOpenId).filter(i=>i!=="*");if(o==="dingtalk"){let i=Array.isArray(t.approvedSenders)?t.approvedSenders:[];return dg(i.map(e=>e?.staffId))}return o==="qq"?dg(t.ownerUserOpenid).filter(i=>i!=="*"):o==="whatsapp"?dg(t.accountJid):[]}function qa(n,t,{channel:o,config:i,equals:e}={}){if(!n||typeof n.accessPolicyFor!="function")throw new TypeError("A workspace store with access policies is required");let a=new Set(UCe(o,i)),A=typeof e=="function"?e:(r,s)=>r===s;return Object.freeze({botId:t,getSettings:()=>n.accessPolicyFor(t),isPrivileged(r,s){if(!["direct","group"].includes(s))return!1;let g=Array.isArray(r)?r:[r];try{return g.some(c=>typeof c=="string"&&[...a].some(I=>A(c.trim(),I)===!0))}catch{return!1}}})}function xCe(n){let t=FI(n.dshHome??process.env.DSH_HOME??XE(KCe(),".dsh")),o=FI(n.dataDir??XE(t,"integrations","dsh-dingtalk"));return{root:o,config:FI(n.configPath??XE(o,"config.json")),bots:FI(n.botsDir??XE(o,"bots")),workspaces:FI(n.workspacesPath??XE(o,"workspaces.json"))}}async function L_(n,t={},o={}){if(!n?.credentials)throw new TypeError("dsh-dingtalk requires ctx.credentials");let i=aa(n,t),e=o.ConfigStore??pQ,a=o.DeviceAuth??hQ,A=o.StateStore??vQ,r=o.HarnessClient??RQ,s=o.Controller??PE,g=o.Runtime??jE,c=o.createConnectionSupervisor??v_,I=typeof n.logger=="function"?n.logger("dsh-dingtalk"):n.logger??console,d=()=>La(n),B=xCe(t),f=await new e(B.config).load(),Q=FI(t.workspace??process.cwd()),y=o.WorkspaceStore??ra,m=o.workspaces??await new y(B.workspaces,{defaultWorkspace:Q}).load(),T=typeof f.list=="function",_=T?f.list():[];T&&await m.reconcile(_.map(Ae=>Ae.botId)),await Promise.all(_.map(Ae=>m.ensure(Ae.botId,{defaultAgentPreset:t.agentPreset,initialAccessPolicy:nr("dingtalk",Ae)})));let R=typeof f.remove=="function"?Ha(f,{workspaces:m}):f,K=o.deviceAuth??new a({baseUrl:t.registrationBaseUrl}),L=new Map,F=Ae=>FI(B.bots,Ae,"state.json"),q=async Ae=>{let ie=L.get(Ae);return ie||(ie=await new A(F(Ae)).load(),L.set(Ae,ie)),ie},V=ja(n,o.commandExecutor),{controlExecutor:x,sessionMaintenanceExecutor:G,fileIngressExecutor:J}=Ja(n,{controlExecutor:o.controlExecutor,sessionMaintenanceExecutor:o.sessionMaintenanceExecutor,fileIngressExecutor:o.fileIngressExecutor}),U=new r({...i,workspace:Q,autostart:!1,dshBin:t.dshBin??"dsh",...V?{commandExecutor:V}:{},...x?{controlExecutor:x}:{},...G?{sessionMaintenanceExecutor:G}:{},...J?{fileIngressExecutor:J}:{}}),N=new s({deviceAuth:K,credentials:n.credentials,configStore:R,logger:I,createRuntime:async({botId:Ae,config:ie,clientSecret:we})=>{let se=await q(Ae);await m.ensure(Ae,{defaultAgentPreset:t.agentPreset,initialAccessPolicy:nr("dingtalk",ie)});let Te=Ka(U,{botId:Ae,workspaces:m,state:se,agentPresetCatalog:d});return new g({config:ie,clientSecret:we,harness:Te.harness,state:Te.state,contextEnhancement:{botId:Ae,getSettings:()=>m.contextEnhancementFor(Ae)},accessPolicy:qa(m,Ae,{channel:"dingtalk",config:ie}),replyTimeoutMs:t.replyTimeoutMs??6e5,maxMessageChars:t.maxMessageChars??4e3,connectTimeoutMs:t.connectTimeoutMs??15e3,logger:{error:(...fe)=>I.error?.(`[${Ae}]`,...fe),warn:(...fe)=>I.warn?.(`[${Ae}]`,...fe),info:(...fe)=>I.info?.(`[${Ae}]`,...fe),debug:(...fe)=>I.debug?.(`[${Ae}]`,...fe)}})},deleteState:async({botId:Ae})=>{let ie=L.get(Ae);if(L.delete(Ae),ie&&typeof ie.remove=="function")await ie.remove();else try{await HCe(F(Ae))}catch(we){if(we?.code!=="ENOENT")throw we}}}),k=xa(N,{workspaces:m,stateFor:q,agentPresetCatalog:d}),z=c({controller:k,harness:U,logger:I,retryDelaysMs:t.retryDelaysMs,healthyIntervalMs:t.healthyIntervalMs}).start();return{controller:k,deliveryAdapter:Ya({channel:"dingtalk",workspaces:m,coreController:N,stateFor:q}),ready:z.ready,async close(){await z.close(),await k.close(),U.stopManagedProcess()}}}import qCe from"qrcode";var ki="bot.context-enhancement.set";function za(n){try{return!n||typeof n!="object"||Array.isArray(n)||Reflect.ownKeys(n).length!==2||!Object.hasOwn(n,"botId")||!Object.hasOwn(n,"config")||typeof n.botId!="string"||!/^[A-Za-z0-9_-]{1,128}$/.test(n.botId)?!1:(kI(n.config),!0)}catch{return!1}}var Va="bot.access-policy.set";function Wa(n){try{return!n||typeof n!="object"||Array.isArray(n)||Reflect.ownKeys(n).length!==2||!Object.hasOwn(n,"botId")||!Object.hasOwn(n,"policy")||typeof n.botId!="string"||!/^[A-Za-z0-9_-]{1,128}$/.test(n.botId)?!1:(Ic(n.policy),!0)}catch{return!1}}var YCe=new Set(["loopback","trusted-host"]);function fr(n){if(n===void 0)return"loopback";if(YCe.has(n))return n;throw new TypeError('dsh-im rpcAuthority must be "loopback" or "trusted-host"')}import{isAbsolute as jCe}from"node:path";var vi="bot.workspace.set";function Za(n){return n!==null&&typeof n=="object"&&!Array.isArray(n)&&Object.keys(n).every(t=>["botId","workspace"].includes(t))&&typeof n.botId=="string"&&/^[A-Za-z0-9_-]{1,128}$/.test(n.botId)&&typeof n.workspace=="string"&&n.workspace.length<=4096&&jCe(n.workspace.trim())}function Xa(n){return["workspace-not-absolute","workspace-not-found","workspace-not-directory","workspace-bot-not-found","agent-preset-invalid","agent-preset-unavailable","context-enhancement-invalid"].includes(n?.code)?{code:n.code,message:n.message}:null}var Pi="bot.preset.set";function JCe(n){return n!==null&&typeof n=="object"&&!Array.isArray(n)}function $a(n){return JCe(n)&&Object.keys(n).every(t=>["botId","agentPreset"].includes(t))&&typeof n.botId=="string"&&/^[A-Za-z0-9_-]{1,128}$/.test(n.botId)&&(n.agentPreset===null||typeof n.agentPreset=="string"&&c_.test(n.agentPreset))}var M1="/dingtalk",Ft=Object.freeze({status:"connection.status",beginProvisioning:"provision.begin",pollProvisioning:"provision.poll",cancelProvisioning:"provision.cancel",bindCredentials:"bot.bind-credentials",reconnectBot:"bot.reconnect",deleteBot:"bot.delete",setWorkspace:vi,setAgentPreset:Pi,setContextEnhancement:ki,setAccessPolicy:Va,approveSender:"bot.sender.approve",revokeSender:"bot.sender.revoke"}),_1=Object.freeze(Object.values(Ft)),zCe=new Set(["clientSecret","client_secret","deviceCode","device_code","secretRef","staffId","senderStaffId","verificationUrl","verificationUri","userCode"]);function H_(n){return n!==null&&typeof n=="object"&&!Array.isArray(n)}function hc(n,t){return H_(n)&&Object.keys(n).every(o=>t.includes(o))}function LI(n){return typeof n=="string"&&/^[A-Za-z0-9_-]{1,128}$/.test(n)}function b1(n,t){return typeof n=="string"&&n.trim().length>0&&n.length<=t}function VCe(n,t){return H_(t)?n===Ft.status?hc(t,[])?null:"connection.status does not accept fields.":n===Ft.beginProvisioning?hc(t,["locale"])&&(t.locale===void 0||t.locale==="zh-CN")?null:"provision.begin received unsupported fields.":[Ft.pollProvisioning,Ft.cancelProvisioning].includes(n)?hc(t,["attemptId"])&&LI(t.attemptId)?null:`${n} requires an attemptId.`:n===Ft.bindCredentials?hc(t,["clientId","clientSecret"])&&b1(t.clientId,256)&&b1(t.clientSecret,1024)?null:"bot.bind-credentials requires Client ID and Client Secret.":n===Ft.reconnectBot?hc(t,["botId","sendTest"])&&LI(t.botId)&&(t.sendTest===void 0||t.sendTest===!0)?null:"bot.reconnect requires a botId and optional sendTest=true.":n===Ft.deleteBot?hc(t,["botId","confirm"])&&LI(t.botId)&&t.confirm===!0?null:"bot.delete requires a botId and confirm=true.":n===Ft.setWorkspace?Za(t)?null:"\u8BF7\u8F93\u5165\u5DE5\u4F5C\u533A\u7EDD\u5BF9\u8DEF\u5F84\u3002":n===Ft.setAgentPreset?$a(t)?null:"\u8BF7\u9009\u62E9 Agent Preset\u3002":n===Ft.setContextEnhancement?za(t)?null:"\u8BF7\u63D0\u4EA4\u6709\u6548\u7684\u4E0A\u4E0B\u6587\u589E\u5F3A\u8BBE\u7F6E\u3002":n===Ft.setAccessPolicy?Wa(t)?null:"\u8BF7\u63D0\u4EA4\u6709\u6548\u7684\u8BBF\u95EE\u8BBE\u7F6E\u3002":n===Ft.approveSender?hc(t,["botId","requestId","confirm"])&&LI(t.botId)&&LI(t.requestId)&&t.confirm===!0?null:"bot.sender.approve requires botId, requestId, and confirm=true.":n===Ft.revokeSender?hc(t,["botId","senderKey","confirm"])&&LI(t.botId)&&LI(t.senderKey)&&t.confirm===!0?null:"bot.sender.revoke requires botId, senderKey, and confirm=true.":"Unknown DingTalk endpoint.":"Payload must be an object."}function KQ(n){return{ok:!1,error:{code:"bad-request",message:n}}}function $E(){return{ok:!1,error:{code:"cancelled",message:"The request was cancelled."}}}function WCe(){return{ok:!1,error:{code:"dingtalk-operation-failed",message:"\u9489\u9489\u64CD\u4F5C\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002"}}}function Hp(n){if(Array.isArray(n))return n.map(Hp);if(!H_(n))return n;let t={};for(let[o,i]of Object.entries(n))zCe.has(o)||(t[o]=Hp(i));return t}async function ZCe(n){return qCe.toDataURL(n,{type:"image/png",errorCorrectionLevel:"M",margin:2,width:320})}async function U_(n,t){return!n||typeof n.verificationUrl!="string"?Hp(n):Hp({...n,qrCodeDataUrl:await t(n.verificationUrl)})}async function is(n,t){let o=structuredClone(n);return o?.provisioning&&(o.provisioning=await U_(o.provisioning,t)),Hp(o)}function XCe(n){for(let t of["status","startProvisioning","registrationStatus","cancelProvisioning","bindCredentials","reconnectBot","deleteBot","approveSender","revokeSender"])if(typeof n?.[t]!="function")throw new TypeError(`A complete DingTalk controller is required (${t})`)}function T1(n,{encodeQr:t=ZCe}={}){XCe(n);let o=new Map,i=e=>{let a=o.get(e);return a||(o.size>=16&&o.delete(o.keys().next().value),a=Promise.resolve().then(()=>t(e)),o.set(e,a)),a};return async(e,a,A)=>{if(A?.aborted)return $E();if(!_1.includes(e))return KQ("Unknown DingTalk endpoint.");let r=VCe(e,a);if(r)return KQ(r);try{let s;if(e===Ft.status)s=await is(await n.status(),i);else if(e===Ft.beginProvisioning){let g=await n.startProvisioning({signal:A});if(A?.aborted)return await n.cancelProvisioning(g.attemptId),$E();s=await U_(g,i)}else if(e===Ft.pollProvisioning){let g=await n.registrationStatus(a.attemptId);if(!g)return KQ("The provisioning attempt no longer exists.");s=await U_(g,i)}else if(e===Ft.cancelProvisioning){if(s=await n.cancelProvisioning(a.attemptId),!s)return KQ("The provisioning attempt no longer exists.");s=Hp(s)}else if(e===Ft.bindCredentials)s=await is(await n.bindCredentials(a),i);else if(e===Ft.reconnectBot){let g=await n.reconnectBot(a.botId);if(A?.aborted)return $E();let c;if(a.sendTest===!0)if(!g?.bots?.some(d=>d?.botId===a.botId&&d?.connected===!0)||typeof n.sendConnectionTest!="function")c=or(Cr("\u9489\u9489\u673A\u5668\u4EBA"));else try{await n.sendConnectionTest(a.botId),c=or()}catch(d){c=or(d)}s=await is({...g,...c?{testMessage:c}:{}},i)}else if(e===Ft.deleteBot)s=await is(await n.deleteBot(a.botId),i);else if(e===Ft.setWorkspace){if(typeof n.updateWorkspace!="function")throw new Error("Workspace update is unavailable");s=await is(await n.updateWorkspace(a.botId,a.workspace),i)}else if(e===Ft.setContextEnhancement){if(typeof n.updateContextEnhancement!="function")throw new Error("Context enhancement update is unavailable");s=await n.updateContextEnhancement(a.botId,a.config,g=>is(g,i))}else if(e===Ft.setAccessPolicy){if(typeof n.updateAccessPolicy!="function")throw new Error("Access policy update is unavailable");s=await n.updateAccessPolicy(a.botId,a.policy,g=>is(g,i))}else if(e===Ft.setAgentPreset){if(typeof n.updateAgentPreset!="function")throw new Error("Agent preset update is unavailable");s=await is(await n.updateAgentPreset(a.botId,a.agentPreset),i)}else e===Ft.approveSender?s=await is(await n.approveSender(a.botId,a.requestId),i):s=await is(await n.revokeSender(a.botId,a.senderKey),i);return A?.aborted?$E():{ok:!0,value:s}}catch(s){let g=Xa(s);return A?.aborted?$E():g?{ok:!1,error:g}:WCe()}}}function xQ(n,t,o,i){if(!n?.connection?.rpc||typeof n.connection.rpc.handle!="function")throw new TypeError("DSH Host Connection RPC is required");return n.connection.rpc.handle(M1,T1(t,o),{authority:fr(i)})}async function N1(n,t={}){if(t?.controller)return xQ(n,t.controller,t.rpcOptions,t.rpcAuthority);let o=await L_(n,t,t.internals),i=t.deliveryService&&o.deliveryAdapter?t.deliveryService.registerAdapter(o.deliveryAdapter):void 0,e=xQ(n,o.controller,t.rpcOptions,t.rpcAuthority);return n.effect(()=>async()=>{await i?.(),await o.close()},"dsh-dingtalk: close bot connections"),e}import{createHash as $Ce}from"node:crypto";import{mkdir as eue,readFile as Aue,rename as tue,unlink as rue,writeFile as aue}from"node:fs/promises";import{dirname as iue}from"node:path";var K_=Object.freeze({version:1,bots:Object.freeze([])});function hg(n){return typeof n=="string"&&n.trim()?n.trim():null}function R1(n){return n.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function eC(n,{botPrefix:t,tokenRefPrefix:o}){let i=hg(n);if(!i)throw new TypeError("platformId is required");let e=$Ce("sha256").update(i).digest("hex").slice(0,24);return{botId:`${t}_${e}`,tokenRef:`${o}_${e.toUpperCase()}`}}function YQ(n,t){let o=hg(n)??"";return o.length<=10?o?`${o.slice(0,3)}\u2022\u2022\u2022`:t:`${o.slice(0,6)}\u2022\u2022\u2022\u2022${o.slice(-4)}`}var Kp=class{#e;#A;#t;#r;#l;#o;#i;#a=K_;#n=Promise.resolve();constructor(t,{channel:o,botPrefix:i,tokenRefPrefix:e,normalizeBotExtension:a=()=>({})}){if(typeof a!="function")throw new TypeError("normalizeBotExtension must be a function");this.#e=t,this.#A=o,this.#t=i,this.#r=e,this.#l=a,this.#o=new RegExp(`^${R1(i)}_[a-f0-9]{24}$`),this.#i=new RegExp(`^${R1(e)}_[A-F0-9]{24}$`)}async load(){try{let t=this.#p(JSON.parse(await Aue(this.#e,"utf8")));if(!t)throw new Error(`dsh-im ${this.#A} config contains invalid bot data`);this.#a=t}catch(t){if(t?.code!=="ENOENT")throw t;this.#a=K_}return this}list(){return structuredClone(this.#a.bots)}get(t){let o=this.#a.bots.find(i=>i.botId===t);return o?structuredClone(o):null}getByPlatformId(t){let o=this.#a.bots.find(i=>i.platformId===t);return o?structuredClone(o):null}async save(t){let o=this.#s(t);if(!o)throw new Error(`Refusing to persist incomplete ${this.#A} bot data`);return this.#c(i=>{let e=i.find(r=>r.platformId===o.platformId&&r.botId!==o.botId),a=i.find(r=>r.tokenRef===o.tokenRef&&r.botId!==o.botId);if(e||a)throw new Error(`Duplicate ${this.#A} bot identity`);let A=i.findIndex(r=>r.botId===o.botId);return A===-1?i.push(o):i[A]=o,structuredClone(o)})}async remove(t){if(!this.#o.test(t))throw new TypeError(`Invalid ${this.#A} bot id`);return this.#c(o=>{let i=o.findIndex(a=>a.botId===t);if(i===-1)return null;let[e]=o.splice(i,1);return structuredClone(e)})}async clear(){let t=this.#n.then(async()=>{try{await rue(this.#e)}catch(o){if(o?.code!=="ENOENT")throw o}this.#a=K_});this.#n=t.then(()=>{},()=>{}),await t}#s(t){if(!t||typeof t!="object")return null;let o=hg(t.platformId),i=hg(t.botId),e=hg(t.tokenRef),a=hg(t.name);if(!o||!i||!e||!a||!this.#o.test(i)||!this.#i.test(e))return null;let A=eC(o,{botPrefix:this.#t,tokenRefPrefix:this.#r});if(A.botId!==i||A.tokenRef!==e)return null;let r=this.#l(t);return!r||typeof r!="object"||Array.isArray(r)?null:Object.freeze({botId:i,platformId:o,tokenRef:e,name:a,username:hg(t.username),createdAt:hg(t.createdAt)??new Date().toISOString(),connectedAt:hg(t.connectedAt),...r})}#p(t){if(!t||t.version!==1||!Array.isArray(t.bots))return null;let o=t.bots.map(A=>this.#s(A));if(o.some(A=>A===null))return null;let i=new Set,e=new Set,a=new Set;for(let A of o){if(i.has(A.botId)||e.has(A.platformId)||a.has(A.tokenRef))return null;i.add(A.botId),e.add(A.platformId),a.add(A.tokenRef)}return Object.freeze({version:1,bots:Object.freeze(o)})}async#c(t){let o,i=this.#n.then(async()=>{let e=[...this.#a.bots];o=t(e);let a=Object.freeze({version:1,bots:Object.freeze(e)});await this.#g(a),this.#a=a});return this.#n=i.then(()=>{},()=>{}),await i,o}async#g(t){await eue(iue(this.#e),{recursive:!0,mode:448});let o=`${this.#e}.tmp`;await aue(o,`${JSON.stringify(t,null,2)} `,{encoding:"utf8",mode:384}),await tue(o,this.#e)}};var k1=Object.freeze({botPrefix:"discord",tokenRefPrefix:"DSH_DISCORD_BOT_TOKEN"});function v1(n){return eC(n,k1)}function P1(n){return YQ(n,w("Discord\u673A\u5668\u4EBA"))}var jQ=class extends Kp{constructor(t){super(t,{channel:"Discord",...k1})}};function AC(n){return typeof n=="string"&&n.trim()?n.trim():null}function tC(n,t){return Object.freeze({code:n,message:t})}var xp=class{#e;#A;#t;#r;#l;#o;#i;#a;#n;#s=new Map;#p=new Map;#c=new Map;#g=0;#I=!1;constructor({descriptor:t,credentials:o,configStore:i,inspectToken:e,deriveIdentity:a,maskPlatformId:A,createRuntime:r,deleteState:s=async()=>{},logger:g=console}){if(!t?.key||!t?.label||!t?.connectionLabel)throw new TypeError("TokenBotController requires a channel descriptor");if(!o||typeof o.resolve!="function"||typeof o.set!="function"||typeof o.unset!="function")throw new TypeError(`${t.label} requires the DSH credential provider`);if(!i||typeof i.list!="function"||typeof i.save!="function"||typeof i.remove!="function")throw new TypeError(`${t.label} requires a config store`);if(typeof e!="function"||typeof a!="function"||typeof A!="function"||typeof r!="function")throw new TypeError(`${t.label} controller dependencies are incomplete`);this.#e=t,this.#A=o,this.#t=i,this.#r=e,this.#l=a,this.#o=A,this.#i=r,this.#a=s,this.#n=g}async initialize(){if(this.#I)return this.status();for(let t of this.#t.list())await this.#B(t.botId,async()=>{if(this.#I||this.#s.get(t.botId)?.status?.ready)return;let o=await this.#C(t.tokenRef);if(!o){this.#p.set(t.botId,tC("missing-token",w("{label}\u673A\u5668\u4EBA\u51ED\u636E\u7F3A\u5931\uFF0C\u8BF7\u79FB\u9664\u540E\u91CD\u65B0\u63A5\u5165\u3002",{label:this.#e.label})));return}try{await this.#d(t,o),this.#p.delete(t.botId)}catch(i){this.#p.set(t.botId,tC("connection-failed",w("{label}\u8FDE\u63A5\u672A\u5C31\u7EEA\uFF0C\u63D2\u4EF6\u4F1A\u81EA\u52A8\u91CD\u8BD5\u3002",{label:this.#e.label}))),this.#n.warn?.(`[dsh-im:${this.#e.key}] bot ${t.botId} failed to initialize:`,i)}finally{this.#f()}});return this.status()}async bindCredentials({token:t}={}){if(this.#I)throw new Error(`${this.#e.label} controller is closed`);let o=AC(t);if(!o)throw new TypeError(`${this.#e.label} Bot Token is required`);let i=await this.#r(o),e=AC(i?.platformId),a=AC(i?.name);if(!e||!a)throw new Error(`${this.#e.label} returned an invalid bot identity`);let A=this.#l(e);return await this.#B(A.botId,async()=>{if(this.#I)throw new Error(`${this.#e.label} controller is closed`);let r=this.#t.getByPlatformId(e),s=await this.#A.resolve(A.tokenRef).catch(()=>{}),g={botId:A.botId,platformId:e,tokenRef:A.tokenRef,name:a,username:AC(i.username),createdAt:r?.createdAt??new Date().toISOString(),connectedAt:new Date().toISOString()};await this.#A.set(A.tokenRef,o);try{await this.#t.save(g)}catch(c){throw await this.#u(A.tokenRef,s),c}try{await this.#d(g,o),this.#p.delete(A.botId)}catch(c){this.#p.set(A.botId,tC("connection-failed",w("{label}\u673A\u5668\u4EBA\u5DF2\u63A5\u5165\uFF0C\u6D88\u606F\u8FDE\u63A5\u6682\u672A\u5C31\u7EEA\u3002",{label:this.#e.label}))),this.#n.warn?.(`[dsh-im:${this.#e.key}] bot ${A.botId} credential connection failed:`,c)}this.#f()}),this.status()}async reconnectBot(t){let o=this.#t.get(t);if(!o)throw new Error(`Unknown ${this.#e.label} bot`);return await this.#B(t,async()=>{let i=await this.#C(o.tokenRef);if(!i)throw new Error(`${this.#e.label} bot token is missing`);try{await this.#d(o,i),this.#p.delete(t)}catch(e){throw this.#p.set(t,tC("connection-failed",w("{label}\u8FDE\u63A5\u4ECD\u672A\u5C31\u7EEA\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002",{label:this.#e.label}))),e}finally{this.#f()}}),this.status()}async updateBotConfig(t,o){if(this.#I)throw new Error(`${this.#e.label} controller is closed`);if(typeof o!="function")throw new TypeError("Bot config update must be a function");return await this.#B(t,async()=>{if(this.#I)throw new Error(`${this.#e.label} controller is closed`);let i=this.#t.get(t);if(!i)throw new Error(`Unknown ${this.#e.label} bot`);let e=await this.#C(i.tokenRef);if(!e)throw new Error(`${this.#e.label} bot token is missing`);if(this.#I)throw new Error(`${this.#e.label} controller is closed`);let a=o(i),A=await this.#t.save(a);try{await this.#d(A,e),this.#p.delete(t)}catch(r){throw this.#p.set(t,tC("connection-failed",w("{label}\u8FDE\u63A5\u4ECD\u672A\u5C31\u7EEA\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002",{label:this.#e.label}))),r}finally{this.#f()}}),this.status()}async sendConnectionTest(t){let o=this.#t.get(t);if(!o)throw new Error(`Unknown ${this.#e.label} bot`);return this.#B(t,async()=>{let i=this.#s.get(t);if(!i?.status?.ready||typeof i.sendConnectionTest!="function"){let a=new Error(w("{label}\u673A\u5668\u4EBA\u5C1A\u672A\u8FDE\u63A5",{label:this.#e.label}));throw a.code="test-target-unavailable",a}let e=w("{name}\uFF08{id}\uFF09",{name:o.name,id:this.#o(o.platformId)});return await i.sendConnectionTest(Ra(e,w("{label}\u673A\u5668\u4EBA",{label:this.#e.label}))),{sent:!0}})}async sendProactiveText(t,o,i,e={}){if(!this.#t.get(t))throw new Error(`Unknown ${this.#e.label} bot`);return this.#B(t,async()=>{let A=this.#s.get(t);if(!A?.status?.ready||typeof A.sendProactiveText!="function"){let r=new Error(w("{label}\u673A\u5668\u4EBA\u5C1A\u672A\u8FDE\u63A5",{label:this.#e.label}));throw r.code="bot-not-connected",r}return A.sendProactiveText(o,i,e)})}async deleteBot(t){let o=this.#t.get(t);if(!o)throw new Error(`Unknown ${this.#e.label} bot`);return await this.#B(t,async()=>{let i=await this.#A.resolve(o.tokenRef).catch(()=>{});await this.#h(t);try{await this.#A.unset(o.tokenRef),await this.#t.remove(t)}catch(e){throw i?.value&&(await this.#A.set(o.tokenRef,i.value).catch(()=>{}),await this.#d(o,i.value).catch(()=>{})),new Error(`Unable to remove the ${this.#e.label} bot safely.`,{cause:e})}await this.#a({botId:t,config:o}).catch(e=>{this.#n.warn?.(`[dsh-im:${this.#e.key}] bot ${t} state cleanup failed:`,e)}),this.#p.delete(t),this.#f()}),this.status()}status(){let t=this.#t.list().map(i=>{let e=this.#s.get(i.botId)?.status??null,a=e?.ready===!0&&e.connectionState==="connected"&&e.harnessReachable===!0,A=a?"connected":e?.connectionState==="connecting"?"connecting":this.#p.has(i.botId)||e?.connectionState==="failed"?"error":"offline";return{botId:i.botId,state:A,connected:a,configured:!0,bot:{name:i.name,username:i.username,idMasked:this.#o(i.platformId)},health:{status:a?"healthy":A==="error"?"error":"offline",summary:a?w("{label}{connectionLabel}\u8FD0\u884C\u6B63\u5E38",{label:this.#e.label,connectionLabel:w(this.#e.connectionLabel)}):A==="error"?w("{label}\u8FDE\u63A5\u672A\u5C31\u7EEA\uFF0C\u63D2\u4EF6\u4F1A\u81EA\u52A8\u91CD\u8BD5",{label:this.#e.label}):w("{label}\u8FDE\u63A5\u5F53\u524D\u79BB\u7EBF",{label:this.#e.label}),lastCheckedAt:e?.lastCheckedAt??null,lastConnectedAt:e?.lastConnectedAt??null},stats:{messagesReceived:e?.messagesReceived??0,messagesReplied:e?.messagesReplied??0},lastMessageError:Xr(e?.lastMessageError),error:structuredClone(this.#p.get(i.botId)??null)}}),o=t.filter(i=>i.connected).length;return{schemaVersion:1,revision:this.#g,state:t.length===0?"disconnected":o===t.length?"connected":o>0?"degraded":"offline",bots:t,totals:{configured:t.length,connected:o}}}async close(){this.#I||(this.#I=!0,await Promise.allSettled([...this.#c.values()]),await Promise.allSettled([...this.#s.keys()].map(t=>this.#h(t))))}async#d(t,o){if(this.#I)throw new Error(`${this.#e.label} controller is closed`);if(await this.#h(t.botId),this.#I)throw new Error(`${this.#e.label} controller is closed`);let i=await this.#i({botId:t.botId,config:t,token:o});if(!i||typeof i.start!="function"||typeof i.stop!="function")throw new TypeError(`createRuntime returned an invalid ${this.#e.label} runtime`);this.#s.set(t.botId,i);try{await i.start()}catch(e){throw await i.stop().catch(()=>{}),this.#s.delete(t.botId),e}}async#h(t){let o=this.#s.get(t);this.#s.delete(t),await o?.stop().catch(i=>{this.#n.warn?.(`[dsh-im:${this.#e.key}] bot ${t} failed to stop cleanly:`,i)})}async#C(t){let o=await this.#A.resolve(t).catch(()=>{});return AC(o?.value)}async#u(t,o){o?.value?await this.#A.set(t,o.value).catch(()=>{}):await this.#A.unset(t).catch(()=>{})}#B(t,o){let a=(this.#c.get(t)??Promise.resolve()).catch(()=>{}).then(o).finally(()=>{this.#c.get(t)===a&&this.#c.delete(t)});return this.#c.set(t,a),a}#f(){this.#g+=1}};import{createHash as oue}from"node:crypto";var nue="https://discord.com/api/v10/",sue=12e4,gue=new Set([50001,50013]),cue=new Set([40005]);function os(n){return typeof n=="string"&&n.trim()?n.trim():null}function G1(n,t){let o=AbortSignal.timeout(t);return n?AbortSignal.any([n,o]):o}function x_(n){return n?.reason instanceof Error?n.reason:new DOMException("The operation was aborted","AbortError")}function Iue(n,t){if(!Number.isInteger(n)||n<1)throw new TypeError(`${t} must be a positive integer`);return n}function L1(n,t){return t?.providerCode!==void 0&&(n.providerCode=t.providerCode),t?.retry_after!==void 0&&(n.retry_after=t.retry_after,n.retryAfter=t.retry_after),Number.isInteger(t?.status)&&(n.status=t.status),n}function lue(n){let t=Number(n?.providerCode),o=Number(n?.status),i=os(n?.message)??"",e="artifact-provider-rejected",a="Discord rejected the attachment.";o===401||o===403||gue.has(t)?(e="artifact-permission-required",a="Discord denied permission to send the attachment."):o===413||cue.has(t)||/(?:request|attachment|file).{0,24}too large/i.test(i)?(e="artifact-too-large",a="The attachment exceeds Discord's size limit."):o===429?(e="artifact-rate-limited",a="Discord rate-limited attachment delivery."):o>=500&&(e="artifact-delivery-uncertain",a="Discord attachment delivery result is uncertain.");let A=new Error(a,{cause:n});return A.code=e,L1(A,n)}function pue(n){let t=new Error("Discord attachment delivery result is uncertain",{cause:n});return t.code="artifact-delivery-uncertain",L1(t,n)}function due(n,t){return new Promise((o,i)=>{if(t?.aborted){i(t.reason??new DOMException("Aborted","AbortError"));return}let e=setTimeout(o,n);e?.unref?.(),t?.addEventListener("abort",()=>{clearTimeout(e),i(t.reason??new DOMException("Aborted","AbortError"))},{once:!0})})}function ei(n,t){let o=os(n);if(!o||!/^\d{5,30}$/.test(o))throw new TypeError(`Invalid Discord ${t}`);return o}function F1(n){let t=os(n);if(!t)throw new TypeError("A Discord reaction emoji is required");return t}function hue(n){return typeof n=="string"&&/^[A-Za-z0-9_-]{20,}\.[A-Za-z0-9_-]{4,}\.[A-Za-z0-9_-]{20,}$/.test(n.trim())}var rC=class{#e;#A;#t;#r;constructor({token:t,fetchImpl:o=fetch,baseUrl:i=nue,fileUploadTimeoutMs:e=sue}){if(!hue(t))throw new TypeError("Discord Bot Token is invalid");if(typeof o!="function")throw new TypeError("DiscordApi requires fetch");this.#e=t.trim(),this.#A=o,this.#t=new URL(i),this.#r=Iue(e,"fileUploadTimeoutMs")}getCurrentUser(t={}){return this.#l("users/@me",{...t,method:"GET"})}getGatewayBot(t={}){return this.#l("gateway/bot",{...t,method:"GET"})}getChannel({channelId:t,signal:o}={}){return this.#l(`channels/${ei(t,"channel id")}`,{method:"GET",signal:o})}startThreadFromMessage({channelId:t,messageId:o,name:i,signal:e}={}){let a=os(i);if(!a||[...a].length>100)throw new TypeError("Discord thread name must contain 1-100 characters");if(e?.aborted)throw x_(e);return this.#l(`channels/${ei(t,"channel id")}/messages/${ei(o,"message id")}/threads`,{method:"POST",signal:e,body:{name:a}})}createMessage({channelId:t,content:o,replyToMessageId:i,signal:e}){return this.#l(`channels/${ei(t,"channel id")}/messages`,{method:"POST",signal:e,body:{content:o,allowed_mentions:{parse:[],replied_user:!1},...i?{message_reference:{message_id:ei(i,"message id"),channel_id:ei(t,"channel id"),fail_if_not_exists:!1}}:{}}})}async createFileMessage({channelId:t,file:o,replyToMessageId:i,signal:e}){if(!o||typeof o!="object"||typeof o.fileName!="string"||!o.fileName||!Buffer.isBuffer(o.bytes))throw new TypeError("A Discord attachment is required");let a=os(o.deliveryKey)??os(o.artifactId),A=a?oue("sha256").update(a).digest("hex").slice(0,25):void 0,r=new FormData;r.append("payload_json",JSON.stringify({allowed_mentions:{parse:[],replied_user:!1},attachments:[{id:0,filename:o.fileName}],...A?{nonce:A,enforce_nonce:!0}:{},...i?{message_reference:{message_id:ei(i,"message id"),channel_id:ei(t,"channel id"),fail_if_not_exists:!1}}:{}})),r.append("files[0]",new Blob([o.bytes],{type:o.mediaType??"application/octet-stream"}),o.fileName);let s=ei(t,"channel id");if(e?.aborted)throw x_(e);let g=G1(e,this.#r);try{return await this.#l(`channels/${s}/messages`,{method:"POST",signal:g,timeoutMs:this.#r,body:r,multipart:!0})}catch(c){throw e?.aborted?x_(e):c?.code?.startsWith?.("discord-")?lue(c):pue(c)}}editMessage({channelId:t,messageId:o,content:i,signal:e}){return this.#l(`channels/${ei(t,"channel id")}/messages/${ei(o,"message id")}`,{method:"PATCH",signal:e,body:{content:i,allowed_mentions:{parse:[],replied_user:!1}}})}sendTyping({channelId:t,signal:o}){return this.#l(`channels/${ei(t,"channel id")}/typing`,{method:"POST",signal:o,expectBody:!1})}async addOwnReaction({channelId:t,messageId:o,emoji:i,signal:e}={}){let a=F1(i);return await this.#l(`channels/${ei(t,"channel id")}/messages/${ei(o,"message id")}/reactions/${encodeURIComponent(a)}/@me`,{method:"PUT",signal:e,expectBody:!1,retry:!1}),a}removeOwnReaction({channelId:t,messageId:o,emoji:i,signal:e}={}){let a=F1(i);return this.#l(`channels/${ei(t,"channel id")}/messages/${ei(o,"message id")}/reactions/${encodeURIComponent(a)}/@me`,{method:"DELETE",signal:e,expectBody:!1,retry:!1})}async#l(t,{method:o,body:i,signal:e,timeoutMs:a=15e3,expectBody:A=!0,retry:r=!0,multipart:s=!1}){let g;try{g=await this.#A(new URL(t,this.#t),{method:o,headers:{authorization:`Bot ${this.#e}`,...s?{}:{"content-type":"application/json"},"user-agent":"DeepSeek-Harness-dsh-im (https://github.com/xmanrui/dsh-im, 1.1.0)"},...i===void 0?{}:{body:s?i:JSON.stringify(i)},signal:G1(e,a),redirect:"error"})}catch(I){throw I?.name==="AbortError"||I?.name==="TimeoutError"?I:new Error(`Discord ${o} transport failed`)}let c=null;if(A||g.status===429||!g.ok)try{c=await g.json()}catch{if(A){let I=new Error(`Discord ${o} returned invalid JSON`);throw I.status=g?.status,I}}if(g.status===429&&r){let I=Math.min(1e4,Math.max(50,Number(c?.retry_after)*1e3||1e3));return await due(I,e),this.#l(t,{method:o,body:i,signal:e,timeoutMs:a,expectBody:A,retry:!1,multipart:s})}if(!g.ok){let I=new Error(os(c?.message)??`Discord API failed with HTTP ${g.status}`);I.code=`discord-${g.status}`,I.status=g.status,(Number.isInteger(c?.code)||typeof c?.code=="string")&&(I.providerCode=c.code);let d=Number(c?.retry_after);throw Number.isFinite(d)&&d>=0&&(I.retry_after=d,I.retryAfter=d),I}return A?c:null}};async function U1(n,t={}){let i=await new rC({token:n,...t}).getCurrentUser();if(!i?.id||i?.bot!==!0)throw new Error("Discord token does not belong to a bot");return{platformId:String(i.id),name:os(i.global_name)??os(i.username)??w("Discord\u673A\u5668\u4EBA"),username:os(i.username)}}var Eue=Object.freeze({success(){},error(){},clear(){},settled:()=>Promise.resolve()});function H1(n,t){!n||typeof n!="object"||(n[t]=(n[t]??0)+1)}async function Cue(n,t){let o=AbortSignal.timeout(t),i,e=new Promise((a,A)=>{i=()=>A(o.reason??new DOMException("Timed out","TimeoutError")),o.addEventListener("abort",i,{once:!0})});try{return await Promise.race([n(o),e])}finally{o.removeEventListener("abort",i)}}function JQ({adapter:n,target:t,reactions:o,status:i,logger:e=console,label:a="channel",timeoutMs:A=2e3}={}){if(!t||typeof n?.addReaction!="function"||typeof n?.removeReaction!="function"||typeof o?.processing!="string"||!o.processing||!Number.isSafeInteger(A)||A<=0)return Eue;let r=null,s=!1,g=async(B,f)=>{try{let Q=await Cue(f,A);return H1(i,B==="add"?"reactionsAdded":"reactionsRemoved"),{ok:!0,value:Q}}catch(Q){return H1(i,"reactionErrors"),e.warn?.(`[dsh-im:${a}] status reaction ${B} failed:`,Q?.message??Q?.name??String(Q)),{ok:!1,value:null}}},c=async B=>{if(r!==null){let Q=r;r=null,await g("remove",y=>n.removeReaction(t,Q,{signal:y}))}if(typeof B!="string"||!B)return;let f=await g("add",Q=>n.addReaction(t,B,{signal:Q}));f.ok&&f.value!==void 0&&f.value!==null&&(r=f.value)},I=c(o.processing),d=B=>{s||(s=!0,I=I.then(()=>c(B),()=>c(B)),I.catch(()=>{}))};return Object.freeze({success:()=>d(o.success),error:()=>d(o.error),clear:()=>d(null),settled:()=>I})}var K1="\u8FD9\u4E2A\u95EE\u9898\u5DF2\u5728\u5176\u4ED6\u5BA2\u6237\u7AEF\u5904\u7406\uFF0C\u65E0\u9700\u518D\u6B21\u56DE\u7B54\u3002",uue="\u4EFB\u52A1\u5DF2\u5B8C\u6210\u3002";function Ii(n){return typeof n=="string"?n.trim():""}function Bue(n,t,o){return t.actor===o&&(n.kind!=="group"||n.addressed===!0)&&!Tt(n)&&!wt(n)&&!!Ii(n.content)}function fue(n,t,o){let i=String(n??w("\u7ED3\u679C\u6587\u4EF6")).replace(/[\r\n]+/g," ").trim().slice(0,255)||w("\u7ED3\u679C\u6587\u4EF6");switch(t?.code){case"artifact-delivery-uncertain":return w("\u7ED3\u679C\u6587\u4EF6\u300C{name}\u300D\u7684\u53D1\u9001\u7ED3\u679C\u672A\u80FD\u786E\u8BA4\uFF0C\u8BF7\u5148\u68C0\u67E5\u804A\u5929\u5185\u662F\u5426\u5DF2\u6536\u5230\uFF0C\u4E0D\u8981\u7ACB\u5373\u91CD\u8BD5\u3002",{name:i});case"artifact-permission-required":return o?.key==="slack"?w("\u7ED3\u679C\u6587\u4EF6\u300C{name}\u300D\u5DF2\u751F\u6210\uFF0C\u4F46 Slack \u5E94\u7528\u7F3A\u5C11 files:write \u6743\u9650\u3002\u8BF7\u66F4\u65B0 Manifest\u3001\u91CD\u65B0\u5B89\u88C5\u5E94\u7528\u5E76\u91CD\u65B0\u8FDE\u63A5\u673A\u5668\u4EBA\u540E\u91CD\u8BD5\u3002",{name:i}):o?.key==="discord"?w("\u7ED3\u679C\u6587\u4EF6\u300C{name}\u300D\u5DF2\u751F\u6210\uFF0C\u4F46\u673A\u5668\u4EBA\u7F3A\u5C11 Discord \u7684 Send Messages\u3001Attach Files \u6216 Read Message History \u6743\u9650\u3002",{name:i}):o?.key==="telegram"?w("\u7ED3\u679C\u6587\u4EF6\u300C{name}\u300D\u5DF2\u751F\u6210\uFF0C\u4F46 Telegram \u4E0D\u5141\u8BB8\u673A\u5668\u4EBA\u5728\u5F53\u524D\u804A\u5929\u53D1\u9001\u6587\u6863\uFF0C\u8BF7\u68C0\u67E5\u804A\u5929\u6743\u9650\u3002",{name:i}):w("\u7ED3\u679C\u6587\u4EF6\u300C{name}\u300D\u5DF2\u751F\u6210\uFF0C\u4F46\u5F53\u524D\u673A\u5668\u4EBA\u6CA1\u6709\u6587\u4EF6\u53D1\u9001\u6743\u9650\uFF0C\u8BF7\u68C0\u67E5\u6E20\u9053\u6743\u9650\u3002",{name:i});case"artifact-too-large":return w("\u7ED3\u679C\u6587\u4EF6\u300C{name}\u300D\u8D85\u8FC7\u5F53\u524D\u6E20\u9053\u5927\u5C0F\u4E0A\u9650\uFF0C\u672A\u53D1\u9001\u3002",{name:i});case"artifact-empty":return w("\u7ED3\u679C\u6587\u4EF6\u300C{name}\u300D\u4E3A\u7A7A\uFF0C\u672A\u53D1\u9001\u3002",{name:i});case"artifact-invalid":case"artifact-changed":case"artifact-unavailable":return w("\u7ED3\u679C\u6587\u4EF6\u300C{name}\u300D\u6682\u65F6\u65E0\u6CD5\u8BFB\u53D6\u6216\u51C6\u5907\u53D1\u9001\uFF0C\u8BF7\u786E\u8BA4\u6587\u4EF6\u4ECD\u53EF\u8BBF\u95EE\u540E\u91CD\u8BD5\u3002",{name:i});case"artifact-rate-limited":return w("\u7ED3\u679C\u6587\u4EF6\u300C{name}\u300D\u6682\u65F6\u88AB\u5F53\u524D\u6E20\u9053\u9650\u6D41\uFF0C\u672A\u80FD\u53D1\u9001\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002",{name:i});case"artifact-provider-rejected":return w("\u7ED3\u679C\u6587\u4EF6\u300C{name}\u300D\u5DF2\u751F\u6210\uFF0C\u4F46\u5F53\u524D\u6E20\u9053\u62D2\u7EDD\u4E86\u8BE5\u6587\u4EF6\u6216\u6587\u4EF6\u6D88\u606F\u3002",{name:i});default:return w("\u7ED3\u679C\u6587\u4EF6\u300C{name}\u300D\u5DF2\u751F\u6210\uFF0C\u4F46\u5F53\u524D\u6E20\u9053\u6682\u65F6\u672A\u80FD\u53D1\u9001\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002",{name:i})}}function io(){return{messagesReceived:0,messagesReplied:0,messagesRejected:0,lastMessageAt:null,lastReplyAt:null,lastRejectedAt:null,lastError:null,lastMessageError:null,reactionsAdded:0,reactionsRemoved:0,reactionErrors:0}}var ns=class{#e;#A;#t;#r;#l;#o;#i;#a;#n;#s;#p=new Map;#c=new Map;#g=new Map;#I=new Map;#d=new Set;#h=new Set;#C;#u=new Ti;constructor({descriptor:t,bot:o,harness:i,state:e,contextEnhancement:a,accessPolicy:A,status:r=io(),logger:s=console,replyTimeoutMs:g=6e5,signal:c}){if(!t?.key||!t?.label)throw new TypeError("A channel descriptor is required");if(!o||typeof o.sendText!="function")throw new TypeError("A bot client is required");if(!i||!e)throw new TypeError("Harness client and state store are required");this.#e=t,this.#A=o,this.#t=i,this.#r=e,this.#l=a,this.#o=A,this.#i=r,this.#a=s,this.#n=g,this.#s=c,this.#C=new Di({label:t.key,logger:s})}get status(){return structuredClone(this.#i)}accept(t,{contextSnapshot:o,accessDecision:i}={}){if(this.#s?.aborted)return Promise.resolve();let e=Ii(t?.conversationId),a=t?.kind==="group"?"group":"direct",A={...t,kind:a,conversationId:e},r=Ii(A.messageId),s=Ii(A.senderId);if(!r||!s||!e||A.senderIsBot===!0||this.#r.hasSeen(r)||this.#I.has(r))return Promise.resolve();if(a==="group"&&A.addressed!==!0)return this.#i.messagesRejected+=1,this.#i.lastRejectedAt=new Date().toISOString(),this.#I.set(r,null),this.#f(A,r,null);if(this.#o||i){let I=Tt(A),d=wt(A),B=i??Ba(this.#o,{conversationType:a,senderIds:[s,Ii(A.senderAlternateId)].filter(Boolean),text:A.content,hasImages:I,hasFiles:d});if(!B.allowed)return this.#i.messagesRejected+=1,this.#i.lastRejectedAt=new Date().toISOString(),this.#I.set(r,null),this.#f(A,r,B.reason==="command-not-allowed"?w(ao):null,{recordReceived:B.reason==="command-not-allowed"})}this.#I.set(r,o===void 0?Aa(this.#l,t?.kind):o);let g=JQ({adapter:this.#A,target:A.kind==="direct"||A.addressed===!0?A.reactionTarget:null,reactions:this.#e.reactions,status:this.#i,logger:this.#a,label:this.#e.key});A.statusReaction=g;let c=this.#B(A,r,s);return c.then(()=>g.success(),()=>g.error()),c}#B(t,o,i){t.kind==="direct"&&So(this.#r,t.connectionTestTarget??t.replyTarget);let e=`${t.kind}:${t.conversationId}`,a=this.#c.get(e),A=Ii(t.content),r=Ni(A);if(r&&t.kind==="group"&&t.addressed===!0)return this.#f(t,o,es());if(r&&t.kind==="direct"){if(/^\/batch$/iu.test(A)&&(this.#p.has(e)||a||this.#C.hasPending(e)))return this.#f(t,o,No());let d=this.#u.handle(e,A,{plainText:!!A&&t.plainText!==!1&&!Tt(t)&&!wt(t)});if(d.handled)return d.kind==="submit"?this.#Q({...t,content:d.prompt,batchSubmission:{token:d.token}},o,i,e):this.#f(t,o,d.message)}else if(t.kind==="direct"&&this.#u.status(e).phase==="collecting"){let I=this.#u.handle(e,A,{plainText:!!A&&t.plainText!==!1&&!Tt(t)&&!wt(t)});if(I.handled)return this.#f(t,o,I.message)}let g=t.kind==="direct"&&this.#u.status(e).phase==="collecting"?null:Fa(A)?Ao:wt(t)?null:ni(A)?Mi:si(A)?to:gi(A)?_i:null;if(g&&(t.kind!=="group"||t.addressed===!0)){let I;return I=this.#S(t,o,e,g).finally(()=>{this.#I.delete(o),this.#h.delete(I)}),this.#h.add(I),I}let c=this.#C.claimReply({key:e,actor:i,messageId:o,text:Tt(t)||wt(t)?"":t.content,addressed:t.kind!=="group"||t.addressed===!0,hasPendingQuestion:!!a,questionCompletion:a?.submitting||a?.claimedReplyMessageId?a.queue:null,isQuestionPending:()=>this.#c.has(e),send:I=>this.#A.sendText(t.replyTarget,I)});if(c){let I;return I=c.process(async()=>this.#r.hasSeen(o)?!1:(await this.#r.markSeen(o),this.#i.messagesReceived+=1,this.#i.lastMessageAt=new Date().toISOString(),!0)).finally(()=>{this.#I.delete(o),this.#d.delete(I)}),this.#d.add(I),I}if(a&&a.actor!==i)return this.#Q(t,o,i,e);if(a?.submitting||a?.claimedReplyMessageId)return this.#Q(t,o,i,e);if(a){Bue(t,a,i)&&(a.claimedReplyMessageId=o);let d=(a.queue??Promise.resolve()).catch(()=>{}).then(()=>this.#D(t,o,i,e,a)).finally(()=>{this.#I.delete(o),a.claimedReplyMessageId===o&&(a.claimedReplyMessageId=null),a.queue===d&&(a.queue=null)});return a.queue=d,d}return this.#Q(t,o,i,e)}#f(t,o,i,{recordReceived:e=!0}={}){let a;return a=(async()=>{this.#r.hasSeen(o)||(await this.#r.markSeen(o),e&&(this.#i.messagesReceived+=1,this.#i.lastMessageAt=new Date().toISOString()),i&&await this.#A.sendText(t.replyTarget,i),this.#i.lastError=null)})().catch(async A=>{if(this.#s?.aborted){t.statusReaction?.clear();return}t.statusReaction?.error(),this.#i.lastError=A?.message??String(A);let r=At(this.#i,A);this.#a.error?.(`[dsh-im:${this.#e.key}] failed to process a batch input message [${r.referenceId}]:`,A)}).finally(()=>{this.#I.delete(o),this.#h.delete(a)}),this.#h.add(a),a}#Q(t,o,i,e,{releaseMessageId:a=!0,alreadyRecorded:A=!1}={}){let s=(this.#p.get(e)??Promise.resolve()).catch(()=>{}).then(()=>this.#m(t,o,i,e,{alreadyRecorded:A})).finally(()=>{a&&this.#I.delete(o),this.#p.get(e)===s&&this.#p.delete(e)});return this.#p.set(e,s),s}async waitForIdle(){await Promise.allSettled([...this.#p.values(),...[...this.#c.values()].flatMap(t=>t.queue?[t.queue]:[]),...this.#d,...this.#h])}async#S(t,o,i,e){if(this.#r.hasSeen(o))return;await this.#r.markSeen(o),this.#i.messagesReceived+=1,this.#i.lastMessageAt=new Date().toISOString();let a=t.replyTarget;try{let A=await e(Ii(t.content),this.#t,this.#r,i,{signal:this.#s,isDirect:t.kind==="direct",hasImages:Tt(t),hasFiles:wt(t),pendingInteraction:this.#c.has(i)||this.#C.hasPending(i),control:{owner:this,key:i}});A?.stopped&&await Promise.allSettled([this.#G(i),this.#C.closeRoute(i)]);for(let r of A?.messages??[A?.message])r&&await this.#A.sendText(a,r);this.#i.lastError=null}catch(A){if(A?.code==="turn-stopped"||this.#s?.aborted){t.statusReaction?.clear();return}t.statusReaction?.error(),this.#i.lastError=A?.message??String(A);let r=At(this.#i,A);this.#a.error?.(`[dsh-im:${this.#e.key}] failed to process a command [${r.referenceId}]:`,A),await this.#A.sendText(a,dt(r)).catch(()=>{})}}sendConnectionTest(t){return nc({state:this.#r,text:t,channelLabel:w("{label}\u673A\u5668\u4EBA",{label:this.#e.label}),send:(o,i)=>this.#A.sendText(o,i)})}sendProactiveText(t,o,{signal:i}={}){return i?.throwIfAborted(),this.#A.sendText(t,o)}async#y(t,o,i=[],e){let a=await vo({artifacts:i,baseReceipt:e,deliveryId:o,channelKey:this.#e.key,signal:this.#s,sendImage:typeof this.#A.sendImage=="function"?A=>this.#A.sendImage(t,A):void 0,sendFile:typeof this.#A.sendFile=="function"?A=>this.#A.sendFile(t,A):void 0,onFailure:(A,r)=>At(this.#i,r,{userMessage:fue(A?.fileName,r,this.#e),reason:r?.code}),sendFailureNotice:(A,r,s)=>this.#A.sendText(t,dt(s)),logger:this.#a});return this.#i.artifactsSent=(this.#i.artifactsSent??0)+a.artifactsSent,this.#i.artifactSendErrors=(this.#i.artifactSendErrors??0)+a.artifactSendErrors,{receipt:a.receipt,userVisible:a.userVisible,artifactSendErrors:a.artifactSendErrors}}async#m(t,o,i,e,{alreadyRecorded:a=!1}={}){if(!a){if(this.#r.hasSeen(o))return;await this.#r.markSeen(o),this.#i.messagesReceived+=1,this.#i.lastMessageAt=new Date().toISOString()}let A=t.replyTarget,r=Ii(t.content),s=t.batchSubmission,g=null,c=!1;try{if(this.#s?.throwIfAborted(),t.kind==="group"&&t.addressed!==!0){this.#i.messagesRejected+=1,this.#i.lastRejectedAt=new Date().toISOString();return}let I=Tt(t),d=wt(t);if(!r&&!I&&!d){await this.#A.sendText(A,w("\u76EE\u524D\u652F\u6301\u6587\u5B57\u3001\u56FE\u7247\u548C\u6587\u4EF6\u6D88\u606F\u3002"));return}let B=r.toLowerCase();if(!I&&!d&&B==="/help"){await this.#A.sendText(A,[w("{label}\u673A\u5668\u4EBA\u5DF2\u8FDE\u63A5 DeepSeek Harness\u3002",{label:this.#e.label}),"",w("\u76F4\u63A5\u53D1\u9001\u6587\u5B57\u3001\u56FE\u7247\u6216\u6587\u4EF6\u5373\u53EF\u7EE7\u7EED\u5F53\u524D\u4F1A\u8BDD\u3002"),w("/new \u5F00\u542F\u4E00\u4E2A\u5168\u65B0\u4F1A\u8BDD"),w("/compact \u538B\u7F29\u5F53\u524D\u4F1A\u8BDD\u7684\u8F83\u65E9\u4E0A\u4E0B\u6587"),w("/history [\u6570\u91CF] \u67E5\u770B\u6700\u8FD1\u5386\u53F2\u6D88\u606F\uFF08\u9ED8\u8BA4 3 \u6761\uFF0C\u6700\u591A 5 \u6761\uFF09"),w("/workspace \u5DE5\u4F5C\u533A\u5E8F\u53F7\u6216\u7EDD\u5BF9\u8DEF\u5F84 \u5207\u6362\u5DE5\u4F5C\u533A"),w("/workspacelist \u5217\u51FA\u5DE5\u4F5C\u533A\u7EDD\u5BF9\u8DEF\u5F84"),w("/sessionlist \u6216 /sessions [\u5DE5\u4F5C\u533A\u5E8F\u53F7\u6216\u7EDD\u5BF9\u8DEF\u5F84] \u5217\u51FA\u4F1A\u8BDD ID \u548C\u6807\u9898"),w("/session Session ID \u6216\u5F53\u524D\u5DE5\u4F5C\u533A\u5E8F\u53F7 \u5C06\u5F53\u524D\u804A\u5929\u7ED1\u5B9A\u5230\u6307\u5B9A\u4F1A\u8BDD"),w("/models \u6309\u5E8F\u53F7\u5217\u51FA\u6240\u6709\u53EF\u7528\u6A21\u578B"),w("/reasoninglist \u6216 /reasonings \u6309\u5E8F\u53F7\u5217\u51FA\u5F53\u524D\u6A21\u578B\u53EF\u7528\u63A8\u7406\u7B49\u7EA7"),w("/reasoning [\u5E8F\u53F7\u3001\u7B49\u7EA7ID\u6216 --default] \u67E5\u770B\u6216\u5207\u6362\u5F53\u524D\u63A8\u7406\u7B49\u7EA7"),w("/model [\u5E8F\u53F7\u6216\u5B8C\u6574\u6A21\u578BID] [\u63A8\u7406\u7B49\u7EA7ID] \u67E5\u770B\u6216\u5207\u6362\u5F53\u524D\u4F1A\u8BDD\u6A21\u578B"),w("\u793A\u4F8B\uFF1A\u5148\u53D1 /models\uFF0C\u518D\u53D1 /model 2 [\u63A8\u7406\u7B49\u7EA7ID]"),w("/presetlist \u6216 /presets \u6309\u5E8F\u53F7\u5217\u51FA\u53EF\u7528 Agent Preset"),w("/preset [\u5E8F\u53F7\u6216\u5B8C\u6574ID] \u67E5\u770B\u6216\u8BBE\u7F6E\u5F53\u524D\u673A\u5668\u4EBA Agent Preset"),w("\u7EAF\u6570\u5B57 ID\uFF1A/preset id:"),w("/preset --default \u8DDF\u968F Host \u9ED8\u8BA4"),w("/stop \u505C\u6B62\u5F53\u524D\u4EFB\u52A1"),w("/steer \u8865\u5145\u6307\u4EE4 \u7EA0\u504F\u5F53\u524D\u4EFB\u52A1"),w("/batch \u5F00\u59CB\u6279\u91CF\u8F93\u5165\uFF08\u4EC5\u79C1\u804A\uFF0C\u6700\u591A 10 \u6761\u6587\u5B57\uFF09"),w("/send \u63D0\u4EA4\u5F53\u524D\u6279\u6B21"),w("/cancel \u53D6\u6D88\u5F53\u524D\u6279\u6B21"),w("/status \u68C0\u67E5\u8FDE\u63A5\u72B6\u6001"),w("/version \u67E5\u770B\u63D2\u4EF6\u7248\u672C"),w("/help \u663E\u793A\u672C\u5E2E\u52A9")].join(` -`));return}if(!I&&!d&&B==="/status"){await this.#t.ensureRunning({signal:this.#s}),await this.#A.sendText(A,w("{label}\u673A\u5668\u4EBA\u4E0E DeepSeek Harness \u8FDE\u63A5\u6B63\u5E38\u3002",{label:this.#e.label}));return}let f=!I&&!d?await Mo(r,this.#t,e):null;if(f){for(let J of f.messages??[f.message])await this.#A.sendText(A,J);return}if(!I&&!d&&B==="/new"){await this.#r.clearSession(e),await this.#A.sendText(A,w("\u5DF2\u5F00\u542F\u65B0\u4F1A\u8BDD\u3002\u8BF7\u53D1\u9001\u4F60\u7684\u95EE\u9898\u3002"));return}let Q=!I&&!d?await bi(r,this.#t,this.#r,e,{signal:this.#s}):null;if(Q){await this.#A.sendText(A,Q.message);return}await this.#A.sendTyping?.(A).catch(J=>{this.#a.warn?.(`[dsh-im:${this.#e.key}] typing indicator failed:`,J)});let y=!1;if(typeof this.#A.openDeliveryStream=="function")try{g=await this.#A.openDeliveryStream(A),c=!0}catch(J){this.#a.warn?.(`[dsh-im:${this.#e.key}] unable to start a semantic reply stream; using final delivery:`,J)}else if(typeof this.#A.openStream=="function")try{g=await this.#A.openStream(A)}catch(J){this.#a.warn?.(`[dsh-im:${this.#e.key}] unable to start a streamed reply; using text:`,J)}let m=I?await Oo(t,{signal:this.#s}):void 0,T=this.#I.get(o);T&&(m=To(m??r,T,()=>({channel:this.#e.key,senderId:i,senderName:t.contextSource?.()?.senderName})));let{answer:_,artifacts:R=[]}=await Oi({harness:this.#t,state:this.#r,key:e,text:r,content:m,createOptions:this.#s?{signal:this.#s}:void 0,existsOptions:this.#s?{signal:this.#s}:void 0,askOptions:{timeoutMs:this.#n,signal:this.#s,control:{owner:this,key:e},onUpdate:g?async J=>{let U=J.type==="text"?J.text:J.type==="tool"?w("\u6B63\u5728\u4F7F\u7528{name}\u2026",{name:J.name}):J.text;if(U){let N=J.type==="text"?"markdown":"plain";await g.update(c?ts(U,N):U)}}:void 0,onInteraction:J=>this.#E(J,{key:e,actor:i,target:A,requiresMention:t.kind==="group"&&t.requiresMention!==!1}),onInteractionResolved:J=>this.#N(J),files:t.files}});s&&this.#u.complete(e,s.token);let K=!Ii(_)&&R.length>0,L=K?w(uue):_,F=K?"plain":"markdown",q=null,V=null;if(g)try{let J=await g.finish(c?ts(L,F):L);y=!0,V=Zt({deliveryId:o,presentation:J?.presentation??g.presentation??`${this.#e.key}-stream`,providerMessageIds:[...Ua(g),...Ua(J)],deliveryOutcome:J?.deliveryOutcome,reason:J?.reason})}catch(J){g.cancel?.(),this.#a.warn?.(`[dsh-im:${this.#e.key}] streamed reply finalization failed; using text:`,J)}if(!y)try{let J=typeof this.#A.sendDelivery=="function"?await this.#A.sendDelivery(A,ts(L,F)):await this.#A.sendText(A,L);V=Zt({deliveryId:o,presentation:J?.presentation??`${this.#e.key}-text`,providerMessageIds:Ua(J),deliveryOutcome:J?.deliveryOutcome,reason:J?.reason})}catch(J){q=ka(J)}let x=V?.deliveryOutcome==="unknown";V?.deliveryOutcome==="failed"?q=ka(new Error(`Final text delivery failed (${V.reason??"unknown"})`),{uncertain:!1}):x&&(q=ka(new Error(`Final text delivery outcome is unknown (${V.reason??"unknown"})`)));let G=await this.#y(A,o,R,V);if(q&&(!G.userVisible||x))throw q.deliveryReceipt=G.receipt,q;return q&&G.artifactSendErrors===0&&At(this.#i,q),G.userVisible&&(this.#i.messagesReplied+=1,this.#i.lastReplyAt=new Date().toISOString(),this.#i.lastError=null,!q&&G.artifactSendErrors===0&&wo(this.#i)),G.receipt}catch(I){let d=I?.code==="turn-stopped";s&&d&&this.#u.complete(e,s.token);let B=s&&!d?this.#u.fail(e,s.token):null;if(d){if(t.statusReaction?.clear(),g)try{await g.finish(w("\u5DF2\u505C\u6B62\u3002"))}catch{g.cancel?.()}return}if(this.#s?.aborted){t.statusReaction?.clear(),g?.cancel?.();return}t.statusReaction?.error(),this.#i.lastError=I?.message??String(I);let f=async _=>{let R=typeof g?.fail=="function"?"fail":typeof g?.finish=="function"?"finish":null;if(!R)return!1;try{let K=await g[R](_);return R==="fail"?!!K&&K.deliveryOutcome!=="failed":K!==!1&&K?.deliveryOutcome!=="failed"}catch(K){return this.#a.warn?.(`[dsh-im:${this.#e.key}] unable to finalize the failed stream:`,K),!1}},Q=bo(I),y=ko(I),m=At(this.#i,I,{userMessage:y??Q,reason:eo(I)?.reason}),T=B?.retained?`${dt(m)} +`));return}if(!I&&!d&&B==="/status"){await this.#t.ensureRunning({signal:this.#s}),await this.#A.sendText(A,w("{label}\u673A\u5668\u4EBA\u4E0E DeepSeek Harness \u8FDE\u63A5\u6B63\u5E38\u3002",{label:this.#e.label}));return}let f=!I&&!d?await Mo(r,this.#t,e):null;if(f){for(let J of f.messages??[f.message])await this.#A.sendText(A,J);return}if(!I&&!d&&B==="/new"){await this.#r.clearSession(e),await this.#A.sendText(A,w("\u5DF2\u5F00\u542F\u65B0\u4F1A\u8BDD\u3002\u8BF7\u53D1\u9001\u4F60\u7684\u95EE\u9898\u3002"));return}let Q=!I&&!d?await bi(r,this.#t,this.#r,e,{signal:this.#s}):null;if(Q){await this.#A.sendText(A,Q.message);return}await this.#A.sendTyping?.(A).catch(J=>{this.#a.warn?.(`[dsh-im:${this.#e.key}] typing indicator failed:`,J)});let y=!1;if(typeof this.#A.openDeliveryStream=="function")try{g=await this.#A.openDeliveryStream(A),c=!0}catch(J){this.#a.warn?.(`[dsh-im:${this.#e.key}] unable to start a semantic reply stream; using final delivery:`,J)}else if(typeof this.#A.openStream=="function")try{g=await this.#A.openStream(A)}catch(J){this.#a.warn?.(`[dsh-im:${this.#e.key}] unable to start a streamed reply; using text:`,J)}let m=I?await Oo(t,{signal:this.#s}):void 0,T=this.#I.get(o);T&&(m=To(m??r,T,()=>({channel:this.#e.key,senderId:i,senderName:t.contextSource?.()?.senderName,conversationTitle:t.contextSource?.()?.conversationTitle})));let{answer:_,artifacts:R=[]}=await Oi({harness:this.#t,state:this.#r,key:e,text:r,content:m,createOptions:this.#s?{signal:this.#s}:void 0,existsOptions:this.#s?{signal:this.#s}:void 0,askOptions:{timeoutMs:this.#n,signal:this.#s,control:{owner:this,key:e},onUpdate:g?async J=>{let U=J.type==="text"?J.text:J.type==="tool"?w("\u6B63\u5728\u4F7F\u7528{name}\u2026",{name:J.name}):J.text;if(U){let N=J.type==="text"?"markdown":"plain";await g.update(c?ts(U,N):U)}}:void 0,onInteraction:J=>this.#E(J,{key:e,actor:i,target:A,requiresMention:t.kind==="group"&&t.requiresMention!==!1}),onInteractionResolved:J=>this.#N(J),files:t.files}});s&&this.#u.complete(e,s.token);let K=!Ii(_)&&R.length>0,L=K?w(uue):_,F=K?"plain":"markdown",q=null,V=null;if(g)try{let J=await g.finish(c?ts(L,F):L);y=!0,V=Zt({deliveryId:o,presentation:J?.presentation??g.presentation??`${this.#e.key}-stream`,providerMessageIds:[...Ua(g),...Ua(J)],deliveryOutcome:J?.deliveryOutcome,reason:J?.reason})}catch(J){g.cancel?.(),this.#a.warn?.(`[dsh-im:${this.#e.key}] streamed reply finalization failed; using text:`,J)}if(!y)try{let J=typeof this.#A.sendDelivery=="function"?await this.#A.sendDelivery(A,ts(L,F)):await this.#A.sendText(A,L);V=Zt({deliveryId:o,presentation:J?.presentation??`${this.#e.key}-text`,providerMessageIds:Ua(J),deliveryOutcome:J?.deliveryOutcome,reason:J?.reason})}catch(J){q=ka(J)}let x=V?.deliveryOutcome==="unknown";V?.deliveryOutcome==="failed"?q=ka(new Error(`Final text delivery failed (${V.reason??"unknown"})`),{uncertain:!1}):x&&(q=ka(new Error(`Final text delivery outcome is unknown (${V.reason??"unknown"})`)));let G=await this.#y(A,o,R,V);if(q&&(!G.userVisible||x))throw q.deliveryReceipt=G.receipt,q;return q&&G.artifactSendErrors===0&&At(this.#i,q),G.userVisible&&(this.#i.messagesReplied+=1,this.#i.lastReplyAt=new Date().toISOString(),this.#i.lastError=null,!q&&G.artifactSendErrors===0&&wo(this.#i)),G.receipt}catch(I){let d=I?.code==="turn-stopped";s&&d&&this.#u.complete(e,s.token);let B=s&&!d?this.#u.fail(e,s.token):null;if(d){if(t.statusReaction?.clear(),g)try{await g.finish(w("\u5DF2\u505C\u6B62\u3002"))}catch{g.cancel?.()}return}if(this.#s?.aborted){t.statusReaction?.clear(),g?.cancel?.();return}t.statusReaction?.error(),this.#i.lastError=I?.message??String(I);let f=async _=>{let R=typeof g?.fail=="function"?"fail":typeof g?.finish=="function"?"finish":null;if(!R)return!1;try{let K=await g[R](_);return R==="fail"?!!K&&K.deliveryOutcome!=="failed":K!==!1&&K?.deliveryOutcome!=="failed"}catch(K){return this.#a.warn?.(`[dsh-im:${this.#e.key}] unable to finalize the failed stream:`,K),!1}},Q=bo(I),y=ko(I),m=At(this.#i,I,{userMessage:y??Q,reason:eo(I)?.reason}),T=B?.retained?`${dt(m)} ${B.message}`:dt(m);if(this.#a.error?.(`[dsh-im:${this.#e.key}] failed to process a message [${m.referenceId}]:`,I),await f(T))return I.deliveryReceipt;g?.cancel?.();try{await this.#A.sendText(A,T)}catch(_){this.#a.error?.(`[dsh-im:${this.#e.key}] failed to send the safe error reply:`,_)}return I.deliveryReceipt}finally{await Promise.allSettled([this.#G(e),this.#C.closeRoute(e)])}}async#D(t,o,i,e,a){if(this.#s?.aborted){t.statusReaction?.clear();return}let A=this.#c.get(e),r=a.claimedReplyMessageId===o;if(!A||A!==a||A.submitting)return r&&(!A||A!==a)?this.#O(t,o):this.#Q(t,o,i,e,{releaseMessageId:!1});if(this.#r.hasSeen(o))return;if(await this.#r.markSeen(o),this.#i.messagesReceived+=1,this.#i.lastMessageAt=new Date().toISOString(),t.kind==="group"&&t.addressed!==!0){this.#i.messagesRejected+=1,this.#i.lastRejectedAt=new Date().toISOString();return}let s=t.replyTarget,g=Ii(t.content);if(!g||Tt(t)||wt(t)){try{await this.#A.sendText(s,w("\u8BF7\u7528\u6587\u5B57\u56DE\u7B54\u5F53\u524D\u95EE\u9898\u3002"))}catch(d){this.#a.error?.(`[dsh-im:${this.#e.key}] failed to reject a non-text interaction reply:`,d)}return}let c=this.#c.get(e);if(!c||c!==a||c.submitting)return r&&(!c||c!==a)?this.#O(t,o,{alreadyRecorded:!0}):this.#Q(t,o,i,e,{releaseMessageId:!1,alreadyRecorded:!0});if(c.target=s,c.needsPresentation){let d=c.presentationTask!==null;try{await this.#T(c)}catch(f){t.statusReaction?.error(),this.#i.lastError=w("{label}\u4EA4\u4E92\u95EE\u9898\u53D1\u9001\u5931\u8D25\u3002",{label:this.#e.label}),this.#a.error?.(`[dsh-im:${this.#e.key}] failed to retry an interaction question:`,f),c.interaction.reconnect?.();return}let B=this.#c.get(e);if(!B||B!==a||B.submitting)return r&&(!B||B!==a)?this.#O(t,o,{alreadyRecorded:!0}):this.#Q(t,o,i,e,{releaseMessageId:!1,alreadyRecorded:!0});if(!d)return}let I=c.questions[c.index];if(I){if(c.answers.push(wi(I,g)),c.index+=1,c.indexthis.#A.sendText(e,c)});if(t?.kind!=="question")return;let A=t?.payload?.questions,r=Ii(t?.interactionId)||Ii(t?.rpcId);if(!Ii(t?.rpcId)||!r||!Ii(t?.sessionId)||!Array.isArray(A)||A.length===0||A.some(c=>!mi(c))){this.#a.warn?.(`[dsh-im:${this.#e.key}] ignored an invalid Harness question interaction`);return}if(t.recovered===!0){await this.#_(t,`${this.#e.label} safely cancelled an interaction left by an earlier client.`);try{await this.#A.sendText(e,w("\u68C0\u6D4B\u5230\u8FD9\u4E2A Session \u4E2D\u9057\u7559\u7684\u5F85\u56DE\u7B54\u95EE\u9898\uFF0C\u5DF2\u5B89\u5168\u53D6\u6D88\u5E76\u7EE7\u7EED\u5904\u7406\u4F60\u521A\u624D\u7684\u6D88\u606F\u3002"))}catch(c){this.#a.error?.(`[dsh-im:${this.#e.key}] failed to send an interaction recovery notice:`,c)}return}let s=this.#c.get(o);if(s?.interactionId===r){s.interaction=t,s.needsPresentation&&await this.#T(s);return}if(this.#g.has(r))return;if(s){this.#a.warn?.(`[dsh-im:${this.#e.key}] cancelled a second pending Harness question`),await this.#_(t,`${this.#e.label} is already handling another user interaction.`);return}let g={kind:"question",interactionId:r,sessionId:t.sessionId,interaction:t,actor:i,requiresMention:a,questions:A,answers:[],index:0,target:e,queue:null,claimedReplyMessageId:null,submitting:!1,needsPresentation:!0,presentationTask:null};this.#c.set(o,g),this.#g.set(r,o),await this.#T(g)}async#N(t){if(t?.kind==="approval"){await this.#C.handleResolved(t);return}let o=Ii(t?.interactionId);if(t?.kind!=="question"||!o)return;let i=this.#g.get(o);i&&this.#R(i,o)}#T(t){if(t.presentationTask)return t.presentationTask;let o=t.questions[t.index];if(!o)return Promise.resolve();let i=(async()=>{await this.#A.sendText(t.target,Si(o,t.index,t.questions.length,{requiresMention:t.requiresMention})),t.needsPresentation=!1})();return t.presentationTask=i,i.then(()=>{t.presentationTask===i&&(t.presentationTask=null)},()=>{t.presentationTask===i&&(t.presentationTask=null)}),i}async#O(t,o,{alreadyRecorded:i=!1}={}){if(!i){if(this.#r.hasSeen(o))return;await this.#r.markSeen(o),this.#i.messagesReceived+=1,this.#i.lastMessageAt=new Date().toISOString()}try{await this.#A.sendText(t.replyTarget,w(K1))}catch(e){this.#a.error?.(`[dsh-im:${this.#e.key}] failed to send an expired interaction notice:`,e)}}#w(t,o){let i=this.#c.get(t);return!i||o!==void 0&&i.interactionId!==o?null:(this.#c.delete(t),this.#g.delete(i.interactionId),i)}#R(t,o){return this.#w(t,o)!==null}async#_(t,o){try{await t.respond({ok:!1,error:{code:"cancelled",message:o,details:{}}},{signal:AbortSignal.timeout(5e3)})}catch(i){if(i?.code!=="interaction-not-pending")throw i}}async#G(t){let o=this.#w(t);if(!(!o||o.kind!=="question"))try{await this.#_(o.interaction,`The ${this.#e.label} interaction ended before the user answered.`)}catch(i){this.#a.warn?.(`[dsh-im:${this.#e.key}] failed to cancel a pending Harness interaction:`,i)}}};var Y_=Object.freeze({key:"discord",label:"Discord",connectionLabel:" Gateway \u957F\u8FDE\u63A5",reactions:Object.freeze({processing:"\u{1F440}",success:"\u2705",error:"\u274C"})}),qQ=class extends ns{constructor(t){super({descriptor:Y_,...t})}};var aC=class extends xp{constructor(t){super({...t,descriptor:Y_,inspectToken:t.inspectToken??U1,deriveIdentity:v1,maskPlatformId:P1})}};var zQ=class extends ur{constructor(t){super({...t,rpcIdPrefix:"discord",logPrefix:"dsh-discord"})}};function ss(n,t){let o=typeof n=="string"?n.trim():"";if(!o)return[];let i=[],e=o;for(;e.length>t;){let a=e.lastIndexOf(` `,t);anull,logger:r=console}){let s,g=[],c=null,I=null,d=null,B=!1,f=n,Q=()=>{B||I!==null||d||!c||(I=setTimeout(()=>{I=null;let y=c;c=null;let m=ss(y,t)[0]??n;d=Promise.resolve(m===f?void 0:e(s,m)).then(()=>{f=m}).catch(T=>r.warn?.("[dsh-im] streamed message update failed:",T)).finally(()=>{d=null,Q()})},o),I?.unref?.())};return{get messageId(){return s},get providerMessageIds(){return[...g]},async start(){return s=await i(n),(typeof s=="string"&&s.trim()||Number.isSafeInteger(s))&&g.push(String(s)),this},update(y){B||typeof y!="string"||!y.trim()||(c=y,Q())},async finish(y){if(B)throw new Error("Message stream is already closed");B=!0,I!==null&&clearTimeout(I),I=null,c=null,await d?.catch(()=>{});let m=ss(y,t),T=m[0]??w("\u5904\u7406\u5B8C\u6210\u3002");T!==f&&await e(s,T),f=T;for(let _ of m.slice(1)){let R=await a(_),K=A(R);(typeof K=="string"&&K.trim()||Number.isSafeInteger(K))&&g.push(String(K))}},cancel(){B=!0,c=null,I!==null&&clearTimeout(I),I=null}}}async function x1(n){try{await n?.body?.cancel?.()}catch{}}function Que(n,t){return!Array.isArray(t)||t.some(o=>typeof o=="string"&&(n.hostname===o||o.startsWith(".")&&(n.hostname===o.slice(1)||n.hostname.endsWith(o))))}async function Yp(n,{fetchImpl:t=fetch,headers:o,signal:i,allowedHosts:e}={}){let a=new URL(n);if(a.protocol!=="https:")throw new Error("File download URL must use HTTPS");if(!Que(a,e))throw new Error("File download URL is not hosted by the messaging platform");let A=await t(a,{method:"GET",headers:o,signal:i,redirect:"manual"});if(Number.isInteger(A?.status)&&A.status>=300&&A.status<400){await x1(A);let r=new Error(`File download redirect was blocked (HTTP ${A.status})`);throw r.code="file-redirect-blocked",r}if(!A?.ok){await x1(A);let r=new Error(`File download failed with HTTP ${A?.status??"unknown"}`);throw r.code="file-http-error",r.status=A?.status,r}if(A.body?.[Symbol.asyncIterator])return{stream:A.body};if(typeof A.arrayBuffer=="function"){let r=Buffer.from(await A.arrayBuffer());return{stream:(async function*(){yield r})()}}throw new Error("File download returned no readable body")}var yue=37377,mue=5e3,Y1=Object.freeze([1e3,3e3,5e3,1e4,3e4]),Sue=0,wue=5,Due=10,Oue=11,bue=12,Mue=new Set([Due,Oue,bue]),_ue=new Set(["image/jpeg","image/png","image/webp","image/gif"]),Tue=new Map([[".jpg","image/jpeg"],[".jpeg","image/jpeg"],[".png","image/png"],[".webp","image/webp"],[".gif","image/gif"]]),q1=Object.freeze(["cdn.discordapp.com"]);function Nue(n){let t=new URL(n);if(t.protocol!=="wss:")throw new Error("Discord returned an insecure Gateway URL");return t.searchParams.set("v","10"),t.searchParams.set("encoding","json"),t.href}function j_(n,t,o){if(typeof n.addEventListener=="function")n.addEventListener(t,o);else if(typeof n.on=="function")n.on(t,o);else throw new TypeError("Discord WebSocket does not support events")}function Rue(n){return typeof n=="string"?n:typeof n?.data=="string"?n.data:Buffer.isBuffer(n)?n.toString("utf8"):Buffer.isBuffer(n?.data)?n.data.toString("utf8"):null}function kue(n){if(n===4004){let o=new Error(w("Discord Bot Token \u65E0\u6548\uFF0C\u8BF7\u91CD\u65B0\u586B\u5199\u3002"));return o.code="discord-401",o}if(n===4013||n===4014){let o=new Error(w("Discord Gateway Intents \u914D\u7F6E\u4E0D\u6B63\u786E\uFF0C\u8BF7\u68C0\u67E5 Developer Portal \u7684 Bot \u8BBE\u7F6E\u3002"));return o.code="discord-intents",o}let t=new Error(`Discord Gateway closed (${n||"unknown"})`);return t.code="discord-gateway-closed",t}function z1(n,t){return typeof n!="string"?"":n.replace(new RegExp(`<@!?${t}>`,"g"),"").trim()}function vue(n,t){return[...z1(n?.content??"",t).replace(/\s+/g," ").trim()||"DeepSeek Harness"].slice(0,100).join("")}function z_(n){return Mue.has(Number(n?.type))}function V1(n,t){return z_(n)&&String(n?.id??"")===String(t?.id??"")&&String(n?.parent_id??"")===String(t?.channel_id??"")}function J_(n,t){return n?.id&&t?.(n),n}function UI(n,t,o,{fromSourceMessage:i=!1,fallback:e=null,notice:a=null}={}){let A=String(t?.id??n.conversationId),r=z_(t),s=r&&String(t?.owner_id??"")===String(o),g=r&&t?.parent_id?String(t.parent_id):A;return{...n,conversationId:A,addressed:n.addressed||s,requiresMention:r?!s:n.kind==="group",replyTarget:{channelId:A,...!i&&n.replyTarget?.replyToMessageId?{replyToMessageId:n.replyTarget.replyToMessageId}:{},...a?{notice:a}:{}},connectionTestTarget:{channelId:A},conversationRoute:{peerId:g,...r?{threadId:A,managed:s}:{},...e?{fallback:e}:{}}}}function Pue(n){let t=Number(n?.status);return!Number.isInteger(t)||t>=500}function j1(n){let t=new Error("Discord Thread creation result is uncertain",{cause:n});return t.code="discord-thread-create-uncertain",t}async function Gue(n,t,{signal:o,onChannel:i}={}){try{let e=J_(await n.getChannel({channelId:String(t.id),signal:o}),i);return V1(e,t)?e:null}catch(e){if(e?.status===404)return null;throw e}}async function J1(n,t,o){try{await n.createMessage({channelId:t.replyTarget.channelId,replyToMessageId:t.replyTarget.replyToMessageId,content:"Thread \u521B\u5EFA\u7ED3\u679C\u6682\u65F6\u65E0\u6CD5\u786E\u8BA4\u3002\u82E5\u5DF2\u521B\u5EFA\uFF0C\u8BF7\u5728\u5BF9\u5E94 Thread \u4E2D\u91CD\u8BD5\uFF1B\u82E5\u672A\u521B\u5EFA\uFF0C\u8BF7\u7A0D\u540E\u91CD\u65B0 @\u673A\u5668\u4EBA\u3002",signal:o})}catch(i){if(o?.aborted)throw o.reason??i}}function W1(n){let t=typeof n?.content_type=="string"?n.content_type.split(";",1)[0].trim().toLowerCase():"";if(_ue.has(t))return t;let o=typeof n?.filename=="string"?n.filename.toLowerCase():"";for(let[i,e]of Tue)if(o.endsWith(i))return e;return null}function Z1(n){return Number.isSafeInteger(n)&&n>=0?n:void 0}function Fue(n,t){let o=W1(n);return!o||typeof n?.url!="string"?null:{name:typeof n.filename=="string"?n.filename:void 0,mediaType:o,size:Z1(n.size),load:i=>Do(n.url,{...i,fetchImpl:t,allowedHosts:q1})}}function Lue(n,t){if(W1(n)||typeof n?.url!="string"||!n.url)return null;let o=typeof n.content_type=="string"&&n.content_type?n.content_type.split(";",1)[0].trim().toLowerCase():void 0;return{name:typeof n.filename=="string"&&n.filename?n.filename:String(n.id??"discord-file"),...o?{mediaType:o}:{},size:Z1(n.size),load:({signal:i}={})=>Yp(n.url,{fetchImpl:t,signal:i,allowedHosts:q1})}}function X1(n,t,{fetchImpl:o=fetch}={}){if(!n?.id||!n?.channel_id||!n?.author?.id||Number(n.type)===21)return null;let i=!n.guild_id,e=i||n.mentions?.some(a=>String(a?.id)===String(t));return{messageId:String(n.id),senderId:String(n.author.id),contextSource:()=>({senderName:[n.member?.nick,n.author.global_name,n.author.username].find(a=>typeof a=="string"&&a.trim())}),senderIsBot:n.author.bot===!0,kind:i?"direct":"group",conversationId:String(n.channel_id),content:z1(n.content??"",t),plainText:(!Array.isArray(n.attachments)||n.attachments.length===0)&&(!Array.isArray(n.sticker_items)||n.sticker_items.length===0)&&!n.poll,images:Array.isArray(n.attachments)?n.attachments.map(a=>Fue(a,o)).filter(Boolean):[],files:Array.isArray(n.attachments)?n.attachments.map(a=>Lue(a,o)).filter(Boolean):[],addressed:e,replyTarget:{channelId:String(n.channel_id),replyToMessageId:String(n.id)},reactionTarget:{channelId:String(n.channel_id),messageId:String(n.id)},connectionTestTarget:{channelId:String(n.channel_id)}}}async function Uue(n,t,{api:o,channel:i,fetchImpl:e=fetch,signal:a,onChannel:A}={}){let r=X1(n,t,{fetchImpl:e});if(!r||r.senderIsBot)return r;if(a?.throwIfAborted(),r.kind==="direct")return UI(r,{id:r.conversationId,type:1},t);if(!o||typeof o.getChannel!="function")throw new TypeError("Discord route resolution requires the Discord API");let s=J_(i??await o.getChannel({channelId:r.conversationId,signal:a}),A);if(z_(s)||!r.addressed)return UI(r,s,t);let g=Number(s?.type);if(g!==Sue&&g!==wue)return UI(r,s,t,{fallback:"unsupported-channel",notice:"\u5F53\u524D\u9891\u9053\u4E0D\u652F\u6301\u81EA\u52A8\u521B\u5EFA Thread\uFF0C\u5DF2\u76F4\u63A5\u5728\u5F53\u524D\u9891\u9053\u56DE\u590D\u3002"});a?.throwIfAborted();let c;try{if(c=J_(await o.startThreadFromMessage({channelId:r.conversationId,messageId:r.messageId,name:vue(n,t),signal:a}),A),!V1(c,n))throw new Error("Discord returned an invalid thread for the source message")}catch(I){let d;try{d=await Gue(o,n,{signal:AbortSignal.timeout(mue),onChannel:A})}catch(B){throw a?.aborted?a.reason??I:(await J1(o,r,a),j1(B))}if(d)return UI(r,d,t,{fromSourceMessage:!0});if(a?.aborted)throw a.reason??I;if(Pue(I))throw await J1(o,r,a),j1(I);return UI(r,s,t,{fallback:"thread-create-failed",notice:"\u65E0\u6CD5\u521B\u5EFA Thread\uFF0C\u5DF2\u76F4\u63A5\u5728\u5F53\u524D\u9891\u9053\u56DE\u590D\u3002"})}return UI(r,c,t,{fromSourceMessage:!0})}var q_=class{#e;#A;#t=new WeakSet;constructor({api:t,signal:o}){this.#e=t,this.#A=o}async sendText(t,o){let i=!this.#t.has(t)&&t?.notice?String(t.notice):null,e=ss(i?`${i} @@ -361,10 +361,10 @@ ID\uFF1A{id}`,{title:r,id:A?.sessionId??i}),w("\u53D1\u9001 /history \u67E5\u770 ${w("\u5185\u5BB9\u8F83\u957F\uFF0C\u751F\u6210\u5B8C\u6210\u540E\u5C06\u5206\u6BB5\u53D1\u9001\u5B8C\u6574\u56DE\u7B54\u3002")}`;return EP(n,Tu-t.length)+t}function Cke(n){let t=[],o=n;for(;o.length>Tu;){let i=EP(o,Tu),e=i.lastIndexOf(` `)+1;e{let c=String(g??"")||"\u2026";await this.#i(a,T6(c)),A=c}};await o.markdown(r);let s=Cke(A);for(let[g,c]of s.entries()){let I=g===0?a:await this.#o(t,i.replyTo);g>0&&e.push(I),await this.#i(I,c),await this.#a(I)}return{messageId:a.messageId,providerMessageIds:e.map(g=>g.messageId)}}catch(a){for(let A of e)await this.#s(A.messageId);throw a}}async sendFile(t,o,{replyTo:i,signal:e}={}){return this.#l(t,o,{replyTo:i,signal:e,messageType:"file",presentation:"feishu-file"})}async sendImage(t,o,{replyTo:i,signal:e}={}){return this.#l(t,o,{replyTo:i,signal:e,messageType:"image",presentation:"feishu-image"})}async#l(t,o,{replyTo:i,signal:e,messageType:a,presentation:A}){if(e?.throwIfAborted(),typeof t!="string"||!t)throw new TypeError("chatId is required");if(!o||typeof o!="object"||typeof o.artifactId!="string"||!o.artifactId||typeof o.deliveryKey!="string"||!o.deliveryKey||typeof o.fileName!="string"||!o.fileName||!Buffer.isBuffer(o.bytes))throw new TypeError("A materialized result file is required");let r;try{r=await _6(Q=>{Q.throwIfAborted();let y=a==="image"?this.#e.im.v1.image.create({data:{image_type:"message",image:o.bytes}}):this.#e.im.v1.file.create({data:{file_type:"stream",file_name:o.fileName,file:o.bytes}});return un(o,y),y},{signal:e,timeoutMs:this.#t,stage:"upload"})}catch(Q){throw e?.aborted?hP(e):_u("upload",Q)}e?.throwIfAborted();let s=a==="image"?r?.image_key??r?.data?.image_key:r?.file_key??r?.data?.file_key;if(typeof s!="string"||!s)throw _u("upload",void 0,r?.code);let g=hke(o,t,a),c=JSON.stringify(a==="image"?{image_key:s}:{file_key:s}),I=i?{path:{message_id:i},data:{msg_type:a,content:c,uuid:g}}:{params:{receive_id_type:"chat_id"},data:{receive_id:t,msg_type:a,content:c,uuid:g}},d=()=>{let Q=i?this.#e.im.v1.message.reply(I):this.#e.im.v1.message.create(I);return un(o,Q),Q},B;try{B=await _6(async Q=>{Q.throwIfAborted();let y;try{y=await d()}catch(m){if(k6(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?hP(e):_u("message send",Q,void 0,{uncertain:!0})}if(Number.isFinite(Number(B?.code))&&Number(B.code)!==0)throw _u("message send",void 0,B.code,{uncertain:!0});let f=B?.data?.message_id;if(typeof f!="string"||!f)throw _u("message send",void 0,void 0,{uncertain:!0});return Zt({deliveryId:o.deliveryKey,presentation:A,providerMessageIds:[f],artifacts:[{artifactId:o.artifactId,outcome:"sent"}]})}async#o(t,o){let i=T6(this.#A),a=Cl("Feishu card.create",await this.#e.cardkit.v1.card.create({data:{type:"card_json",data:JSON.stringify(uke(i))}}))?.data?.card_id;if(!a)throw new Error("Feishu card.create returned no card_id");let A=await this.#n(t,a,o);return{cardId:a,messageId:A,content:i,sequence:0}}async#i(t,o){if(o===t.content)return;let i=await this.#e.cardkit.v1.cardElement.content({path:{card_id:t.cardId,element_id:N6},data:{content:o,sequence:++t.sequence,uuid:`content_${t.cardId}_${t.sequence}`}});Cl("Feishu cardElement.content",i),t.content=o}async#a(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:Eke(t.content)||w("\u56DE\u7B54\u5B8C\u6210")}}}),sequence:++t.sequence,uuid:`settings_${t.cardId}_${t.sequence}`}});Cl("Feishu card.settings",o)}async#n(t,o,i){let e=JSON.stringify({type:"card",data:{card_id:o}}),a=i?await this.#e.im.v1.message.reply({path:{message_id:i},data:{msg_type:"interactive",content:e}}):await this.#e.im.v1.message.create({params:{receive_id_type:"chat_id"},data:{receive_id:t,msg_type:"interactive",content:e}});Cl("Feishu message send",a);let A=a?.data?.message_id;if(!A)throw new Error("Feishu message send returned no message_id");return A}async#s(t){try{let o=await this.#e.im.v1.message.delete({path:{message_id:t}});Cl("Feishu message delete",o)}catch(o){console.warn("[bridge] unable to recall a failed streaming card:",o.message)}}async addReaction(t,o){let e=Cl("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){Cl("Feishu reaction.delete",await this.#e.im.v1.messageReaction.delete({path:{message_id:t,reaction_id:o}}))}};var P6="/open-apis/application/v7/app_slash_commands",Bke=new Set(["99991640","99991672"]),ES=Object.freeze(["application:app_slash_command:read","application:app_slash_command:write"]),G6="ai-agent_outlined",CP=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:"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 uP(n,t){let o=n==="lark"?"https://open.larksuite.com":"https://open.feishu.cn";return new URL(t,o)}function v6(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 BP(n,t){let o=AbortSignal.timeout(t);return n?AbortSignal.any([n,o]):o}async function fP(n,t,o){try{return v6(await n.request(t),o)}catch(i){let e=i?.response?.data;if(e&&typeof e=="object"&&!Array.isArray(e)&&Object.hasOwn(e,"code"))return v6(e,o);throw i}}async function fke({appId:n,appSecret:t,domain:o,httpInstance:i,timeoutMs:e,signal:a}){if(!n||!t)throw new Error("Feishu slash registration requires app credentials");if(!i||typeof i.request!="function")throw new TypeError("Feishu slash registration requires an HTTP instance");let A=await fP(i,{method:"POST",url:uP(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:BP(a,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 Qke({tenantAccessToken:n,domain:t,httpInstance:o,timeoutMs:i,signal:e}){let a=await fP(o,{method:"GET",url:uP(t,P6).href,headers:{authorization:`Bearer ${n}`,"content-type":"application/json; charset=utf-8"},signal:BP(e,i),timeout:i},"Feishu slash command list");return Array.isArray(a.data?.items)?a.data.items:[]}async function yke({tenantAccessToken:n,domain:t,httpInstance:o,timeoutMs:i,signal:e,command:a,description:A,icon:r=G6}){let s={command:a};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 fP(o,{method:"POST",url:uP(t,P6).href,headers:{authorization:`Bearer ${n}`,"content-type":"application/json; charset=utf-8"},data:s,signal:BP(e,i),timeout:i},`Feishu slash command create (/${a})`)).data?.command_id??null}async function F6({appId:n,appSecret:t,domain:o="feishu",httpInstance:i,timeoutMs:e=15e3,signal:a,manifest:A=CP}){let r=await fke({appId:n,appSecret:t,domain:o,httpInstance:i,timeoutMs:e,signal:a}),s=new Set((await Qke({tenantAccessToken:r,domain:o,httpInstance:i,timeoutMs:e,signal:a})).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 yke({tenantAccessToken:r,domain:o,httpInstance:i,timeoutMs:e,signal:a,command:d,description:B,icon:I.icon??G6});g.push({command:d,command_id:f})}catch(B){if(B?.code==="40000000"&&/already exists/i.test(B?.msg??"")){s.add(d);continue}if(Bke.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 Ske=15e3,wke="\u2705 \u4FEE\u590D\u5B8C\u6210\uFF1A\u5DF2\u5B9E\u6D4B\u6536\u5230 card.action.trigger\uFF0C\u83DC\u5355\u6309\u94AE\u73B0\u5728\u53EF\u7528\u3002",Dke="\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",QP="\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",Oke="\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",bke=new Set(["connected","connecting","reconnecting"]);function Mn(n){return typeof n=="string"&&n.trim()?n.trim():null}function Mke(n){return Mn(n?.operator?.open_id)??Mn(n?.operator?.operator_id?.open_id)}function _ke(n,t){try{let o=n?.getConnectionStatus?.()?.state;return typeof o=="string"&&o?o:t}catch{return t}}function Yd(n,t){let o=new Error(t);return o.code=n,o}function Tke(n,t){if(!n||typeof n.request!="function")return;let o=i=>({...i??{},timeout:i?.timeout??t});return{request:i=>n.request(o(i)),get:(i,e)=>n.get(i,o(e)),delete:(i,e)=>n.delete(i,o(e)),head:(i,e)=>n.head(i,o(e)),options:(i,e)=>n.options(i,o(e)),post:(i,e,a)=>n.post(i,e,o(a)),put:(i,e,a)=>n.put(i,e,o(a)),patch:(i,e,a)=>n.patch(i,e,o(a))}}function Nke({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 CS=class{#e;#A;#t;#r;#l;#o;#i;#a;#n;#s;#p;#c;#g;#I;#d;#h;#C;#u;#B=null;#f=null;#Q=null;#S=null;#y=null;#m=null;#D=new Map;#E;#N=!0;constructor({lark:t,botId:o,appId:i,appSecret:e,domain:a="feishu",botOpenId:A,groupResponseMode:r,ownerOpenId:s,ownerOpenIds:g,harness:c,state:I,contextEnhancement:d,accessPolicy:B,repair:f,replyTimeoutMs:Q=6e5,connectTimeoutMs:y=15e3,requestTimeoutMs:m=Ske,slashCommands:T=!0,wsAgent:_,logger:R=console}){if(!t)throw new Error("FeishuRuntime requires the Feishu SDK");if(!i||!e)throw new Error("FeishuRuntime requires app credentials");let K=Array.isArray(g)?g:[s],L=[...new Set(K.filter(F=>typeof F=="string"&&F))];if(L.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&&!Mn(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=Mn(o),this.#t=i,this.#r=e,this.#l=a,this.#o=Mn(A),this.#i=Io(r),this.#a=L,this.#n=c,this.#s=I,this.#p=d,this.#c=B,this.#u=f??null,this.#g=Q,this.#I=y,this.#d=m,this.#N=!!T,this.#h=_,this.#C=R,this.#E=Nke({allowedSenderCount:L.length})}get status(){return structuredClone(this.#E)}setGroupResponseMode(t){this.#i=Io(t),this.#f?.setGroupResponseMode(this.#i)}async start(){for(;;){for(;this.#y;)await this.#y;if(this.#S)return this.#S;let o=this.#Q;if(o){let i=_ke(o,this.#E.feishuLongConnectionState);if(bke.has(i))return this.status;await this.stop({preserveError:i==="failed"});continue}if(this.#B||this.#f||this.#m){await this.stop({preserveError:this.#E.feishuLongConnectionState==="failed"});continue}break}let t;return t=this.#T().finally(()=>{this.#S===t&&(this.#S=null)}),this.#S=t,t}async#T(){let t=new AbortController;this.#m=t;let{signal:o}=t,i=()=>o.reason??new DOMException("Feishu runtime stopped","AbortError"),e=()=>!o.aborted&&this.#m===t,a=()=>{if(!e())throw i()};this.#E.startedAt=new Date().toISOString(),this.#E.feishuLongConnectionState="connecting",this.#E.lastError=null;try{await this.#n.ensureRunning({signal:o}),a(),this.#E.harnessReachable=!0;let A=this.#l==="lark"?this.#e.Domain.Lark:this.#e.Domain.Feishu,r={appId:this.#t,appSecret:this.#r,domain:A},s=Tke(this.#e.defaultHttpInstance,this.#d);s&&(r.httpInstance=s);let g=new this.#e.Client(r);this.#B=g;let c=new hS({client:g,initialText:w("\u5DF2\u8FDE\u63A5 DeepSeek Harness\uFF0C\u6B63\u5728\u601D\u8003\u2026")}),I=new pS({client:g,channel:c,harness:this.#n,state:this.#s,contextEnhancement:this.#p,accessPolicy:this.#c,status:this.#E,allowedSenderOpenIds:new Set(this.#a),botId:this.#A,appId:this.#t,botOpenId:this.#o,groupResponseMode:this.#i,repair:this.#u,replyTimeoutMs:this.#g,signal:o,logger:this.#C});this.#f=I;let d=new this.#e.EventDispatcher({}).register({"im.message.receive_v1":T=>{e()&&I.accept(T)},"im.message.reaction.created_v1":()=>{},"im.message.reaction.deleted_v1":()=>{},"card.action.trigger":T=>{e()&&(this.#E.cardActionsReceived+=1,this.#E.lastCardActionAt=new Date().toISOString(),this.#O(T)||I.onCardAction(T))}}),B,f,Q=new Promise((T,_)=>{let R=!1,K=()=>{f(i())},L=(q,V)=>{R||(R=!0,clearTimeout(F),o.removeEventListener("abort",K),q(V))},F=setTimeout(()=>{L(_,new Error(`Feishu WebSocket handshake timed out after ${this.#I}ms`))},this.#I);B=()=>{L(T)},f=q=>{L(_,q)},o.addEventListener("abort",K,{once:!0}),o.aborted&&K()});Q.catch(()=>{});let y=new this.#e.WSClient({...r,...this.#h?{agent:this.#h}:{},loggerLevel:this.#e.LoggerLevel.info,handshakeTimeoutMs:this.#I,onReady:()=>{e()&&(this.#E.feishuLongConnectionState="connected",this.#E.ready=!0,this.#E.lastError=null,B())},onError:T=>{e()&&(this.#E.feishuLongConnectionState="failed",this.#E.ready=!1,this.#E.lastError=T?.message??String(T),this.#C.error("[dsh-feishu] Feishu long connection failed:",this.#E.lastError),f(T))},onReconnecting:()=>{e()&&(this.#E.feishuLongConnectionState="reconnecting",this.#E.ready=!1)},onReconnected:()=>{e()&&(this.#E.feishuLongConnectionState="connected",this.#E.ready=!0,this.#E.lastError=null)}});this.#Q=y;let m=Promise.resolve().then(()=>y.start({eventDispatcher:d})).catch(T=>{throw f(T),T});return await Promise.all([m,Q]),a(),this.#N&&s&&this.#R(s,e,o),this.status}catch(A){throw o.aborted||(this.#E.ready=!1,this.#E.feishuLongConnectionState="failed",this.#E.lastError=A?.message??String(A),await this.#G({preserveError:!0,abortController:t})),A}}async beginCardActionProbe({expectedOperatorOpenId:t,timeoutMs:o=9e4}={}){if(!this.#E.ready||!this.#B)throw Yd("card_action_probe_unavailable","\u98DE\u4E66\u673A\u5668\u4EBA\u5C1A\u672A\u8FDE\u63A5");let i=Mn(t);if(!i||i==="*")throw new TypeError("A precise Feishu operator open_id is required");if(!Number.isFinite(o)||o<=0||o>10*6e4)throw new TypeError("Card-action probe timeout must be between 1 and 600000ms");let e=mke().replaceAll("-",""),a;try{a=await this.#B.im.v1.message.create({params:{receive_id_type:"open_id"},data:{receive_id:i,msg_type:"interactive",content:p6(e)}})}catch{throw this.#w(i,w(QP),"failure"),Yd("card_action_probe_send_failed","\u65E0\u6CD5\u53D1\u9001\u98DE\u4E66\u5361\u7247\u56DE\u8C03\u6D4B\u8BD5")}if(a?.code&&a.code!==0)throw this.#w(i,w(QP),"failure"),Yd("card_action_probe_send_failed","\u65E0\u6CD5\u53D1\u9001\u98DE\u4E66\u5361\u7247\u56DE\u8C03\u6D4B\u8BD5");let A=Mn(a?.data?.message_id)??Mn(a?.message_id);if(!A)throw this.#w(i,w(QP),"failure"),Yd("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.#w(i,w(Dke),"timeout"),s(Yd("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:i,timeout:g,resolve:r,reject:s})})}#O(t){let o=Mn(t?.context?.open_message_id);if(!o)return!1;let i=this.#D.get(o);if(!i)return!1;let e=t?.action?.value,a=Mke(t);return e?.action!=="repair_verify"||e?.nonce!==i.nonce||a!==i.expectedOperatorOpenId?!1:(clearTimeout(i.timeout),this.#D.delete(o),this.#E.cardActionProbesVerified+=1,this.#w(a,w(wke),"success").finally(()=>{i.resolve({verified:!0,messageId:o,operatorOpenId:a})}),!0)}#w(t,o,i){let e=this.#B;return e?Promise.resolve().then(async()=>{let a=await e.im.v1.message.create({params:{receive_id_type:"open_id"},data:{receive_id:t,msg_type:"text",content:JSON.stringify({text:o})}});if(a?.code&&a.code!==0)throw new Error("Feishu callback repair notice failed");return!0}).catch(()=>(this.#C.warn?.(`[dsh-feishu] unable to send the callback repair ${i} notice`),!1)):(this.#C.warn?.(`[dsh-feishu] unable to send the callback repair ${i} notice`),Promise.resolve(!1))}async sendConnectionTest(t){if(!this.#E.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,a,A)=>{let r=await this.#B.im.v1.message.create({params:{receive_id_type:e},data:{receive_id:a,msg_type:"text",content:JSON.stringify({text:A})}});if(r?.code&&r.code!==0)throw new Error(`Feishu connection test failed: ${r.msg||r.code}`)},i=this.#a.find(e=>e!=="*");return i?(await o("open_id",i,t),{sent:!0}):nc({state:this.#s,text:t,channelLabel:w("\u98DE\u4E66\u673A\u5668\u4EBA"),send:async(e,a)=>{let A=typeof e?.chatId=="string"?e.chatId.trim():"";if(!A)throw Cr(w("\u98DE\u4E66\u673A\u5668\u4EBA"));await o("chat_id",A,a)}})}async sendProactiveText(t,o,{signal:i}={}){if(!this.#E.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,a=t?.kind==="user"?Mn(t?.route?.openId):t?.kind==="group"?Mn(t?.route?.chatId):null;if(!e||!a){let r=new TypeError("Invalid Feishu proactive delivery target");throw r.code="invalid-target",r}i?.throwIfAborted();let A=await this.#B.im.v1.message.create({params:{receive_id_type:e},data:{receive_id:a,msg_type:"text",content:JSON.stringify({text:o})}});if(A?.code&&A.code!==0){let r=new Error(`Feishu proactive delivery failed: ${A.msg||A.code}`);throw r.code="target-rejected",r}return{sent:!0}}async#R(t,o,i){this.#E.slashCommandRegistration="registering",this.#E.slashCommandsError=null;try{let e=await F6({appId:this.#t,appSecret:this.#r,domain:this.#l,httpInstance:t,signal:i,manifest:CP});if(!o())return;this.#E.slashCommandRegistration="done",this.#E.slashCommandsRegistered=e.created.length,this.#E.slashCommandsExisting=e.existing.length,this.#E.slashCommandsFailed=e.failed.length,this.#E.slashCommandsError=e.failed.length>0?e.failed.map(a=>`/${a.command}: ${a.error?.message??String(a.error)}`).join("; "):null,e.created.length>0&&this.#C.info?.(`[dsh-feishu] registered ${e.created.length} slash command(s)`),e.failed.length>0&&this.#C.warn?.(`[dsh-feishu] ${e.failed.length} slash command(s) failed to register: ${this.#E.slashCommandsError}`)}catch(e){if(!o())return;this.#E.slashCommandRegistration="failed",this.#E.slashCommandsError=e?.message??String(e),this.#C.warn?.(`[dsh-feishu] slash command registration skipped: ${this.#E.slashCommandsError}`)}}stop(t={}){if(this.#y)return this.#y;let o;return o=this.#_(t).finally(()=>{this.#y===o&&(this.#y=null)}),this.#y=o,o}async#_({preserveError:t=!1}={}){let o=this.#m;this.#m===o&&(this.#m=null),o?.abort(new DOMException("Feishu runtime stopped","AbortError"));let i=this.#S;return i&&await i.catch(()=>{}),this.#G({preserveError:t,abortController:o})}async#G({preserveError:t=!1,abortController:o}={}){let i=t?this.#E.lastError:null;this.#m===o&&(this.#m=null),o?.abort(new DOMException("Feishu runtime stopped","AbortError"));for(let A of this.#D.values())clearTimeout(A.timeout),this.#w(A.expectedOperatorOpenId,w(Oke),"abort"),A.reject(Yd("abort","\u98DE\u4E66\u8FD0\u884C\u65F6\u5DF2\u505C\u6B62"));this.#D.clear(),this.#E.ready=!1;let e=this.#Q;this.#Q=null,e?.close({force:!0});let a=this.#f;return this.#f=null,a&&await a.waitForIdle(),this.#B=null,this.#E.feishuLongConnectionState=t?"failed":"idle",this.#E.slashCommandRegistration="idle",this.#E.lastError=i,this.status}};var uS=class extends ur{constructor(t){super({...t,rpcIdPrefix:"feishu",logPrefix:"dsh-feishu"})}};import{createHash as Rke}from"node:crypto";import{mkdir as kke,readFile as vke,rename as Pke,unlink as Gke,writeFile as Fke}from"node:fs/promises";import{dirname as Lke}from"node:path";var QS="DSH_FEISHU_APP_SECRET";function Qs(n){return typeof n=="string"&&n.trim()?n.trim():null}function L6(n){let t=Qs(n);return t&&/^[A-Za-z0-9_-]{1,128}$/.test(t)?t:null}function U6(n){return`bot_${Rke("sha256").update(n).digest("hex").slice(0,24)}`}function Uke(n){let t=Array.isArray(n.ownerOpenIds)?n.ownerOpenIds:[n.ownerOpenId];return[...new Set(t.map(Qs).filter(Boolean))]}function BS(n,{legacy:t=!1}={}){if(!n||typeof n!="object")return null;let o=Qs(n.appId),i=Uke(n);if(!o||i.length===0)return null;let e=L6(n.id)??(t?U6(o):null),a=Qs(n.secretRef)??(t?QS:null);if(!e||!a||!/^[A-Za-z_][A-Za-z0-9_]*$/.test(a))return null;let A=n.domain==="lark"?"lark":"feishu";return Object.freeze({id:e,appId:o,secretRef:a,ownerOpenIds:Object.freeze(i),domain:A,botName:Qs(n.botName),botOpenId:Qs(n.botOpenId),activated:n.activated??null,groupResponseMode:Io(n.groupResponseMode),groupMessagePermissionGranted:n.groupMessagePermissionGranted===!0,deletionPending:n.deletionPending===!0,connectedAt:Qs(n.connectedAt),createdAt:Qs(n.createdAt)??Qs(n.connectedAt)})}function Hke(n){if(!n||typeof n!="object")return null;if(n.version===2&&Array.isArray(n.bots)){let o=n.bots.map(A=>BS(A));if(o.some(A=>A===null))throw new Error("dsh-feishu config contains an invalid bot entry");let i=new Set,e=new Set,a=new Set;for(let A of o){if(i.has(A.id)||e.has(A.secretRef)||a.has(A.appId))throw new Error("dsh-feishu config contains duplicate bot identities");i.add(A.id),e.add(A.secretRef),a.add(A.appId)}return{value:Object.freeze({version:2,bots:Object.freeze(o)}),migrated:!1}}let t=BS(n,{legacy:!0});return t?{value:Object.freeze({version:2,bots:Object.freeze([t])}),migrated:!0}:null}var fS=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 vke(this.#e,"utf8")),o=Hke(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(i=>i.id===t);return o?structuredClone(o):null}async save(t){let o={...t};o.id||(o.id=U6(Qs(o.appId)??"invalid")),o.secretRef||(o.secretRef=QS);let i=BS(o);if(!i)throw new Error("Refusing to persist incomplete dsh-feishu configuration");return await this.#r([i]),this.get()}async saveBot(t){let o=BS(t);if(!o)throw new Error("Refusing to persist incomplete dsh-feishu bot configuration");return this.#l(i=>{if(i.find(r=>r.secretRef===o.secretRef&&r.id!==o.id))throw new Error("Refusing to share a credential reference between Feishu bots");if(i.find(r=>r.appId===o.appId&&r.id!==o.id))throw new Error("Refusing to persist the same Feishu app twice");let A=i.findIndex(r=>r.id===o.id);return A===-1?i.push(o):i[A]=o,structuredClone(o)})}async removeBot(t){if(!L6(t))throw new TypeError("Invalid Feishu bot id");return this.#l(o=>{let i=o.findIndex(a=>a.id===t);if(i===-1)return null;let[e]=o.splice(i,1);return structuredClone(e)})}async clear(){let t=this.#t.then(async()=>{try{await Gke(this.#e)}catch(o){if(o?.code!=="ENOENT")throw o}this.#A=Object.freeze({version:2,bots:Object.freeze([])})});this.#t=t.then(()=>{},()=>{}),await t}async#r(t){let o=Object.freeze({version:2,bots:Object.freeze([...t])}),i=this.#t.then(async()=>{await this.#o(o),this.#A=o});this.#t=i.then(()=>{},()=>{}),await i}async#l(t){let o,i=this.#t.then(async()=>{let e=[...this.#A.bots];o=t(e);let a=Object.freeze({version:2,bots:Object.freeze(e)});await this.#o(a),this.#A=a});return this.#t=i.then(()=>{},()=>{}),await i,o}async#o(t){await kke(Lke(this.#e),{recursive:!0,mode:448});let o=`${this.#e}.tmp`;await Fke(o,`${JSON.stringify(t,null,2)} -`,{encoding:"utf8",mode:384}),await Pke(o,this.#e)}};import{randomUUID as J6}from"node:crypto";var yP=new Set(["starting","qr_ready","polling","slow_down","domain_switched","saving"]),Kke=new Set(["polling","slow_down","domain_switched"]),Ki=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 H6(n){return["access_denied","expired_token","abort"].includes(n?.code)?n.code:"registration_failed"}function mP(n){let t=H6(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 xke(n){let t=Number(n);if(!Number.isFinite(t)||t<=0)throw new TypeError("registerApp onQRCodeReady returned an invalid expireIn");return t}function Yke(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 Tg=class{#e;#A;#t;#r;#l;#o=0;#i=null;#a;constructor({registerApp:t,onCredentials:o,now:i=Date.now,setTimeout:e=globalThis.setTimeout,clearTimeout:a=globalThis.clearTimeout}={}){if(typeof t!="function")throw new TypeError("RegistrationManager requires a registerApp function");if(typeof o!="function")throw new TypeError("RegistrationManager requires an onCredentials function");if(typeof i!="function"||typeof e!="function"||typeof a!="function")throw new TypeError("RegistrationManager clock dependencies must be functions");this.#e=t,this.#A=o,this.#t=i,this.#r=e,this.#l=a,this.#a=this.#s(null,Ki.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.#i=o,this.#a=this.#s(o,Ki.STARTING);let i={...t,signal:o.controller.signal,onQRCodeReady:a=>this.#c(o,a),onStatusChange:a=>this.#g(o,a)};return Promise.resolve().then(()=>this.#e(i)).then(a=>this.#I(o,a),a=>this.#d(o,a)),this.status()}status(){this.#h();let t={...this.#a};t.error&&(t.error={...t.error});let o=this.#i;return o&&o.expiresAt!==null&&yP.has(t.state)&&(t.remainingSeconds=Math.max(0,Math.ceil((o.expiresAt-this.#t())/1e3))),t}cancel(){let t=this.#i;return t?(this.#u(t,Ki.CANCELLED,{error:{code:"abort",message:"Registration was cancelled."}}),t.controller.abort(),this.status()):this.status()}#n(t){return this.#i===t}#s(t,o,i={}){let e={state:o,attempt:t?.id??this.#o,updatedAt:this.#t(),...i};return t?.qrCodeUrl&&yP.has(o)&&(e.qrCodeUrl=t.qrCodeUrl,e.expiresAt=t.expiresAt),t?.pollIntervalSeconds!==null&&yP.has(o)&&(e.pollIntervalSeconds=t.pollIntervalSeconds),e}#p(t,o,i={}){this.#n(t)&&(this.#a=this.#s(t,o,i))}#c(t,o){if(!this.#n(t))return;if(typeof o?.url!="string"||!o.url)throw new TypeError("registerApp onQRCodeReady returned an invalid URL");let i=xke(o.expireIn);t.qrCodeUrl=o.url,t.expiresAt=this.#t()+i*1e3,this.#B(t),t.expiryTimer=this.#r(()=>this.#C(t),i*1e3),t.expiryTimer?.unref?.(),this.#p(t,Ki.QR_READY)}#g(t,o){!this.#n(t)||!Kke.has(o?.status)||(o.status===Ki.SLOW_DOWN&&Number.isFinite(Number(o.interval))&&(t.pollIntervalSeconds=Number(o.interval)),this.#p(t,o.status))}async#I(t,o){if(!this.#n(t))return;let i=o?.client_id,e=o?.client_secret;if(typeof i!="string"||!i||typeof e!="string"||!e){this.#u(t,Ki.ERROR,{error:{code:"invalid_credentials",message:"Feishu registration returned invalid credentials."}});return}let a;try{a=Yke(o.user_info)}catch{this.#u(t,Ki.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.#p(t,Ki.SAVING);try{await this.#A({client_id:i,client_secret:e,user_info:a})}catch{this.#n(t)&&this.#u(t,Ki.ERROR,{error:{code:"credentials_callback_failed",message:"Unable to store the Feishu credentials."}});return}this.#n(t)&&this.#u(t,Ki.SUCCEEDED)}#d(t,o){if(!this.#n(t))return;let i=H6(o);if(i==="expired_token"){this.#u(t,Ki.EXPIRED,{error:mP(o)});return}if(i==="abort"){this.#u(t,Ki.CANCELLED,{error:mP(o)});return}this.#u(t,Ki.ERROR,{error:mP(o)})}#h(){let t=this.#i;t&&t.expiresAt!==null&&this.#t()>=t.expiresAt&&this.#C(t)}#C(t){this.#n(t)&&(this.#u(t,Ki.EXPIRED,{error:{code:"expired_token",message:"The registration QR code expired."}}),t.controller.abort())}#u(t,o,i={}){this.#n(t)&&(this.#B(t),this.#a=this.#s(t,o,i),this.#i=null)}#B(t){t.expiryTimer!==null&&(this.#l(t.expiryTimer),t.expiryTimer=null)}#f(){let t=this.#i;t&&(this.#B(t),this.#i=null,t.controller.abort())}};var jke="card.action.trigger",Jke="im:message:readonly",qke="im:resource",Nu="callback_repair";function zke(n){return n==="lark"?"accounts.larksuite.com":"accounts.feishu.cn"}function Vke(n){return n==="lark"?"open.larksuite.com":"open.feishu.cn"}function SP(n,t,o="feishu",i="Feishu app update"){let e;try{e=new URL(n)}catch{throw new Error(`${i} returned an invalid verification URL`)}let a=o==="feishu"||o==="lark",A=e.searchParams.getAll("clientID"),r=e.searchParams.getAll("tp"),s=e.searchParams.getAll("addons"),g=String(t).includes("{{")||String(t).includes("}}")||[...e.searchParams.values()].some(c=>c.includes("{{")||c.includes("}}"));if(!a||e.protocol!=="https:"||e.hostname!==Vke(o)||e.port!==""||e.username!==""||e.password!==""||r.length!==1||r[0]!=="sdk"||A.length!==1||A[0]!==t||e.searchParams.has("createOnly")||s.length!==1||!s[0]?.trim()||g)throw new Error(`${i} returned an unsafe verification URL`);return e.toString()}function Wke(n,t,o="feishu"){return SP(n,t,o,"Feishu callback repair")}var yS=class{#e;#A;#t;constructor({registerApp:t,onCredentials:o,appId:i,domain:e="feishu"}={}){if(typeof t!="function")throw new TypeError("registerApp is required");if(typeof o!="function")throw new TypeError("onCredentials is required");if(typeof i!="string"||!i.trim())throw new TypeError("appId is required");if(e!=="feishu"&&e!=="lark")throw new TypeError("domain is invalid");this.#A=i.trim(),this.#t=e,this.#e=new Tg({registerApp:a=>t({...a,onQRCodeReady:A=>{Wke(A?.url,this.#A,this.#t),a.onQRCodeReady(A)}}),onCredentials:o})}start(){return this.#e.start({source:"deepseek-harness-card-action-repair",domain:zke(this.#t),appId:this.#A,addons:{preset:!1,scopes:{tenant:[Jke,qke,...ES]},callbacks:{items:[jke]}}})}status(){return this.#e.status()}cancel(){return this.#e.cancel()}};var Zke="im:message.group_msg",SS="group_message_permission";function Xke(n){return n==="lark"?"accounts.larksuite.com":"accounts.feishu.cn"}function $ke(n,t,o="feishu"){return SP(n,t,o,"Feishu group message permission update")}var mS=class{#e;#A;#t;constructor({registerApp:t,onCredentials:o,appId:i,domain:e="feishu"}={}){if(typeof t!="function")throw new TypeError("registerApp is required");if(typeof o!="function")throw new TypeError("onCredentials is required");if(typeof i!="string"||!i.trim())throw new TypeError("appId is required");if(e!=="feishu"&&e!=="lark")throw new TypeError("domain is invalid");this.#A=i.trim(),this.#t=e,this.#e=new Tg({registerApp:a=>t({...a,onQRCodeReady:A=>{$ke(A?.url,this.#A,this.#t),a.onQRCodeReady(A)}}),onCredentials:o})}start(){return this.#e.start({source:"deepseek-harness-group-message-permission",domain:Xke(this.#t),appId:this.#A,addons:{preset:!1,scopes:{tenant:[Zke]}}})}status(){return this.#e.status()}cancel(){return this.#e.cancel()}};var K6=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",...ES]);var wP=new Set(["starting","qr_ready","polling","slow_down","domain_switched"]),wS=new Set([...wP,"saving"]),x6=new Set([Nu,SS]),Y6="*",eve=12e4,Ave=6e5;function q6(){return{ready:!1,feishuLongConnectionState:"idle",harnessReachable:!1}}function Ru(n){return n?n.status:q6()}function ku(n){return n.ready===!0&&n.feishuLongConnectionState==="connected"&&n.harnessReachable===!0}function z6(n){return n.length>12?`${n.slice(0,8)}\u2022\u2022\u2022\u2022${n.slice(-4)}`:"cli_\u2022\u2022\u2022\u2022"}function tve(n){return{name:n.botName,appIdMasked:z6(n.appId),activated:n.activated,domain:n.domain}}function rve({connected:n,error:t,connection:o}){return n?"connected":t||o.feishuLongConnectionState==="failed"?"error":"disconnected"}function ave(){return`bot_${J6().replaceAll("-","")}`}function ive(){return`reg_${J6().replaceAll("-","")}`}function j6(n){return`DSH_FEISHU_APP_SECRET_${n.slice(4).toUpperCase()}`}function DS(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:Io(n.groupResponseMode),groupMessagePermissionGranted:n.groupMessagePermissionGranted===!0,deletionPending:n.deletionPending===!0,connectedAt:n.connectedAt??null,createdAt:n.createdAt??null})}function OS(n){return typeof n=="string"&&n.trim()?n.trim():null}var vu=class{#e;#A;#t;#r;#l;#o;#i;#a;#n=new Map;#s=new Map;#p=new Map;#c=new Map;#g=new Map;#I=null;#d=Promise.resolve();#h=new Map;#C=1;#u;#B=!1;constructor({registerApp:t,verifyApp:o,credentials:i,configStore:e,createRuntime:a,deleteState:A=async()=>{},createBotId:r=ave,createRegistrationId:s=ive,callbackProbeTimeoutMs:g=eve}){if(typeof t!="function")throw new Error("registerApp is required");if(typeof o!="function")throw new Error("verifyApp is required");if(!i)throw new Error("credentials service is required");if(!e||typeof e.list!="function")throw new Error("multi-bot config store is required");if(typeof a!="function")throw new Error("createRuntime is required");if(typeof A!="function")throw new Error("deleteState must be a function");if(!Number.isFinite(g)||g<=0||g>Ave)throw new TypeError("callbackProbeTimeoutMs must be between 1 and 600000ms");this.#e=t,this.#A=o,this.#t=i,this.#r=e,this.#l=a,this.#o=A,this.#i=r,this.#a=s,this.#u=g}async initialize(){if(this.#B)return this.status();let t=this.#r.list(),o=!1;return await Promise.allSettled(t.map(i=>this.#k(i.id,async()=>{let e=Ru(this.#n.get(i.id));if(ku(e)||e.feishuLongConnectionState==="connecting"||e.feishuLongConnectionState==="reconnecting")return;if(o=!0,i.deletionPending){this.#s.set(i.id,{code:"deletion_pending",message:"\u673A\u5668\u4EBA\u6B63\u5728\u7B49\u5F85\u5B8C\u6210\u672C\u5730\u5220\u9664\uFF0C\u8BF7\u91CD\u8BD5\u79FB\u9664\u3002"});return}let a;try{a=await this.#t.resolve(i.secretRef)}catch{this.#s.set(i.id,{code:"missing_credentials",message:"\u65E0\u6CD5\u8BFB\u53D6\u673A\u5668\u4EBA\u51ED\u636E\uFF0C\u8BF7\u68C0\u67E5\u51ED\u636E\u5B58\u50A8\u3002"});return}if(!a?.value){this.#s.set(i.id,{code:"missing_credentials",message:"\u673A\u5668\u4EBA\u51ED\u636E\u7F3A\u5931\uFF0C\u8BF7\u5220\u9664\u540E\u91CD\u65B0\u626B\u7801\u63A5\u5165\u3002"});return}try{await this.#E(i,a.value),this.#s.delete(i.id)}catch{this.#s.set(i.id,{code:"connection_failed",message:"\u673A\u5668\u4EBA\u6682\u65F6\u65E0\u6CD5\u8FDE\u63A5\u98DE\u4E66\uFF0C\u8BF7\u91CD\u8BD5\u3002"})}}))),o&&this.#P(),this.status()}startRegistration(){this.#_();let t=this.#a();if(typeof t!="string"||!/^[A-Za-z0-9_-]{1,128}$/.test(t)||this.#p.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 Tg({registerApp:this.#e,onCredentials:i=>this.#G(()=>this.#D(o,i))}),this.#p.set(t,o),this.#I=t,this.#F(),o.manager.start({source:"deepseek-harness",createOnly:!0,appPreset:{name:"{user} \u7684\u5317\u6C47\u661F\u6CB3 AI \u52A9\u624B",desc:"\u8FDE\u63A5\u98DE\u4E66\u4E0E DeepSeek Harness\uFF0C\u5728\u804A\u5929\u4E2D\u4F7F\u7528\u4F01\u4E1A AI \u52A9\u624B\u3002"},addons:{preset:!1,scopes:{tenant:[...K6]},events:{items:{tenant:["im.message.receive_v1"]}},callbacks:{items:["card.action.trigger"]}}}),this.#P(),this.registrationStatus(t)}startCallbackRepair(t,{actorOpenId:o,chatId:i}={}){this.#_();let e=this.#R(t);if(e.deletionPending)throw new Error("Cannot repair a Feishu bot pending deletion");let a=this.#c.get(t),A=a?this.#p.get(a):null;if(A&&wS.has(A.manager.status().state)){if(A.operation!==Nu)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.#a();if(typeof r!="string"||!/^[A-Za-z0-9_-]{1,128}$/.test(r)||this.#p.has(r))throw new Error("Registration id generator returned an invalid or duplicate id");let s={id:r,operation:Nu,manager:null,botId:t,createdNew:!1,cancelled:!1,remoteCommitted:!1,processing:null,publicError:null,stage:"authorizing",target:structuredClone(e),targetFingerprint:DS(e),initiator:{actorOpenId:OS(o),chatId:OS(i)}};return s.manager=new yS({registerApp:this.#e,appId:e.appId,domain:e.domain,onCredentials:g=>{s.remoteCommitted=!0;let I=this.#y(s,g).finally(()=>{s.processing===I&&(s.processing=null)});return s.processing=I,I}}),this.#p.set(r,s),this.#c.set(t,r),this.#I=r,this.#F(),s.manager.start(),this.#P(),this.registrationStatus(r)}startGroupMessagePermission(t){this.#_();let o=this.#R(t);if(o.deletionPending)throw new Error("Cannot update permissions for a Feishu bot pending deletion");let i=this.#c.get(t),e=i?this.#p.get(i):null;if(e&&wS.has(e.manager.status().state)){if(e.operation!==SS)throw new Error("Another Feishu app update is already active for this bot");return this.registrationStatus(e.id)}this.#c.delete(t);let a=this.#a();if(typeof a!="string"||!/^[A-Za-z0-9_-]{1,128}$/.test(a)||this.#p.has(a))throw new Error("Registration id generator returned an invalid or duplicate id");let A={id:a,operation:SS,manager:null,botId:t,createdNew:!1,cancelled:!1,remoteCommitted:!1,processing:null,publicError:null,stage:"authorizing",target:structuredClone(o),targetFingerprint:DS(o),initiator:{actorOpenId:null,chatId:null}};return A.manager=new mS({registerApp:this.#e,appId:o.appId,domain:o.domain,onCredentials:r=>{A.remoteCommitted=!0;let g=this.#S(A,r).finally(()=>{A.processing===g&&(A.processing=null)});return A.processing=g,g}}),this.#p.set(a,A),this.#c.set(t,a),this.#I=a,this.#F(),A.manager.start(),this.#P(),this.registrationStatus(a)}hasRegistration(t){return this.#p.has(t)}registrationStatus(t){let o=this.#p.get(t);return o?this.#f({registration:o,selectedBotId:o.botId}):null}async cancelRegistration(t=this.#I){let o=this.#p.get(t);if(!o)return this.status();let i=o.manager.status().state;return x6.has(o.operation)&&i==="saving"?this.registrationStatus(t):wS.has(i)?(o.cancelled=!0,o.manager.cancel(),await this.#G(async()=>{o.createdNew&&o.botId&&this.#g.get(o.botId)===o.id&&this.#r.getBot(o.botId)&&await this.#k(o.botId,()=>this.#O(o.botId))}),this.#P(),this.registrationStatus(t)??this.status()):this.registrationStatus(t)}status(t){return this.#f({registration:this.#p.get(this.#I)??null,selectedBotId:t})}async bindCredentials({appId:t,appSecret:o,domain:i="feishu"}={}){this.#_();let e=typeof t=="string"?t.trim():"",a=typeof o=="string"?o.trim():"",A=i==="lark"?"lark":"feishu";if(!e||!a)throw new TypeError("Feishu App ID and App Secret are required");return this.#G(async()=>{this.#_();let r=await this.#A({appId:e,appSecret:a,domain:A});this.#_();let s=this.#r.list().find(f=>f.appId===e),g=s?.id??this.#i();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??j6(g),I=await this.#t.resolve(c).catch(()=>{}),d={...s,id:g,appId:e,secretRef:c,ownerOpenIds:s?.ownerOpenIds?.length?s.ownerOpenIds:[Y6],domain:A,botName:r.name,botOpenId:r.openId,activated:r.activated,deletionPending:!1,connectedAt:new Date().toISOString(),createdAt:s?.createdAt??new Date().toISOString()};await this.#t.set(c,a);let B;try{B=await this.#r.saveBot(d)}catch(f){throw await this.#w(c,I),f}return await this.#k(g,async()=>{try{await this.#E(B,a),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.#P(),this.status(g)})}async reconnectBot(t){return this.#_(),this.#k(t,async()=>{let o=this.#R(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(ku(Ru(this.#n.get(t))))return this.status(t);let i;try{i=await this.#t.resolve(o.secretRef)}catch{i=null}if(!i?.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.#P(),this.status(t);try{await this.#E(o,i.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.#P(),this.status(t)})}async sendConnectionTest(t){return this.#_(),this.#k(t,async()=>{let o=this.#R(t),i=this.#n.get(t);if(!ku(Ru(i))||typeof i.sendConnectionTest!="function"){let e=new Error("\u98DE\u4E66\u673A\u5668\u4EBA\u5C1A\u672A\u8FDE\u63A5");throw e.code="test-target-unavailable",e}return i.sendConnectionTest(Ra(`${o.botName}\uFF08${z6(o.appId)}\uFF09`,"\u98DE\u4E66\u673A\u5668\u4EBA"))})}async sendProactiveText(t,o,i,e={}){return this.#_(),this.#k(t,async()=>{this.#R(t);let a=this.#n.get(t);if(!ku(Ru(a))||typeof a.sendProactiveText!="function"){let A=new Error("\u98DE\u4E66\u673A\u5668\u4EBA\u5C1A\u672A\u8FDE\u63A5");throw A.code="bot-not-connected",A}return a.sendProactiveText(o,i,e)})}async disconnectBot(t){return this.#_(),this.#k(t,async()=>(this.#R(t),await this.#T(t),this.#s.delete(t),this.#P(),this.status(t)))}async updateGroupResponseMode(t,o){if(this.#_(),!nS(o))throw new TypeError("Invalid Feishu group response mode");return this.#G(()=>this.#k(t,async()=>{let i=this.#R(t);if(o==="all"&&i.groupMessagePermissionGranted!==!0){let a=new Error("Authorize im:message.group_msg before enabling all group messages");throw a.code="group_message_permission_required",a}let e=await this.#r.saveBot({...i,groupResponseMode:o});return this.#n.get(t)?.setGroupResponseMode?.(e.groupResponseMode),this.#P(),this.status(t)}))}async deleteBot(t){return this.#_(),this.#G(()=>this.#k(t,async()=>(this.#R(t),await this.#O(t),this.#P(),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.#p.values()){let i=o.manager.status().state;x6.has(o.operation)&&i==="saving"?(o.manager.cancel(),o.processing&&t.push(o.processing)):wS.has(i)&&(o.cancelled=!0,o.manager.cancel())}await this.#d,await Promise.allSettled([...this.#h.values()]),await Promise.allSettled([...this.#n.keys()].map(o=>this.#T(o))),await Promise.allSettled(t),await this.#d,await Promise.allSettled([...this.#h.values()]),await Promise.allSettled([...this.#n.keys()].map(o=>this.#T(o)))}#f({registration:t,selectedBotId:o}={}){let i=this.#r.list().map(I=>{let d=Ru(this.#n.get(I.id)),B=ku(d),f=this.#s.get(I.id)??null;return{botId:I.id,phase:rve({connected:B,error:f,connection:d}),connected:B,configured:!0,groupResponseMode:Io(I.groupResponseMode),groupMessagePermissionGranted:I.groupMessagePermissionGranted===!0,bot:tve(I),connection:d,lastMessageError:Xr(d.lastMessageError),error:f}}),e=t?this.#Q(t):{state:"idle",attempt:0,updatedAt:Date.now()},a=wP.has(e.state),A=e.state==="saving",r=!!t&&(a||A),s=i.find(I=>I.botId===o)??(r?null:i[0]??null),g=i.some(I=>I.connected),c=s?.phase??"unconfigured";return a?c="registering":A?c="connecting":e.state==="error"&&!s&&(c="error"),{schemaVersion:2,revision:this.#C,phase:c,connected:s?.connected??!1,configured:i.length>0,bot:s?.bot??null,connection:s?.connection??q6(),error:s?.error??e.error??null,registration:e,bots:i,totals:{configured:i.length,connected:i.filter(I=>I.connected).length},anyConnected:g}}#Q(t){let o=t.manager.status();return{...o,attempt:t.id,...t.botId?{botId:t.botId}:{},...t.operation?{operation:t.operation}:{},...t.stage?{stage:t.stage}:{},...o.state==="error"&&t.publicError?{error:{...t.publicError}}:{}}}async#S(t,o){let i=o.client_id,e=o.client_secret,a=OS(o.user_info?.open_id),A=o.user_info?.tenant_brand,r=t.target;if(t.cancelled)throw this.#m(t,"abort","Group message permission update was cancelled before local activation.");if(i!==r.appId)throw this.#m(t,"repair_app_mismatch","Feishu returned credentials for a different app.");if(!a)throw this.#m(t,"repair_owner_missing","Feishu returned no permission operator identity.");if(A!==void 0&&A!==r.domain)throw this.#m(t,"repair_domain_mismatch","Feishu returned credentials for a different account domain.");if(!r.ownerOpenIds.includes(Y6)&&!r.ownerOpenIds.includes(a))throw this.#m(t,"repair_owner_mismatch","The Feishu permission operator is not an owner of this configured bot.");t.stage="verifying_identity";let s;try{s=await this.#A({appId:i,appSecret:e,domain:r.domain})}catch(g){throw this.#m(t,"repair_credentials_invalid","Feishu could not verify the updated app credentials.",g)}if(r.botOpenId&&s?.openId!==r.botOpenId)throw this.#m(t,"repair_bot_mismatch","The updated Feishu app belongs to a different bot identity.");await this.#G(()=>this.#k(t.botId,async()=>{let g=this.#r.getBot(t.botId);if(!g||g.deletionPending||DS(g)!==t.targetFingerprint)throw this.#m(t,"repair_target_changed","The Feishu bot changed while its permission update was in progress.");let c;try{c=await this.#t.resolve(g.secretRef)}catch(d){throw this.#m(t,"credential_update_failed","Unable to read the current Feishu credential.",d)}if(c?.value!==e){t.stage="persisting_secret";try{await this.#t.set(g.secretRef,e)}catch(B){if((await this.#t.resolve(g.secretRef).catch(()=>null))?.value!==e)throw this.#m(t,"credential_update_failed","Unable to store the updated Feishu credential.",B)}if((await this.#t.resolve(g.secretRef).catch(()=>null))?.value!==e)throw this.#m(t,"credential_state_unknown","The updated Feishu credential could not be confirmed after writing.")}t.stage="enabling_all_messages";let I;try{I=await this.#r.saveBot({...g,groupMessagePermissionGranted:!0,groupResponseMode:"all"})}catch(d){throw this.#m(t,"group_message_permission_save_failed","The permission was accepted, but all-message mode could not be saved.",d)}t.stage="restarting";try{await this.#E(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.#P(),this.#m(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.#P()}))}async#y(t,o){let i=o.client_id,e=o.client_secret,a=OS(o.user_info?.open_id),A=o.user_info?.tenant_brand,r=t.target;if(t.cancelled)throw this.#m(t,"abort","Callback repair was cancelled before local activation.");if(i!==r.appId)throw this.#m(t,"repair_app_mismatch","Feishu returned credentials for a different app.");if(!a)throw this.#m(t,"repair_owner_missing","Feishu returned no repair operator identity.");if(A!==void 0&&A!==r.domain)throw this.#m(t,"repair_domain_mismatch","Feishu returned credentials for a different account domain.");t.stage="verifying_identity";let s;try{s=await this.#A({appId:i,appSecret:e,domain:r.domain})}catch(c){throw this.#m(t,"repair_credentials_invalid","Feishu could not verify the repaired app credentials.",c)}if(r.botOpenId&&s?.openId!==r.botOpenId)throw this.#m(t,"repair_bot_mismatch","The repaired Feishu app belongs to a different bot identity.");let g=await this.#G(()=>this.#k(t.botId,async()=>{let c=this.#r.getBot(t.botId);if(!c||c.deletionPending||DS(c)!==t.targetFingerprint)throw this.#m(t,"repair_target_changed","The Feishu bot changed while its callback repair was in progress.");let I;try{I=await this.#t.resolve(c.secretRef)}catch(f){throw this.#m(t,"credential_update_failed","Unable to read the current Feishu credential.",f)}if(I?.value!==e){t.stage="persisting_secret";try{await this.#t.set(c.secretRef,e)}catch(Q){if((await this.#t.resolve(c.secretRef).catch(()=>null))?.value!==e)throw this.#m(t,"credential_update_failed","Unable to store the repaired Feishu credential.",Q)}if((await this.#t.resolve(c.secretRef).catch(()=>null))?.value!==e)throw this.#m(t,"credential_state_unknown","The repaired Feishu credential could not be confirmed after writing.")}let B;t.stage="restarting";try{await this.#E(c,e),B=this.#n.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.#P(),this.#m(t,"repair_connection_failed","The repaired Feishu runtime could not be started.",f)}if(!B)throw this.#m(t,"repair_connection_failed","The repaired Feishu runtime is unavailable.");return this.#s.delete(t.botId),this.#P(),B}));if(typeof g.beginCardActionProbe!="function")throw this.#m(t,"card_action_probe_unavailable","The Feishu runtime cannot verify card callbacks.");t.stage="awaiting_callback";try{if((await g.beginCardActionProbe({expectedOperatorOpenId:t.initiator.actorOpenId??a,timeoutMs:this.#u,...t.initiator.chatId?{chatId:t.initiator.chatId}:{}}))?.verified!==!0){let I=new Error("Feishu runtime returned no callback proof");throw I.code="card_action_probe_failed",I}}catch(c){let I=c?.code==="card_action_probe_timeout"?"card_action_probe_timeout":c?.code==="card_action_probe_unavailable"?"card_action_probe_unavailable":c?.code==="card_action_probe_send_failed"?"card_action_probe_send_failed":"card_action_probe_failed";throw this.#m(t,I,I==="card_action_probe_timeout"?"Timed out waiting for the Feishu callback verification button.":"The Feishu card callback probe failed.",c)}t.stage="verified",t.publicError=null,this.#P()}#m(t,o,i,e){t.publicError={code:o,message:i};let a=new Error(i,e?{cause:e}:void 0);return a.code=o,a}async#D(t,o){if(t.cancelled)throw new Error("Registration was cancelled");let i=o.client_id,e=o.client_secret,a=o.user_info?.open_id,A=o.user_info?.tenant_brand==="lark"?"lark":"feishu";if(!a)throw new Error("Feishu registration returned no owner open_id");let r=await this.#A({appId:i,appSecret:e,domain:A});if(t.cancelled)throw new Error("Registration was cancelled");let s=this.#r.list().find(Q=>Q.appId===i),g=s?.id??this.#i();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??j6(g),I=this.#g.get(g),d=await this.#t.resolve(c).catch(()=>{});await this.#t.set(c,e);let B;try{B=await this.#r.saveBot({...s,id:g,appId:i,secretRef:c,ownerOpenIds:[...new Set([...s?.ownerOpenIds??[],a])],domain:A,botName:r.name,botOpenId:r.openId,activated:r.activated,deletionPending:!1,connectedAt:new Date().toISOString(),createdAt:s?.createdAt??new Date().toISOString()}),t.botId=g,t.createdNew=!s,this.#g.set(g,t.id)}catch(Q){try{await this.#w(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.#k(g,()=>this.#O(g)):(await this.#r.saveBot(s),await this.#w(c,d),I?this.#g.set(g,I):this.#g.delete(g)),new Error("Registration was cancelled");let f=!1;try{if(await this.#k(g,()=>this.#E(B,e)),t.cancelled)throw t.createdNew?await this.#k(g,()=>this.#O(g)):(await this.#r.saveBot(s),await this.#w(c,d),I?this.#g.set(g,I):this.#g.delete(g),d?.value&&!s.deletionPending?await this.#k(g,()=>this.#E(s,d.value)):await this.#k(g,()=>this.#T(g))),f=!0,new Error("Registration was cancelled");this.#s.delete(g),this.#P()}catch(Q){if(t.cancelled)throw!f&&t.createdNew&&this.#r.getBot(g)?await this.#k(g,()=>this.#O(g)):!f&&s&&(await this.#r.saveBot(s),await this.#w(c,d),I?this.#g.set(g,I):this.#g.delete(g),!this.#B&&d?.value&&!s.deletionPending?await this.#k(g,()=>this.#E(s,d.value)):await this.#k(g,()=>this.#T(g))),this.#P(),Q;if(s&&d?.value)try{throw await this.#r.saveBot(s),await this.#w(c,d),I?this.#g.set(g,I):this.#g.delete(g),s.deletionPending?(await this.#k(g,()=>this.#T(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.#k(g,()=>this.#E(s,d.value)),this.#s.delete(g)),this.#P(),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.#P(),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.#P(),Q}}async#E(t,o){await this.#T(t.id);let i=await this.#l({botId:t.id,config:t,appSecret:o,repair:this.#N(t.id)});this.#n.set(t.id,i);try{await i.start()}catch(e){throw this.#n.get(t.id)===i&&this.#n.delete(t.id),await i.stop({preserveError:!0}).catch(()=>{}),e}}#N(t){let o=i=>{let e=this.#p.get(i);return e?.operation===Nu&&e.botId===t?e:null};return Object.freeze({start:({actorOpenId:i,chatId:e}={})=>this.startCallbackRepair(t,{actorOpenId:i,chatId:e}),status:({attemptId:i}={})=>o(i)?this.registrationStatus(i):null,cancel:async({attemptId:i}={})=>o(i)?this.cancelRegistration(i):this.status(t)})}async#T(t){let o=this.#n.get(t);this.#n.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.#T(t);try{await this.#t.unset(o.secretRef)}catch(i){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:i})}try{await this.#o({botId:t,config:o})}catch(i){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:i})}await this.#r.removeBot(t),this.#s.delete(t),this.#g.delete(t)}}async#w(t,o){o?.value?await this.#t.set(t,o.value):await this.#t.unset(t)}#R(t){let o=this.#r.getBot(t);if(!o)throw new Error("Unknown Feishu bot");return o}#_(){if(this.#B)throw new Error("The Feishu controller is closed")}#G(t){let o=this.#d.then(t,t);return this.#d=o.then(()=>{},()=>{}),o}#k(t,o){let e=(this.#h.get(t)??Promise.resolve()).then(o,o),a=e.then(()=>{},()=>{});return this.#h.set(t,a),a.finally(()=>{this.#h.get(t)===a&&this.#h.delete(t)}),e}#F(){if(!(this.#p.size<=32))for(let[t,o]of this.#p){if(t===this.#I)continue;let i=o.manager.status().state;if(!wP.has(i)&&i!=="saving"&&this.#p.delete(t),this.#p.size<=32)break}}#P(){this.#C+=1}};var sve=["open.feishu.cn","open.larksuite.com"];function gve(n,t){if(t==="*")return!0;let o=t.startsWith(".")?t.slice(1):t;return o?n===o||n.endsWith(`.${o}`):!1}function cve(n){for(let t of["no_proxy","NO_PROXY"]){let o=n?.[t];if(typeof o!="string"||!o.trim())continue;let i=o.split(",").map(e=>e.trim().toLowerCase()).filter(Boolean);if(sve.some(e=>i.some(a=>gve(e,a))))return!0}return!1}function Ive(n){if(!cve(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 lve(n,t=o=>new V6.default(o)){let o=Ive(n);return o?t(o):void 0}function pve(n){let t=kc(n.dshHome??process.env.DSH_HOME??jd(ove(),".dsh")),o=kc(n.dataDir??jd(t,"integrations","dsh-feishu"));return{root:o,config:kc(n.configPath??jd(o,"config.json")),legacyState:kc(n.statePath??jd(o,"state.json")),bots:kc(n.botsDir??jd(o,"bots")),workspaces:kc(n.workspacesPath??jd(o,"workspaces.json"))}}async function DP(n,t={},o={}){if(!n?.credentials)throw new TypeError("dsh-feishu requires ctx.credentials");let i=aa(n,t),e=o.lark??rP,a=o.Controller??vu,A=o.ConfigStore??fS,r=o.StateStore??iS,s=o.HarnessClient??uS,g=o.FeishuRuntime??CS,c=o.verifyFeishuApp??t6,I=fe=>c({...fe,httpInstance:e.defaultHttpInstance}),d=o.createConnectionSupervisor??aP,B=typeof n.logger=="function"?n.logger("dsh-feishu"):n.logger??console,f=()=>La(n),Q=pve(t),y=await new A(Q.config).load(),m=kc(t.workspace??process.cwd()),T=o.WorkspaceStore??ra,_=o.workspaces??await new T(Q.workspaces,{defaultWorkspace:m}).load(),R=typeof y.list=="function",K=()=>R?y.list():[],L=K();R&&await _.reconcile(L.map(fe=>fe.id)),await Promise.all(L.map(fe=>_.ensure(fe.id,{defaultAgentPreset:t.agentPreset,initialAccessPolicy:nr("feishu",fe)})));let F=typeof y.removeBot=="function"?Ha(y,{workspaces:_,method:"removeBot",botIdFromRemoved:fe=>fe.id,saveMethod:"saveBot",botIdFromSave:fe=>fe?.id}):y,q=new Map,V=fe=>!fe.id||!fe.secretRef||fe.secretRef===QS?Q.legacyState:kc(Q.bots,fe.id,"state.json"),x=async fe=>{let ke=fe.id??"__legacy__",Re=q.get(ke);return Re||(Re=await new r(V(fe)).load(),q.set(ke,Re)),Re},G=async fe=>{let ke=K().find(Re=>Re.id===fe);if(!ke)throw new Error("Unknown Feishu bot");return x(ke)},J=ja(n,o.commandExecutor),{controlExecutor:U,sessionMaintenanceExecutor:N,fileIngressExecutor:k}=Ja(n,{controlExecutor:o.controlExecutor,sessionMaintenanceExecutor:o.sessionMaintenanceExecutor,fileIngressExecutor:o.fileIngressExecutor}),z=new s({...i,workspace:m,autostart:!1,dshBin:t.dshBin??"dsh",...J?{commandExecutor:J}:{},...U?{controlExecutor:U}:{},...N?{sessionMaintenanceExecutor:N}:{},...k?{fileIngressExecutor:k}:{}}),Ae=o.proxyEnv??process.env,ie=lve(Ae,o.createProxyAgent),we=new a({registerApp:fe=>e.registerApp(fe),verifyApp:I,credentials:n.credentials,configStore:F,createRuntime:async({botId:fe,config:ke,appSecret:Re,repair:We})=>{let ve=await x(ke),aA=fe??ke.id??ke.appId;await _.ensure(aA,{defaultAgentPreset:t.agentPreset,initialAccessPolicy:nr("feishu",ke)});let Be=Ka(z,{botId:aA,workspaces:_,state:ve,agentPresetCatalog:f});return new g({lark:e,botId:aA,repair:We,appId:ke.appId,appSecret:Re,domain:ke.domain,botOpenId:ke.botOpenId,groupResponseMode:ke.groupResponseMode,ownerOpenIds:ke.ownerOpenIds??[ke.ownerOpenId],harness:Be.harness,state:Be.state,contextEnhancement:{botId:aA,getSettings:()=>_.contextEnhancementFor(aA)},accessPolicy:qa(_,aA,{channel:"feishu",config:ke}),replyTimeoutMs:t.replyTimeoutMs??6e5,slashCommands:t.slashCommands!==!1,...ie?{wsAgent:ie}:{},logger:{error:(...Ie)=>B.error?.(`[${fe??ke.id}]`,...Ie),warn:(...Ie)=>B.warn?.(`[${fe??ke.id}]`,...Ie),info:(...Ie)=>B.info?.(`[${fe??ke.id}]`,...Ie),debug:(...Ie)=>B.debug?.(`[${fe??ke.id}]`,...Ie)}})},deleteState:async({botId:fe,config:ke})=>{q.delete(fe);try{await nve(V(ke))}catch(Re){if(Re?.code!=="ENOENT")throw Re}}}),se=xa(we,{workspaces:_,stateFor:G,agentPresetCatalog:f}),Te=d({controller:se,harness:z,logger:B,retryDelaysMs:t.retryDelaysMs,healthyIntervalMs:t.healthyIntervalMs}).start();return{controller:se,deliveryAdapter:Ya({channel:"feishu",workspaces:_,coreController:we,stateFor:G}),ready:Te.ready,async close(){await Te.close(),await se.close(),z.stopManagedProcess(),ie?.destroy?.()}}}import Nve from"qrcode";var qd=qe(RP(),1);var Mve=qe(RP(),1);var _ve=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",\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.",\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 Pke(o,this.#e)}};import{randomUUID as J6}from"node:crypto";var yP=new Set(["starting","qr_ready","polling","slow_down","domain_switched","saving"]),Kke=new Set(["polling","slow_down","domain_switched"]),Ki=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 H6(n){return["access_denied","expired_token","abort"].includes(n?.code)?n.code:"registration_failed"}function mP(n){let t=H6(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 xke(n){let t=Number(n);if(!Number.isFinite(t)||t<=0)throw new TypeError("registerApp onQRCodeReady returned an invalid expireIn");return t}function Yke(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 Tg=class{#e;#A;#t;#r;#l;#o=0;#i=null;#a;constructor({registerApp:t,onCredentials:o,now:i=Date.now,setTimeout:e=globalThis.setTimeout,clearTimeout:a=globalThis.clearTimeout}={}){if(typeof t!="function")throw new TypeError("RegistrationManager requires a registerApp function");if(typeof o!="function")throw new TypeError("RegistrationManager requires an onCredentials function");if(typeof i!="function"||typeof e!="function"||typeof a!="function")throw new TypeError("RegistrationManager clock dependencies must be functions");this.#e=t,this.#A=o,this.#t=i,this.#r=e,this.#l=a,this.#a=this.#s(null,Ki.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.#i=o,this.#a=this.#s(o,Ki.STARTING);let i={...t,signal:o.controller.signal,onQRCodeReady:a=>this.#c(o,a),onStatusChange:a=>this.#g(o,a)};return Promise.resolve().then(()=>this.#e(i)).then(a=>this.#I(o,a),a=>this.#d(o,a)),this.status()}status(){this.#h();let t={...this.#a};t.error&&(t.error={...t.error});let o=this.#i;return o&&o.expiresAt!==null&&yP.has(t.state)&&(t.remainingSeconds=Math.max(0,Math.ceil((o.expiresAt-this.#t())/1e3))),t}cancel(){let t=this.#i;return t?(this.#u(t,Ki.CANCELLED,{error:{code:"abort",message:"Registration was cancelled."}}),t.controller.abort(),this.status()):this.status()}#n(t){return this.#i===t}#s(t,o,i={}){let e={state:o,attempt:t?.id??this.#o,updatedAt:this.#t(),...i};return t?.qrCodeUrl&&yP.has(o)&&(e.qrCodeUrl=t.qrCodeUrl,e.expiresAt=t.expiresAt),t?.pollIntervalSeconds!==null&&yP.has(o)&&(e.pollIntervalSeconds=t.pollIntervalSeconds),e}#p(t,o,i={}){this.#n(t)&&(this.#a=this.#s(t,o,i))}#c(t,o){if(!this.#n(t))return;if(typeof o?.url!="string"||!o.url)throw new TypeError("registerApp onQRCodeReady returned an invalid URL");let i=xke(o.expireIn);t.qrCodeUrl=o.url,t.expiresAt=this.#t()+i*1e3,this.#B(t),t.expiryTimer=this.#r(()=>this.#C(t),i*1e3),t.expiryTimer?.unref?.(),this.#p(t,Ki.QR_READY)}#g(t,o){!this.#n(t)||!Kke.has(o?.status)||(o.status===Ki.SLOW_DOWN&&Number.isFinite(Number(o.interval))&&(t.pollIntervalSeconds=Number(o.interval)),this.#p(t,o.status))}async#I(t,o){if(!this.#n(t))return;let i=o?.client_id,e=o?.client_secret;if(typeof i!="string"||!i||typeof e!="string"||!e){this.#u(t,Ki.ERROR,{error:{code:"invalid_credentials",message:"Feishu registration returned invalid credentials."}});return}let a;try{a=Yke(o.user_info)}catch{this.#u(t,Ki.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.#p(t,Ki.SAVING);try{await this.#A({client_id:i,client_secret:e,user_info:a})}catch{this.#n(t)&&this.#u(t,Ki.ERROR,{error:{code:"credentials_callback_failed",message:"Unable to store the Feishu credentials."}});return}this.#n(t)&&this.#u(t,Ki.SUCCEEDED)}#d(t,o){if(!this.#n(t))return;let i=H6(o);if(i==="expired_token"){this.#u(t,Ki.EXPIRED,{error:mP(o)});return}if(i==="abort"){this.#u(t,Ki.CANCELLED,{error:mP(o)});return}this.#u(t,Ki.ERROR,{error:mP(o)})}#h(){let t=this.#i;t&&t.expiresAt!==null&&this.#t()>=t.expiresAt&&this.#C(t)}#C(t){this.#n(t)&&(this.#u(t,Ki.EXPIRED,{error:{code:"expired_token",message:"The registration QR code expired."}}),t.controller.abort())}#u(t,o,i={}){this.#n(t)&&(this.#B(t),this.#a=this.#s(t,o,i),this.#i=null)}#B(t){t.expiryTimer!==null&&(this.#l(t.expiryTimer),t.expiryTimer=null)}#f(){let t=this.#i;t&&(this.#B(t),this.#i=null,t.controller.abort())}};var jke="card.action.trigger",Jke="im:message:readonly",qke="im:resource",Nu="callback_repair";function zke(n){return n==="lark"?"accounts.larksuite.com":"accounts.feishu.cn"}function Vke(n){return n==="lark"?"open.larksuite.com":"open.feishu.cn"}function SP(n,t,o="feishu",i="Feishu app update"){let e;try{e=new URL(n)}catch{throw new Error(`${i} returned an invalid verification URL`)}let a=o==="feishu"||o==="lark",A=e.searchParams.getAll("clientID"),r=e.searchParams.getAll("tp"),s=e.searchParams.getAll("addons"),g=String(t).includes("{{")||String(t).includes("}}")||[...e.searchParams.values()].some(c=>c.includes("{{")||c.includes("}}"));if(!a||e.protocol!=="https:"||e.hostname!==Vke(o)||e.port!==""||e.username!==""||e.password!==""||r.length!==1||r[0]!=="sdk"||A.length!==1||A[0]!==t||e.searchParams.has("createOnly")||s.length!==1||!s[0]?.trim()||g)throw new Error(`${i} returned an unsafe verification URL`);return e.toString()}function Wke(n,t,o="feishu"){return SP(n,t,o,"Feishu callback repair")}var yS=class{#e;#A;#t;constructor({registerApp:t,onCredentials:o,appId:i,domain:e="feishu"}={}){if(typeof t!="function")throw new TypeError("registerApp is required");if(typeof o!="function")throw new TypeError("onCredentials is required");if(typeof i!="string"||!i.trim())throw new TypeError("appId is required");if(e!=="feishu"&&e!=="lark")throw new TypeError("domain is invalid");this.#A=i.trim(),this.#t=e,this.#e=new Tg({registerApp:a=>t({...a,onQRCodeReady:A=>{Wke(A?.url,this.#A,this.#t),a.onQRCodeReady(A)}}),onCredentials:o})}start(){return this.#e.start({source:"deepseek-harness-card-action-repair",domain:zke(this.#t),appId:this.#A,addons:{preset:!1,scopes:{tenant:[Jke,qke,...ES]},callbacks:{items:[jke]}}})}status(){return this.#e.status()}cancel(){return this.#e.cancel()}};var Zke="im:message.group_msg",SS="group_message_permission";function Xke(n){return n==="lark"?"accounts.larksuite.com":"accounts.feishu.cn"}function $ke(n,t,o="feishu"){return SP(n,t,o,"Feishu group message permission update")}var mS=class{#e;#A;#t;constructor({registerApp:t,onCredentials:o,appId:i,domain:e="feishu"}={}){if(typeof t!="function")throw new TypeError("registerApp is required");if(typeof o!="function")throw new TypeError("onCredentials is required");if(typeof i!="string"||!i.trim())throw new TypeError("appId is required");if(e!=="feishu"&&e!=="lark")throw new TypeError("domain is invalid");this.#A=i.trim(),this.#t=e,this.#e=new Tg({registerApp:a=>t({...a,onQRCodeReady:A=>{$ke(A?.url,this.#A,this.#t),a.onQRCodeReady(A)}}),onCredentials:o})}start(){return this.#e.start({source:"deepseek-harness-group-message-permission",domain:Xke(this.#t),appId:this.#A,addons:{preset:!1,scopes:{tenant:[Zke]}}})}status(){return this.#e.status()}cancel(){return this.#e.cancel()}};var K6=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",...ES]);var wP=new Set(["starting","qr_ready","polling","slow_down","domain_switched"]),wS=new Set([...wP,"saving"]),x6=new Set([Nu,SS]),Y6="*",eve=12e4,Ave=6e5;function q6(){return{ready:!1,feishuLongConnectionState:"idle",harnessReachable:!1}}function Ru(n){return n?n.status:q6()}function ku(n){return n.ready===!0&&n.feishuLongConnectionState==="connected"&&n.harnessReachable===!0}function z6(n){return n.length>12?`${n.slice(0,8)}\u2022\u2022\u2022\u2022${n.slice(-4)}`:"cli_\u2022\u2022\u2022\u2022"}function tve(n){return{name:n.botName,appIdMasked:z6(n.appId),activated:n.activated,domain:n.domain}}function rve({connected:n,error:t,connection:o}){return n?"connected":t||o.feishuLongConnectionState==="failed"?"error":"disconnected"}function ave(){return`bot_${J6().replaceAll("-","")}`}function ive(){return`reg_${J6().replaceAll("-","")}`}function j6(n){return`DSH_FEISHU_APP_SECRET_${n.slice(4).toUpperCase()}`}function DS(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:Io(n.groupResponseMode),groupMessagePermissionGranted:n.groupMessagePermissionGranted===!0,deletionPending:n.deletionPending===!0,connectedAt:n.connectedAt??null,createdAt:n.createdAt??null})}function OS(n){return typeof n=="string"&&n.trim()?n.trim():null}var vu=class{#e;#A;#t;#r;#l;#o;#i;#a;#n=new Map;#s=new Map;#p=new Map;#c=new Map;#g=new Map;#I=null;#d=Promise.resolve();#h=new Map;#C=1;#u;#B=!1;constructor({registerApp:t,verifyApp:o,credentials:i,configStore:e,createRuntime:a,deleteState:A=async()=>{},createBotId:r=ave,createRegistrationId:s=ive,callbackProbeTimeoutMs:g=eve}){if(typeof t!="function")throw new Error("registerApp is required");if(typeof o!="function")throw new Error("verifyApp is required");if(!i)throw new Error("credentials service is required");if(!e||typeof e.list!="function")throw new Error("multi-bot config store is required");if(typeof a!="function")throw new Error("createRuntime is required");if(typeof A!="function")throw new Error("deleteState must be a function");if(!Number.isFinite(g)||g<=0||g>Ave)throw new TypeError("callbackProbeTimeoutMs must be between 1 and 600000ms");this.#e=t,this.#A=o,this.#t=i,this.#r=e,this.#l=a,this.#o=A,this.#i=r,this.#a=s,this.#u=g}async initialize(){if(this.#B)return this.status();let t=this.#r.list(),o=!1;return await Promise.allSettled(t.map(i=>this.#k(i.id,async()=>{let e=Ru(this.#n.get(i.id));if(ku(e)||e.feishuLongConnectionState==="connecting"||e.feishuLongConnectionState==="reconnecting")return;if(o=!0,i.deletionPending){this.#s.set(i.id,{code:"deletion_pending",message:"\u673A\u5668\u4EBA\u6B63\u5728\u7B49\u5F85\u5B8C\u6210\u672C\u5730\u5220\u9664\uFF0C\u8BF7\u91CD\u8BD5\u79FB\u9664\u3002"});return}let a;try{a=await this.#t.resolve(i.secretRef)}catch{this.#s.set(i.id,{code:"missing_credentials",message:"\u65E0\u6CD5\u8BFB\u53D6\u673A\u5668\u4EBA\u51ED\u636E\uFF0C\u8BF7\u68C0\u67E5\u51ED\u636E\u5B58\u50A8\u3002"});return}if(!a?.value){this.#s.set(i.id,{code:"missing_credentials",message:"\u673A\u5668\u4EBA\u51ED\u636E\u7F3A\u5931\uFF0C\u8BF7\u5220\u9664\u540E\u91CD\u65B0\u626B\u7801\u63A5\u5165\u3002"});return}try{await this.#E(i,a.value),this.#s.delete(i.id)}catch{this.#s.set(i.id,{code:"connection_failed",message:"\u673A\u5668\u4EBA\u6682\u65F6\u65E0\u6CD5\u8FDE\u63A5\u98DE\u4E66\uFF0C\u8BF7\u91CD\u8BD5\u3002"})}}))),o&&this.#P(),this.status()}startRegistration(){this.#_();let t=this.#a();if(typeof t!="string"||!/^[A-Za-z0-9_-]{1,128}$/.test(t)||this.#p.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 Tg({registerApp:this.#e,onCredentials:i=>this.#G(()=>this.#D(o,i))}),this.#p.set(t,o),this.#I=t,this.#F(),o.manager.start({source:"deepseek-harness",createOnly:!0,appPreset:{name:"{user} \u7684\u5317\u6C47\u661F\u6CB3 AI \u52A9\u624B",desc:"\u8FDE\u63A5\u98DE\u4E66\u4E0E DeepSeek Harness\uFF0C\u5728\u804A\u5929\u4E2D\u4F7F\u7528\u4F01\u4E1A AI \u52A9\u624B\u3002"},addons:{preset:!1,scopes:{tenant:[...K6]},events:{items:{tenant:["im.message.receive_v1"]}},callbacks:{items:["card.action.trigger"]}}}),this.#P(),this.registrationStatus(t)}startCallbackRepair(t,{actorOpenId:o,chatId:i}={}){this.#_();let e=this.#R(t);if(e.deletionPending)throw new Error("Cannot repair a Feishu bot pending deletion");let a=this.#c.get(t),A=a?this.#p.get(a):null;if(A&&wS.has(A.manager.status().state)){if(A.operation!==Nu)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.#a();if(typeof r!="string"||!/^[A-Za-z0-9_-]{1,128}$/.test(r)||this.#p.has(r))throw new Error("Registration id generator returned an invalid or duplicate id");let s={id:r,operation:Nu,manager:null,botId:t,createdNew:!1,cancelled:!1,remoteCommitted:!1,processing:null,publicError:null,stage:"authorizing",target:structuredClone(e),targetFingerprint:DS(e),initiator:{actorOpenId:OS(o),chatId:OS(i)}};return s.manager=new yS({registerApp:this.#e,appId:e.appId,domain:e.domain,onCredentials:g=>{s.remoteCommitted=!0;let I=this.#y(s,g).finally(()=>{s.processing===I&&(s.processing=null)});return s.processing=I,I}}),this.#p.set(r,s),this.#c.set(t,r),this.#I=r,this.#F(),s.manager.start(),this.#P(),this.registrationStatus(r)}startGroupMessagePermission(t){this.#_();let o=this.#R(t);if(o.deletionPending)throw new Error("Cannot update permissions for a Feishu bot pending deletion");let i=this.#c.get(t),e=i?this.#p.get(i):null;if(e&&wS.has(e.manager.status().state)){if(e.operation!==SS)throw new Error("Another Feishu app update is already active for this bot");return this.registrationStatus(e.id)}this.#c.delete(t);let a=this.#a();if(typeof a!="string"||!/^[A-Za-z0-9_-]{1,128}$/.test(a)||this.#p.has(a))throw new Error("Registration id generator returned an invalid or duplicate id");let A={id:a,operation:SS,manager:null,botId:t,createdNew:!1,cancelled:!1,remoteCommitted:!1,processing:null,publicError:null,stage:"authorizing",target:structuredClone(o),targetFingerprint:DS(o),initiator:{actorOpenId:null,chatId:null}};return A.manager=new mS({registerApp:this.#e,appId:o.appId,domain:o.domain,onCredentials:r=>{A.remoteCommitted=!0;let g=this.#S(A,r).finally(()=>{A.processing===g&&(A.processing=null)});return A.processing=g,g}}),this.#p.set(a,A),this.#c.set(t,a),this.#I=a,this.#F(),A.manager.start(),this.#P(),this.registrationStatus(a)}hasRegistration(t){return this.#p.has(t)}registrationStatus(t){let o=this.#p.get(t);return o?this.#f({registration:o,selectedBotId:o.botId}):null}async cancelRegistration(t=this.#I){let o=this.#p.get(t);if(!o)return this.status();let i=o.manager.status().state;return x6.has(o.operation)&&i==="saving"?this.registrationStatus(t):wS.has(i)?(o.cancelled=!0,o.manager.cancel(),await this.#G(async()=>{o.createdNew&&o.botId&&this.#g.get(o.botId)===o.id&&this.#r.getBot(o.botId)&&await this.#k(o.botId,()=>this.#O(o.botId))}),this.#P(),this.registrationStatus(t)??this.status()):this.registrationStatus(t)}status(t){return this.#f({registration:this.#p.get(this.#I)??null,selectedBotId:t})}async bindCredentials({appId:t,appSecret:o,domain:i="feishu"}={}){this.#_();let e=typeof t=="string"?t.trim():"",a=typeof o=="string"?o.trim():"",A=i==="lark"?"lark":"feishu";if(!e||!a)throw new TypeError("Feishu App ID and App Secret are required");return this.#G(async()=>{this.#_();let r=await this.#A({appId:e,appSecret:a,domain:A});this.#_();let s=this.#r.list().find(f=>f.appId===e),g=s?.id??this.#i();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??j6(g),I=await this.#t.resolve(c).catch(()=>{}),d={...s,id:g,appId:e,secretRef:c,ownerOpenIds:s?.ownerOpenIds?.length?s.ownerOpenIds:[Y6],domain:A,botName:r.name,botOpenId:r.openId,activated:r.activated,deletionPending:!1,connectedAt:new Date().toISOString(),createdAt:s?.createdAt??new Date().toISOString()};await this.#t.set(c,a);let B;try{B=await this.#r.saveBot(d)}catch(f){throw await this.#w(c,I),f}return await this.#k(g,async()=>{try{await this.#E(B,a),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.#P(),this.status(g)})}async reconnectBot(t){return this.#_(),this.#k(t,async()=>{let o=this.#R(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(ku(Ru(this.#n.get(t))))return this.status(t);let i;try{i=await this.#t.resolve(o.secretRef)}catch{i=null}if(!i?.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.#P(),this.status(t);try{await this.#E(o,i.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.#P(),this.status(t)})}async sendConnectionTest(t){return this.#_(),this.#k(t,async()=>{let o=this.#R(t),i=this.#n.get(t);if(!ku(Ru(i))||typeof i.sendConnectionTest!="function"){let e=new Error("\u98DE\u4E66\u673A\u5668\u4EBA\u5C1A\u672A\u8FDE\u63A5");throw e.code="test-target-unavailable",e}return i.sendConnectionTest(Ra(`${o.botName}\uFF08${z6(o.appId)}\uFF09`,"\u98DE\u4E66\u673A\u5668\u4EBA"))})}async sendProactiveText(t,o,i,e={}){return this.#_(),this.#k(t,async()=>{this.#R(t);let a=this.#n.get(t);if(!ku(Ru(a))||typeof a.sendProactiveText!="function"){let A=new Error("\u98DE\u4E66\u673A\u5668\u4EBA\u5C1A\u672A\u8FDE\u63A5");throw A.code="bot-not-connected",A}return a.sendProactiveText(o,i,e)})}async disconnectBot(t){return this.#_(),this.#k(t,async()=>(this.#R(t),await this.#T(t),this.#s.delete(t),this.#P(),this.status(t)))}async updateGroupResponseMode(t,o){if(this.#_(),!nS(o))throw new TypeError("Invalid Feishu group response mode");return this.#G(()=>this.#k(t,async()=>{let i=this.#R(t);if(o==="all"&&i.groupMessagePermissionGranted!==!0){let a=new Error("Authorize im:message.group_msg before enabling all group messages");throw a.code="group_message_permission_required",a}let e=await this.#r.saveBot({...i,groupResponseMode:o});return this.#n.get(t)?.setGroupResponseMode?.(e.groupResponseMode),this.#P(),this.status(t)}))}async deleteBot(t){return this.#_(),this.#G(()=>this.#k(t,async()=>(this.#R(t),await this.#O(t),this.#P(),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.#p.values()){let i=o.manager.status().state;x6.has(o.operation)&&i==="saving"?(o.manager.cancel(),o.processing&&t.push(o.processing)):wS.has(i)&&(o.cancelled=!0,o.manager.cancel())}await this.#d,await Promise.allSettled([...this.#h.values()]),await Promise.allSettled([...this.#n.keys()].map(o=>this.#T(o))),await Promise.allSettled(t),await this.#d,await Promise.allSettled([...this.#h.values()]),await Promise.allSettled([...this.#n.keys()].map(o=>this.#T(o)))}#f({registration:t,selectedBotId:o}={}){let i=this.#r.list().map(I=>{let d=Ru(this.#n.get(I.id)),B=ku(d),f=this.#s.get(I.id)??null;return{botId:I.id,phase:rve({connected:B,error:f,connection:d}),connected:B,configured:!0,groupResponseMode:Io(I.groupResponseMode),groupMessagePermissionGranted:I.groupMessagePermissionGranted===!0,bot:tve(I),connection:d,lastMessageError:Xr(d.lastMessageError),error:f}}),e=t?this.#Q(t):{state:"idle",attempt:0,updatedAt:Date.now()},a=wP.has(e.state),A=e.state==="saving",r=!!t&&(a||A),s=i.find(I=>I.botId===o)??(r?null:i[0]??null),g=i.some(I=>I.connected),c=s?.phase??"unconfigured";return a?c="registering":A?c="connecting":e.state==="error"&&!s&&(c="error"),{schemaVersion:2,revision:this.#C,phase:c,connected:s?.connected??!1,configured:i.length>0,bot:s?.bot??null,connection:s?.connection??q6(),error:s?.error??e.error??null,registration:e,bots:i,totals:{configured:i.length,connected:i.filter(I=>I.connected).length},anyConnected:g}}#Q(t){let o=t.manager.status();return{...o,attempt:t.id,...t.botId?{botId:t.botId}:{},...t.operation?{operation:t.operation}:{},...t.stage?{stage:t.stage}:{},...o.state==="error"&&t.publicError?{error:{...t.publicError}}:{}}}async#S(t,o){let i=o.client_id,e=o.client_secret,a=OS(o.user_info?.open_id),A=o.user_info?.tenant_brand,r=t.target;if(t.cancelled)throw this.#m(t,"abort","Group message permission update was cancelled before local activation.");if(i!==r.appId)throw this.#m(t,"repair_app_mismatch","Feishu returned credentials for a different app.");if(!a)throw this.#m(t,"repair_owner_missing","Feishu returned no permission operator identity.");if(A!==void 0&&A!==r.domain)throw this.#m(t,"repair_domain_mismatch","Feishu returned credentials for a different account domain.");if(!r.ownerOpenIds.includes(Y6)&&!r.ownerOpenIds.includes(a))throw this.#m(t,"repair_owner_mismatch","The Feishu permission operator is not an owner of this configured bot.");t.stage="verifying_identity";let s;try{s=await this.#A({appId:i,appSecret:e,domain:r.domain})}catch(g){throw this.#m(t,"repair_credentials_invalid","Feishu could not verify the updated app credentials.",g)}if(r.botOpenId&&s?.openId!==r.botOpenId)throw this.#m(t,"repair_bot_mismatch","The updated Feishu app belongs to a different bot identity.");await this.#G(()=>this.#k(t.botId,async()=>{let g=this.#r.getBot(t.botId);if(!g||g.deletionPending||DS(g)!==t.targetFingerprint)throw this.#m(t,"repair_target_changed","The Feishu bot changed while its permission update was in progress.");let c;try{c=await this.#t.resolve(g.secretRef)}catch(d){throw this.#m(t,"credential_update_failed","Unable to read the current Feishu credential.",d)}if(c?.value!==e){t.stage="persisting_secret";try{await this.#t.set(g.secretRef,e)}catch(B){if((await this.#t.resolve(g.secretRef).catch(()=>null))?.value!==e)throw this.#m(t,"credential_update_failed","Unable to store the updated Feishu credential.",B)}if((await this.#t.resolve(g.secretRef).catch(()=>null))?.value!==e)throw this.#m(t,"credential_state_unknown","The updated Feishu credential could not be confirmed after writing.")}t.stage="enabling_all_messages";let I;try{I=await this.#r.saveBot({...g,groupMessagePermissionGranted:!0,groupResponseMode:"all"})}catch(d){throw this.#m(t,"group_message_permission_save_failed","The permission was accepted, but all-message mode could not be saved.",d)}t.stage="restarting";try{await this.#E(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.#P(),this.#m(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.#P()}))}async#y(t,o){let i=o.client_id,e=o.client_secret,a=OS(o.user_info?.open_id),A=o.user_info?.tenant_brand,r=t.target;if(t.cancelled)throw this.#m(t,"abort","Callback repair was cancelled before local activation.");if(i!==r.appId)throw this.#m(t,"repair_app_mismatch","Feishu returned credentials for a different app.");if(!a)throw this.#m(t,"repair_owner_missing","Feishu returned no repair operator identity.");if(A!==void 0&&A!==r.domain)throw this.#m(t,"repair_domain_mismatch","Feishu returned credentials for a different account domain.");t.stage="verifying_identity";let s;try{s=await this.#A({appId:i,appSecret:e,domain:r.domain})}catch(c){throw this.#m(t,"repair_credentials_invalid","Feishu could not verify the repaired app credentials.",c)}if(r.botOpenId&&s?.openId!==r.botOpenId)throw this.#m(t,"repair_bot_mismatch","The repaired Feishu app belongs to a different bot identity.");let g=await this.#G(()=>this.#k(t.botId,async()=>{let c=this.#r.getBot(t.botId);if(!c||c.deletionPending||DS(c)!==t.targetFingerprint)throw this.#m(t,"repair_target_changed","The Feishu bot changed while its callback repair was in progress.");let I;try{I=await this.#t.resolve(c.secretRef)}catch(f){throw this.#m(t,"credential_update_failed","Unable to read the current Feishu credential.",f)}if(I?.value!==e){t.stage="persisting_secret";try{await this.#t.set(c.secretRef,e)}catch(Q){if((await this.#t.resolve(c.secretRef).catch(()=>null))?.value!==e)throw this.#m(t,"credential_update_failed","Unable to store the repaired Feishu credential.",Q)}if((await this.#t.resolve(c.secretRef).catch(()=>null))?.value!==e)throw this.#m(t,"credential_state_unknown","The repaired Feishu credential could not be confirmed after writing.")}let B;t.stage="restarting";try{await this.#E(c,e),B=this.#n.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.#P(),this.#m(t,"repair_connection_failed","The repaired Feishu runtime could not be started.",f)}if(!B)throw this.#m(t,"repair_connection_failed","The repaired Feishu runtime is unavailable.");return this.#s.delete(t.botId),this.#P(),B}));if(typeof g.beginCardActionProbe!="function")throw this.#m(t,"card_action_probe_unavailable","The Feishu runtime cannot verify card callbacks.");t.stage="awaiting_callback";try{if((await g.beginCardActionProbe({expectedOperatorOpenId:t.initiator.actorOpenId??a,timeoutMs:this.#u,...t.initiator.chatId?{chatId:t.initiator.chatId}:{}}))?.verified!==!0){let I=new Error("Feishu runtime returned no callback proof");throw I.code="card_action_probe_failed",I}}catch(c){let I=c?.code==="card_action_probe_timeout"?"card_action_probe_timeout":c?.code==="card_action_probe_unavailable"?"card_action_probe_unavailable":c?.code==="card_action_probe_send_failed"?"card_action_probe_send_failed":"card_action_probe_failed";throw this.#m(t,I,I==="card_action_probe_timeout"?"Timed out waiting for the Feishu callback verification button.":"The Feishu card callback probe failed.",c)}t.stage="verified",t.publicError=null,this.#P()}#m(t,o,i,e){t.publicError={code:o,message:i};let a=new Error(i,e?{cause:e}:void 0);return a.code=o,a}async#D(t,o){if(t.cancelled)throw new Error("Registration was cancelled");let i=o.client_id,e=o.client_secret,a=o.user_info?.open_id,A=o.user_info?.tenant_brand==="lark"?"lark":"feishu";if(!a)throw new Error("Feishu registration returned no owner open_id");let r=await this.#A({appId:i,appSecret:e,domain:A});if(t.cancelled)throw new Error("Registration was cancelled");let s=this.#r.list().find(Q=>Q.appId===i),g=s?.id??this.#i();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??j6(g),I=this.#g.get(g),d=await this.#t.resolve(c).catch(()=>{});await this.#t.set(c,e);let B;try{B=await this.#r.saveBot({...s,id:g,appId:i,secretRef:c,ownerOpenIds:[...new Set([...s?.ownerOpenIds??[],a])],domain:A,botName:r.name,botOpenId:r.openId,activated:r.activated,deletionPending:!1,connectedAt:new Date().toISOString(),createdAt:s?.createdAt??new Date().toISOString()}),t.botId=g,t.createdNew=!s,this.#g.set(g,t.id)}catch(Q){try{await this.#w(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.#k(g,()=>this.#O(g)):(await this.#r.saveBot(s),await this.#w(c,d),I?this.#g.set(g,I):this.#g.delete(g)),new Error("Registration was cancelled");let f=!1;try{if(await this.#k(g,()=>this.#E(B,e)),t.cancelled)throw t.createdNew?await this.#k(g,()=>this.#O(g)):(await this.#r.saveBot(s),await this.#w(c,d),I?this.#g.set(g,I):this.#g.delete(g),d?.value&&!s.deletionPending?await this.#k(g,()=>this.#E(s,d.value)):await this.#k(g,()=>this.#T(g))),f=!0,new Error("Registration was cancelled");this.#s.delete(g),this.#P()}catch(Q){if(t.cancelled)throw!f&&t.createdNew&&this.#r.getBot(g)?await this.#k(g,()=>this.#O(g)):!f&&s&&(await this.#r.saveBot(s),await this.#w(c,d),I?this.#g.set(g,I):this.#g.delete(g),!this.#B&&d?.value&&!s.deletionPending?await this.#k(g,()=>this.#E(s,d.value)):await this.#k(g,()=>this.#T(g))),this.#P(),Q;if(s&&d?.value)try{throw await this.#r.saveBot(s),await this.#w(c,d),I?this.#g.set(g,I):this.#g.delete(g),s.deletionPending?(await this.#k(g,()=>this.#T(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.#k(g,()=>this.#E(s,d.value)),this.#s.delete(g)),this.#P(),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.#P(),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.#P(),Q}}async#E(t,o){await this.#T(t.id);let i=await this.#l({botId:t.id,config:t,appSecret:o,repair:this.#N(t.id)});this.#n.set(t.id,i);try{await i.start()}catch(e){throw this.#n.get(t.id)===i&&this.#n.delete(t.id),await i.stop({preserveError:!0}).catch(()=>{}),e}}#N(t){let o=i=>{let e=this.#p.get(i);return e?.operation===Nu&&e.botId===t?e:null};return Object.freeze({start:({actorOpenId:i,chatId:e}={})=>this.startCallbackRepair(t,{actorOpenId:i,chatId:e}),status:({attemptId:i}={})=>o(i)?this.registrationStatus(i):null,cancel:async({attemptId:i}={})=>o(i)?this.cancelRegistration(i):this.status(t)})}async#T(t){let o=this.#n.get(t);this.#n.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.#T(t);try{await this.#t.unset(o.secretRef)}catch(i){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:i})}try{await this.#o({botId:t,config:o})}catch(i){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:i})}await this.#r.removeBot(t),this.#s.delete(t),this.#g.delete(t)}}async#w(t,o){o?.value?await this.#t.set(t,o.value):await this.#t.unset(t)}#R(t){let o=this.#r.getBot(t);if(!o)throw new Error("Unknown Feishu bot");return o}#_(){if(this.#B)throw new Error("The Feishu controller is closed")}#G(t){let o=this.#d.then(t,t);return this.#d=o.then(()=>{},()=>{}),o}#k(t,o){let e=(this.#h.get(t)??Promise.resolve()).then(o,o),a=e.then(()=>{},()=>{});return this.#h.set(t,a),a.finally(()=>{this.#h.get(t)===a&&this.#h.delete(t)}),e}#F(){if(!(this.#p.size<=32))for(let[t,o]of this.#p){if(t===this.#I)continue;let i=o.manager.status().state;if(!wP.has(i)&&i!=="saving"&&this.#p.delete(t),this.#p.size<=32)break}}#P(){this.#C+=1}};var sve=["open.feishu.cn","open.larksuite.com"];function gve(n,t){if(t==="*")return!0;let o=t.startsWith(".")?t.slice(1):t;return o?n===o||n.endsWith(`.${o}`):!1}function cve(n){for(let t of["no_proxy","NO_PROXY"]){let o=n?.[t];if(typeof o!="string"||!o.trim())continue;let i=o.split(",").map(e=>e.trim().toLowerCase()).filter(Boolean);if(sve.some(e=>i.some(a=>gve(e,a))))return!0}return!1}function Ive(n){if(!cve(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 lve(n,t=o=>new V6.default(o)){let o=Ive(n);return o?t(o):void 0}function pve(n){let t=kc(n.dshHome??process.env.DSH_HOME??jd(ove(),".dsh")),o=kc(n.dataDir??jd(t,"integrations","dsh-feishu"));return{root:o,config:kc(n.configPath??jd(o,"config.json")),legacyState:kc(n.statePath??jd(o,"state.json")),bots:kc(n.botsDir??jd(o,"bots")),workspaces:kc(n.workspacesPath??jd(o,"workspaces.json"))}}async function DP(n,t={},o={}){if(!n?.credentials)throw new TypeError("dsh-feishu requires ctx.credentials");let i=aa(n,t),e=o.lark??rP,a=o.Controller??vu,A=o.ConfigStore??fS,r=o.StateStore??iS,s=o.HarnessClient??uS,g=o.FeishuRuntime??CS,c=o.verifyFeishuApp??t6,I=fe=>c({...fe,httpInstance:e.defaultHttpInstance}),d=o.createConnectionSupervisor??aP,B=typeof n.logger=="function"?n.logger("dsh-feishu"):n.logger??console,f=()=>La(n),Q=pve(t),y=await new A(Q.config).load(),m=kc(t.workspace??process.cwd()),T=o.WorkspaceStore??ra,_=o.workspaces??await new T(Q.workspaces,{defaultWorkspace:m}).load(),R=typeof y.list=="function",K=()=>R?y.list():[],L=K();R&&await _.reconcile(L.map(fe=>fe.id)),await Promise.all(L.map(fe=>_.ensure(fe.id,{defaultAgentPreset:t.agentPreset,initialAccessPolicy:nr("feishu",fe)})));let F=typeof y.removeBot=="function"?Ha(y,{workspaces:_,method:"removeBot",botIdFromRemoved:fe=>fe.id,saveMethod:"saveBot",botIdFromSave:fe=>fe?.id}):y,q=new Map,V=fe=>!fe.id||!fe.secretRef||fe.secretRef===QS?Q.legacyState:kc(Q.bots,fe.id,"state.json"),x=async fe=>{let ke=fe.id??"__legacy__",Re=q.get(ke);return Re||(Re=await new r(V(fe)).load(),q.set(ke,Re)),Re},G=async fe=>{let ke=K().find(Re=>Re.id===fe);if(!ke)throw new Error("Unknown Feishu bot");return x(ke)},J=ja(n,o.commandExecutor),{controlExecutor:U,sessionMaintenanceExecutor:N,fileIngressExecutor:k}=Ja(n,{controlExecutor:o.controlExecutor,sessionMaintenanceExecutor:o.sessionMaintenanceExecutor,fileIngressExecutor:o.fileIngressExecutor}),z=new s({...i,workspace:m,autostart:!1,dshBin:t.dshBin??"dsh",...J?{commandExecutor:J}:{},...U?{controlExecutor:U}:{},...N?{sessionMaintenanceExecutor:N}:{},...k?{fileIngressExecutor:k}:{}}),Ae=o.proxyEnv??process.env,ie=lve(Ae,o.createProxyAgent),we=new a({registerApp:fe=>e.registerApp(fe),verifyApp:I,credentials:n.credentials,configStore:F,createRuntime:async({botId:fe,config:ke,appSecret:Re,repair:We})=>{let ve=await x(ke),aA=fe??ke.id??ke.appId;await _.ensure(aA,{defaultAgentPreset:t.agentPreset,initialAccessPolicy:nr("feishu",ke)});let Be=Ka(z,{botId:aA,workspaces:_,state:ve,agentPresetCatalog:f});return new g({lark:e,botId:aA,repair:We,appId:ke.appId,appSecret:Re,domain:ke.domain,botOpenId:ke.botOpenId,groupResponseMode:ke.groupResponseMode,ownerOpenIds:ke.ownerOpenIds??[ke.ownerOpenId],harness:Be.harness,state:Be.state,contextEnhancement:{botId:aA,getSettings:()=>_.contextEnhancementFor(aA)},accessPolicy:qa(_,aA,{channel:"feishu",config:ke}),replyTimeoutMs:t.replyTimeoutMs??6e5,slashCommands:t.slashCommands!==!1,...ie?{wsAgent:ie}:{},logger:{error:(...Ie)=>B.error?.(`[${fe??ke.id}]`,...Ie),warn:(...Ie)=>B.warn?.(`[${fe??ke.id}]`,...Ie),info:(...Ie)=>B.info?.(`[${fe??ke.id}]`,...Ie),debug:(...Ie)=>B.debug?.(`[${fe??ke.id}]`,...Ie)}})},deleteState:async({botId:fe,config:ke})=>{q.delete(fe);try{await nve(V(ke))}catch(Re){if(Re?.code!=="ENOENT")throw Re}}}),se=xa(we,{workspaces:_,stateFor:G,agentPresetCatalog:f}),Te=d({controller:se,harness:z,logger:B,retryDelaysMs:t.retryDelaysMs,healthyIntervalMs:t.healthyIntervalMs}).start();return{controller:se,deliveryAdapter:Ya({channel:"feishu",workspaces:_,coreController:we,stateFor:G}),ready:Te.ready,async close(){await Te.close(),await se.close(),z.stopManagedProcess(),ie?.destroy?.()}}}import Nve from"qrcode";var qd=qe(RP(),1);var Mve=qe(RP(),1);var _ve=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",\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.",\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\u4E94\u4E2A\u5B57\u6BB5\u3002":"Source fields must be chosen from the five defined fields.","\u4FDD\u5B58\u4E2D\u2026":"Saving\u2026",\u672A\u8BBE\u7F6E:"Not set","\u5DE5\u4F5C\u533A\u4FEE\u6539\u5931\u8D25\uFF0C\u8BF7\u91CD\u8BD5\u3002":"Could not update the workspace. Try again.","\u8BF7\u8F93\u5165\u5DE5\u4F5C\u533A\u7EDD\u5BF9\u8DEF\u5F84\u3002":"Enter an absolute workspace path.","\u5DE5\u4F5C\u533A\u5FC5\u987B\u662F\u7EDD\u5BF9\u8DEF\u5F84\u3002":"The workspace must be an absolute path.","\u5DE5\u4F5C\u533A\u8DEF\u5F84\u4E0D\u5B58\u5728\u3002":"The workspace path does not exist.","\u5DE5\u4F5C\u533A\u8DEF\u5F84\u5FC5\u987B\u6307\u5411\u4E00\u4E2A\u76EE\u5F55\u3002":"The workspace path must point to a directory.","\u627E\u4E0D\u5230\u8981\u4FEE\u6539\u7684\u673A\u5668\u4EBA\u3002":"The bot could not be found.","Agent Preset":"Agent Preset","\u67E5\u770B Agent Preset \u8BF4\u660E":"View Agent Preset help","\u8DDF\u968F Host \u9ED8\u8BA4":"Follow the Host default","\uFF08\u5DF2\u4E0D\u53EF\u7528\uFF09":" (unavailable)","\u53EA\u5F71\u54CD\u65B0\u5EFA\u4F1A\u8BDD\uFF1B\u82E5\u5F53\u524D\u804A\u5929\u5DF2\u6709\u4F1A\u8BDD\uFF0C\u5148\u53D1\u9001 /new\uFF0C\u518D\u53D1\u9001\u666E\u901A\u6D88\u606F\u751F\u6548\u3002":"This affects only new sessions. If the current chat already has a session, send /new, then send a regular message to apply it.","\u5F53\u524D Agent Preset \u5DF2\u4E0D\u53EF\u7528\uFF0C\u8BF7\u9009\u62E9\u5176\u4ED6 Preset \u6216\u8DDF\u968F Host \u9ED8\u8BA4\u3002":"The current Agent Preset is unavailable. Choose another preset or follow the Host default.","Agent Preset \u4FEE\u6539\u5931\u8D25\uFF0C\u8BF7\u91CD\u8BD5\u3002":"Could not update the Agent Preset. Try again.","\u8BF7\u9009\u62E9 Agent Preset\u3002":"Choose an Agent Preset.","Agent Preset \u65E0\u6548\u3002":"The Agent Preset is invalid.","Agent Preset \u4E0D\u5B58\u5728\u6216\u4E0D\u53EF\u7528\u3002":"The Agent Preset does not exist or is unavailable.",\u5C1A\u672A\u68C0\u67E5:"Not checked yet",\u521A\u521A:"Just now",\u68C0\u67E5\u8FDE\u63A5:"Check connection","\u68C0\u67E5\u4E2D\u2026":"Checking\u2026","\u8FDE\u63A5\u68C0\u67E5\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002":"Connection check failed. Try again later.","\u6D4B\u8BD5\u6D88\u606F\u5DF2\u53D1\u9001\uFF0C\u8BF7\u5230\u5BF9\u5E94\u673A\u5668\u4EBA\u4F1A\u8BDD\u4E2D\u786E\u8BA4\u3002":"Test message sent. Check the matching bot conversation.","\u8FDE\u63A5\u68C0\u67E5\u5B8C\u6210\u3002\u673A\u5668\u4EBA\u5C1A\u672A\u6536\u5230\u53EF\u7528\u4E8E\u6D4B\u8BD5\u7684\u79C1\u804A\u6D88\u606F\u3002":"Connection check completed. The bot has not received a direct message it can use for testing.","\u8FDE\u63A5\u68C0\u67E5\u5B8C\u6210\uFF0C\u4F46\u6D4B\u8BD5\u6D88\u606F\u53D1\u9001\u5931\u8D25\u3002":"Connection check completed, but the test message could not be sent.","\u6D4B\u8BD5\u6D88\u606F\u5DF2\u53D1\u9001\uFF0C\u8BF7\u5230\u98DE\u4E66\u4F1A\u8BDD\u4E2D\u786E\u8BA4\u3002":"Test message sent. Check the Feishu conversation.","\u6D4B\u8BD5\u6D88\u606F\u5DF2\u53D1\u9001\uFF0C\u8BF7\u5230 WhatsApp \u81EA\u804A\u4F1A\u8BDD\u4E2D\u786E\u8BA4\u3002":"Test message sent. Check the WhatsApp self-chat.","\u8FDE\u63A5\u68C0\u67E5\u5B8C\u6210\uFF0C\u4F46\u5F53\u524D\u6CA1\u6709\u53EF\u7528\u7684 WhatsApp \u81EA\u804A\u76EE\u6807\u3002":"Connection check completed, but no WhatsApp self-chat target is available.","\u9489\u9489\u8FDE\u63A5\u68C0\u67E5\u5B8C\u6210\uFF0C\u6D4B\u8BD5\u6D88\u606F\u5DF2\u53D1\u9001\u3002":"DingTalk connection check completed and the test message was sent.","\u9489\u9489\u8FDE\u63A5\u68C0\u67E5\u5B8C\u6210\uFF0C\u4F46\u6D4B\u8BD5\u6D88\u606F\u53D1\u9001\u5931\u8D25\u3002":"DingTalk connection check completed, but the test message could not be sent.","\u5FAE\u4FE1\u8FDE\u63A5\u68C0\u67E5\u5B8C\u6210\uFF0C\u6D4B\u8BD5\u6D88\u606F\u5DF2\u53D1\u9001\u3002":"WeChat connection check completed and the test message was sent.","\u5FAE\u4FE1\u8FDE\u63A5\u68C0\u67E5\u5B8C\u6210\uFF0C\u4F46\u6D4B\u8BD5\u6D88\u606F\u53D1\u9001\u5931\u8D25\u3002":"WeChat connection check completed, but the test message could not be sent.","\u4F01\u4E1A\u5FAE\u4FE1\u8FDE\u63A5\u68C0\u67E5\u5B8C\u6210\uFF0C\u6D4B\u8BD5\u6D88\u606F\u5DF2\u53D1\u9001\u3002":"WeCom connection check completed and the test message was sent.","\u4F01\u4E1A\u5FAE\u4FE1\u8FDE\u63A5\u68C0\u67E5\u5B8C\u6210\uFF0C\u4F46\u6D4B\u8BD5\u6D88\u606F\u53D1\u9001\u5931\u8D25\u3002":"WeCom connection check completed, but the test message could not be sent.",\u91CD\u8BD5\u8FDE\u63A5:"Reconnect","\u91CD\u8BD5\u4E2D\u2026":"Retrying\u2026",\u79FB\u9664\u63A5\u5165:"Remove connection",\u786E\u8BA4\u79FB\u9664\u63A5\u5165:"Remove connection",\u786E\u8BA4\u79FB\u9664:"Remove","\u6B63\u5728\u79FB\u9664\u2026":"Removing\u2026",\u4FDD\u7559\u673A\u5668\u4EBA:"Keep bot",\u4FDD\u7559\u8D26\u53F7:"Keep account",\u53D6\u6D88:"Cancel",\u5173\u95ED:"Close",\u7ACB\u5373\u91CD\u8BD5:"Retry now",\u91CD\u65B0\u8BFB\u53D6:"Reload",\u91CD\u65B0\u751F\u6210\u4E8C\u7EF4\u7801:"Generate a new QR code",\u91CD\u65B0\u751F\u6210\u4E8C\u7EF4\u7801\u540E\u7EE7\u7EED:"Generate a new QR code",\u5237\u65B0\u4E8C\u7EF4\u7801:"Refresh QR code","\u5237\u65B0\u4E2D\u2026":"Refreshing\u2026",\u6362\u4E00\u4E2A\u4E8C\u7EF4\u7801:"Get another QR code",\u7EE7\u7EED\u8FDE\u63A5:"Continue connecting",\u7ED1\u5B9A\u5E76\u8FDE\u63A5:"Connect","\u6B63\u5728\u7ED1\u5B9A\u2026":"Connecting\u2026",\u9A8C\u8BC1\u5E76\u8FDE\u63A5:"Verify and connect","\u6B63\u5728\u9A8C\u8BC1\u5E76\u8FDE\u63A5\u2026":"Verifying and connecting\u2026","\u6B63\u5728\u9A8C\u8BC1\u2026":"Verifying\u2026","\u64CD\u4F5C\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5":"The operation failed. Try again later.",\u8BF7\u7A0D\u540E\u91CD\u8BD5:"Try again later.",\u5F53\u524D\u4E8C\u7EF4\u7801\u6709\u6548\u65F6\u95F4:"QR code expires in",\u4E8C\u7EF4\u7801\u6709\u6548\u65F6\u95F4:"QR code expires in",\u4E8C\u7EF4\u7801\u5DF2\u8FC7\u671F:"QR code expired",\u4E8C\u7EF4\u7801\u5DF2\u5931\u6548:"QR code expired","\u4E8C\u7EF4\u7801\u5DF2\u8FC7\u671F\n\u8BF7\u91CD\u65B0\u751F\u6210":`QR code expired +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\u516D\u4E2A\u5B57\u6BB5\u3002":"Source fields must be chosen from the six defined fields.","\u4FDD\u5B58\u4E2D\u2026":"Saving\u2026",\u672A\u8BBE\u7F6E:"Not set","\u5DE5\u4F5C\u533A\u4FEE\u6539\u5931\u8D25\uFF0C\u8BF7\u91CD\u8BD5\u3002":"Could not update the workspace. Try again.","\u8BF7\u8F93\u5165\u5DE5\u4F5C\u533A\u7EDD\u5BF9\u8DEF\u5F84\u3002":"Enter an absolute workspace path.","\u5DE5\u4F5C\u533A\u5FC5\u987B\u662F\u7EDD\u5BF9\u8DEF\u5F84\u3002":"The workspace must be an absolute path.","\u5DE5\u4F5C\u533A\u8DEF\u5F84\u4E0D\u5B58\u5728\u3002":"The workspace path does not exist.","\u5DE5\u4F5C\u533A\u8DEF\u5F84\u5FC5\u987B\u6307\u5411\u4E00\u4E2A\u76EE\u5F55\u3002":"The workspace path must point to a directory.","\u627E\u4E0D\u5230\u8981\u4FEE\u6539\u7684\u673A\u5668\u4EBA\u3002":"The bot could not be found.","Agent Preset":"Agent Preset","\u67E5\u770B Agent Preset \u8BF4\u660E":"View Agent Preset help","\u8DDF\u968F Host \u9ED8\u8BA4":"Follow the Host default","\uFF08\u5DF2\u4E0D\u53EF\u7528\uFF09":" (unavailable)","\u53EA\u5F71\u54CD\u65B0\u5EFA\u4F1A\u8BDD\uFF1B\u82E5\u5F53\u524D\u804A\u5929\u5DF2\u6709\u4F1A\u8BDD\uFF0C\u5148\u53D1\u9001 /new\uFF0C\u518D\u53D1\u9001\u666E\u901A\u6D88\u606F\u751F\u6548\u3002":"This affects only new sessions. If the current chat already has a session, send /new, then send a regular message to apply it.","\u5F53\u524D Agent Preset \u5DF2\u4E0D\u53EF\u7528\uFF0C\u8BF7\u9009\u62E9\u5176\u4ED6 Preset \u6216\u8DDF\u968F Host \u9ED8\u8BA4\u3002":"The current Agent Preset is unavailable. Choose another preset or follow the Host default.","Agent Preset \u4FEE\u6539\u5931\u8D25\uFF0C\u8BF7\u91CD\u8BD5\u3002":"Could not update the Agent Preset. Try again.","\u8BF7\u9009\u62E9 Agent Preset\u3002":"Choose an Agent Preset.","Agent Preset \u65E0\u6548\u3002":"The Agent Preset is invalid.","Agent Preset \u4E0D\u5B58\u5728\u6216\u4E0D\u53EF\u7528\u3002":"The Agent Preset does not exist or is unavailable.",\u5C1A\u672A\u68C0\u67E5:"Not checked yet",\u521A\u521A:"Just now",\u68C0\u67E5\u8FDE\u63A5:"Check connection","\u68C0\u67E5\u4E2D\u2026":"Checking\u2026","\u8FDE\u63A5\u68C0\u67E5\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002":"Connection check failed. Try again later.","\u6D4B\u8BD5\u6D88\u606F\u5DF2\u53D1\u9001\uFF0C\u8BF7\u5230\u5BF9\u5E94\u673A\u5668\u4EBA\u4F1A\u8BDD\u4E2D\u786E\u8BA4\u3002":"Test message sent. Check the matching bot conversation.","\u8FDE\u63A5\u68C0\u67E5\u5B8C\u6210\u3002\u673A\u5668\u4EBA\u5C1A\u672A\u6536\u5230\u53EF\u7528\u4E8E\u6D4B\u8BD5\u7684\u79C1\u804A\u6D88\u606F\u3002":"Connection check completed. The bot has not received a direct message it can use for testing.","\u8FDE\u63A5\u68C0\u67E5\u5B8C\u6210\uFF0C\u4F46\u6D4B\u8BD5\u6D88\u606F\u53D1\u9001\u5931\u8D25\u3002":"Connection check completed, but the test message could not be sent.","\u6D4B\u8BD5\u6D88\u606F\u5DF2\u53D1\u9001\uFF0C\u8BF7\u5230\u98DE\u4E66\u4F1A\u8BDD\u4E2D\u786E\u8BA4\u3002":"Test message sent. Check the Feishu conversation.","\u6D4B\u8BD5\u6D88\u606F\u5DF2\u53D1\u9001\uFF0C\u8BF7\u5230 WhatsApp \u81EA\u804A\u4F1A\u8BDD\u4E2D\u786E\u8BA4\u3002":"Test message sent. Check the WhatsApp self-chat.","\u8FDE\u63A5\u68C0\u67E5\u5B8C\u6210\uFF0C\u4F46\u5F53\u524D\u6CA1\u6709\u53EF\u7528\u7684 WhatsApp \u81EA\u804A\u76EE\u6807\u3002":"Connection check completed, but no WhatsApp self-chat target is available.","\u9489\u9489\u8FDE\u63A5\u68C0\u67E5\u5B8C\u6210\uFF0C\u6D4B\u8BD5\u6D88\u606F\u5DF2\u53D1\u9001\u3002":"DingTalk connection check completed and the test message was sent.","\u9489\u9489\u8FDE\u63A5\u68C0\u67E5\u5B8C\u6210\uFF0C\u4F46\u6D4B\u8BD5\u6D88\u606F\u53D1\u9001\u5931\u8D25\u3002":"DingTalk connection check completed, but the test message could not be sent.","\u5FAE\u4FE1\u8FDE\u63A5\u68C0\u67E5\u5B8C\u6210\uFF0C\u6D4B\u8BD5\u6D88\u606F\u5DF2\u53D1\u9001\u3002":"WeChat connection check completed and the test message was sent.","\u5FAE\u4FE1\u8FDE\u63A5\u68C0\u67E5\u5B8C\u6210\uFF0C\u4F46\u6D4B\u8BD5\u6D88\u606F\u53D1\u9001\u5931\u8D25\u3002":"WeChat connection check completed, but the test message could not be sent.","\u4F01\u4E1A\u5FAE\u4FE1\u8FDE\u63A5\u68C0\u67E5\u5B8C\u6210\uFF0C\u6D4B\u8BD5\u6D88\u606F\u5DF2\u53D1\u9001\u3002":"WeCom connection check completed and the test message was sent.","\u4F01\u4E1A\u5FAE\u4FE1\u8FDE\u63A5\u68C0\u67E5\u5B8C\u6210\uFF0C\u4F46\u6D4B\u8BD5\u6D88\u606F\u53D1\u9001\u5931\u8D25\u3002":"WeCom connection check completed, but the test message could not be sent.",\u91CD\u8BD5\u8FDE\u63A5:"Reconnect","\u91CD\u8BD5\u4E2D\u2026":"Retrying\u2026",\u79FB\u9664\u63A5\u5165:"Remove connection",\u786E\u8BA4\u79FB\u9664\u63A5\u5165:"Remove connection",\u786E\u8BA4\u79FB\u9664:"Remove","\u6B63\u5728\u79FB\u9664\u2026":"Removing\u2026",\u4FDD\u7559\u673A\u5668\u4EBA:"Keep bot",\u4FDD\u7559\u8D26\u53F7:"Keep account",\u53D6\u6D88:"Cancel",\u5173\u95ED:"Close",\u7ACB\u5373\u91CD\u8BD5:"Retry now",\u91CD\u65B0\u8BFB\u53D6:"Reload",\u91CD\u65B0\u751F\u6210\u4E8C\u7EF4\u7801:"Generate a new QR code",\u91CD\u65B0\u751F\u6210\u4E8C\u7EF4\u7801\u540E\u7EE7\u7EED:"Generate a new QR code",\u5237\u65B0\u4E8C\u7EF4\u7801:"Refresh QR code","\u5237\u65B0\u4E2D\u2026":"Refreshing\u2026",\u6362\u4E00\u4E2A\u4E8C\u7EF4\u7801:"Get another QR code",\u7EE7\u7EED\u8FDE\u63A5:"Continue connecting",\u7ED1\u5B9A\u5E76\u8FDE\u63A5:"Connect","\u6B63\u5728\u7ED1\u5B9A\u2026":"Connecting\u2026",\u9A8C\u8BC1\u5E76\u8FDE\u63A5:"Verify and connect","\u6B63\u5728\u9A8C\u8BC1\u5E76\u8FDE\u63A5\u2026":"Verifying and connecting\u2026","\u6B63\u5728\u9A8C\u8BC1\u2026":"Verifying\u2026","\u64CD\u4F5C\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5":"The operation failed. Try again later.",\u8BF7\u7A0D\u540E\u91CD\u8BD5:"Try again later.",\u5F53\u524D\u4E8C\u7EF4\u7801\u6709\u6548\u65F6\u95F4:"QR code expires in",\u4E8C\u7EF4\u7801\u6709\u6548\u65F6\u95F4:"QR code expires in",\u4E8C\u7EF4\u7801\u5DF2\u8FC7\u671F:"QR code expired",\u4E8C\u7EF4\u7801\u5DF2\u5931\u6548:"QR code expired","\u4E8C\u7EF4\u7801\u5DF2\u8FC7\u671F\n\u8BF7\u91CD\u65B0\u751F\u6210":`QR code expired Generate a new one`,"\u4E8C\u7EF4\u7801\u56FE\u7247\u6B63\u5728\u751F\u6210\u2026":"Generating QR code\u2026","\u4E8C\u7EF4\u7801\u6B63\u5728\u751F\u6210\u2026":"Generating QR code\u2026","\u4E8C\u7EF4\u7801\u6B63\u5728\u81EA\u52A8\u5237\u65B0\u2026":"Refreshing QR code\u2026","\u4E8C\u7EF4\u7801\u672A\u5C31\u7EEA\uFF0C\u8BF7\u6253\u5F00\u6388\u6743\u94FE\u63A5":"The QR code is not ready. Open the authorization link.","\u4E8C\u7EF4\u7801\u56FE\u7247\u672A\u5C31\u7EEA\uFF0C\u8BF7\u4F7F\u7528\u5907\u7528\u94FE\u63A5\u3002":"The QR code is not ready. Use the alternate link.","\u4E8C\u7EF4\u7801\u56FE\u7247\u672A\u5C31\u7EEA\uFF0C\u8BF7\u91CD\u65B0\u751F\u6210\u3002":"The QR code is not ready. Generate a new one.",\u7B49\u5F85\u5237\u65B0:"Waiting to refresh",\u6B63\u5728\u5237\u65B0\u4E8C\u7EF4\u7801:"Refreshing QR code",\u6253\u5F00\u5907\u7528\u94FE\u63A5:"Open alternate link",\u751F\u6210\u4E8C\u7EF4\u7801:"Generate QR code",\u751F\u6210\u5FAE\u4FE1\u4E8C\u7EF4\u7801:"Generate WeChat QR code",\u751F\u6210\u98DE\u4E66\u4E8C\u7EF4\u7801:"Generate Feishu QR code",\u751F\u6210\u9489\u9489\u4E8C\u7EF4\u7801:"Generate DingTalk QR code",\u751F\u6210\u4F01\u4E1A\u5FAE\u4FE1\u4E8C\u7EF4\u7801:"Generate WeCom QR code","\u751F\u6210 QQ \u4E8C\u7EF4\u7801":"Generate QQ QR code","\u6B63\u5728\u751F\u6210\u4E8C\u7EF4\u7801\u2026":"Generating QR code\u2026",\u6B63\u5728\u51C6\u5907\u6388\u6743\u4E8C\u7EF4\u7801:"Preparing authorization QR code",\u6B63\u5728\u51C6\u5907\u6743\u9650\u6388\u6743\u4E8C\u7EF4\u7801:"Preparing permission authorization QR code",\u6B63\u5728\u51C6\u5907\u5FAE\u4FE1\u4E8C\u7EF4\u7801:"Preparing WeChat QR code",\u6B63\u5728\u6DFB\u52A0\u65B0\u673A\u5668\u4EBA:"Adding a new bot","\u6B63\u5728\u7533\u8BF7\u9489\u9489\u6388\u6743\u4E8C\u7EF4\u7801\u2026":"Requesting DingTalk authorization QR code\u2026","\u6B63\u5728\u7533\u8BF7\u4F01\u4E1A\u5FAE\u4FE1\u4E8C\u7EF4\u7801\u2026":"Requesting WeCom QR code\u2026","\u6B63\u5728\u7533\u8BF7 QQ \u4E8C\u7EF4\u7801\u2026":"Requesting QQ QR code\u2026","\u6B63\u5728\u751F\u6210 WhatsApp \u4E8C\u7EF4\u7801":"Generating WhatsApp QR code","\u626B\u7801\uFF0C\u521B\u5EFA\u7B2C\u4E00\u4E2A\u98DE\u4E66\u5165\u53E3":"Scan to create your first Feishu bot","\u626B\u7801\u53EA\u4F1A\u65B0\u589E\u4E00\u4E2A\u673A\u5668\u4EBA\uFF0C\u5DF2\u63A5\u5165\u7684\u673A\u5668\u4EBA\u4F1A\u7EE7\u7EED\u6B63\u5E38\u6536\u53D1\u6D88\u606F\u3002":"Scanning adds one bot. Existing bots will continue to send and receive messages.","\u65E0\u9700\u624B\u52A8\u586B\u5199 App ID\u3002\u4EE5\u540E\u8FD8\u53EF\u4EE5\u7EE7\u7EED\u6DFB\u52A0\u673A\u5668\u4EBA\uFF0C\u5206\u522B\u670D\u52A1\u4E0D\u540C\u56E2\u961F\u6216\u98DE\u4E66\u79DF\u6237\u3002":"No App ID is required. You can add more bots later for different teams or Feishu tenants.",\u4F7F\u7528\u98DE\u4E66\u626B\u7801\u521B\u5EFA\u673A\u5668\u4EBA:"Scan with Feishu to create a bot",\u5237\u65B0\u4E8C\u7EF4\u7801\u540E\u7EE7\u7EED:"Refresh the QR code to continue","\u6253\u5F00\u98DE\u4E66\u79FB\u52A8\u7AEF\uFF0C\u4F7F\u7528\u626B\u4E00\u626B\u8BFB\u53D6\u4E8C\u7EF4\u7801":"Open Feishu on your phone and scan the QR code","\u6838\u5BF9\u5E94\u7528\u540D\u79F0\u4E0E\u6743\u9650\u8303\u56F4\uFF0C\u5E76\u786E\u8BA4\u521B\u5EFA":"Review the app name and permissions, then confirm","\u4FDD\u6301\u672C\u9875\u6253\u5F00\uFF0C\u7B49\u5F85\u65B0\u673A\u5668\u4EBA\u7684\u957F\u8FDE\u63A5\u5C31\u7EEA":"Keep this page open until the bot connection is ready",\u5728\u98DE\u4E66\u4E2D\u6253\u5F00:"Open in Feishu",\u53D6\u6D88\u6DFB\u52A0:"Cancel",\u4F7F\u7528\u98DE\u4E66\u626B\u7801\u8865\u5168\u6743\u9650:"Scan with Feishu to complete permissions",\u4F7F\u7528\u98DE\u4E66\u786E\u8BA4\u7FA4\u6D88\u606F\u6743\u9650:"Confirm group-message permission with Feishu","\u626B\u7801\u4F1A\u66F4\u65B0\u73B0\u6709\u98DE\u4E66\u5E94\u7528\uFF0C\u53EA\u589E\u91CF\u5F00\u901A\u201C\u83B7\u53D6\u7FA4\u7EC4\u4E2D\u6240\u6709\u6D88\u606F\u201D\u6743\u9650\uFF1B\u4E0D\u4F1A\u521B\u5EFA\u65B0\u5E94\u7528\u3002\u786E\u8BA4\u540E\u4F1A\u81EA\u52A8\u542F\u7528\u201C\u54CD\u5E94\u6240\u6709\u7FA4\u6D88\u606F\u201D\uFF0C\u5176\u4ED6\u673A\u5668\u4EBA\u4E0D\u53D7\u5F71\u54CD\u3002":"Scanning updates the existing Feishu app with only the \u201CRead all messages in associated group chat\u201D scope. It does not create a new app. After confirmation, \u201CRespond to all group messages\u201D is enabled automatically; other bots are unaffected.","\u6838\u5BF9\u73B0\u6709\u5E94\u7528\uFF0C\u5E76\u786E\u8BA4\u201C\u83B7\u53D6\u7FA4\u7EC4\u4E2D\u6240\u6709\u6D88\u606F\u201D\u6743\u9650":"Review the existing app and confirm the \u201CRead all messages in associated group chat\u201D permission","\u4FDD\u6301\u672C\u9875\u6253\u5F00\uFF0C\u7B49\u5F85\u6743\u9650\u751F\u6548\u5E76\u81EA\u52A8\u5207\u6362\u54CD\u5E94\u65B9\u5F0F":"Keep this page open while the permission takes effect and the response mode switches automatically",\u53D6\u6D88\u6388\u6743:"Cancel authorization","\u5DF2\u786E\u8BA4\uFF0C\u6B63\u5728\u542F\u7528\u5168\u90E8\u6D88\u606F\u6A21\u5F0F":"Confirmed. Enabling all-message mode","\u6743\u9650\u914D\u7F6E\u5DF2\u63D0\u4EA4\uFF0C\u6B63\u5728\u4FDD\u5B58\u8BBE\u7F6E\u5E76\u91CD\u8FDE\u6B64\u673A\u5668\u4EBA\uFF1B\u6B64\u9636\u6BB5\u65E0\u6CD5\u53D6\u6D88\uFF0C\u5176\u4ED6\u673A\u5668\u4EBA\u4E0D\u4F1A\u4E2D\u65AD\u3002":"The permission update was submitted. Saving the setting and reconnecting this bot. This stage cannot be cancelled; other bots will not be interrupted.","\u6743\u9650\u914D\u7F6E\u5DF2\u63D0\u4EA4\uFF0C\u6B63\u5728\u542F\u7528\u5168\u90E8\u6D88\u606F\u6A21\u5F0F\u5E76\u91CD\u8FDE\u6B64\u673A\u5668\u4EBA\uFF1B\u6B64\u9636\u6BB5\u65E0\u6CD5\u53D6\u6D88\uFF0C\u5176\u4ED6\u673A\u5668\u4EBA\u4E0D\u4F1A\u4E2D\u65AD\u3002":"The permission update was submitted. Enabling all-message mode and reconnecting this bot. This stage cannot be cancelled; other bots will not be interrupted.","\u6B63\u5728\u4E3A\u73B0\u6709\u98DE\u4E66\u5E94\u7528\u7533\u8BF7\u7FA4\u6D88\u606F\u6743\u9650\u4E8C\u7EF4\u7801\uFF0C\u8BF7\u7A0D\u5019\u3002":"Requesting a group-message permission QR code for the existing Feishu app\u2026",\u7FA4\u6D88\u606F\u6743\u9650\u6CA1\u6709\u5F00\u901A\u5B8C\u6210:"Group-message permission was not granted","\u626B\u7801\u4F1A\u66F4\u65B0\u73B0\u6709\u98DE\u4E66\u5E94\u7528\uFF0C\u589E\u91CF\u8865\u5145\u5F53\u524D\u7F3A\u5C11\u7684\u5361\u7247\u6309\u94AE\u56DE\u8C03\u3001\u8BFB\u53D6\u7528\u6237\u6D88\u606F\u5185\u56FE\u7247\u6216\u6587\u4EF6\u6240\u9700\u7684 im:message:readonly\uFF08\u98DE\u4E66\u663E\u793A\u4E3A\u201C\u83B7\u53D6\u5355\u804A\u3001\u7FA4\u7EC4\u6D88\u606F\u201D\uFF09\u3001\u4E0A\u4F20\u673A\u5668\u4EBA\u56FE\u7247\u6216\u6587\u4EF6\u6240\u9700\u7684 im:resource\uFF0C\u4EE5\u53CA\u539F\u751F\u547D\u4EE4\u9762\u677F\u6240\u9700\u7684 application:app_slash_command:read / write\uFF1B\u4E0D\u4F1A\u521B\u5EFA\u65B0\u5E94\u7528\u3002\u786E\u8BA4\u9875\u53EA\u663E\u793A\u5F53\u524D\u7F3A\u5C11\u9879\uFF0C\u5B8C\u6210\u540E\u6B64\u673A\u5668\u4EBA\u4F1A\u77ED\u6682\u91CD\u8FDE\uFF0C\u5176\u4ED6\u673A\u5668\u4EBA\u4E0D\u53D7\u5F71\u54CD\u3002":"Scanning updates the existing Feishu app with the missing card-button callback, im:message:readonly for reading images or files in user messages (shown by Feishu as \u201CRead direct and group messages\u201D), im:resource for uploading images or files sent by the bot, and application:app_slash_command:read / write for the native command panel. It does not create a new app. The confirmation page shows only missing items; this bot reconnects briefly afterward, while other bots are unaffected.","\u6838\u5BF9\u73B0\u6709\u5E94\u7528\u540D\u79F0\uFF0C\u5E76\u786E\u8BA4\u53EA\u65B0\u589E\u5F53\u524D\u7F3A\u5C11\u7684\u4E0A\u8FF0\u914D\u7F6E":"Review the existing app name and confirm that only the missing items described above are added","\u4FDD\u6301\u672C\u9875\u6253\u5F00\uFF0C\u7B49\u5F85\u6743\u9650\u4E0E\u56DE\u8C03\u8865\u5168\u5B8C\u6210":"Keep this page open until permissions and the callback are complete",\u53D6\u6D88\u8865\u5168:"Cancel setup","\u5DF2\u786E\u8BA4\uFF0C\u6B63\u5728\u5B8C\u6210\u6743\u9650\u4E0E\u56DE\u8C03\u914D\u7F6E":"Confirmed. Completing permissions and callback setup",\u6B63\u5728\u51C6\u5907\u6743\u9650\u8865\u5168\u4E8C\u7EF4\u7801:"Preparing the permission-completion QR code","\u914D\u7F6E\u5DF2\u63D0\u4EA4\uFF0C\u6B63\u5728\u4FDD\u5B58\u6743\u9650\u3001\u9A8C\u8BC1\u5361\u7247\u56DE\u8C03\u5E76\u91CD\u8FDE\u6B64\u673A\u5668\u4EBA\uFF1B\u6B64\u9636\u6BB5\u65E0\u6CD5\u53D6\u6D88\uFF0C\u5176\u4ED6\u673A\u5668\u4EBA\u4E0D\u4F1A\u4E2D\u65AD\u3002":"The update was submitted. Saving permissions, verifying the card callback, and reconnecting this bot. This stage cannot be cancelled; other bots will not be interrupted.","\u6B63\u5728\u4E3A\u73B0\u6709\u98DE\u4E66\u5E94\u7528\u7533\u8BF7\u4E00\u6B21\u6027\u66F4\u65B0\u4E8C\u7EF4\u7801\uFF0C\u8BF7\u7A0D\u5019\u3002":"Requesting a one-time update QR code for the existing Feishu app\u2026",\u6743\u9650\u4E0E\u56DE\u8C03\u6CA1\u6709\u8865\u5168\u5B8C\u6210:"Permissions and callback setup did not finish",\u8865\u5168\u6743\u9650:"Complete permissions",\u8865\u5168\u8303\u56F4:"Completion scope","\u589E\u91CF\u6DFB\u52A0\u5F53\u524D\u7F3A\u5C11\u7684\u5361\u7247\u56DE\u8C03 card.action.trigger\u3001\u8BFB\u53D6\u6D88\u606F\u5185\u56FE\u7247\u6216\u6587\u4EF6\u6240\u9700\u7684 im:message:readonly\uFF08\u98DE\u4E66\u663E\u793A\u4E3A\u201C\u83B7\u53D6\u5355\u804A\u3001\u7FA4\u7EC4\u6D88\u606F\u201D\uFF09\u3001\u4E0A\u4F20\u673A\u5668\u4EBA\u56FE\u7247\u6216\u6587\u4EF6\u6240\u9700\u7684 im:resource\uFF0C\u4EE5\u53CA\u539F\u751F\u547D\u4EE4\u9762\u677F\u6240\u9700\u7684 application:app_slash_command:read / write\uFF1B\u786E\u8BA4\u9875\u53EA\u663E\u793A\u5F53\u524D\u7F3A\u5C11\u9879\uFF0C\u4E0D\u4F1A\u521B\u5EFA\u65B0\u5E94\u7528\u3002":"Adds the missing card callback card.action.trigger, im:message:readonly for reading images or files in messages (shown by Feishu as \u201CRead direct and group messages\u201D), im:resource for uploading images or files sent by the bot, and application:app_slash_command:read / write for the native command panel. The confirmation page shows only missing items; no new app is created.","\u7B49\u5F85\u626B\u7801\u2026":"Waiting for scan\u2026",\u98DE\u4E66\u670D\u52A1\u8FD4\u56DE\u4E86\u4E0D\u5339\u914D\u7684\u6743\u9650\u8865\u5168\u4E8C\u7EF4\u7801:"Feishu returned a permission-completion QR code for a different bot",\u98DE\u4E66\u670D\u52A1\u8FD4\u56DE\u4E86\u4E0D\u5339\u914D\u7684\u7FA4\u6D88\u606F\u6743\u9650\u4E8C\u7EF4\u7801:"Feishu returned a group-message permission QR code for a different bot","\u98DE\u4E66\u670D\u52A1\u8FD4\u56DE\u7684\u4FEE\u590D\u4FE1\u606F\u7F3A\u5C11 botId":"Feishu repair status is missing the bot ID","\u98DE\u4E66\u670D\u52A1\u8FD4\u56DE\u7684\u5E94\u7528\u66F4\u65B0\u4FE1\u606F\u7F3A\u5C11 botId":"Feishu app-update status is missing the bot ID",\u98DE\u4E66\u670D\u52A1\u8FD4\u56DE\u4E86\u4E0D\u5339\u914D\u7684\u6CE8\u518C\u8FDB\u5EA6:"Feishu returned registration progress for a different operation",\u6B64\u673A\u5668\u4EBA:"this bot","\u7528\u4E8E\u4E3A${botName}\u5F00\u901A\u7FA4\u6D88\u606F\u6743\u9650\u7684\u4E00\u6B21\u6027\u6388\u6743\u4E8C\u7EF4\u7801":"One-time QR code for granting group-message permission to ${botName}","\u6B63\u5728\u4E3A\u300C${botName}\u300D\u5F00\u901A\u7FA4\u6D88\u606F\u6743\u9650":"Granting group-message permission to \u201C${botName}\u201D",'${botName ?? "\u673A\u5668\u4EBA"}\u7684\u6743\u9650\u8865\u5168\u4E8C\u7EF4\u7801\u5DF2\u751F\u6210\uFF0C\u8BF7\u4F7F\u7528\u98DE\u4E66\u626B\u7801\u3002':'Permission-completion QR code generated for ${botName ?? "bot"}. Scan it with Feishu.','${botName ?? "\u673A\u5668\u4EBA"}\u7684\u7FA4\u6D88\u606F\u6743\u9650\u4E8C\u7EF4\u7801\u5DF2\u751F\u6210\uFF0C\u8BF7\u4F7F\u7528\u98DE\u4E66\u786E\u8BA4\u3002':'Group-message permission QR code generated for ${botName ?? "bot"}. Confirm it with Feishu.',"${targetBotName}\u5DF2\u5F00\u901A\u7FA4\u6D88\u606F\u6743\u9650\uFF0C\u5E76\u542F\u7528\u201C\u54CD\u5E94\u6240\u6709\u7FA4\u6D88\u606F\u201D\u3002":"${targetBotName} now has group-message permission and \u201CRespond to all group messages\u201D is enabled.","${targetBot.bot.name}\u5DF2\u5F00\u901A\u7FA4\u6D88\u606F\u6743\u9650\uFF0C\u5E76\u542F\u7528\u201C\u54CD\u5E94\u6240\u6709\u7FA4\u6D88\u606F\u201D\u3002":"${targetBot.bot.name} now has group-message permission and \u201CRespond to all group messages\u201D is enabled.","${targetBot.bot.name}\u5DF2\u8FDE\u63A5\uFF0C\u53EF\u4EE5\u5728\u98DE\u4E66\u4E2D\u5F00\u59CB\u804A\u5929\u3002":"${targetBot.bot.name} is connected and ready to chat in Feishu.","\u5DF2\u53D6\u6D88\u8865\u5168\u6743\u9650\u4E0E\u56DE\u8C03\u3002":"Completing permissions and the callback was cancelled.","\u5DF2\u53D6\u6D88\u7FA4\u6D88\u606F\u6743\u9650\u6388\u6743\u3002":"Group-message permission authorization was cancelled.","\u6743\u9650\u4E0E\u56DE\u8C03\u5DF2\u66F4\u65B0\uFF0C\u4F46\u6682\u65F6\u65E0\u6CD5\u786E\u8BA4\u673A\u5668\u4EBA\u8FDE\u63A5\u72B6\u6001":"Permissions and the callback were updated, but the bot connection could not be confirmed yet","\u7FA4\u6D88\u606F\u6743\u9650\u5DF2\u66F4\u65B0\uFF0C\u4F46\u6682\u65F6\u65E0\u6CD5\u786E\u8BA4\u673A\u5668\u4EBA\u8FDE\u63A5\u72B6\u6001":"The group-message permission was updated, but the bot connection could not be confirmed yet",\u98DE\u4E66\u6743\u9650\u4E0E\u56DE\u8C03\u8865\u5168\u5931\u8D25:"Could not complete Feishu permissions and callback setup",\u98DE\u4E66\u7FA4\u6D88\u606F\u6743\u9650\u5F00\u901A\u5931\u8D25:"Could not grant the Feishu group-message permission","\u8BF7\u5148\u5B8C\u6210\u5F53\u524D\u98DE\u4E66\u6388\u6743\u64CD\u4F5C\uFF0C\u518D\u5F00\u901A\u7FA4\u6D88\u606F\u6743\u9650\u3002":"Finish the current Feishu authorization before granting group-message permission.","\u5DF2\u786E\u8BA4\uFF0C\u6B63\u5728\u8FDE\u63A5\u65B0\u673A\u5668\u4EBA":"Confirmed. Connecting the new bot","\u6B63\u5728\u5B89\u5168\u4FDD\u5B58\u51ED\u636E\u5E76\u68C0\u67E5\u65B0\u673A\u5668\u4EBA\u7684\u6D88\u606F\u901A\u9053\uFF0C\u5176\u4ED6\u673A\u5668\u4EBA\u4E0D\u4F1A\u4E2D\u65AD\u3002":"Saving credentials and checking the new bot connection. Existing bots will not be interrupted.","\u6B63\u5728\u5411\u98DE\u4E66\u7533\u8BF7\u4E00\u6B21\u6027\u6388\u6743\u4E8C\u7EF4\u7801\uFF0C\u8BF7\u7A0D\u5019\u3002":"Requesting a one-time authorization QR code from Feishu\u2026",\u65B0\u673A\u5668\u4EBA\u6CA1\u6709\u6DFB\u52A0\u5B8C\u6210:"The new bot was not added","\u65B0\u98DE\u4E66\u673A\u5668\u4EBA\u5DF2\u8FDE\u63A5\uFF0C\u53EF\u4EE5\u5F00\u59CB\u804A\u5929\u3002":"The new Feishu bot is connected and ready to chat.",\u98DE\u4E66\u5E94\u7528\u521B\u5EFA\u5931\u8D25:"Could not create the Feishu app","\u673A\u5668\u4EBA\u5DF2\u7ECF\u521B\u5EFA\uFF0C\u4F46\u6682\u65F6\u65E0\u6CD5\u786E\u8BA4\u8FDE\u63A5\u72B6\u6001":"The bot was created, but its connection could not be confirmed yet",\u673A\u5668\u4EBA\u4ECD\u672A\u8FDE\u63A5:"The bot is still offline",\u673A\u5668\u4EBA\u5C1A\u672A\u8FDE\u63A5:"The bot is not connected yet",\u957F\u8FDE\u63A5\u8FD0\u884C\u6B63\u5E38:"Persistent connection is healthy",\u957F\u8FDE\u63A5:"Persistent connection",\u5E94\u7528\u6807\u8BC6\u5DF2\u5B89\u5168\u4FDD\u5B58:"App identifier stored securely",\u673A\u5668\u4EBA\u6807\u8BC6\u5DF2\u5B89\u5168\u4FDD\u5B58:"Bot identifier stored securely",\u5DF2\u5B89\u5168\u4FDD\u5B58:"Stored securely",\u5DF2\u63A5\u5165\u7684\u5FAE\u4FE1\u8D26\u53F7:"Connected WeChat accounts",\u5DF2\u63A5\u5165\u7684\u673A\u5668\u4EBA:"Connected bots",\u5DF2\u63A5\u5165\u7684\u9489\u9489\u673A\u5668\u4EBA:"Connected DingTalk bots",\u5DF2\u7ED1\u5B9A\u7684\u4F01\u4E1A\u5FAE\u4FE1\u673A\u5668\u4EBA:"Connected WeCom bots","\u5DF2\u7ED1\u5B9A\u7684 QQ \u673A\u5668\u4EBA":"Connected QQ bots","\u5DF2\u63A5\u5165\u7684 WhatsApp \u673A\u5668\u4EBA":"Connected WhatsApp accounts",\u4F7F\u7528\u624B\u673A\u5FAE\u4FE1\u626B\u63CF\u4E8C\u7EF4\u7801:"Scan with WeChat on your phone","\u626B\u4E00\u6B21\u7801\uFF0C\u5C31\u80FD\u5728\u5FAE\u4FE1\u91CC\u4F7F\u7528 Harness":"Scan once to use Harness in WeChat",\u6253\u5F00\u624B\u673A\u5FAE\u4FE1\u5E76\u626B\u63CF\u5DE6\u4FA7\u4E8C\u7EF4\u7801:"Open WeChat on your phone and scan the QR code",\u5728\u5FAE\u4FE1\u4E2D\u786E\u8BA4\u8FDE\u63A5\u8BE5\u673A\u5668\u4EBA:"Confirm the bot connection in WeChat","\u4FDD\u6301\u672C\u9875\u6253\u5F00\uFF0C\u7B49\u5F85\u673A\u5668\u4EBA\u81EA\u52A8\u8FDE\u63A5":"Keep this page open while the bot connects",\u7B49\u5F85\u5FAE\u4FE1\u626B\u7801:"Waiting for WeChat scan",\u9700\u8981\u914D\u5BF9\u7801:"Pairing code required",\u8F93\u5165\u624B\u673A\u5FAE\u4FE1\u663E\u793A\u7684\u6570\u5B57:"Enter the number shown in WeChat",\u5FAE\u4FE1\u914D\u5BF9\u7801:"WeChat pairing code","\u5DF2\u626B\u7801\uFF0C\u8BF7\u5728\u624B\u673A\u4E0A\u786E\u8BA4":"Scanned. Confirm on your phone","\u914D\u5BF9\u7801\u5DF2\u63D0\u4EA4\uFF0C\u6B63\u5728\u7B49\u5F85\u5FAE\u4FE1\u786E\u8BA4\u3002":"Pairing code submitted. Waiting for WeChat confirmation.","\u8FD9\u662F\u5FAE\u4FE1\u9644\u52A0\u7684\u5B89\u5168\u786E\u8BA4\u6B65\u9AA4\u3002\u914D\u5BF9\u7801\u53EA\u7528\u4E8E\u672C\u6B21\u626B\u7801\u8F6E\u8BE2\uFF0C\u4E0D\u4F1A\u5199\u5165\u914D\u7F6E\u6216\u65E5\u5FD7\u3002":"This is an additional WeChat confirmation step. The pairing code is used only for this connection and is never stored.","\u6B63\u5728\u4FDD\u5B58\u51ED\u636E\u5E76\u9A8C\u8BC1 Harness \u4E0E\u5FAE\u4FE1\u957F\u8F6E\u8BE2\u3002":"Saving credentials and verifying the WeChat connection.","\u5FAE\u4FE1\u5DF2\u786E\u8BA4\uFF0C\u6B63\u5728\u542F\u52A8\u6D88\u606F\u8FDE\u63A5":"Confirmed in WeChat. Starting the message connection","\u5FAE\u4FE1\u5DF2\u6388\u6743\uFF0C\u4F46\u65E0\u6CD5\u8BFB\u53D6\u73B0\u6709\u767B\u5F55\u51ED\u636E\u3002\u8BF7\u68C0\u67E5 DSH \u51ED\u636E\u5B58\u50A8\u3002":"WeChat was authorized, but the existing login credential could not be read. Check the DSH credential store.","\u5FAE\u4FE1\u5DF2\u6388\u6743\uFF0C\u4F46\u767B\u5F55\u51ED\u636E\u65E0\u6CD5\u5199\u5165 DSH \u51ED\u636E\u5B58\u50A8\u3002\u8BF7\u68C0\u67E5\u51ED\u636E\u5B58\u50A8\u662F\u5426\u53EF\u5199\u3002":"WeChat was authorized, but the login credential could not be written to the DSH credential store. Check that the store is writable.","\u5FAE\u4FE1\u5DF2\u6388\u6743\uFF0C\u4F46\u8D26\u53F7\u914D\u7F6E\u65E0\u6CD5\u5199\u5165\u672C\u673A\u3002\u8BF7\u68C0\u67E5 DSH_HOME \u76EE\u5F55\u6743\u9650\u3002":"WeChat was authorized, but the account configuration could not be saved locally. Check the DSH_HOME directory permissions.","\u5FAE\u4FE1\u5DF2\u6388\u6743\uFF0C\u4F46\u65E0\u6CD5\u521D\u59CB\u5316\u8D26\u53F7\u72B6\u6001\u6216\u5DE5\u4F5C\u533A\u3002\u8BF7\u68C0\u67E5 DSH_HOME \u548C\u5DE5\u4F5C\u533A\u76EE\u5F55\u3002":"WeChat was authorized, but the account state or workspace could not be initialized. Check DSH_HOME and the workspace directory.","\u5FAE\u4FE1\u5DF2\u6388\u6743\uFF0C\u4F46\u63D2\u4EF6\u65E0\u6CD5\u8FDE\u63A5\u672C\u673A Harness\u3002\u8BF7\u68C0\u67E5 dsh web \u5730\u5740\u548C\u7AEF\u53E3\u3002":"WeChat was authorized, but the plugin could not connect to the local Harness. Check the dsh web address and port.","\u5FAE\u4FE1\u5DF2\u6388\u6743\uFF0C\u4F46 Harness \u5065\u5EB7\u68C0\u67E5\u8D85\u65F6\u3002\u8BF7\u786E\u8BA4 dsh web \u672A\u963B\u585E\u3002":"WeChat was authorized, but the Harness health check timed out. Confirm that dsh web is not blocked.","\u5FAE\u4FE1\u5DF2\u6388\u6743\uFF0C\u4F46 Harness \u62D2\u7EDD\u4E86\u672C\u673A\u5065\u5EB7\u68C0\u67E5\u3002\u8BF7\u68C0\u67E5 Host \u4FE1\u4EFB\u914D\u7F6E\u3002":"WeChat was authorized, but Harness denied the local health check. Check the Host trust configuration.","\u5FAE\u4FE1\u5DF2\u6388\u6743\uFF0C\u4F46\u627E\u4E0D\u5230 Harness \u5065\u5EB7\u68C0\u67E5\u63A5\u53E3\u3002\u8BF7\u786E\u8BA4 Harness \u4E0E\u63D2\u4EF6\u7248\u672C\u517C\u5BB9\u3002":"WeChat was authorized, but the Harness health endpoint was not found. Confirm that Harness and the plugin are compatible.","\u5FAE\u4FE1\u5DF2\u6388\u6743\uFF0C\u4F46 Harness \u5065\u5EB7\u68C0\u67E5\u8FD4\u56DE\u670D\u52A1\u9519\u8BEF\u3002\u8BF7\u67E5\u770B dsh web \u65E5\u5FD7\u3002":"WeChat was authorized, but the Harness health check returned a service error. Check the dsh web logs.","\u5FAE\u4FE1\u5DF2\u6388\u6743\uFF0C\u4F46 Harness \u8FD4\u56DE\u4E86\u65E0\u6CD5\u8BC6\u522B\u7684\u54CD\u5E94\u3002\u8BF7\u786E\u8BA4 Harness \u4E0E\u63D2\u4EF6\u7248\u672C\u517C\u5BB9\u3002":"WeChat was authorized, but Harness returned an unrecognized response. Confirm that Harness and the plugin are compatible.","\u5FAE\u4FE1\u5DF2\u6388\u6743\uFF0C\u4F46 Harness \u62D2\u7EDD\u4E86\u5065\u5EB7\u68C0\u67E5\u8BF7\u6C42\u3002\u8BF7\u67E5\u770B dsh web \u65E5\u5FD7\u3002":"WeChat was authorized, but Harness rejected the health-check request. Check the dsh web logs.","\u5FAE\u4FE1\u5DF2\u6388\u6743\uFF0C\u4F46 Harness \u5065\u5EB7\u68C0\u67E5\u53D1\u751F\u672A\u77E5\u9519\u8BEF\u3002\u8BF7\u67E5\u770B dsh web \u65E5\u5FD7\u3002":"WeChat was authorized, but the Harness health check failed unexpectedly. Check the dsh web logs.","\u5FAE\u4FE1\u5DF2\u6388\u6743\uFF0C\u4F46\u6D88\u606F\u8FDE\u63A5\u521D\u59CB\u5316\u5931\u8D25\u3002\u8BF7\u67E5\u770B dsh web \u65E5\u5FD7\u540E\u91CD\u8BD5\u3002":"WeChat was authorized, but the message connection could not be initialized. Check the dsh web logs and try again.","\u5FAE\u4FE1\u5DF2\u6388\u6743\uFF0C\u4F46\u6FC0\u6D3B\u8FC7\u7A0B\u4E2D\u53D1\u751F\u672A\u77E5\u9519\u8BEF\u3002\u8BF7\u67E5\u770B dsh web \u65E5\u5FD7\u3002":"WeChat was authorized, but an unknown error occurred during activation. Check the dsh web logs.","\u5FAE\u4FE1\u5DF2\u7ED1\u5B9A\uFF0C\u53EF\u4EE5\u5F00\u59CB\u5411\u5DF2\u7ED1\u5B9A\u7684\u673A\u5668\u4EBA\u53D1\u6D88\u606F\u3002":"WeChat is connected and ready for messages.","\u8FD9\u4E2A\u5FAE\u4FE1\u8D26\u53F7\u5DF2\u7ECF\u7ED1\u5B9A\u5E76\u4FDD\u6301\u5728\u7EBF\u3002":"This WeChat account is connected and online.","\u5FAE\u4FE1\u8D26\u53F7\u53CA\u672C\u673A\u51ED\u636E\u5DF2\u79FB\u9664\u3002":"The WeChat account and local credentials were removed.","\u5DF2\u53D6\u6D88\u5FAE\u4FE1\u7ED1\u5B9A\u3002":"WeChat setup was cancelled.","\u6B63\u5728\u8054\u7CFB\u817E\u8BAF\u5FAE\u4FE1 iLink \u670D\u52A1\u3002":"Contacting the WeChat iLink service.","iLink \u957F\u8F6E\u8BE2":"iLink long polling","\u626B\u4E00\u6B21\u7801\uFF0C\u81EA\u52A8\u521B\u5EFA\u5E76\u8FDE\u63A5\u673A\u5668\u4EBA":"Scan once to create and connect a bot","\u4F7F\u7528\u9489\u9489 App \u5B8C\u6210\u673A\u5668\u4EBA\u6388\u6743":"Authorize the bot with the DingTalk app","\u4F7F\u7528\u5DF2\u52A0\u5165\u4F01\u4E1A/\u7EC4\u7EC7\u7684\u9489\u9489\u8D26\u53F7\u626B\u63CF\u5DE6\u4FA7\u4E8C\u7EF4\u7801":"Scan the QR code with a DingTalk account that belongs to an organization","\u5728\u6388\u6743\u9875\u70B9\u51FB\u201C\u4E00\u952E\u521B\u5EFA\u65B0\u673A\u5668\u4EBA\u201D":"Select \u201CCreate new bot\u201D on the authorization page","\u8BF7\u52FF\u5173\u95ED\u672C\u9875\uFF0C\u9489\u9489\u5B8C\u6210\u6388\u6743\u540E\u5C06\u81EA\u52A8\u7EE7\u7EED\u3002":"Keep this page open. Setup will continue after DingTalk authorization.",\u7B49\u5F85\u9489\u9489\u626B\u7801\u6388\u6743:"Waiting for DingTalk authorization","\u6388\u6743\u5DF2\u786E\u8BA4\uFF0C\u6B63\u5728\u521B\u5EFA\u9489\u9489\u673A\u5668\u4EBA":"Authorized. Creating the DingTalk bot",\u6B63\u5728\u786E\u8BA4\u9489\u9489\u6388\u6743:"Confirming DingTalk authorization","\u6B63\u5728\u68C0\u67E5\u9489\u9489 Stream \u957F\u8FDE\u63A5\uFF0C\u6210\u529F\u540E\u4F1A\u81EA\u52A8\u663E\u793A\u4E3A\u5728\u7EBF\u3002":"Checking the DingTalk Stream connection. It will appear online when ready.","\u9489\u9489\u673A\u5668\u4EBA\u5DF2\u63A5\u5165\uFF0C\u53EF\u4EE5\u5F00\u59CB\u53D1\u9001\u6D88\u606F\u3002":"The DingTalk bot is connected and ready for messages.","\u8FD9\u4E2A\u9489\u9489\u673A\u5668\u4EBA\u5DF2\u7ECF\u63A5\u5165\u5E76\u4FDD\u6301\u5728\u7EBF\u3002":"This DingTalk bot is connected and online.","Stream \u957F\u8FDE\u63A5":"Stream persistent connection","\u4F7F\u7528\u4F01\u4E1A\u5FAE\u4FE1 App \u626B\u7801\u521B\u5EFA\u667A\u80FD\u673A\u5668\u4EBA":"Scan with WeCom to create an AI bot","\u4F7F\u7528\u4F01\u4E1A\u5FAE\u4FE1 App \u5B8C\u6210\u667A\u80FD\u673A\u5668\u4EBA\u6388\u6743":"Authorize the AI bot with WeCom","\u6253\u5F00\u4F01\u4E1A\u5FAE\u4FE1 App\uFF0C\u626B\u63CF\u5DE6\u4FA7\u4E8C\u7EF4\u7801":"Open WeCom and scan the QR code",\u5728\u817E\u8BAF\u6388\u6743\u9875\u9762\u786E\u8BA4\u521B\u5EFA\u667A\u80FD\u673A\u5668\u4EBA:"Confirm bot creation on the Tencent authorization page",\u8FD4\u56DE\u8FD9\u91CC\u7B49\u5F85\u8FDE\u63A5\u5B8C\u6210:"Return here and wait for the connection to complete","\u7B49\u5F85\u4F01\u4E1A\u5FAE\u4FE1 App \u626B\u7801":"Waiting for WeCom scan","\u4F01\u4E1A\u5FAE\u4FE1\u5DF2\u6388\u6743\uFF0C\u6B63\u5728\u8FDE\u63A5\u673A\u5668\u4EBA":"Authorized in WeCom. Connecting the bot","\u51ED\u636E\u6B63\u5728\u5199\u5165\u672C\u673A\uFF0C\u5E76\u542F\u52A8\u4F01\u4E1A\u5FAE\u4FE1 WebSocket \u6D88\u606F\u8FDE\u63A5\u3002":"Saving credentials locally and starting the WeCom WebSocket connection.","WebSocket \u957F\u8FDE\u63A5":"WebSocket persistent connection","\u4F7F\u7528\u624B\u673A QQ \u626B\u7801\u521B\u5EFA\u5E76\u7ED1\u5B9A\u673A\u5668\u4EBA":"Scan with mobile QQ to create and connect a bot","\u4F7F\u7528\u624B\u673A QQ \u5B8C\u6210\u673A\u5668\u4EBA\u7ED1\u5B9A":"Complete bot setup with mobile QQ","\u6253\u5F00\u624B\u673A QQ\uFF0C\u626B\u63CF\u5DE6\u4FA7\u4E8C\u7EF4\u7801":"Open mobile QQ and scan the QR code",\u5728\u817E\u8BAF\u6388\u6743\u9875\u9762\u786E\u8BA4\u521B\u5EFA\u6216\u7ED1\u5B9A\u673A\u5668\u4EBA:"Confirm bot creation or connection on the Tencent authorization page","\u7B49\u5F85\u624B\u673A QQ \u626B\u7801":"Waiting for mobile QQ scan","QQ \u5DF2\u6388\u6743\uFF0C\u6B63\u5728\u8FDE\u63A5\u673A\u5668\u4EBA":"Authorized in QQ. Connecting the bot","\u51ED\u636E\u6B63\u5728\u5199\u5165\u672C\u673A\uFF0C\u5E76\u542F\u52A8 QQ WebSocket \u6D88\u606F\u8FDE\u63A5\u3002":"Saving credentials locally and starting the QQ WebSocket connection.","\u4F7F\u7528\u624B\u673A WhatsApp \u626B\u63CF\u4E8C\u7EF4\u7801\u5373\u53EF\u63A5\u5165\u3002":"Scan the QR code with WhatsApp to connect.","\u7528\u624B\u673A WhatsApp \u626B\u63CF\u4E8C\u7EF4\u7801":"Scan with WhatsApp on your phone","\u6253\u5F00 WhatsApp \u2192 \u8BBE\u7F6E \u2192 \u5DF2\u5173\u8054\u8BBE\u5907":"Open WhatsApp \u2192 Settings \u2192 Linked devices","\u70B9\u51FB\u201C\u5173\u8054\u8BBE\u5907\u201D\u5E76\u626B\u63CF\u5DE6\u4FA7\u4E8C\u7EF4\u7801":"Select \u201CLink a device\u201D and scan the QR code","\u7B49\u5F85 WhatsApp \u626B\u7801":"Waiting for WhatsApp scan","\u5DF2\u626B\u7801\uFF0C\u6B63\u5728\u8FDE\u63A5 WhatsApp":"Scanned. Connecting WhatsApp","\u6B63\u5728\u5EFA\u7ACB\u5B89\u5168\u7684\u5173\u8054\u8BBE\u5907\u4F1A\u8BDD\u3002":"Creating a secure linked-device session.","\u5173\u8054\u8BBE\u5907\u6B63\u5728\u63A5\u5165 DeepSeek Harness\u3002":"Linking the device to DeepSeek Harness.","WhatsApp Web \u5173\u8054\u8BBE\u5907\u8FD0\u884C\u6B63\u5E38":"WhatsApp linked device is healthy","\u67E5\u770B WhatsApp \u8BBF\u95EE\u6A21\u5F0F\u8BF4\u660E":"View WhatsApp access mode details","WhatsApp \u8BBF\u95EE\u6A21\u5F0F":"WhatsApp access mode",\u4EC5\u81EA\u5DF1\u6A21\u5F0F:"Only me",\u6307\u5B9A\u8054\u7CFB\u4EBA\u6A21\u5F0F:"Selected contacts",\u5F00\u653E\u54CD\u5E94\u6A21\u5F0F:"Open responses","\u4EC5\u81EA\u5DF1\u6A21\u5F0F\uFF08\u9ED8\u8BA4\uFF09":"Only me (default)","\u5DF2\u751F\u6548\uFF1A":"Active: ","\u53EA\u54CD\u5E94\u5DF2\u7ED1\u5B9A WhatsApp \u8D26\u53F7\u7684\u81EA\u804A\u6D88\u606F\u3002":"Only respond to self-chat messages from the linked WhatsApp account.","\u54CD\u5E94\u81EA\u804A\u548C\u767D\u540D\u5355\u8054\u7CFB\u4EBA\u7684\u79C1\u804A\uFF0C\u5FFD\u7565\u7FA4\u804A\u3002":"Respond to self-chat and allowlisted direct messages; ignore group messages.","\u54CD\u5E94\u6240\u6709\u79C1\u804A\u3001\u5DF2\u7ED1\u5B9A\u8D26\u53F7\u81EA\u5DF1\u53D1\u51FA\u7684\u7FA4\u804A\u6D88\u606F\uFF0C\u4EE5\u53CA\u5176\u4ED6\u7FA4\u6210\u5458\u7684\u63D0\u53CA\u6216\u56DE\u590D\u3002":"Respond to all direct messages, group messages sent by the linked account, and mentions or replies from other group members.","\u5141\u8BB8\u79C1\u804A\u7684 WhatsApp \u7535\u8BDD\u53F7\u7801":"WhatsApp phone numbers allowed to send direct messages",\u6BCF\u884C\u4E00\u4E2A\u542B\u56FD\u5BB6\u6216\u5730\u533A\u4EE3\u7801\u7684\u53F7\u7801:"One number with country or region code per line","\u53EF\u4EE5\u5305\u542B\u5F00\u5934\u7684 +\uFF0C\u4FDD\u5B58\u65F6\u4F1A\u81EA\u52A8\u79FB\u9664\u3002":"A leading + is allowed and removed when saved.","\u4EC5\u6307\u5B9A\u8054\u7CFB\u4EBA\u6A21\u5F0F\u4F7F\u7528\u767D\u540D\u5355\uFF0C\u5207\u6362\u6A21\u5F0F\u65F6\u4F1A\u4FDD\u7559\u3002":"Only Selected contacts uses the allowlist; it is retained when modes change.","\u767D\u540D\u5355\u4E3A\u7A7A\uFF1B\u4FDD\u5B58\u540E\u5C06\u53EA\u63A5\u53D7\u81EA\u804A\u6D88\u606F\u3002":"The allowlist is empty; only self-chat messages will be accepted after saving.","\u7535\u8BDD\u53F7\u7801\u5FC5\u987B\u5305\u542B\u56FD\u5BB6\u6216\u5730\u533A\u4EE3\u7801\uFF0C\u6BCF\u884C\u4E00\u4E2A\u3002":"Each phone number must include a country or region code on its own line.","WhatsApp \u8BBF\u95EE\u8BBE\u7F6E\u6682\u4E0D\u53EF\u7528\u3002":"WhatsApp access settings are currently unavailable.","WhatsApp \u8BBF\u95EE\u8BBE\u7F6E\u4FDD\u5B58\u5931\u8D25\u3002":"Could not save WhatsApp access settings.","Bot API \u957F\u8F6E\u8BE2":"Bot API long polling"," Gateway \u957F\u8FDE\u63A5":" Gateway persistent connection","Gateway \u957F\u8FDE\u63A5":"Gateway persistent connection"," Socket Mode \u957F\u8FDE\u63A5":" Socket Mode persistent connection","Socket Mode \u957F\u8FDE\u63A5":"Socket Mode persistent connection","\u63A5\u5165 Telegram \u673A\u5668\u4EBA":"Connect a Telegram bot","\u5148\u901A\u8FC7 @BotFather \u83B7\u53D6 Bot Token\uFF0C\u518D\u5728\u8FD9\u91CC\u5B8C\u6210\u63A5\u5165\u3002":"Get a Bot Token from @BotFather, then connect it here.","\u586B\u5199 @BotFather \u751F\u6210\u7684 Bot Token":"Enter the Bot Token from @BotFather",\u8BBF\u95EE\u6A21\u5F0F:"Access mode","Telegram \u8BBF\u95EE\u6A21\u5F0F":"Telegram access mode","\u67E5\u770B Telegram \u8BBF\u95EE\u6A21\u5F0F\u8BF4\u660E":"View Telegram access mode details","\u7FA4\u804A\u5168\u90E8\u5FFD\u7565\uFF0C\u79C1\u804A\u4EC5\u5141\u8BB8\u767D\u540D\u5355\u7528\u6237\u3002":"All group messages are ignored; only allowlisted users may send DMs.","\u4FDD\u6301\u539F\u6709\u884C\u4E3A\uFF1A\u79C1\u804A\u76F4\u63A5\u54CD\u5E94\uFF0C\u7FA4\u804A\u5728\u88AB\u63D0\u53CA\u6216\u56DE\u590D\u65F6\u54CD\u5E94\u3002":"Keep the original behavior: respond to DMs and to group mentions or replies.",\u5B89\u5168\u6A21\u5F0F:"Safe mode",\u517C\u5BB9\u6A21\u5F0F:"Compatible mode","\u5DF2\u751F\u6548\uFF1A\u5B89\u5168\u6A21\u5F0F":"Active: Safe mode","\u5DF2\u751F\u6548\uFF1A\u517C\u5BB9\u6A21\u5F0F":"Active: Compatible mode",\u6A21\u5F0F:"Mode","\u517C\u5BB9\u6A21\u5F0F\uFF08\u9ED8\u8BA4\uFF09":"Compatible mode (default)","\u5B89\u5168\u6A21\u5F0F\uFF08\u79C1\u804A\u767D\u540D\u5355\uFF09":"Safe mode (private-chat allowlist)","\u5141\u8BB8\u79C1\u804A\u7684 Telegram User ID":"Telegram User IDs allowed to send DMs","\u6BCF\u884C\u4E00\u4E2A\u6570\u5B57 User ID":"One numeric User ID per line","\u767D\u540D\u5355\u4EC5\u5C5E\u4E8E\u5F53\u524D\u673A\u5668\u4EBA\u3002":"This allowlist belongs only to the current bot.","\u517C\u5BB9\u6A21\u5F0F\u4E0B\u6682\u4E0D\u4F7F\u7528\u767D\u540D\u5355\uFF0C\u5207\u6362\u6A21\u5F0F\u65F6\u4F1A\u4FDD\u7559\u3002":"Compatible mode does not enforce the allowlist; it is retained when modes change.","\u767D\u540D\u5355\u4E3A\u7A7A\uFF1B\u4FDD\u5B58\u540E\u8BE5\u673A\u5668\u4EBA\u4F1A\u62D2\u7EDD\u6240\u6709\u5165\u7AD9\u6D88\u606F\u3002":"The allowlist is empty; this bot will reject all inbound messages after saving.","\u6B63\u5728\u4FDD\u5B58\u2026":"Saving\u2026",\u4FDD\u5B58\u8BBF\u95EE\u8BBE\u7F6E:"Save access settings","User ID \u5FC5\u987B\u662F 1\u201316 \u4F4D\u6B63\u6574\u6570\uFF0C\u6BCF\u884C\u4E00\u4E2A\u3002":"Each User ID must be a 1\u201316 digit positive integer on its own line.","Telegram \u8BBF\u95EE\u8BBE\u7F6E\u6682\u4E0D\u53EF\u7528\u3002":"Telegram access settings are currently unavailable.","Telegram \u8BBF\u95EE\u8BBE\u7F6E\u4FDD\u5B58\u5931\u8D25\u3002":"Could not save Telegram access settings.","\u63A5\u5165 Discord \u673A\u5668\u4EBA":"Connect a Discord bot","\u5148\u5728 Developer Portal \u521B\u5EFA Bot \u5E76\u9080\u8BF7\u5230\u670D\u52A1\u5668\uFF0C\u518D\u5728\u8FD9\u91CC\u5B8C\u6210\u63A5\u5165\u3002":"Create a bot in the Developer Portal and invite it to your server, then connect it here.","\u586B\u5199 Discord Developer Portal \u7684 Bot Token":"Enter the Bot Token from the Discord Developer Portal","\u63A5\u5165 Slack \u673A\u5668\u4EBA":"Connect a Slack bot","\u5148\u7528 Manifest \u521B\u5EFA\u5E76\u914D\u7F6E Slack App":"Create and configure a Slack app with the manifest","\u590D\u5236\u914D\u7F6E\u540E\uFF0C\u5728 Slack \u9009\u62E9 From a manifest\uFF1B\u521B\u5EFA\u5B8C\u6210\u540E\u751F\u6210 connections:write App Token\uFF0C\u5E76\u5C06\u5E94\u7528\u5B89\u88C5\u5230\u5DE5\u4F5C\u533A\u3002":"Copy the manifest and choose \u201CFrom a manifest\u201D in Slack. Then create a connections:write App Token and install the app to your workspace.","\u590D\u5236 Manifest":"Copy manifest","\u5DF2\u590D\u5236 Manifest":"Manifest copied","\u6253\u5F00 Slack \u521B\u5EFA\u9875":"Open Slack app creation","Bot Token \u6765\u81EA OAuth & Permissions\uFF1BApp Token \u6765\u81EA Basic Information\uFF0C\u5E76\u4E14\u5FC5\u987B\u5305\u542B connections:write\u3002":"Get the Bot Token from OAuth & Permissions and the App Token from Basic Information. The App Token must include connections:write.","\u4F7F\u7528\u5B98\u65B9 App Manifest \u5FEB\u901F\u914D\u7F6E\u673A\u5668\u4EBA\uFF0C\u518D\u586B\u5199 Bot Token \u4E0E App Token \u5EFA\u7ACB\u672C\u5730 Socket Mode \u8FDE\u63A5\u3002":"Configure the bot with the official app manifest, then enter the Bot Token and App Token to start a local Socket Mode connection.","Slack \u5DE5\u4F5C\u533A":"Slack workspace","Bot Token \u4E0E App Token":"Bot Token and App Token","\u586B\u5199 Bot Token":"Enter Bot Token",\u624B\u52A8\u63A5\u5165\u98DE\u4E66\u673A\u5668\u4EBA:"Connect Feishu bot manually",\u624B\u52A8\u63A5\u5165\u9489\u9489\u673A\u5668\u4EBA:"Connect DingTalk bot manually",\u624B\u52A8\u63A5\u5165\u4F01\u4E1A\u5FAE\u4FE1\u673A\u5668\u4EBA:"Connect WeCom bot manually",\u624B\u52A8\u63A5\u5165QQ\u673A\u5668\u4EBA:"Connect QQ bot manually","\u586B\u5199\u98DE\u4E66\u5F00\u653E\u5E73\u53F0 App ID":"Enter the Feishu Open Platform App ID","\u586B\u5199\u98DE\u4E66\u5F00\u653E\u5E73\u53F0 App Secret":"Enter the Feishu Open Platform App Secret","\u586B\u5199\u9489\u9489\u5E94\u7528 Client ID":"Enter the DingTalk Client ID","\u586B\u5199\u9489\u9489\u5E94\u7528 Client Secret":"Enter the DingTalk Client Secret","\u586B\u5199\u4F01\u4E1A\u5FAE\u4FE1\u667A\u80FD\u673A\u5668\u4EBA Bot ID":"Enter the WeCom AI Bot ID","\u586B\u5199\u4F01\u4E1A\u5FAE\u4FE1\u667A\u80FD\u673A\u5668\u4EBA Secret":"Enter the WeCom AI Bot Secret","\u586B\u5199 QQ \u5F00\u653E\u5E73\u53F0 AppID":"Enter the QQ Open Platform AppID","\u586B\u5199 QQ \u5F00\u653E\u5E73\u53F0 AppSecret":"Enter the QQ Open Platform AppSecret",\u626B\u7801\u63A5\u5165\u5FAE\u4FE1\u673A\u5668\u4EBA:"Connect WeChat bot by QR code",\u626B\u7801\u63A5\u5165\u98DE\u4E66\u673A\u5668\u4EBA:"Connect Feishu bot by QR code",\u626B\u7801\u63A5\u5165\u9489\u9489\u673A\u5668\u4EBA:"Connect DingTalk bot by QR code",\u626B\u7801\u63A5\u5165\u4F01\u4E1A\u5FAE\u4FE1\u673A\u5668\u4EBA:"Connect WeCom bot by QR code","\u626B\u7801\u63A5\u5165 QQ \u673A\u5668\u4EBA":"Connect QQ bot by QR code","\u626B\u7801\u63A5\u5165 WhatsApp \u673A\u5668\u4EBA":"Connect WhatsApp by QR code","\u626B\u7801\u7ED1\u5B9A WhatsApp \u673A\u5668\u4EBA":"Connect WhatsApp by QR code","\u4F7F\u7528 App ID \u548C App Secret \u7ED1\u5B9A\u98DE\u4E66\u673A\u5668\u4EBA":"Connect a Feishu bot with App ID and App Secret","\u4F7F\u7528 Client ID \u548C Client Secret \u7ED1\u5B9A\u9489\u9489\u673A\u5668\u4EBA":"Connect a DingTalk bot with Client ID and Client Secret","\u4F7F\u7528 Bot ID \u548C Secret \u7ED1\u5B9A\u4F01\u4E1A\u5FAE\u4FE1\u673A\u5668\u4EBA":"Connect a WeCom bot with Bot ID and Secret","\u4F7F\u7528 AppID \u548C AppSecret \u7ED1\u5B9A QQ \u673A\u5668\u4EBA":"Connect a QQ bot with AppID and AppSecret","\u4F7F\u7528 Manifest \u548C\u53CC Token \u63A5\u5165 Slack \u673A\u5668\u4EBA":"Connect a Slack bot with a manifest and two tokens","\u4F7F\u7528 Bot Token \u63A5\u5165 Telegram \u673A\u5668\u4EBA":"Connect a Telegram bot with a Bot Token","\u4F7F\u7528 Bot Token \u63A5\u5165 Discord \u673A\u5668\u4EBA":"Connect a Discord bot with a Bot Token",\u53D6\u6D88\u7ED1\u5B9A:"Cancel setup",\u53D6\u6D88\u63A5\u5165:"Cancel setup","\u4E8C\u7EF4\u7801\u7531\u817E\u8BAF\u5FAE\u4FE1 iLink \u670D\u52A1\u7B7E\u53D1\u3002\u7528\u624B\u673A\u5FAE\u4FE1\u626B\u63CF\u5E76\u786E\u8BA4\u540E\uFF0C\u8D26\u53F7\u51ED\u636E\u4F1A\u76F4\u63A5\u5199\u5165 Harness Host\uFF0C\u6D4F\u89C8\u5668\u4E0D\u4F1A\u6536\u5230 bot_token\u3002":"The QR code is issued by Tencent WeChat iLink. After you scan and confirm, account credentials are written directly to the Harness Host and are never exposed to the browser.","\u626B\u7801\u8D26\u53F7\u5FC5\u987B\u5DF2\u52A0\u5165\u4F01\u4E1A/\u7EC4\u7EC7\u3002\u5982\u679C\u9489\u9489\u63D0\u793A\u5C1A\u672A\u52A0\u5165\u7EC4\u7EC7\uFF0C\u8BF7\u5728\u63D0\u793A\u9875\u521B\u5EFA\u7EC4\u7EC7\uFF0C\u6216\u6362\u7528\u5DF2\u52A0\u5165\u7EC4\u7EC7\u7684\u8D26\u53F7\u3002":"The DingTalk account must belong to an organization. If prompted, create an organization or use an account that already belongs to one.","\u8BF7\u5728\u624B\u673A\u4E0A\u6838\u5BF9\u5E76\u786E\u8BA4\u6388\u6743\u3002\u90E8\u5206\u8D26\u53F7\u4F1A\u989D\u5916\u663E\u793A\u4E00\u4E2A\u914D\u5BF9\u6570\u5B57\uFF0C\u9875\u9762\u4F1A\u5728\u9700\u8981\u65F6\u63D0\u793A\u8F93\u5165\u3002":"Review and confirm authorization on your phone. Some accounts may also require a pairing number.","\u6388\u6743\u7531\u9489\u9489\u5B98\u65B9\u9875\u9762\u5B8C\u6210\u3002\u626B\u7801\u8D26\u53F7\u5FC5\u987B\u5DF2\u52A0\u5165\u4E00\u4E2A\u4F01\u4E1A/\u7EC4\u7EC7\u5E76\u6709\u6743\u521B\u5EFA\u673A\u5668\u4EBA\uFF1B\u521B\u5EFA\u6210\u529F\u540E\uFF0C\u5E94\u7528\u51ED\u636E\u4F1A\u76F4\u63A5\u5199\u5165 Harness Host\u3002":"Authorization is completed on DingTalk\u2019s official page. The account must belong to an organization and be allowed to create bots. Credentials are written directly to the Harness Host.","\u626B\u7801\u7531\u817E\u8BAF\u5B98\u65B9\u9875\u9762\u5B8C\u6210\uFF0C\u4E0D\u9700\u8981\u624B\u52A8\u586B\u5199 AppID \u6216 AppSecret\u3002\u626B\u7801\u6210\u529F\u540E\uFF0C\u673A\u5668\u4EBA\u4F1A\u81EA\u52A8\u8FDE\u63A5 DeepSeek Harness\u3002":"Scanning is completed on Tencent\u2019s official page. No AppID or AppSecret is required, and the bot connects automatically.","\u626B\u7801\u7531\u817E\u8BAF\u5B98\u65B9\u9875\u9762\u5B8C\u6210\uFF0C\u4E0D\u9700\u8981\u624B\u52A8\u586B\u5199 Bot ID \u6216 Secret\u3002\u521B\u5EFA\u6210\u529F\u540E\uFF0C\u673A\u5668\u4EBA\u4F1A\u81EA\u52A8\u8FDE\u63A5 DeepSeek Harness\u3002":"Scanning is completed on Tencent\u2019s official page. No Bot ID or Secret is required, and the bot connects automatically.","\u817E\u8BAF\u9875\u9762\u4F1A\u521B\u5EFA\u6216\u7ED1\u5B9A\u4E00\u4E2A QQ \u673A\u5668\u4EBA\uFF0C\u5E76\u628A\u8FDE\u63A5\u51ED\u636E\u5B89\u5168\u4EA4\u7ED9\u672C\u673A Harness Host\u3002":"Tencent will create or connect a QQ bot and securely deliver its credentials to the local Harness Host.","\u4F01\u4E1A\u5FAE\u4FE1\u5B98\u65B9\u9875\u9762\u4F1A\u521B\u5EFA\u4E00\u4E2A\u667A\u80FD\u673A\u5668\u4EBA\uFF0C\u5E76\u628A\u8FDE\u63A5\u51ED\u636E\u5B89\u5168\u4EA4\u7ED9\u672C\u673A Harness Host\u3002":"WeCom will create an AI bot and securely deliver its credentials to the local Harness Host.","\u4ECE\u6B64 Harness \u79FB\u9664\u8FD9\u4E2A\u5FAE\u4FE1\u8D26\u53F7\uFF1F":"Remove this WeChat account from Harness?","\u8FD9\u4F1A\u505C\u6B62\u6D88\u606F\u8FDE\u63A5\uFF0C\u5E76\u5220\u9664\u672C\u673A\u4FDD\u5B58\u7684 bot_token\u3001\u8D26\u53F7\u914D\u7F6E\u548C\u4F1A\u8BDD\u6620\u5C04\u3002\u5176\u4ED6\u5FAE\u4FE1\u8D26\u53F7\u4E0D\u53D7\u5F71\u54CD\u3002":"This stops the message connection and removes the locally stored bot_token, account configuration, and session mappings. Other WeChat accounts are not affected.","\u6B64\u64CD\u4F5C\u4F1A\u505C\u6B62\u8FD9\u4E2A\u673A\u5668\u4EBA\u7684\u8FDE\u63A5\uFF0C\u5E76\u5220\u9664\u4FDD\u5B58\u5728\u672C\u673A\u7684\u63A5\u5165\u914D\u7F6E\u548C\u51ED\u636E\u3002\u98DE\u4E66\u5F00\u653E\u5E73\u53F0\u4E2D\u7684\u5E94\u7528\u4E0D\u4F1A\u88AB\u81EA\u52A8\u5220\u9664\uFF0C\u5176\u4ED6\u673A\u5668\u4EBA\u4E5F\u4E0D\u53D7\u5F71\u54CD\u3002":"This stops the bot connection and removes the locally stored configuration and credentials. The app in Feishu Open Platform is not deleted, and other bots are not affected.","\u8FD9\u4F1A\u505C\u6B62\u6D88\u606F\u8FDE\u63A5\uFF0C\u5E76\u5220\u9664\u672C\u673A\u4FDD\u5B58\u7684\u5E94\u7528\u51ED\u636E\u3001\u673A\u5668\u4EBA\u914D\u7F6E\u53CA\u4F1A\u8BDD\u6620\u5C04\u3002\u9489\u9489\u5F00\u653E\u5E73\u53F0\u4E2D\u7684\u673A\u5668\u4EBA\u4E0D\u4F1A\u88AB\u81EA\u52A8\u5220\u9664\u3002":"This stops the message connection and removes the locally stored app credentials, bot configuration, and session mappings. The bot in DingTalk Open Platform is not deleted.","\u8FD9\u4F1A\u505C\u6B62\u6D88\u606F\u8FDE\u63A5\uFF0C\u5E76\u5220\u9664\u672C\u673A\u4FDD\u5B58\u7684\u5E94\u7528\u51ED\u636E\u3001\u673A\u5668\u4EBA\u914D\u7F6E\u53CA\u4F1A\u8BDD\u6620\u5C04\u3002\u4F01\u4E1A\u5FAE\u4FE1\u5E73\u53F0\u4E2D\u7684\u673A\u5668\u4EBA\u4E0D\u4F1A\u88AB\u81EA\u52A8\u5220\u9664\u3002":"This stops the message connection and removes the locally stored app credentials, bot configuration, and session mappings. The bot in WeCom is not deleted.","\u8FD9\u4F1A\u505C\u6B62\u6D88\u606F\u8FDE\u63A5\uFF0C\u5E76\u5220\u9664\u672C\u673A\u4FDD\u5B58\u7684\u5E94\u7528\u51ED\u636E\u3001\u673A\u5668\u4EBA\u914D\u7F6E\u53CA\u4F1A\u8BDD\u6620\u5C04\u3002\u817E\u8BAF\u5E73\u53F0\u4E2D\u7684\u673A\u5668\u4EBA\u4E0D\u4F1A\u88AB\u81EA\u52A8\u5220\u9664\u3002":"This stops the message connection and removes the locally stored app credentials, bot configuration, and session mappings. The bot on Tencent\u2019s platform is not deleted.","\u8FD9\u4F1A\u505C\u6B62\u6D88\u606F\u8FDE\u63A5\uFF0C\u5E76\u5220\u9664\u672C\u673A\u4FDD\u5B58\u7684 WhatsApp \u5173\u8054\u8BBE\u5907\u548C\u4F1A\u8BDD\u6620\u5C04\u3002":"This stops the message connection and removes the locally stored WhatsApp linked device and session mappings.",\u6B63\u5728\u8BFB\u53D6\u98DE\u4E66\u673A\u5668\u4EBA\u5217\u8868:"Loading Feishu bots","\u6B63\u5728\u8BFB\u53D6\u98DE\u4E66\u8FDE\u63A5\u72B6\u6001\u2026":"Loading Feishu connection status\u2026","\u6B63\u5728\u8BFB\u53D6\u5FAE\u4FE1\u8FDE\u63A5\u72B6\u6001\u2026":"Loading WeChat connection status\u2026","\u6B63\u5728\u8BFB\u53D6\u9489\u9489\u8FDE\u63A5\u72B6\u6001\u2026":"Loading DingTalk connection status\u2026","\u901A\u8FC7\u626B\u7801\u628A\u9489\u9489\u673A\u5668\u4EBA\u63A5\u5165 DeepSeek Harness":"Connect a DingTalk bot to DeepSeek Harness by QR code",\u9489\u9489\u670D\u52A1\u6CA1\u6709\u8FD4\u56DE\u626B\u7801\u7ED1\u5B9A\u8FDB\u5EA6:"DingTalk did not return QR setup progress",\u9489\u9489\u626B\u7801\u670D\u52A1\u6CA1\u6709\u8FD4\u56DE\u6709\u6548\u7684\u7ED1\u5B9A\u4EFB\u52A1:"DingTalk did not return a valid setup attempt","\u9489\u9489 Stream \u957F\u8FDE\u63A5\u8FD0\u884C\u6B63\u5E38":"DingTalk Stream connection is healthy",\u9489\u9489\u670D\u52A1\u6CA1\u6709\u8FD4\u56DE\u6709\u6548\u7684\u673A\u5668\u4EBA\u5217\u8868:"DingTalk did not return a valid bot list","${totals.connected} / ${totals.configured} \u5728\u7EBF":"${totals.connected} / ${totals.configured} online","\u7528\u4E8E\u628A\u9489\u9489\u673A\u5668\u4EBA\u63A5\u5165 DeepSeek Harness \u7684\u4E00\u6B21\u6027\u4E8C\u7EF4\u7801":"One-time QR code for connecting a DingTalk bot to DeepSeek Harness","\u4E8C\u7EF4\u7801\u5DF2\u8FC7\u671F\\n\u8BF7\u91CD\u65B0\u751F\u6210":"QR code expired\\nGenerate a new one","\u673A\u5668\u4EBA\u5DF2\u521B\u5EFA\uFF0C\u6B63\u5728\u5EFA\u7ACB\u6D88\u606F\u8FDE\u63A5":"Bot created. Starting the message connection",\u9489\u9489\u626B\u7801\u670D\u52A1\u6CA1\u6709\u8FD4\u56DE\u5B89\u5168\u7684\u4E8C\u7EF4\u7801:"DingTalk did not return a secure QR code","\u9489\u9489\u4E8C\u7EF4\u7801\u5DF2\u751F\u6210\uFF0C\u8BF7\u4F7F\u7528\u9489\u9489 App \u626B\u63CF\u3002":"DingTalk QR code generated. Scan it with the DingTalk app.","\u9489\u9489\u673A\u5668\u4EBA\u51ED\u636E\u5DF2\u7ED1\u5B9A\u3002":"DingTalk bot credentials connected.","\u5DF2\u53D6\u6D88\u9489\u9489\u673A\u5668\u4EBA\u63A5\u5165\u3002":"DingTalk bot setup cancelled.","\u9489\u9489\u673A\u5668\u4EBA\u53CA\u672C\u673A\u51ED\u636E\u5DF2\u79FB\u9664\u3002":"DingTalk bot and local credentials removed.",\u98DE\u4E66\u670D\u52A1\u6CA1\u6709\u8FD4\u56DE\u4E8C\u7EF4\u7801\u4FE1\u606F:"Feishu did not return QR code information",\u98DE\u4E66\u670D\u52A1\u8FD4\u56DE\u7684\u4E8C\u7EF4\u7801\u4FE1\u606F\u4E0D\u5B8C\u6574:"Feishu returned incomplete QR code information",\u98DE\u4E66\u670D\u52A1\u8FD4\u56DE\u4E86\u65E0\u6548\u7684\u673A\u5668\u4EBA\u72B6\u6001:"Feishu returned an invalid bot status","\u98DE\u4E66\u670D\u52A1\u8FD4\u56DE\u7684\u673A\u5668\u4EBA\u7F3A\u5C11 botId":"The Feishu bot is missing botId",\u98DE\u4E66\u670D\u52A1\u6CA1\u6709\u8FD4\u56DE\u8FDE\u63A5\u72B6\u6001:"Feishu did not return connection status",\u98DE\u4E66\u670D\u52A1\u6CA1\u6709\u8FD4\u56DE\u521B\u5EFA\u8FDB\u5EA6:"Feishu did not return creation progress",\u98DE\u4E66\u670D\u52A1\u8FD4\u56DE\u4E86\u672A\u77E5\u7684\u521B\u5EFA\u72B6\u6001:"Feishu returned an unknown creation status","\u5DF2\u63A5\u5165 ${totals.configured} \u4E2A\u673A\u5668\u4EBA\uFF0C\u5176\u4E2D ${totals.connected} \u4E2A\u5728\u7EBF":"${totals.connected} of ${totals.configured} bots online",\u5C1A\u672A\u63A5\u5165\u673A\u5668\u4EBA:"No bot connected yet","\u7528\u4E8E\u65B0\u589E DeepSeek Harness \u98DE\u4E66\u673A\u5668\u4EBA\u7684\u4E00\u6B21\u6027\u6388\u6743\u4E8C\u7EF4\u7801":"One-time authorization QR code for adding a Feishu bot to DeepSeek Harness",\u8BF7\u5237\u65B0\u540E\u91CD\u65B0\u626B\u7801:"Refresh and scan again",'${connected ? "\u68C0\u67E5\u8FDE\u63A5" : "\u91CD\u8BD5\u8FDE\u63A5"}${bot.name}':'${connected ? "Check connection" : "Reconnect"} ${bot.name}',\u65E0\u6CD5\u8BFB\u53D6\u98DE\u4E66\u673A\u5668\u4EBA:"Could not load Feishu bots","\u6388\u6743\u4E8C\u7EF4\u7801\u5DF2\u751F\u6210\uFF0C\u8BF7\u4F7F\u7528\u98DE\u4E66\u626B\u7801\u3002":"Authorization QR code generated. Scan it with Feishu.","\u98DE\u4E66\u673A\u5668\u4EBA\u51ED\u636E\u5DF2\u7ED1\u5B9A\u3002":"Feishu bot credentials connected.","\u5DF2\u53D6\u6D88\u6DFB\u52A0\u673A\u5668\u4EBA\u3002":"Adding the bot was cancelled.","${newBot.bot.name}\u5DF2\u8FDE\u63A5\uFF0C\u53EF\u4EE5\u5728\u98DE\u4E66\u4E2D\u5F00\u59CB\u804A\u5929\u3002":"${newBot.bot.name} is connected and ready to chat in Feishu.","${bot.name}\u64CD\u4F5C\u5931\u8D25\uFF0C\u8BF7\u67E5\u770B\u673A\u5668\u4EBA\u72B6\u6001\u3002":"${bot.name} operation failed. Check the bot status.","${bot.name}\u5DF2\u4ECE\u6B64 DeepSeek Harness \u79FB\u9664\uFF1B\u98DE\u4E66\u5F00\u653E\u5E73\u53F0\u4E2D\u7684\u5E94\u7528\u672A\u88AB\u5220\u9664\u3002":"${bot.name} was removed from this DeepSeek Harness. The app in Feishu Open Platform was not deleted.",\u65E0\u6CD5\u8BFB\u53D6\u8FDE\u63A5\u72B6\u6001:"Could not load connection status","QQ \u670D\u52A1\u6CA1\u6709\u8FD4\u56DE\u626B\u7801\u7ED1\u5B9A\u8FDB\u5EA6":"QQ did not return QR setup progress","QQ \u626B\u7801\u670D\u52A1\u6CA1\u6709\u8FD4\u56DE\u6709\u6548\u7684\u7ED1\u5B9A\u4EFB\u52A1":"QQ did not return a valid setup attempt","QQ WebSocket \u957F\u8FDE\u63A5\u8FD0\u884C\u6B63\u5E38":"QQ WebSocket connection is healthy","QQ \u8FDE\u63A5\u672A\u5C31\u7EEA\uFF0C\u63D2\u4EF6\u4F1A\u81EA\u52A8\u91CD\u8BD5\u3002":"The QQ connection is not ready; the plugin will retry automatically.","QQ \u8FDE\u63A5\u672A\u5C31\u7EEA\uFF0C\u63D2\u4EF6\u4F1A\u81EA\u52A8\u91CD\u8BD5":"The QQ connection is not ready; the plugin will retry automatically","QQ \u8FDE\u63A5\u5F53\u524D\u79BB\u7EBF":"The QQ connection is currently offline","QQ \u670D\u52A1\u6CA1\u6709\u8FD4\u56DE\u6709\u6548\u7684\u673A\u5668\u4EBA\u5217\u8868":"QQ did not return a valid bot list","\u5C1A\u672A\u7ED1\u5B9A QQ \u673A\u5668\u4EBA":"No QQ bot connected yet","\u7528\u4E8E\u7ED1\u5B9A QQ \u673A\u5668\u4EBA\u7684\u4E00\u6B21\u6027\u4E8C\u7EF4\u7801":"One-time QR code for connecting a QQ bot","${channel}${connectionSummary}\u8FD0\u884C\u6B63\u5E38":"${channel}${connectionSummary} is healthy","${channel} \u670D\u52A1\u6CA1\u6709\u8FD4\u56DE\u6709\u6548\u7684\u673A\u5668\u4EBA\u5217\u8868":"${channel} did not return a valid bot list","\u4F7F\u7528 Bot Token \u63A5\u5165 ${channel} \u673A\u5668\u4EBA":"Connect a ${channel} bot with a Bot Token","${model.totals.connected} / ${model.totals.configured} \u5728\u7EBF":"${model.totals.connected}/${model.totals.configured} online"," Bot API \u957F\u8F6E\u8BE2":" Bot API long polling",\u4F01\u4E1A\u5FAE\u4FE1\u670D\u52A1\u6CA1\u6709\u8FD4\u56DE\u626B\u7801\u7ED1\u5B9A\u8FDB\u5EA6:"WeCom did not return QR setup progress",\u4F01\u4E1A\u5FAE\u4FE1\u626B\u7801\u670D\u52A1\u6CA1\u6709\u8FD4\u56DE\u6709\u6548\u7684\u7ED1\u5B9A\u4EFB\u52A1:"WeCom did not return a valid setup attempt","\u4F01\u4E1A\u5FAE\u4FE1 WebSocket \u957F\u8FDE\u63A5\u8FD0\u884C\u6B63\u5E38":"WeCom WebSocket connection is healthy",\u4F01\u4E1A\u5FAE\u4FE1\u670D\u52A1\u6CA1\u6709\u8FD4\u56DE\u6709\u6548\u7684\u673A\u5668\u4EBA\u5217\u8868:"WeCom did not return a valid bot list",\u5C1A\u672A\u7ED1\u5B9A\u4F01\u4E1A\u5FAE\u4FE1\u673A\u5668\u4EBA:"No WeCom bot connected yet",\u7528\u4E8E\u7ED1\u5B9A\u4F01\u4E1A\u5FAE\u4FE1\u673A\u5668\u4EBA\u7684\u4E00\u6B21\u6027\u4E8C\u7EF4\u7801:"One-time QR code for connecting a WeCom bot",\u5FAE\u4FE1\u626B\u7801\u670D\u52A1\u6CA1\u6709\u8FD4\u56DE\u6709\u6548\u7684\u7ED1\u5B9A\u4EFB\u52A1:"WeChat did not return a valid setup attempt",\u5FAE\u4FE1\u7ED1\u5B9A\u6CA1\u6709\u5B8C\u6210:"WeChat setup did not complete",\u5FAE\u4FE1\u8FDE\u63A5\u6B63\u5E38:"WeChat connection is healthy",\u5FAE\u4FE1\u8FDE\u63A5\u672A\u5C31\u7EEA:"WeChat connection is not ready","\u5F53\u524D\u6A21\u578B\u4E0D\u652F\u6301\u56FE\u7247\uFF0C\u8BF7\u7528 /models \u67E5\u770B\u53EF\u7528\u6A21\u578B\uFF0C\u518D\u7528 /model <\u5E8F\u53F7> \u5207\u6362\u540E\u91CD\u53D1\u3002":"The current model does not support images. Use /models to list models, then /model to switch and resend.","\u56FE\u7247\u8D85\u8FC7\u5BBF\u4E3B\u5141\u8BB8\u7684\u5927\u5C0F\uFF0C\u8BF7\u538B\u7F29\u540E\u91CD\u8BD5\u3002":"The image exceeds the Host size limit. Compress it and try again.","\u56FE\u7247\u5206\u8FA8\u7387\u8FC7\u9AD8\uFF0C\u8BF7\u538B\u7F29\u540E\u91CD\u8BD5\u3002":"The image resolution is too high. Compress it and try again.","\u56FE\u7247\u5185\u5BB9\u65E0\u6548\u6216\u683C\u5F0F\u4E0D\u53D7\u652F\u6301\uFF0C\u8BF7\u91CD\u65B0\u53D1\u9001\u3002":"The image is invalid or unsupported. Send it again.","\u672A\u80FD\u8BFB\u53D6\u56FE\u7247\u5185\u5BB9\uFF0C\u8BF7\u91CD\u65B0\u53D1\u9001\u3002":"The image could not be read. Send it again.","\u56FE\u7247\u683C\u5F0F\u4E0E\u5B9E\u9645\u5185\u5BB9\u4E0D\u4E00\u81F4\uFF0C\u8BF7\u91CD\u65B0\u53D1\u9001\u3002":"The declared image format does not match its content. Send it again.","\u4E00\u6B21\u53D1\u9001\u7684\u56FE\u7247\u6570\u91CF\u8D85\u8FC7\u5BBF\u4E3B\u9650\u5236\uFF0C\u8BF7\u51CF\u5C11\u540E\u91CD\u8BD5\u3002":"The message exceeds the Host image-count limit. Remove some images and try again.","\u56FE\u7247\u603B\u5927\u5C0F\u8D85\u8FC7\u5BBF\u4E3B\u9650\u5236\uFF0C\u8BF7\u51CF\u5C11\u56FE\u7247\u6216\u538B\u7F29\u540E\u91CD\u8BD5\u3002":"The images exceed the Host total-size limit. Remove or compress some images and try again.","\u56FE\u7247\u4E0B\u8F7D\u5730\u5740\u53D1\u751F\u4E86\u91CD\u5B9A\u5411\uFF0C\u6682\u65F6\u65E0\u6CD5\u8BFB\u53D6\u3002":"The image download redirected and cannot be read.","\u56FE\u7247\u8D85\u8FC7 5 MB\uFF0C\u8BF7\u538B\u7F29\u540E\u91CD\u8BD5\u3002":"The image exceeds 5 MB. Compress it and try again.","\u4E00\u6B21\u53D1\u9001\u7684\u56FE\u7247\u603B\u5927\u5C0F\u8FC7\u5927\uFF0C\u8BF7\u51CF\u5C11\u56FE\u7247\u6570\u91CF\u6216\u538B\u7F29\u540E\u91CD\u8BD5\u3002":"The images are too large in total. Remove or compress some images and try again.","\u56FE\u7247\u4E0B\u8F7D\u5931\u8D25\uFF0C\u8BF7\u91CD\u65B0\u53D1\u9001\u540E\u518D\u8BD5\u3002":"The image download failed. Send it again.","\u6682\u4E0D\u652F\u6301\u8BE5\u56FE\u7247\u683C\u5F0F\uFF0C\u8BF7\u53D1\u9001 JPEG\u3001PNG\u3001WebP \u6216 GIF \u56FE\u7247\u3002":"This image format is unsupported. Send a JPEG, PNG, WebP, or GIF image.","\u6D88\u606F\u5904\u7406\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002":"Message processing failed. Try again later.",\u5FAE\u4FE1\u670D\u52A1\u6CA1\u6709\u8FD4\u56DE\u6709\u6548\u7684\u8D26\u53F7\u5217\u8868:"WeChat did not return a valid account list",\u5C1A\u672A\u7ED1\u5B9A\u5FAE\u4FE1:"No WeChat account connected yet","\u7528\u4E8E\u628A\u5FAE\u4FE1\u673A\u5668\u4EBA\u7ED1\u5B9A\u5230 DeepSeek Harness \u7684\u4E00\u6B21\u6027\u4E8C\u7EF4\u7801":"One-time QR code for connecting a WeChat bot to DeepSeek Harness","\u4FDD\u6301\u672C\u9875\u6253\u5F00\uFF0C\u7B49\u5F85\u6D88\u606F\u957F\u8F6E\u8BE2\u53D8\u4E3A\u5728\u7EBF":"Keep this page open until long polling is online","\u5FAE\u4FE1\u4E8C\u7EF4\u7801\u5DF2\u751F\u6210\uFF0C\u8BF7\u4F7F\u7528\u624B\u673A\u5FAE\u4FE1\u626B\u63CF\u3002":"WeChat QR code generated. Scan it with WeChat on your phone.","\u79FB\u9664\u5931\u8D25\uFF1A${presentError(error).message}":"Removal failed: ${presentError(error).message}",\u65E0\u6CD5\u8BFB\u53D6\u5FAE\u4FE1\u72B6\u6001:"Could not load WeChat status","WhatsApp \u670D\u52A1\u6CA1\u6709\u8FD4\u56DE\u626B\u7801\u8FDB\u5EA6":"WhatsApp did not return QR setup progress","WhatsApp \u670D\u52A1\u6CA1\u6709\u8FD4\u56DE\u6709\u6548\u7684\u626B\u7801\u4EFB\u52A1":"WhatsApp did not return a valid setup attempt","WhatsApp \u670D\u52A1\u6CA1\u6709\u8FD4\u56DE\u6709\u6548\u7684\u673A\u5668\u4EBA\u5217\u8868":"WhatsApp did not return a valid account list","\u7528\u4E8E\u5173\u8054 WhatsApp \u8BBE\u5907\u7684\u4E00\u6B21\u6027\u4E8C\u7EF4\u7801":"One-time QR code for linking a WhatsApp device",\u7528\u6237:"User","\u5FAE\u4FE1\u7528\u6237 ID":"WeChat user ID","\u586B\u5199\u63A5\u6536\u6D88\u606F\u7684\u7528\u6237 ID":"Enter the recipient user ID",\u79C1\u804A:"Direct message",\u7FA4\u804A:"Group","\u7FA4 Chat ID":"Group Chat ID","\u7528\u6237 ID":"User ID","\u586B\u5199\u9489\u9489\u7528\u6237 ID":"Enter the DingTalk user ID","\u7FA4 Open Conversation ID":"Group Open Conversation ID","\u586B\u5199\u4F01\u4E1A\u5FAE\u4FE1\u7528\u6237 ID":"Enter the WeCom user ID","\u586B\u5199\u7FA4 chatid":"Enter the group chatid",\u5355\u804A:"Direct message","\u7528\u6237 Open ID":"User Open ID","\u586B\u5199 user_openid":"Enter the user_openid","\u7FA4 Open ID":"Group Open ID","\u586B\u5199 group_openid":"Enter the group_openid",\u4F1A\u8BDD:"Conversation",\u7EBF\u7A0B:"Thread","Thread \u65F6\u95F4\u6233":"Thread timestamp",\u804A\u5929:"Chat",\u8BDD\u9898:"Topic",\u9891\u9053\u6216\u79C1\u4FE1:"Channel or DM","\u586B\u5199\u53EF\u53D1\u6D88\u606F\u7684 Channel ID":"Enter a Channel ID the bot can message","\u7528\u6237 JID":"User JID","\u7FA4 JID":"Group JID","\u8BF7\u6C42\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002":"Request failed. Try again later.","\u5F53\u524D\u6D4F\u89C8\u5668\u4E0D\u652F\u6301\u81EA\u52A8\u590D\u5236\uFF0C\u8BF7\u624B\u52A8\u9009\u62E9\u590D\u5236\u3002":"Automatic copy is unavailable. Select and copy the value manually.","\u76EE\u6807\u4FDD\u5B58\u5931\u8D25\uFF0C\u8BF7\u68C0\u67E5\u540E\u91CD\u8BD5\u3002":"Could not save the target. Check it and try again.","\u65E0\u6CD5\u751F\u6210\u672A\u5360\u7528\u7684 Target ID\uFF0C\u8BF7\u91CD\u8BD5\u3002":"Could not generate an unused Target ID. Try again.",\u7F16\u8F91\u6295\u9012\u76EE\u6807:"Edit delivery target",\u65B0\u5EFA\u6295\u9012\u76EE\u6807:"New delivery target","\u5DF2\u4ECE\u4F1A\u8BDD\u81EA\u52A8\u586B\u5165\u76EE\u6807\u4FE1\u606F\uFF1B\u786E\u8BA4\u540E\u518D\u4FDD\u5B58\u3002":"Target details were filled from the conversation. Review them before saving.","\u8BF7\u624B\u52A8\u586B\u5199\u4ECE\u5BF9\u5E94\u5E73\u53F0\u53D6\u5F97\u7684\u539F\u751F\u6807\u8BC6\u3002":"Enter the native identifier from the platform manually.","\u4F8B\u5982 daily-report":"For example, daily-report","\u4F7F\u7528\u5927\u5C0F\u5199\u5B57\u6BCD\u3001\u6570\u5B57\u3001\u70B9\u3001\u4E0B\u5212\u7EBF\u3001\u5192\u53F7\u3001@ \u6216\u8FDE\u5B57\u7B26\u3002":"Use letters, numbers, dots, underscores, colons, @, or hyphens.","\u663E\u793A\u540D\u79F0\uFF08\u53EF\u9009\uFF09":"Display name (optional)","\u4F8B\u5982 \u6BCF\u65E5\u6C47\u62A5\u7FA4":"For example, Daily reports",\u76EE\u6807\u7C7B\u578B:"Target type",\u4FDD\u5B58\u76EE\u6807:"Save target",\u8BF7\u5148\u5B8C\u6210\u6295\u9012\u76EE\u6807\u8BFB\u53D6:"Wait for delivery targets to finish loading",\u4ECE\u5DF2\u804A\u8FC7\u7684\u4F1A\u8BDD\u9009\u62E9:"Choose from conversations",\u5DF2\u804A\u4F1A\u8BDD:"Conversation",\u4ECE\u4F1A\u8BDD\u9009\u62E9targetID:"Select a targetID from conversations","\u9009\u62E9\u540E\u4F1A\u81EA\u52A8\u586B\u5199\u76EE\u6807\u4FE1\u606F\u548C\u8C03\u7528\u522B\u540D\uFF0C\u786E\u8BA4\u540E\u518D\u4FDD\u5B58\u3002":"Selecting a conversation fills the target details and call alias. Review them before saving.","\u6B63\u5728\u5237\u65B0\u2026":"Refreshing\u2026",\u5237\u65B0:"Refresh","\u6B63\u5728\u8BFB\u53D6\u5DF2\u804A\u4F1A\u8BDD\u2026":"Loading known conversations\u2026","\u65E0\u6CD5\u8BFB\u53D6\u5DF2\u804A\u4F1A\u8BDD\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002":"Could not load known conversations. Try again later.",\u8FD8\u6CA1\u6709\u53EF\u9009\u62E9\u7684\u4F1A\u8BDD:"No conversations to choose from","\u5148\u5728\u5BF9\u5E94\u5E73\u53F0\u4E0E\u673A\u5668\u4EBA\u804A\u4E00\u6761\u6D88\u606F\uFF0C\u518D\u5237\u65B0\u3002":"Send the bot a message on the platform, then refresh.",\u5DF2\u6DFB\u52A0:"Added","\u624B\u52A8\u586B\u5199\uFF08\u9AD8\u7EA7\uFF09":"Enter manually (advanced)","\u6D4B\u8BD5\u6D88\u606F\u5DF2\u53D1\u9001\uFF0C\u8BF7\u5230\u76EE\u6807\u4F1A\u8BDD\u786E\u8BA4\u3002":"Test message sent. Confirm it in the target conversation.","\u6D4B\u8BD5\u53D1\u9001\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002":"Test delivery failed. Try again later.",\u5DF2\u590D\u5236\u8C03\u7528\u53C2\u6570:"Call parameters copied","\u590D\u5236\u5931\u8D25\u3002":"Copy failed.","\u5220\u9664\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002":"Could not delete the target. Try again later.",\u590D\u5236\u8C03\u7528\u53C2\u6570:"Copy call parameters",\u673A\u5668\u4EBA\u79BB\u7EBF\u65F6\u4E0D\u53EF\u53D1\u9001\u6D4B\u8BD5\u6D88\u606F:"Test delivery is unavailable while the bot is offline",\u6D4B\u8BD5\u6295\u9012\u76EE\u6807:"Test delivery target",\u6D4B\u8BD5:"Test",\u7F16\u8F91:"Edit",\u5220\u9664:"Delete","\u5220\u9664 ":"Delete ","\uFF1F\u4F7F\u7528\u8FD9\u4E2A targetId \u7684\u5916\u90E8\u8C03\u7528\u5C06\u8FD4\u56DE unknown-target\u3002":"? External calls using this targetId will return unknown-target.","\u6B63\u5728\u5220\u9664\u2026":"Deleting\u2026",\u786E\u8BA4\u5220\u9664:"Delete target","\u6295\u9012\u76EE\u6807\u8BBE\u7F6E\u6682\u4E0D\u53EF\u7528\u3002":"Delivery target settings are unavailable.","\u65E0\u6CD5\u8BFB\u53D6\u6295\u9012\u76EE\u6807\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002":"Could not load delivery targets. Try again later.","\u2190 \u8FD4\u56DE\u673A\u5668\u4EBA\u5217\u8868":"\u2190 Back to bots",\u4F7F\u7528\u6587\u6863:"User guide",\u6253\u5F00\u4E3B\u52A8\u6295\u9012\u4F7F\u7528\u6587\u6863:"Open the proactive delivery guide","\u5F53\u524D\u6E20\u9053\u6682\u4E0D\u652F\u6301\u6295\u9012\u76EE\u6807\u3002":"Delivery targets are not supported for this channel.","\u5DF2\u590D\u5236 Bot ID":"Bot ID copied",\u590D\u5236:"Copy",\u6295\u9012\u76EE\u6807:"Delivery targets","\u673A\u5668\u4EBA\u5F53\u524D\u79BB\u7EBF\uFF1B\u4ECD\u53EF\u914D\u7F6E\u76EE\u6807\uFF0C\u6062\u590D\u8FDE\u63A5\u540E\u518D\u6D4B\u8BD5\u3002":"The bot is offline. You can still configure targets and test them after reconnection.",\u65B0\u5EFA\u76EE\u6807:"New target","\u6B63\u5728\u8BFB\u53D6\u6295\u9012\u76EE\u6807\u2026":"Loading delivery targets\u2026",\u5C1A\u672A\u914D\u7F6E\u6295\u9012\u76EE\u6807:"No delivery targets yet","\u70B9\u51FB\u201C\u65B0\u5EFA\u76EE\u6807\u201D\u53EF\u4ECE\u5DF2\u804A\u8FC7\u7684\u4F1A\u8BDD\u9009\u62E9\uFF0C\u4E5F\u53EF\u624B\u52A8\u586B\u5199\u3002":"Select New target to choose a conversation or enter the details manually."});var dlA=Object.freeze(Object.fromEntries(Object.keys(_ve).map(n=>[n,n==="$locale"?"zh":n])));var hlA=Object.freeze(["aria-label","alt","placeholder","title"]);var Tve=Object.freeze({defaultId:"",items:Object.freeze([])}),BlA=qd.createContext(Tve);var kP="/feishu",g5=Object.freeze({status:"connection.status",beginProvisioning:"provision.begin",beginCallbackRepair:"bot.callback-repair.begin",beginGroupMessagePermission:"bot.group-message-permission.begin",pollProvisioning:"provision.poll",cancelProvisioning:"provision.cancel",bindCredentials:"bot.bind-credentials",reconnectBot:"bot.reconnect",disconnectBot:"bot.disconnect",deleteBot:"bot.delete",setWorkspace:"bot.workspace.set",setAgentPreset:"bot.preset.set",setContextEnhancement:"bot.context-enhancement.set",setAccessPolicy:"bot.access-policy.set",setGroupResponseMode:"bot.group-response-mode.set",testConnection:"connection.test",disconnect:"connection.disconnect"}),MlA=Object.freeze({PROVISION:"provision",CALLBACK_REPAIR:"callback_repair",GROUP_MESSAGE_PERMISSION:"group_message_permission"});var Dt=Object.freeze({...g5,setAccessPolicy:Va});var ul=Object.freeze({reconnectBot:"bot.reconnect",disconnectBot:"bot.disconnect",deleteBot:"bot.delete"}),d5=Object.freeze([...new Set([...Object.values(Dt),...Object.values(ul)])]),Rve=new Set(["idle","starting","qr_ready","polling","slow_down","domain_switched","saving","succeeded","expired","cancelled","error"]),kve=new Set(["provision","callback_repair","group_message_permission"]),h5="callback_repair",PP="group_message_permission",kS=new Set([h5,PP]),vve=new Set(["accounts.feishu.cn","accounts.larksuite.com","open.feishu.cn","open.larksuite.com"]),Pve=/^[A-Za-z0-9_-]{1,128}$/,Gve=/^cli_[A-Za-z0-9_-]+$/,c5=Object.freeze({abort:"Registration was cancelled.",access_denied:"Registration was denied.",expired_token:"The registration QR code expired.",invalid_credentials:"Feishu returned invalid app credentials.",credentials_callback_failed:"Unable to activate the Feishu connection.",registration_failed:"Unable to register the Feishu app.",connection_failed:"The bot was created, but its connection could not be started.",credential_removal_failed:"Unable to remove the Feishu credentials.",state_cleanup_failed:"Unable to remove the bot session data. Please retry.",deletion_pending:"Bot deletion is incomplete. Retry removal to finish cleanup.",missing_credentials:"The bot credentials are missing. Delete it and scan again.",repair_app_mismatch:"The authorized Feishu app does not match the selected bot.",repair_owner_missing:"Feishu did not return the authorizing account identity.",repair_domain_mismatch:"The authorized Feishu tenant does not match the selected bot.",repair_owner_mismatch:"The authorizing Feishu account is not an owner of the selected bot.",repair_credentials_invalid:"Feishu returned credentials that could not be verified for the selected bot.",repair_bot_mismatch:"The verified Feishu bot does not match the selected bot.",repair_target_changed:"The selected bot changed while repair was in progress. Start the repair again.",credential_update_failed:"Unable to store the repaired Feishu credentials.",credential_state_unknown:"The repaired Feishu credentials could not be confirmed after saving.",repair_connection_failed:"The callback update was accepted, but the selected bot could not reconnect.",group_message_permission_required:"Authorize access to all group messages before enabling this mode.",group_message_permission_save_failed:"Feishu granted the permission, but all-message mode could not be saved.",group_message_permission_connection_failed:"Feishu granted the permission, but the selected bot could not reconnect.",card_action_probe_unavailable:"The selected bot is not connected, so its card button cannot be verified.",card_action_probe_send_failed:"The callback update was accepted, but the verification card could not be sent.",card_action_probe_timeout:"Feishu accepted the update, but the card button was not verified in time. Start the repair again and click the test button within two minutes.",card_action_probe_failed:"Feishu accepted the update, but the card button verification failed."}),Fve=Object.freeze({idle:"pending",starting:"pending",qr_ready:"pending",polling:"pending",slow_down:"pending",domain_switched:"pending",saving:"connecting",succeeded:"connected",expired:"expired",cancelled:"failed",error:"failed"});function Lve(n){if(n===null||typeof n!="object"||Array.isArray(n))return!1;let t=Object.getPrototypeOf(n);return t===Object.prototype||t===null}function jo(n,t){return Lve(n)&&Reflect.ownKeys(n).every(o=>typeof o=="string"&&t.has(o))}function Gu(n){return Number.isFinite(n)?n:void 0}function _n(n){return typeof n=="string"&&Pve.test(n)}function I5(n,t){return typeof n=="string"&&n.trim().length>0&&n.length<=t}function FP(n){if(!n||typeof n!="object")return null;let t=typeof n.code=="string"&&Object.hasOwn(c5,n.code)?n.code:"registration_failed";return{code:t,message:c5[t]}}function ys(n){if(!n||typeof n!="object")return{state:"idle",attempt:0};let t=Rve.has(n.state)?n.state:"error",o=_n(n.attempt)?n.attempt:Gu(n.attempt)??0,i={state:t,attempt:o};i.operation=kve.has(n.operation)?n.operation:"provision";let e=Gu(n.updatedAt),a=Gu(n.expiresAt),A=Gu(n.remainingSeconds),r=Gu(n.pollIntervalSeconds);e!==void 0&&(i.updatedAt=e),typeof n.qrCodeUrl=="string"&&n.qrCodeUrl.length>0&&(i.qrCodeUrl=n.qrCodeUrl),a!==void 0&&(i.expiresAt=a),A!==void 0&&(i.remainingSeconds=A),r!==void 0&&(i.pollIntervalSeconds=r),_n(n.botId)&&(i.botId=n.botId);let s=FP(n.error);return s&&(i.error=s),i}function Uve(n,t,o){if(!(typeof n!="string"||n.length===0))try{let i=new URL(n);if(i.protocol!=="https:"||!vve.has(i.hostname)||i.port||i.username||i.password)return;if(kS.has(t)){let e=i.searchParams.getAll("clientID"),a=i.searchParams.getAll("tp"),A=i.searchParams.getAll("addons"),r=[...i.searchParams.values()].some(s=>s.includes("{{")||s.includes("}}"));if(e.length!==1||a.length!==1||a[0]!=="sdk"||!Gve.test(e[0]??"")||i.hostname!==o||i.searchParams.has("createOnly")||A.length!==1||!A[0]?.trim()||r)return}return i.toString()}catch{return}}function vS(n){let t=n&&typeof n=="object"?n:{};return{connected:t.connected===!0||t.ready===!0&&t.feishuLongConnectionState==="connected"&&t.harnessReachable===!0,ready:t.ready===!0,harnessReachable:t.harnessReachable===!0}}function E5(n){let t=n&&typeof n=="object"?n:{},o={name:typeof t.name=="string"&&t.name.length>0?t.name:"\u98DE\u4E66\u673A\u5668\u4EBA"};return typeof t.avatarUrl=="string"&&(o.avatarUrl=t.avatarUrl),typeof t.appIdMasked=="string"&&(o.appIdMasked=t.appIdMasked),typeof t.tenantName=="string"&&(o.tenantName=t.tenantName),(t.domain==="feishu"||t.domain==="lark")&&(o.domain=t.domain),(typeof t.activated=="boolean"||typeof t.activated=="number")&&(o.activated=t.activated),o}function C5(n,t){return t?{status:"healthy",summary:"\u957F\u8FDE\u63A5\u8FD0\u884C\u6B63\u5E38",lastCheckedAt:Date.now()}:n?.configured===!0?{status:"offline",summary:"\u673A\u5668\u4EBA\u5C1A\u672A\u8FDE\u63A5",lastCheckedAt:Date.now()}:{status:"offline",summary:"\u5C1A\u672A\u63A5\u5165\u98DE\u4E66\u673A\u5668\u4EBA",lastCheckedAt:Date.now()}}function u5(n,t,o){return o?"connected":n?.phase==="error"||t.state==="error"?"error":n?.phase==="connecting"||t.state==="saving"?"connecting":n?.phase==="registering"||["starting","qr_ready","polling","slow_down","domain_switched"].includes(t.state)?"provisioning":"disconnected"}async function B5(n){return Nve.toDataURL(n,{errorCorrectionLevel:"M",margin:1,width:320,type:"image/png"})}async function Hve(n,t,o){let i=Uve(n.qrCodeUrl,n.operation,o),e={attemptId:String(n.attempt),operation:n.operation,...n.botId?{botId:n.botId}:{},expiresAt:n.expiresAt??Date.now()+5*6e4,pollIntervalMs:Math.max(800,Math.min(1e4,(n.pollIntervalSeconds??1.8)*1e3))};if(i)return{...e,verificationUrl:i,qrCodeDataUrl:await t(i)};if(n.state==="saving"&&kS.has(n.operation)&&n.botId)return{...e,submitted:!0}}function Kve(n){let t=n&&typeof n=="object"?n:{};if(!_n(t.botId))return null;let o=vS(t.connection),i=t.connected===!0||o.connected,e={state:"idle"},a={botId:t.botId,state:u5(t,e,i),connected:i,configured:t.configured===!0,agentPreset:ng(t.agentPreset),contextEnhancement:Rp(t.contextEnhancement),accessPolicy:Pp(t.accessPolicy),groupResponseMode:Io(t.groupResponseMode),groupMessagePermissionGranted:t.groupMessagePermissionGranted===!0,bot:E5(t.bot),health:C5(t,i)};typeof t.workspace=="string"&&t.workspace&&(a.workspace=t.workspace);let A=Xr(t.lastMessageError);A&&(a.lastMessageError=A);let r=FP(t.error);return r&&(a.error=r),a}async function Qa(n,{encodeQr:t=B5}={}){let o=n&&typeof n=="object"?n:{},i=ys(o.registration),e=vS(o.connection),a=o.connected===!0||e.connected,r=(kS.has(i.operation)&&i.botId&&Array.isArray(o.bots)?o.bots.find(d=>d?.botId===i.botId):void 0)?.bot?.domain==="lark"?"open.larksuite.com":"open.feishu.cn",s=await Hve(i,t,r),g=FP(o.error)??i.error??null,c=Array.isArray(o.bots)?o.bots.map(Kve).filter(Boolean):[],I={schemaVersion:o.schemaVersion===2?2:1,revision:Number.isSafeInteger(o.revision)&&o.revision>=0?o.revision:0,state:u5(o,i,a),connected:a,configured:o.configured===!0,bot:E5(o.bot),health:C5(o,a),bots:c,agentPresetCatalog:$n(o.agentPresetCatalog),totals:{configured:c.length||(o.configured===!0?1:0),connected:c.length?c.filter(d=>d.connected).length:a?1:0}};return s&&(I.provisioning=s),g&&(I.error=g),I}function NS(n){return{ok:!1,error:{code:"bad-request",message:n,details:{issues:[]}}}}function RS(){return{ok:!1,error:{code:"cancelled",message:"The Feishu request was cancelled.",details:{}}}}function xve(){return{ok:!1,error:{code:"internal",message:"The Feishu integration operation failed.",details:{}}}}function Yve(n,t){return n===Dt.status?jo(t,new Set)?null:"This endpoint accepts an empty payload only.":n===Dt.testConnection?jo(t,new Set)?null:"This endpoint accepts an empty payload only.":n===Dt.beginProvisioning?jo(t,new Set(["locale","replaceAttemptId"]))?t.locale!==void 0&&t.locale!=="zh-CN"?"The provisioning locale must be zh-CN.":t.replaceAttemptId!==void 0&&!_n(t.replaceAttemptId)?"replaceAttemptId must be a valid opaque id.":null:"Provisioning accepts locale and replaceAttemptId only.":n===Dt.beginCallbackRepair?jo(t,new Set(["botId"]))&&_n(t.botId)?null:"Callback repair requires a single valid botId.":n===Dt.beginGroupMessagePermission?jo(t,new Set(["botId"]))&&_n(t.botId)?null:"Group message permission update requires a single valid botId.":n===Dt.bindCredentials?jo(t,new Set(["appId","appSecret"]))&&I5(t.appId,256)&&I5(t.appSecret,1024)?null:"Credential binding requires App ID and App Secret.":n===Dt.pollProvisioning||n===Dt.cancelProvisioning?jo(t,new Set(["attemptId"]))&&_n(t.attemptId)?null:"A single valid attemptId is required.":n===Dt.disconnect?jo(t,new Set(["removeCredentials"]))&&t.removeCredentials===!0?null:"Disconnect requires removeCredentials=true.":n===ul.reconnectBot?jo(t,new Set(["botId","sendTest"]))&&_n(t.botId)&&(t.sendTest===void 0||typeof t.sendTest=="boolean")?null:"A valid botId and optional sendTest flag are required.":n===ul.disconnectBot?jo(t,new Set(["botId"]))&&_n(t.botId)?null:"A single valid botId is required.":n===ul.deleteBot?jo(t,new Set(["botId","confirm"]))&&_n(t.botId)&&t.confirm===!0?null:"Deleting a bot requires a valid botId and confirm=true.":n===Dt.setWorkspace?Za(t)?null:"\u8BF7\u8F93\u5165\u5DE5\u4F5C\u533A\u7EDD\u5BF9\u8DEF\u5F84\u3002":n===Dt.setAgentPreset?$a(t)?null:"\u8BF7\u9009\u62E9 Agent Preset\u3002":n===Dt.setContextEnhancement?za(t)?null:"\u8BF7\u63D0\u4EA4\u6709\u6548\u7684\u4E0A\u4E0B\u6587\u589E\u5F3A\u8BBE\u7F6E\u3002":n===Dt.setAccessPolicy?Wa(t)?null:"\u8BF7\u63D0\u4EA4\u6709\u6548\u7684\u8BBF\u95EE\u8BBE\u7F6E\u3002":n===Dt.setGroupResponseMode?jo(t,new Set(["botId","groupResponseMode"]))&&_n(t.botId)&&nS(t.groupResponseMode)?null:"\u8BF7\u9009\u62E9\u7FA4\u804A\u54CD\u5E94\u65B9\u5F0F\u3002":"Unknown Feishu endpoint."}function jve(n,t){return new Promise((o,i)=>{if(t?.aborted){i(t.reason??new Error("aborted"));return}let e=setTimeout(a,n);e.unref?.();function a(){t?.removeEventListener("abort",A),o()}function A(){clearTimeout(e),i(t.reason??new Error("aborted"))}t?.addEventListener("abort",A,{once:!0})})}async function GP(n,t){return typeof n.registrationStatus=="function"?n.registrationStatus(t):n.status()}async function vP(n,t,o,i){let e=t,a=Date.now()+15e3;for(;;){let A=ys(e?.registration);if(A.qrCodeUrl)return e;if(["error","expired","cancelled"].includes(A.state))throw new Error("Provisioning stopped before the QR code was ready.");if(Date.now()>=a)throw new Error("Provisioning QR code timed out.");if(await jve(50,i),e=await GP(n,o),!e)throw new Error("The provisioning attempt is no longer active.")}}function l5(n,t){return String(ys(n?.registration).attempt)===t}function p5(n){let t=ys(n?.registration);return t.state==="succeeded"?t.botId&&(n?.connected===!0||vS(n?.connection).connected)?"connected":"connecting":Fve[t.state]??"failed"}function Jve(n){if(!n||typeof n.status!="function"||typeof n.startRegistration!="function"||typeof n.cancelRegistration!="function"||typeof n.disconnect!="function")throw new TypeError("A Feishu controller with status/start/cancel/disconnect is required")}function f5(n,{encodeQr:t=B5}={}){Jve(n);let o=new Map,i=new Map,e=a=>{let A=o.get(a);return A||(o.size>=32&&o.delete(o.keys().next().value),A=Promise.resolve().then(()=>t(a)),o.set(a,A)),A};return async(a,A,r)=>{if(r?.aborted)return RS();if(!d5.includes(a))return NS("Unknown Feishu endpoint.");let s=Yve(a,A);if(s)return NS(s);try{let g;if(a===Dt.status)g=await Qa(await n.status(),{encodeQr:e});else if(a===Dt.beginProvisioning){A.replaceAttemptId&&await n.cancelRegistration(A.replaceAttemptId);let c=await n.startRegistration({locale:A.locale}),I=String(ys(c?.registration).attempt),d=await vP(n,c,I,r);if(g=(await Qa(d,{encodeQr:e})).provisioning,!g)throw new Error("Provisioning did not produce a QR code.");i.set(I,g.verificationUrl)}else if(a===Dt.beginCallbackRepair){if(typeof n.startCallbackRepair!="function")throw new Error("Feishu callback repair is unavailable.");let c=await n.startCallbackRepair(A.botId),I=String(ys(c?.registration).attempt),d=await vP(n,c,I,r);if(g=(await Qa(d,{encodeQr:e})).provisioning,!g||g.operation!==h5||g.botId!==A.botId)throw new Error("Callback repair did not produce a safe QR code.");i.set(I,g.verificationUrl)}else if(a===Dt.beginGroupMessagePermission){if(typeof n.startGroupMessagePermission!="function")throw new Error("Feishu group message permission update is unavailable.");let c=await n.startGroupMessagePermission(A.botId),I=String(ys(c?.registration).attempt),d=await vP(n,c,I,r);if(g=(await Qa(d,{encodeQr:e})).provisioning,!g||g.operation!==PP||g.botId!==A.botId)throw new Error("Group message permission update did not produce a safe QR code.");i.set(I,g.verificationUrl)}else if(a===Dt.pollProvisioning){let c=await GP(n,A.attemptId);if(!c||!l5(c,A.attemptId))return NS("The provisioning attempt is no longer active.");let I=ys(c.registration),d=await Qa(c,{encodeQr:e});if(g={status:p5(c),operation:I.operation,...I.botId?{botId:I.botId}:{},...d.provisioning?{provisioning:d.provisioning}:{},...I.botId&&d.connected?{connection:d}:{},...d.error?{message:d.error.message}:{}},["connected","expired","failed"].includes(g.status)){let B=i.get(A.attemptId);B&&o.delete(B),i.delete(A.attemptId)}}else if(a===Dt.cancelProvisioning){let c=await GP(n,A.attemptId);if(!c||!l5(c,A.attemptId))return NS("The provisioning attempt is no longer active.");let I=typeof n.registrationStatus=="function",d=ys(c.registration),B;!I&&d.state==="saving"?B=await n.disconnect():B=await n.cancelRegistration(A.attemptId);let f=ys(B?.registration);if(kS.has(d.operation)&&d.state==="saving"&&["saving","succeeded"].includes(f.state)&&(g={status:p5(B),operation:f.operation,...f.botId?{botId:f.botId}:{},message:d.operation===PP?"The permission update was already submitted and is still being applied.":"Callback repair was already submitted and is still being verified."}),g?.status!=="connecting"){let Q=i.get(A.attemptId);Q&&o.delete(Q),i.delete(A.attemptId),g??={status:"failed",operation:d.operation,...d.botId?{botId:d.botId}:{},message:"Registration was cancelled."}}}else if(a===Dt.bindCredentials){if(typeof n.bindCredentials!="function")throw new Error("Credential binding is unavailable");g=await Qa(await n.bindCredentials(A),{encodeQr:e})}else if(a===Dt.testConnection){let c=await n.status(),d=c?.connected===!0||vS(c?.connection).connected||typeof n.reconnect!="function"?c:await n.reconnect();g=await Qa(d,{encodeQr:e})}else if(a===Dt.disconnect)g=await Qa(await n.disconnect(),{encodeQr:e});else if(a===ul.reconnectBot){if(typeof n.reconnectBot!="function")throw new Error("Multi-bot reconnect is unavailable");let c=await n.reconnectBot(A.botId);if(r?.aborted)return RS();if(g=await Qa(c,{encodeQr:e}),A.sendTest===!0){let I=null;if(!(c?.bots?.some(B=>B?.botId===A.botId&&B.connected===!0)===!0))I=new Error("Feishu bot is not connected"),I.code="test-target-unavailable";else try{if(typeof n.sendConnectionTest!="function"){let B=new Error("Connection test is unavailable");throw B.code="test-target-unavailable",B}await n.sendConnectionTest(A.botId)}catch(B){I=B}g={...g,testMessage:or(I)}}}else if(a===ul.disconnectBot){if(typeof n.disconnectBot!="function")throw new Error("Multi-bot disconnect is unavailable");g=await Qa(await n.disconnectBot(A.botId),{encodeQr:e})}else if(a===Dt.setWorkspace){if(typeof n.updateWorkspace!="function")throw new Error("Workspace update is unavailable");g=await Qa(await n.updateWorkspace(A.botId,A.workspace),{encodeQr:e})}else if(a===Dt.setContextEnhancement){if(typeof n.updateContextEnhancement!="function")throw new Error("Context enhancement update is unavailable");g=await n.updateContextEnhancement(A.botId,A.config,c=>Qa(c,{encodeQr:e}))}else if(a===Dt.setAccessPolicy){if(typeof n.updateAccessPolicy!="function")throw new Error("Access policy update is unavailable");g=await n.updateAccessPolicy(A.botId,A.policy,c=>Qa(c,{encodeQr:e}))}else if(a===Dt.setAgentPreset){if(typeof n.updateAgentPreset!="function")throw new Error("Agent preset update is unavailable");g=await Qa(await n.updateAgentPreset(A.botId,A.agentPreset),{encodeQr:e})}else if(a===Dt.setGroupResponseMode){if(typeof n.updateGroupResponseMode!="function")throw new Error("Group response mode update is unavailable");g=await Qa(await n.updateGroupResponseMode(A.botId,A.groupResponseMode),{encodeQr:e})}else{if(typeof n.deleteBot!="function")throw new Error("Multi-bot delete is unavailable");g=await Qa(await n.deleteBot(A.botId),{encodeQr:e})}return r?.aborted?RS():{ok:!0,value:g}}catch(g){let c=Xa(g);return r?.aborted?RS():c?{ok:!1,error:{...c,details:{}}}:xve()}}}function PS(n,t,o,i){if(!n?.connection?.rpc||typeof n.connection.rpc.handle!="function")throw new TypeError("DSH Host Connection RPC is required");return n.connection.rpc.handle(kP,f5(t,o),{authority:fr(i)})}function qve(n,t){if(t?.controller)return t.controller;if(typeof t?.createController=="function")return t.createController();if(typeof t?.createProvisioningManager=="function")return nT(t)}async function Q5(n,t={}){let o=qve(n,t);if(o)return PS(n,o,t.rpcOptions,t.rpcAuthority);let i=await DP(n,t),e=t.deliveryService&&i.deliveryAdapter?t.deliveryService.registerAdapter(i.deliveryAdapter):void 0,a=PS(n,i.controller,t.rpcOptions,t.rpcAuthority);return n.effect(()=>async()=>{await e?.(),await i.close()},"dsh-feishu: close controller and live connection"),a}import{unlink as jPe}from"node:fs/promises";import{homedir as JPe}from"node:os";import{join as Hu,resolve as yl}from"node:path";import{createHash as zve}from"node:crypto";import{mkdir as Vve,readFile as Wve,rename as Zve,unlink as Xve,writeFile as $ve}from"node:fs/promises";import{dirname as ePe}from"node:path";var LP=Object.freeze({version:1,bots:Object.freeze([])});function vc(n){return typeof n=="string"&&n.trim()?n.trim():null}function y5(n){let t=vc(n);return t&&/^qq_[a-f0-9]{24}$/.test(t)?t:null}function APe(n){let t=vc(n);return t&&/^DSH_QQBOT_APP_SECRET_[A-F0-9]{24}$/.test(t)?t:null}function FS(n){let t=vc(n);if(!t)throw new TypeError("appId is required");let o=zve("sha256").update(t).digest("hex").slice(0,24);return{botId:`qq_${o}`,secretRef:`DSH_QQBOT_APP_SECRET_${o.toUpperCase()}`}}function UP(n){let t=vc(n)??"";return t.length<=10?t?`${t.slice(0,3)}\u2022\u2022\u2022`:w("QQ\u673A\u5668\u4EBA"):`${t.slice(0,6)}\u2022\u2022\u2022\u2022${t.slice(-4)}`}function m5(n){if(!n||typeof n!="object")return null;let t=vc(n.appId),o=vc(n.ownerUserOpenid),i=y5(n.botId),e=APe(n.secretRef);if(!t||!o||!i||!e)return null;let a=FS(t);return a.botId!==i||a.secretRef!==e?null:Object.freeze({botId:i,appId:t,secretRef:e,ownerUserOpenid:o,createdAt:vc(n.createdAt)??new Date().toISOString(),connectedAt:vc(n.connectedAt)})}function tPe(n){if(!n||n.version!==1||!Array.isArray(n.bots))return null;let t=n.bots.map(m5);if(t.some(a=>a===null))return null;let o=new Set,i=new Set,e=new Set;for(let a of t){if(o.has(a.botId)||i.has(a.appId)||e.has(a.secretRef))return null;o.add(a.botId),i.add(a.appId),e.add(a.secretRef)}return Object.freeze({version:1,bots:Object.freeze(t)})}var GS=class{#e;#A=LP;#t=Promise.resolve();constructor(t){this.#e=t}async load(){try{let t=tPe(JSON.parse(await Wve(this.#e,"utf8")));if(!t)throw new Error("dsh-im QQ config contains invalid bot data");this.#A=t}catch(t){if(t?.code!=="ENOENT")throw t;this.#A=LP}return this}list(){return structuredClone(this.#A.bots)}get(t){let o=this.#A.bots.find(i=>i.botId===t);return o?structuredClone(o):null}getByAppId(t){let o=this.#A.bots.find(i=>i.appId===t);return o?structuredClone(o):null}async save(t){let o=m5(t);if(!o)throw new Error("Refusing to persist incomplete QQ bot data");return this.#r(i=>{let e=i.find(r=>r.appId===o.appId&&r.botId!==o.botId),a=i.find(r=>r.secretRef===o.secretRef&&r.botId!==o.botId);if(e||a)throw new Error("Duplicate QQ bot identity");let A=i.findIndex(r=>r.botId===o.botId);return A===-1?i.push(o):i[A]=o,structuredClone(o)})}async remove(t){if(!y5(t))throw new TypeError("Invalid QQ bot id");return this.#r(o=>{let i=o.findIndex(a=>a.botId===t);if(i===-1)return null;let[e]=o.splice(i,1);return structuredClone(e)})}async clear(){let t=this.#t.then(async()=>{try{await Xve(this.#e)}catch(o){if(o?.code!=="ENOENT")throw o}this.#A=LP});this.#t=t.then(()=>{},()=>{}),await t}async#r(t){let o,i=this.#t.then(async()=>{let e=[...this.#A.bots];o=t(e);let a=Object.freeze({version:1,bots:Object.freeze(e)});await this.#l(a),this.#A=a});return this.#t=i.then(()=>{},()=>{}),await i,o}async#l(t){await Vve(ePe(this.#e),{recursive:!0,mode:448});let o=`${this.#e}.tmp`;await $ve(o,`${JSON.stringify(t,null,2)} `,{encoding:"utf8",mode:384}),await Zve(o,this.#e)}};var LS=class extends ur{constructor(t){super({...t,rpcIdPrefix:"qq",logPrefix:"dsh-qq"})}};import{randomUUID as rPe}from"node:crypto";var S5=new Set(["starting","pending","refreshing","connecting"]),Bl=new Set(["connected","failed","cancelled"]),aPe=5*6e4;function fl(n){return typeof n=="string"&&n.trim()?n.trim():null}function Tn(n,t){return Object.freeze({code:n,message:t})}function US(n){return n?{attemptId:n.id,status:n.state,qrRevision:n.qrRevision,pollIntervalMs:1e3,...n.verificationUrl?{verificationUrl:n.verificationUrl}:{},...n.expiresAt?{expiresAt:n.expiresAt}:{},...n.botId?{botId:n.botId}:{},...n.error?{error:structuredClone(n.error)}:{}}:null}var Fu=class{#e;#A;#t;#r;#l;#o;#i=new Map;#a=new Map;#n=new Map;#s=null;#p=new Map;#c=0;#g=!1;constructor({qrAuth:t,credentials:o,configStore:i,createRuntime:e,deleteState:a=async()=>{},logger:A=console}){if(!t||typeof t.start!="function")throw new TypeError("QQ QR auth is required");if(!o||typeof o.resolve!="function"||typeof o.set!="function"||typeof o.unset!="function")throw new TypeError("QqController requires the DSH credential provider");if(!i||typeof i.list!="function"||typeof i.save!="function"||typeof i.remove!="function")throw new TypeError("QqController requires a config store");if(typeof e!="function")throw new TypeError("createRuntime is required");this.#e=t,this.#A=o,this.#t=i,this.#r=e,this.#l=a,this.#o=A}async initialize(){if(this.#g)return this.status();for(let t of this.#t.list())await this.#f(t.botId,async()=>{if(this.#g||this.#i.get(t.botId)?.status?.ready)return;let o=await this.#u(t.secretRef);if(!o){this.#a.set(t.botId,Tn("missing-secret",w("QQ \u673A\u5668\u4EBA\u51ED\u636E\u7F3A\u5931\uFF0C\u8BF7\u79FB\u9664\u540E\u91CD\u65B0\u626B\u7801\u3002")));return}try{await this.#h(t,o),this.#a.delete(t.botId)}catch(i){this.#a.set(t.botId,Tn("connection-failed",w("QQ \u8FDE\u63A5\u672A\u5C31\u7EEA\uFF0C\u63D2\u4EF6\u4F1A\u81EA\u52A8\u91CD\u8BD5\u3002"))),this.#o.warn?.(`[dsh-im:qq] bot ${t.botId} failed to initialize:`,i)}finally{this.#Q()}});return this.status()}async startProvisioning(){if(this.#g)throw new Error("QQ controller is closed");this.#s&&await this.cancelProvisioning(this.#s);let t,o,i=new Promise((a,A)=>{t=a,o=A}),e={id:rPe(),state:"starting",createdAt:Date.now(),expiresAt:null,qrRevision:0,verificationUrl:null,controller:new AbortController,dispose:null,task:null,error:null,botId:null};this.#n.set(e.id,e),this.#s=e.id,this.#Q();try{return e.dispose=this.#e.start({onQrDisplayed:a=>{if(e.controller.signal.aborted||Bl.has(e.state))return;let A=fl(a);A&&(e.verificationUrl=A,e.qrRevision+=1,e.expiresAt=Date.now()+aPe,e.state="pending",this.#Q(),t())},onQrExpired:()=>{e.controller.signal.aborted||Bl.has(e.state)||(e.state="refreshing",e.verificationUrl=null,e.expiresAt=null,this.#Q())},onSuccess:a=>{e.controller.signal.aborted||Bl.has(e.state)||(e.task=this.#I(e,a))},onFailure:a=>{e.controller.signal.aborted||Bl.has(e.state)||(e.state="failed",e.error=Tn("qr-connect-failed",w("QQ \u626B\u7801\u670D\u52A1\u6682\u65F6\u4E0D\u53EF\u7528\uFF0C\u8BF7\u91CD\u65B0\u751F\u6210\u4E8C\u7EF4\u7801\u3002")),this.#s===e.id&&(this.#s=null),this.#Q(),o(a))}},{signal:e.controller.signal}),await i,US(e)}catch(a){throw e.controller.signal.aborted?(e.state="cancelled",e.error=Tn("cancelled",w("\u626B\u7801\u7ED1\u5B9A\u5DF2\u53D6\u6D88\u3002"))):Bl.has(e.state)||(e.state="failed",e.error=Tn("qr-start-failed",w("\u65E0\u6CD5\u751F\u6210 QQ \u4E8C\u7EF4\u7801\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002"))),this.#s===e.id&&(this.#s=null),this.#Q(),a}}registrationStatus(t){return US(this.#n.get(t))}async bindCredentials({appId:t,appSecret:o}={}){if(this.#g)throw new Error("QQ controller is closed");let i=fl(t),e=fl(o);if(!i||!e)throw new TypeError("QQ AppID and AppSecret are required");if(this.#s&&await this.cancelProvisioning(this.#s),this.#g)throw new Error("QQ controller is closed");let a=FS(i);return await this.#f(a.botId,async()=>{if(this.#g)throw new Error("QQ controller is closed");let A=this.#t.getByAppId(i),r=await this.#A.resolve(a.secretRef).catch(()=>{});if(this.#g)throw new Error("QQ controller is closed");let s={botId:a.botId,appId:i,secretRef:a.secretRef,ownerUserOpenid:A?.ownerUserOpenid??"*",createdAt:A?.createdAt??new Date().toISOString(),connectedAt:new Date().toISOString()};await this.#A.set(a.secretRef,e);try{await this.#t.save(s)}catch(g){throw await this.#B(a.secretRef,r),g}try{await this.#h(s,e),this.#a.delete(a.botId)}catch(g){this.#a.set(a.botId,Tn("connection-failed",w("QQ \u673A\u5668\u4EBA\u5DF2\u7ED1\u5B9A\uFF0C\u6D88\u606F\u8FDE\u63A5\u6682\u672A\u5C31\u7EEA\u3002"))),this.#o.warn?.(`[dsh-im:qq] bot ${a.botId} credential connection failed:`,g)}this.#Q()}),this.status()}async cancelProvisioning(t){let o=this.#n.get(t);return o?(Bl.has(o.state)||(o.controller.abort(),o.dispose?.(),await o.task?.catch(()=>{}),Bl.has(o.state)||(o.state="cancelled"),o.error??=Tn("cancelled",w("\u626B\u7801\u7ED1\u5B9A\u5DF2\u53D6\u6D88\u3002"))),this.#s===o.id&&(this.#s=null),this.#Q(),US(o)):null}async reconnectBot(t){let o=this.#t.get(t);if(!o)throw new Error("Unknown QQ bot");return await this.#f(t,async()=>{let i=await this.#u(o.secretRef);if(!i)throw new Error("QQ bot secret is missing");try{await this.#h(o,i),this.#a.delete(t)}catch(e){throw this.#a.set(t,Tn("connection-failed",w("QQ \u8FDE\u63A5\u4ECD\u672A\u5C31\u7EEA\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002"))),e}finally{this.#Q()}}),this.status()}async sendConnectionTest(t){let o=this.#t.get(t);if(!o)throw new Error("Unknown QQ bot");return this.#f(t,async()=>{let i=this.#i.get(t);if(!i?.status?.ready||typeof i.sendConnectionTest!="function"){let e=new Error(w("QQ\u673A\u5668\u4EBA\u5C1A\u672A\u8FDE\u63A5"));throw e.code="test-target-unavailable",e}return await i.sendConnectionTest(Ra(w("QQ \u673A\u5668\u4EBA\uFF08{appId}\uFF09",{appId:UP(o.appId)}))),{sent:!0}})}async sendProactiveText(t,o,i,e={}){if(!this.#t.get(t))throw new Error("Unknown QQ bot");return this.#f(t,async()=>{let A=this.#i.get(t);if(!A?.status?.ready||typeof A.sendProactiveText!="function"){let r=new Error(w("QQ\u673A\u5668\u4EBA\u5C1A\u672A\u8FDE\u63A5"));throw r.code="bot-not-connected",r}return A.sendProactiveText(o,i,e)})}async deleteBot(t){let o=this.#t.get(t);if(!o)throw new Error("Unknown QQ bot");return await this.#f(t,async()=>{let i=await this.#A.resolve(o.secretRef).catch(()=>{});await this.#C(t);try{await this.#A.unset(o.secretRef),await this.#t.remove(t)}catch(e){throw i?.value&&(await this.#A.set(o.secretRef,i.value).catch(()=>{}),await this.#h(o,i.value).catch(()=>{})),new Error("Unable to remove the QQ bot safely.",{cause:e})}await this.#l({botId:t,config:o}).catch(e=>{this.#o.warn?.(`[dsh-im:qq] bot ${t} state cleanup failed:`,e)}),this.#a.delete(t),this.#Q()}),this.status()}status(){let t=this.#t.list().map(e=>{let a=this.#i.get(e.botId)?.status??null,A=a?.ready===!0&&a.qqConnectionState==="connected"&&a.harnessReachable===!0,r=A?"connected":a?.qqConnectionState==="connecting"?"connecting":this.#a.has(e.botId)||a?.qqConnectionState==="failed"?"error":"offline";return{botId:e.botId,state:r,connected:A,configured:!0,bot:{name:w("QQ\u673A\u5668\u4EBA"),appIdMasked:UP(e.appId)},health:{status:A?"healthy":r==="error"?"error":"offline",summary:A?w("QQ WebSocket \u957F\u8FDE\u63A5\u8FD0\u884C\u6B63\u5E38"):r==="error"?w("QQ \u8FDE\u63A5\u672A\u5C31\u7EEA\uFF0C\u63D2\u4EF6\u4F1A\u81EA\u52A8\u91CD\u8BD5"):w("QQ \u8FDE\u63A5\u5F53\u524D\u79BB\u7EBF"),lastCheckedAt:a?.lastCheckedAt??null,lastConnectedAt:a?.lastConnectedAt??null},stats:{messagesReceived:a?.messagesReceived??0,messagesReplied:a?.messagesReplied??0},lastMessageError:Xr(a?.lastMessageError),error:structuredClone(this.#a.get(e.botId)??null)}}),o=t.filter(e=>e.connected).length,i=this.#s?this.#n.get(this.#s):null;return{schemaVersion:1,revision:this.#c,state:i&&S5.has(i.state)?"provisioning":t.length===0?"disconnected":o===t.length?"connected":o>0?"degraded":"offline",bots:t,totals:{configured:t.length,connected:o},...i&&S5.has(i.state)?{provisioning:US(i)}:{}}}async close(){this.#g||(this.#g=!0,this.#s&&await this.cancelProvisioning(this.#s),await Promise.allSettled([...this.#p.values()]),await Promise.allSettled([...this.#i.keys()].map(t=>this.#C(t))))}async#I(t,o){try{t.state="connecting",t.verificationUrl=null,t.expiresAt=null,this.#Q();let i=Array.isArray(o)?o[0]:null,e=fl(i?.appId),a=fl(i?.appSecret),A=fl(i?.userOpenid);if(!e||!a||!A)throw new Error("QQ authorization returned incomplete credentials");t.botId=await this.#d(t,{appId:e,appSecret:a,ownerUserOpenid:A}),t.state="connected",t.error=null}catch(i){t.controller.signal.aborted?(t.state="cancelled",t.error=Tn("cancelled",w("\u626B\u7801\u7ED1\u5B9A\u5DF2\u53D6\u6D88\u3002"))):(t.state="failed",t.error=Tn("activation-failed",w("QQ \u5DF2\u6388\u6743\uFF0C\u4F46\u65E0\u6CD5\u5B89\u5168\u4FDD\u5B58\u63A5\u5165\u914D\u7F6E\u3002")),this.#o.error?.("[dsh-im:qq] provisioning failed:",i))}finally{t.dispose?.(),this.#s===t.id&&(this.#s=null),this.#Q()}}async#d(t,{appId:o,appSecret:i,ownerUserOpenid:e}){let a=FS(o),A=this.#t.getByAppId(o),r=await this.#A.resolve(a.secretRef).catch(()=>{}),s={botId:a.botId,appId:o,secretRef:a.secretRef,ownerUserOpenid:e,createdAt:A?.createdAt??new Date().toISOString(),connectedAt:new Date().toISOString()};return this.#f(a.botId,async()=>{await this.#A.set(a.secretRef,i);try{if(t.controller.signal.aborted)throw new DOMException("Cancelled","AbortError");await this.#t.save(s)}catch(g){throw await this.#B(a.secretRef,r),g}try{if(t.controller.signal.aborted)throw new DOMException("Cancelled","AbortError");await this.#h(s,i),this.#a.delete(a.botId)}catch(g){if(t.controller.signal.aborted)throw await this.#C(a.botId),A?await this.#t.save(A).catch(()=>{}):await this.#t.remove(a.botId).catch(()=>null)&&await this.#l({botId:a.botId,config:s}).catch(I=>{this.#o.warn?.("[dsh-im:qq] cancelled bot state cleanup failed:",I)}),await this.#B(a.secretRef,r),g;this.#a.set(a.botId,Tn("connection-failed",w("QQ \u673A\u5668\u4EBA\u5DF2\u7ED1\u5B9A\uFF0C\u6D88\u606F\u8FDE\u63A5\u6682\u672A\u5C31\u7EEA\u3002"))),this.#o.warn?.(`[dsh-im:qq] bot ${a.botId} activation connection failed:`,g)}return this.#Q(),a.botId})}async#h(t,o){if(this.#g)throw new Error("QQ controller is closed");if(await this.#C(t.botId),this.#g)throw new Error("QQ controller is closed");let i=await this.#r({botId:t.botId,config:t,appSecret:o});if(!i||typeof i.start!="function"||typeof i.stop!="function")throw new TypeError("createRuntime returned an invalid QQ runtime");this.#i.set(t.botId,i);try{await i.start()}catch(e){throw await i.stop().catch(()=>{}),this.#i.delete(t.botId),e}}async#C(t){let o=this.#i.get(t);this.#i.delete(t),await o?.stop().catch(i=>{this.#o.warn?.(`[dsh-im:qq] bot ${t} failed to stop cleanly:`,i)})}async#u(t){let o=await this.#A.resolve(t).catch(()=>{});return fl(o?.value)}async#B(t,o){o?.value?await this.#A.set(t,o.value).catch(()=>{}):await this.#A.unset(t).catch(()=>{})}#f(t,o){let a=(this.#p.get(t)??Promise.resolve()).catch(()=>{}).then(o).finally(()=>{this.#p.get(t)===a&&this.#p.delete(t)});return this.#p.set(t,a),a}#Q(){this.#c+=1}};import{QQBot as TPe,contentSanitizer as NPe,typingIndicator as RPe}from"@tencent-connect/qqbot-nodejs";import{ApiError as iPe}from"@tencent-connect/qqbot-nodejs";var w5=4500,oPe=/^( {0,3})(`{3,}|~{3,})(.*)$/,nPe=new Set([40034090]),sPe=Object.freeze({c2c:4,group:5}),gPe=()=>w("\u56DE\u7B54\u8F83\u957F\uFF0C\u540E\u7EED\u5185\u5BB9\u672A\u80FD\u901A\u8FC7 QQ \u5B8C\u6574\u53D1\u9001\uFF0C\u8BF7\u56DE\u590D\u201C\u7EE7\u7EED\u201D\u3002");function KP(n,t){let o=Math.min(t,n.length),i=n.charCodeAt(o-1),e=n.charCodeAt(o);return i>=55296&&i<=56319&&e>=56320&&e<=57343&&(o-=1),Math.max(1,o)}function b5(n){let t=n.endsWith("\r")?n.slice(0,-1):n,o=oPe.exec(t);return!o||o[2][0]==="`"&&o[3].includes("`")?null:{delimiter:o[2],info:o[3],indent:o[1].length}}function cPe(n,t){let o=/^ {0,3}(`{3,}|~{3,})[ \t]*$/.exec(n);return!!(o&&o[1][0]===t.delimiter[0]&&o[1].length>=t.delimiter.length)}function D5(n,t){let o=0;for(let i of n.split(` `)){let e=0;for(;e<3&&i[e]===" ";)e+=1;let a=0;for(;i[e+a]===t;)a+=1;o=Math.max(o,a)}return o}function IPe(n,t){let o="`".repeat(Math.max(3,D5(n,"`")+1)),i="~".repeat(Math.max(3,D5(n,"~")+1));return t.includes("`")?i:o.length<=i.length?o:i}function lPe(n,t){let o=0,i=0,e=t;for(;e>0&&olPe(o,t))}function HP(n,t){if(n.length<=t)return[n];let o=[],i=n;for(;i.length>t;){let e=KP(i,t),a=i.lastIndexOf(` @@ -398,7 +398,7 @@ ${T}`:K),await g()}catch(K){this.#a.error?.("[dsh-im:qq] failed to send the safe `,{encoding:"utf8",mode:384}),await AGe(A,this.#e),this.#A=a});return this.#t=i.then(()=>{},()=>{}),await i,o}};var nGe="https://slack.com/api/",Yu="files.slack.com",sGe="slack.com",K5="/files-pri/",gGe=Object.freeze([Yu]),cGe="/upload/",IGe=12e4;function Ss(n){return typeof n=="string"&&n.trim()?n.trim():null}function x5(n,t){let o=AbortSignal.timeout(t);return n?AbortSignal.any([n,o]):o}function Ku(n){return n?.reason instanceof Error?n.reason:new DOMException("The operation was aborted","AbortError")}function lGe(n,t){if(!Number.isInteger(n)||n<1)throw new TypeError(`${t} must be a positive integer`);return n}function Y5(n,t){return t?.providerCode!==void 0&&(n.providerCode=t.providerCode),Number.isInteger(t?.status)&&(n.status=t.status),n}function ml(n){let t="artifact-provider-failed",o="Slack file upload preparation failed";n?.code==="slack-file_upload_size_restricted"?(t="artifact-too-large",o="Slack rejected the result file because it is too large"):n?.code==="slack-missing-scope"?(t="artifact-permission-required",o="Slack file delivery requires the files:write scope"):n?.code?.startsWith?.("slack-")&&(t="artifact-provider-rejected",o="Slack rejected file upload preparation");let i=new Error(o,{cause:n});return i.code=t,Y5(i,n)}function pGe(n){let t=new Error("Slack file completion result is uncertain",{cause:n});return t.code="artifact-delivery-uncertain",Y5(t,n)}function dGe(n){return Number.isInteger(n)&&n>=300&&n<400}async function tG(n){try{await n?.body?.cancel?.()}catch{}}function hGe(n){let t=new URL(n);if(t.protocol!=="https:")throw new Error("Image download URL must use HTTPS");if(t.username||t.password||t.port&&t.port!=="443")throw new Error("Image download URL is not hosted by the messaging platform");if(t.hostname===sGe&&t.pathname.startsWith(K5)&&(t.hostname=Yu),t.hostname!==Yu||!t.pathname.startsWith(K5))throw new Error("Image download URL is not hosted by the messaging platform");return t.hash="",t}function EGe(n){let t=new URL(n);if(t.protocol!=="https:"||t.username||t.password||t.port&&t.port!=="443"||t.hostname!==Yu||!t.pathname.startsWith(cGe))throw new Error("Slack returned an unsafe file upload URL");return t.hash="",t}function CGe(n,t){let o=n?.headers?.get?.("location");if(!o)return null;try{return new URL(o,t)}catch{return null}}function uGe(n){let t=n?.headers?.get?.("x-oauth-scopes");return t==null?null:new Set(t.split(",").map(o=>o.trim()).filter(Boolean))}function BGe(n){return n?.protocol==="https:"&&!n.username&&!n.password&&(!n.port||n.port==="443")&&n.hostname.endsWith(".slack.com")&&n.hostname!==Yu&&n.pathname==="/"&&n.searchParams.has("redir")}function fGe(n,t){return new Promise((o,i)=>{if(t?.aborted){i(t.reason??new DOMException("Aborted","AbortError"));return}let e=setTimeout(o,n);e?.unref?.(),t?.addEventListener("abort",()=>{clearTimeout(e),i(t.reason??new DOMException("Aborted","AbortError"))},{once:!0})})}function Nn(n,t){let o=Ss(n);if(!o||!/^[A-Z][A-Z0-9]{4,30}$/i.test(o))throw new TypeError(`Invalid Slack ${t}`);return o}function ms(n,t){let o=Ss(n);if(!o)throw new TypeError(`Slack ${t} is required`);return o}function xu(n,{trim:t=!0}={}){let o=typeof n=="string"?n:"",i=t?o.trim():o;if(!i)throw new TypeError("Slack message text is required");return i.replace(/<@([A-Z0-9]+)>/gi,"@$1").replace(/]*)?>/gi,"@$1")}function QGe(n,t,o){let i=Ss(t?.error)??"unknown_error",e=new Error(`Slack ${n} failed: ${i.replaceAll("_"," ")}`);return e.providerCode=i,["invalid_auth","not_authed","token_revoked","account_inactive"].includes(i)?e.code=o==="app"?"slack-invalid-app-token":"slack-invalid-bot-token":i==="missing_scope"?e.code="slack-missing-scope":i==="method_not_supported_for_channel_type"||i==="channel_type_not_supported"||i==="deprecated_endpoint"?e.code="slack-stream-unavailable":e.code=`slack-${i}`,e}function j5(n){return typeof n=="string"&&/^xoxb-[A-Za-z0-9-]{16,}$/.test(n.trim())}function J5(n){return typeof n=="string"&&/^xapp-[A-Za-z0-9-]{16,}$/.test(n.trim())}var ju=class{#e;#A;#t;#r;#l=null;#o;constructor({botToken:t,appToken:o,fetchImpl:i=fetch,baseUrl:e=nGe,fileUploadTimeoutMs:a=IGe}){if(t!==void 0&&!j5(t))throw new TypeError("Slack Bot Token is invalid");if(o!==void 0&&!J5(o))throw new TypeError("Slack App Token is invalid");if(!t&&!o)throw new TypeError("SlackApi requires a token");if(typeof i!="function")throw new TypeError("SlackApi requires fetch");this.#e=t?.trim(),this.#A=o?.trim(),this.#t=i,this.#r=new URL(e),this.#o=lGe(a,"fileUploadTimeoutMs")}authTest(t={}){return this.#a("auth.test",{...t,tokenKind:"bot"})}openConnection(t={}){return this.#a("apps.connections.open",{...t,tokenKind:"app",body:void 0})}async fileInfo({fileId:t,signal:o}={}){let i=await this.#a("files.info",{tokenKind:"bot",signal:o,body:{file:Nn(t,"file id")}});if(!i?.file||typeof i.file!="object"||Array.isArray(i.file))throw new Error("Slack files.info returned no file object");return i.file}postMessage({channelId:t,text:o,threadTs:i,signal:e}){return this.#a("chat.postMessage",{tokenKind:"bot",signal:e,body:{channel:Nn(t,"channel id"),text:xu(o),...i?{thread_ts:Ss(i)}:{},mrkdwn:!0,link_names:!1,unfurl_links:!1,unfurl_media:!1}})}updateMessage({channelId:t,ts:o,text:i,signal:e}){return this.#a("chat.update",{tokenKind:"bot",signal:e,body:{channel:Nn(t,"channel id"),ts:ms(o,"message timestamp"),text:xu(i),parse:"none",link_names:!1}})}addReaction({channelId:t,messageTs:o,emojiName:i,signal:e,timeoutMs:a}){return this.#a("reactions.add",{tokenKind:"bot",signal:e,timeoutMs:a,retry:!1,body:{channel:Nn(t,"channel id"),timestamp:ms(o,"message timestamp"),name:ms(i,"reaction name")}})}removeReaction({channelId:t,messageTs:o,emojiName:i,signal:e,timeoutMs:a}){return this.#a("reactions.remove",{tokenKind:"bot",signal:e,timeoutMs:a,retry:!1,body:{channel:Nn(t,"channel id"),timestamp:ms(o,"message timestamp"),name:ms(i,"reaction name")}})}startStream({channelId:t,threadTs:o,recipientTeamId:i,recipientUserId:e,markdownText:a,signal:A}){return this.#a("chat.startStream",{tokenKind:"bot",signal:A,body:{channel:Nn(t,"channel id"),thread_ts:ms(o,"thread timestamp"),...i?{recipient_team_id:Nn(i,"team id")}:{},...e?{recipient_user_id:Nn(e,"user id")}:{},...Ss(a)?{markdown_text:xu(a)}:{}}})}appendStream({channelId:t,ts:o,markdownText:i,signal:e}){return this.#a("chat.appendStream",{tokenKind:"bot",signal:e,body:{channel:Nn(t,"channel id"),ts:ms(o,"stream timestamp"),markdown_text:xu(i,{trim:!1})}})}stopStream({channelId:t,ts:o,markdownText:i,signal:e}){return this.#a("chat.stopStream",{tokenKind:"bot",signal:e,body:{channel:Nn(t,"channel id"),ts:ms(o,"stream timestamp"),...Ss(i)?{markdown_text:xu(i,{trim:!1})}:{}}})}async uploadFile({channelId:t,threadTs:o,file:i,signal:e}){if(!i||typeof i!="object"||typeof i.fileName!="string"||!i.fileName||!Buffer.isBuffer(i.bytes))throw new TypeError("A Slack file is required");if(e?.aborted)throw Ku(e);let a=x5(e,this.#o),A;try{A=await this.#a("files.getUploadURLExternal",{tokenKind:"bot",signal:a,timeoutMs:this.#o,body:{filename:i.fileName,length:i.bytes.byteLength}})}catch(I){throw e?.aborted?Ku(e):ml(I)}let r,s;try{r=ms(A?.file_id,"file id"),s=EGe(A?.upload_url)}catch(I){throw ml(I)}let g;try{g=await this.#t(s,{method:"POST",headers:{"content-type":i.mediaType??"application/octet-stream"},body:i.bytes,signal:a,redirect:"error"})}catch(I){throw e?.aborted?Ku(e):ml(I)}if(!Number.isInteger(g?.status))throw ml(new Error("Slack file upload returned an invalid response"));if(g.status!==200){await tG(g);let I=new Error(`Slack file upload failed with HTTP ${g.status}`);throw I.status=g.status,g.status===413?I.code="artifact-too-large":g.status===429?I.code="artifact-rate-limited":I.code="artifact-provider-rejected",I}await tG(g);let c;try{c={files:[{id:r,title:i.fileName}],channel_id:Nn(t,"channel id"),...o?{thread_ts:ms(o,"thread timestamp")}:{}}}catch(I){throw ml(I)}if(a.aborted)throw e?.aborted?Ku(e):ml(a.reason);try{let I=await this.#a("files.completeUploadExternal",{tokenKind:"bot",signal:a,timeoutMs:this.#o,retry:!1,body:c});if(!Array.isArray(I?.files)||!I.files.some(d=>Ss(d?.id)===r))throw new Error("Slack file completion did not confirm the uploaded file");return I}catch(I){throw e?.aborted?Ku(e):I?.code==="slack-missing-scope"?ml(I):pGe(I)}}async downloadFile({url:t,signal:o,maxBytes:i}){return this.#i({url:t,signal:o,maxBytes:i,stream:!1})}async downloadFileStream({url:t,signal:o}){return this.#i({url:t,signal:o,stream:!0})}async#i({url:t,signal:o,maxBytes:i,stream:e}){if(!this.#e)throw new TypeError("Slack bot token is required for file download");let a=hGe(t),r={fetchImpl:async(s,g)=>{let c=await this.#t(s,g);if(!dGe(c?.status))return c;let I=CGe(c,s);if(this.#l&&!this.#l.has("files:read")||BGe(I))throw await tG(c),new ut("slack-file-access-required","Slack redirected a private file request to the workspace because file access was not granted",w("Slack \u672A\u6388\u6743\u673A\u5668\u4EBA\u8BFB\u53D6\u8BE5\u6587\u4EF6\u3002\u8BF7\u4E3A\u5E94\u7528\u6DFB\u52A0 files:read \u540E\u91CD\u65B0\u5B89\u88C5\uFF0C\u518D\u91CD\u65B0\u53D1\u9001\u56FE\u7247\u3002"));return c},headers:{authorization:`Bearer ${this.#e}`},signal:o,allowedHosts:gGe};return e?Yp(a,r):Do(a,{...r,maxBytes:i})}async#a(t,{tokenKind:o,body:i,signal:e,timeoutMs:a=15e3,retry:A=!0}){let r=o==="app"?this.#A:this.#e;if(!r)throw new TypeError(`Slack ${o} token is required for ${t}`);let s=t==="files.getUploadURLExternal"||t==="files.info",g;try{g=await this.#t(new URL(t,this.#r),{method:"POST",headers:{authorization:`Bearer ${r}`,"content-type":i===void 0||s?"application/x-www-form-urlencoded;charset=utf-8":"application/json;charset=utf-8","user-agent":"DeepSeek-Harness-dsh-im (https://github.com/xmanrui/dsh-im, 0.2.2)"},...i===void 0?{}:{body:s?new URLSearchParams(i).toString():JSON.stringify(i)},signal:x5(e,a),redirect:"error"})}catch(I){throw I?.name==="AbortError"||I?.name==="TimeoutError"?I:new Error(`Slack ${t} transport failed`)}if(o==="bot"){let I=uGe(g);I&&(this.#l=I)}let c;try{c=await g.json()}catch{throw new Error(`Slack ${t} returned invalid JSON`)}if(g.status===429&&A){let I=Number(g.headers.get("retry-after"))||1;return await fGe(Math.min(1e4,Math.max(100,I*1e3)),e),this.#a(t,{tokenKind:o,body:i,signal:e,timeoutMs:a,retry:!1})}if(!g.ok||c?.ok!==!0){let I=QGe(t,c,o);throw I.status=g.status,I}return c}};async function q5({botToken:n,appToken:t},o={}){if(!j5(n)){let r=new TypeError(w("Slack Bot Token \u5FC5\u987B\u4EE5 xoxb- \u5F00\u5934\u3002"));throw r.code="slack-invalid-bot-token",r}if(!J5(t)){let r=new TypeError(w("Slack App Token \u5FC5\u987B\u4EE5 xapp- \u5F00\u5934\u3002"));throw r.code="slack-invalid-app-token",r}let i=new ju({botToken:n,appToken:t,...o}),[e,a]=await Promise.all([i.authTest(),i.openConnection()]);if(!e?.team_id||!e?.user_id||!e?.bot_id)throw new Error(w("Slack Bot Token \u6CA1\u6709\u8FD4\u56DE\u5B8C\u6574\u7684\u673A\u5668\u4EBA\u8EAB\u4EFD\u3002"));let A;try{A=new URL(a?.url)}catch{A=null}if(!A||A.protocol!=="wss:"){let r=new Error(w("Slack App Token \u65E0\u6CD5\u521B\u5EFA Socket Mode \u8FDE\u63A5\uFF0C\u8BF7\u786E\u8BA4\u5DF2\u542F\u7528 Socket Mode \u548C connections:write\u3002"));throw r.code="slack-socket-mode",r}return{platformId:`${e.team_id}:${e.user_id}`,name:Ss(e.user)??"DeepSeek Harness",username:Ss(e.user),teamId:String(e.team_id),teamName:Ss(e.team)}}var rG=Object.freeze({key:"slack",label:"Slack",connectionLabel:" Socket Mode \u957F\u8FDE\u63A5",reactions:Object.freeze({processing:"eyes",success:"white_check_mark",error:"x"})}),WS=class extends ns{constructor(t){super({descriptor:rG,...t})}};function Ng(n){return typeof n=="string"&&n.trim()?n.trim():null}function ZS(n,t){return Object.freeze({code:n,message:t})}var Ju=class{#e;#A;#t;#r;#l;#o;#i=new Map;#a=new Map;#n=new Map;#s=0;#p=!1;constructor({credentials:t,configStore:o,inspectCredentials:i=q5,createRuntime:e,deleteState:a=async()=>{},logger:A=console}){if(!t||typeof t.resolve!="function"||typeof t.set!="function"||typeof t.unset!="function")throw new TypeError("Slack requires the DSH credential provider");if(!o||typeof o.list!="function"||typeof o.save!="function"||typeof o.remove!="function")throw new TypeError("Slack requires a config store");if(typeof i!="function"||typeof e!="function")throw new TypeError("Slack controller dependencies are incomplete");this.#e=t,this.#A=o,this.#t=i,this.#r=e,this.#l=a,this.#o=A}async initialize(){if(this.#p)return this.status();for(let t of this.#A.list())await this.#h(t.botId,async()=>{if(this.#p||this.#i.get(t.botId)?.status?.ready)return;let o=await this.#I(t);if(!o){this.#a.set(t.botId,ZS("missing-token",w("Slack\u673A\u5668\u4EBA\u51ED\u636E\u7F3A\u5931\uFF0C\u8BF7\u79FB\u9664\u540E\u91CD\u65B0\u63A5\u5165\u3002")));return}try{await this.#c(t,o),this.#a.delete(t.botId)}catch(i){this.#a.set(t.botId,ZS("connection-failed",w("Slack Socket Mode \u8FDE\u63A5\u672A\u5C31\u7EEA\uFF0C\u63D2\u4EF6\u4F1A\u81EA\u52A8\u91CD\u8BD5\u3002"))),this.#o.warn?.(`[dsh-im:slack] bot ${t.botId} failed to initialize:`,i)}finally{this.#C()}});return this.status()}async bindCredentials({botToken:t,appToken:o}={}){if(this.#p)throw new Error("Slack controller is closed");let i=Ng(t),e=Ng(o);if(!i||!e)throw new TypeError("Slack Bot Token and App Token are required");let a=await this.#t({botToken:i,appToken:e}),A=Ng(a?.platformId),r=Ng(a?.name);if(!A||!r)throw new Error("Slack returned an invalid bot identity");let s=eG(A);return await this.#h(s.botId,async()=>{if(this.#p)throw new Error("Slack controller is closed");let g=this.#A.getByPlatformId(A),c=await this.#e.resolve(s.botTokenRef).catch(()=>{}),I=await this.#e.resolve(s.appTokenRef).catch(()=>{}),d={...s,platformId:A,name:r,username:Ng(a.username),teamId:Ng(a.teamId),teamName:Ng(a.teamName),createdAt:g?.createdAt??new Date().toISOString(),connectedAt:new Date().toISOString()};try{await this.#e.set(s.botTokenRef,i),await this.#e.set(s.appTokenRef,e),await this.#A.save(d)}catch(B){throw await Promise.all([this.#d(s.botTokenRef,c),this.#d(s.appTokenRef,I)]),B}try{await this.#c(d,{botToken:i,appToken:e}),this.#a.delete(s.botId)}catch(B){this.#a.set(s.botId,ZS("connection-failed",w("Slack\u673A\u5668\u4EBA\u5DF2\u63A5\u5165\uFF0CSocket Mode \u8FDE\u63A5\u6682\u672A\u5C31\u7EEA\u3002"))),this.#o.warn?.(`[dsh-im:slack] bot ${s.botId} credential connection failed:`,B)}this.#C()}),this.status()}async reconnectBot(t){let o=this.#A.get(t);if(!o)throw new Error("Unknown Slack bot");return await this.#h(t,async()=>{let i=await this.#I(o);if(!i)throw new Error("Slack bot credentials are missing");try{await this.#c(o,i),this.#a.delete(t)}catch(e){throw this.#a.set(t,ZS("connection-failed",w("Slack Socket Mode \u8FDE\u63A5\u4ECD\u672A\u5C31\u7EEA\uFF0C\u8BF7\u68C0\u67E5\u4E24\u4E2A Token\u3002"))),e}finally{this.#C()}}),this.status()}async sendConnectionTest(t){let o=this.#A.get(t);if(!o)throw new Error("Unknown Slack bot");return this.#h(t,async()=>{let i=this.#i.get(t);if(!i?.status?.ready||typeof i.sendConnectionTest!="function"){let e=new Error(w("Slack\u673A\u5668\u4EBA\u5C1A\u672A\u8FDE\u63A5"));throw e.code="test-target-unavailable",e}return await i.sendConnectionTest(Ra(`${o.name}\uFF08${AG(o.platformId)}\uFF09`,w("Slack\u673A\u5668\u4EBA"))),{sent:!0}})}async sendProactiveText(t,o,i,e={}){if(!this.#A.get(t))throw new Error("Unknown Slack bot");return this.#h(t,async()=>{let A=this.#i.get(t);if(!A?.status?.ready||typeof A.sendProactiveText!="function"){let r=new Error(w("Slack\u673A\u5668\u4EBA\u5C1A\u672A\u8FDE\u63A5"));throw r.code="bot-not-connected",r}return A.sendProactiveText(o,i,e)})}async deleteBot(t){let o=this.#A.get(t);if(!o)throw new Error("Unknown Slack bot");return await this.#h(t,async()=>{let i=await this.#e.resolve(o.botTokenRef).catch(()=>{}),e=await this.#e.resolve(o.appTokenRef).catch(()=>{});await this.#g(t);try{await this.#e.unset(o.botTokenRef),await this.#e.unset(o.appTokenRef),await this.#A.remove(t)}catch(a){throw await Promise.all([this.#d(o.botTokenRef,i),this.#d(o.appTokenRef,e)]),i?.value&&e?.value&&await this.#c(o,{botToken:i.value,appToken:e.value}).catch(()=>{}),new Error("Unable to remove the Slack bot safely.",{cause:a})}await this.#l({botId:t,config:o}).catch(a=>{this.#o.warn?.(`[dsh-im:slack] bot ${t} state cleanup failed:`,a)}),this.#a.delete(t),this.#C()}),this.status()}status(){let t=this.#A.list().map(i=>{let e=this.#i.get(i.botId)?.status??null,a=e?.ready===!0&&e.connectionState==="connected"&&e.harnessReachable===!0,A=a?"connected":e?.connectionState==="connecting"?"connecting":this.#a.has(i.botId)||e?.connectionState==="failed"?"error":"offline";return{botId:i.botId,state:A,connected:a,configured:!0,bot:{name:i.name,username:i.username,teamName:i.teamName,idMasked:AG(i.platformId)},health:{status:a?"healthy":A==="error"?"error":"offline",summary:a?w(`Slack${rG.connectionLabel}\u8FD0\u884C\u6B63\u5E38`):A==="error"?w("Slack\u8FDE\u63A5\u672A\u5C31\u7EEA\uFF0C\u63D2\u4EF6\u4F1A\u81EA\u52A8\u91CD\u8BD5"):w("Slack\u8FDE\u63A5\u5F53\u524D\u79BB\u7EBF"),lastCheckedAt:e?.lastCheckedAt??null,lastConnectedAt:e?.lastConnectedAt??null},stats:{messagesReceived:e?.messagesReceived??0,messagesReplied:e?.messagesReplied??0},lastMessageError:Xr(e?.lastMessageError),error:structuredClone(this.#a.get(i.botId)??null)}}),o=t.filter(i=>i.connected).length;return{schemaVersion:1,revision:this.#s,state:t.length===0?"disconnected":o===t.length?"connected":o>0?"degraded":"offline",bots:t,totals:{configured:t.length,connected:o}}}async close(){this.#p||(this.#p=!0,await Promise.allSettled([...this.#n.values()]),await Promise.allSettled([...this.#i.keys()].map(t=>this.#g(t))))}async#c(t,{botToken:o,appToken:i}){if(this.#p)throw new Error("Slack controller is closed");if(await this.#g(t.botId),this.#p)throw new Error("Slack controller is closed");let e=await this.#r({botId:t.botId,config:t,botToken:o,appToken:i});if(!e||typeof e.start!="function"||typeof e.stop!="function")throw new TypeError("createRuntime returned an invalid Slack runtime");this.#i.set(t.botId,e);try{await e.start()}catch(a){throw await e.stop().catch(()=>{}),this.#i.delete(t.botId),a}}async#g(t){let o=this.#i.get(t);this.#i.delete(t),await o?.stop().catch(i=>{this.#o.warn?.(`[dsh-im:slack] bot ${t} failed to stop cleanly:`,i)})}async#I(t){let[o,i]=await Promise.all([this.#e.resolve(t.botTokenRef).catch(()=>{}),this.#e.resolve(t.appTokenRef).catch(()=>{})]),e=Ng(o?.value),a=Ng(i?.value);return e&&a?{botToken:e,appToken:a}:null}async#d(t,o){o?.value?await this.#e.set(t,o.value).catch(()=>{}):await this.#e.unset(t).catch(()=>{})}#h(t,o){let a=(this.#n.get(t)??Promise.resolve()).catch(()=>{}).then(o).finally(()=>{this.#n.get(t)===a&&this.#n.delete(t)});return this.#n.set(t,a),a}#C(){this.#s+=1}};var XS=class extends ur{constructor(t){super({...t,rpcIdPrefix:"slack",logPrefix:"dsh-slack"})}};var z5=Object.freeze([1e3,3e3,5e3,1e4,3e4]),iG=38e3,V5=11e3,Z5=new Set(["image/jpeg","image/png","image/webp","image/gif"]);function aG(n,t,o){if(typeof n.addEventListener=="function")n.addEventListener(t,o);else if(typeof n.on=="function")n.on(t,o);else throw new TypeError("Slack WebSocket does not support events")}function yGe(n){let t=n?.data??n;return typeof t=="string"?t:Buffer.isBuffer(t)?t.toString("utf8"):t instanceof ArrayBuffer?Buffer.from(t).toString("utf8"):ArrayBuffer.isView(t)?Buffer.from(t.buffer,t.byteOffset,t.byteLength).toString("utf8"):null}function mGe(n){let t=new URL(n);if(t.protocol!=="wss:")throw new Error("Slack returned an insecure Socket Mode URL");return t.href}function SGe(n){return typeof n=="string"?n.replaceAll("&","&").replaceAll("<","<").replaceAll(">",">"):""}function wGe(n,t){return SGe(n).replace(new RegExp(`<@${t}>`,"gi"),"").trim()}function oG(n){return typeof n?.url_private_download=="string"&&n.url_private_download?n.url_private_download:n?.url_private}function DGe(n,t){let o=typeof n?.mimetype=="string"?n.mimetype.toLowerCase():"",i=oG(n);return!Z5.has(o)||typeof i!="string"||!i?null:{name:typeof n.name=="string"?n.name:void 0,mediaType:o,size:Number.isSafeInteger(n.size)&&n.size>=0?n.size:void 0,load:e=>t(i,e)}}function OGe(n,t,o){let i=typeof n?.mimetype=="string"&&n.mimetype?n.mimetype.toLowerCase():void 0,e=oG(n);if(Z5.has(i))return null;let a=n?.file_access==="check_file_info"&&typeof n?.id=="string"&&n.id;return(typeof e!="string"||!e)&&!a?null:{name:typeof n?.name=="string"&&n.name?n.name:typeof n?.title=="string"&&n.title?n.title:a?n.id:"slack-file",...i?{mediaType:i}:{},size:Number.isSafeInteger(n?.size)&&n.size>=0?n.size:void 0,load:async({signal:A}={})=>{if(!a)return t(e,{signal:A});let r=await o(n.id,{signal:A}),s=oG(r);if(typeof s!="string"||!s)throw new Error("Slack files.info returned no downloadable URL");let g=await t(s,{signal:A}),c=typeof r?.name=="string"&&r.name?r.name:typeof r?.title=="string"&&r.title?r.title:n.id,I=typeof r?.mimetype=="string"&&r.mimetype?r.mimetype.toLowerCase():void 0;return Buffer.isBuffer(g)||g instanceof Uint8Array?{data:g,name:c,...I?{mediaType:I}:{}}:{...g,name:c,...I?{mediaType:I}:{}}}}}function bGe(n,t,{loadFile:o=async()=>{throw new Error("Slack file downloader is unavailable")},loadFileStream:i=o,loadFileInfo:e=async()=>{throw new Error("Slack file metadata loader is unavailable")}}={}){let a=n?.event;if(!a||!n?.event_id||!a.channel||!a.user||!a.ts)return null;let A=a.type==="message"&&a.channel_type==="im",r=a.type==="app_mention";if(!A&&!r||a.subtype&&a.subtype!=="file_share"||a.bot_id||a.app_id)return null;let s=String(a.thread_ts??a.ts);return{messageId:String(n.event_id),senderId:String(a.user),senderIsBot:String(a.user)===String(t),kind:A?"direct":"group",conversationId:A?String(a.channel):`${a.channel}:${s}`,content:wGe(a.text??"",t),plainText:!Array.isArray(a.files)||a.files.length===0,images:Array.isArray(a.files)?a.files.map(g=>DGe(g,o)).filter(Boolean):[],files:Array.isArray(a.files)?a.files.map(g=>OGe(g,i,e)).filter(Boolean):[],addressed:A||r,reactionTarget:{channelId:String(a.channel),messageTs:String(a.ts)},replyTarget:{channelId:String(a.channel),threadTs:s,recipientUserId:String(a.user),recipientTeamId:String(a.user_team??n.team_id??"")},connectionTestTarget:{channelId:String(a.channel)}}}function MGe(n){if(typeof n!="string")return!1;let t="__DSH_IM_TOOL_NAME__",o=w("\u6B63\u5728\u4F7F\u7528{name}\u2026",{name:t}),i=o.indexOf(t);if(i<0)return!1;let e=o.slice(0,i),a=o.slice(i+t.length),A=n.trim();return A.startsWith(e)&&A.endsWith(a)&&A.length>e.length+a.length}async function W5(n,t,o,i,e){if(i)for(let a=0;a{let y=ss(Q,iG)[0]??"";if(!y||!y.startsWith(A))return;let m=y.slice(A.length);m&&(await W5(n,t,a,m,o),A=y)},f=()=>{I||c||s!==null||g||!r||(s=setTimeout(()=>{s=null;let Q=r;r="",g=B(Q).catch(y=>{c=!0,i.warn?.("[dsh-im:slack] streaming append failed:",y)}).finally(()=>{g=null,f()})},350),s?.unref?.())};return{messageId:a,get providerMessageIds(){return[...d]},update(Q){I||c||typeof Q!="string"||!Q.trim()||MGe(Q)||(r=Q,f())},async finish(Q){if(I)throw new Error("Slack message stream is already closed");I=!0,s!==null&&clearTimeout(s),s=null,r="",await g?.catch(()=>{});let y=ss(Q,iG),m=y[0]??w("\u5904\u7406\u5B8C\u6210\u3002");!c&&m.startsWith(A)?(await W5(n,t,a,m.slice(A.length),o),await n.stopStream({channelId:t.channelId,ts:a,signal:o})):(await n.stopStream({channelId:t.channelId,ts:a,signal:o}).catch(()=>{}),await n.updateMessage({channelId:t.channelId,ts:a,text:m,signal:o}));for(let T of y.slice(1)){let _=await n.postMessage({channelId:t.channelId,threadTs:t.threadTs,text:T,signal:o});typeof _?.ts=="string"&&_.ts&&d.push(_.ts)}},cancel(){I=!0,r="",s!==null&&clearTimeout(s),s=null,n.stopStream({channelId:t.channelId,ts:a,signal:o}).catch(()=>{})}}}var nG=class{#e;#A;#t;constructor({api:t,signal:o,logger:i}){this.#e=t,this.#A=o,this.#t=i}async sendText(t,o){let i=ss(o,iG),e=[];for(let a of i){let A=await this.#e.postMessage({channelId:t.channelId,threadTs:t.threadTs,text:a,signal:this.#A});typeof A?.ts=="string"&&A.ts&&e.push(A.ts)}return{providerMessageIds:e}}async addReaction(t,o,{signal:i}={}){let e=String(o??"").trim();return await this.#e.addReaction({channelId:t.channelId,messageTs:t.messageTs,emojiName:e,signal:i??this.#A}),e}removeReaction(t,o,{signal:i}={}){return this.#e.removeReaction({channelId:t.channelId,messageTs:t.messageTs,emojiName:o,signal:i??this.#A})}openStream(t){return _Ge({api:this.#e,target:t,signal:this.#A,logger:this.#t})}sendFile(t,o){return this.#e.uploadFile({channelId:t.channelId,threadTs:t.threadTs,file:o,signal:this.#A})}};function TGe(){return{startedAt:null,ready:!1,connectionState:"idle",harnessReachable:!1,lastCheckedAt:null,lastConnectedAt:null,lastError:null,...io()}}var qu=class{#e;#A;#t;#r;#l;#o;#i;#a;#n;#s;#p;#c;#g=TGe();#I=null;#d=null;#h=null;#C=null;#u=null;#B=null;#f=0;#Q=0;#S=!0;#y=null;constructor({config:t,botToken:o,appToken:i,harness:e,state:a,contextEnhancement:A,accessPolicy:r,logger:s=console,replyTimeoutMs:g=6e5,connectTimeoutMs:c=2e4,createApi:I=B=>new ju(B),createWebSocket:d=B=>new WebSocket(B)}){if(!t||!o||!i||!e||!a)throw new TypeError("SlackRuntime requires config, both tokens, Harness, and state");if(typeof d!="function")throw new TypeError("SlackRuntime requires WebSocket");this.#e=t,this.#A=o,this.#t=i,this.#r=e,this.#l=a,this.#o=A,this.#i=r,this.#a=s,this.#n=g,this.#s=c,this.#p=I,this.#c=d}get status(){return structuredClone(this.#g)}async sendConnectionTest(t){if(!this.#g.ready||!this.#d){let o=new Error("Slack bot is not connected");throw o.code="test-target-unavailable",o}return this.#d.sendConnectionTest(t)}async sendProactiveText(t,o,i={}){if(!this.#g.ready||!this.#d){let A=new Error("Slack bot is not connected");throw A.code="bot-not-connected",A}let e=typeof t?.route?.channelId=="string"?t.route.channelId.trim():"",a=typeof t?.route?.threadTs=="string"?t.route.threadTs.trim():"";if(!e||t?.kind!=="conversation"&&t?.kind!=="thread"||t.kind==="thread"&&!a||t.kind==="conversation"&&a){let A=new TypeError("Invalid Slack proactive delivery target");throw A.code="invalid-target",A}return this.#d.sendProactiveText({channelId:e,...a?{threadTs:a}:{}},o,i)}async start(){return this.#g.ready&&this.#C?this.status:this.#y?this.#y:(this.#y=this.#m().finally(()=>{this.#y=null}),this.#y)}async#m(){await this.stop(),this.#S=!1,this.#f=0,this.#g.startedAt=new Date().toISOString(),this.#g.connectionState="connecting",this.#g.lastError=null,await this.#r.ensureRunning(),this.#g.harnessReachable=!0;let t=new AbortController;this.#h=t;let o=this.#p({botToken:this.#A,appToken:this.#t});this.#I=o;try{let i=await o.authTest({signal:t.signal});if(`${i?.team_id}:${i?.user_id}`!==this.#e.platformId)throw new Error("Slack Bot Token identity does not match the saved bot");let e=new nG({api:o,signal:t.signal,logger:this.#a});this.#d=new WS({bot:e,harness:this.#r,state:this.#l,contextEnhancement:this.#o,accessPolicy:this.#i,status:this.#g,logger:this.#a,replyTimeoutMs:this.#n,signal:t.signal});let a;try{await Promise.race([this.#D(),new Promise((A,r)=>{a=setTimeout(()=>r(new Error("Slack Socket Mode did not become ready in time")),this.#s),a?.unref?.()})])}finally{clearTimeout(a)}return this.status}catch(i){throw this.#g.ready=!1,this.#g.connectionState="failed",this.#g.lastError=i?.message??String(i),await this.stop(),i}}async#D(){if(this.#S)throw new Error("Slack runtime is stopped");let t=await this.#I.openConnection({signal:this.#h?.signal});return this.#E(t?.url)}#E(t){if(this.#S)return Promise.reject(new Error("Slack runtime is stopped"));let o=++this.#Q,i=this.#c(mGe(t));this.#C=i;let e=!1;return new Promise((a,A)=>{let r=s=>{if(e||o!==this.#Q)return;e=!0,this.#u=s?.connection_info?.app_id??null,this.#f=0;let g=Date.now();this.#g.ready=!0,this.#g.connectionState="connected",this.#g.lastCheckedAt=g,this.#g.lastConnectedAt=g,this.#g.lastError=null,a()};aG(i,"message",s=>{if(o!==this.#Q||this.#S)return;let g=yGe(s);if(!g)return;let c;try{c=JSON.parse(g)}catch{this.#a.warn?.("[dsh-im:slack] ignored malformed Socket Mode JSON");return}if(c.type==="hello"){r(c);return}if(c.envelope_id&&i.readyState===1&&(i.send(JSON.stringify({envelope_id:c.envelope_id})),this.#g.lastCheckedAt=Date.now()),c.type==="disconnect"){i.close(4e3,"Slack requested reconnect");return}if(c.type!=="events_api"||c.payload?.type!=="event_callback"||this.#u&&c.payload.api_app_id&&c.payload.api_app_id!==this.#u)return;let I=bGe(c.payload,this.#e.platformId.split(":")[1],{loadFile:(B,f)=>this.#I.downloadFile({url:B,...f}),loadFileStream:(B,f)=>this.#I.downloadFileStream({url:B,...f}),loadFileInfo:(B,f)=>this.#I.fileInfo({fileId:B,...f})}),d=this.#d;I&&d&&d.accept(I).catch(B=>{o!==this.#Q||this.#S||this.#a.error?.(`[dsh-im:slack] bot ${this.#e.botId} message handling failed:`,B)})}),aG(i,"close",(s={})=>{if(o!==this.#Q)return;if(this.#C===i&&(this.#C=null),this.#S){e||A(new DOMException("Stopped","AbortError"));return}let g=Number(s.code)||0,c=new Error(`Slack Socket Mode closed (${g||"unknown"})`);this.#g.ready=!1,this.#g.connectionState="connecting",this.#g.lastError=c.message,e||(e=!0,A(c)),this.#N()}),aG(i,"error",()=>{o!==this.#Q||this.#S||(this.#g.lastError="Slack Socket Mode WebSocket error")})})}#N(){if(this.#S||this.#B!==null)return;let t=z5[Math.min(this.#f,z5.length-1)];this.#f+=1,this.#B=setTimeout(()=>{this.#B=null,this.#D().catch(o=>{this.#S||(this.#a.warn?.("[dsh-im:slack] Socket Mode reconnect failed:",o),this.#N())})},t),this.#B?.unref?.()}async stop(){this.#S=!0,this.#Q+=1,this.#h?.abort(),this.#h=null,this.#B!==null&&clearTimeout(this.#B),this.#B=null;let t=this.#C,o=this.#d;this.#C=null,this.#d=null,this.#I=null,this.#u=null;try{t&&t.readyState<2&&t.close(1e3,"Plugin stopped")}catch(i){this.#a.warn?.(`[dsh-im:slack] bot ${this.#e.botId} failed to close Socket Mode:`,i)}return await Promise.race([o?.waitForIdle()??Promise.resolve(),new Promise(i=>setTimeout(i,2e3))]),this.#g.ready=!1,this.#g.connectionState="idle",this.status}};var $S=class extends gs{};async function sG(n,t={},o={}){if(!n?.credentials)throw new TypeError("dsh-im slack requires ctx.credentials");let i=aa(n,t),e=o.ConfigStore??VS,a=o.StateStore??$S,A=o.HarnessClient??XS,r=o.Controller??Ju,s=o.Runtime??qu,g=o.createConnectionSupervisor??jp,c=typeof n.logger=="function"?n.logger("dsh-im:slack"):n.logger??console,I=()=>La(n),d=W_(t,"slack"),B=await new e(d.config).load(),f=X5(t.workspace??process.cwd()),Q=o.WorkspaceStore??ra,y=o.workspaces??await new Q(d.workspaces,{defaultWorkspace:f}).load(),m=B.list();await y.reconcile(m.map(N=>N.botId)),await Promise.all(m.map(N=>y.ensure(N.botId,{defaultAgentPreset:t.agentPreset,initialAccessPolicy:nr("slack",N)})));let T=typeof B.remove=="function"?Ha(B,{workspaces:y}):B,_=new Map,R=N=>X5(d.bots,N,"state.json"),K=async N=>{let k=_.get(N);return k||(k=await new a(R(N)).load(),_.set(N,k)),k},L=ja(n,o.commandExecutor),{controlExecutor:F,sessionMaintenanceExecutor:q,fileIngressExecutor:V}=Ja(n,{controlExecutor:o.controlExecutor,sessionMaintenanceExecutor:o.sessionMaintenanceExecutor,fileIngressExecutor:o.fileIngressExecutor}),x=new A({...i,workspace:f,autostart:!1,dshBin:t.dshBin??"dsh",...L?{commandExecutor:L}:{},...F?{controlExecutor:F}:{},...q?{sessionMaintenanceExecutor:q}:{},...V?{fileIngressExecutor:V}:{}}),G=new r({credentials:n.credentials,configStore:T,logger:c,...o.inspectCredentials?{inspectCredentials:o.inspectCredentials}:{},createRuntime:async({botId:N,config:k,botToken:z,appToken:Ae})=>{let ie=await K(N);await y.ensure(N,{defaultAgentPreset:t.agentPreset,initialAccessPolicy:nr("slack",k)});let we=Ka(x,{botId:N,workspaces:y,state:ie,agentPresetCatalog:I});return new s({config:k,botToken:z,appToken:Ae,harness:we.harness,state:we.state,contextEnhancement:{botId:N,getSettings:()=>y.contextEnhancementFor(N)},accessPolicy:qa(y,N,{channel:"slack",config:k}),replyTimeoutMs:t.replyTimeoutMs??6e5,connectTimeoutMs:t.connectTimeoutMs??2e4,logger:{error:(...se)=>c.error?.(`[${N}]`,...se),warn:(...se)=>c.warn?.(`[${N}]`,...se),info:(...se)=>c.info?.(`[${N}]`,...se),debug:(...se)=>c.debug?.(`[${N}]`,...se)}})},deleteState:async({botId:N})=>{let k=_.get(N);if(_.delete(N),k&&typeof k.remove=="function")await k.remove();else try{await NGe(R(N))}catch(z){if(z?.code!=="ENOENT")throw z}}}),J=xa(G,{workspaces:y,stateFor:K,agentPresetCatalog:I}),U=g({channel:"slack",controller:J,harness:x,logger:c,retryDelaysMs:t.retryDelaysMs,healthyIntervalMs:t.healthyIntervalMs}).start();return{controller:J,deliveryAdapter:Ya({channel:"slack",workspaces:y,coreController:G,stateFor:K}),ready:U.ready,async close(){await U.close(),await J.close(),x.stopManagedProcess()}}}var eZ="/slack",ya=Object.freeze({status:"connection.status",bindCredentials:"bot.bind-credentials",reconnectBot:"bot.reconnect",deleteBot:"bot.delete",setWorkspace:vi,setAgentPreset:Pi,setContextEnhancement:ki,setAccessPolicy:Va}),AZ=Object.freeze(Object.values(ya)),RGe=new Set(["token","botToken","appToken","botTokenRef","appTokenRef","tokenRef","platformId","secret","secretRef"]);function cG(n){return n!==null&&typeof n=="object"&&!Array.isArray(n)}function ew(n,t){return cG(n)&&Object.keys(n).every(o=>t.includes(o))}function $5(n){return typeof n=="string"&&/^slack_[a-f0-9]{24}$/.test(n)}function kGe(n){return typeof n=="string"&&/^xoxb-[A-Za-z0-9-]{16,}$/.test(n.trim())&&n.length<=4096}function vGe(n){return typeof n=="string"&&/^xapp-[A-Za-z0-9-]{16,}$/.test(n.trim())&&n.length<=4096}function PGe(n,t){return cG(t)?n===ya.status?ew(t,[])?null:"connection.status does not accept fields.":n===ya.bindCredentials?ew(t,["botToken","appToken"])&&kGe(t.botToken)&&vGe(t.appToken)?null:"bot.bind-credentials requires xoxb Bot Token and xapp App Token.":n===ya.reconnectBot?ew(t,["botId","sendTest"])&&$5(t.botId)&&(t.sendTest===void 0||typeof t.sendTest=="boolean")?null:"bot.reconnect requires a botId.":n===ya.deleteBot?ew(t,["botId","confirm"])&&$5(t.botId)&&t.confirm===!0?null:"bot.delete requires a botId and confirm=true.":n===ya.setWorkspace?Za(t)?null:"\u8BF7\u8F93\u5165\u5DE5\u4F5C\u533A\u7EDD\u5BF9\u8DEF\u5F84\u3002":n===ya.setAgentPreset?$a(t)?null:"\u8BF7\u9009\u62E9 Agent Preset\u3002":n===ya.setContextEnhancement?za(t)?null:"\u8BF7\u63D0\u4EA4\u6709\u6548\u7684\u4E0A\u4E0B\u6587\u589E\u5F3A\u8BBE\u7F6E\u3002":n===ya.setAccessPolicy?Wa(t)?null:"\u8BF7\u63D0\u4EA4\u6709\u6548\u7684\u8BBF\u95EE\u8BBE\u7F6E\u3002":"Unknown Slack endpoint.":"Payload must be an object."}function gG(n){if(Array.isArray(n))return n.map(gG);if(!cG(n))return n;let t={};for(let[o,i]of Object.entries(n))RGe.has(o)||(t[o]=gG(i));return t}function GGe(n){let t=Xa(n);return t||(n?.code==="slack-invalid-bot-token"?{code:"invalid-bot-token",message:"Slack Bot Token \u65E0\u6548\uFF0C\u8BF7\u786E\u8BA4\u4F7F\u7528\u4EE5 xoxb- \u5F00\u5934\u7684\u4EE4\u724C\u3002"}:n?.code==="slack-invalid-app-token"?{code:"invalid-app-token",message:"Slack App Token \u65E0\u6548\uFF0C\u8BF7\u786E\u8BA4\u4F7F\u7528\u4EE5 xapp- \u5F00\u5934\u7684\u4EE4\u724C\u3002"}:n?.code==="slack-missing-scope"?{code:"missing-scope",message:"Slack \u5E94\u7528\u6743\u9650\u4E0D\u5B8C\u6574\uFF0C\u8BF7\u91CD\u65B0\u5BFC\u5165 Manifest \u5E76\u5B89\u88C5\u5230\u5DE5\u4F5C\u533A\u3002"}:n?.code==="slack-socket-mode"?{code:"socket-mode-unavailable",message:n.message}:{code:"slack-operation-failed",message:"Slack \u64CD\u4F5C\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002"})}function tZ(n){for(let t of["status","bindCredentials","reconnectBot","deleteBot"])if(typeof n?.[t]!="function")throw new TypeError(`A complete Slack controller is required (${t})`);return async(t,o,i)=>{if(i?.aborted)return{ok:!1,error:{code:"cancelled",message:"The request was cancelled."}};if(!AZ.includes(t))return{ok:!1,error:{code:"bad-request",message:"Unknown Slack endpoint."}};let e=PGe(t,o);if(e)return{ok:!1,error:{code:"bad-request",message:e}};try{let a;if(t===ya.status)a=await n.status();else if(t===ya.bindCredentials)a=await n.bindCredentials(o);else if(t===ya.reconnectBot){if(a=await n.reconnectBot(o.botId),i?.aborted)return{ok:!1,error:{code:"cancelled",message:"The request was cancelled."}};if(o.sendTest===!0){let A=null;try{if(a?.bots?.find(r=>r?.botId===o.botId)?.connected!==!0){let r=new Error("Bot is not connected");throw r.code="test-target-unavailable",r}if(typeof n.sendConnectionTest!="function"){let r=new Error("Connection test is unavailable");throw r.code="test-target-unavailable",r}await n.sendConnectionTest(o.botId)}catch(r){A=r}a={...a,testMessage:or(A)}}}else if(t===ya.setWorkspace){if(typeof n.updateWorkspace!="function")throw new Error("Workspace update is unavailable");a=await n.updateWorkspace(o.botId,o.workspace)}else if(t===ya.setContextEnhancement){if(typeof n.updateContextEnhancement!="function")throw new Error("Context enhancement update is unavailable");a=await n.updateContextEnhancement(o.botId,o.config)}else if(t===ya.setAccessPolicy){if(typeof n.updateAccessPolicy!="function")throw new Error("Access policy update is unavailable");a=await n.updateAccessPolicy(o.botId,o.policy)}else if(t===ya.setAgentPreset){if(typeof n.updateAgentPreset!="function")throw new Error("Agent preset update is unavailable");a=await n.updateAgentPreset(o.botId,o.agentPreset)}else a=await n.deleteBot(o.botId);return i?.aborted?{ok:!1,error:{code:"cancelled",message:"The request was cancelled."}}:{ok:!0,value:gG(a)}}catch(a){return i?.aborted?{ok:!1,error:{code:"cancelled",message:"The request was cancelled."}}:{ok:!1,error:GGe(a)}}}}function Aw(n,t,o){if(!n?.connection?.rpc||typeof n.connection.rpc.handle!="function")throw new TypeError("DSH Host Connection RPC is required");return n.connection.rpc.handle(eZ,tZ(t),{authority:fr(o)})}async function rZ(n,t={}){if(t?.controller)return Aw(n,t.controller,t.rpcAuthority);let o=await sG(n,t,t.internals??{}),i=t.deliveryService&&o.deliveryAdapter?t.deliveryService.registerAdapter(o.deliveryAdapter):void 0,e=Aw(n,o.controller,t.rpcAuthority);return n.effect(()=>async()=>{await i?.(),await o.close()},"dsh-im: close Slack bot connections"),e}var aZ=Object.freeze({botPrefix:"telegram",tokenRefPrefix:"DSH_TELEGRAM_BOT_TOKEN"}),IG=Object.freeze({compatible:"compatible",privateAllowlist:"private-allowlist"}),FGe=/^[1-9]\d{0,15}$/;function iZ(n){if(n===void 0)return Object.freeze([]);if(!Array.isArray(n))throw new TypeError("allowedUsers must be an array of numeric Telegram User IDs");let t=n.map(o=>{let i=typeof o=="number"&&Number.isSafeInteger(o)?String(o):typeof o=="string"?o.trim():"";if(!FGe.test(i))throw new TypeError("allowedUsers contains an invalid Telegram User ID");return i});return Object.freeze([...new Set(t)])}function rw(n={}){if(!n||typeof n!="object"||Array.isArray(n))throw new TypeError("Telegram access policy must be an object");let t=n.accessMode??IG.compatible;if(!Object.values(IG).includes(t))throw new TypeError("Telegram accessMode must be compatible or private-allowlist");return Object.freeze({accessMode:t,allowedUsers:iZ(n.allowedUsers)})}function LGe(n){let t=Object.hasOwn(n,"accessMode"),o=Object.hasOwn(n,"allowedUsers");if(!t&&!o)return{};try{let i=rw(n);return{...t?{accessMode:i.accessMode}:{},...o||t?{allowedUsers:i.allowedUsers}:{}}}catch{return null}}function oZ(n){return eC(n,aZ)}function nZ(n){return YQ(n,w("Telegram\u673A\u5668\u4EBA"))}var tw=class extends Kp{constructor(t){super(t,{channel:"Telegram",...aZ,normalizeBotExtension:LGe})}async save(t){let o=t?.platformId?this.getByPlatformId(String(t.platformId)):null;return super.save({...o,...t})}};var aw=class extends ur{constructor(t){super({...t,rpcIdPrefix:"telegram",logPrefix:"dsh-telegram"})}};var UGe="https://api.telegram.org/",sZ=Object.freeze(["api.telegram.org"]),HGe=12e4;function Rg(n){return typeof n=="string"&&n.trim()?n.trim():null}function gZ(n,t){let o=AbortSignal.timeout(t);return n?AbortSignal.any([n,o]):o}function lG(n){return n?.reason instanceof Error?n.reason:new DOMException("The operation was aborted","AbortError")}function KGe(n,t){if(!Number.isInteger(n)||n<1)throw new TypeError(`${t} must be a positive integer`);return n}function IZ(n,t){return t?.providerCode!==void 0&&(n.providerCode=t.providerCode),t?.retry_after!==void 0&&(n.retry_after=t.retry_after,n.retryAfter=t.retry_after),Number.isInteger(t?.status)&&(n.status=t.status),n}function pG(n){if(!n||typeof n!="object"||Array.isArray(n))throw new TypeError("A Telegram rich message is required");let t=["markdown","html","blocks"].filter(i=>n[i]!==void 0);if(t.length!==1)throw new TypeError("A Telegram rich message requires exactly one format");let o=t[0];if((o==="markdown"||o==="html")&&(typeof n[o]!="string"||!n[o].trim()))throw new TypeError("Telegram rich message text is invalid");if(o==="blocks"&&!Array.isArray(n.blocks))throw new TypeError("Telegram rich message blocks are invalid");return n}function xGe(n,t="document"){let o=Number(n?.providerCode),i=Number(n?.status),e=Rg(n?.message)??"",a="artifact-provider-rejected",A=`Telegram rejected the ${t}.`;o===401||o===403||i===401||i===403?(a="artifact-permission-required",A=`Telegram denied permission to send the ${t}.`):o===413||i===413||/(?:file|request|entity).{0,20}(?:too (?:big|large)|size limit)|too (?:big|large)/i.test(e)?(a="artifact-too-large",A=`The ${t} exceeds Telegram's size limit.`):o===429||i===429?(a="artifact-rate-limited",A=`Telegram rate-limited ${t} delivery.`):(o>=500||i>=500)&&(a="artifact-delivery-uncertain",A=`Telegram ${t} delivery result is uncertain.`);let r=new Error(A,{cause:n});return r.code=a,IZ(r,n)}function cZ(n,t="document"){let o=new Error(`Telegram ${t} delivery result is uncertain`,{cause:n});return o.code="artifact-delivery-uncertain",IZ(o,n)}function YGe(n){return typeof n=="string"&&/^\d{5,20}:[A-Za-z0-9_-]{20,}$/.test(n.trim())}var jGe=/^[a-z0-9_]{1,32}$/;function JGe(n){return!!n&&typeof n=="object"&&!Array.isArray(n)&&typeof n.command=="string"&&jGe.test(n.command)&&typeof n.description=="string"&&n.description.length>=1&&n.description.length<=256}var dG=Object.freeze({type:"commands"}),zu=class{#e;#A;#t;#r;#l;constructor({token:t,fetchImpl:o=fetch,FormDataImpl:i=globalThis.FormData,baseUrl:e=UGe,fileUploadTimeoutMs:a=HGe}){if(!YGe(t))throw new TypeError("Telegram Bot Token is invalid");if(typeof o!="function")throw new TypeError("TelegramApi requires fetch");if(typeof i!="function")throw new TypeError("TelegramApi requires FormData");this.#e=t.trim(),this.#A=o,this.#t=i,this.#r=new URL(e),this.#l=KGe(a,"fileUploadTimeoutMs")}async getMe(t={}){return this.#a("getMe",{},t)}async getWebhookInfo(t={}){return this.#a("getWebhookInfo",{},t)}async getUpdates({offset:t,timeout:o=25,signal:i}={}){let e={timeout:o,limit:100,allowed_updates:["message"],...Number.isSafeInteger(t)?{offset:t}:{}};return this.#a("getUpdates",e,{signal:i,timeoutMs:Math.max(1e4,(o+10)*1e3)})}async getFile({fileId:t,signal:o}={}){let i=Rg(t);if(!i||!/^[A-Za-z0-9_-]{1,512}$/.test(i))throw new TypeError("Telegram file id is invalid");return this.#a("getFile",{file_id:i},{signal:o})}async downloadFile({fileId:t,signal:o,maxBytes:i}={}){let e=await this.#o(t,o);return Do(e,{fetchImpl:this.#A,signal:o,maxBytes:i,allowedHosts:sZ})}async downloadFileStream({fileId:t,signal:o}={}){let i=await this.#o(t,o);return Yp(i,{fetchImpl:this.#A,signal:o,allowedHosts:sZ})}async#o(t,o){let i=await this.getFile({fileId:t,signal:o}),e=Rg(i?.file_path);if(!e||e.startsWith("/")||e.includes("\\")||e.includes("?")||e.includes("#"))throw new Error("Telegram returned an invalid file path");let a;try{a=e.split("/").map(r=>decodeURIComponent(r))}catch{throw new Error("Telegram returned an invalid file path")}if(a.some(r=>!r||r==="."||r===".."))throw new Error("Telegram returned an invalid file path");let A=new URL(this.#r);return A.pathname=`/file/bot${this.#e}/${e}`,A}async sendMessage({chatId:t,text:o,replyToMessageId:i,messageThreadId:e,signal:a}){return this.#a("sendMessage",{chat_id:t,text:o,link_preview_options:{is_disabled:!0},...i?{reply_parameters:{message_id:i,allow_sending_without_reply:!0}}:{},...e?{message_thread_id:e}:{}},{signal:a})}async setMessageReaction({chatId:t,messageId:o,emoji:i,signal:e,timeoutMs:a}){let A=Rg(i);return this.#a("setMessageReaction",{chat_id:t,message_id:o,reaction:A?[{type:"emoji",emoji:A}]:[]},{signal:e,timeoutMs:a})}async sendRichMessage({chatId:t,richMessage:o,replyToMessageId:i,messageThreadId:e,signal:a}){return this.#a("sendRichMessage",{chat_id:t,rich_message:pG(o),...i?{reply_parameters:{message_id:i,allow_sending_without_reply:!0}}:{},...e?{message_thread_id:e}:{}},{signal:a})}async sendRichMessageDraft({chatId:t,draftId:o,richMessage:i,messageThreadId:e,signal:a}){if(!Number.isSafeInteger(o)||o===0)throw new TypeError("Telegram rich message draft id must be a non-zero integer");return this.#a("sendRichMessageDraft",{chat_id:t,draft_id:o,rich_message:pG(i),...e?{message_thread_id:e}:{}},{signal:a})}async sendDocument({chatId:t,file:o,replyToMessageId:i,messageThreadId:e,signal:a}){return this.#i("sendDocument","document","document",{chatId:t,file:o,replyToMessageId:i,messageThreadId:e,signal:a})}async sendPhoto({chatId:t,file:o,replyToMessageId:i,messageThreadId:e,signal:a}){return this.#i("sendPhoto","photo","photo",{chatId:t,file:o,replyToMessageId:i,messageThreadId:e,signal:a})}async#i(t,o,i,{chatId:e,file:a,replyToMessageId:A,messageThreadId:r,signal:s}){if(!a||typeof a!="object"||typeof a.fileName!="string"||!a.fileName||!Buffer.isBuffer(a.bytes))throw new TypeError(`A Telegram ${i} is required`);let g=new this.#t;if(g.append("chat_id",String(e)),g.append(o,new Blob([a.bytes],{type:a.mediaType??"application/octet-stream"}),a.fileName),A&&g.append("reply_parameters",JSON.stringify({message_id:A,allow_sending_without_reply:!0})),r&&g.append("message_thread_id",String(r)),s?.aborted)throw lG(s);let c=gZ(s,this.#l);try{return await this.#a(t,g,{signal:c,timeoutMs:this.#l,multipart:!0})}catch(I){throw s?.aborted?lG(s):I?.deliveryOutcome==="unknown"?cZ(I?.cause??I,i):I?.code?.startsWith?.("telegram-")?xGe(I,i):cZ(I,i)}}async editMessageText({chatId:t,messageId:o,text:i,richMessage:e,signal:a}){if(i===void 0==(e===void 0))throw new TypeError("Telegram message edit requires exactly one of text or richMessage");return this.#a("editMessageText",{chat_id:t,message_id:o,...i===void 0?{rich_message:pG(e)}:{text:i,link_preview_options:{is_disabled:!0}}},{signal:a})}async sendChatAction({chatId:t,messageThreadId:o,signal:i}){return this.#a("sendChatAction",{chat_id:t,action:"typing",...o?{message_thread_id:o}:{}},{signal:i})}async setMyCommands({commands:t,scope:o,languageCode:i,signal:e}={}){if(!Array.isArray(t)||t.length===0||t.some(a=>!JGe(a)))throw new TypeError("Telegram bot commands are invalid");return this.#a("setMyCommands",{commands:t,...o?{scope:o}:{},...Rg(i)?{language_code:Rg(i)}:{}},{signal:e})}async setChatMenuButton({menuButton:t=dG,signal:o}={}){if(!t||typeof t!="object"||Array.isArray(t))throw new TypeError("Telegram menu button is invalid");return this.#a("setChatMenuButton",{menu_button:t},{signal:o})}async#a(t,o,{signal:i,timeoutMs:e=15e3,multipart:a=!1}={}){if(i?.aborted)throw lG(i);let A=new URL(this.#r);A.pathname=`${A.pathname.replace(/\/$/,"")}/bot${this.#e}/${t}`;let r;try{r=await this.#A(A,{method:"POST",...a?{}:{headers:{"content-type":"application/json"}},body:a?o:JSON.stringify(o),signal:gZ(i,e),redirect:"error"})}catch(g){let c=new Error(`Telegram ${t} transport failed`,{cause:g});throw c.code=g?.name==="TimeoutError"?"telegram-timeout":g?.name==="AbortError"?"telegram-aborted-after-dispatch":"telegram-transport-error",c.deliveryOutcome="unknown",c}let s;try{s=await r.json()}catch{let g=new Error(`Telegram ${t} returned invalid JSON`);throw g.status=r?.status,g.code="telegram-response-invalid",g.deliveryOutcome="unknown",g}if(!r.ok||s?.ok!==!0){let g=Rg(s?.description),c=new Error(g??`Telegram ${t} failed`);c.code=Number.isInteger(s?.error_code)?`telegram-${s.error_code}`:"telegram-api-error",c.status=r.status,Number.isInteger(s?.error_code)&&(c.providerCode=s.error_code);let I=Number(s?.parameters?.retry_after);throw Number.isFinite(I)&&I>=0&&(c.retry_after=I,c.retryAfter=I),c}return s.result}};async function lZ(n,t={}){let i=await new zu({token:n,...t}).getMe();if(!i?.id||i?.is_bot!==!0)throw new Error("Telegram token does not belong to a bot");return{platformId:String(i.id),name:Rg([i.first_name,i.last_name].filter(Boolean).join(" "))??w("Telegram\u673A\u5668\u4EBA"),username:Rg(i.username)}}var hG=Object.freeze({key:"telegram",label:"Telegram",connectionLabel:" Bot API \u957F\u8F6E\u8BE2",reactions:Object.freeze({processing:"\u{1F440}",success:"\u{1F44D}",error:"\u{1F44E}"})}),iw=class extends ns{constructor(t){super({descriptor:hG,...t})}};var Vu=class extends xp{#e;constructor(t){super({...t,descriptor:hG,inspectToken:t.inspectToken??lZ,deriveIdentity:oZ,maskPlatformId:nZ}),this.#e=t.configStore}status(){let t=super.status();return{...t,bots:t.bots.map(o=>{let i=this.#e.get(o.botId),e=rw(i??{});return{...o,accessPolicy:e}})}}async setAccessPolicy(t,o){let i=rw(o);return this.updateBotConfig(t,e=>({...e,...i}))}};import{randomInt as eFe}from"node:crypto";import{EnvHttpProxyAgent as qGe,FormData as zGe,fetch as VGe}from"undici";var WGe=4;function pZ(){let n=new qGe({connections:WGe}),t=!1;return{fetchImpl:(o,i={})=>VGe(o,{...i,dispatcher:n}),FormDataImpl:zGe,async destroy(){t||(t=!0,await n.destroy())}}}function CG(n){if(typeof n!="string"||!n.trim())throw new TypeError("Telegram message text must be a non-empty string");return n}function uG(n){return n==="&"?5:n==="<"||n===">"?4:1}function EG(n){return Array.from(n).reduce((t,o)=>t+uG(o),0)}function ZGe(n,t,o,i){let e=t+Math.floor(i*.5);for(let a=o-1;a>=e;a-=1)if(n[a]===` `||n[a]===" ")return a+1;return o}function BG(n,t,o=()=>1){if(typeof n!="string")throw new TypeError("Telegram message text must be a string");if(!n)return[];let i=Array.from(n),e=[],a=0;for(;at)break;r+=s,A+=1}if(A===a)throw new Error("Telegram message character exceeds the chunk limit");A",">")}function dZ(n,t){return BG(n,t,uG).map(o=>({source:o,markdown:Wu(o)}))}function $Ge(n,t,o,i){let e=n.slice(t.length,n.length-o.length),a=EG(t)+Math.max(EG(o),EG("```"))+1,A=i-a;if(A<1)throw new Error("Telegram Rich Markdown code fence exceeds the limit");let r=BG(e,A,uG);return r.map((s,g)=>{let c=g===r.length-1,I=s.endsWith(` `)?"":` -`,d=c?o:"```",B=`${g===0?t:""}${s}${c?o:""}`,f=Wu(`${t}${s}${I}${d}`);if(Array.from(f).length>i)throw new Error("Telegram Rich Markdown code block exceeds the limit");return{source:B,markdown:f}})}function fG(n){let t=CG(n);return hZ(t),Wu(t)}function QG(n,t=3e4){if(!Number.isInteger(t)||t<128||t>32768)throw new TypeError("Telegram Rich Markdown limit is invalid");let o=CG(n),i=hZ(o),e=Wu(o);if(Array.from(e).length<=t)return[{source:o,markdown:e}];let a=[],A=0;for(let r=0;rA&&a.push(...dZ(o.slice(A,s.index),t));let c=g.index+g[0].length,I=o.slice(s.index,c),d=Wu(I);Array.from(d).length<=t?a.push({source:I,markdown:d}):a.push(...$Ge(I,s[0],g[0],t)),A=c}return A4096)throw new TypeError("Telegram regular message limit is invalid");return BG(CG(n),t,o=>o.length)}var AFe=Object.freeze([{command:"new",description:"\u5F00\u542F\u4E00\u4E2A\u5168\u65B0\u4F1A\u8BDD"},{command:"compact",description:"\u538B\u7F29\u5F53\u524D\u4F1A\u8BDD\u7684\u8F83\u65E9\u4E0A\u4E0B\u6587"},{command:"workspace",description:"\u5207\u6362\u5DE5\u4F5C\u533A"},{command:"workspacelist",description:"\u5217\u51FA\u5DE5\u4F5C\u533A\u7EDD\u5BF9\u8DEF\u5F84"},{command:"sessionlist",description:"\u5217\u51FA\u4F1A\u8BDD ID \u548C\u6807\u9898"},{command:"sessions",description:"\u5217\u51FA\u4F1A\u8BDD ID \u548C\u6807\u9898"},{command:"session",description:"\u5C06\u5F53\u524D\u804A\u5929\u7ED1\u5B9A\u5230\u6307\u5B9A\u4F1A\u8BDD"},{command:"models",description:"\u6309\u5E8F\u53F7\u5217\u51FA\u6240\u6709\u53EF\u7528\u6A21\u578B"},{command:"model",description:"\u67E5\u770B\u6216\u5207\u6362\u5F53\u524D\u4F1A\u8BDD\u6A21\u578B"},{command:"presetlist",description:"\u5217\u51FA\u53EF\u7528 Agent Preset"},{command:"presets",description:"\u5217\u51FA\u53EF\u7528 Agent Preset"},{command:"preset",description:"\u67E5\u770B\u6216\u8BBE\u7F6E\u65B0\u4F1A\u8BDD Agent Preset"},{command:"stop",description:"\u505C\u6B62\u5F53\u524D\u4EFB\u52A1"},{command:"steer",description:"\u7EA0\u504F\u5F53\u524D\u4EFB\u52A1"},{command:"batch",description:"\u5F00\u59CB\u6279\u91CF\u8F93\u5165\uFF08\u4EC5\u79C1\u804A\uFF09"},{command:"send",description:"\u63D0\u4EA4\u5F53\u524D\u6279\u6B21"},{command:"cancel",description:"\u53D6\u6D88\u5F53\u524D\u6279\u6B21"},{command:"status",description:"\u68C0\u67E5\u8FDE\u63A5\u72B6\u6001"},{command:"version",description:"\u67E5\u770B\u63D2\u4EF6\u7248\u672C"},{command:"help",description:"\u663E\u793A\u5E2E\u52A9"}]);function tFe(){return AFe.map(n=>({...n,description:w(n.description)}))}function rFe(n){return n.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function aFe(n,t){return t?[[n?.text,n?.entities],[n?.caption,n?.caption_entities]].some(([o,i])=>typeof o=="string"&&Array.isArray(i)&&i.some(e=>e?.type!=="mention"||!Number.isInteger(e.offset)||!Number.isInteger(e.length)?!1:o.slice(e.offset,e.offset+e.length).toLowerCase()===`@${t.toLowerCase()}`)):!1}function iFe(n,t){return!t||typeof n!="string"?n:n.replace(new RegExp(`@${rFe(t)}\\b`,"ig"),"").trim()}var oFe=new Set(["image/jpeg","image/png","image/webp","image/gif"]),nFe=new Map([[".jpg","image/jpeg"],[".jpeg","image/jpeg"],[".png","image/png"],[".webp","image/webp"],[".gif","image/gif"]]);function CZ(n){let t=n?.mime_type??n?.mimetype,o=typeof t=="string"?t.toLowerCase():"";if(oFe.has(o))return o;let i=typeof n?.file_name=="string"?n.file_name.toLowerCase():"";for(let[e,a]of nFe)if(i.endsWith(e))return a;return null}function wG(n){return Number.isSafeInteger(n)&&n>=0?n:void 0}function EZ(n){return wG(n?.file_size)??(Number(n?.width)||0)*(Number(n?.height)||0)}function sFe(n,t){let o,i,e;if(Array.isArray(n?.photo)&&n.photo.length>0)o=n.photo.reduce((a,A)=>EZ(A)>EZ(a)?A:a),i="image/jpeg",e=`${o.file_unique_id??o.file_id??"telegram-photo"}.jpg`;else if(n?.document){let a=CZ(n.document);if(!a)return null;o=n.document,i=a,e=typeof o.file_name=="string"?o.file_name:void 0}return!o||typeof o.file_id!="string"?null:{name:e,mediaType:i,size:wG(o.file_size),load:a=>t(o.file_id,a)}}function gFe(n,t){let o=n?.document;if(!o||CZ(o)||typeof o.file_id!="string"||!o.file_id)return null;let i=typeof o.mime_type=="string"&&o.mime_type?o.mime_type.toLowerCase():void 0;return{name:typeof o.file_name=="string"&&o.file_name?o.file_name:String(o.file_unique_id??o.file_id),...i?{mediaType:i}:{},size:wG(o.file_size),load:({signal:e}={})=>t(o.file_id,{signal:e})}}function cFe(n,{botId:t,username:o,loadFile:i=async()=>{throw new Error("Telegram file downloader is unavailable")},loadFileStream:e=i}){let a=n?.message,A=a?.chat?.id,r=a?.from?.id,s=a?.message_id;if(!Number.isSafeInteger(n?.update_id)||A===void 0||r===void 0||!Number.isSafeInteger(s)||!["private","group","supergroup"].includes(a.chat?.type))return null;let g=a.chat.type==="private",c=g||String(a.reply_to_message?.from?.id??"")===String(t)||aFe(a,o),I=Number.isSafeInteger(a.message_thread_id)?a.message_thread_id:void 0,d=sFe(a,i),B=gFe(a,e);return{messageId:String(n.update_id),senderId:String(r),contextSource:()=>({senderName:[a.from?.first_name,a.from?.last_name].filter(f=>typeof f=="string"&&f.trim()).map(f=>f.trim()).join(" ")||a.from?.username}),senderIsBot:a.from?.is_bot===!0,kind:g?"direct":"group",conversationId:I===void 0?String(A):`${A}:${I}`,content:iFe(a.text??a.caption??"",o),plainText:typeof a.text=="string",images:d?[d]:[],files:B?[B]:[],addressed:c,reactionTarget:{chatId:A,messageId:s},replyTarget:{chatId:A,chatType:a.chat.type,replyToMessageId:s,messageThreadId:I},connectionTestTarget:{chatId:A,messageThreadId:I}}}function mG(n){return Number.isSafeInteger(n?.message_id)?String(n.message_id):null}function Zu(n){let t=Number(n?.providerCode),o=Number(n?.status),i=n?.deliveryOutcome==="unknown"||t>=500||o>=500||["telegram-timeout","telegram-aborted-after-dispatch","telegram-transport-error","telegram-response-invalid"].includes(n?.code);return{outcome:i?"unknown":"failed",reason:typeof n?.code=="string"&&n.code?n.code:i?"telegram-delivery-uncertain":"telegram-provider-rejected"}}function xi(n,t,o="sent",i){return{presentation:n,providerMessageIds:[...new Set(t)],deliveryOutcome:o,...i?{reason:i}:{}}}var ow=class{#e;#A;#t;#r;#l;#o=!1;#i=null;constructor({update:t,finish:o,fail:i,providerMessageIds:e=[],presentation:a,logger:A}){this.#e=t,this.#A=o,this.#t=i,this.#l=e,this.presentation=a,this.#r=A}get providerMessageIds(){return[...this.#l]}async update(t){if(this.#o)return;let o=ts(t),i=`${o.format}:${o.text}`;if(i!==this.#i){this.#i=i;try{return await this.#e(o)}catch(e){this.#r.warn?.("[dsh-im:telegram] rich stream update failed:",e);return}}}async finish(t){if(this.#o)throw new Error("Message stream is already closed");this.#o=!0;let o=await this.#A(ts(t));return this.#l.push(...o?.providerMessageIds??[]),o}async fail(t){if(this.#o)return;this.#o=!0;let o=await this.#t(ts(t,"plain"));return this.#l.push(...o?.providerMessageIds??[]),o}cancel(){this.#o=!0}},SG=class{#e;#A;#t;constructor({api:t,signal:o,logger:i=console}){this.#e=t,this.#A=o,this.#t=i}async sendText(t,o){let i=yG(o),e=[];for(let[a,A]of i.entries()){let r=await this.#e.sendMessage({chatId:t.chatId,text:A,replyToMessageId:a===0?t.replyToMessageId:void 0,messageThreadId:t.messageThreadId,signal:this.#A});Number.isSafeInteger(r?.message_id)&&e.push(String(r.message_id))}return{providerMessageIds:e}}async addReaction(t,o,{signal:i}={}){let e=String(o??"").trim();return await this.#e.setMessageReaction({chatId:t.chatId,messageId:t.messageId,emoji:e,signal:i??this.#A}),e}removeReaction(t,o,{signal:i}={}){return this.#e.setMessageReaction({chatId:t.chatId,messageId:t.messageId,signal:i??this.#A})}sendTyping(t){return this.#e.sendChatAction({chatId:t.chatId,messageThreadId:t.messageThreadId,signal:this.#A})}sendFile(t,o){return this.#e.sendDocument({chatId:t.chatId,file:o,replyToMessageId:t.replyToMessageId,messageThreadId:t.messageThreadId,signal:this.#A})}sendImage(t,o){return this.#e.sendPhoto({chatId:t.chatId,file:o,replyToMessageId:t.replyToMessageId,messageThreadId:t.messageThreadId,signal:this.#A})}async#r(t,o,{placeholderMessageId:i}={}){let e=yG(o),a=i===void 0?[]:[String(i)],A=0;if(i!==void 0)try{await this.#e.editMessageText({chatId:t.chatId,messageId:i,text:e[0],signal:this.#A}),A=1}catch(r){let s=Zu(r);if(s.outcome==="unknown")return xi("text-fallback",a,"unknown",s.reason);let g=await this.#r(t,o),c=g.deliveryOutcome==="sent"?"\u56DE\u590D\u5DF2\u53D1\u9001\u3002":g.deliveryOutcome==="unknown"?"\u56DE\u590D\u53D1\u9001\u7ED3\u679C\u672A\u80FD\u786E\u8BA4\u3002":"\u6D88\u606F\u53D1\u9001\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002";try{await this.#e.editMessageText({chatId:t.chatId,messageId:i,text:c,signal:this.#A})}catch(I){this.#t.warn?.("[dsh-im:telegram] unable to replace the processing placeholder:",I)}return xi("text-fallback",[...a,...g.providerMessageIds],g.deliveryOutcome,g.reason)}for(let r=A;rI.source).join(""),c=await this.#r({...t,replyToMessageId:a===0?t.replyToMessageId:void 0},g);return xi(c.presentation,[...e,...c.providerMessageIds],c.deliveryOutcome,c.reason)}return xi("telegram-rich-final",e)}async#o(t,o,i){if(i.format==="plain")return this.#r(t,i.text,{placeholderMessageId:o});let e;try{e=QG(i.text)}catch{return this.#r(t,i.text,{placeholderMessageId:o})}let a=[String(o)];try{await this.#e.editMessageText({chatId:t.chatId,messageId:o,richMessage:{markdown:e[0].markdown},signal:this.#A})}catch(A){let r=Zu(A);return r.outcome==="unknown"?xi("telegram-rich-final",a,"unknown",r.reason):this.#r(t,i.text,{placeholderMessageId:o})}for(let[A,r]of e.slice(1).entries())try{let s=await this.#e.sendRichMessage({chatId:t.chatId,richMessage:{markdown:r.markdown},messageThreadId:t.messageThreadId,signal:this.#A}),g=mG(s);g&&a.push(g)}catch(s){let g=Zu(s);if(g.outcome==="unknown")return xi("telegram-rich-final",a,"unknown",g.reason);let c=e.slice(A+1).map(d=>d.source).join(""),I=await this.#r({...t,replyToMessageId:void 0},c);return xi(I.presentation,[...a,...I.providerMessageIds],I.deliveryOutcome,I.reason)}return xi("telegram-rich-final",a)}sendDelivery(t,o){return this.#l(t,ts(o))}async openDeliveryStream(t){if(t.chatType==="private"){let e=eFe(1,2147483647),a=async r=>{let s={markdown:fG(r.text)};return await this.#e.sendRichMessageDraft({chatId:t.chatId,draftId:e,richMessage:s,messageThreadId:t.messageThreadId,signal:this.#A}),xi("telegram-rich-draft",[])},A=new ow({update:a,finish:r=>this.#l(t,r),fail:r=>this.#r(t,r.text),presentation:"telegram-rich-draft",logger:this.#t});return await A.update(ts("\u6B63\u5728\u5904\u7406\u2026","plain")),A}let i=(await this.#e.sendMessage({chatId:t.chatId,text:"\u6B63\u5728\u5904\u7406\u2026",replyToMessageId:t.replyToMessageId,messageThreadId:t.messageThreadId,signal:this.#A}))?.message_id;if(!Number.isSafeInteger(i))throw new Error("Telegram did not return a placeholder message id");return new ow({update:async e=>e.format==="plain"?(await this.#e.editMessageText({chatId:t.chatId,messageId:i,text:e.text,signal:this.#A}),xi("text-fallback",[String(i)])):(await this.#e.editMessageText({chatId:t.chatId,messageId:i,richMessage:{markdown:fG(e.text)},signal:this.#A}),xi("telegram-rich-draft",[String(i)])),finish:e=>this.#o(t,i,e),fail:e=>this.#r(t,e.text,{placeholderMessageId:i}),providerMessageIds:[String(i)],presentation:"telegram-regular",logger:this.#t})}async openStream(t){return VQ({limit:4e3,create:async i=>(await this.#e.sendMessage({chatId:t.chatId,text:i,replyToMessageId:t.replyToMessageId,messageThreadId:t.messageThreadId,signal:this.#A})).message_id,edit:(i,e)=>this.#e.editMessageText({chatId:t.chatId,messageId:i,text:e,signal:this.#A}),sendRemainder:i=>this.#e.sendMessage({chatId:t.chatId,text:i,messageThreadId:t.messageThreadId,signal:this.#A}),messageIdForResult:i=>i?.message_id}).start()}};function IFe(){return{startedAt:null,ready:!1,connectionState:"idle",harnessReachable:!1,lastCheckedAt:null,lastConnectedAt:null,lastError:null,...io()}}var Xu=class{#e;#A;#t;#r;#l;#o;#i;#a;#n;#s;#p=IFe();#c=null;#g=null;#I=null;#d=null;#h=null;#C=null;constructor({config:t,token:o,harness:i,state:e,contextEnhancement:a,accessPolicy:A,logger:r=console,replyTimeoutMs:s=6e5,createApi:g=I=>new zu(I),createHttpTransport:c=pZ}){if(!t||!o||!i||!e)throw new TypeError("TelegramRuntime requires config, token, Harness, and state");this.#e=t,this.#A=o,this.#t=i,this.#r=e,this.#l=a,this.#o=A,this.#i=r,this.#a=s,this.#n=g,this.#s=c}get status(){return structuredClone(this.#p)}async sendConnectionTest(t){if(!this.#p.ready||!this.#I){let o=new Error("Telegram bot is not connected");throw o.code="test-target-unavailable",o}return this.#I.sendConnectionTest(t)}async sendProactiveText(t,o,i={}){if(!this.#p.ready||!this.#I){let r=new Error("Telegram bot is not connected");throw r.code="bot-not-connected",r}let e=typeof t?.route?.chatId=="string"?t.route.chatId.trim():"",a=Number(e),A=t?.route?.messageThreadId;if(!/^-?\d+$/.test(e)||!Number.isSafeInteger(a)||t?.kind!=="chat"&&t?.kind!=="topic"||t.kind==="topic"&&(!Number.isSafeInteger(A)||A<=0)||t.kind==="chat"&&A!==void 0){let r=new TypeError("Invalid Telegram proactive delivery target");throw r.code="invalid-target",r}return this.#I.sendProactiveText({chatId:a,...t.kind==="topic"?{messageThreadId:A}:{}},o,i)}async start(){return this.#p.ready&&this.#h?this.status:this.#C?this.#C:(this.#C=this.#u().finally(()=>{this.#C=null}),this.#C)}async#u(){await this.stop(),this.#p.startedAt=new Date().toISOString(),this.#p.connectionState="connecting",this.#p.lastError=null,await this.#t.ensureRunning(),this.#p.harnessReachable=!0;let t=new AbortController;this.#d=t;try{let o=this.#s();this.#c=o;let i=this.#n({token:this.#A,fetchImpl:o.fetchImpl,FormDataImpl:o.FormDataImpl});this.#g=i;let e=await i.getMe({signal:t.signal});if(String(e?.id??"")!==this.#e.platformId||e?.is_bot!==!0)throw new Error("Telegram token identity does not match the saved bot");let a=await i.getWebhookInfo({signal:t.signal});if(typeof a?.url=="string"&&a.url){let g=new Error(w("\u8BE5 Telegram \u673A\u5668\u4EBA\u5DF2\u914D\u7F6E Webhook\uFF0C\u8BF7\u5148\u5728\u539F\u670D\u52A1\u4E2D\u79FB\u9664 Webhook \u540E\u91CD\u8BD5\u3002"));throw g.code="webhook-configured",g}try{await i.setMyCommands({commands:tFe(),signal:t.signal}),await i.setChatMenuButton({menuButton:dG,signal:t.signal})}catch(g){this.#i.warn?.(`[dsh-im:telegram] bot ${this.#e.botId} command menu setup failed:`,g)}let A=new SG({api:i,signal:t.signal,logger:this.#i});this.#I=new iw({bot:A,harness:this.#t,state:this.#r,contextEnhancement:this.#l,accessPolicy:this.#o,status:this.#p,logger:this.#i,replyTimeoutMs:this.#a,signal:t.signal});let r=this.#r.cursor();if(r===null){let g=await i.getUpdates({offset:-1,timeout:0,signal:t.signal});r=g.length>0?g.at(-1).update_id+1:0,await this.#r.setCursor(r)}let s=Date.now();return this.#p.ready=!0,this.#p.connectionState="connected",this.#p.lastCheckedAt=s,this.#p.lastConnectedAt=s,this.#h=this.#B(r,t.signal),this.#h.catch(g=>{t.signal.aborted||(this.#p.ready=!1,this.#p.connectionState="failed",this.#p.lastError=g?.message??String(g),this.#i.error?.(`[dsh-im:telegram] bot ${this.#e.botId} polling stopped:`,g))}),this.status}catch(o){throw this.#p.ready=!1,this.#p.connectionState="failed",this.#p.lastError=o?.message??String(o),await this.stop(),o}}async#B(t,o){let i=t;for(;!o.aborted;){let e=await this.#g.getUpdates({offset:i,timeout:25,signal:o});if(this.#p.lastCheckedAt=Date.now(),o.aborted)return;let a=e.map(A=>{let r=A?.message?.chat?.type;return{update:A,contextSnapshot:Aa(this.#l,r==="private"?"direct":r==="group"||r==="supergroup"?"group":null)}});for(let{update:A,contextSnapshot:r}of a){if(o.aborted)return;let s=cFe(A,{botId:this.#e.platformId,username:this.#e.username,loadFile:(g,c)=>this.#g.downloadFile({fileId:g,...c}),loadFileStream:(g,c)=>this.#g.downloadFileStream({fileId:g,...c})});s&&this.#I.accept(s,{contextSnapshot:r}).catch(g=>{o.aborted||this.#i.error?.(`[dsh-im:telegram] bot ${this.#e.botId} message handling failed:`,g)}),i=A.update_id+1,await this.#r.setCursor(i)}}}async stop(){let t=this.#h,o=this.#I,i=this.#c;this.#d?.abort(),this.#d=null,this.#h=null,this.#c=null,this.#g=null,this.#I=null,await Promise.race([t?.catch(()=>{})??Promise.resolve(),new Promise(e=>setTimeout(e,2e3))]),await Promise.race([o?.waitForIdle()??Promise.resolve(),new Promise(e=>setTimeout(e,2e3))]);try{await i?.destroy()}catch{this.#i.warn?.("[dsh-im:telegram] Telegram HTTP transport cleanup failed")}return this.#p.ready=!1,this.#p.connectionState="idle",this.status}};var nw=class extends gs{};function DG(n,t={},o={}){return XQ(n,t,o,{channel:"telegram",ConfigStore:tw,StateStore:nw,HarnessClient:aw,Controller:Vu,Runtime:Xu})}var uZ="/telegram",BZ=Tr,lFe=Object.freeze(Object.values(BZ));function fZ(n){return ey(n,{channel:"Telegram"})}function sw(n,t,o){if(!n?.connection?.rpc||typeof n.connection.rpc.handle!="function")throw new TypeError("DSH Host Connection RPC is required");return n.connection.rpc.handle(uZ,fZ(t),{authority:fr(o)})}async function QZ(n,t={}){if(t?.controller)return sw(n,t.controller,t.rpcAuthority);let o=await DG(n,t,t.internals??{}),i=t.deliveryService&&o.deliveryAdapter?t.deliveryService.registerAdapter(o.deliveryAdapter):void 0,e=sw(n,o.controller,t.rpcAuthority);return n.effect(()=>async()=>{await i?.(),await o.close()},"dsh-im: close Telegram bot connections"),e}import{unlink as rLe}from"node:fs/promises";import{homedir as aLe}from"node:os";import{join as rB,resolve as Ol}from"node:path";import{createHash as pFe}from"node:crypto";import{mkdir as dFe,readFile as hFe,rename as EFe,unlink as CFe,writeFile as uFe}from"node:fs/promises";import{dirname as BFe}from"node:path";var OG=Object.freeze({version:1,bots:Object.freeze([])});function Sl(n){return typeof n=="string"&&n.trim()?n.trim():null}function yZ(n){let t=Sl(n);return t&&/^wecom_[a-f0-9]{24}$/.test(t)?t:null}function fFe(n){let t=Sl(n);return t&&/^DSH_WECOM_BOT_SECRET_[A-F0-9]{24}$/.test(t)?t:null}function cw(n){let t=Sl(n);if(!t)throw new TypeError("Enterprise WeChat bot ID is required");let o=pFe("sha256").update(t).digest("hex").slice(0,24);return{botId:`wecom_${o}`,secretRef:`DSH_WECOM_BOT_SECRET_${o.toUpperCase()}`}}function bG(n){let t=Sl(n)??"";return t?t.length<=10?`${t.slice(0,3)}\u2022\u2022\u2022`:`${t.slice(0,6)}\u2022\u2022\u2022\u2022${t.slice(-4)}`:w("\u4F01\u4E1A\u5FAE\u4FE1\u673A\u5668\u4EBA")}function mZ(n){if(!n||typeof n!="object")return null;let t=yZ(n.botId),o=Sl(n.remoteBotId),i=fFe(n.secretRef);if(!t||!o||!i)return null;let e=cw(o);return e.botId!==t||e.secretRef!==i?null:Object.freeze({botId:t,remoteBotId:o,secretRef:i,createdAt:Sl(n.createdAt)??new Date().toISOString(),connectedAt:Sl(n.connectedAt)})}function QFe(n){if(!n||n.version!==1||!Array.isArray(n.bots))return null;let t=n.bots.map(mZ);if(t.some(a=>a===null))return null;let o=new Set,i=new Set,e=new Set;for(let a of t){if(o.has(a.botId)||i.has(a.remoteBotId)||e.has(a.secretRef))return null;o.add(a.botId),i.add(a.remoteBotId),e.add(a.secretRef)}return Object.freeze({version:1,bots:Object.freeze(t)})}var gw=class{#e;#A=OG;#t=Promise.resolve();constructor(t){this.#e=t}async load(){try{let t=QFe(JSON.parse(await hFe(this.#e,"utf8")));if(!t)throw new Error("dsh-im Enterprise WeChat config contains invalid bot data");this.#A=t}catch(t){if(t?.code!=="ENOENT")throw t;this.#A=OG}return this}list(){return structuredClone(this.#A.bots)}get(t){let o=this.#A.bots.find(i=>i.botId===t);return o?structuredClone(o):null}getByRemoteBotId(t){let o=this.#A.bots.find(i=>i.remoteBotId===t);return o?structuredClone(o):null}async save(t){let o=mZ(t);if(!o)throw new Error("Refusing to persist incomplete Enterprise WeChat bot data");return this.#r(i=>{let e=i.find(r=>r.remoteBotId===o.remoteBotId&&r.botId!==o.botId),a=i.find(r=>r.secretRef===o.secretRef&&r.botId!==o.botId);if(e||a)throw new Error("Duplicate Enterprise WeChat bot identity");let A=i.findIndex(r=>r.botId===o.botId);return A===-1?i.push(o):i[A]=o,structuredClone(o)})}async remove(t){if(!yZ(t))throw new TypeError("Invalid Enterprise WeChat bot ID");return this.#r(o=>{let i=o.findIndex(a=>a.botId===t);if(i===-1)return null;let[e]=o.splice(i,1);return structuredClone(e)})}async clear(){let t=this.#t.then(async()=>{try{await CFe(this.#e)}catch(o){if(o?.code!=="ENOENT")throw o}this.#A=OG});this.#t=t.then(()=>{},()=>{}),await t}async#r(t){let o,i=this.#t.then(async()=>{let e=[...this.#A.bots];o=t(e);let a=Object.freeze({version:1,bots:Object.freeze(e)});await this.#l(a),this.#A=a});return this.#t=i.then(()=>{},()=>{}),await i,o}async#l(t){await dFe(BFe(this.#e),{recursive:!0,mode:448});let o=`${this.#e}.tmp`;await uFe(o,`${JSON.stringify(t,null,2)} +`,d=c?o:"```",B=`${g===0?t:""}${s}${c?o:""}`,f=Wu(`${t}${s}${I}${d}`);if(Array.from(f).length>i)throw new Error("Telegram Rich Markdown code block exceeds the limit");return{source:B,markdown:f}})}function fG(n){let t=CG(n);return hZ(t),Wu(t)}function QG(n,t=3e4){if(!Number.isInteger(t)||t<128||t>32768)throw new TypeError("Telegram Rich Markdown limit is invalid");let o=CG(n),i=hZ(o),e=Wu(o);if(Array.from(e).length<=t)return[{source:o,markdown:e}];let a=[],A=0;for(let r=0;rA&&a.push(...dZ(o.slice(A,s.index),t));let c=g.index+g[0].length,I=o.slice(s.index,c),d=Wu(I);Array.from(d).length<=t?a.push({source:I,markdown:d}):a.push(...$Ge(I,s[0],g[0],t)),A=c}return A4096)throw new TypeError("Telegram regular message limit is invalid");return BG(CG(n),t,o=>o.length)}var AFe=Object.freeze([{command:"new",description:"\u5F00\u542F\u4E00\u4E2A\u5168\u65B0\u4F1A\u8BDD"},{command:"compact",description:"\u538B\u7F29\u5F53\u524D\u4F1A\u8BDD\u7684\u8F83\u65E9\u4E0A\u4E0B\u6587"},{command:"workspace",description:"\u5207\u6362\u5DE5\u4F5C\u533A"},{command:"workspacelist",description:"\u5217\u51FA\u5DE5\u4F5C\u533A\u7EDD\u5BF9\u8DEF\u5F84"},{command:"sessionlist",description:"\u5217\u51FA\u4F1A\u8BDD ID \u548C\u6807\u9898"},{command:"sessions",description:"\u5217\u51FA\u4F1A\u8BDD ID \u548C\u6807\u9898"},{command:"session",description:"\u5C06\u5F53\u524D\u804A\u5929\u7ED1\u5B9A\u5230\u6307\u5B9A\u4F1A\u8BDD"},{command:"models",description:"\u6309\u5E8F\u53F7\u5217\u51FA\u6240\u6709\u53EF\u7528\u6A21\u578B"},{command:"model",description:"\u67E5\u770B\u6216\u5207\u6362\u5F53\u524D\u4F1A\u8BDD\u6A21\u578B"},{command:"presetlist",description:"\u5217\u51FA\u53EF\u7528 Agent Preset"},{command:"presets",description:"\u5217\u51FA\u53EF\u7528 Agent Preset"},{command:"preset",description:"\u67E5\u770B\u6216\u8BBE\u7F6E\u65B0\u4F1A\u8BDD Agent Preset"},{command:"stop",description:"\u505C\u6B62\u5F53\u524D\u4EFB\u52A1"},{command:"steer",description:"\u7EA0\u504F\u5F53\u524D\u4EFB\u52A1"},{command:"batch",description:"\u5F00\u59CB\u6279\u91CF\u8F93\u5165\uFF08\u4EC5\u79C1\u804A\uFF09"},{command:"send",description:"\u63D0\u4EA4\u5F53\u524D\u6279\u6B21"},{command:"cancel",description:"\u53D6\u6D88\u5F53\u524D\u6279\u6B21"},{command:"status",description:"\u68C0\u67E5\u8FDE\u63A5\u72B6\u6001"},{command:"version",description:"\u67E5\u770B\u63D2\u4EF6\u7248\u672C"},{command:"help",description:"\u663E\u793A\u5E2E\u52A9"}]);function tFe(){return AFe.map(n=>({...n,description:w(n.description)}))}function rFe(n){return n.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function aFe(n,t){return t?[[n?.text,n?.entities],[n?.caption,n?.caption_entities]].some(([o,i])=>typeof o=="string"&&Array.isArray(i)&&i.some(e=>e?.type!=="mention"||!Number.isInteger(e.offset)||!Number.isInteger(e.length)?!1:o.slice(e.offset,e.offset+e.length).toLowerCase()===`@${t.toLowerCase()}`)):!1}function iFe(n,t){return!t||typeof n!="string"?n:n.replace(new RegExp(`@${rFe(t)}\\b`,"ig"),"").trim()}var oFe=new Set(["image/jpeg","image/png","image/webp","image/gif"]),nFe=new Map([[".jpg","image/jpeg"],[".jpeg","image/jpeg"],[".png","image/png"],[".webp","image/webp"],[".gif","image/gif"]]);function CZ(n){let t=n?.mime_type??n?.mimetype,o=typeof t=="string"?t.toLowerCase():"";if(oFe.has(o))return o;let i=typeof n?.file_name=="string"?n.file_name.toLowerCase():"";for(let[e,a]of nFe)if(i.endsWith(e))return a;return null}function wG(n){return Number.isSafeInteger(n)&&n>=0?n:void 0}function EZ(n){return wG(n?.file_size)??(Number(n?.width)||0)*(Number(n?.height)||0)}function sFe(n,t){let o,i,e;if(Array.isArray(n?.photo)&&n.photo.length>0)o=n.photo.reduce((a,A)=>EZ(A)>EZ(a)?A:a),i="image/jpeg",e=`${o.file_unique_id??o.file_id??"telegram-photo"}.jpg`;else if(n?.document){let a=CZ(n.document);if(!a)return null;o=n.document,i=a,e=typeof o.file_name=="string"?o.file_name:void 0}return!o||typeof o.file_id!="string"?null:{name:e,mediaType:i,size:wG(o.file_size),load:a=>t(o.file_id,a)}}function gFe(n,t){let o=n?.document;if(!o||CZ(o)||typeof o.file_id!="string"||!o.file_id)return null;let i=typeof o.mime_type=="string"&&o.mime_type?o.mime_type.toLowerCase():void 0;return{name:typeof o.file_name=="string"&&o.file_name?o.file_name:String(o.file_unique_id??o.file_id),...i?{mediaType:i}:{},size:wG(o.file_size),load:({signal:e}={})=>t(o.file_id,{signal:e})}}function cFe(n,{botId:t,username:o,loadFile:i=async()=>{throw new Error("Telegram file downloader is unavailable")},loadFileStream:e=i}){let a=n?.message,A=a?.chat?.id,r=a?.from?.id,s=a?.message_id;if(!Number.isSafeInteger(n?.update_id)||A===void 0||r===void 0||!Number.isSafeInteger(s)||!["private","group","supergroup"].includes(a.chat?.type))return null;let g=a.chat.type==="private",c=g||String(a.reply_to_message?.from?.id??"")===String(t)||aFe(a,o),I=Number.isSafeInteger(a.message_thread_id)?a.message_thread_id:void 0,d=sFe(a,i),B=gFe(a,e);return{messageId:String(n.update_id),senderId:String(r),contextSource:()=>({senderName:[a.from?.first_name,a.from?.last_name].filter(f=>typeof f=="string"&&f.trim()).map(f=>f.trim()).join(" ")||a.from?.username,conversationTitle:g?void 0:a.chat?.title}),senderIsBot:a.from?.is_bot===!0,kind:g?"direct":"group",conversationId:I===void 0?String(A):`${A}:${I}`,content:iFe(a.text??a.caption??"",o),plainText:typeof a.text=="string",images:d?[d]:[],files:B?[B]:[],addressed:c,reactionTarget:{chatId:A,messageId:s},replyTarget:{chatId:A,chatType:a.chat.type,replyToMessageId:s,messageThreadId:I},connectionTestTarget:{chatId:A,messageThreadId:I}}}function mG(n){return Number.isSafeInteger(n?.message_id)?String(n.message_id):null}function Zu(n){let t=Number(n?.providerCode),o=Number(n?.status),i=n?.deliveryOutcome==="unknown"||t>=500||o>=500||["telegram-timeout","telegram-aborted-after-dispatch","telegram-transport-error","telegram-response-invalid"].includes(n?.code);return{outcome:i?"unknown":"failed",reason:typeof n?.code=="string"&&n.code?n.code:i?"telegram-delivery-uncertain":"telegram-provider-rejected"}}function xi(n,t,o="sent",i){return{presentation:n,providerMessageIds:[...new Set(t)],deliveryOutcome:o,...i?{reason:i}:{}}}var ow=class{#e;#A;#t;#r;#l;#o=!1;#i=null;constructor({update:t,finish:o,fail:i,providerMessageIds:e=[],presentation:a,logger:A}){this.#e=t,this.#A=o,this.#t=i,this.#l=e,this.presentation=a,this.#r=A}get providerMessageIds(){return[...this.#l]}async update(t){if(this.#o)return;let o=ts(t),i=`${o.format}:${o.text}`;if(i!==this.#i){this.#i=i;try{return await this.#e(o)}catch(e){this.#r.warn?.("[dsh-im:telegram] rich stream update failed:",e);return}}}async finish(t){if(this.#o)throw new Error("Message stream is already closed");this.#o=!0;let o=await this.#A(ts(t));return this.#l.push(...o?.providerMessageIds??[]),o}async fail(t){if(this.#o)return;this.#o=!0;let o=await this.#t(ts(t,"plain"));return this.#l.push(...o?.providerMessageIds??[]),o}cancel(){this.#o=!0}},SG=class{#e;#A;#t;constructor({api:t,signal:o,logger:i=console}){this.#e=t,this.#A=o,this.#t=i}async sendText(t,o){let i=yG(o),e=[];for(let[a,A]of i.entries()){let r=await this.#e.sendMessage({chatId:t.chatId,text:A,replyToMessageId:a===0?t.replyToMessageId:void 0,messageThreadId:t.messageThreadId,signal:this.#A});Number.isSafeInteger(r?.message_id)&&e.push(String(r.message_id))}return{providerMessageIds:e}}async addReaction(t,o,{signal:i}={}){let e=String(o??"").trim();return await this.#e.setMessageReaction({chatId:t.chatId,messageId:t.messageId,emoji:e,signal:i??this.#A}),e}removeReaction(t,o,{signal:i}={}){return this.#e.setMessageReaction({chatId:t.chatId,messageId:t.messageId,signal:i??this.#A})}sendTyping(t){return this.#e.sendChatAction({chatId:t.chatId,messageThreadId:t.messageThreadId,signal:this.#A})}sendFile(t,o){return this.#e.sendDocument({chatId:t.chatId,file:o,replyToMessageId:t.replyToMessageId,messageThreadId:t.messageThreadId,signal:this.#A})}sendImage(t,o){return this.#e.sendPhoto({chatId:t.chatId,file:o,replyToMessageId:t.replyToMessageId,messageThreadId:t.messageThreadId,signal:this.#A})}async#r(t,o,{placeholderMessageId:i}={}){let e=yG(o),a=i===void 0?[]:[String(i)],A=0;if(i!==void 0)try{await this.#e.editMessageText({chatId:t.chatId,messageId:i,text:e[0],signal:this.#A}),A=1}catch(r){let s=Zu(r);if(s.outcome==="unknown")return xi("text-fallback",a,"unknown",s.reason);let g=await this.#r(t,o),c=g.deliveryOutcome==="sent"?"\u56DE\u590D\u5DF2\u53D1\u9001\u3002":g.deliveryOutcome==="unknown"?"\u56DE\u590D\u53D1\u9001\u7ED3\u679C\u672A\u80FD\u786E\u8BA4\u3002":"\u6D88\u606F\u53D1\u9001\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002";try{await this.#e.editMessageText({chatId:t.chatId,messageId:i,text:c,signal:this.#A})}catch(I){this.#t.warn?.("[dsh-im:telegram] unable to replace the processing placeholder:",I)}return xi("text-fallback",[...a,...g.providerMessageIds],g.deliveryOutcome,g.reason)}for(let r=A;rI.source).join(""),c=await this.#r({...t,replyToMessageId:a===0?t.replyToMessageId:void 0},g);return xi(c.presentation,[...e,...c.providerMessageIds],c.deliveryOutcome,c.reason)}return xi("telegram-rich-final",e)}async#o(t,o,i){if(i.format==="plain")return this.#r(t,i.text,{placeholderMessageId:o});let e;try{e=QG(i.text)}catch{return this.#r(t,i.text,{placeholderMessageId:o})}let a=[String(o)];try{await this.#e.editMessageText({chatId:t.chatId,messageId:o,richMessage:{markdown:e[0].markdown},signal:this.#A})}catch(A){let r=Zu(A);return r.outcome==="unknown"?xi("telegram-rich-final",a,"unknown",r.reason):this.#r(t,i.text,{placeholderMessageId:o})}for(let[A,r]of e.slice(1).entries())try{let s=await this.#e.sendRichMessage({chatId:t.chatId,richMessage:{markdown:r.markdown},messageThreadId:t.messageThreadId,signal:this.#A}),g=mG(s);g&&a.push(g)}catch(s){let g=Zu(s);if(g.outcome==="unknown")return xi("telegram-rich-final",a,"unknown",g.reason);let c=e.slice(A+1).map(d=>d.source).join(""),I=await this.#r({...t,replyToMessageId:void 0},c);return xi(I.presentation,[...a,...I.providerMessageIds],I.deliveryOutcome,I.reason)}return xi("telegram-rich-final",a)}sendDelivery(t,o){return this.#l(t,ts(o))}async openDeliveryStream(t){if(t.chatType==="private"){let e=eFe(1,2147483647),a=async r=>{let s={markdown:fG(r.text)};return await this.#e.sendRichMessageDraft({chatId:t.chatId,draftId:e,richMessage:s,messageThreadId:t.messageThreadId,signal:this.#A}),xi("telegram-rich-draft",[])},A=new ow({update:a,finish:r=>this.#l(t,r),fail:r=>this.#r(t,r.text),presentation:"telegram-rich-draft",logger:this.#t});return await A.update(ts("\u6B63\u5728\u5904\u7406\u2026","plain")),A}let i=(await this.#e.sendMessage({chatId:t.chatId,text:"\u6B63\u5728\u5904\u7406\u2026",replyToMessageId:t.replyToMessageId,messageThreadId:t.messageThreadId,signal:this.#A}))?.message_id;if(!Number.isSafeInteger(i))throw new Error("Telegram did not return a placeholder message id");return new ow({update:async e=>e.format==="plain"?(await this.#e.editMessageText({chatId:t.chatId,messageId:i,text:e.text,signal:this.#A}),xi("text-fallback",[String(i)])):(await this.#e.editMessageText({chatId:t.chatId,messageId:i,richMessage:{markdown:fG(e.text)},signal:this.#A}),xi("telegram-rich-draft",[String(i)])),finish:e=>this.#o(t,i,e),fail:e=>this.#r(t,e.text,{placeholderMessageId:i}),providerMessageIds:[String(i)],presentation:"telegram-regular",logger:this.#t})}async openStream(t){return VQ({limit:4e3,create:async i=>(await this.#e.sendMessage({chatId:t.chatId,text:i,replyToMessageId:t.replyToMessageId,messageThreadId:t.messageThreadId,signal:this.#A})).message_id,edit:(i,e)=>this.#e.editMessageText({chatId:t.chatId,messageId:i,text:e,signal:this.#A}),sendRemainder:i=>this.#e.sendMessage({chatId:t.chatId,text:i,messageThreadId:t.messageThreadId,signal:this.#A}),messageIdForResult:i=>i?.message_id}).start()}};function IFe(){return{startedAt:null,ready:!1,connectionState:"idle",harnessReachable:!1,lastCheckedAt:null,lastConnectedAt:null,lastError:null,...io()}}var Xu=class{#e;#A;#t;#r;#l;#o;#i;#a;#n;#s;#p=IFe();#c=null;#g=null;#I=null;#d=null;#h=null;#C=null;constructor({config:t,token:o,harness:i,state:e,contextEnhancement:a,accessPolicy:A,logger:r=console,replyTimeoutMs:s=6e5,createApi:g=I=>new zu(I),createHttpTransport:c=pZ}){if(!t||!o||!i||!e)throw new TypeError("TelegramRuntime requires config, token, Harness, and state");this.#e=t,this.#A=o,this.#t=i,this.#r=e,this.#l=a,this.#o=A,this.#i=r,this.#a=s,this.#n=g,this.#s=c}get status(){return structuredClone(this.#p)}async sendConnectionTest(t){if(!this.#p.ready||!this.#I){let o=new Error("Telegram bot is not connected");throw o.code="test-target-unavailable",o}return this.#I.sendConnectionTest(t)}async sendProactiveText(t,o,i={}){if(!this.#p.ready||!this.#I){let r=new Error("Telegram bot is not connected");throw r.code="bot-not-connected",r}let e=typeof t?.route?.chatId=="string"?t.route.chatId.trim():"",a=Number(e),A=t?.route?.messageThreadId;if(!/^-?\d+$/.test(e)||!Number.isSafeInteger(a)||t?.kind!=="chat"&&t?.kind!=="topic"||t.kind==="topic"&&(!Number.isSafeInteger(A)||A<=0)||t.kind==="chat"&&A!==void 0){let r=new TypeError("Invalid Telegram proactive delivery target");throw r.code="invalid-target",r}return this.#I.sendProactiveText({chatId:a,...t.kind==="topic"?{messageThreadId:A}:{}},o,i)}async start(){return this.#p.ready&&this.#h?this.status:this.#C?this.#C:(this.#C=this.#u().finally(()=>{this.#C=null}),this.#C)}async#u(){await this.stop(),this.#p.startedAt=new Date().toISOString(),this.#p.connectionState="connecting",this.#p.lastError=null,await this.#t.ensureRunning(),this.#p.harnessReachable=!0;let t=new AbortController;this.#d=t;try{let o=this.#s();this.#c=o;let i=this.#n({token:this.#A,fetchImpl:o.fetchImpl,FormDataImpl:o.FormDataImpl});this.#g=i;let e=await i.getMe({signal:t.signal});if(String(e?.id??"")!==this.#e.platformId||e?.is_bot!==!0)throw new Error("Telegram token identity does not match the saved bot");let a=await i.getWebhookInfo({signal:t.signal});if(typeof a?.url=="string"&&a.url){let g=new Error(w("\u8BE5 Telegram \u673A\u5668\u4EBA\u5DF2\u914D\u7F6E Webhook\uFF0C\u8BF7\u5148\u5728\u539F\u670D\u52A1\u4E2D\u79FB\u9664 Webhook \u540E\u91CD\u8BD5\u3002"));throw g.code="webhook-configured",g}try{await i.setMyCommands({commands:tFe(),signal:t.signal}),await i.setChatMenuButton({menuButton:dG,signal:t.signal})}catch(g){this.#i.warn?.(`[dsh-im:telegram] bot ${this.#e.botId} command menu setup failed:`,g)}let A=new SG({api:i,signal:t.signal,logger:this.#i});this.#I=new iw({bot:A,harness:this.#t,state:this.#r,contextEnhancement:this.#l,accessPolicy:this.#o,status:this.#p,logger:this.#i,replyTimeoutMs:this.#a,signal:t.signal});let r=this.#r.cursor();if(r===null){let g=await i.getUpdates({offset:-1,timeout:0,signal:t.signal});r=g.length>0?g.at(-1).update_id+1:0,await this.#r.setCursor(r)}let s=Date.now();return this.#p.ready=!0,this.#p.connectionState="connected",this.#p.lastCheckedAt=s,this.#p.lastConnectedAt=s,this.#h=this.#B(r,t.signal),this.#h.catch(g=>{t.signal.aborted||(this.#p.ready=!1,this.#p.connectionState="failed",this.#p.lastError=g?.message??String(g),this.#i.error?.(`[dsh-im:telegram] bot ${this.#e.botId} polling stopped:`,g))}),this.status}catch(o){throw this.#p.ready=!1,this.#p.connectionState="failed",this.#p.lastError=o?.message??String(o),await this.stop(),o}}async#B(t,o){let i=t;for(;!o.aborted;){let e=await this.#g.getUpdates({offset:i,timeout:25,signal:o});if(this.#p.lastCheckedAt=Date.now(),o.aborted)return;let a=e.map(A=>{let r=A?.message?.chat?.type;return{update:A,contextSnapshot:Aa(this.#l,r==="private"?"direct":r==="group"||r==="supergroup"?"group":null)}});for(let{update:A,contextSnapshot:r}of a){if(o.aborted)return;let s=cFe(A,{botId:this.#e.platformId,username:this.#e.username,loadFile:(g,c)=>this.#g.downloadFile({fileId:g,...c}),loadFileStream:(g,c)=>this.#g.downloadFileStream({fileId:g,...c})});s&&this.#I.accept(s,{contextSnapshot:r}).catch(g=>{o.aborted||this.#i.error?.(`[dsh-im:telegram] bot ${this.#e.botId} message handling failed:`,g)}),i=A.update_id+1,await this.#r.setCursor(i)}}}async stop(){let t=this.#h,o=this.#I,i=this.#c;this.#d?.abort(),this.#d=null,this.#h=null,this.#c=null,this.#g=null,this.#I=null,await Promise.race([t?.catch(()=>{})??Promise.resolve(),new Promise(e=>setTimeout(e,2e3))]),await Promise.race([o?.waitForIdle()??Promise.resolve(),new Promise(e=>setTimeout(e,2e3))]);try{await i?.destroy()}catch{this.#i.warn?.("[dsh-im:telegram] Telegram HTTP transport cleanup failed")}return this.#p.ready=!1,this.#p.connectionState="idle",this.status}};var nw=class extends gs{};function DG(n,t={},o={}){return XQ(n,t,o,{channel:"telegram",ConfigStore:tw,StateStore:nw,HarnessClient:aw,Controller:Vu,Runtime:Xu})}var uZ="/telegram",BZ=Tr,lFe=Object.freeze(Object.values(BZ));function fZ(n){return ey(n,{channel:"Telegram"})}function sw(n,t,o){if(!n?.connection?.rpc||typeof n.connection.rpc.handle!="function")throw new TypeError("DSH Host Connection RPC is required");return n.connection.rpc.handle(uZ,fZ(t),{authority:fr(o)})}async function QZ(n,t={}){if(t?.controller)return sw(n,t.controller,t.rpcAuthority);let o=await DG(n,t,t.internals??{}),i=t.deliveryService&&o.deliveryAdapter?t.deliveryService.registerAdapter(o.deliveryAdapter):void 0,e=sw(n,o.controller,t.rpcAuthority);return n.effect(()=>async()=>{await i?.(),await o.close()},"dsh-im: close Telegram bot connections"),e}import{unlink as rLe}from"node:fs/promises";import{homedir as aLe}from"node:os";import{join as rB,resolve as Ol}from"node:path";import{createHash as pFe}from"node:crypto";import{mkdir as dFe,readFile as hFe,rename as EFe,unlink as CFe,writeFile as uFe}from"node:fs/promises";import{dirname as BFe}from"node:path";var OG=Object.freeze({version:1,bots:Object.freeze([])});function Sl(n){return typeof n=="string"&&n.trim()?n.trim():null}function yZ(n){let t=Sl(n);return t&&/^wecom_[a-f0-9]{24}$/.test(t)?t:null}function fFe(n){let t=Sl(n);return t&&/^DSH_WECOM_BOT_SECRET_[A-F0-9]{24}$/.test(t)?t:null}function cw(n){let t=Sl(n);if(!t)throw new TypeError("Enterprise WeChat bot ID is required");let o=pFe("sha256").update(t).digest("hex").slice(0,24);return{botId:`wecom_${o}`,secretRef:`DSH_WECOM_BOT_SECRET_${o.toUpperCase()}`}}function bG(n){let t=Sl(n)??"";return t?t.length<=10?`${t.slice(0,3)}\u2022\u2022\u2022`:`${t.slice(0,6)}\u2022\u2022\u2022\u2022${t.slice(-4)}`:w("\u4F01\u4E1A\u5FAE\u4FE1\u673A\u5668\u4EBA")}function mZ(n){if(!n||typeof n!="object")return null;let t=yZ(n.botId),o=Sl(n.remoteBotId),i=fFe(n.secretRef);if(!t||!o||!i)return null;let e=cw(o);return e.botId!==t||e.secretRef!==i?null:Object.freeze({botId:t,remoteBotId:o,secretRef:i,createdAt:Sl(n.createdAt)??new Date().toISOString(),connectedAt:Sl(n.connectedAt)})}function QFe(n){if(!n||n.version!==1||!Array.isArray(n.bots))return null;let t=n.bots.map(mZ);if(t.some(a=>a===null))return null;let o=new Set,i=new Set,e=new Set;for(let a of t){if(o.has(a.botId)||i.has(a.remoteBotId)||e.has(a.secretRef))return null;o.add(a.botId),i.add(a.remoteBotId),e.add(a.secretRef)}return Object.freeze({version:1,bots:Object.freeze(t)})}var gw=class{#e;#A=OG;#t=Promise.resolve();constructor(t){this.#e=t}async load(){try{let t=QFe(JSON.parse(await hFe(this.#e,"utf8")));if(!t)throw new Error("dsh-im Enterprise WeChat config contains invalid bot data");this.#A=t}catch(t){if(t?.code!=="ENOENT")throw t;this.#A=OG}return this}list(){return structuredClone(this.#A.bots)}get(t){let o=this.#A.bots.find(i=>i.botId===t);return o?structuredClone(o):null}getByRemoteBotId(t){let o=this.#A.bots.find(i=>i.remoteBotId===t);return o?structuredClone(o):null}async save(t){let o=mZ(t);if(!o)throw new Error("Refusing to persist incomplete Enterprise WeChat bot data");return this.#r(i=>{let e=i.find(r=>r.remoteBotId===o.remoteBotId&&r.botId!==o.botId),a=i.find(r=>r.secretRef===o.secretRef&&r.botId!==o.botId);if(e||a)throw new Error("Duplicate Enterprise WeChat bot identity");let A=i.findIndex(r=>r.botId===o.botId);return A===-1?i.push(o):i[A]=o,structuredClone(o)})}async remove(t){if(!yZ(t))throw new TypeError("Invalid Enterprise WeChat bot ID");return this.#r(o=>{let i=o.findIndex(a=>a.botId===t);if(i===-1)return null;let[e]=o.splice(i,1);return structuredClone(e)})}async clear(){let t=this.#t.then(async()=>{try{await CFe(this.#e)}catch(o){if(o?.code!=="ENOENT")throw o}this.#A=OG});this.#t=t.then(()=>{},()=>{}),await t}async#r(t){let o,i=this.#t.then(async()=>{let e=[...this.#A.bots];o=t(e);let a=Object.freeze({version:1,bots:Object.freeze(e)});await this.#l(a),this.#A=a});return this.#t=i.then(()=>{},()=>{}),await i,o}async#l(t){await dFe(BFe(this.#e),{recursive:!0,mode:448});let o=`${this.#e}.tmp`;await uFe(o,`${JSON.stringify(t,null,2)} `,{encoding:"utf8",mode:384}),await EFe(o,this.#e)}};var Iw=class extends ur{constructor(t){super({...t,rpcIdPrefix:"wecom",logPrefix:"dsh-wecom"})}};var yFe="https://work.weixin.qq.com/ai/qc/generate",mFe="https://work.weixin.qq.com/ai/qc/query_result";function SZ(){return process.platform==="win32"?2:process.platform==="linux"?3:1}function Zd(n){return typeof n=="string"&&n.trim()?n.trim():null}function SFe(n){let t=Zd(n);if(!t)return null;try{let o=new URL(t);return o.protocol==="https:"&&o.hostname==="work.weixin.qq.com"&&(!o.port||o.port==="443")?o.href:null}catch{return null}}function wFe(n,t){return n?AbortSignal.any([n,AbortSignal.timeout(t)]):AbortSignal.timeout(t)}async function wZ(n,t,o){let i=await n(t,{method:"GET",redirect:"error",signal:wFe(o,1e4),headers:{accept:"application/json"}});if(!i.ok)throw new Error(`Enterprise WeChat QR service returned HTTP ${i.status}`);return i.json()}var lw=class{#e;#A;#t;#r;constructor({fetch:t=globalThis.fetch,clock:o=()=>Date.now(),source:i="deepseek-harness",platform:e=SZ()}={}){if(typeof t!="function")throw new TypeError("A fetch implementation is required");this.#e=t,this.#A=o,this.#t=i,this.#r=[1,2,3].includes(e)?e:SZ()}async start({signal:t}={}){let o=new URL(yFe);o.searchParams.set("source",this.#t),o.searchParams.set("plat",String(this.#r));let i=await wZ(this.#e,o,t),e=Zd(i?.data?.scode),a=SFe(i?.data?.auth_url);if(!e||!a)throw new Error("Enterprise WeChat QR service returned invalid data");return{scode:e,verificationUrl:a,expiresAt:this.#A()+3e5,pollIntervalMs:3e3}}async poll({scode:t,signal:o}={}){let i=Zd(t);if(!i)throw new TypeError("Enterprise WeChat QR poll code is required");let e=new URL(mFe);e.searchParams.set("scode",i);let a=await wZ(this.#e,e,o),A=Zd(a?.data?.status)?.toLowerCase();if(A==="success"){let r=Zd(a?.data?.bot_info?.botid),s=Zd(a?.data?.bot_info?.secret);if(!r||!s)throw new Error("Enterprise WeChat QR result omitted bot credentials");return{status:"success",remoteBotId:r,secret:s}}return["expired","timeout"].includes(A)?{status:"expired"}:["fail","failed","error"].includes(A)?{status:"failed"}:{status:"waiting"}}};import{mkdir as DFe,readFile as OFe,rename as bFe,unlink as MFe,writeFile as _Fe}from"node:fs/promises";import{dirname as TFe}from"node:path";var pw=Object.freeze({version:1,sessions:{},seenMessageIds:[]});function NFe(n){if(!n||typeof n!="object")return structuredClone(pw);let t={};if(n.sessions&&typeof n.sessions=="object"&&!Array.isArray(n.sessions))for(let[o,i]of Object.entries(n.sessions))typeof o=="string"&&typeof i=="string"&&i&&(t[o]=i);return{version:1,sessions:t,seenMessageIds:Array.isArray(n.seenMessageIds)?n.seenMessageIds.filter(o=>typeof o=="string").slice(-1e3):[]}}var dw=class{#e;#A=structuredClone(pw);#t=Promise.resolve();constructor(t){this.#e=t}async load(){try{this.#A=NFe(JSON.parse(await OFe(this.#e,"utf8")))}catch(t){if(t?.code!=="ENOENT")throw t;this.#A=structuredClone(pw),await this.#r()}return this}sessionFor(t){return this.#A.sessions[t]??null}async setSession(t,o){this.#A.sessions[t]=o,await this.#r()}async clearSession(t){delete this.#A.sessions[t],await this.#r()}async clearSessions(){this.#A.sessions={},await this.#r()}hasSeen(t){return this.#A.seenMessageIds.includes(t)}async markSeen(t){this.hasSeen(t)||(this.#A.seenMessageIds.push(t),this.#A.seenMessageIds.length>1e3&&this.#A.seenMessageIds.splice(0,this.#A.seenMessageIds.length-1e3),await this.#r())}snapshot(){return structuredClone(this.#A)}async remove(){try{await MFe(this.#e)}catch(t){if(t?.code!=="ENOENT")throw t}this.#A=structuredClone(pw)}async#r(){let t=`${JSON.stringify(this.#A,null,2)} `,o=this.#t.then(async()=>{await DFe(TFe(this.#e),{recursive:!0,mode:448});let i=`${this.#e}.tmp`;await _Fe(i,t,{encoding:"utf8",mode:384}),await bFe(i,this.#e)});this.#t=o.then(()=>{},()=>{}),await o}};import{randomUUID as RFe}from"node:crypto";var DZ=new Set(["pending","connecting"]),$u=new Set(["connected","failed","cancelled","expired"]);function wl(n){return typeof n=="string"&&n.trim()?n.trim():null}function Yi(n,t){return Object.freeze({code:n,message:t})}function Dl(n){return n?{attemptId:n.id,status:n.state,pollIntervalMs:n.pollIntervalMs,qrRevision:n.qrRevision,...n.verificationUrl?{verificationUrl:n.verificationUrl}:{},...n.expiresAt?{expiresAt:n.expiresAt}:{},...n.botId?{botId:n.botId}:{},...n.error?{error:structuredClone(n.error)}:{}}:null}var eB=class{#e;#A;#t;#r;#l;#o;#i=new Map;#a=new Map;#n=new Map;#s=null;#p=new Map;#c=0;#g=!1;constructor({qrAuth:t,credentials:o,configStore:i,createRuntime:e,deleteState:a=async()=>{},logger:A=console}){if(!t||typeof t.start!="function"||typeof t.poll!="function")throw new TypeError("Enterprise WeChat QR auth is required");if(!o||typeof o.resolve!="function"||typeof o.set!="function"||typeof o.unset!="function")throw new TypeError("WecomController requires the DSH credential provider");if(!i||typeof i.list!="function"||typeof i.save!="function"||typeof i.remove!="function")throw new TypeError("WecomController requires a config store");if(typeof e!="function")throw new TypeError("createRuntime is required");this.#e=t,this.#A=o,this.#t=i,this.#r=e,this.#l=a,this.#o=A}async initialize(){if(this.#g)return this.status();for(let t of this.#t.list())await this.#Q(t.botId,async()=>{let o=this.#i.get(t.botId)?.status;if(this.#g||o?.ready||o?.wecomConnectionState==="connecting")return;let i=await this.#B(t.secretRef);if(!i){this.#a.set(t.botId,Yi("missing-secret",w("\u4F01\u4E1A\u5FAE\u4FE1\u673A\u5668\u4EBA\u51ED\u636E\u7F3A\u5931\uFF0C\u8BF7\u79FB\u9664\u540E\u91CD\u65B0\u626B\u7801\u3002")));return}try{await this.#C(t,i),this.#a.delete(t.botId)}catch{this.#a.set(t.botId,Yi("connection-failed",w("\u4F01\u4E1A\u5FAE\u4FE1\u8FDE\u63A5\u672A\u5C31\u7EEA\uFF0C\u63D2\u4EF6\u4F1A\u81EA\u52A8\u91CD\u8BD5\u3002"))),this.#o.warn?.(`[dsh-im:wecom] bot ${t.botId} failed to initialize`)}finally{this.#y()}});return this.status()}async startProvisioning(){if(this.#g)throw new Error("Enterprise WeChat controller is closed");this.#s&&await this.cancelProvisioning(this.#s);let t={id:RFe(),state:"pending",createdAt:Date.now(),expiresAt:null,pollIntervalMs:3e3,qrRevision:1,verificationUrl:null,scode:null,botId:null,error:null,controller:new AbortController,polling:null,transition:null};this.#n.set(t.id,t),this.#s=t.id,this.#y();try{let o=await this.#e.start({signal:t.controller.signal});if(t.scode=wl(o.scode),t.verificationUrl=wl(o.verificationUrl),t.expiresAt=Number(o.expiresAt),t.pollIntervalMs=Math.min(1e4,Math.max(500,Number(o.pollIntervalMs)||3e3)),!t.scode||!t.verificationUrl||!Number.isFinite(t.expiresAt))throw new Error("Enterprise WeChat QR auth returned incomplete data");return this.#y(),Dl(t)}catch(o){throw t.state=t.controller.signal.aborted?"cancelled":"failed",t.error=t.controller.signal.aborted?Yi("cancelled",w("\u626B\u7801\u7ED1\u5B9A\u5DF2\u53D6\u6D88\u3002")):Yi("qr-start-failed",w("\u65E0\u6CD5\u751F\u6210\u4F01\u4E1A\u5FAE\u4FE1\u4E8C\u7EF4\u7801\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002")),this.#S(t),o}}async registrationStatus(t){let o=this.#n.get(t);if(!o||$u.has(o.state))return Dl(o);if(o.state==="connecting")return await o.transition?.catch(()=>{}),Dl(o);if(Date.now()>=o.expiresAt)return o.state="expired",o.error=Yi("expired",w("\u4F01\u4E1A\u5FAE\u4FE1\u4E8C\u7EF4\u7801\u5DF2\u8FC7\u671F\uFF0C\u8BF7\u91CD\u65B0\u751F\u6210\u3002")),o.controller.abort(),this.#S(o),Dl(o);if(!o.polling){let i=this.#I(o).finally(()=>{o.polling===i&&(o.polling=null)});o.polling=i}return await o.polling.catch(()=>{}),Dl(o)}async bindCredentials({botId:t,secret:o}={}){if(this.#g)throw new Error("Enterprise WeChat controller is closed");let i=wl(t),e=wl(o);if(!i||!e)throw new TypeError("Enterprise WeChat Bot ID and Secret are required");if(this.#s&&await this.cancelProvisioning(this.#s),this.#g)throw new Error("Enterprise WeChat controller is closed");let a=cw(i);return await this.#Q(a.botId,async()=>{if(this.#g)throw new Error("Enterprise WeChat controller is closed");let A=this.#t.getByRemoteBotId(i),r=await this.#A.resolve(a.secretRef).catch(()=>{});if(this.#g)throw new Error("Enterprise WeChat controller is closed");let s={botId:a.botId,remoteBotId:i,secretRef:a.secretRef,createdAt:A?.createdAt??new Date().toISOString(),connectedAt:new Date().toISOString()};await this.#A.set(a.secretRef,e);try{await this.#t.save(s)}catch(g){throw await this.#f(a.secretRef,r),g}try{await this.#C(s,e),this.#a.delete(a.botId)}catch{this.#a.set(a.botId,Yi("connection-failed",w("\u4F01\u4E1A\u5FAE\u4FE1\u673A\u5668\u4EBA\u5DF2\u7ED1\u5B9A\uFF0C\u6D88\u606F\u8FDE\u63A5\u6682\u672A\u5C31\u7EEA\u3002"))),this.#o.warn?.(`[dsh-im:wecom] bot ${a.botId} credential connection failed`)}this.#y()}),this.status()}async cancelProvisioning(t){let o=this.#n.get(t);return o?($u.has(o.state)||(o.controller.abort(),await Promise.allSettled([o.polling,o.transition].filter(Boolean)),$u.has(o.state)||(o.state="cancelled"),o.error??=Yi("cancelled",w("\u626B\u7801\u7ED1\u5B9A\u5DF2\u53D6\u6D88\u3002")),this.#S(o)),Dl(o)):null}async reconnectBot(t){let o=this.#t.get(t);if(!o)throw new Error("Unknown Enterprise WeChat bot");return await this.#Q(t,async()=>{let i=await this.#B(o.secretRef);if(!i)throw new Error("Enterprise WeChat bot secret is missing");try{await this.#C(o,i),this.#a.delete(t)}catch(e){throw this.#a.set(t,Yi("connection-failed",w("\u4F01\u4E1A\u5FAE\u4FE1\u8FDE\u63A5\u4ECD\u672A\u5C31\u7EEA\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002"))),e}finally{this.#y()}}),this.status()}async sendConnectionTest(t){let o=this.#t.get(t);if(!o)throw new Error("Unknown Enterprise WeChat bot");return this.#Q(t,async()=>{let i=this.#i.get(t);if(!i?.status?.ready||typeof i.sendConnectionTest!="function")throw Cr(w("\u4F01\u4E1A\u5FAE\u4FE1\u673A\u5668\u4EBA"));return i.sendConnectionTest(Ra(w("\u4F01\u4E1A\u5FAE\u4FE1\u673A\u5668\u4EBA\uFF08{botId}\uFF09",{botId:bG(o.remoteBotId)})))})}async sendProactiveText(t,o,i,e={}){if(!this.#t.get(t))throw new Error("Unknown Enterprise WeChat bot");return this.#Q(t,async()=>{let A=this.#i.get(t);if(!A?.status?.ready||typeof A.sendProactiveText!="function"){let r=new Error(w("\u4F01\u4E1A\u5FAE\u4FE1\u8FDE\u63A5\u5F53\u524D\u79BB\u7EBF"));throw r.code="bot-not-connected",r}return A.sendProactiveText(o,i,e)})}async deleteBot(t){let o=this.#t.get(t);if(!o)throw new Error("Unknown Enterprise WeChat bot");return await this.#Q(t,async()=>{let i=await this.#A.resolve(o.secretRef).catch(()=>{});await this.#u(t);try{await this.#A.unset(o.secretRef),await this.#t.remove(t)}catch(e){throw i?.value&&(await this.#A.set(o.secretRef,i.value).catch(()=>{}),await this.#C(o,i.value).catch(()=>{})),new Error("Unable to remove the Enterprise WeChat bot safely.",{cause:e})}await this.#l({botId:t,config:o}).catch(e=>{this.#o.warn?.(`[dsh-im:wecom] bot ${t} state cleanup failed:`,e)}),this.#a.delete(t),this.#y()}),this.status()}status(){let t=this.#t.list().map(e=>{let a=this.#i.get(e.botId)?.status??null,A=a?.ready===!0&&a.wecomConnectionState==="connected"&&a.harnessReachable===!0,r=A?"connected":a?.wecomConnectionState==="connecting"?"connecting":this.#a.has(e.botId)||a?.wecomConnectionState==="failed"?"error":"offline";return{botId:e.botId,state:r,connected:A,configured:!0,bot:{name:w("\u4F01\u4E1A\u5FAE\u4FE1\u673A\u5668\u4EBA"),appIdMasked:bG(e.remoteBotId)},health:{status:A?"healthy":r==="error"?"error":"offline",summary:A?w("\u4F01\u4E1A\u5FAE\u4FE1 WebSocket \u957F\u8FDE\u63A5\u8FD0\u884C\u6B63\u5E38"):r==="error"?w("\u4F01\u4E1A\u5FAE\u4FE1\u8FDE\u63A5\u672A\u5C31\u7EEA\uFF0C\u63D2\u4EF6\u4F1A\u81EA\u52A8\u91CD\u8BD5"):w("\u4F01\u4E1A\u5FAE\u4FE1\u8FDE\u63A5\u5F53\u524D\u79BB\u7EBF"),lastCheckedAt:a?.lastCheckedAt??null,lastConnectedAt:a?.lastConnectedAt??null},stats:{messagesReceived:a?.messagesReceived??0,messagesReplied:a?.messagesReplied??0},lastMessageError:Xr(a?.lastMessageError),error:structuredClone(this.#a.get(e.botId)??null)}}),o=t.filter(e=>e.connected).length,i=this.#s?this.#n.get(this.#s):null;return{schemaVersion:1,revision:this.#c,state:i&&DZ.has(i.state)?"provisioning":t.length===0?"disconnected":o===t.length?"connected":o>0?"degraded":"offline",bots:t,totals:{configured:t.length,connected:o},...i&&DZ.has(i.state)?{provisioning:Dl(i)}:{}}}async close(){this.#g||(this.#g=!0,this.#s&&await this.cancelProvisioning(this.#s),await Promise.allSettled([...this.#p.values()]),await Promise.allSettled([...this.#i.keys()].map(t=>this.#u(t))))}async#I(t){try{let o=await this.#e.poll({scode:t.scode,signal:t.controller.signal});if(t.controller.signal.aborted||$u.has(t.state)||o.status==="waiting")return;if(o.status==="expired"){t.state="expired",t.error=Yi("expired",w("\u4F01\u4E1A\u5FAE\u4FE1\u4E8C\u7EF4\u7801\u5DF2\u8FC7\u671F\uFF0C\u8BF7\u91CD\u65B0\u751F\u6210\u3002")),this.#S(t);return}if(o.status!=="success"){t.state="failed",t.error=Yi("qr-connect-failed",w("\u4F01\u4E1A\u5FAE\u4FE1\u626B\u7801\u6CA1\u6709\u5B8C\u6210\uFF0C\u8BF7\u91CD\u65B0\u751F\u6210\u4E8C\u7EF4\u7801\u3002")),this.#S(t);return}t.state="connecting",t.verificationUrl=null,t.expiresAt=null,t.scode=null,this.#y();let i=this.#d(t,o);t.transition=i,await i}catch{if(t.controller.signal.aborted)return;t.state="failed",t.error=Yi("qr-connect-failed",w("\u4F01\u4E1A\u5FAE\u4FE1\u626B\u7801\u670D\u52A1\u6682\u65F6\u4E0D\u53EF\u7528\uFF0C\u8BF7\u91CD\u65B0\u751F\u6210\u4E8C\u7EF4\u7801\u3002")),this.#o.warn?.("[dsh-im:wecom] QR polling failed"),this.#S(t)}}async#d(t,o){try{let i=wl(o.remoteBotId),e=wl(o.secret);if(!i||!e)throw new Error("Enterprise WeChat authorization returned incomplete credentials");t.botId=await this.#h(t,{remoteBotId:i,secret:e}),t.state="connected",t.error=null}catch{t.controller.signal.aborted?(t.state="cancelled",t.error=Yi("cancelled",w("\u626B\u7801\u7ED1\u5B9A\u5DF2\u53D6\u6D88\u3002"))):(t.state="failed",t.error=Yi("activation-failed",w("\u4F01\u4E1A\u5FAE\u4FE1\u5DF2\u6388\u6743\uFF0C\u4F46\u65E0\u6CD5\u5B89\u5168\u4FDD\u5B58\u63A5\u5165\u914D\u7F6E\u3002")),this.#o.error?.("[dsh-im:wecom] provisioning failed"))}finally{this.#S(t)}}async#h(t,{remoteBotId:o,secret:i}){let e=cw(o),a=this.#t.getByRemoteBotId(o),A=await this.#A.resolve(e.secretRef).catch(()=>{}),r={botId:e.botId,remoteBotId:o,secretRef:e.secretRef,createdAt:a?.createdAt??new Date().toISOString(),connectedAt:new Date().toISOString()};return this.#Q(e.botId,async()=>{await this.#A.set(e.secretRef,i);try{if(t.controller.signal.aborted)throw new DOMException("Cancelled","AbortError");await this.#t.save(r)}catch(s){throw await this.#f(e.secretRef,A),s}try{if(t.controller.signal.aborted)throw new DOMException("Cancelled","AbortError");await this.#C(r,i),this.#a.delete(e.botId)}catch(s){if(t.controller.signal.aborted)throw await this.#u(e.botId),a?await this.#t.save(a).catch(()=>{}):await this.#t.remove(e.botId).catch(()=>null)&&await this.#l({botId:e.botId,config:r}).catch(c=>{this.#o.warn?.("[dsh-im:wecom] cancelled bot state cleanup failed:",c)}),await this.#f(e.secretRef,A),s;this.#a.set(e.botId,Yi("connection-failed",w("\u4F01\u4E1A\u5FAE\u4FE1\u673A\u5668\u4EBA\u5DF2\u7ED1\u5B9A\uFF0C\u6D88\u606F\u8FDE\u63A5\u6682\u672A\u5C31\u7EEA\u3002"))),this.#o.warn?.(`[dsh-im:wecom] bot ${e.botId} activation connection failed`)}return this.#y(),e.botId})}async#C(t,o){if(this.#g)throw new Error("Enterprise WeChat controller is closed");if(await this.#u(t.botId),this.#g)throw new Error("Enterprise WeChat controller is closed");let i=await this.#r({botId:t.botId,config:t,secret:o});if(!i||typeof i.start!="function"||typeof i.stop!="function")throw new TypeError("createRuntime returned an invalid Enterprise WeChat runtime");this.#i.set(t.botId,i);try{await i.start()}catch(e){throw await i.stop().catch(()=>{}),this.#i.delete(t.botId),e}}async#u(t){let o=this.#i.get(t);this.#i.delete(t),await o?.stop().catch(i=>{this.#o.warn?.(`[dsh-im:wecom] bot ${t} failed to stop cleanly:`,i)})}async#B(t){let o=await this.#A.resolve(t).catch(()=>{});return wl(o?.value)}async#f(t,o){o?.value?await this.#A.set(t,o.value).catch(()=>{}):await this.#A.unset(t).catch(()=>{})}#Q(t,o){let a=(this.#p.get(t)??Promise.resolve()).catch(()=>{}).then(o).finally(()=>{this.#p.get(t)===a&&this.#p.delete(t)});return this.#p.set(t,a),a}#S(t){t.scode=null,t.verificationUrl=null,t.expiresAt=null,this.#s===t.id&&(this.#s=null),this.#y();let o=[...this.#n.values()].filter(i=>$u.has(i.state));for(;o.length>16;)this.#n.delete(o.shift().id)}#y(){this.#c+=1}};import{WSAuthFailureError as ZFe,WSClient as XFe,WSReconnectExhaustedError as $Fe}from"@wecom/aibot-node-sdk";import{generateReqId as kFe}from"@wecom/aibot-node-sdk";var NG=12e4;function vFe(){return[w("\u4F01\u4E1A\u5FAE\u4FE1\u673A\u5668\u4EBA\u5DF2\u8FDE\u63A5 DeepSeek Harness\u3002"),"",w("\u76F4\u63A5\u53D1\u9001\u6587\u5B57\u3001\u56FE\u7247\u6216\u6587\u4EF6\u5373\u53EF\u7EE7\u7EED\u5F53\u524D\u4F1A\u8BDD\u3002"),w("/new \u5F00\u542F\u4E00\u4E2A\u5168\u65B0\u4F1A\u8BDD"),w("/compact \u538B\u7F29\u5F53\u524D\u4F1A\u8BDD\u7684\u8F83\u65E9\u4E0A\u4E0B\u6587"),w("/history [\u6570\u91CF] \u67E5\u770B\u6700\u8FD1\u5386\u53F2\u6D88\u606F\uFF08\u9ED8\u8BA4 3 \u6761\uFF0C\u6700\u591A 5 \u6761\uFF09"),w("/workspace \u5DE5\u4F5C\u533A\u5E8F\u53F7\u6216\u7EDD\u5BF9\u8DEF\u5F84 \u5207\u6362\u5DE5\u4F5C\u533A"),w("/workspacelist \u5217\u51FA\u5DE5\u4F5C\u533A\u7EDD\u5BF9\u8DEF\u5F84"),w("/sessionlist \u6216 /sessions [\u5DE5\u4F5C\u533A\u5E8F\u53F7\u6216\u7EDD\u5BF9\u8DEF\u5F84] \u5217\u51FA\u4F1A\u8BDD ID \u548C\u6807\u9898"),w("/session Session ID \u6216\u5F53\u524D\u5DE5\u4F5C\u533A\u5E8F\u53F7 \u5C06\u5F53\u524D\u804A\u5929\u7ED1\u5B9A\u5230\u6307\u5B9A\u4F1A\u8BDD"),w("/models \u6309\u5E8F\u53F7\u5217\u51FA\u6240\u6709\u53EF\u7528\u6A21\u578B"),w("/reasoninglist \u6216 /reasonings \u6309\u5E8F\u53F7\u5217\u51FA\u5F53\u524D\u6A21\u578B\u53EF\u7528\u63A8\u7406\u7B49\u7EA7"),w("/reasoning [\u5E8F\u53F7\u3001\u7B49\u7EA7ID\u6216 --default] \u67E5\u770B\u6216\u5207\u6362\u5F53\u524D\u63A8\u7406\u7B49\u7EA7"),w("/model [\u5E8F\u53F7\u6216\u5B8C\u6574\u6A21\u578BID] [\u63A8\u7406\u7B49\u7EA7ID] \u67E5\u770B\u6216\u5207\u6362\u5F53\u524D\u4F1A\u8BDD\u6A21\u578B"),w("\u793A\u4F8B\uFF1A\u5148\u53D1 /models\uFF0C\u518D\u53D1 /model 2 [\u63A8\u7406\u7B49\u7EA7ID]"),w("/presetlist \u6216 /presets \u6309\u5E8F\u53F7\u5217\u51FA\u53EF\u7528 Agent Preset"),w("/preset [\u5E8F\u53F7\u6216\u5B8C\u6574ID] \u67E5\u770B\u6216\u8BBE\u7F6E\u5F53\u524D\u673A\u5668\u4EBA Agent Preset"),w("\u7EAF\u6570\u5B57 ID\uFF1A/preset id:"),w("/preset --default \u8DDF\u968F Host \u9ED8\u8BA4"),w("/stop \u505C\u6B62\u5F53\u524D\u4EFB\u52A1"),w("/steer \u8865\u5145\u6307\u4EE4 \u7EA0\u504F\u5F53\u524D\u4EFB\u52A1"),w("/batch \u5F00\u59CB\u6279\u91CF\u8F93\u5165\uFF08\u4EC5\u79C1\u804A\uFF0C\u6700\u591A 10 \u6761\u6587\u5B57\uFF09"),w("/send \u63D0\u4EA4\u5F53\u524D\u6279\u6B21"),w("/cancel \u53D6\u6D88\u5F53\u524D\u6279\u6B21"),w("/status \u68C0\u67E5\u8FDE\u63A5\u72B6\u6001"),w("/version \u67E5\u770B\u63D2\u4EF6\u7248\u672C"),w("/help \u663E\u793A\u672C\u5E2E\u52A9")].join(` `)}var PFe=18e3,OZ=5*1024*1024,_Z=4;function ma(n){return typeof n=="string"&&n.trim()?n.trim():null}function ws(n){return n?.body&&typeof n.body=="object"?n.body:{}}function bZ(n){let t=ws(n);return t.chattype==="group"?`group:${t.chatid}`:`direct:${t.from?.userid}`}function vG(n){let t=ws(n),o="";return t.msgtype==="text"?o=typeof t.text?.content=="string"?t.text.content.trim():"":t.msgtype==="voice"?o=typeof t.voice?.content=="string"?t.voice.content.trim():"":t.msgtype==="mixed"&&Array.isArray(t.mixed?.msg_item)&&(o=t.mixed.msg_item.filter(i=>i?.msgtype==="text"&&typeof i.text?.content=="string").map(i=>i.text.content).join(` diff --git a/plugin-src/client/context-enhancement.js b/plugin-src/client/context-enhancement.js index 55790a8..9d9876f 100644 --- a/plugin-src/client/context-enhancement.js +++ b/plugin-src/client/context-enhancement.js @@ -16,15 +16,28 @@ const FIELD_LABELS = Object.freeze({ conversationType: '会话类型', senderId: '发送者标识', senderName: '发送者昵称', + conversationTitle: '会话标题', botId: '机器人标识', }); +const FIELD_HELP = Object.freeze({ + senderName: Object.freeze({ + labelKey: 'senderNameHelpLabel', + text: '该字段不是每个渠道都能提供。当前消息没有发送者昵称时,即使已选择该字段, 中也会省略 senderName。', + }), + conversationTitle: Object.freeze({ + labelKey: 'conversationTitleHelpLabel', + text: '该字段不是每个渠道都能提供。钉钉群聊会带上群名。当前消息没有会话标题时,即使已选择该字段, 中也会省略 conversationTitle。', + }), +}); + const SCOPE_COPY = Object.freeze({ group: Object.freeze({ title: '群聊', enable: '启用', fieldsHelpLabel: '查看群聊来源字段说明', senderNameHelpLabel: '查看群聊发送者昵称字段说明', + conversationTitleHelpLabel: '查看群聊会话标题字段说明', guidanceLabel: '增强提示词', guidanceHelpLabel: '查看群聊增强提示词使用说明', guidanceUsage: '用于告诉模型如何使用当前群聊消息的 来源字段。只填写正文,插件会自动添加 成对标签。', @@ -35,6 +48,7 @@ const SCOPE_COPY = Object.freeze({ enable: '启用', fieldsHelpLabel: '查看私聊来源字段说明', senderNameHelpLabel: '查看私聊发送者昵称字段说明', + conversationTitleHelpLabel: '查看私聊会话标题字段说明', guidanceLabel: '增强提示词', guidanceHelpLabel: '查看私聊增强提示词使用说明', guidanceUsage: '用于告诉模型如何使用当前私聊消息的 来源字段。只填写正文,插件会自动添加 成对标签。', @@ -73,7 +87,6 @@ function ContextEnhancementScopeEditor({ const copy = SCOPE_COPY[kind]; const unavailableId = `${idPrefix}-${kind}-unavailable`; const fieldsHelpId = `${idPrefix}-${kind}-fields-help`; - const senderNameHelpId = `${idPrefix}-${kind}-sender-name-help`; const guidanceId = `${idPrefix}-${kind}-guidance`; const guidanceHelpId = `${idPrefix}-${kind}-guidance-help`; const disabled = busy || !supported; @@ -118,16 +131,17 @@ function ContextEnhancementScopeEditor({ }), h('span', { className: 'dim-contextFieldText' }, h('label', { className: 'dim-contextFieldName', htmlFor: fieldId }, FIELD_LABELS[field]), - field === 'senderName' ? h('span', { className: 'dim-contextHelp dim-contextFieldHelp' }, + FIELD_HELP[field] ? h('span', { className: 'dim-contextHelp dim-contextFieldHelp' }, h('button', { type: 'button', className: 'dim-contextHelpButton dim-contextFieldHelpButton', disabled, - 'aria-label': copy.senderNameHelpLabel, 'aria-describedby': senderNameHelpId, + 'aria-label': copy[FIELD_HELP[field].labelKey], + 'aria-describedby': `${idPrefix}-${kind}-${field}-help`, }, h('span', { 'aria-hidden': 'true' }, '?')), h('span', { - id: senderNameHelpId, + id: `${idPrefix}-${kind}-${field}-help`, className: 'dim-contextTooltip dim-contextFieldTooltip', role: 'tooltip', - }, '该字段不是每个渠道都能提供。当前消息没有发送者昵称时,即使已选择该字段, 中也会省略 senderName。')) : null, + }, FIELD_HELP[field].text)) : null, h('label', { className: 'dim-contextFieldKey', htmlFor: fieldId }, field))); }))), h('div', { className: 'dim-contextGuidance dim-contextScopeBlock' }, diff --git a/plugin-src/client/i18n.js b/plugin-src/client/i18n.js index 686c844..ee50cda 100644 --- a/plugin-src/client/i18n.js +++ b/plugin-src/client/i18n.js @@ -288,6 +288,10 @@ const EN = Object.freeze({ '查看群聊发送者昵称字段说明': 'View group sender name field details', '查看私聊发送者昵称字段说明': 'View direct sender name field details', '该字段不是每个渠道都能提供。当前消息没有发送者昵称时,即使已选择该字段, 中也会省略 senderName。': 'This field is not available on every channel. If the current message has no sender name, omits senderName even when the field is selected.', + '会话标题': 'Conversation title', + '查看群聊会话标题字段说明': 'View group conversation title field details', + '查看私聊会话标题字段说明': 'View direct conversation title field details', + '该字段不是每个渠道都能提供。钉钉群聊会带上群名。当前消息没有会话标题时,即使已选择该字段, 中也会省略 conversationTitle。': '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.', '机器人标识': 'Bot ID', '增强提示词': 'Guidance', '查看增强提示词使用说明': 'View guidance instructions', @@ -315,7 +319,7 @@ const EN = Object.freeze({ '上下文增强保存失败,请重试。': 'Could not save context enhancement. Try again.', '请提交完整的上下文增强设置。': 'Submit the complete context enhancement settings.', '群聊和私聊开关必须是布尔值。': 'Group and direct switches must be booleans.', - '来源字段只能选择已定义的五个字段。': 'Source fields must be chosen from the five defined fields.', + '来源字段只能选择已定义的六个字段。': 'Source fields must be chosen from the six defined fields.', '保存中…': 'Saving…', '未设置': 'Not set', '工作区修改失败,请重试。': 'Could not update the workspace. Try again.', diff --git a/src/channels/dingtalk/dingtalk-bridge.mjs b/src/channels/dingtalk/dingtalk-bridge.mjs index a9fcd6f..767729f 100644 --- a/src/channels/dingtalk/dingtalk-bridge.mjs +++ b/src/channels/dingtalk/dingtalk-bridge.mjs @@ -1001,6 +1001,7 @@ export class DingtalkHarnessBridge { channel: 'dingtalk', senderId: sender, senderName: message.senderNick, + conversationTitle: message.conversationTitle, })); } if (typeof this.#api.createAiCard === 'function' diff --git a/src/channels/shared/context-enhancement.mjs b/src/channels/shared/context-enhancement.mjs index 5c26d1b..26c69fd 100644 --- a/src/channels/shared/context-enhancement.mjs +++ b/src/channels/shared/context-enhancement.mjs @@ -1,6 +1,6 @@ // Shared by the Host and settings UI; keep this module browser-compatible. export const CONTEXT_ENHANCEMENT_FIELDS = Object.freeze([ - 'channel', 'conversationType', 'senderId', 'senderName', 'botId', + 'channel', 'conversationType', 'senderId', 'senderName', 'conversationTitle', 'botId', ]); export const CONTEXT_ENHANCEMENT_GUIDANCE_MAX_LENGTH = 8_000; @@ -36,7 +36,10 @@ const CHANNELS = new Set([ 'wecom', 'weixin', 'feishu', 'dingtalk', 'qq', 'slack', 'telegram', 'discord', 'whatsapp', ]); -const SOURCE_LIMITS = { channel: 16, conversationType: 6, senderId: 256, senderName: 256, botId: 128 }; +const SOURCE_LIMITS = { + channel: 16, conversationType: 6, senderId: 256, senderName: 256, + conversationTitle: 256, botId: 128, +}; const CONTROL_CHARACTERS = /[\u0000-\u001f\u007f-\u009f\u202a-\u202e\u2066-\u2069]/g; function invalidConfig(message) { @@ -61,7 +64,7 @@ function validateContextEnhancementScope(input) { throw invalidConfig('群聊和私聊开关必须是布尔值。'); } if (!Array.isArray(fields) || ![...fields].every((field) => CONTEXT_ENHANCEMENT_FIELDS.includes(field))) { - throw invalidConfig('来源字段只能选择已定义的五个字段。'); + throw invalidConfig('来源字段只能选择已定义的六个字段。'); } if (typeof guidance !== 'string' || guidance.length > CONTEXT_ENHANCEMENT_GUIDANCE_MAX_LENGTH) { throw invalidConfig(`增强提示词不得超过 ${CONTEXT_ENHANCEMENT_GUIDANCE_MAX_LENGTH} 个字符。`); @@ -146,7 +149,9 @@ function sourceString(value, field) { function sourceBlock(snapshot, sourceFactory) { const { fields } = snapshot.config; - const needsSource = fields.some((field) => ['channel', 'senderId', 'senderName'].includes(field)); + const needsSource = fields.some((field) => [ + 'channel', 'senderId', 'senderName', 'conversationTitle', + ].includes(field)); const source = needsSource ? sourceFactory?.() : null; const projected = {}; for (const field of fields) { diff --git a/src/channels/shared/text-harness-bridge.mjs b/src/channels/shared/text-harness-bridge.mjs index 08277fc..19a8d29 100644 --- a/src/channels/shared/text-harness-bridge.mjs +++ b/src/channels/shared/text-harness-bridge.mjs @@ -678,6 +678,7 @@ export class TextHarnessBridge { channel: this.#descriptor.key, senderId, senderName: message.contextSource?.()?.senderName, + conversationTitle: message.contextSource?.()?.conversationTitle, })); } const { answer, artifacts = [] } = await askInWorkspaceSession({ diff --git a/src/channels/telegram/telegram-runtime.mjs b/src/channels/telegram/telegram-runtime.mjs index 0942747..5c1e873 100644 --- a/src/channels/telegram/telegram-runtime.mjs +++ b/src/channels/telegram/telegram-runtime.mjs @@ -166,6 +166,7 @@ export function normalizeTelegramUpdate(update, { senderName: [message.from?.first_name, message.from?.last_name] .filter((value) => typeof value === 'string' && value.trim()) .map((value) => value.trim()).join(' ') || message.from?.username, + conversationTitle: direct ? undefined : message.chat?.title, }), senderIsBot: message.from?.is_bot === true, kind: direct ? 'direct' : 'group', diff --git a/test/channels/shared/context-enhancement-bridges.test.mjs b/test/channels/shared/context-enhancement-bridges.test.mjs index 6076050..22c0b95 100644 --- a/test/channels/shared/context-enhancement-bridges.test.mjs +++ b/test/channels/shared/context-enhancement-bridges.test.mjs @@ -177,7 +177,8 @@ function fixture(channel, { contextEnhancement, onAsk } = {}) { const from = { id: actor === 'actor' ? 42 : 43, is_bot: false }; nameValue(from, 'first_name'); value = normalizeTelegramUpdate({ update_id: id, message: { - message_id: id, chat: { id: 100, type: group ? 'supergroup' : 'private' }, from, + message_id: id, chat: { id: 100, type: group ? 'supergroup' : 'private', + ...(group ? { title: 'Telegram群' } : {}) }, from, text: group ? `@testbot ${text}` : text, entities: group ? [{ type: 'mention', offset: 0, length: 8 }] : [], } }, { botId: 'bot', username: 'testbot' }); } else if (channel === 'discord') { @@ -206,7 +207,8 @@ function fixture(channel, { contextEnhancement, onAsk } = {}) { item_list: [{ type: 1, text_item: { text } }] }; } else if (channel === 'dingtalk') { value = { msgId: String(id), msgtype: 'text', text: { content: text }, senderStaffId: actor, - conversationType: group ? '2' : '1', conversationId: 'chat', isInAtList: true, + conversationType: group ? '2' : '1', conversationId: 'chat', + conversationTitle: group ? '钉钉测试群' : undefined, isInAtList: true, sessionWebhook: 'https://oapi.dingtalk.com/robot/reply?ticket=test' }; nameValue(value, 'senderNick'); } else if (channel === 'qq') { @@ -299,6 +301,8 @@ for (const channel of CHANNELS) { senderId: channel === 'telegram' ? '42' : channel === 'whatsapp' ? 'actor@s.whatsapp.net' : 'actor', ...(['dingtalk', 'telegram', 'discord', 'whatsapp'].includes(channel) || (channel === 'qq' && kind === 'group') ? { senderName: 'Ada' } : {}), + ...(channel === 'dingtalk' && kind === 'group' ? { conversationTitle: '钉钉测试群' } : {}), + ...(channel === 'telegram' && kind === 'group' ? { conversationTitle: 'Telegram群' } : {}), botId: `${channel}_internal`, }; assert.deepEqual(sourceOf(current.prompts[0]), expected); diff --git a/test/context-enhancement-ui.test.mjs b/test/context-enhancement-ui.test.mjs index 84014c4..1a7eba7 100644 --- a/test/context-enhancement-ui.test.mjs +++ b/test/context-enhancement-ui.test.mjs @@ -217,6 +217,11 @@ test('context settings default to off with sender ID and empty guidance, and exp assert.equal(senderNameHelp.parent.props.className, 'dim-contextHelp dim-contextFieldHelp'); assert.equal(senderNameHelp.parent.parent.props.className, 'dim-contextFieldText'); assert.match(textOf(senderNameTooltip), /不是每个渠道.*dsh_im_source.*省略 senderName/s); + const conversationTitleHelp = renderer.root.findByProps({ 'aria-label': '查看群聊会话标题字段说明' }); + const conversationTitleTooltip = renderer.root.findByProps({ id: conversationTitleHelp.props['aria-describedby'] }); + assert.equal(conversationTitleHelp.props.type, 'button'); + assert.equal(conversationTitleHelp.parent.props.className, 'dim-contextHelp dim-contextFieldHelp'); + assert.match(textOf(conversationTitleTooltip), /不是每个渠道.*dsh_im_source.*省略 conversationTitle/s); assert.deepEqual(saved, []); }); diff --git a/test/context-enhancement.test.mjs b/test/context-enhancement.test.mjs index 2d5c287..781b984 100644 --- a/test/context-enhancement.test.mjs +++ b/test/context-enhancement.test.mjs @@ -185,16 +185,16 @@ test('group and direct messages use only their own fields and guidance', () => { assert.doesNotMatch(direct, /GROUP-ONLY-TOKEN|channel/); }); -test('all 32 source-field subsets are projected in canonical order with no hidden fields', () => { +test('all 64 source-field subsets are projected in canonical order with no hidden fields', () => { const expected = { channel: 'telegram', conversationType: 'group', - senderId: '123', senderName: '张三', botId: 'bot_one', + senderId: '123', senderName: '张三', conversationTitle: '测试群', botId: 'bot_one', }; - for (let mask = 0; mask < 32; mask += 1) { + for (let mask = 0; mask < 64; mask += 1) { const fields = CONTEXT_ENHANCEMENT_FIELDS.filter((_field, index) => mask & (1 << index)); const selected = snapshot(config({ fields: [...fields].reverse() })); const actual = enhanceContextContent(' original\n', selected, () => ({ - channel: 'telegram', senderId: 123, senderName: '张三', + channel: 'telegram', senderId: 123, senderName: '张三', conversationTitle: '测试群', botId: 'platform-secret-not-used', conversationType: 'direct', token: 'never-sent', })); if (fields.length === 0) {