@ycodium-ai/plugin-im 0.2.3236 → 0.2.3238

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -30,12 +30,17 @@ they pick their own project:
30
30
  saved as secrets and the scanner as the only allowed person: no draft, no Save. It relies on
31
31
  non-public console interfaces and may break; the inline panel then shows the step list with the
32
32
  failed step marked. See `src/lark/setup/`.
33
- - **Access mode** (per bot): `allowlist` (default) or `open`. `allowlist` admits only
34
- the people on the allow list; `open` admits any sender the platform can identify.
33
+ - **Access mode** (per bot): `allowlist` (default), `open`, `privateOpen` or `groupOpen`.
34
+ `allowlist` admits only the people on the allow list; `open` admits any sender the
35
+ platform can identify.
36
+ `privateOpen` opens private chats and requires the allowlist in groups; `groupOpen`
37
+ opens groups and requires the allowlist in private chats. Both use the same list.
38
+ Either mixed mode requires the allowlist when the chat type is unknown.
35
39
  New bots start on `allowlist`.
36
40
  - **Allowed people** is an allow-list of that platform's user ids (shown when the
37
- mode is allowlist). Empty means nobody can make the agent work. Someone who is
38
- not admitted gets one reply with their own user id and where to put it, at most
41
+ mode requires the allowlist for either chat type). Empty blocks everyone in chats
42
+ that require the allowlist. Someone who is not admitted gets one reply with their
43
+ own user id and where to put it, at most
39
44
  once every ten minutes per person (the table of who was told is bounded in memory).
40
45
  In `open` mode any identifiable sender is admitted; the deny hint still applies
41
46
  when the platform reports no sender id.
package/assets/ui.js CHANGED
@@ -1,8 +1,8 @@
1
- var Kn=window.__ycodiumPluginHost.react;var{Activity:Xn,Children:Zn,Component:et,Fragment:Be,Profiler:nt,PureComponent:tt,StrictMode:it,Suspense:ot,__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE:rt,__COMPILER_RUNTIME:at,act:lt,cache:st,cacheSignal:dt,captureOwnerStack:ct,cloneElement:ut,createContext:te,createElement:xe,createRef:mt,forwardRef:gt,isValidElement:yt,lazy:ft,memo:pt,startTransition:bt,unstable_useCacheRefresh:vt,use:ie,useActionState:St,useCallback:It,useContext:wt,useDebugValue:Ct,useDeferredValue:ht,useEffect:Le,useEffectEvent:xt,useId:Rt,useImperativeHandle:kt,useInsertionEffect:Nt,useLayoutEffect:Tt,useMemo:M,useOptimistic:_t,useReducer:Pt,useRef:A,useState:R,useSyncExternalStore:Et,useTransition:At,version:Ot}=Kn;var O=(e,n)=>{let t=e[n];return typeof t=="string"?t.trim():""};var C="/developers/v1",Mt={uploadImage:`${C}/app/upload/image`,createFromTemplate:`${C}/manifest/upsert_by_template`,createBare:`${C}/app/create`,listApps:`${C}/app/list`,robotSwitch:e=>`${C}/robot/switch/${e}`,eventSwitch:e=>`${C}/event/switch/${e}`,eventRead:e=>`${C}/event/${e}`,eventUpdate:e=>`${C}/event/update/${e}`,callbackSwitch:e=>`${C}/callback/switch/${e}`,callbackRead:e=>`${C}/callback/${e}`,callbackUpdate:e=>`${C}/callback/update/${e}`,scopeCatalog:e=>`${C}/scope/all/${e}`,scopeUpdate:e=>`${C}/scope/update/${e}`,safeSetting:e=>`${C}/safe_setting/update/${e}`,visibleOnline:e=>`${C}/visible/online/${e}`,versionList:e=>`${C}/app_version/list/${e}`,versionCreate:e=>`${C}/app_version/create/${e}`,publishCommit:(e,n)=>`${C}/publish/commit/${e}/${n}`,secret:e=>`${C}/secret/${e}`};var Kt=10*6e4;var Me=9e4;var Ke="settings.view",Fe="settings.connections",Ve="settings.saveBot",De="settings.removeBot",Ue="settings.saveGeneral",$e="settings.saveTarget",Ge="settings.removeTarget",He="larkSetup.session",ze="wecomSetup.session",K={labelKey:"setup.action.label",descriptionKey:"setup.action.description",badgeKey:"setup.action.badge",warningKey:"setup.action.warning"},Qe={checkConnection:"im.settings.checkConnection",reconnect:"im.settings.reconnect",resetInbox:"im.settings.resetInbox",copyDiagnostics:"im.settings.copyDiagnostics",larkRepair:"im.settings.larkRepair",larkCallbackProbe:"im.settings.larkCallbackProbe"},We=e=>e==="telegram"?["rowAction.resetInbox.telegramOffline"]:[],je=[{id:"checkConnection",labelKey:"rowAction.checkConnection.label",descriptionKey:"rowAction.checkConnection.description"},{id:"reconnect",labelKey:"rowAction.reconnect.label",descriptionKey:"rowAction.reconnect.description"},{id:"resetInbox",labelKey:"rowAction.resetInbox.label",descriptionKey:"rowAction.resetInbox.description"},{id:"copyDiagnostics",labelKey:"rowAction.copyDiagnostics.label",descriptionKey:"rowAction.copyDiagnostics.description"},{id:"larkRepair",labelKey:"rowAction.larkRepair.label",descriptionKey:"rowAction.larkRepair.description",platform:"lark"},{id:"larkCallbackProbe",labelKey:"rowAction.larkCallbackProbe.label",descriptionKey:"rowAction.larkCallbackProbe.description",descriptionParams:{seconds:Me/1e3},platform:"lark"}],Fn="lark",oe=[{value:"zh-CN",labelKey:"settings.language.zhCN"},{value:"en",labelKey:"settings.language.en"}],Vn="botId",re=e=>O(e,"platform")||Fn,qe=(e,n)=>{let t=e.showWhen;if(t===void 0)return!0;let o=t.key==="platform"?re(n):O(n,t.key);return t.equals.includes(o)},Ye=(e,n,t)=>e.map(o=>o.key===Vn?{...o,kind:"select",options:n.map(l=>({value:l.rowId,label:`${O(l.values,"displayName")||t(l.platform)} (${l.rowId})`}))}:o),Je=(e,n)=>{switch(n.kind){case"qr":{let{expired:t,...o}=e,l=n.expiresAt===void 0?{payload:n.payload}:{payload:n.payload,expiresAt:n.expiresAt};return{...o,qr:l}}case"status":{let t=n.params===void 0?{statusKey:n.statusKey}:{statusKey:n.statusKey,params:n.params};if(n.expired!==!0)return{...e,status:t};let{qr:o,...l}=e;return{...l,status:t,expired:!0}}case"steps":return{...e,steps:n.steps};case"done":case"failed":{let{status:t,...o}=e;return{...o,result:n}}}},Re=e=>e==="inboxUnreadable"?"settingsSection.connection.reason.inbox-unreadable":e==="notAvailable"?"settingsSection.connection.reason.not-available":`rowAction.checkConnection.hint.${e}`,q=e=>e.reason==="not-available"||e.hint==="notAvailable",ae=e=>e?.state==="failed"&&(e.reason==="inbox-unreadable"||e.hint==="inboxUnreadable"),Xe=e=>e.hint==="wecomBotCredentials"||e.hint==="unauthorized"||e.hint==="larkCredentials"||e.hint==="wecomLongConnOff"||e.hint==="wecomTakenOver",F=e=>e.state==="duplicate"||q(e)||e.hint==="connecting"||e.hint==="wecomCallbackNotSeen"?"warning":"error";var Ze=e=>{if(!e||typeof e!="object"||Array.isArray(e)||!("code"in e)||typeof e.code!="string"||!e.code.trim()||!("reason"in e)||typeof e.reason!="string"||!e.reason.trim()||!("message"in e)||typeof e.message!="string"||!e.message.trim()||!("referenceId"in e)||typeof e.referenceId!="string"||!e.referenceId.trim()||!("at"in e)||typeof e.at!="number"||!Number.isFinite(e.at))return null;let n="messageKey"in e?e.messageKey:void 0;if(n!==void 0&&(typeof n!="string"||!n.trim()))return null;let t="messageParams"in e?e.messageParams:void 0,o;if(t!==void 0){if(!t||typeof t!="object"||Array.isArray(t)||!("detail"in t)||typeof t.detail!="string")return null;o={detail:t.detail.slice(0,500)}}return{code:e.code.slice(0,64),reason:e.reason.slice(0,64),message:e.message.slice(0,500),...n!==void 0?{messageKey:n.slice(0,128)}:{},...o===void 0?{}:{messageParams:o},referenceId:e.referenceId.slice(0,40),at:e.at}},en=e=>!e||typeof e!="object"||Array.isArray(e)?Ze(e):Ze(Object.fromEntries(Object.entries(e).map(([n,t])=>[n,typeof t=="string"?t.trim():t])));var nn=(e,n)=>{let t=e.filter(o=>o.configured);return{configured:t.length,connected:t.filter(o=>n?.[o.rowId]?.state==="connected").length}},tn=e=>{if(e.error!==null||e.isUnavailable||typeof e.data!="object"||e.data===null||Array.isArray(e.data))return null;let n=e.data;return Object.values(n).some(t=>"lastMessageError"in t||"statusSince"in t)?Object.fromEntries(Object.entries(n).map(([t,o])=>{let{lastMessageError:l,statusSince:r,...a}=o,d=en(l);return[t,{...a,...typeof r=="number"&&Number.isSafeInteger(r)&&r>=0&&r<=864e13?{statusSince:r}:{},...d===null?{}:{lastMessageError:d}}]})):n},ke=e=>e===null||!e.configured?{key:"settingsSection.status.incomplete",tone:"attention"}:{key:"settingsSection.status.ready",tone:"success"},on=(e,n)=>{if(e===null||!e.configured)return ke(e);let t=n?.[e.rowId];switch(t?.state){case"connecting":return{key:"settingsSection.status.connecting",tone:"working"};case"connected":return{key:"settingsSection.status.connected",tone:"success"};case"failed":case"duplicate":return{key:"settingsSection.status.notConnected",tone:F(t)};default:return{key:"settingsSection.status.ready",tone:"neutral"}}},rn=(e,n,t,o)=>{if(e===null||!e.configured)return null;let l=n?.[e.rowId];return l?.state==="failed"?ae(l)?{text:o(Re("inboxUnreadable")),variant:F(l)}:{text:[o(l.reason===void 0?"settingsSection.connection.failed":`settingsSection.connection.reason.${l.reason}`),l.hint===void 0?null:o(Re(l.hint)),q(l)||Xe(l)?null:o("settingsSection.connection.reconnect"),l.error===void 0?null:o("settingsSection.connection.details",{error:l.error})].filter(a=>a!==null).join(" "),variant:F(l)}:l?.state==="duplicate"?{text:o("settingsSection.connection.duplicate",{name:t??l.duplicateOf??""}),variant:F(l)}:null};var{jsx:i,jsxs:s,Fragment:N}=window.__ycodiumPluginHost.jsxRuntime;function an(e){let n=e.bridge.useFormatTimestamp();if(e.since===void 0)return null;let t=new Date(e.since).toISOString();return i("time",{className:"im-small im-muted",dateTime:t,children:e.t("settingsSection.connection.since",{time:n(t)})})}var ln=te(null);function sn(e){return i(ln,{value:e.bridge,children:e.children})}var Dn=new Set(["Collapsible","CollapsiblePanel","CollapsibleTrigger"]);function S(e){let n=t=>{let r=ie(ln)?.ui?.[e];return r===void 0?Dn.has(e)?xe("div",{className:t.className},t.children):null:xe(r,t)};return n.displayName=e,n}var p=S("Button"),$=S("Input"),G=S("Label"),dn=S("Switch"),le=S("Select"),se=S("SelectTrigger"),Y=S("SelectValue"),de=S("SelectPopup"),ce=S("SelectItem"),ue=S("StatusPill"),cn=S("PluginIcon"),un=S("EmptyInline"),H=S("Alert"),mn=S("AlertAction"),z=S("AlertDescription"),gn=S("Collapsible"),yn=S("CollapsibleTrigger"),fn=S("CollapsiblePanel"),V=S("Spinner"),pn=S("QRCodeSvg"),bn=S("ProxyChoiceSelect");var vn=(e,n)=>{if(e.kind==="done")return{headline:e.messageKey===void 0?n("settingsSection.action.done"):n(e.messageKey),tone:e.tone??"done",link:e.link===void 0?void 0:{url:e.link.url,label:n(e.link.labelKey)},note:void 0,headlineTone:e.tone??"done",details:(e.warnings??[]).map(d=>n(d.key,d.params))};let t=e.params?.ref,o=t===void 0?e.detail:n("rowAction.diagnostic.ref",{ref:t,detail:e.detail??""}).trimEnd(),l=e.params?.hint?.toString(),r=e.noteKey===void 0?void 0:n(e.noteKey),a=F({hint:l})==="warning"?"caution":"issue";return{headline:n(e.reasonKey,e.params),link:void 0,note:r,tone:a,headlineTone:r===void 0?a:"neutral",details:[...o===void 0?[]:[o],...(e.warnings??[]).map(d=>n(d.key,d.params))]}};var Sn=(e,n,t,o)=>{let l=o?.state==="failed"&&q(o),r=ae(o);return{actions:je.filter(a=>(a.platform===void 0||a.platform===e)&&(a.id!=="resetInbox"||r)).map(a=>({...a,descriptionKeys:[a.descriptionKey,...a.id==="resetInbox"?We(e):[]],disabled:n||t||a.id==="reconnect"&&l})),noteKey:n?"settingsSection.action.saveFirst":l?"rowAction.reconnect.notAvailable":null}},me=e=>typeof e=="object"&&e!==null&&!Array.isArray(e),In=e=>me(e)&&Array.isArray(e.bots)&&Array.isArray(e.targets)&&me(e.delivery),wn=e=>me(e)&&In(e.view)&&Array.isArray(e.columns)&&Array.isArray(e.targetColumns)&&Array.isArray(e.proxies)?e:null,J=async(e,n,t,o)=>{try{let l=await e.commands.invoke(n,t,o);return me(l)&&l.ok===!0&&In(l.view)?l.view:null}catch{return null}},Cn=(e,n)=>n.isPending?e.phase==="asked"?{...e,phase:"refetching"}:e:n.view!==null&&!n.failed?e.phase==="refetching"||JSON.stringify(n.view)===JSON.stringify(e.view)?null:e:e.phase==="asked"?e:{...e,phase:"asked"},E=e=>e==null||e.length===0?{}:{environmentId:e},X=(e,n)=>n===null?e:`${e}:${n}`,Ne=e=>JSON.stringify([e.replyLanguage,e.delivery]);function Q(e,n,t){if(n!==void 0&&n.length>0)return e(n);if(t!==void 0&&t.length>0)return t}function hn(e,n){return n.length===0?null:n.map(t=>e(t==="required"?"settingsSection.issue.required":"settingsSection.issue.format")).join(" ")}function D(e,n,t){return`im-${(e??"here").replace(/[^A-Za-z0-9_-]/g,"")}-${n}-${t}`}function Z(e,n,t){let o=[n?`${e}-issue`:null,t?`${e}-hint`:null].filter(l=>l!==null);return o.length===0?void 0:o.join(" ")}function B(e){return s("div",{className:e.span===!0?"im-field im-span":"im-field",children:[i(G,{htmlFor:e.id,children:e.label}),e.children,e.issue?i("p",{id:`${e.id}-issue`,className:"im-small im-issue",role:"alert",children:e.issue}):null,e.description===void 0?null:i("p",{id:`${e.id}-hint`,className:"im-hint im-small im-muted",children:e.description})]})}function ge(e){let n=e.stored&&e.value===""&&!e.clearing?e.savedPlaceholder:e.placeholder;return s("div",{className:"im-secret",children:[i($,{id:e.id,type:"password",value:e.value,placeholder:n,disabled:e.disabled,autoComplete:"new-password","aria-invalid":e.invalid?!0:void 0,"aria-describedby":e.describedBy,onChange:t=>e.onChange(t.target.value)}),e.stored?i(p,{variant:"ghost",size:"sm","aria-pressed":e.clearing,disabled:e.disabled,onClick:e.onToggleClear,children:e.clearing?e.undoLabel:e.clearLabel}):null]})}function ye(e){let n=e.saving||e.busy===!0;return!e.dirty&&!e.saving&&!e.failed?null:s("div",{className:"im-span",children:[e.dirty||e.saving?s("div",{className:"im-actions",children:[s(p,{variant:e.solid?"default":"outline",disabled:n||!e.dirty,onClick:e.onSave,children:[e.saving?i(V,{}):null,e.saveLabel]}),e.dirty&&!n?i(p,{variant:"ghost",size:"sm",onClick:e.onRevert,children:e.revertLabel}):null]}):null,e.failed?i("p",{className:"im-small im-issue",role:"alert",children:e.failedLabel}):null]})}async function fe(e,n,t){try{await e.writeClipboard(n),e.notify(t("settingsSection.copied"),"success")}catch{e.notify(t("settingsSection.copyFailed"),"warning")}}var Un=e=>typeof e=="object"&&e!==null&&!Array.isArray(e);function pe(e){let n=M(()=>E(e.environmentId),[e.environmentId]),t=e.bridge.commands.useSubscription(e.command,e.payload,n),o=M(()=>Un(t.data)?e.items==="snapshots"?t.data:Je({},t.data):{},[t.data,e.items]),l=o.result,r=A(null),a=e.onSettled;Le(()=>{l===void 0||r.current===t.data||(r.current=t.data,a?.(l))},[l,t.data,a]);let d=e.t,m=l===void 0&&t.error===null&&!t.isUnavailable;return s("div",{className:"im-flow im-span",children:[t.isUnavailable||t.error!==null?i(H,{variant:"error",layout:"inline",children:i(z,{children:d("settingsSection.action.failedToRun")})}):null,o.qr===void 0?null:i("div",{className:"im-qr",children:i(pn,{value:o.qr.payload,size:176,marginSize:2,title:d("settingsSection.action.qrTitle")})}),o.status===void 0?null:s("p",{className:"im-inline im-medium",children:[m?i(V,{}):null,i("span",{children:d(o.status.statusKey,o.status.params)})]}),m&&o.status===void 0&&o.qr===void 0?s("p",{className:"im-inline im-medium",children:[i(V,{}),i("span",{children:d("settingsSection.action.running")})]}):null,o.steps===void 0?null:i("ul",{className:"im-steps im-small",children:o.steps.map(y=>s("li",{"data-state":y.state,children:[i("span",{children:d(y.labelKey)}),i("span",{className:"im-muted",children:d(`settingsSection.step.${y.state}`)})]},y.id))}),l===void 0?null:i($n,{result:l,bridge:e.bridge,t:d}),s("div",{className:"im-actions",children:[l?.kind==="failed"||o.expired===!0||t.error!==null?i(p,{variant:"ghost",size:"sm",onClick:t.refresh,children:d("settingsSection.retry")}):null,i(p,{variant:"ghost",size:"sm",onClick:e.onClose,children:d(l===void 0?"settingsSection.cancel":"settingsSection.action.close")})]})]})}var xn=e=>e==="issue"?"im-issue":e==="caution"?"im-caution":"";function $n(e){let{headline:n,headlineTone:t,tone:o,note:l,link:r,details:a}=vn(e.result,e.t),d=e.t;return s("div",{className:"im-result",children:[s("div",{className:"im-result-verdict",role:"status",children:[i("p",{className:`im-medium im-result-headline ${xn(t)}`.trimEnd(),children:n}),l===void 0?null:i("p",{className:`im-small im-result-note ${xn(o)}`.trimEnd(),children:l})]}),r===void 0?null:i("div",{className:"im-actions",children:i(p,{className:"im-link",variant:"link",size:"sm",onClick:()=>e.bridge.openExternal(r.url),children:r.label})}),a.length===0?null:s(N,{children:[i("pre",{className:"im-detail im-small",children:a.join(`
1
+ var Vn=window.__ycodiumPluginHost.react;var{Activity:Zn,Children:et,Component:nt,Fragment:Le,Profiler:tt,PureComponent:it,StrictMode:ot,Suspense:rt,__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE:at,__COMPILER_RUNTIME:lt,act:st,cache:dt,cacheSignal:ct,captureOwnerStack:ut,cloneElement:mt,createContext:ie,createElement:xe,createRef:gt,forwardRef:yt,isValidElement:ft,lazy:pt,memo:vt,startTransition:bt,unstable_useCacheRefresh:St,use:oe,useActionState:It,useCallback:wt,useContext:Ct,useDebugValue:ht,useDeferredValue:xt,useEffect:Me,useEffectEvent:Rt,useId:kt,useImperativeHandle:Tt,useInsertionEffect:Nt,useLayoutEffect:_t,useMemo:M,useOptimistic:Et,useReducer:Pt,useRef:A,useState:R,useSyncExternalStore:At,useTransition:Ot,version:Bt}=Vn;var O=(e,n)=>{let t=e[n];return typeof t=="string"?t.trim():""};var C="/developers/v1",Kt={uploadImage:`${C}/app/upload/image`,createFromTemplate:`${C}/manifest/upsert_by_template`,createBare:`${C}/app/create`,listApps:`${C}/app/list`,robotSwitch:e=>`${C}/robot/switch/${e}`,eventSwitch:e=>`${C}/event/switch/${e}`,eventRead:e=>`${C}/event/${e}`,eventUpdate:e=>`${C}/event/update/${e}`,callbackSwitch:e=>`${C}/callback/switch/${e}`,callbackRead:e=>`${C}/callback/${e}`,callbackUpdate:e=>`${C}/callback/update/${e}`,scopeCatalog:e=>`${C}/scope/all/${e}`,scopeUpdate:e=>`${C}/scope/update/${e}`,safeSetting:e=>`${C}/safe_setting/update/${e}`,visibleOnline:e=>`${C}/visible/online/${e}`,versionList:e=>`${C}/app_version/list/${e}`,versionCreate:e=>`${C}/app_version/create/${e}`,publishCommit:(e,n)=>`${C}/publish/commit/${e}/${n}`,secret:e=>`${C}/secret/${e}`};var Vt=10*6e4;var Ke=9e4;var Ve="settings.view",Fe="settings.connections",De="settings.saveBot",Ue="settings.removeBot",$e="settings.saveGeneral",Ge="settings.saveTarget",He="settings.removeTarget",ze="larkSetup.session",Qe="wecomSetup.session",K={labelKey:"setup.action.label",descriptionKey:"setup.action.description",badgeKey:"setup.action.badge",warningKey:"setup.action.warning"},We={checkConnection:"im.settings.checkConnection",reconnect:"im.settings.reconnect",resetInbox:"im.settings.resetInbox",copyDiagnostics:"im.settings.copyDiagnostics",larkRepair:"im.settings.larkRepair",larkCallbackProbe:"im.settings.larkCallbackProbe"},je=e=>e==="telegram"?["rowAction.resetInbox.telegramOffline"]:[],qe=[{id:"checkConnection",labelKey:"rowAction.checkConnection.label",descriptionKey:"rowAction.checkConnection.description"},{id:"reconnect",labelKey:"rowAction.reconnect.label",descriptionKey:"rowAction.reconnect.description"},{id:"resetInbox",labelKey:"rowAction.resetInbox.label",descriptionKey:"rowAction.resetInbox.description"},{id:"copyDiagnostics",labelKey:"rowAction.copyDiagnostics.label",descriptionKey:"rowAction.copyDiagnostics.description"},{id:"larkRepair",labelKey:"rowAction.larkRepair.label",descriptionKey:"rowAction.larkRepair.description",platform:"lark"},{id:"larkCallbackProbe",labelKey:"rowAction.larkCallbackProbe.label",descriptionKey:"rowAction.larkCallbackProbe.description",descriptionParams:{seconds:Ke/1e3},platform:"lark"}],Fn="lark",re=[{value:"zh-CN",labelKey:"settings.language.zhCN"},{value:"en",labelKey:"settings.language.en"}],Dn="botId",ae=e=>O(e,"platform")||Fn,Ye=(e,n)=>{let t=e.showWhen;if(t===void 0)return!0;let o=t.key==="platform"?ae(n):O(n,t.key);return t.equals.includes(o)},Je=(e,n,t)=>e.map(o=>o.key===Dn?{...o,kind:"select",options:n.map(l=>({value:l.rowId,label:`${O(l.values,"displayName")||t(l.platform)} (${l.rowId})`}))}:o),Xe=(e,n)=>{switch(n.kind){case"qr":{let{expired:t,...o}=e,l=n.expiresAt===void 0?{payload:n.payload}:{payload:n.payload,expiresAt:n.expiresAt};return{...o,qr:l}}case"status":{let t=n.params===void 0?{statusKey:n.statusKey}:{statusKey:n.statusKey,params:n.params};if(n.expired!==!0)return{...e,status:t};let{qr:o,...l}=e;return{...l,status:t,expired:!0}}case"steps":return{...e,steps:n.steps};case"done":case"failed":{let{status:t,...o}=e;return{...o,result:n}}}},Re=e=>e==="inboxUnreadable"?"settingsSection.connection.reason.inbox-unreadable":e==="notAvailable"?"settingsSection.connection.reason.not-available":`rowAction.checkConnection.hint.${e}`,q=e=>e.reason==="not-available"||e.hint==="notAvailable",le=e=>e?.state==="failed"&&(e.reason==="inbox-unreadable"||e.hint==="inboxUnreadable"),Ze=e=>e.hint==="wecomBotCredentials"||e.hint==="unauthorized"||e.hint==="larkCredentials"||e.hint==="wecomLongConnOff"||e.hint==="wecomTakenOver",V=e=>e.state==="duplicate"||q(e)||e.hint==="connecting"||e.hint==="wecomCallbackNotSeen"?"warning":"error";var en=e=>{if(!e||typeof e!="object"||Array.isArray(e)||!("code"in e)||typeof e.code!="string"||!e.code.trim()||!("reason"in e)||typeof e.reason!="string"||!e.reason.trim()||!("message"in e)||typeof e.message!="string"||!e.message.trim()||!("referenceId"in e)||typeof e.referenceId!="string"||!e.referenceId.trim()||!("at"in e)||typeof e.at!="number"||!Number.isFinite(e.at))return null;let n="messageKey"in e?e.messageKey:void 0;if(n!==void 0&&(typeof n!="string"||!n.trim()))return null;let t="messageParams"in e?e.messageParams:void 0,o;if(t!==void 0){if(!t||typeof t!="object"||Array.isArray(t)||!("detail"in t)||typeof t.detail!="string")return null;o={detail:t.detail.slice(0,500)}}return{code:e.code.slice(0,64),reason:e.reason.slice(0,64),message:e.message.slice(0,500),...n!==void 0?{messageKey:n.slice(0,128)}:{},...o===void 0?{}:{messageParams:o},referenceId:e.referenceId.slice(0,40),at:e.at}},nn=e=>!e||typeof e!="object"||Array.isArray(e)?en(e):en(Object.fromEntries(Object.entries(e).map(([n,t])=>[n,typeof t=="string"?t.trim():t])));var tn=(e,n)=>{let t=e.filter(o=>o.configured);return{configured:t.length,connected:t.filter(o=>n?.[o.rowId]?.state==="connected").length}},on=e=>{if(e.error!==null||e.isUnavailable||typeof e.data!="object"||e.data===null||Array.isArray(e.data))return null;let n=e.data;return Object.values(n).some(t=>"lastMessageError"in t||"statusSince"in t)?Object.fromEntries(Object.entries(n).map(([t,o])=>{let{lastMessageError:l,statusSince:r,...a}=o,d=nn(l);return[t,{...a,...typeof r=="number"&&Number.isSafeInteger(r)&&r>=0&&r<=864e13?{statusSince:r}:{},...d===null?{}:{lastMessageError:d}}]})):n},ke=e=>e===null||!e.configured?{key:"settingsSection.status.incomplete",tone:"attention"}:{key:"settingsSection.status.ready",tone:"success"},rn=(e,n)=>{if(e===null||!e.configured)return ke(e);let t=n?.[e.rowId];switch(t?.state){case"connecting":return{key:"settingsSection.status.connecting",tone:"working"};case"connected":return{key:"settingsSection.status.connected",tone:"success"};case"failed":case"duplicate":return{key:"settingsSection.status.notConnected",tone:V(t)};default:return{key:"settingsSection.status.ready",tone:"neutral"}}},an=(e,n,t,o)=>{if(e===null||!e.configured)return null;let l=n?.[e.rowId];return l?.state==="failed"?le(l)?{text:o(Re("inboxUnreadable")),variant:V(l)}:{text:[o(l.reason===void 0?"settingsSection.connection.failed":`settingsSection.connection.reason.${l.reason}`),l.hint===void 0?null:o(Re(l.hint)),q(l)||Ze(l)?null:o("settingsSection.connection.reconnect"),l.error===void 0?null:o("settingsSection.connection.details",{error:l.error})].filter(a=>a!==null).join(" "),variant:V(l)}:l?.state==="duplicate"?{text:o("settingsSection.connection.duplicate",{name:t??l.duplicateOf??""}),variant:V(l)}:null};var{jsx:i,jsxs:s,Fragment:T}=window.__ycodiumPluginHost.jsxRuntime;function ln(e){let n=e.bridge.useFormatTimestamp();if(e.since===void 0)return null;let t=new Date(e.since).toISOString();return i("time",{className:"im-small im-muted",dateTime:t,children:e.t("settingsSection.connection.since",{time:n(t)})})}var sn=ie(null);function dn(e){return i(sn,{value:e.bridge,children:e.children})}var Un=new Set(["Collapsible","CollapsiblePanel","CollapsibleTrigger"]);function S(e){let n=t=>{let r=oe(sn)?.ui?.[e];return r===void 0?Un.has(e)?xe("div",{className:t.className},t.children):null:xe(r,t)};return n.displayName=e,n}var p=S("Button"),$=S("Input"),G=S("Label"),cn=S("Switch"),se=S("Select"),de=S("SelectTrigger"),Y=S("SelectValue"),ce=S("SelectPopup"),J=S("SelectItem"),ue=S("StatusPill"),un=S("PluginIcon"),mn=S("EmptyInline"),H=S("Alert"),gn=S("AlertAction"),z=S("AlertDescription"),yn=S("Collapsible"),fn=S("CollapsibleTrigger"),pn=S("CollapsiblePanel"),F=S("Spinner"),vn=S("QRCodeSvg"),bn=S("ProxyChoiceSelect");var Sn=(e,n)=>{if(e.kind==="done")return{headline:e.messageKey===void 0?n("settingsSection.action.done"):n(e.messageKey),tone:e.tone??"done",link:e.link===void 0?void 0:{url:e.link.url,label:n(e.link.labelKey)},note:void 0,headlineTone:e.tone??"done",details:(e.warnings??[]).map(d=>n(d.key,d.params))};let t=e.params?.ref,o=t===void 0?e.detail:n("rowAction.diagnostic.ref",{ref:t,detail:e.detail??""}).trimEnd(),l=e.params?.hint?.toString(),r=e.noteKey===void 0?void 0:n(e.noteKey),a=V({hint:l})==="warning"?"caution":"issue";return{headline:n(e.reasonKey,e.params),link:void 0,note:r,tone:a,headlineTone:r===void 0?a:"neutral",details:[...o===void 0?[]:[o],...(e.warnings??[]).map(d=>n(d.key,d.params))]}};var In=(e,n,t,o)=>{let l=o?.state==="failed"&&q(o),r=le(o);return{actions:qe.filter(a=>(a.platform===void 0||a.platform===e)&&(a.id!=="resetInbox"||r)).map(a=>({...a,descriptionKeys:[a.descriptionKey,...a.id==="resetInbox"?je(e):[]],disabled:n||t||a.id==="reconnect"&&l})),noteKey:n?"settingsSection.action.saveFirst":l?"rowAction.reconnect.notAvailable":null}},me=e=>typeof e=="object"&&e!==null&&!Array.isArray(e),wn=e=>me(e)&&Array.isArray(e.bots)&&Array.isArray(e.targets)&&me(e.delivery),Cn=e=>me(e)&&wn(e.view)&&Array.isArray(e.columns)&&Array.isArray(e.targetColumns)&&Array.isArray(e.proxies)?e:null,X=async(e,n,t,o)=>{try{let l=await e.commands.invoke(n,t,o);return me(l)&&l.ok===!0&&wn(l.view)?l.view:null}catch{return null}},hn=(e,n)=>n.isPending?e.phase==="asked"?{...e,phase:"refetching"}:e:n.view!==null&&!n.failed?e.phase==="refetching"||JSON.stringify(n.view)===JSON.stringify(e.view)?null:e:e.phase==="asked"?e:{...e,phase:"asked"},P=e=>e==null||e.length===0?{}:{environmentId:e},Z=(e,n)=>n===null?e:`${e}:${n}`,Te=e=>JSON.stringify([e.replyLanguage,e.delivery]);function Q(e,n,t){if(n!==void 0&&n.length>0)return e(n);if(t!==void 0&&t.length>0)return t}function xn(e,n){return n.length===0?null:n.map(t=>e(t==="required"?"settingsSection.issue.required":"settingsSection.issue.format")).join(" ")}function D(e,n,t){return`im-${(e??"here").replace(/[^A-Za-z0-9_-]/g,"")}-${n}-${t}`}function ee(e,n,t){let o=[n?`${e}-issue`:null,t?`${e}-hint`:null].filter(l=>l!==null);return o.length===0?void 0:o.join(" ")}function B(e){return s("div",{className:e.span===!0?"im-field im-span":"im-field",children:[i(G,{htmlFor:e.id,children:e.label}),e.children,e.issue?i("p",{id:`${e.id}-issue`,className:"im-small im-issue",role:"alert",children:e.issue}):null,e.description===void 0?null:i("p",{id:`${e.id}-hint`,className:"im-hint im-small im-muted",children:e.description})]})}function ge(e){let n=e.stored&&e.value===""&&!e.clearing?e.savedPlaceholder:e.placeholder;return s("div",{className:"im-secret",children:[i($,{id:e.id,type:"password",value:e.value,placeholder:n,disabled:e.disabled,autoComplete:"new-password","aria-invalid":e.invalid?!0:void 0,"aria-describedby":e.describedBy,onChange:t=>e.onChange(t.target.value)}),e.stored?i(p,{variant:"ghost",size:"sm","aria-pressed":e.clearing,disabled:e.disabled,onClick:e.onToggleClear,children:e.clearing?e.undoLabel:e.clearLabel}):null]})}function ye(e){let n=e.saving||e.busy===!0;return!e.dirty&&!e.saving&&!e.failed?null:s("div",{className:"im-span",children:[e.dirty||e.saving?s("div",{className:"im-actions",children:[s(p,{variant:e.solid?"default":"outline",disabled:n||!e.dirty,onClick:e.onSave,children:[e.saving?i(F,{}):null,e.saveLabel]}),e.dirty&&!n?i(p,{variant:"ghost",size:"sm",onClick:e.onRevert,children:e.revertLabel}):null]}):null,e.failed?i("p",{className:"im-small im-issue",role:"alert",children:e.failedLabel}):null]})}async function fe(e,n,t){try{await e.writeClipboard(n),e.notify(t("settingsSection.copied"),"success")}catch{e.notify(t("settingsSection.copyFailed"),"warning")}}var $n=e=>typeof e=="object"&&e!==null&&!Array.isArray(e);function pe(e){let n=M(()=>P(e.environmentId),[e.environmentId]),t=e.bridge.commands.useSubscription(e.command,e.payload,n),o=M(()=>$n(t.data)?e.items==="snapshots"?t.data:Xe({},t.data):{},[t.data,e.items]),l=o.result,r=A(null),a=e.onSettled;Me(()=>{l===void 0||r.current===t.data||(r.current=t.data,a?.(l))},[l,t.data,a]);let d=e.t,u=l===void 0&&t.error===null&&!t.isUnavailable;return s("div",{className:"im-flow im-span",children:[t.isUnavailable||t.error!==null?i(H,{variant:"error",layout:"inline",children:i(z,{children:d("settingsSection.action.failedToRun")})}):null,o.qr===void 0?null:i("div",{className:"im-qr",children:i(vn,{value:o.qr.payload,size:176,marginSize:2,title:d("settingsSection.action.qrTitle")})}),o.status===void 0?null:s("p",{className:"im-inline im-medium",children:[u?i(F,{}):null,i("span",{children:d(o.status.statusKey,o.status.params)})]}),u&&o.status===void 0&&o.qr===void 0?s("p",{className:"im-inline im-medium",children:[i(F,{}),i("span",{children:d("settingsSection.action.running")})]}):null,o.steps===void 0?null:i("ul",{className:"im-steps im-small",children:o.steps.map(g=>s("li",{"data-state":g.state,children:[i("span",{children:d(g.labelKey)}),i("span",{className:"im-muted",children:d(`settingsSection.step.${g.state}`)})]},g.id))}),l===void 0?null:i(Gn,{result:l,bridge:e.bridge,t:d}),s("div",{className:"im-actions",children:[l?.kind==="failed"||o.expired===!0||t.error!==null?i(p,{variant:"ghost",size:"sm",onClick:t.refresh,children:d("settingsSection.retry")}):null,i(p,{variant:"ghost",size:"sm",onClick:e.onClose,children:d(l===void 0?"settingsSection.cancel":"settingsSection.action.close")})]})]})}var Rn=e=>e==="issue"?"im-issue":e==="caution"?"im-caution":"";function Gn(e){let{headline:n,headlineTone:t,tone:o,note:l,link:r,details:a}=Sn(e.result,e.t),d=e.t;return s("div",{className:"im-result",children:[s("div",{className:"im-result-verdict",role:"status",children:[i("p",{className:`im-medium im-result-headline ${Rn(t)}`.trimEnd(),children:n}),l===void 0?null:i("p",{className:`im-small im-result-note ${Rn(o)}`.trimEnd(),children:l})]}),r===void 0?null:i("div",{className:"im-actions",children:i(p,{className:"im-link",variant:"link",size:"sm",onClick:()=>e.bridge.openExternal(r.url),children:r.label})}),a.length===0?null:s(T,{children:[i("pre",{className:"im-detail im-small",children:a.join(`
2
2
 
3
3
  `)}),i("div",{className:"im-actions",children:i(p,{variant:"ghost",size:"sm",onClick:()=>{fe(e.bridge,a.join(`
4
4
 
5
- `),d)},children:d("settingsSection.copy")})})]})]})}function Gn(e){return e.length>12?`${e.slice(0,8)}\u2022\u2022\u2022\u2022${e.slice(-4)}`:"cli_\u2022\u2022\u2022\u2022"}function Rn(e){return e.length<=10?`${e.slice(0,3)}\u2022\u2022\u2022`:`${e.slice(0,6)}\u2022\u2022\u2022\u2022${e.slice(-4)}`}var Hn={lark:{column:"larkAppId",mask:Gn},wecom:{column:"wecomBotId",mask:Rn},"wecom-app":{column:"wecomAppCorpId",mask:Rn}};function kn(e,n){let t=Hn[e];if(t===void 0)return null;let o=O(n,t.column);return o===""?null:t.mask(o)}function Te(e){return s(gn,{className:e.className===void 0?"im-collapse":`im-collapse ${e.className}`,...e.defaultOpen===void 0?{}:{defaultOpen:e.defaultOpen},...e.open===void 0?{}:{open:e.open},...e.onOpenChange===void 0?{}:{onOpenChange:e.onOpenChange},children:[s("div",{className:"im-head",children:[s(yn,{className:"im-toggle",children:[i("span",{className:"im-chevron","aria-hidden":"true"}),e.icon,i("span",{className:"im-title im-medium",children:e.title}),e.meta]}),e.actions]}),e.notice,i(fn,{children:i("div",{className:"im-panel",children:e.children})})]})}function be(e){return i("section",{className:"im-block",children:i(Te,{...e})})}function Nn(e){let n=e.columns.filter(u=>qe(u,e.values)),t=e.groupBotSettings?n.filter(u=>u.group==="essential"):n,o=e.groupBotSettings?n.filter(u=>u.group!=="essential"):[],l=e.issues.filter(u=>o.some(f=>f.key===u.column)),r=JSON.stringify(l),[a,d]=R(()=>({open:l.length>0,issues:r})),m=a.open||a.issues!==r&&l.length>0;a.issues!==r&&d({open:m,issues:r});let y=u=>i(zn,{column:u,scope:e.scope,environmentId:e.environmentId,proxies:e.proxies,values:e.values,secrets:e.secrets,clearSecrets:e.clearSecrets,storedSecrets:e.storedSecrets,issues:e.issues,disabled:e.disabled,t:e.t,onValue:e.onValue,onSecret:e.onSecret,onToggleClear:e.onToggleClear},u.key);return s(N,{children:[t.map(y),e.publicFields.map(u=>i(Wn,{field:u,scope:e.scope,environmentId:e.environmentId,bridge:e.bridge,t:e.t},u.key)),o.length===0?null:i(Te,{className:"im-span",title:l.length>0?e.t("settingsSection.moreSettingsIssues",{count:l.length}):e.t("settingsSection.moreSettings"),open:m,onOpenChange:u=>d({open:u,issues:r}),children:i("div",{className:"im-form",children:o.map(y)})})]})}function zn(e){let n=e.column,t=D(e.environmentId,e.scope,n.key),o=Q(e.t,n.labelKey,n.label)??n.key,l=Q(e.t,n.descriptionKey,n.description),r=Q(e.t,n.placeholderKey,n.placeholder),a=hn(e.t,e.issues.filter(m=>m.column===n.key).map(m=>m.code)),d=Z(t,a!==null,l!==void 0);return n.kind==="password"?i(B,{id:t,label:o,description:l,issue:a,children:i(ge,{id:t,value:e.secrets[n.key]??"",stored:e.storedSecrets[n.key]===!0,clearing:e.clearSecrets.includes(n.key),disabled:e.disabled,invalid:a!==null,describedBy:d,placeholder:r,savedPlaceholder:e.t("settingsSection.secret.saved"),clearLabel:e.t("settingsSection.secret.clear"),undoLabel:e.t("settingsSection.secret.clearUndo"),onChange:m=>{m!==(e.secrets[n.key]??"")&&e.onSecret(n.key,m)},onToggleClear:()=>e.onToggleClear(n.key)})}):n.kind==="select"?i(Qn,{column:n,id:t,label:o,description:l,issue:a,described:d,values:e.values,disabled:e.disabled,t:e.t,onValue:e.onValue}):n.kind==="proxy"?i("div",{className:"im-field",children:i(bn,{id:t,label:o,hint:l,value:e.values[n.key]??"",proxies:e.proxies,disabled:e.disabled,onChange:m=>{m!==(e.values[n.key]??"")&&e.onValue(n.key,m)},children:a===null?null:i("p",{id:`${t}-issue`,className:"im-small im-issue",role:"alert",children:a})})}):i(B,{id:t,label:o,description:l,issue:a,children:i($,{id:t,type:"text",value:e.values[n.key]??"",placeholder:r,disabled:e.disabled,"aria-invalid":a!==null?!0:void 0,"aria-describedby":d,onChange:m=>{let y=m.target.value;y!==(e.values[n.key]??"")&&e.onValue(n.key,y)}})})}function Qn(e){let n=e.values[e.column.key]??"",t=e.column.options??[],o=t.find(r=>r.value===n),l=n===""?void 0:o===void 0?n:Q(e.t,o.labelKey,o.label)??o.value;return i(B,{id:e.id,label:e.label,description:e.description,issue:e.issue,children:s(le,{className:"im-wide",value:n===""?null:n,disabled:e.disabled,onValueChange:r=>{let a=r??"";a!==n&&e.onValue(e.column.key,a)},children:[i(se,{id:e.id,"aria-invalid":e.issue!==null?!0:void 0,"aria-describedby":e.described,children:l===void 0?i(Y,{placeholder:e.t("settingsSection.select.default")}):i(Y,{children:l})}),i(de,{children:t.map(r=>r.value===""?null:i(ce,{value:r.value,children:Q(e.t,r.labelKey,r.label)??r.value},r.value))})]})})}function Wn(e){let n=D(e.environmentId,`${e.scope}-pub`,e.field.key);return s("div",{className:"im-field im-span",children:[i(G,{children:e.t(`settingsSection.publicField.${e.field.key}`)}),e.field.value===""?null:s("div",{className:"im-inline im-public-row",children:[i("span",{id:n,className:"im-public-value im-small",children:jn(e.field.value)}),e.field.copyable?i(p,{variant:"ghost",size:"sm",onClick:()=>{fe(e.bridge,e.field.value,e.t)},children:e.t("settingsSection.copy")}):null]}),e.field.hint===void 0?null:i("p",{className:"im-small im-muted",children:e.t(`settingsSection.publicFieldHint.${e.field.hint}`)})]})}function jn(e){let n=0;return e.split(/(?<=\/)(?!\/)/).map(t=>{let o=n;return n+=t.length,s(Be,{children:[o===0?null:i("wbr",{}),t]},o)})}function Tn(e){let n={};for(let[r,a]of Object.entries(e.values))(e.baseline[r]??"")!==a&&(n[r]=a);let t={};for(let[r,a]of Object.entries(e.secrets))a!==""&&(t[r]=a);let o=[];for(let r of e.clearSecrets)Object.hasOwn(t,r)||o.includes(r)||o.push(r);return e.rowId===void 0||Object.keys(n).length>0||Object.keys(t).length>0||o.length>0?{changed:!0,edit:{...e.rowId===void 0?{}:{rowId:e.rowId},values:n,...Object.keys(t).length>0?{secrets:t}:{},...o.length>0?{clearSecrets:o}:{}}}:{changed:!1}}function qn(e){let n=e.trim();if(!/^\d+$/.test(n))return null;let t=Number(n);return!Number.isInteger(t)||t<1||t>65535?null:t}function _n(e){let n={};e.replyLanguage!==e.baseline.replyLanguage&&(n.replyLanguage=e.replyLanguage),e.enabled!==e.baseline.enabled&&(n.deliveryHttpEnabled=e.enabled);let t=!1;if(e.enabled){let o=qn(e.port);o===null?t=!0:o!==e.baseline.port&&(n.deliveryHttpPort=o),e.token!==""?n.deliveryHttpToken=e.token:e.clearToken&&e.baseline.hasToken&&(n.clearDeliveryHttpToken=!0)}return t?{changed:!0,invalidPort:!0}:Object.keys(n).length===0?{changed:!1}:{changed:!0,invalidPort:!1,payload:n}}var Pn=te({activeId:null,activate:()=>{}});function En(e){return i(Pn,{value:{activeId:e.activeId,activate:e.activate},children:e.children})}function ve(e){let n=ie(Pn);return{chosen:n.activeId===e,activate:()=>n.activate(e)}}function Se(e,n){let t=A(!1);return{cancelProps:{autoFocus:!0,"aria-describedby":e,onClick:()=>{t.current=!0,n()}},confirmProps:{"aria-describedby":e},triggerRef:o=>{o===null||!t.current||(t.current=!1,o.focus())}}}function Ie(e,n){return{signature:n,values:{...e?.values},secrets:{},clearSecrets:[],saving:!1,failed:!1,confirming:!1,removing:!1,removeFailed:!1}}function _e(e){let{kind:n,row:t}=e,o=t===null?n.newSlot:JSON.stringify(t),l=ve(X(n.newSlot,t?.rowId??null)),r=A(0),[a,d]=R(()=>Ie(t,o)),m=t!==null&&n.removeHintKey!==void 0?`im-remove-consequence-${n.newSlot}-${t.rowId}`:void 0,y=Se(m,()=>d(g=>({...g,confirming:!1})));a.signature!==o&&(r.current+=1,d(Ie(t,o)));let u=Tn({...t===null?{}:{rowId:t.rowId},baseline:t?.values??{},values:a.values,secrets:a.secrets,clearSecrets:a.clearSecrets}),f=u.changed,h=t===null||!t.configured,v=e.status??ke(t),w=e.notice??null,c=a.saving||a.removing;function x(g){l.activate(),d(b=>({...g(b),failed:!1}))}function k(){if(!u.changed||c)return;l.activate();let g=u.edit,b=++r.current;d(I=>({...I,saving:!0,failed:!1})),J(e.bridge,n.saveCommand,g,E(e.environmentId)).then(I=>{if(r.current!==b)return;if(I===null){d(U=>({...U,saving:!1,failed:!0}));return}let P=t===null?void 0:n.rows(I).find(U=>U.rowId===t.rowId);P!==void 0&&d(Ie(P,JSON.stringify(P))),e.onSaved(I)})}function L(){if(t===null){e.onDiscard();return}let g=t.rowId,b=++r.current;d(I=>({...I,removing:!0,removeFailed:!1})),J(e.bridge,n.removeCommand,{rowId:g},E(e.environmentId)).then(I=>{if(r.current===b){if(I===null){d(P=>({...P,removing:!1,removeFailed:!0,confirming:!0}));return}e.onSaved(I)}})}return s(be,{title:e.title(a.values),icon:e.icon?.(a.values),defaultOpen:h,meta:s(N,{children:[e.meta?.(a.values),s("span",{className:"im-status",children:[e.statusMeta,i(ue,{tone:v.tone,children:e.t(v.key)})]})]}),actions:a.confirming?s("div",{className:"im-actions",children:[i(p,{type:"button",variant:"ghost",size:"sm",disabled:a.removing||a.saving,...y.cancelProps,children:e.t("settingsSection.cancel")}),i(p,{type:"button",variant:"destructive",size:"sm",disabled:a.removing||a.saving,...y.confirmProps,onClick:L,children:e.t(n.removeConfirmKey)})]}):i(p,{type:"button",variant:"ghost",size:"sm",disabled:c,ref:y.triggerRef,onClick:()=>d(g=>({...g,confirming:!0,removeFailed:!1})),children:e.t("settingsSection.remove")}),notice:s(N,{children:[e.summary,a.confirming&&t!==null&&n.removeHintKey!==void 0?i("p",{id:m,children:e.t(n.removeHintKey)}):null,a.removeFailed?i("p",{className:"im-small im-issue",role:"alert",children:e.t(n.removeFailedKey)}):null]}),children:[w===null?null:i(H,{variant:w.variant,children:i(z,{children:w.text})}),s("div",{className:"im-form",children:[i(Nn,{scope:`${n.newSlot}-${t?.rowId??"new"}`,environmentId:e.environmentId,columns:e.columns,groupBotSettings:n.groupBotSettings===!0,proxies:e.proxies,values:a.values,secrets:a.secrets,clearSecrets:a.clearSecrets,storedSecrets:t?.secrets??{},issues:t?.issues??[],publicFields:t?.publicFields??[],disabled:c,bridge:e.bridge,t:e.t,onValue:(g,b)=>x(I=>({...I,values:{...I.values,[g]:b}})),onSecret:(g,b)=>x(I=>({...I,secrets:{...I.secrets,[g]:b}})),onToggleClear:g=>x(b=>({...b,clearSecrets:b.clearSecrets.includes(g)?b.clearSecrets.filter(I=>I!==g):[...b.clearSecrets,g]}))}),e.extra?.({dirty:f,frozen:c}),i(ye,{dirty:f,saving:a.saving,busy:a.removing,solid:l.chosen&&f,failed:a.failed,saveLabel:e.t("settingsSection.save"),revertLabel:e.t("settingsSection.revert"),failedLabel:e.t("settingsSection.saveFailed"),onSave:k,onRevert:()=>{r.current+=1,d(Ie(t,o))}})]})]})}function An(e){let n=e.bridge.useFormatTimestamp(),{error:t,t:o}=e;if(t===void 0)return null;let l=new Date(t.at),r=Number.isFinite(l.getTime())?l.toISOString():null;return s("div",{className:"im-small",role:"status",children:[s("p",{children:[i("strong",{className:"im-issue",children:o("settingsSection.lastMessageError.title")}),o("settingsSection.lastMessageError.separator"),i("span",{children:t.messageKey===void 0?t.message:o(t.messageKey,{...t.messageParams,defaultValue:t.message})})]}),s("p",{className:"im-muted",children:[o("settingsSection.lastMessageError.code",{code:t.code})," \xB7 ",o("settingsSection.lastMessageError.reference",{referenceId:t.referenceId}),r===null?null:s(N,{children:[" \xB7 ",i("time",{dateTime:r,children:n(r)})]})]})]})}var we={groupBotSettings:!0,newSlot:"im-new-row",saveCommand:Ve,removeCommand:De,rows:e=>e.bots,removeConfirmKey:"settingsSection.removeConfirm",removeHintKey:"settingsSection.removeHint",removeFailedKey:"settingsSection.removeFailed"},Ce={newSlot:"im-new-target",saveCommand:$e,removeCommand:Ge,rows:e=>e.targets,removeConfirmKey:"settingsSection.target.removeConfirm",removeFailedKey:"settingsSection.target.removeFailed"},On=(e,n,t)=>{let o=(e.displayName??"").trim();return o.length>0?o:t(`platform.${n}`)};function Pe(e){let{bot:n,t}=e,o=e.bots.find(f=>f.rowId===(n===null?void 0:e.connections?.[n.rowId]?.duplicateOf)),l=rn(n,e.connections,o===void 0?void 0:On(o.values,o.platform,t),t),[r,a]=R(null),[d,m]=R(!1),y=n===null?void 0:`im-reset-consequence-${n.rowId}`,u=Se(y,()=>m(!1));return i(_e,{...e,kind:we,row:n,status:on(n,e.connections),statusMeta:n?.configured&&e.connections?.[n.rowId]?.statusSince!==void 0?i(an,{since:e.connections[n.rowId]?.statusSince,bridge:e.bridge,t}):null,notice:l,summary:n===null?null:i(An,{error:e.connections?.[n.rowId]?.lastMessageError,bridge:e.bridge,t}),title:f=>On(f,re(f),t),icon:f=>{let h=O(f,"platform");if(h==="")return null;let w=e.columns.find(c=>c.key==="platform")?.options?.find(c=>c.value===h)?.icon;return w?i(cn,{name:w}):null},meta:f=>{let h=re(f),v=kn(h,f),w=t(`platform.${h}`);return i("span",{className:"im-small im-muted",...v===null?{}:{title:v},children:v===null?w:`${w} \xB7 ${v}`})},extra:({dirty:f,frozen:h})=>{if(n===null)return null;let v=Sn(n.platform,f,h,e.connections?.[n.rowId]),w=v.actions.find(c=>c.id==="resetInbox");return s(N,{children:[s("div",{className:"im-span",children:[d&&w!==void 0?s(N,{children:[i("p",{id:y,children:w.descriptionKeys.map(c=>t(c)).join(" ")}),s("div",{className:"im-actions",children:[i(p,{type:"button",variant:"ghost",size:"sm",disabled:h,...u.cancelProps,children:t("settingsSection.cancel")}),i(p,{type:"button",variant:"destructive",size:"sm",disabled:w.disabled,...u.confirmProps,onClick:()=>{m(!1),a({id:"resetInbox",payload:{rowId:n.rowId}})},children:t("rowAction.resetInbox.confirm")})]})]}):i("div",{className:"im-actions",children:v.actions.map(c=>i(p,{type:"button",variant:"ghost",size:"sm",disabled:c.disabled,title:c.descriptionKeys.map(x=>t(x,c.descriptionParams)).join(" "),ref:c.id==="resetInbox"?u.triggerRef:void 0,onClick:()=>{c.id==="resetInbox"?m(!0):a({id:c.id,payload:{rowId:n.rowId}})},children:t(c.labelKey)},c.id))}),v.noteKey!==null?i("p",{className:"im-small im-muted",children:t(v.noteKey)}):null]}),r===null?null:i(pe,{bridge:e.bridge,command:Qe[r.id],payload:r.payload,items:"latest",environmentId:e.environmentId,t,onClose:()=>a(null)},r.id)]})}})}function Ee(e){let{t:n}=e;return i(_e,{...e,kind:Ce,row:e.target,title:t=>{let o=(t.name??"").trim()||(t.targetId??"").trim();return o.length>0?o:n("settingsSection.target.untitled")}})}var Yn="im-general";function he(e,n){return{signature:n,replyLanguage:e.replyLanguage,enabled:e.delivery.enabled,port:String(e.delivery.port),token:"",clearToken:!1,saving:!1,failed:!1}}function Bn(e){let n=e.view,t=Ne(n),o=ve(Yn),l=A(0),[r,a]=R(()=>he(n,t));r.signature!==t&&(l.current+=1,a(he(n,t)));let d=_n({baseline:{replyLanguage:n.replyLanguage,enabled:n.delivery.enabled,port:n.delivery.port,hasToken:n.delivery.hasToken},replyLanguage:r.replyLanguage,enabled:r.enabled,port:r.port,token:r.token,clearToken:r.clearToken}),m=d.changed,y=d.changed&&d.invalidPort,u=D(e.environmentId,"general","port"),f=D(e.environmentId,"general","token"),h=D(e.environmentId,"general","language");function v(c){o.activate(),a(x=>({...x,...c,failed:!1}))}function w(){if(!d.changed||r.saving)return;if(o.activate(),d.invalidPort){a(k=>({...k,failed:!0}));return}let c=d.payload,x=++l.current;a(k=>({...k,saving:!0,failed:!1})),J(e.bridge,Ue,c,E(e.environmentId)).then(k=>{if(l.current===x){if(k===null){a(L=>({...L,saving:!1,failed:!0}));return}a(he(k,Ne(k))),e.onSaved(k)}})}return i(be,{title:e.t("settingsSection.general"),defaultOpen:!1,children:s("div",{className:"im-form",children:[i(B,{id:h,label:e.t("settings.language.label"),description:e.t("settings.language.description"),children:s(le,{className:"im-wide",value:r.replyLanguage,disabled:r.saving,onValueChange:c=>{let x=oe.find(k=>k.value===c);x===void 0||x.value===r.replyLanguage||v({replyLanguage:x.value})},children:[i(se,{id:h,"aria-describedby":`${h}-hint`,children:i(Y,{children:oe.filter(c=>c.value===r.replyLanguage).map(c=>e.t(c.labelKey))})}),i(de,{children:oe.map(c=>i(ce,{value:c.value,children:e.t(c.labelKey)},c.value))})]})}),s("div",{className:"im-field",children:[s(G,{className:"im-inline",children:[i("span",{className:"im-medium",children:e.t("settings.deliveryHttp.enabled.label")}),i(dn,{checked:r.enabled,disabled:r.saving,onCheckedChange:c=>{c!==r.enabled&&v({enabled:c})}})]}),i("p",{className:"im-small im-muted",children:e.t("settings.deliveryHttp.enabled.description")})]}),r.enabled?i(B,{id:u,label:e.t("settings.deliveryHttp.port.label"),description:e.t("settings.deliveryHttp.port.description"),issue:y?e.t("settingsSection.issue.format"):null,children:i($,{id:u,type:"number",value:r.port,disabled:r.saving,"aria-invalid":y?!0:void 0,"aria-describedby":Z(u,y,!0),onChange:c=>{c.target.value!==r.port&&v({port:c.target.value})}})}):null,r.enabled?i(B,{id:f,label:e.t("settings.deliveryHttp.token.label"),description:e.t("settings.deliveryHttp.token.description"),children:i(ge,{id:f,value:r.token,stored:n.delivery.hasToken,clearing:r.clearToken,disabled:r.saving,invalid:!1,describedBy:Z(f,!1,!0),savedPlaceholder:e.t("settingsSection.secret.saved"),clearLabel:e.t("settingsSection.secret.clear"),undoLabel:e.t("settingsSection.secret.clearUndo"),onChange:c=>{c!==r.token&&v({token:c})},onToggleClear:()=>v({clearToken:!r.clearToken})})}):null,i(ye,{dirty:m,saving:r.saving,solid:o.chosen&&m,failed:r.failed,saveLabel:e.t("settingsSection.save"),revertLabel:e.t("settingsSection.revert"),failedLabel:e.t("settingsSection.saveFailed"),onSave:w,onRevert:()=>{l.current+=1,a(he(n,t))}})]})})}var Ln=`
5
+ `),d)},children:d("settingsSection.copy")})})]})]})}function Hn(e){return e.length>12?`${e.slice(0,8)}\u2022\u2022\u2022\u2022${e.slice(-4)}`:"cli_\u2022\u2022\u2022\u2022"}function kn(e){return e.length<=10?`${e.slice(0,3)}\u2022\u2022\u2022`:`${e.slice(0,6)}\u2022\u2022\u2022\u2022${e.slice(-4)}`}var zn={lark:{column:"larkAppId",mask:Hn},wecom:{column:"wecomBotId",mask:kn},"wecom-app":{column:"wecomAppCorpId",mask:kn}};function Tn(e,n){let t=zn[e];if(t===void 0)return null;let o=O(n,t.column);return o===""?null:t.mask(o)}function Ne(e){return s(yn,{className:e.className===void 0?"im-collapse":`im-collapse ${e.className}`,...e.defaultOpen===void 0?{}:{defaultOpen:e.defaultOpen},...e.open===void 0?{}:{open:e.open},...e.onOpenChange===void 0?{}:{onOpenChange:e.onOpenChange},children:[s("div",{className:"im-head",children:[s(fn,{className:"im-toggle",children:[i("span",{className:"im-chevron","aria-hidden":"true"}),e.icon,i("span",{className:"im-title im-medium",children:e.title}),e.meta]}),e.actions]}),e.notice,i(pn,{children:i("div",{className:"im-panel",children:e.children})})]})}function ve(e){return i("section",{className:"im-block",children:i(Ne,{...e})})}var _e="\0empty";function Nn(e){let n=e.columns.filter(m=>Ye(m,e.values)),t=e.groupBotSettings?n.filter(m=>m.group==="essential"):n,o=e.groupBotSettings?n.filter(m=>m.group!=="essential"):[],l=e.issues.filter(m=>o.some(f=>f.key===m.column)),r=JSON.stringify(l),[a,d]=R(()=>({open:l.length>0,issues:r})),u=a.open||a.issues!==r&&l.length>0;a.issues!==r&&d({open:u,issues:r});let g=m=>i(Qn,{column:m,scope:e.scope,environmentId:e.environmentId,proxies:e.proxies,values:e.values,savedValues:e.savedValues,secrets:e.secrets,clearSecrets:e.clearSecrets,storedSecrets:e.storedSecrets,issues:e.issues,disabled:e.disabled,t:e.t,onValue:e.onValue,onSecret:e.onSecret,onToggleClear:e.onToggleClear},m.key);return s(T,{children:[t.map(g),e.publicFields.map(m=>i(jn,{field:m,scope:e.scope,environmentId:e.environmentId,bridge:e.bridge,t:e.t},m.key)),o.length===0?null:i(Ne,{className:"im-span",title:l.length>0?e.t("settingsSection.moreSettingsIssues",{count:l.length}):e.t("settingsSection.moreSettings"),open:u,onOpenChange:m=>d({open:m,issues:r}),children:i("div",{className:"im-form",children:o.map(g)})})]})}function Qn(e){let n=e.column,t=D(e.environmentId,e.scope,n.key),o=Q(e.t,n.labelKey,n.label)??n.key,l=Q(e.t,n.descriptionKey,n.description),r=Q(e.t,n.placeholderKey,n.placeholder),a=xn(e.t,e.issues.filter(u=>u.column===n.key).map(u=>u.code)),d=ee(t,a!==null,l!==void 0);return n.kind==="password"?i(B,{id:t,label:o,description:l,issue:a,children:i(ge,{id:t,value:e.secrets[n.key]??"",stored:e.storedSecrets[n.key]===!0,clearing:e.clearSecrets.includes(n.key),disabled:e.disabled,invalid:a!==null,describedBy:d,placeholder:r,savedPlaceholder:e.t("settingsSection.secret.saved"),clearLabel:e.t("settingsSection.secret.clear"),undoLabel:e.t("settingsSection.secret.clearUndo"),onChange:u=>{u!==(e.secrets[n.key]??"")&&e.onSecret(n.key,u)},onToggleClear:()=>e.onToggleClear(n.key)})}):n.kind==="select"?i(Wn,{column:n,id:t,label:o,description:l,issue:a,described:d,values:e.values,savedValues:e.savedValues,disabled:e.disabled,t:e.t,onValue:e.onValue}):n.kind==="proxy"?i("div",{className:"im-field",children:i(bn,{id:t,label:o,hint:l,value:e.values[n.key]??"",proxies:e.proxies,disabled:e.disabled,onChange:u=>{u!==(e.values[n.key]??"")&&e.onValue(n.key,u)},children:a===null?null:i("p",{id:`${t}-issue`,className:"im-small im-issue",role:"alert",children:a})})}):i(B,{id:t,label:o,description:l,issue:a,children:i($,{id:t,type:"text",value:e.values[n.key]??"",placeholder:r,disabled:e.disabled,"aria-invalid":a!==null?!0:void 0,"aria-describedby":d,onChange:u=>{let g=u.target.value;g!==(e.values[n.key]??"")&&e.onValue(n.key,g)}})})}function Wn(e){let n=e.values[e.column.key]??"",t=e.savedValues[e.column.key]??"",o=e.column.options??[],l=o.some(u=>u.value===""),r=o.find(u=>u.value===n),a=u=>e.column.unavailableLabelKey===void 0?u:e.t(e.column.unavailableLabelKey,{value:u}),d=n===""&&r===void 0?void 0:r===void 0?a(n):Q(e.t,r.labelKey,r.label)??r.value;return i(B,{id:e.id,label:e.label,description:e.description,issue:e.issue,children:s(se,{className:"im-wide",value:n===""?l?_e:null:n,disabled:e.disabled,onValueChange:u=>{let g=l&&u===_e?"":u??"";g!==n&&e.onValue(e.column.key,g)},children:[i(de,{id:e.id,"aria-invalid":e.issue!==null?!0:void 0,"aria-describedby":e.described,children:d===void 0?i(Y,{placeholder:e.t("settingsSection.select.default")}):i(Y,{children:d})}),s(ce,{children:[e.column.listsUnknownValue===!0&&t!==""&&!o.some(u=>u.value===t)?i(J,{value:t,disabled:e.column.unavailableLabelKey!==void 0,children:a(t)}):null,o.map(u=>i(J,{value:u.value===""?_e:u.value,children:Q(e.t,u.labelKey,u.label)??u.value},u.value))]})]})})}function jn(e){let n=D(e.environmentId,`${e.scope}-pub`,e.field.key);return s("div",{className:"im-field im-span",children:[i(G,{children:e.t(`settingsSection.publicField.${e.field.key}`)}),e.field.value===""?null:s("div",{className:"im-inline im-public-row",children:[i("span",{id:n,className:"im-public-value im-small",children:qn(e.field.value)}),e.field.copyable?i(p,{variant:"ghost",size:"sm",onClick:()=>{fe(e.bridge,e.field.value,e.t)},children:e.t("settingsSection.copy")}):null]}),e.field.hint===void 0?null:i("p",{className:"im-small im-muted",children:e.t(`settingsSection.publicFieldHint.${e.field.hint}`)})]})}function qn(e){let n=0;return e.split(/(?<=\/)(?!\/)/).map(t=>{let o=n;return n+=t.length,s(Le,{children:[o===0?null:i("wbr",{}),t]},o)})}function _n(e){let n={};for(let[r,a]of Object.entries(e.values))(e.baseline[r]??"")!==a&&(n[r]=a);let t={};for(let[r,a]of Object.entries(e.secrets))a!==""&&(t[r]=a);let o=[];for(let r of e.clearSecrets)Object.hasOwn(t,r)||o.includes(r)||o.push(r);return e.rowId===void 0||Object.keys(n).length>0||Object.keys(t).length>0||o.length>0?{changed:!0,edit:{...e.rowId===void 0?{}:{rowId:e.rowId},values:n,...Object.keys(t).length>0?{secrets:t}:{},...o.length>0?{clearSecrets:o}:{}}}:{changed:!1}}function Yn(e){let n=e.trim();if(!/^\d+$/.test(n))return null;let t=Number(n);return!Number.isInteger(t)||t<1||t>65535?null:t}function En(e){let n={};e.replyLanguage!==e.baseline.replyLanguage&&(n.replyLanguage=e.replyLanguage),e.enabled!==e.baseline.enabled&&(n.deliveryHttpEnabled=e.enabled);let t=!1;if(e.enabled){let o=Yn(e.port);o===null?t=!0:o!==e.baseline.port&&(n.deliveryHttpPort=o),e.token!==""?n.deliveryHttpToken=e.token:e.clearToken&&e.baseline.hasToken&&(n.clearDeliveryHttpToken=!0)}return t?{changed:!0,invalidPort:!0}:Object.keys(n).length===0?{changed:!1}:{changed:!0,invalidPort:!1,payload:n}}var Pn=ie({activeId:null,activate:()=>{}});function An(e){return i(Pn,{value:{activeId:e.activeId,activate:e.activate},children:e.children})}function be(e){let n=oe(Pn);return{chosen:n.activeId===e,activate:()=>n.activate(e)}}function Se(e,n){let t=A(!1);return{cancelProps:{autoFocus:!0,"aria-describedby":e,onClick:()=>{t.current=!0,n()}},confirmProps:{"aria-describedby":e},triggerRef:o=>{o===null||!t.current||(t.current=!1,o.focus())}}}function Ie(e,n){return{signature:n,values:{...e?.values},secrets:{},clearSecrets:[],saving:!1,failed:!1,confirming:!1,removing:!1,removeFailed:!1}}function Ee(e){let{kind:n,row:t}=e,o=t===null?n.newSlot:JSON.stringify(t),l=be(Z(n.newSlot,t?.rowId??null)),r=A(0),[a,d]=R(()=>Ie(t,o)),u=t!==null&&n.removeHintKey!==void 0?`im-remove-consequence-${n.newSlot}-${t.rowId}`:void 0,g=Se(u,()=>d(y=>({...y,confirming:!1})));a.signature!==o&&(r.current+=1,d(Ie(t,o)));let m=_n({...t===null?{}:{rowId:t.rowId},baseline:t?.values??{},values:a.values,secrets:a.secrets,clearSecrets:a.clearSecrets}),f=m.changed,h=t===null||!t.configured,b=e.status??ke(t),w=e.notice??null,c=a.saving||a.removing;function x(y){l.activate(),d(v=>({...y(v),failed:!1}))}function k(){if(!m.changed||c)return;l.activate();let y=m.edit,v=++r.current;d(I=>({...I,saving:!0,failed:!1})),X(e.bridge,n.saveCommand,y,P(e.environmentId)).then(I=>{if(r.current!==v)return;if(I===null){d(U=>({...U,saving:!1,failed:!0}));return}let E=t===null?void 0:n.rows(I).find(U=>U.rowId===t.rowId);E!==void 0&&d(Ie(E,JSON.stringify(E))),e.onSaved(I)})}function L(){if(t===null){e.onDiscard();return}let y=t.rowId,v=++r.current;d(I=>({...I,removing:!0,removeFailed:!1})),X(e.bridge,n.removeCommand,{rowId:y},P(e.environmentId)).then(I=>{if(r.current===v){if(I===null){d(E=>({...E,removing:!1,removeFailed:!0,confirming:!0}));return}e.onSaved(I)}})}return s(ve,{title:e.title(a.values),icon:e.icon?.(a.values),defaultOpen:h,meta:s(T,{children:[e.meta?.(a.values),s("span",{className:"im-status",children:[e.statusMeta,i(ue,{tone:b.tone,children:e.t(b.key)})]})]}),actions:a.confirming?s("div",{className:"im-actions",children:[i(p,{type:"button",variant:"ghost",size:"sm",disabled:a.removing||a.saving,...g.cancelProps,children:e.t("settingsSection.cancel")}),i(p,{type:"button",variant:"destructive",size:"sm",disabled:a.removing||a.saving,...g.confirmProps,onClick:L,children:e.t(n.removeConfirmKey)})]}):i(p,{type:"button",variant:"ghost",size:"sm",disabled:c,ref:g.triggerRef,onClick:()=>d(y=>({...y,confirming:!0,removeFailed:!1})),children:e.t("settingsSection.remove")}),notice:s(T,{children:[e.summary,a.confirming&&t!==null&&n.removeHintKey!==void 0?i("p",{id:u,children:e.t(n.removeHintKey)}):null,a.removeFailed?i("p",{className:"im-small im-issue",role:"alert",children:e.t(n.removeFailedKey)}):null]}),children:[w===null?null:i(H,{variant:w.variant,children:i(z,{children:w.text})}),s("div",{className:"im-form",children:[i(Nn,{scope:`${n.newSlot}-${t?.rowId??"new"}`,environmentId:e.environmentId,columns:e.columns,groupBotSettings:n.groupBotSettings===!0,proxies:e.proxies,values:a.values,savedValues:t?.values??{},secrets:a.secrets,clearSecrets:a.clearSecrets,storedSecrets:t?.secrets??{},issues:t?.issues??[],publicFields:t?.publicFields??[],disabled:c,bridge:e.bridge,t:e.t,onValue:(y,v)=>x(I=>({...I,values:{...I.values,[y]:v}})),onSecret:(y,v)=>x(I=>({...I,secrets:{...I.secrets,[y]:v}})),onToggleClear:y=>x(v=>({...v,clearSecrets:v.clearSecrets.includes(y)?v.clearSecrets.filter(I=>I!==y):[...v.clearSecrets,y]}))}),e.extra?.({dirty:f,frozen:c}),i(ye,{dirty:f,saving:a.saving,busy:a.removing,solid:l.chosen&&f,failed:a.failed,saveLabel:e.t("settingsSection.save"),revertLabel:e.t("settingsSection.revert"),failedLabel:e.t("settingsSection.saveFailed"),onSave:k,onRevert:()=>{r.current+=1,d(Ie(t,o))}})]})]})}function On(e){let n=e.bridge.useFormatTimestamp(),{error:t,t:o}=e;if(t===void 0)return null;let l=new Date(t.at),r=Number.isFinite(l.getTime())?l.toISOString():null;return s("div",{className:"im-small",role:"status",children:[s("p",{children:[i("strong",{className:"im-issue",children:o("settingsSection.lastMessageError.title")}),o("settingsSection.lastMessageError.separator"),i("span",{children:t.messageKey===void 0?t.message:o(t.messageKey,{...t.messageParams,defaultValue:t.message})})]}),s("p",{className:"im-muted",children:[o("settingsSection.lastMessageError.code",{code:t.code})," \xB7 ",o("settingsSection.lastMessageError.reference",{referenceId:t.referenceId}),r===null?null:s(T,{children:[" \xB7 ",i("time",{dateTime:r,children:n(r)})]})]})]})}var we={groupBotSettings:!0,newSlot:"im-new-row",saveCommand:De,removeCommand:Ue,rows:e=>e.bots,removeConfirmKey:"settingsSection.removeConfirm",removeHintKey:"settingsSection.removeHint",removeFailedKey:"settingsSection.removeFailed"},Ce={newSlot:"im-new-target",saveCommand:Ge,removeCommand:He,rows:e=>e.targets,removeConfirmKey:"settingsSection.target.removeConfirm",removeFailedKey:"settingsSection.target.removeFailed"},Bn=(e,n,t)=>{let o=(e.displayName??"").trim();return o.length>0?o:t(`platform.${n}`)};function Pe(e){let{bot:n,t}=e,o=e.bots.find(f=>f.rowId===(n===null?void 0:e.connections?.[n.rowId]?.duplicateOf)),l=an(n,e.connections,o===void 0?void 0:Bn(o.values,o.platform,t),t),[r,a]=R(null),[d,u]=R(!1),g=n===null?void 0:`im-reset-consequence-${n.rowId}`,m=Se(g,()=>u(!1));return i(Ee,{...e,kind:we,row:n,status:rn(n,e.connections),statusMeta:n?.configured&&e.connections?.[n.rowId]?.statusSince!==void 0?i(ln,{since:e.connections[n.rowId]?.statusSince,bridge:e.bridge,t}):null,notice:l,summary:n===null?null:i(On,{error:e.connections?.[n.rowId]?.lastMessageError,bridge:e.bridge,t}),title:f=>Bn(f,ae(f),t),icon:f=>{let h=O(f,"platform");if(h==="")return null;let w=e.columns.find(c=>c.key==="platform")?.options?.find(c=>c.value===h)?.icon;return w?i(un,{name:w}):null},meta:f=>{let h=ae(f),b=Tn(h,f),w=t(`platform.${h}`);return i("span",{className:"im-small im-muted",...b===null?{}:{title:b},children:b===null?w:`${w} \xB7 ${b}`})},extra:({dirty:f,frozen:h})=>{if(n===null)return null;let b=In(n.platform,f,h,e.connections?.[n.rowId]),w=b.actions.find(c=>c.id==="resetInbox");return s(T,{children:[s("div",{className:"im-span",children:[d&&w!==void 0?s(T,{children:[i("p",{id:g,children:w.descriptionKeys.map(c=>t(c)).join(" ")}),s("div",{className:"im-actions",children:[i(p,{type:"button",variant:"ghost",size:"sm",disabled:h,...m.cancelProps,children:t("settingsSection.cancel")}),i(p,{type:"button",variant:"destructive",size:"sm",disabled:w.disabled,...m.confirmProps,onClick:()=>{u(!1),a({id:"resetInbox",payload:{rowId:n.rowId}})},children:t("rowAction.resetInbox.confirm")})]})]}):i("div",{className:"im-actions",children:b.actions.map(c=>i(p,{type:"button",variant:"ghost",size:"sm",disabled:c.disabled,title:c.descriptionKeys.map(x=>t(x,c.descriptionParams)).join(" "),ref:c.id==="resetInbox"?m.triggerRef:void 0,onClick:()=>{c.id==="resetInbox"?u(!0):a({id:c.id,payload:{rowId:n.rowId}})},children:t(c.labelKey)},c.id))}),b.noteKey!==null?i("p",{className:"im-small im-muted",children:t(b.noteKey)}):null]}),r===null?null:i(pe,{bridge:e.bridge,command:We[r.id],payload:r.payload,items:"latest",environmentId:e.environmentId,t,onClose:()=>a(null)},r.id)]})}})}function Ae(e){let{t:n}=e;return i(Ee,{...e,kind:Ce,row:e.target,title:t=>{let o=(t.name??"").trim()||(t.targetId??"").trim();return o.length>0?o:n("settingsSection.target.untitled")}})}var Jn="im-general";function he(e,n){return{signature:n,replyLanguage:e.replyLanguage,enabled:e.delivery.enabled,port:String(e.delivery.port),token:"",clearToken:!1,saving:!1,failed:!1}}function Ln(e){let n=e.view,t=Te(n),o=be(Jn),l=A(0),[r,a]=R(()=>he(n,t));r.signature!==t&&(l.current+=1,a(he(n,t)));let d=En({baseline:{replyLanguage:n.replyLanguage,enabled:n.delivery.enabled,port:n.delivery.port,hasToken:n.delivery.hasToken},replyLanguage:r.replyLanguage,enabled:r.enabled,port:r.port,token:r.token,clearToken:r.clearToken}),u=d.changed,g=d.changed&&d.invalidPort,m=D(e.environmentId,"general","port"),f=D(e.environmentId,"general","token"),h=D(e.environmentId,"general","language");function b(c){o.activate(),a(x=>({...x,...c,failed:!1}))}function w(){if(!d.changed||r.saving)return;if(o.activate(),d.invalidPort){a(k=>({...k,failed:!0}));return}let c=d.payload,x=++l.current;a(k=>({...k,saving:!0,failed:!1})),X(e.bridge,$e,c,P(e.environmentId)).then(k=>{if(l.current===x){if(k===null){a(L=>({...L,saving:!1,failed:!0}));return}a(he(k,Te(k))),e.onSaved(k)}})}return i(ve,{title:e.t("settingsSection.general"),defaultOpen:!1,children:s("div",{className:"im-form",children:[i(B,{id:h,label:e.t("settings.language.label"),description:e.t("settings.language.description"),children:s(se,{className:"im-wide",value:r.replyLanguage,disabled:r.saving,onValueChange:c=>{let x=re.find(k=>k.value===c);x===void 0||x.value===r.replyLanguage||b({replyLanguage:x.value})},children:[i(de,{id:h,"aria-describedby":`${h}-hint`,children:i(Y,{children:re.filter(c=>c.value===r.replyLanguage).map(c=>e.t(c.labelKey))})}),i(ce,{children:re.map(c=>i(J,{value:c.value,children:e.t(c.labelKey)},c.value))})]})}),s("div",{className:"im-field",children:[s(G,{className:"im-inline",children:[i("span",{className:"im-medium",children:e.t("settings.deliveryHttp.enabled.label")}),i(cn,{checked:r.enabled,disabled:r.saving,onCheckedChange:c=>{c!==r.enabled&&b({enabled:c})}})]}),i("p",{className:"im-small im-muted",children:e.t("settings.deliveryHttp.enabled.description")})]}),r.enabled?i(B,{id:m,label:e.t("settings.deliveryHttp.port.label"),description:e.t("settings.deliveryHttp.port.description"),issue:g?e.t("settingsSection.issue.format"):null,children:i($,{id:m,type:"number",value:r.port,disabled:r.saving,"aria-invalid":g?!0:void 0,"aria-describedby":ee(m,g,!0),onChange:c=>{c.target.value!==r.port&&b({port:c.target.value})}})}):null,r.enabled?i(B,{id:f,label:e.t("settings.deliveryHttp.token.label"),description:e.t("settings.deliveryHttp.token.description"),children:i(ge,{id:f,value:r.token,stored:n.delivery.hasToken,clearing:r.clearToken,disabled:r.saving,invalid:!1,describedBy:ee(f,!1,!0),savedPlaceholder:e.t("settingsSection.secret.saved"),clearLabel:e.t("settingsSection.secret.clear"),undoLabel:e.t("settingsSection.secret.clearUndo"),onChange:c=>{c!==r.token&&b({token:c})},onToggleClear:()=>b({clearToken:!r.clearToken})})}):null,i(ye,{dirty:u,saving:r.saving,solid:o.chosen&&u,failed:r.failed,saveLabel:e.t("settingsSection.save"),revertLabel:e.t("settingsSection.revert"),failedLabel:e.t("settingsSection.saveFailed"),onSave:w,onRevert:()=>{l.current+=1,a(he(n,t))}})]})})}var Mn=`
6
6
  .im-settings {
7
7
  box-sizing: border-box;
8
8
  color: var(--foreground);
@@ -238,4 +238,4 @@ var Kn=window.__ycodiumPluginHost.react;var{Activity:Xn,Children:Zn,Component:et
238
238
  grid-column: 1 / -1;
239
239
  }
240
240
  }
241
- `;var Ae={};function Mn(e){let n=e.bridge.i18n.usePluginTranslation(),t=M(()=>E(e.environmentId),[e.environmentId]),o=e.bridge.commands.useQuery(Ke,Ae,t),l=e.bridge.commands.useSubscription(Fe,Ae,t),r=tn(l),a=M(()=>wn(o.data),[o.data]),[d,m]=R(null),[y,u]=R(null),[f,h]=R(!1),[v,w]=R(!1),[c,x]=R(null),[k,L]=R(null);if(a!==null&&a!==d&&m(a),y!==null){let _=Cn(y,{view:a?.view??null,isPending:o.isPending,failed:o.error!==null});_!==y&&u(_)}let g=y?.view??a?.view??d?.view??null,b=a??d,I=a===null&&o.data!==null&&!o.isPending,P=c==="lark"?{command:He,descriptionKey:K.descriptionKey}:c==="wecom"?{command:ze,descriptionKey:"wecomSetup.action.description"}:null,U=M(()=>Ye(b?.targetColumns??[],g?.bots??[],_=>n(`platform.${_}`)),[b,g,n]);function W(_){u({view:_,phase:"asked"}),o.refresh()}function ee(){u(null),o.refresh()}let j;if(o.isUnavailable)j=i(Oe,{variant:"warning",message:n("settingsSection.unavailable"),retryLabel:n("settingsSection.retry"),onRetry:ee});else if(g===null&&o.isPending)j=i("div",{className:"im-pending",children:i(V,{size:"md"})});else if(g===null||b===null)j=i(Oe,{variant:"error",message:n("settingsSection.loadFailed"),retryLabel:n("settingsSection.retry"),onRetry:ee});else{let _=g.bots.length===0&&!f;j=s(En,{activeId:k,activate:L,children:[o.error!==null||I?i(Oe,{variant:"error",message:n("settingsSection.loadFailed"),retryLabel:n("settingsSection.retry"),onRetry:ee}):null,i(Bn,{view:g,environmentId:e.environmentId,bridge:e.bridge,t:n,onSaved:W}),g.bots.map(T=>i(Pe,{bot:T,bots:g.bots,connections:r,columns:b.columns,proxies:b.proxies,environmentId:e.environmentId,bridge:e.bridge,t:n,onSaved:W,onDiscard:()=>{}},T.rowId)),f?i(Pe,{bot:null,bots:g.bots,connections:r,columns:b.columns,proxies:b.proxies,environmentId:e.environmentId,bridge:e.bridge,t:n,onSaved:T=>{h(!1),W(T)},onDiscard:()=>h(!1)},we.newSlot):null,_?i(un,{title:n("settingsSection.empty"),description:n("settingsSection.emptyGuide",{larkLabel:n(K.labelKey),wecomLabel:n("wecomSetup.action.label"),addBotLabel:n("settingsSection.addBot")})}):null,s("div",{className:"im-actions",children:[i(p,{variant:"outline",disabled:f,onClick:()=>{h(!0),L(X(we.newSlot,null))},children:n("settingsSection.addBot")}),s(p,{variant:_?"default":"outline",disabled:c!==null,onClick:()=>x("lark"),children:[n(K.labelKey),i("span",{className:_?"im-badge im-badge-on-primary im-small":"im-badge im-small",children:n(K.badgeKey)})]}),s(p,{variant:"outline",disabled:c!==null,onClick:()=>x("wecom"),children:[n("wecomSetup.action.label"),i("span",{className:"im-badge im-small",children:n(K.badgeKey)})]})]}),i("p",{className:"im-small im-muted",children:n(K.warningKey)}),P?s("section",{className:"im-block",children:[i("p",{className:"im-small im-muted",children:n(P.descriptionKey)}),i(pe,{bridge:e.bridge,command:P.command,payload:Ae,items:"snapshots",environmentId:e.environmentId,t:n,onSettled:T=>{T.kind==="done"&&ee()},onClose:()=>x(null)})]}):null,i("h3",{className:"im-heading im-medium",children:n("settings.deliveryTargets.label")}),i("p",{className:"im-small im-muted",children:n("settingsSection.target.description")}),g.targets.map(T=>i(Ee,{target:T,columns:U,proxies:b.proxies,environmentId:e.environmentId,bridge:e.bridge,t:n,onSaved:W,onDiscard:()=>{}},T.rowId)),v?i(Ee,{target:null,columns:U,proxies:b.proxies,environmentId:e.environmentId,bridge:e.bridge,t:n,onSaved:T=>{w(!1),W(T)},onDiscard:()=>w(!1)},Ce.newSlot):null,i("div",{className:"im-actions",children:i(p,{variant:"outline",disabled:v,onClick:()=>{w(!0),L(X(Ce.newSlot,null))},children:n("settingsSection.target.add")})})]})}let ne=r===null?null:nn(g?.bots??[],r);return i(sn,{bridge:e.bridge,children:s("div",{className:"im-settings",children:[i("style",{children:Ln}),s("div",{className:"im-head",children:[i("h2",{className:"im-heading im-medium im-title",children:n("settings.title")}),ne!==null&&ne.configured>0?i(ue,{tone:"neutral","aria-label":n("settingsSection.onlineLabel",ne),children:n("settingsSection.online",ne)}):null]}),j]})})}function Oe(e){return s(H,{variant:e.variant,layout:"inline",children:[i(z,{children:e.message}),i(mn,{children:i(p,{variant:"ghost",size:"sm",onClick:e.onRetry,children:e.retryLabel})})]})}function Jn(e){return{slots:[{name:"settings.section",order:20,component(n){return i(Mn,{bridge:e,environmentId:n.environmentId??null},n.environmentId??"")}}]}}export{Jn as default};
241
+ `;var Oe={};function Kn(e){let n=e.bridge.i18n.usePluginTranslation(),t=M(()=>P(e.environmentId),[e.environmentId]),o=e.bridge.commands.useQuery(Ve,Oe,t),l=e.bridge.commands.useSubscription(Fe,Oe,t),r=on(l),a=M(()=>Cn(o.data),[o.data]),[d,u]=R(null),[g,m]=R(null),[f,h]=R(!1),[b,w]=R(!1),[c,x]=R(null),[k,L]=R(null);if(a!==null&&a!==d&&u(a),g!==null){let _=hn(g,{view:a?.view??null,isPending:o.isPending,failed:o.error!==null});_!==g&&m(_)}let y=g?.view??a?.view??d?.view??null,v=a??d,I=a===null&&o.data!==null&&!o.isPending,E=c==="lark"?{command:ze,descriptionKey:K.descriptionKey}:c==="wecom"?{command:Qe,descriptionKey:"wecomSetup.action.description"}:null,U=M(()=>Je(v?.targetColumns??[],y?.bots??[],_=>n(`platform.${_}`)),[v,y,n]);function W(_){m({view:_,phase:"asked"}),o.refresh()}function ne(){m(null),o.refresh()}let j;if(o.isUnavailable)j=i(Be,{variant:"warning",message:n("settingsSection.unavailable"),retryLabel:n("settingsSection.retry"),onRetry:ne});else if(y===null&&o.isPending)j=i("div",{className:"im-pending",children:i(F,{size:"md"})});else if(y===null||v===null)j=i(Be,{variant:"error",message:n("settingsSection.loadFailed"),retryLabel:n("settingsSection.retry"),onRetry:ne});else{let _=y.bots.length===0&&!f;j=s(An,{activeId:k,activate:L,children:[o.error!==null||I?i(Be,{variant:"error",message:n("settingsSection.loadFailed"),retryLabel:n("settingsSection.retry"),onRetry:ne}):null,i(Ln,{view:y,environmentId:e.environmentId,bridge:e.bridge,t:n,onSaved:W}),y.bots.map(N=>i(Pe,{bot:N,bots:y.bots,connections:r,columns:v.columns,proxies:v.proxies,environmentId:e.environmentId,bridge:e.bridge,t:n,onSaved:W,onDiscard:()=>{}},N.rowId)),f?i(Pe,{bot:null,bots:y.bots,connections:r,columns:v.columns,proxies:v.proxies,environmentId:e.environmentId,bridge:e.bridge,t:n,onSaved:N=>{h(!1),W(N)},onDiscard:()=>h(!1)},we.newSlot):null,_?i(mn,{title:n("settingsSection.empty"),description:n("settingsSection.emptyGuide",{larkLabel:n(K.labelKey),wecomLabel:n("wecomSetup.action.label"),addBotLabel:n("settingsSection.addBot")})}):null,s("div",{className:"im-actions",children:[i(p,{variant:"outline",disabled:f,onClick:()=>{h(!0),L(Z(we.newSlot,null))},children:n("settingsSection.addBot")}),s(p,{variant:_?"default":"outline",disabled:c!==null,onClick:()=>x("lark"),children:[n(K.labelKey),i("span",{className:_?"im-badge im-badge-on-primary im-small":"im-badge im-small",children:n(K.badgeKey)})]}),s(p,{variant:"outline",disabled:c!==null,onClick:()=>x("wecom"),children:[n("wecomSetup.action.label"),i("span",{className:"im-badge im-small",children:n(K.badgeKey)})]})]}),i("p",{className:"im-small im-muted",children:n(K.warningKey)}),E?s("section",{className:"im-block",children:[i("p",{className:"im-small im-muted",children:n(E.descriptionKey)}),i(pe,{bridge:e.bridge,command:E.command,payload:Oe,items:"snapshots",environmentId:e.environmentId,t:n,onSettled:N=>{N.kind==="done"&&ne()},onClose:()=>x(null)})]}):null,i("h3",{className:"im-heading im-medium",children:n("settings.deliveryTargets.label")}),i("p",{className:"im-small im-muted",children:n("settingsSection.target.description")}),y.targets.map(N=>i(Ae,{target:N,columns:U,proxies:v.proxies,environmentId:e.environmentId,bridge:e.bridge,t:n,onSaved:W,onDiscard:()=>{}},N.rowId)),b?i(Ae,{target:null,columns:U,proxies:v.proxies,environmentId:e.environmentId,bridge:e.bridge,t:n,onSaved:N=>{w(!1),W(N)},onDiscard:()=>w(!1)},Ce.newSlot):null,i("div",{className:"im-actions",children:i(p,{variant:"outline",disabled:b,onClick:()=>{w(!0),L(Z(Ce.newSlot,null))},children:n("settingsSection.target.add")})})]})}let te=r===null?null:tn(y?.bots??[],r);return i(dn,{bridge:e.bridge,children:s("div",{className:"im-settings",children:[i("style",{children:Mn}),s("div",{className:"im-head",children:[i("h2",{className:"im-heading im-medium im-title",children:n("settings.title")}),te!==null&&te.configured>0?i(ue,{tone:"neutral","aria-label":n("settingsSection.onlineLabel",te),children:n("settingsSection.online",te)}):null]}),j]})})}function Be(e){return s(H,{variant:e.variant,layout:"inline",children:[i(z,{children:e.message}),i(gn,{children:i(p,{variant:"ghost",size:"sm",onClick:e.onRetry,children:e.retryLabel})})]})}function Xn(e){return{slots:[{name:"settings.section",order:20,component(n){return i(Kn,{bridge:e,environmentId:n.environmentId??null},n.environmentId??"")}}]}}export{Xn as default};
package/dist/index.js CHANGED
@@ -127265,6 +127265,68 @@ var buildDeliverySettingsFields = () => [
127265
127265
  }
127266
127266
  ];
127267
127267
 
127268
+ // src/modelChoice.ts
127269
+ var MODEL_LIST_MAX = 30;
127270
+ var parseModelValue = (value2) => {
127271
+ const separator = value2.indexOf("/");
127272
+ return separator <= 0 || separator === value2.length - 1 ? null : { instanceId: value2.slice(0, separator), model: value2.slice(separator + 1) };
127273
+ };
127274
+ var modelValue = (selection) => selection === null ? "" : `${selection.instanceId}/${selection.model}`;
127275
+ var isModelCatalogComplete = (instances) => instances !== null && instances.every((instance) => !instance.enabled || instance.models !== void 0);
127276
+ var modelChoices = (instances) => instances.flatMap(
127277
+ (instance) => instance.enabled ? (instance.models ?? []).map(
127278
+ (model) => ({
127279
+ instanceId: instance.instanceId,
127280
+ model: model.slug,
127281
+ instanceName: instance.displayName ?? instance.instanceId,
127282
+ modelName: model.name === "" ? model.slug : model.name
127283
+ })
127284
+ ) : []
127285
+ );
127286
+ var modelLabel = (choice) => `${choice.instanceName} \xB7 ${choice.modelName}`;
127287
+ var rawModelLabel = (selection) => `${selection.instanceId} \xB7 ${selection.model}`;
127288
+ var sameModel = (left, right) => left.instanceId === right.instanceId && left.model === right.model;
127289
+ var modelCatalogHas = (choices, selection) => choices.some((choice) => sameModel(choice, selection));
127290
+ var formatModels = (current, choices, t) => {
127291
+ const currentLabel = current === null ? t("model.currentUnknown") : t("model.current", {
127292
+ model: modelLabel(
127293
+ choices.find((choice) => sameModel(choice, current)) ?? {
127294
+ instanceName: current.instanceId,
127295
+ modelName: current.model
127296
+ }
127297
+ )
127298
+ });
127299
+ if (choices.length === 0) return [currentLabel, t("model.unavailable")].join("\n");
127300
+ const shown = choices.slice(0, MODEL_LIST_MAX);
127301
+ return [
127302
+ currentLabel,
127303
+ "",
127304
+ t("model.listTitle"),
127305
+ ...shown.map(
127306
+ (choice, index) => `${String(index + 1)}. ${current !== null && sameModel(choice, current) ? "\u2605 " : ""}${modelLabel(choice)}`
127307
+ ),
127308
+ ...choices.length > shown.length ? [t("model.more", { count: choices.length - shown.length })] : [],
127309
+ "",
127310
+ t("model.footer")
127311
+ ].join("\n");
127312
+ };
127313
+ var pickModel = (arg, choices) => {
127314
+ const wanted = arg.trim();
127315
+ if (wanted === "") return null;
127316
+ if (/^\d+$/.test(wanted)) return choices.slice(0, MODEL_LIST_MAX)[Number(wanted) - 1] ?? null;
127317
+ const needle = wanted.toLowerCase();
127318
+ const selection = parseModelValue(needle);
127319
+ const qualified = choices.filter(
127320
+ (choice) => selection !== null && choice.instanceId.toLowerCase() === selection.instanceId && (choice.model.toLowerCase() === selection.model || choice.modelName.toLowerCase() === selection.model)
127321
+ );
127322
+ if (qualified.length === 1) return qualified[0] ?? null;
127323
+ if (qualified.length > 1) return null;
127324
+ const named = choices.filter(
127325
+ (choice) => choice.model.toLowerCase() === needle || choice.modelName.toLowerCase() === needle
127326
+ );
127327
+ return named.length === 1 ? named[0] ?? null : null;
127328
+ };
127329
+
127268
127330
  // src/botConfig.ts
127269
127331
  var BOTS_FIELD = "bots";
127270
127332
  var REPLY_LANGUAGE_FIELD = "replyLanguage";
@@ -127284,7 +127346,9 @@ var QUEUE_MODES = new Set(QUEUE_MODE_OPTIONS.map((option2) => option2.value));
127284
127346
  var DEFAULT_QUEUE_MODE = "queue";
127285
127347
  var ACCESS_MODE_OPTIONS = [
127286
127348
  { value: "allowlist", labelKey: "settings.accessMode.allowlist" },
127287
- { value: "open", labelKey: "settings.accessMode.open" }
127349
+ { value: "open", labelKey: "settings.accessMode.open" },
127350
+ { value: "privateOpen", labelKey: "settings.accessMode.privateOpen" },
127351
+ { value: "groupOpen", labelKey: "settings.accessMode.groupOpen" }
127288
127352
  ];
127289
127353
  var ACCESS_MODES = new Set(
127290
127354
  ACCESS_MODE_OPTIONS.map((option2) => option2.value)
@@ -127308,7 +127372,7 @@ var parseOnOff = (value2, defaultOn) => {
127308
127372
  if (value2 === "off") return false;
127309
127373
  return defaultOn;
127310
127374
  };
127311
- var buildBotColumns = (adapters) => {
127375
+ var buildBotColumns = (adapters, models = [], catalogComplete = true) => {
127312
127376
  const platformColumn = {
127313
127377
  key: "platform",
127314
127378
  group: "essential",
@@ -127351,8 +127415,14 @@ var buildBotColumns = (adapters) => {
127351
127415
  kind: "text",
127352
127416
  labelKey: "column.allowedSenders.label",
127353
127417
  descriptionKey: "column.allowedSenders.description",
127354
- // 缺省/空串=allowlist(与 parseAccessMode 一致),仍显示白名单框。
127355
- showWhen: { key: "accessMode", equals: ["allowlist", ""] }
127418
+ // 除了两边都放开的 open,哪一档都至少有一边按名单;缺省/空串=allowlist,也显示。
127419
+ showWhen: {
127420
+ key: "accessMode",
127421
+ equals: [
127422
+ ...ACCESS_MODE_OPTIONS.flatMap(({ value: value2 }) => value2 === "open" ? [] : [value2]),
127423
+ ""
127424
+ ]
127425
+ }
127356
127426
  },
127357
127427
  {
127358
127428
  // 选项由宿主填,连三态一起——插件只声明「这个格子装的是代理」,宿主因此
@@ -127363,6 +127433,22 @@ var buildBotColumns = (adapters) => {
127363
127433
  labelKey: "column.proxy.label",
127364
127434
  descriptionKey: "column.proxy.description"
127365
127435
  },
127436
+ {
127437
+ key: "defaultModel",
127438
+ group: "more",
127439
+ kind: "select",
127440
+ listsUnknownValue: true,
127441
+ labelKey: "column.defaultModel.label",
127442
+ descriptionKey: "column.defaultModel.description",
127443
+ ...catalogComplete ? { unavailableLabelKey: "settings.defaultModel.unavailable" } : {},
127444
+ options: [
127445
+ { value: "", labelKey: "settings.defaultModel.follow" },
127446
+ ...models.map((choice) => ({
127447
+ value: modelValue(choice),
127448
+ label: modelLabel(choice)
127449
+ }))
127450
+ ]
127451
+ },
127366
127452
  {
127367
127453
  key: "runtimeMode",
127368
127454
  group: "more",
@@ -127461,10 +127547,12 @@ var readBot = (adapterFor, rowId, row) => {
127461
127547
  const adapter = adapterFor(platform);
127462
127548
  if (adapter === void 0) return null;
127463
127549
  const requested = readString(row, "runtimeMode");
127550
+ const defaultModel = parseModelValue(readString(row, "defaultModel"));
127464
127551
  const allowedSenders = new Set(parseAllowedSenders(readString(row, "allowedSenders")));
127465
127552
  const bot = {
127466
127553
  ...readBotView(rowId, row, adapter),
127467
127554
  platform,
127555
+ ...defaultModel === null ? {} : { defaultModel },
127468
127556
  accessMode: parseAccessMode(readString(row, "accessMode")),
127469
127557
  allowedSenders,
127470
127558
  runtimeMode: INBOUND_RUNTIME_MODES.has(requested) ? requested : DEFAULT_INBOUND_RUNTIME_MODE,
@@ -127493,9 +127581,10 @@ var findBindingByChatKey = (bots, state, chatKey) => {
127493
127581
  const bot = bots.find((candidate) => isChatKeyOfRow(chatKey, candidate.rowId));
127494
127582
  return bot === void 0 ? void 0 : bindingOf(bot, chatKey.slice(bot.rowId.length + 1), state);
127495
127583
  };
127496
- var isAllowedSender = (bot, sender) => {
127584
+ var isAllowedSender = (bot, sender, chatKind) => {
127497
127585
  if (sender === null || sender === "") return false;
127498
- if (bot.accessMode === "open") return true;
127586
+ if (bot.accessMode === "open" || bot.accessMode === "privateOpen" && chatKind === "private" || bot.accessMode === "groupOpen" && chatKind === "group")
127587
+ return true;
127499
127588
  return bot.allowedSenders.has(sender);
127500
127589
  };
127501
127590
 
@@ -127640,7 +127729,7 @@ var makeApprovals = (core, anchors) => {
127640
127729
  if (found === void 0) return null;
127641
127730
  if (found.approval.resolved) return t("approval.alreadyHandled");
127642
127731
  const target2 = bindingForChatKey(found.approval.chatKey);
127643
- if (target2 === void 0 || !isAllowedSender(target2, operatorId)) {
127732
+ if (target2 === void 0 || !isAllowedSender(target2, operatorId, chatOf(core.state, found.approval.chatKey).chatKind)) {
127644
127733
  host.log.warn("chat ignored an approval click from someone not on the allow list", {
127645
127734
  bot: target2?.displayName ?? found.approval.chatKey,
127646
127735
  operator: operatorId
@@ -133302,60 +133391,6 @@ var helpText = (t, options = {}) => [
133302
133391
  ...options.panel === true ? ["", t("help.panel")] : []
133303
133392
  ].join("\n");
133304
133393
 
133305
- // src/modelChoice.ts
133306
- var MODEL_LIST_MAX = 30;
133307
- var modelChoices = (instances) => instances.flatMap(
133308
- (instance) => instance.enabled ? (instance.models ?? []).map(
133309
- (model) => ({
133310
- instanceId: instance.instanceId,
133311
- model: model.slug,
133312
- instanceName: instance.displayName ?? instance.instanceId,
133313
- modelName: model.name === "" ? model.slug : model.name
133314
- })
133315
- ) : []
133316
- );
133317
- var modelLabel = (choice) => `${choice.instanceName} \xB7 ${choice.modelName}`;
133318
- var rawModelLabel = (selection) => `${selection.instanceId} \xB7 ${selection.model}`;
133319
- var sameModel = (left, right) => left.instanceId === right.instanceId && left.model === right.model;
133320
- var formatModels = (current, choices, t) => {
133321
- const currentLabel = current === null ? t("model.currentUnknown") : t("model.current", {
133322
- model: modelLabel(
133323
- choices.find((choice) => sameModel(choice, current)) ?? {
133324
- instanceName: current.instanceId,
133325
- modelName: current.model
133326
- }
133327
- )
133328
- });
133329
- if (choices.length === 0) return [currentLabel, t("model.unavailable")].join("\n");
133330
- const shown = choices.slice(0, MODEL_LIST_MAX);
133331
- return [
133332
- currentLabel,
133333
- "",
133334
- t("model.listTitle"),
133335
- ...shown.map(
133336
- (choice, index) => `${String(index + 1)}. ${current !== null && sameModel(choice, current) ? "\u2605 " : ""}${modelLabel(choice)}`
133337
- ),
133338
- ...choices.length > shown.length ? [t("model.more", { count: choices.length - shown.length })] : [],
133339
- "",
133340
- t("model.footer")
133341
- ].join("\n");
133342
- };
133343
- var pickModel = (arg, choices) => {
133344
- const wanted = arg.trim();
133345
- if (wanted === "") return null;
133346
- if (/^\d+$/.test(wanted)) return choices.slice(0, MODEL_LIST_MAX)[Number(wanted) - 1] ?? null;
133347
- const needle = wanted.toLowerCase();
133348
- const qualified = choices.filter(
133349
- (choice) => `${choice.instanceId}/${choice.model}`.toLowerCase() === needle || `${choice.instanceId}/${choice.modelName}`.toLowerCase() === needle
133350
- );
133351
- if (qualified.length === 1) return qualified[0] ?? null;
133352
- if (qualified.length > 1) return null;
133353
- const named = choices.filter(
133354
- (choice) => choice.model.toLowerCase() === needle || choice.modelName.toLowerCase() === needle
133355
- );
133356
- return named.length === 1 ? named[0] ?? null : null;
133357
- };
133358
-
133359
133394
  // src/commands.ts
133360
133395
  var NEEDS_PROJECT_COMMANDS = /* @__PURE__ */ new Set(["sessions", "resume", "selectTeam", "selectThread"]);
133361
133396
  var makeCommands = (core, deps) => {
@@ -134314,8 +134349,8 @@ var startConnections = (core, inboundHandlersFor, inboundState, recovery) => {
134314
134349
  },
134315
134350
  onButton: (...args2) => closed || disposed ? null : inbound.onButton(...args2),
134316
134351
  onPanelClick: (click) => closed || disposed ? null : inbound.onPanelClick?.(click) ?? null,
134317
- onGreeting: (chatId, senderId) => {
134318
- if (!closed && !disposed) inbound.onGreeting?.(chatId, senderId);
134352
+ onGreeting: (chatId, senderId, chatKind) => {
134353
+ if (!closed && !disposed) inbound.onGreeting?.(chatId, senderId, chatKind);
134319
134354
  },
134320
134355
  onConnectionState: (status) => {
134321
134356
  if (closed) return;
@@ -134910,6 +134945,17 @@ var diagnosticRef = (kind, nowMs = Date.now()) => {
134910
134945
  const stamp = nowMs.toString(36).toUpperCase();
134911
134946
  return `${PREFIX[kind]}-${stamp}-${shortSalt()}`;
134912
134947
  };
134948
+ var reportOf = (bot, stage, ok, detail, hint) => ({
134949
+ ref: diagnosticRef("conn"),
134950
+ platform: bot.platform,
134951
+ botName: bot.displayName,
134952
+ rowId: bot.rowId,
134953
+ stage,
134954
+ ok,
134955
+ detail,
134956
+ at: (/* @__PURE__ */ new Date()).toISOString(),
134957
+ ...hint === void 0 ? {} : { hint }
134958
+ });
134913
134959
  var formatDiagnosticCopy = (report) => [
134914
134960
  `ok=${report.ok ? "yes" : "no"}`,
134915
134961
  `platform=${report.platform}`,
@@ -135535,18 +135581,60 @@ var makeInboxReplay = (core, currentBot, state, enqueueForChat, resumeMessage, c
135535
135581
  };
135536
135582
  };
135537
135583
 
135584
+ // src/connectionTest.ts
135585
+ var connectionTestMessage = (t, botName, platformLabel) => t("reply.connectionTest", { name: botName.trim() || platformLabel });
135586
+ var makeConnectionTests = (t) => {
135587
+ const targets = /* @__PURE__ */ new Map();
135588
+ return {
135589
+ remember: (current, message, key) => {
135590
+ if (message.chatKind !== "private" || !isAllowedSender(current, message.senderId, message.chatKind))
135591
+ return;
135592
+ targets.set(current.rowId, { chatId: message.chatId, key });
135593
+ },
135594
+ retainRows: (rowIds) => {
135595
+ const kept = new Set(rowIds);
135596
+ for (const rowId of targets.keys()) if (!kept.has(rowId)) targets.delete(rowId);
135597
+ },
135598
+ send: async (bot, adapter) => {
135599
+ const remembered = targets.get(bot.rowId);
135600
+ if (remembered === void 0 || remembered.key !== connectionKey(adapter, bot))
135601
+ return { sent: false, code: "test-target-unavailable" };
135602
+ try {
135603
+ await adapter.sendText(
135604
+ { ...bot, chatId: remembered.chatId },
135605
+ connectionTestMessage(t, bot.displayName, adapter.label)
135606
+ );
135607
+ return { sent: true };
135608
+ } catch (error) {
135609
+ return {
135610
+ sent: false,
135611
+ code: "test-message-failed",
135612
+ error: reportOf(
135613
+ bot,
135614
+ "connection.test",
135615
+ false,
135616
+ botRedactor(adapter.columns, bot.values).redact(describeError(error))
135617
+ )
135618
+ };
135619
+ }
135620
+ }
135621
+ };
135622
+ };
135623
+
135538
135624
  // src/greetings.ts
135539
135625
  var GREETING_COOLDOWN_MS = 12 * 60 * 6e4;
135540
135626
  var GREETING_KEY_LIMIT = 1e3;
135541
135627
  var makeGreetings = (core, enqueueForChat, now) => {
135542
135628
  const cooldown = makeCooldown(GREETING_COOLDOWN_MS, now, GREETING_KEY_LIMIT);
135543
- return (rowId, chatId, senderId) => {
135629
+ return (rowId, chatId, senderId, eventChatKind) => {
135630
+ const chatKey = chatKeyOf({ rowId, chatId });
135631
+ const chatKind = () => eventChatKind ?? chatOf(core.state, chatKey).chatKind;
135544
135632
  const bot = core.bots().find((candidate) => candidate.rowId === rowId);
135545
- if (bot === void 0 || !isAllowedSender(bot, senderId)) return;
135633
+ if (bot === void 0 || !isAllowedSender(bot, senderId, chatKind())) return;
135546
135634
  if (!cooldown.tryAcquire(`${rowId}:${senderId}`)) return;
135547
- enqueueForChat(chatKeyOf({ rowId, chatId }), async () => {
135635
+ enqueueForChat(chatKey, async () => {
135548
135636
  const current = core.bots().find((candidate) => candidate.rowId === rowId);
135549
- if (current === void 0 || !isAllowedSender(current, senderId)) return;
135637
+ if (current === void 0 || !isAllowedSender(current, senderId, chatKind())) return;
135550
135638
  await core.deliver(core.bindingOf(current, chatId), core.t("reply.welcome"));
135551
135639
  });
135552
135640
  };
@@ -135599,6 +135687,7 @@ var NOT_ALLOWED_REPLY_KEY_LIMIT = 1e3;
135599
135687
  var makeInbound = (core, deps) => {
135600
135688
  const { host, t, adapterFor, commit, deliver, bindingOf: bindingOf2, bots } = core;
135601
135689
  const { enqueueForChat } = deps;
135690
+ const connectionTests = makeConnectionTests(t);
135602
135691
  const now = deps.now ?? deps.retryClock?.now ?? (() => Date.now());
135603
135692
  const greet = makeGreetings(core, enqueueForChat, now);
135604
135693
  const { targetOf } = deps.commands;
@@ -135759,7 +135848,7 @@ var makeInbound = (core, deps) => {
135759
135848
  await execute(work.route);
135760
135849
  return;
135761
135850
  }
135762
- if (!isAllowedSender(target2, message.senderId)) {
135851
+ if (!isAllowedSender(target2, message.senderId, message.chatKind)) {
135763
135852
  await saveRoute({ kind: "unavailable" });
135764
135853
  await complete();
135765
135854
  turnAwayStranger(target2, message.senderId);
@@ -135817,7 +135906,7 @@ var makeInbound = (core, deps) => {
135817
135906
  },
135818
135907
  noteChatAlias: (alias, chatId) => noteChatAlias(bot, alias, chatId),
135819
135908
  knowsChatAlias: (alias) => chatAliasOf(core.state, bot.rowId, alias) !== void 0,
135820
- onGreeting: (chatId, senderId) => greet(bot.rowId, chatId, senderId),
135909
+ onGreeting: (chatId, senderId, chatKind) => greet(bot.rowId, chatId, senderId, chatKind),
135821
135910
  onMessage: async (received) => {
135822
135911
  const current = currentBot(bot.rowId);
135823
135912
  if (!accepting || current === void 0) throw new Error("inbound is not accepting messages");
@@ -135835,6 +135924,9 @@ var makeInbound = (core, deps) => {
135835
135924
  }
135836
135925
  const claim = inboundState.claimReceipt(current.rowId, work.key, saved, now());
135837
135926
  if (!claim.first) return claim.persisted;
135927
+ const receivedAdapter = adapterFor(bot.platform);
135928
+ if (receivedAdapter !== void 0)
135929
+ connectionTests.remember(current, message, connectionKey(receivedAdapter, bot));
135838
135930
  const receipt = claim.persisted.catch((error) => {
135839
135931
  inboundState.abandon(current.rowId, work.key);
135840
135932
  host.log.warn(
@@ -135877,6 +135969,7 @@ var makeInbound = (core, deps) => {
135877
135969
  replay.enqueue(rowId, entry.key, ready, { entry, message: messages.get(entry.key) });
135878
135970
  };
135879
135971
  return {
135972
+ connectionTests,
135880
135973
  inboundHandlersFor,
135881
135974
  resumeMessage,
135882
135975
  enqueueReplay,
@@ -136505,7 +136598,8 @@ var makeInteractions = (core, deps) => {
136505
136598
  anchored: (binding, threadId) => deps.anchors.anchored(binding, threadId, null),
136506
136599
  allowed: (chatKey, operatorId) => {
136507
136600
  const binding = bindingForChatKey(chatKey);
136508
- if (binding !== void 0 && isAllowedSender(binding, operatorId)) return true;
136601
+ if (binding !== void 0 && isAllowedSender(binding, operatorId, chatOf(core.state, chatKey).chatKind))
136602
+ return true;
136509
136603
  host.log.warn("chat ignored a button click from someone not on the allow list", {
136510
136604
  bot: binding?.displayName ?? chatKey,
136511
136605
  operator: operatorId
@@ -145331,7 +145425,7 @@ var en_default = {
145331
145425
  },
145332
145426
  settings: {
145333
145427
  title: "Chat",
145334
- description: "Connect chat bots to Ycodium. One row per bot: create the bot on its platform, paste its credentials, and pick an access mode (allowlist / open). In allowlist mode, list the people allowed to use it. For Lark, Connect a Lark bot does all of that with one scan. Admitted people message the bot (or add it to a group), pick a project in the chat, and can start work.",
145428
+ description: 'Connect chat bots to Ycodium. One row per bot: create the bot on its platform, paste its credentials, and pick one access mode that decides who can use it in private chats and groups. Where the allowlist applies, list the people in "Allowed people". For Lark, Connect a Lark bot does all of that with one scan. Admitted people message the bot (or add it to a group), pick a project in the chat, and can start work.',
145335
145429
  bots: "Bots",
145336
145430
  language: {
145337
145431
  label: "Reply language",
@@ -145339,6 +145433,10 @@ var en_default = {
145339
145433
  zhCN: "\u4E2D\u6587",
145340
145434
  en: "English"
145341
145435
  },
145436
+ defaultModel: {
145437
+ follow: "Follow chat / project default",
145438
+ unavailable: "{{value}} (unavailable)"
145439
+ },
145342
145440
  runtimeMode: {
145343
145441
  approvalRequired: "Ask before commands and file changes",
145344
145442
  autoAcceptEdits: "Auto-accept edits, ask before other actions",
@@ -145387,7 +145485,9 @@ var en_default = {
145387
145485
  },
145388
145486
  accessMode: {
145389
145487
  allowlist: "Allowlist only (default)",
145390
- open: "Allow everyone"
145488
+ open: "Allow everyone",
145489
+ privateOpen: "Private chats: open; groups: allowlist",
145490
+ groupOpen: "Private chats: allowlist; groups: open"
145391
145491
  }
145392
145492
  },
145393
145493
  platform: {
@@ -145423,12 +145523,16 @@ var en_default = {
145423
145523
  },
145424
145524
  allowedSenders: {
145425
145525
  label: "Allowed people",
145426
- description: "Comma-separated user ids from that platform. Used only in allowlist mode; while the list is empty, nobody can. Message the bot and it tells you your own id."
145526
+ description: "Comma-separated user ids from that platform. Used in chats where the access mode requires the allowlist; while the list is empty, nobody can use the bot in those chats. To find an id: from an account not yet on the list, message the bot in a chat that requires the allowlist (mention it in a group). The bot replies with the id, at most once every 10 minutes per account."
145427
145527
  },
145428
145528
  proxy: {
145429
145529
  label: "Proxy",
145430
145530
  description: "Some platforms are only reachable through a proxy on this machine, and which one can differ per bot."
145431
145531
  },
145532
+ defaultModel: {
145533
+ label: "Default model",
145534
+ description: "Used for new sessions when the chat has no /model selection. Existing sessions keep their model; send /new to use this default. Unavailable choices fall back to the project default."
145535
+ },
145432
145536
  runtimeMode: {
145433
145537
  label: "What a chat message may do",
145434
145538
  description: "Admitted people start turns from chat, so this is deliberately not full access by default. Whichever mode asks, the request lands in the chat."
@@ -145519,11 +145623,12 @@ var en_default = {
145519
145623
  },
145520
145624
  accessMode: {
145521
145625
  label: "Access mode",
145522
- description: 'Allowlist admits only "Allowed people"; open admits any identifiable sender. New bots default to allowlist.'
145626
+ description: 'Allowlist admits only "Allowed people"; open admits any identifiable sender. New bots default to allowlist. "Private chats: open; groups: allowlist" and "Private chats: allowlist; groups: open" share the same "Allowed people"; in either of them, when the chat type cannot be confirmed, only "Allowed people" can use the bot.'
145523
145627
  }
145524
145628
  },
145525
145629
  reply: {
145526
145630
  deliveryFailed: "The reply could not be delivered. Check this bot's connection and permissions, then try again.",
145631
+ connectionTest: "\u2705 Ycodium connection test\nThis test message was sent by \u201C{{name}}\u201D using Check connection in Settings. No reply needed.",
145527
145632
  wecomDeliveryFailed: "This reply didn't reach {{recipient}} in WeCom: they are outside this app's visible range. Add them to the app's visible range in the WeCom admin console, then ask the agent to send it again.",
145528
145633
  conclusionRecovered: "(Finished while restarting; delivered now)",
145529
145634
  notAllowed: "You are not on this bot's allow list, so this tap had no effect.",
@@ -145920,11 +146025,20 @@ var en_default = {
145920
146025
  rowAction: {
145921
146026
  checkConnection: {
145922
146027
  label: "Check connection",
145923
- description: "Verify platform credentials still work; does not open a session or call a model.",
146028
+ description: "Verify credentials and send a test message to the most recent private chat; does not open a session or call a model.",
145924
146029
  running: "Checking {{rowId}}\u2026",
145925
146030
  done: "Connection OK",
146031
+ doneTestFailed: "Credentials OK, but the test message was not sent",
146032
+ doneNoTarget: "Credentials OK, but no test message was sent",
145926
146033
  failed: "Connection failed",
145927
146034
  notSaved: "Save this row first (credentials are read from saved config only).",
146035
+ credentialRef: "Credential check reference: {{ref}}\n{{detail}}",
146036
+ testMessage: {
146037
+ sent: "Sent to whoever last messaged the bot privately. Ask them to confirm.",
146038
+ "test-target-unavailable": "No private chat to test with yet. Message the bot privately from an account allowed to use the bot, then check again.",
146039
+ "test-message-failed": "Check that the bot can still send to that private chat (reason below), then check again.",
146040
+ ref: "Test message reference: {{ref}}\n{{detail}}"
146041
+ },
145928
146042
  hint: {
145929
146043
  networkMultipleCauses: "This failure has more than one network cause. Check this machine's network and this bot's Proxy setting, then check again.",
145930
146044
  networkDns: "The service's domain name could not be resolved. Check this machine's DNS and network settings, then check again.",
@@ -146186,7 +146300,7 @@ var zh_CN_default = {
146186
146300
  },
146187
146301
  settings: {
146188
146302
  title: "\u804A\u5929",
146189
- description: "\u628A\u804A\u5929\u673A\u5668\u4EBA\u63A5\u5230 Ycodium\u3002\u4E00\u884C\u4E00\u4E2A\u673A\u5668\u4EBA\uFF1A\u5148\u5728\u5BF9\u5E94\u5E73\u53F0\u5EFA\u597D\u673A\u5668\u4EBA\u3001\u628A\u51ED\u636E\u586B\u8FDB\u6765\uFF0C\u518D\u9009\u8BBF\u95EE\u6A21\u5F0F\uFF08\u4EC5\u767D\u540D\u5355\uFF0F\u5141\u8BB8\u6240\u6709\u4EBA\uFF09\u3002\u4EC5\u767D\u540D\u5355\u65F6\u628A\u5141\u8BB8\u4F7F\u7528\u5B83\u7684\u4EBA\u586B\u8FDB\u300C\u5141\u8BB8\u7684\u4EBA\u300D\u3002\u98DE\u4E66\u53EF\u4EE5\u7528\u300C\u8FDE\u63A5\u98DE\u4E66\u673A\u5668\u4EBA\u300D\uFF0C\u626B\u4E00\u6B21\u7801\u5168\u90E8\u914D\u597D\u3002\u83B7\u51C6\u7684\u4EBA\u79C1\u804A\u673A\u5668\u4EBA\uFF08\u6216\u628A\u5B83\u62C9\u8FDB\u7FA4\uFF09\u3001\u5728\u804A\u5929\u91CC\u9009\u597D\u9879\u76EE\uFF0C\u5C31\u80FD\u6D3E\u6D3B\u3002",
146303
+ description: "\u628A\u804A\u5929\u673A\u5668\u4EBA\u63A5\u5230 Ycodium\u3002\u4E00\u884C\u4E00\u4E2A\u673A\u5668\u4EBA\uFF1A\u5148\u5728\u5BF9\u5E94\u5E73\u53F0\u5EFA\u597D\u673A\u5668\u4EBA\u3001\u628A\u51ED\u636E\u586B\u8FDB\u6765\uFF0C\u518D\u9009\u4E00\u4E2A\u8BBF\u95EE\u6A21\u5F0F\uFF0C\u51B3\u5B9A\u79C1\u804A\u548C\u7FA4\u91CC\u8C01\u80FD\u7528\uFF1B\u7528\u5230\u540D\u5355\u65F6\uFF0C\u628A\u4EBA\u586B\u8FDB\u300C\u5141\u8BB8\u7684\u4EBA\u300D\u3002\u98DE\u4E66\u53EF\u4EE5\u7528\u300C\u8FDE\u63A5\u98DE\u4E66\u673A\u5668\u4EBA\u300D\uFF0C\u626B\u4E00\u6B21\u7801\u5168\u90E8\u914D\u597D\u3002\u83B7\u51C6\u7684\u4EBA\u79C1\u804A\u673A\u5668\u4EBA\uFF08\u6216\u628A\u5B83\u62C9\u8FDB\u7FA4\uFF09\u3001\u5728\u804A\u5929\u91CC\u9009\u597D\u9879\u76EE\uFF0C\u5C31\u80FD\u6D3E\u6D3B\u3002",
146190
146304
  bots: "\u673A\u5668\u4EBA",
146191
146305
  language: {
146192
146306
  label: "\u56DE\u8BDD\u8BED\u8A00",
@@ -146194,6 +146308,10 @@ var zh_CN_default = {
146194
146308
  zhCN: "\u4E2D\u6587",
146195
146309
  en: "English"
146196
146310
  },
146311
+ defaultModel: {
146312
+ follow: "\u8DDF\u968F\u804A\u5929 / \u9879\u76EE\u9ED8\u8BA4",
146313
+ unavailable: "{{value}}\uFF08\u4E0D\u53EF\u7528\uFF09"
146314
+ },
146197
146315
  runtimeMode: {
146198
146316
  approvalRequired: "\u547D\u4EE4\u548C\u6539\u6587\u4EF6\u524D\u5148\u95EE",
146199
146317
  autoAcceptEdits: "\u81EA\u52A8\u63A5\u53D7\u6539\u52A8\uFF0C\u5176\u4ED6\u64CD\u4F5C\u5148\u95EE",
@@ -146242,7 +146360,9 @@ var zh_CN_default = {
146242
146360
  },
146243
146361
  accessMode: {
146244
146362
  allowlist: "\u4EC5\u767D\u540D\u5355\uFF08\u9ED8\u8BA4\uFF09",
146245
- open: "\u5141\u8BB8\u6240\u6709\u4EBA"
146363
+ open: "\u5141\u8BB8\u6240\u6709\u4EBA",
146364
+ privateOpen: "\u79C1\u804A\u653E\u5F00\uFF0C\u7FA4\u91CC\u9650\u540D\u5355",
146365
+ groupOpen: "\u79C1\u804A\u9650\u540D\u5355\uFF0C\u7FA4\u91CC\u653E\u5F00"
146246
146366
  }
146247
146367
  },
146248
146368
  platform: {
@@ -146278,12 +146398,16 @@ var zh_CN_default = {
146278
146398
  },
146279
146399
  allowedSenders: {
146280
146400
  label: "\u5141\u8BB8\u7684\u4EBA",
146281
- description: "\u8BE5\u5E73\u53F0\u7684\u7528\u6237 id\uFF0C\u9017\u53F7\u5206\u9694\u3002\u4EC5\u5728\u300C\u4EC5\u767D\u540D\u5355\u300D\u6A21\u5F0F\u4E0B\u751F\u6548\uFF1B\u7559\u7A7A\u5219\u8C01\u90FD\u4E0D\u80FD\u3002\u7ED9\u673A\u5668\u4EBA\u53D1\u4E00\u53E5\u8BDD\uFF0C\u5B83\u4F1A\u544A\u8BC9\u4F60\u81EA\u5DF1\u7684 id\u3002"
146401
+ description: "\u8BE5\u5E73\u53F0\u7684\u7528\u6237 id\uFF0C\u9017\u53F7\u5206\u9694\u3002\u5728\u8BBF\u95EE\u6A21\u5F0F\u8981\u6C42\u540D\u5355\u7684\u804A\u5929\u91CC\u751F\u6548\uFF1B\u7559\u7A7A\u5219\u8C01\u90FD\u4E0D\u80FD\u5728\u8FD9\u4E9B\u804A\u5929\u91CC\u4F7F\u7528\u673A\u5668\u4EBA\u3002\u67E5 id\uFF1A\u7528\u8FD8\u4E0D\u5728\u540D\u5355\u4E0A\u7684\u8D26\u53F7\uFF0C\u5728\u8981\u6C42\u540D\u5355\u7684\u804A\u5929\u91CC\u7ED9\u673A\u5668\u4EBA\u53D1\u4E00\u53E5\u8BDD\uFF08\u7FA4\u91CC\u8981 @ \u5B83\uFF09\uFF0C\u5B83\u4F1A\u56DE\u590D\u8FD9\u4E2A id\uFF1B\u540C\u4E00\u8D26\u53F7 10 \u5206\u949F\u5185\u53EA\u56DE\u4E00\u6B21\u3002"
146282
146402
  },
146283
146403
  proxy: {
146284
146404
  label: "\u4EE3\u7406",
146285
146405
  description: "\u6709\u4E9B\u5E73\u53F0\u53EA\u80FD\u7ECF\u672C\u673A\u4E0A\u7684\u67D0\u4E2A\u4EE3\u7406\u624D\u8FDE\u5F97\u4E0A\uFF0C\u800C\u4E14\u6BCF\u4E2A\u673A\u5668\u4EBA\u53EF\u4EE5\u4E0D\u4E00\u6837\u3002"
146286
146406
  },
146407
+ defaultModel: {
146408
+ label: "\u9ED8\u8BA4\u6A21\u578B",
146409
+ description: "\u804A\u5929\u672A\u7528 /model \u9009\u6A21\u578B\u65F6\uFF0C\u65B0\u4F1A\u8BDD\u4F7F\u7528\u6B64\u9ED8\u8BA4\u6A21\u578B\u3002\u5DF2\u6709\u4F1A\u8BDD\u4FDD\u7559\u539F\u6A21\u578B\uFF1B\u53D1\u9001 /new \u540E\u4F7F\u7528\u65B0\u9ED8\u8BA4\u3002\u4E0D\u53EF\u7528\u65F6\u56DE\u9000\u5230\u9879\u76EE\u9ED8\u8BA4\u3002"
146410
+ },
146287
146411
  runtimeMode: {
146288
146412
  label: "\u804A\u5929\u6D88\u606F\u80FD\u505A\u4EC0\u4E48",
146289
146413
  description: "\u83B7\u51C6\u7684\u4EBA\u90FD\u80FD\u4ECE\u804A\u5929\u91CC\u5F00\u4E00\u8F6E\uFF0C\u6240\u4EE5\u9ED8\u8BA4\u6545\u610F\u4E0D\u7ED9\u6EE1\u6743\u9650\u3002\u4E0D\u8BBA\u9009\u54EA\u4E00\u6863\uFF0C\u8981\u62CD\u677F\u7684\u4E8B\u90FD\u4F1A\u6446\u5230\u804A\u5929\u91CC\u3002"
@@ -146374,11 +146498,12 @@ var zh_CN_default = {
146374
146498
  },
146375
146499
  accessMode: {
146376
146500
  label: "\u8BBF\u95EE\u6A21\u5F0F",
146377
- description: "\u4EC5\u767D\u540D\u5355\uFF1D\u53EA\u6709\u300C\u5141\u8BB8\u7684\u4EBA\u300D\u80FD\u89E6\u53D1\uFF1B\u5141\u8BB8\u6240\u6709\u4EBA\uFF1D\u5E73\u53F0\u80FD\u8BC6\u522B\u7684\u53D1\u9001\u8005\u5747\u53EF\u3002\u65B0\u673A\u5668\u4EBA\u9ED8\u8BA4\u4EC5\u767D\u540D\u5355\u3002"
146501
+ description: "\u4EC5\u767D\u540D\u5355\uFF1D\u53EA\u6709\u300C\u5141\u8BB8\u7684\u4EBA\u300D\u80FD\u89E6\u53D1\uFF1B\u5141\u8BB8\u6240\u6709\u4EBA\uFF1D\u5E73\u53F0\u80FD\u8BC6\u522B\u7684\u53D1\u9001\u8005\u5747\u53EF\u3002\u65B0\u673A\u5668\u4EBA\u9ED8\u8BA4\u4EC5\u767D\u540D\u5355\u3002\u300C\u79C1\u804A\u653E\u5F00\uFF0C\u7FA4\u91CC\u9650\u540D\u5355\u300D\u4E0E\u300C\u79C1\u804A\u9650\u540D\u5355\uFF0C\u7FA4\u91CC\u653E\u5F00\u300D\u5171\u7528\u540C\u4E00\u4EFD\u300C\u5141\u8BB8\u7684\u4EBA\u300D\uFF1B\u8FD9\u4E24\u79CD\u6A21\u5F0F\u4E0B\uFF0C\u65E0\u6CD5\u786E\u8BA4\u662F\u79C1\u804A\u8FD8\u662F\u7FA4\u65F6\uFF0C\u53EA\u6709\u300C\u5141\u8BB8\u7684\u4EBA\u300D\u80FD\u7528\u673A\u5668\u4EBA\u3002"
146378
146502
  }
146379
146503
  },
146380
146504
  reply: {
146381
146505
  deliveryFailed: "\u56DE\u590D\u672A\u80FD\u9001\u8FBE\u3002\u8BF7\u68C0\u67E5\u8FD9\u4E2A\u673A\u5668\u4EBA\u7684\u8FDE\u63A5\u4E0E\u6743\u9650\uFF0C\u7136\u540E\u91CD\u8BD5\u3002",
146506
+ connectionTest: "\u2705 Ycodium \u8FDE\u63A5\u6D4B\u8BD5\n\u8FD9\u6761\u6D4B\u8BD5\u6D88\u606F\u7531\u300C{{name}}\u300D\u673A\u5668\u4EBA\u901A\u8FC7\u8BBE\u7F6E\u9875\u7684\u300C\u68C0\u67E5\u8FDE\u63A5\u300D\u53D1\u51FA\uFF0C\u65E0\u9700\u56DE\u590D\u3002",
146382
146507
  wecomDeliveryFailed: "\u8FD9\u6761\u56DE\u590D\u6CA1\u9001\u5230\u4F01\u4E1A\u5FAE\u4FE1\u91CC\u7684 {{recipient}}\uFF1A\u5BF9\u65B9\u4E0D\u5728\u8FD9\u4E2A\u5E94\u7528\u7684\u53EF\u89C1\u8303\u56F4\u3002\u5230\u4F01\u4E1A\u5FAE\u4FE1\u7BA1\u7406\u540E\u53F0\u628A\u4ED6\u4EEC\u52A0\u8FDB\u5E94\u7528\u7684\u53EF\u89C1\u8303\u56F4\uFF0C\u518D\u8BA9 agent \u91CD\u53D1\u4E00\u6B21\u3002",
146383
146508
  conclusionRecovered: "\uFF08\u91CD\u542F\u671F\u95F4\u5B8C\u6210\uFF0C\u73B0\u5728\u8865\u53D1\uFF09",
146384
146509
  notAllowed: "\u4F60\u4E0D\u5728\u8FD9\u4E2A\u673A\u5668\u4EBA\u7684\u5141\u8BB8\u540D\u5355\u91CC\uFF0C\u8FD9\u6B21\u70B9\u51FB\u6CA1\u6709\u751F\u6548\u3002",
@@ -146775,11 +146900,20 @@ var zh_CN_default = {
146775
146900
  rowAction: {
146776
146901
  checkConnection: {
146777
146902
  label: "\u68C0\u67E5\u8FDE\u63A5",
146778
- description: "\u9A8C\u8BC1\u5E73\u53F0\u51ED\u636E\u662F\u5426\u4ECD\u53EF\u7528\uFF1B\u4E0D\u4F1A\u5F00\u4F1A\u8BDD\uFF0C\u4E5F\u4E0D\u4F1A\u8C03\u6A21\u578B\u3002",
146903
+ description: "\u9A8C\u8BC1\u5E73\u53F0\u51ED\u636E\uFF0C\u5E76\u5411\u6700\u8FD1\u7684\u79C1\u804A\u53D1\u4E00\u6761\u6D4B\u8BD5\u6D88\u606F\uFF1B\u4E0D\u4F1A\u5F00\u4F1A\u8BDD\uFF0C\u4E5F\u4E0D\u4F1A\u8C03\u6A21\u578B\u3002",
146779
146904
  running: "\u6B63\u5728\u68C0\u67E5 {{rowId}} \u2026",
146780
146905
  done: "\u8FDE\u63A5\u6B63\u5E38",
146906
+ doneTestFailed: "\u51ED\u636E\u6B63\u5E38\uFF0C\u4F46\u6D4B\u8BD5\u6D88\u606F\u6CA1\u53D1\u51FA\u53BB",
146907
+ doneNoTarget: "\u51ED\u636E\u6B63\u5E38\uFF0C\u4F46\u8FD8\u6CA1\u53D1\u6D4B\u8BD5\u6D88\u606F",
146781
146908
  failed: "\u8FDE\u63A5\u5931\u8D25",
146782
146909
  notSaved: "\u8BF7\u5148\u4FDD\u5B58\u8FD9\u4E00\u884C\u518D\u68C0\u67E5\u8FDE\u63A5\uFF08\u51ED\u636E\u53EA\u4ECE\u5DF2\u4FDD\u5B58\u914D\u7F6E\u8BFB\u53D6\uFF09\u3002",
146910
+ credentialRef: "\u51ED\u636E\u68C0\u67E5\u53C2\u8003\u53F7\uFF1A{{ref}}\n{{detail}}",
146911
+ testMessage: {
146912
+ sent: "\u5DF2\u53D1\u5230\u6700\u8FD1\u79C1\u804A\u8FC7\u673A\u5668\u4EBA\u7684\u4EBA\uFF0C\u8BF7\u5BF9\u65B9\u786E\u8BA4\u6536\u5230\u3002",
146913
+ "test-target-unavailable": "\u8FD8\u6CA1\u6709\u53EF\u7528\u4E8E\u6D4B\u8BD5\u7684\u79C1\u804A\u3002\u7528\u83B7\u51C6\u4F7F\u7528\u8FD9\u4E2A\u673A\u5668\u4EBA\u7684\u8D26\u53F7\u79C1\u804A\u5B83\u4E00\u53E5\uFF0C\u518D\u68C0\u67E5\u3002",
146914
+ "test-message-failed": "\u786E\u8BA4\u673A\u5668\u4EBA\u8FD8\u80FD\u5728\u90A3\u4E2A\u79C1\u804A\u91CC\u53D1\u6D88\u606F\uFF08\u539F\u56E0\u89C1\u4E0B\u65B9\uFF09\uFF0C\u518D\u68C0\u67E5\u3002",
146915
+ ref: "\u6D4B\u8BD5\u6D88\u606F\u53C2\u8003\u53F7\uFF1A{{ref}}\n{{detail}}"
146916
+ },
146783
146917
  hint: {
146784
146918
  networkMultipleCauses: "\u8FD9\u6B21\u5931\u8D25\u80CC\u540E\u4E0D\u6B62\u4E00\u79CD\u7F51\u7EDC\u95EE\u9898\u3002\u8BF7\u68C0\u67E5\u8FD9\u53F0\u673A\u5668\u7684\u7F51\u7EDC\u548C\u8FD9\u4E2A\u673A\u5668\u4EBA\u7684\u300C\u4EE3\u7406\u300D\u8BBE\u7F6E\uFF0C\u518D\u68C0\u67E5\u4E00\u6B21\u3002",
146785
146919
  networkDns: "\u670D\u52A1\u57DF\u540D\u89E3\u6790\u5931\u8D25\u3002\u8BF7\u68C0\u67E5\u8FD9\u53F0\u673A\u5668\u7684 DNS \u548C\u7F51\u7EDC\u8BBE\u7F6E\uFF0C\u518D\u68C0\u67E5\u4E00\u6B21\u3002",
@@ -147828,10 +147962,24 @@ var makeLarkAdapter = (deps) => {
147828
147962
 
147829
147963
  // src/modelPlan.ts
147830
147964
  import { threadOrNull as threadOrNull4 } from "@ycodium-ai/plugin-api";
147965
+
147966
+ // src/botModel.ts
147967
+ var resolveDefaultModel = async (bot, chatModel, projectDefault, providers, knownInstances) => {
147968
+ if (chatModel !== null) return chatModel;
147969
+ if (bot.defaultModel !== void 0) {
147970
+ const instances = knownInstances === void 0 ? await providers.list({}).catch(() => null) : knownInstances;
147971
+ if (!isModelCatalogComplete(instances) || modelCatalogHas(modelChoices(instances ?? []), bot.defaultModel)) {
147972
+ return bot.defaultModel;
147973
+ }
147974
+ }
147975
+ return projectDefault;
147976
+ };
147977
+
147978
+ // src/modelPlan.ts
147831
147979
  var makeModelPlan = (core, deps) => {
147832
147980
  const { host, t, commit, deliver } = core;
147833
147981
  const { threadStillUsable } = deps;
147834
- const currentModelOf = async (binding) => {
147982
+ const currentModelOf = async (binding, instances) => {
147835
147983
  const chat = chatOf(core.state, chatKeyOf(binding));
147836
147984
  if (chat.threadId !== null) {
147837
147985
  const thread = await threadOrNull4(host.threads, chat.threadId).catch(() => null);
@@ -147844,15 +147992,20 @@ var makeModelPlan = (core, deps) => {
147844
147992
  }
147845
147993
  if (chat.model !== null) return chat.model;
147846
147994
  const project = binding.projectId === "" ? null : await host.projects.get({ projectId: binding.projectId }).catch(() => null);
147847
- const fallback = project?.defaultModelSelection ?? null;
147848
- return fallback === null ? null : { instanceId: fallback.instanceId, model: fallback.model };
147995
+ return resolveDefaultModel(
147996
+ binding,
147997
+ chat.model,
147998
+ project?.defaultModelSelection ?? null,
147999
+ host.providers.instances,
148000
+ instances
148001
+ );
147849
148002
  };
147850
148003
  const handleModel = async (binding, arg) => {
147851
148004
  const chatKey = chatKeyOf(binding);
147852
148005
  const instances = await host.providers.instances.list({}).catch(() => null);
147853
148006
  const choices = instances === null ? [] : modelChoices(instances);
147854
148007
  if (arg === "") {
147855
- await deliver(binding, formatModels(await currentModelOf(binding), choices, t));
148008
+ await deliver(binding, formatModels(await currentModelOf(binding, instances), choices, t));
147856
148009
  return;
147857
148010
  }
147858
148011
  if (choices.length === 0) {
@@ -148566,7 +148719,8 @@ var makePanelWiring = (core, deps) => {
148566
148719
  const binding = bindingForChatKey(chatKey);
148567
148720
  const instances = await host.providers.instances.list({}).catch(() => null);
148568
148721
  if (binding === void 0 || instances === null) return null;
148569
- return { current: await currentModelOf(binding), choices: modelChoices(instances) };
148722
+ const choices = modelChoices(instances);
148723
+ return { current: await currentModelOf(binding, instances), choices };
148570
148724
  },
148571
148725
  loadProjects: async (chatKey) => {
148572
148726
  const rows = await projectRowsFor(chatKey);
@@ -148598,7 +148752,7 @@ var makePanelWiring = (core, deps) => {
148598
148752
  const opener = remembered === void 0 ? void 0 : bindingForChatKey(remembered);
148599
148753
  const chatId = opener !== void 0 && opener.rowId === bot.rowId && adapterFor(opener.platform)?.parentChatIdOf?.(opener.chatId) === click.chatId ? opener.chatId : click.chatId;
148600
148754
  const target2 = bindingOf2(bot, chatId);
148601
- if (!isAllowedSender(target2, click.operatorId)) {
148755
+ if (!isAllowedSender(target2, click.operatorId, chatOf(core.state, chatKeyOf(target2)).chatKind)) {
148602
148756
  host.log.warn("chat ignored a panel click from someone not on the allow list", {
148603
148757
  bot: target2.displayName,
148604
148758
  operator: click.operatorId
@@ -150526,7 +150680,7 @@ var makeTelegramAdapter = (deps) => {
150526
150680
  let backoff = BACKOFF_START_MS;
150527
150681
  let botUsername;
150528
150682
  let botId;
150529
- let menuSent = false;
150683
+ let menuLanguage;
150530
150684
  let liveApi;
150531
150685
  const isSoloGroup = makeSoloGroupCheck(async (chatId) => {
150532
150686
  const count = await (await apiFor(binding)).getChatMemberCount(chatId);
@@ -150554,8 +150708,8 @@ var makeTelegramAdapter = (deps) => {
150554
150708
  if (running) handlers.onConnectionState?.({ state: "connected" });
150555
150709
  }
150556
150710
  if (!running) return;
150557
- if (!menuSent) {
150558
- menuSent = true;
150711
+ if (menuLanguage !== t.language) {
150712
+ menuLanguage = t.language;
150559
150713
  void api.setMyCommands(telegramCommandMenu(t)).catch((error) => {
150560
150714
  deps.log.warn("telegram could not set the command menu", {
150561
150715
  bot: binding.displayName,
@@ -151066,7 +151220,12 @@ var makeTurns = (core, deps) => {
151066
151220
  });
151067
151221
  return null;
151068
151222
  }
151069
- const modelSelection = chatOf(core.state, chatKey).model ?? project.defaultModelSelection;
151223
+ const modelSelection = await resolveDefaultModel(
151224
+ binding,
151225
+ chatOf(core.state, chatKey).model,
151226
+ project.defaultModelSelection,
151227
+ host.providers.instances
151228
+ );
151070
151229
  if (modelSelection === null) {
151071
151230
  host.log.warn("chat cannot start a thread: the project has no default model", {
151072
151231
  bot: binding.displayName,
@@ -151465,17 +151624,6 @@ var botOf = (config2, adapters, rowId) => {
151465
151624
  const adapter = adapters.find((candidate) => candidate.platform === platform);
151466
151625
  return { ...readBotView(rowId, raw, adapter ?? { label: platform }), platform };
151467
151626
  };
151468
- var reportOf = (bot, stage, ok, detail, hint) => ({
151469
- ref: diagnosticRef("conn"),
151470
- platform: bot.platform,
151471
- botName: bot.displayName,
151472
- rowId: bot.rowId,
151473
- stage,
151474
- ok,
151475
- detail,
151476
- at: (/* @__PURE__ */ new Date()).toISOString(),
151477
- ...hint === void 0 ? {} : { hint }
151478
- });
151479
151627
  var probe = async (adapters, bot) => {
151480
151628
  const adapter = adapters.find((candidate) => candidate.platform === bot.platform);
151481
151629
  if (adapter?.checkConnection === void 0) {
@@ -151501,14 +151649,31 @@ var probe = async (adapters, bot) => {
151501
151649
  );
151502
151650
  }
151503
151651
  };
151504
- var emitReport = (emit, report, action) => {
151652
+ var emitReport = (emit, report, action, testMessage) => {
151505
151653
  const detail = action.copyable ? formatDiagnosticCopy(report) : report.detail;
151506
151654
  if (report.ok) {
151655
+ const unsent = testMessage === void 0 || testMessage.sent ? void 0 : testMessage;
151656
+ const messageKey = unsent === void 0 ? `${action.keyPrefix}.done` : unsent.code === "test-message-failed" ? "rowAction.checkConnection.doneTestFailed" : "rowAction.checkConnection.doneNoTarget";
151507
151657
  emit({
151508
151658
  kind: "done",
151509
151659
  fills: {},
151510
- messageKey: `${action.keyPrefix}.done`,
151511
- warnings: [{ key: "rowAction.diagnostic.ref", params: { ref: report.ref, detail } }]
151660
+ messageKey,
151661
+ ...unsent?.code === "test-message-failed" ? { tone: "caution" } : {},
151662
+ // 顺序:该做什么 → 测试消息的诊断 → 凭据检查的诊断。
151663
+ warnings: [
151664
+ ...testMessage === void 0 ? [] : [
151665
+ {
151666
+ key: `rowAction.checkConnection.testMessage.${testMessage.sent ? "sent" : testMessage.code}`
151667
+ }
151668
+ ],
151669
+ ...unsent?.error === void 0 ? [] : [
151670
+ {
151671
+ key: "rowAction.checkConnection.testMessage.ref",
151672
+ params: { ref: unsent.error.ref, detail: unsent.error.detail }
151673
+ }
151674
+ ],
151675
+ { key: action.refKey, params: { ref: report.ref, detail } }
151676
+ ]
151512
151677
  });
151513
151678
  return;
151514
151679
  }
@@ -151526,7 +151691,7 @@ var emitReport = (emit, report, action) => {
151526
151691
  detail
151527
151692
  });
151528
151693
  };
151529
- var registerSettingsRowActions = (ctx, adapters, connections, inboundState, beginLarkCardActionProbe) => {
151694
+ var registerSettingsRowActions = (ctx, adapters, connections, inboundState, beginLarkCardActionProbe, connectionTests) => {
151530
151695
  const resolveBot = (rowId) => botOf(ctx.config, adapters, rowId);
151531
151696
  const registerProbeAction = (action) => {
151532
151697
  ctx.stream({
@@ -151555,7 +151720,10 @@ var registerSettingsRowActions = (ctx, adapters, connections, inboundState, begi
151555
151720
  );
151556
151721
  return;
151557
151722
  }
151558
- emitReport(emit, await probe(adapters, bot), action);
151723
+ const report = await probe(adapters, bot);
151724
+ const adapter = adapters.find((candidate) => candidate.platform === bot.platform);
151725
+ const testMessage = report.ok && action.sendsTestMessage && adapter !== void 0 ? await connectionTests.send(bot, adapter) : void 0;
151726
+ emitReport(emit, report, action, testMessage);
151559
151727
  }
151560
151728
  });
151561
151729
  };
@@ -151563,7 +151731,9 @@ var registerSettingsRowActions = (ctx, adapters, connections, inboundState, begi
151563
151731
  name: BOT_ACTION_COMMANDS.checkConnection,
151564
151732
  summary: "Probe an IM bot's platform credentials without calling a model.",
151565
151733
  keyPrefix: "rowAction.checkConnection",
151566
- copyable: false
151734
+ copyable: false,
151735
+ sendsTestMessage: true,
151736
+ refKey: "rowAction.checkConnection.credentialRef"
151567
151737
  });
151568
151738
  ctx.stream({
151569
151739
  name: BOT_ACTION_COMMANDS.reconnect,
@@ -151589,7 +151759,9 @@ var registerSettingsRowActions = (ctx, adapters, connections, inboundState, begi
151589
151759
  name: BOT_ACTION_COMMANDS.copyDiagnostics,
151590
151760
  summary: "Probe an IM bot and return a copy-paste diagnostic report.",
151591
151761
  keyPrefix: "rowAction.copyDiagnostics",
151592
- copyable: true
151762
+ copyable: true,
151763
+ sendsTestMessage: false,
151764
+ refKey: "rowAction.diagnostic.ref"
151593
151765
  });
151594
151766
  ctx.stream({
151595
151767
  name: BOT_ACTION_COMMANDS.resetInbox,
@@ -151901,17 +152073,22 @@ var registerSettingsCommands = (ctx, adapters, updateSettings, connections) => {
151901
152073
  });
151902
152074
  ctx.command({
151903
152075
  name: SETTINGS_VIEW_COMMAND,
151904
- description: "Read the chat-bridge settings view, bot columns, and this machine's proxies.",
152076
+ description: "Read the chat-bridge settings view, bot columns, model choices, and this machine's proxies.",
151905
152077
  scope: "read",
151906
152078
  payloadSchema: EMPTY_PAYLOAD,
151907
152079
  handle: async () => {
151908
- const [config2, listed] = await Promise.all([
152080
+ const [config2, listed, instances] = await Promise.all([
151909
152081
  ctx.settings.read(),
151910
- ctx.machineSettings.proxies.list({})
152082
+ ctx.machineSettings.proxies.list({}),
152083
+ ctx.providers.instances.list({}).catch(() => null)
151911
152084
  ]);
151912
152085
  return {
151913
152086
  view: buildSettingsView(config2, adapters),
151914
- columns: buildBotColumns(adapters),
152087
+ columns: buildBotColumns(
152088
+ adapters,
152089
+ modelChoices(instances ?? []),
152090
+ isModelCatalogComplete(instances)
152091
+ ),
151915
152092
  targetColumns: deliveryTargetColumns(),
151916
152093
  proxies: listed.map(proxyChoice)
151917
152094
  };
@@ -153937,12 +154114,12 @@ var makeWecomAppAdapter = (deps) => {
153937
154114
  if (chatId === "") return;
153938
154115
  if (message.msgtype === "event") {
153939
154116
  if (message.event === "subscribe" || message.event === "enter_agent") {
153940
- handlers.onGreeting?.(chatId, chatId);
154117
+ handlers.onGreeting?.(chatId, chatId, "private");
153941
154118
  }
153942
154119
  return;
153943
154120
  }
153944
154121
  const messageId = message.msgid ?? `${chatId}:${message.createTime ?? Date.now()}`;
153945
- const base2 = { messageId, chatId, senderId: chatId };
154122
+ const base2 = { messageId, chatId, senderId: chatId, chatKind: "private" };
153946
154123
  const receive = (inbound) => {
153947
154124
  void handlers.onMessage(inbound).catch((error) => {
153948
154125
  deps.log.warn("wecom-app could not persist inbound message", {
@@ -154382,7 +154559,14 @@ var definition = {
154382
154559
  await chatQueue.closeAndDrain();
154383
154560
  }
154384
154561
  });
154385
- registerSettingsRowActions(ctx, adapters, connections, inboundState, lark.beginCardActionProbe);
154562
+ registerSettingsRowActions(
154563
+ ctx,
154564
+ adapters,
154565
+ connections,
154566
+ inboundState,
154567
+ lark.beginCardActionProbe,
154568
+ inbound.connectionTests
154569
+ );
154386
154570
  registerSettingsCommands(ctx, adapters, updateSettings, connections);
154387
154571
  const { bots, connecting } = connections.reconcile();
154388
154572
  const deliveryHttp = makeDeliveryHttp({
@@ -154395,6 +154579,7 @@ var definition = {
154395
154579
  if (typeof ctx.settings.onChange === "function") {
154396
154580
  ctx.settings.onChange(async (config2) => {
154397
154581
  setLanguage(parseReplyLanguage(config2[REPLY_LANGUAGE_FIELD]));
154582
+ inbound.connectionTests.retainRows(Object.keys(config2[BOTS_FIELD] ?? {}));
154398
154583
  connections.reconcile();
154399
154584
  await deliveryHttp.apply(config2);
154400
154585
  });
package/locales/en.json CHANGED
@@ -7,7 +7,7 @@
7
7
  },
8
8
  "settings": {
9
9
  "title": "Chat",
10
- "description": "Connect chat bots to Ycodium. One row per bot: create the bot on its platform, paste its credentials, and pick an access mode (allowlist / open). In allowlist mode, list the people allowed to use it. For Lark, Connect a Lark bot does all of that with one scan. Admitted people message the bot (or add it to a group), pick a project in the chat, and can start work.",
10
+ "description": "Connect chat bots to Ycodium. One row per bot: create the bot on its platform, paste its credentials, and pick one access mode that decides who can use it in private chats and groups. Where the allowlist applies, list the people in \"Allowed people\". For Lark, Connect a Lark bot does all of that with one scan. Admitted people message the bot (or add it to a group), pick a project in the chat, and can start work.",
11
11
  "bots": "Bots",
12
12
  "language": {
13
13
  "label": "Reply language",
@@ -15,6 +15,10 @@
15
15
  "zhCN": "中文",
16
16
  "en": "English"
17
17
  },
18
+ "defaultModel": {
19
+ "follow": "Follow chat / project default",
20
+ "unavailable": "{{value}} (unavailable)"
21
+ },
18
22
  "runtimeMode": {
19
23
  "approvalRequired": "Ask before commands and file changes",
20
24
  "autoAcceptEdits": "Auto-accept edits, ask before other actions",
@@ -63,7 +67,9 @@
63
67
  },
64
68
  "accessMode": {
65
69
  "allowlist": "Allowlist only (default)",
66
- "open": "Allow everyone"
70
+ "open": "Allow everyone",
71
+ "privateOpen": "Private chats: open; groups: allowlist",
72
+ "groupOpen": "Private chats: allowlist; groups: open"
67
73
  }
68
74
  },
69
75
  "platform": {
@@ -99,12 +105,16 @@
99
105
  },
100
106
  "allowedSenders": {
101
107
  "label": "Allowed people",
102
- "description": "Comma-separated user ids from that platform. Used only in allowlist mode; while the list is empty, nobody can. Message the bot and it tells you your own id."
108
+ "description": "Comma-separated user ids from that platform. Used in chats where the access mode requires the allowlist; while the list is empty, nobody can use the bot in those chats. To find an id: from an account not yet on the list, message the bot in a chat that requires the allowlist (mention it in a group). The bot replies with the id, at most once every 10 minutes per account."
103
109
  },
104
110
  "proxy": {
105
111
  "label": "Proxy",
106
112
  "description": "Some platforms are only reachable through a proxy on this machine, and which one can differ per bot."
107
113
  },
114
+ "defaultModel": {
115
+ "label": "Default model",
116
+ "description": "Used for new sessions when the chat has no /model selection. Existing sessions keep their model; send /new to use this default. Unavailable choices fall back to the project default."
117
+ },
108
118
  "runtimeMode": {
109
119
  "label": "What a chat message may do",
110
120
  "description": "Admitted people start turns from chat, so this is deliberately not full access by default. Whichever mode asks, the request lands in the chat."
@@ -195,11 +205,12 @@
195
205
  },
196
206
  "accessMode": {
197
207
  "label": "Access mode",
198
- "description": "Allowlist admits only \"Allowed people\"; open admits any identifiable sender. New bots default to allowlist."
208
+ "description": "Allowlist admits only \"Allowed people\"; open admits any identifiable sender. New bots default to allowlist. \"Private chats: open; groups: allowlist\" and \"Private chats: allowlist; groups: open\" share the same \"Allowed people\"; in either of them, when the chat type cannot be confirmed, only \"Allowed people\" can use the bot."
199
209
  }
200
210
  },
201
211
  "reply": {
202
212
  "deliveryFailed": "The reply could not be delivered. Check this bot's connection and permissions, then try again.",
213
+ "connectionTest": "✅ Ycodium connection test\nThis test message was sent by “{{name}}” using Check connection in Settings. No reply needed.",
203
214
  "wecomDeliveryFailed": "This reply didn't reach {{recipient}} in WeCom: they are outside this app's visible range. Add them to the app's visible range in the WeCom admin console, then ask the agent to send it again.",
204
215
  "conclusionRecovered": "(Finished while restarting; delivered now)",
205
216
  "notAllowed": "You are not on this bot's allow list, so this tap had no effect.",
@@ -596,11 +607,20 @@
596
607
  "rowAction": {
597
608
  "checkConnection": {
598
609
  "label": "Check connection",
599
- "description": "Verify platform credentials still work; does not open a session or call a model.",
610
+ "description": "Verify credentials and send a test message to the most recent private chat; does not open a session or call a model.",
600
611
  "running": "Checking {{rowId}}…",
601
612
  "done": "Connection OK",
613
+ "doneTestFailed": "Credentials OK, but the test message was not sent",
614
+ "doneNoTarget": "Credentials OK, but no test message was sent",
602
615
  "failed": "Connection failed",
603
616
  "notSaved": "Save this row first (credentials are read from saved config only).",
617
+ "credentialRef": "Credential check reference: {{ref}}\n{{detail}}",
618
+ "testMessage": {
619
+ "sent": "Sent to whoever last messaged the bot privately. Ask them to confirm.",
620
+ "test-target-unavailable": "No private chat to test with yet. Message the bot privately from an account allowed to use the bot, then check again.",
621
+ "test-message-failed": "Check that the bot can still send to that private chat (reason below), then check again.",
622
+ "ref": "Test message reference: {{ref}}\n{{detail}}"
623
+ },
604
624
  "hint": {
605
625
  "networkMultipleCauses": "This failure has more than one network cause. Check this machine's network and this bot's Proxy setting, then check again.",
606
626
  "networkDns": "The service's domain name could not be resolved. Check this machine's DNS and network settings, then check again.",
@@ -7,7 +7,7 @@
7
7
  },
8
8
  "settings": {
9
9
  "title": "聊天",
10
- "description": "把聊天机器人接到 Ycodium。一行一个机器人:先在对应平台建好机器人、把凭据填进来,再选访问模式(仅白名单/允许所有人)。仅白名单时把允许使用它的人填进「允许的人」。飞书可以用「连接飞书机器人」,扫一次码全部配好。获准的人私聊机器人(或把它拉进群)、在聊天里选好项目,就能派活。",
10
+ "description": "把聊天机器人接到 Ycodium。一行一个机器人:先在对应平台建好机器人、把凭据填进来,再选一个访问模式,决定私聊和群里谁能用;用到名单时,把人填进「允许的人」。飞书可以用「连接飞书机器人」,扫一次码全部配好。获准的人私聊机器人(或把它拉进群)、在聊天里选好项目,就能派活。",
11
11
  "bots": "机器人",
12
12
  "language": {
13
13
  "label": "回话语言",
@@ -15,6 +15,10 @@
15
15
  "zhCN": "中文",
16
16
  "en": "English"
17
17
  },
18
+ "defaultModel": {
19
+ "follow": "跟随聊天 / 项目默认",
20
+ "unavailable": "{{value}}(不可用)"
21
+ },
18
22
  "runtimeMode": {
19
23
  "approvalRequired": "命令和改文件前先问",
20
24
  "autoAcceptEdits": "自动接受改动,其他操作先问",
@@ -63,7 +67,9 @@
63
67
  },
64
68
  "accessMode": {
65
69
  "allowlist": "仅白名单(默认)",
66
- "open": "允许所有人"
70
+ "open": "允许所有人",
71
+ "privateOpen": "私聊放开,群里限名单",
72
+ "groupOpen": "私聊限名单,群里放开"
67
73
  }
68
74
  },
69
75
  "platform": {
@@ -99,12 +105,16 @@
99
105
  },
100
106
  "allowedSenders": {
101
107
  "label": "允许的人",
102
- "description": "该平台的用户 id,逗号分隔。仅在「仅白名单」模式下生效;留空则谁都不能。给机器人发一句话,它会告诉你自己的 id。"
108
+ "description": "该平台的用户 id,逗号分隔。在访问模式要求名单的聊天里生效;留空则谁都不能在这些聊天里使用机器人。查 id:用还不在名单上的账号,在要求名单的聊天里给机器人发一句话(群里要 @ 它),它会回复这个 id;同一账号 10 分钟内只回一次。"
103
109
  },
104
110
  "proxy": {
105
111
  "label": "代理",
106
112
  "description": "有些平台只能经本机上的某个代理才连得上,而且每个机器人可以不一样。"
107
113
  },
114
+ "defaultModel": {
115
+ "label": "默认模型",
116
+ "description": "聊天未用 /model 选模型时,新会话使用此默认模型。已有会话保留原模型;发送 /new 后使用新默认。不可用时回退到项目默认。"
117
+ },
108
118
  "runtimeMode": {
109
119
  "label": "聊天消息能做什么",
110
120
  "description": "获准的人都能从聊天里开一轮,所以默认故意不给满权限。不论选哪一档,要拍板的事都会摆到聊天里。"
@@ -195,11 +205,12 @@
195
205
  },
196
206
  "accessMode": {
197
207
  "label": "访问模式",
198
- "description": "仅白名单=只有「允许的人」能触发;允许所有人=平台能识别的发送者均可。新机器人默认仅白名单。"
208
+ "description": "仅白名单=只有「允许的人」能触发;允许所有人=平台能识别的发送者均可。新机器人默认仅白名单。「私聊放开,群里限名单」与「私聊限名单,群里放开」共用同一份「允许的人」;这两种模式下,无法确认是私聊还是群时,只有「允许的人」能用机器人。"
199
209
  }
200
210
  },
201
211
  "reply": {
202
212
  "deliveryFailed": "回复未能送达。请检查这个机器人的连接与权限,然后重试。",
213
+ "connectionTest": "✅ Ycodium 连接测试\n这条测试消息由「{{name}}」机器人通过设置页的「检查连接」发出,无需回复。",
203
214
  "wecomDeliveryFailed": "这条回复没送到企业微信里的 {{recipient}}:对方不在这个应用的可见范围。到企业微信管理后台把他们加进应用的可见范围,再让 agent 重发一次。",
204
215
  "conclusionRecovered": "(重启期间完成,现在补发)",
205
216
  "notAllowed": "你不在这个机器人的允许名单里,这次点击没有生效。",
@@ -596,11 +607,20 @@
596
607
  "rowAction": {
597
608
  "checkConnection": {
598
609
  "label": "检查连接",
599
- "description": "验证平台凭据是否仍可用;不会开会话,也不会调模型。",
610
+ "description": "验证平台凭据,并向最近的私聊发一条测试消息;不会开会话,也不会调模型。",
600
611
  "running": "正在检查 {{rowId}} …",
601
612
  "done": "连接正常",
613
+ "doneTestFailed": "凭据正常,但测试消息没发出去",
614
+ "doneNoTarget": "凭据正常,但还没发测试消息",
602
615
  "failed": "连接失败",
603
616
  "notSaved": "请先保存这一行再检查连接(凭据只从已保存配置读取)。",
617
+ "credentialRef": "凭据检查参考号:{{ref}}\n{{detail}}",
618
+ "testMessage": {
619
+ "sent": "已发到最近私聊过机器人的人,请对方确认收到。",
620
+ "test-target-unavailable": "还没有可用于测试的私聊。用获准使用这个机器人的账号私聊它一句,再检查。",
621
+ "test-message-failed": "确认机器人还能在那个私聊里发消息(原因见下方),再检查。",
622
+ "ref": "测试消息参考号:{{ref}}\n{{detail}}"
623
+ },
604
624
  "hint": {
605
625
  "networkMultipleCauses": "这次失败背后不止一种网络问题。请检查这台机器的网络和这个机器人的「代理」设置,再检查一次。",
606
626
  "networkDns": "服务域名解析失败。请检查这台机器的 DNS 和网络设置,再检查一次。",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ycodium-ai/plugin-im",
3
- "version": "0.2.3236",
3
+ "version": "0.2.3238",
4
4
  "description": "Talk to your agents from Telegram, WeCom, Lark, or WeChat (experimental).",
5
5
  "keywords": [
6
6
  "im",
@@ -32,7 +32,7 @@
32
32
  "markdown-it": "^15.0.2",
33
33
  "react": "19.2.6",
34
34
  "vite-plus": "0.2.2",
35
- "@ycodium-ai/plugin-api": "0.2.3236",
35
+ "@ycodium-ai/plugin-api": "0.2.3238",
36
36
  "ycodium-react-test-harness": "0.0.0"
37
37
  },
38
38
  "ycodium": {