@jingyi0605/codingns 0.9.9 → 1.0.0-beta.1

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.
Files changed (94) hide show
  1. package/bin/codingns.mjs +14 -0
  2. package/dist/public/assets/{AdaptiveButlerPage-CqBM1XiC.js → AdaptiveButlerPage-BYETYaIe.js} +1 -1
  3. package/dist/public/assets/{App-Pe30N_Dy.js → App-CHsm-VrM.js} +3 -3
  4. package/dist/public/assets/App-Z0Zd7gXR.css +1 -0
  5. package/dist/public/assets/{BootstrapPage-D9ai1XhC.js → BootstrapPage-Bp0KfySv.js} +1 -1
  6. package/dist/public/assets/ConversationPage-BCrNml1k.js +9 -0
  7. package/dist/public/assets/{DesktopDetachPreviewPage-BJVPVFf2.js → DesktopDetachPreviewPage-DlDSb_tf.js} +1 -1
  8. package/dist/public/assets/{DesktopModal-DyC_e0eF.js → DesktopModal-Csj5AdAN.js} +1 -1
  9. package/dist/public/assets/{DesktopWindowPage-BZleww0T.js → DesktopWindowPage-CacXiWjV.js} +1 -1
  10. package/dist/public/assets/{FileContextPanel-BklQRQXj.js → FileContextPanel-DzMUQvE5.js} +1 -1
  11. package/dist/public/assets/{GitSidebar-D0tb3W87.js → GitSidebar-C8IC18GH.js} +2 -2
  12. package/dist/public/assets/{MobileCreateSessionSheet-BS881Agk.js → MobileCreateSessionSheet-BtqR_hKc.js} +1 -1
  13. package/dist/public/assets/{MobileSheet-C32hwIFd.js → MobileSheet-Co-qPMBD.js} +1 -1
  14. package/dist/public/assets/{PluginAccessOverview-BDiz6fV8.js → PluginAccessOverview-D-KXkcyj.js} +1 -1
  15. package/dist/public/assets/{PluginContainerPage-BMT6J0YS.js → PluginContainerPage-BKwCIs4r.js} +1 -1
  16. package/dist/public/assets/{PluginDetailPage-ztNhvCWP.js → PluginDetailPage-Djv_swcO.js} +1 -1
  17. package/dist/public/assets/{PluginsListPage-Cuk2-U6E.js → PluginsListPage-DAECNoN6.js} +1 -1
  18. package/dist/public/assets/{PureConversationPage-ShluI2En.js → PureConversationPage-DP1X7Hix.js} +1 -1
  19. package/dist/public/assets/{RelayConnectEntryPage-CMbjlD0k.js → RelayConnectEntryPage-xL_IPH8a.js} +1 -1
  20. package/dist/public/assets/{ServerSettingsModal-CLSWyHu6.js → ServerSettingsModal-CyhMgk10.js} +1 -1
  21. package/dist/public/assets/{SessionIndexPage-dqfauVAj.js → SessionIndexPage-CVEz50tc.js} +1 -1
  22. package/dist/public/assets/SettingsPage-CQNCrgaj.js +2 -0
  23. package/dist/public/assets/{TerminalManagerPanel-75khWhRz.js → TerminalManagerPanel-wVnoRA8u.js} +1 -1
  24. package/dist/public/assets/{ToolFilesPage-S3eWxO_D.js → ToolFilesPage-BospXumK.js} +1 -1
  25. package/dist/public/assets/{ToolGitPage-8RAMpope.js → ToolGitPage-B2zOeCAD.js} +1 -1
  26. package/dist/public/assets/{ToolProcessesPage-TZACKEoH.js → ToolProcessesPage-BDShao4b.js} +1 -1
  27. package/dist/public/assets/{ToolsHomePage-Whgu6Tyf.js → ToolsHomePage-s4zH7D9M.js} +1 -1
  28. package/dist/public/assets/{WorkbenchLandingPage-CC24vHza.js → WorkbenchLandingPage-D51QCU_u.js} +1 -1
  29. package/dist/public/assets/WorkbenchLayout-Bo2BbMY6.js +1081 -0
  30. package/dist/public/assets/{WorkbenchModal-2PaCY_Gj.js → WorkbenchModal-YsyEdJ_m.js} +1 -1
  31. package/dist/public/assets/WorkbenchShellRoute-D3l4aWJS.js +1 -0
  32. package/dist/public/assets/WorkbenchShellRoute-D5fnyF8z.css +1 -0
  33. package/dist/public/assets/{WorkspaceDebugDetailPage-Ce_oMmJ8.js → WorkspaceDebugDetailPage-CMjNLqFq.js} +1 -1
  34. package/dist/public/assets/{WorkspaceDetailPage-aX6w4Q7S.js → WorkspaceDetailPage-CKxTbPKh.js} +1 -1
  35. package/dist/public/assets/{WorkspaceHomePage-DQttgj2w.js → WorkspaceHomePage-CEy4ShCu.js} +1 -1
  36. package/dist/public/assets/{client-runtime-manager-CGVLChqs.js → client-runtime-manager-BFXU9DmS.js} +1 -1
  37. package/dist/public/assets/host-alias-Zb2xyVrf.js +1 -0
  38. package/dist/public/assets/{index-Bp1FnRo_.js → index-BilHJjYU.js} +3 -3
  39. package/dist/public/assets/index-OR7OITpQ.css +1 -0
  40. package/dist/public/assets/{login-direct-candidate-resolver-Bvs5uPix.js → login-direct-candidate-resolver-DL8DS-Si.js} +1 -1
  41. package/dist/public/assets/{peer-host-config-sync-oelf2T0_.js → peer-host-config-sync-d2ZcPC5P.js} +1 -1
  42. package/dist/public/assets/{plugin-permission-copy-Do028HzJ.js → plugin-permission-copy-DrLk22m5.js} +1 -1
  43. package/dist/public/assets/{plugins-api-BOugklJ-.js → plugins-api-COF4oh24.js} +1 -1
  44. package/dist/public/assets/{preferences-service-Dys1mbBy.js → preferences-service-CEWNV1w9.js} +1 -1
  45. package/dist/public/assets/{relay-entry-B6UDc5cD.js → relay-entry-Cmc8vTlE.js} +1 -1
  46. package/dist/public/assets/{useRegisteredDebugTemplates-BafVuBvE.js → useRegisteredDebugTemplates-FdmHG2S4.js} +1 -1
  47. package/dist/public/assets/workbench-navigation-ED0157V-.js +1 -0
  48. package/dist/public/index.html +2 -2
  49. package/dist/server/config/env.js +5 -3
  50. package/dist/server/config/env.js.map +1 -1
  51. package/dist/server/modules/butler/butler-session-service.d.ts +1 -0
  52. package/dist/server/modules/butler/butler-session-service.js +2 -1
  53. package/dist/server/modules/butler/butler-session-service.js.map +1 -1
  54. package/dist/server/modules/client/npm-global-package-service.js +3 -0
  55. package/dist/server/modules/client/npm-global-package-service.js.map +1 -1
  56. package/dist/server/modules/client/service-update-types.d.ts +3 -0
  57. package/dist/server/modules/peer-host/peer-host-controller.d.ts +5 -0
  58. package/dist/server/modules/peer-host/peer-host-controller.js +3 -0
  59. package/dist/server/modules/peer-host/peer-host-controller.js.map +1 -1
  60. package/dist/server/modules/peer-host/peer-host-service.d.ts +1 -0
  61. package/dist/server/modules/peer-host/peer-host-service.js +44 -0
  62. package/dist/server/modules/peer-host/peer-host-service.js.map +1 -1
  63. package/dist/server/modules/sessions/session-history-service.d.ts +1 -0
  64. package/dist/server/modules/sessions/session-history-service.js +6 -2
  65. package/dist/server/modules/sessions/session-history-service.js.map +1 -1
  66. package/dist/server/modules/terminal/runtime/terminal-log-spooler.d.ts +5 -0
  67. package/dist/server/modules/terminal/runtime/terminal-log-spooler.js +54 -7
  68. package/dist/server/modules/terminal/runtime/terminal-log-spooler.js.map +1 -1
  69. package/dist/server/modules/workbench/affairs-assistant-session-snapshot-service.js +2 -1
  70. package/dist/server/modules/workbench/affairs-assistant-session-snapshot-service.js.map +1 -1
  71. package/dist/server/modules/workbench/workbench-service.js +11 -1
  72. package/dist/server/modules/workbench/workbench-service.js.map +1 -1
  73. package/dist/server/modules/workspace/affairs-lightweight-session-controller.d.ts +4 -0
  74. package/dist/server/modules/workspace/affairs-lightweight-session-controller.js +26 -0
  75. package/dist/server/modules/workspace/affairs-lightweight-session-controller.js.map +1 -1
  76. package/dist/server/modules/workspace/affairs-lightweight-session-service.d.ts +15 -1
  77. package/dist/server/modules/workspace/affairs-lightweight-session-service.js +201 -22
  78. package/dist/server/modules/workspace/affairs-lightweight-session-service.js.map +1 -1
  79. package/dist/server/routes/peer-hosts.js +1 -0
  80. package/dist/server/routes/peer-hosts.js.map +1 -1
  81. package/dist/server/server/create-server.js +1 -1
  82. package/dist/server/server/create-server.js.map +1 -1
  83. package/package.json +3 -2
  84. package/scripts/node22-runtime.mjs +176 -0
  85. package/scripts/postinstall.mjs +6 -0
  86. package/dist/public/assets/App-7zrCMhE-.css +0 -1
  87. package/dist/public/assets/ConversationPage-C8aU99KN.js +0 -9
  88. package/dist/public/assets/SettingsPage-PUga-wwJ.js +0 -2
  89. package/dist/public/assets/WorkbenchLayout-CoYxMzzR.js +0 -1081
  90. package/dist/public/assets/WorkbenchShellRoute-DLVRpGzb.css +0 -1
  91. package/dist/public/assets/WorkbenchShellRoute-QXztW_Ny.js +0 -1
  92. package/dist/public/assets/host-alias-CeDJeL0T.js +0 -1
  93. package/dist/public/assets/index-BehUkul4.css +0 -1
  94. package/dist/public/assets/workbench-navigation-Bs4OQYD3.js +0 -1
@@ -1,4 +1,4 @@
1
- const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/peer-host-config-sync-oelf2T0_.js","assets/host-alias-CeDJeL0T.js","assets/App-Pe30N_Dy.js","assets/App-7zrCMhE-.css"])))=>i.map(i=>d[i]);
1
+ const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/peer-host-config-sync-d2ZcPC5P.js","assets/host-alias-Zb2xyVrf.js","assets/App-CHsm-VrM.js","assets/App-Z0Zd7gXR.css"])))=>i.map(i=>d[i]);
2
2
  var $h=Object.defineProperty;var Jh=(i,r,o)=>r in i?$h(i,r,{enumerable:!0,configurable:!0,writable:!0,value:o}):i[r]=o;var L=(i,r,o)=>Jh(i,typeof r!="symbol"?r+"":r,o);function Xh(i,r){for(var o=0;o<r.length;o++){const c=r[o];if(typeof c!="string"&&!Array.isArray(c)){for(const u in c)if(u!=="default"&&!(u in i)){const p=Object.getOwnPropertyDescriptor(c,u);p&&Object.defineProperty(i,u,p.get?p:{enumerable:!0,get:()=>c[u]})}}}return Object.freeze(Object.defineProperty(i,Symbol.toStringTag,{value:"Module"}))}(function(){const r=document.createElement("link").relList;if(r&&r.supports&&r.supports("modulepreload"))return;for(const u of document.querySelectorAll('link[rel="modulepreload"]'))c(u);new MutationObserver(u=>{for(const p of u)if(p.type==="childList")for(const y of p.addedNodes)y.tagName==="LINK"&&y.rel==="modulepreload"&&c(y)}).observe(document,{childList:!0,subtree:!0});function o(u){const p={};return u.integrity&&(p.integrity=u.integrity),u.referrerPolicy&&(p.referrerPolicy=u.referrerPolicy),u.crossOrigin==="use-credentials"?p.credentials="include":u.crossOrigin==="anonymous"?p.credentials="omit":p.credentials="same-origin",p}function c(u){if(u.ep)return;u.ep=!0;const p=o(u);fetch(u.href,p)}})();function Vd(i){return i&&i.__esModule&&Object.prototype.hasOwnProperty.call(i,"default")?i.default:i}var Ls={exports:{}},qi={},Rs={exports:{}},G={};/**
3
3
  * @license React
4
4
  * react.production.min.js
@@ -38,7 +38,7 @@ var $h=Object.defineProperty;var Jh=(i,r,o)=>r in i?$h(i,r,{enumerable:!0,config
38
38
  `+s[d].replace(" at new "," at ");return e.displayName&&h.includes("<anonymous>")&&(h=h.replace("<anonymous>",e.displayName)),h}while(1<=d&&0<=f);break}}}finally{q=!1,Error.prepareStackTrace=a}return(e=e?e.displayName||e.name:"")?v(e):""}function $(e){switch(e.tag){case 5:return v(e.type);case 16:return v("Lazy");case 13:return v("Suspense");case 19:return v("SuspenseList");case 0:case 2:case 15:return e=K(e.type,!1),e;case 11:return e=K(e.type.render,!1),e;case 1:return e=K(e.type,!0),e;default:return""}}function J(e){if(e==null)return null;if(typeof e=="function")return e.displayName||e.name||null;if(typeof e=="string")return e;switch(e){case We:return"Fragment";case Ie:return"Portal";case _t:return"Profiler";case at:return"StrictMode";case Qe:return"Suspense";case pt:return"SuspenseList"}if(typeof e=="object")switch(e.$$typeof){case ua:return(e.displayName||"Context")+".Consumer";case Et:return(e._context.displayName||"Context")+".Provider";case wt:var t=e.render;return e=e.displayName,e||(e=t.displayName||t.name||"",e=e!==""?"ForwardRef("+e+")":"ForwardRef"),e;case vt:return t=e.displayName||null,t!==null?t:J(e.type)||"Memo";case _e:t=e._payload,e=e._init;try{return J(e(t))}catch{}}return null}function re(e){var t=e.type;switch(e.tag){case 24:return"Cache";case 9:return(t.displayName||"Context")+".Consumer";case 10:return(t._context.displayName||"Context")+".Provider";case 18:return"DehydratedFragment";case 11:return e=t.render,e=e.displayName||e.name||"",t.displayName||(e!==""?"ForwardRef("+e+")":"ForwardRef");case 7:return"Fragment";case 5:return t;case 4:return"Portal";case 3:return"Root";case 6:return"Text";case 16:return J(t);case 8:return t===at?"StrictMode":"Mode";case 22:return"Offscreen";case 12:return"Profiler";case 21:return"Scope";case 13:return"Suspense";case 19:return"SuspenseList";case 25:return"TracingMarker";case 1:case 0:case 17:case 2:case 14:case 15:if(typeof t=="function")return t.displayName||t.name||null;if(typeof t=="string")return t}return null}function te(e){switch(typeof e){case"boolean":case"number":case"string":case"undefined":return e;case"object":return e;default:return""}}function ce(e){var t=e.type;return(e=e.nodeName)&&e.toLowerCase()==="input"&&(t==="checkbox"||t==="radio")}function Ye(e){var t=ce(e)?"checked":"value",a=Object.getOwnPropertyDescriptor(e.constructor.prototype,t),n=""+e[t];if(!e.hasOwnProperty(t)&&typeof a<"u"&&typeof a.get=="function"&&typeof a.set=="function"){var s=a.get,l=a.set;return Object.defineProperty(e,t,{configurable:!0,get:function(){return s.call(this)},set:function(d){n=""+d,l.call(this,d)}}),Object.defineProperty(e,t,{enumerable:a.enumerable}),{getValue:function(){return n},setValue:function(d){n=""+d},stopTracking:function(){e._valueTracker=null,delete e[t]}}}}function Zi(e){e._valueTracker||(e._valueTracker=Ye(e))}function ol(e){if(!e)return!1;var t=e._valueTracker;if(!t)return!0;var a=t.getValue(),n="";return e&&(n=ce(e)?e.checked?"true":"false":e.value),e=n,e!==a?(t.setValue(e),!0):!1}function er(e){if(e=e||(typeof document<"u"?document:void 0),typeof e>"u")return null;try{return e.activeElement||e.body}catch{return e.body}}function xn(e,t){var a=t.checked;return I({},t,{defaultChecked:void 0,defaultValue:void 0,value:void 0,checked:a??e._wrapperState.initialChecked})}function sl(e,t){var a=t.defaultValue==null?"":t.defaultValue,n=t.checked!=null?t.checked:t.defaultChecked;a=te(t.value!=null?t.value:a),e._wrapperState={initialChecked:n,initialValue:a,controlled:t.type==="checkbox"||t.type==="radio"?t.checked!=null:t.value!=null}}function ll(e,t){t=t.checked,t!=null&&ut(e,"checked",t,!1)}function On(e,t){ll(e,t);var a=te(t.value),n=t.type;if(a!=null)n==="number"?(a===0&&e.value===""||e.value!=a)&&(e.value=""+a):e.value!==""+a&&(e.value=""+a);else if(n==="submit"||n==="reset"){e.removeAttribute("value");return}t.hasOwnProperty("value")?Hn(e,t.type,a):t.hasOwnProperty("defaultValue")&&Hn(e,t.type,te(t.defaultValue)),t.checked==null&&t.defaultChecked!=null&&(e.defaultChecked=!!t.defaultChecked)}function cl(e,t,a){if(t.hasOwnProperty("value")||t.hasOwnProperty("defaultValue")){var n=t.type;if(!(n!=="submit"&&n!=="reset"||t.value!==void 0&&t.value!==null))return;t=""+e._wrapperState.initialValue,a||t===e.value||(e.value=t),e.defaultValue=t}a=e.name,a!==""&&(e.name=""),e.defaultChecked=!!e._wrapperState.initialChecked,a!==""&&(e.name=a)}function Hn(e,t,a){(t!=="number"||er(e.ownerDocument)!==e)&&(a==null?e.defaultValue=""+e._wrapperState.initialValue:e.defaultValue!==""+a&&(e.defaultValue=""+a))}var oi=Array.isArray;function Ra(e,t,a,n){if(e=e.options,t){t={};for(var s=0;s<a.length;s++)t["$"+a[s]]=!0;for(a=0;a<e.length;a++)s=t.hasOwnProperty("$"+e[a].value),e[a].selected!==s&&(e[a].selected=s),s&&n&&(e[a].defaultSelected=!0)}else{for(a=""+te(a),t=null,s=0;s<e.length;s++){if(e[s].value===a){e[s].selected=!0,n&&(e[s].defaultSelected=!0);return}t!==null||e[s].disabled||(t=e[s])}t!==null&&(t.selected=!0)}}function Nn(e,t){if(t.dangerouslySetInnerHTML!=null)throw Error(o(91));return I({},t,{value:void 0,defaultValue:void 0,children:""+e._wrapperState.initialValue})}function ul(e,t){var a=t.value;if(a==null){if(a=t.children,t=t.defaultValue,a!=null){if(t!=null)throw Error(o(92));if(oi(a)){if(1<a.length)throw Error(o(93));a=a[0]}t=a}t==null&&(t=""),a=t}e._wrapperState={initialValue:te(a)}}function dl(e,t){var a=te(t.value),n=te(t.defaultValue);a!=null&&(a=""+a,a!==e.value&&(e.value=a),t.defaultValue==null&&e.defaultValue!==a&&(e.defaultValue=a)),n!=null&&(e.defaultValue=""+n)}function pl(e){var t=e.textContent;t===e._wrapperState.initialValue&&t!==""&&t!==null&&(e.value=t)}function fl(e){switch(e){case"svg":return"http://www.w3.org/2000/svg";case"math":return"http://www.w3.org/1998/Math/MathML";default:return"http://www.w3.org/1999/xhtml"}}function Bn(e,t){return e==null||e==="http://www.w3.org/1999/xhtml"?fl(t):e==="http://www.w3.org/2000/svg"&&t==="foreignObject"?"http://www.w3.org/1999/xhtml":e}var tr,hl=(function(e){return typeof MSApp<"u"&&MSApp.execUnsafeLocalFunction?function(t,a,n,s){MSApp.execUnsafeLocalFunction(function(){return e(t,a,n,s)})}:e})(function(e,t){if(e.namespaceURI!=="http://www.w3.org/2000/svg"||"innerHTML"in e)e.innerHTML=t;else{for(tr=tr||document.createElement("div"),tr.innerHTML="<svg>"+t.valueOf().toString()+"</svg>",t=tr.firstChild;e.firstChild;)e.removeChild(e.firstChild);for(;t.firstChild;)e.appendChild(t.firstChild)}});function si(e,t){if(t){var a=e.firstChild;if(a&&a===e.lastChild&&a.nodeType===3){a.nodeValue=t;return}}e.textContent=t}var li={animationIterationCount:!0,aspectRatio:!0,borderImageOutset:!0,borderImageSlice:!0,borderImageWidth:!0,boxFlex:!0,boxFlexGroup:!0,boxOrdinalGroup:!0,columnCount:!0,columns:!0,flex:!0,flexGrow:!0,flexPositive:!0,flexShrink:!0,flexNegative:!0,flexOrder:!0,gridArea:!0,gridRow:!0,gridRowEnd:!0,gridRowSpan:!0,gridRowStart:!0,gridColumn:!0,gridColumnEnd:!0,gridColumnSpan:!0,gridColumnStart:!0,fontWeight:!0,lineClamp:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,tabSize:!0,widows:!0,zIndex:!0,zoom:!0,fillOpacity:!0,floodOpacity:!0,stopOpacity:!0,strokeDasharray:!0,strokeDashoffset:!0,strokeMiterlimit:!0,strokeOpacity:!0,strokeWidth:!0},Zp=["Webkit","ms","Moz","O"];Object.keys(li).forEach(function(e){Zp.forEach(function(t){t=t+e.charAt(0).toUpperCase()+e.substring(1),li[t]=li[e]})});function ml(e,t,a){return t==null||typeof t=="boolean"||t===""?"":a||typeof t!="number"||t===0||li.hasOwnProperty(e)&&li[e]?(""+t).trim():t+"px"}function gl(e,t){e=e.style;for(var a in t)if(t.hasOwnProperty(a)){var n=a.indexOf("--")===0,s=ml(a,t[a],n);a==="float"&&(a="cssFloat"),n?e.setProperty(a,s):e[a]=s}}var ef=I({menuitem:!0},{area:!0,base:!0,br:!0,col:!0,embed:!0,hr:!0,img:!0,input:!0,keygen:!0,link:!0,meta:!0,param:!0,source:!0,track:!0,wbr:!0});function Un(e,t){if(t){if(ef[e]&&(t.children!=null||t.dangerouslySetInnerHTML!=null))throw Error(o(137,e));if(t.dangerouslySetInnerHTML!=null){if(t.children!=null)throw Error(o(60));if(typeof t.dangerouslySetInnerHTML!="object"||!("__html"in t.dangerouslySetInnerHTML))throw Error(o(61))}if(t.style!=null&&typeof t.style!="object")throw Error(o(62))}}function Wn(e,t){if(e.indexOf("-")===-1)return typeof t.is=="string";switch(e){case"annotation-xml":case"color-profile":case"font-face":case"font-face-src":case"font-face-uri":case"font-face-format":case"font-face-name":case"missing-glyph":return!1;default:return!0}}var _n=null;function Vn(e){return e=e.target||e.srcElement||window,e.correspondingUseElement&&(e=e.correspondingUseElement),e.nodeType===3?e.parentNode:e}var zn=null,Fa=null,Ea=null;function bl(e){if(e=Fi(e)){if(typeof zn!="function")throw Error(o(280));var t=e.stateNode;t&&(t=Cr(t),zn(e.stateNode,e.type,t))}}function yl(e){Fa?Ea?Ea.push(e):Ea=[e]:Fa=e}function Sl(){if(Fa){var e=Fa,t=Ea;if(Ea=Fa=null,bl(e),t)for(e=0;e<t.length;e++)bl(t[e])}}function Tl(e,t){return e(t)}function kl(){}var jn=!1;function wl(e,t,a){if(jn)return e(t,a);jn=!0;try{return Tl(e,t,a)}finally{jn=!1,(Fa!==null||Ea!==null)&&(kl(),Sl())}}function ci(e,t){var a=e.stateNode;if(a===null)return null;var n=Cr(a);if(n===null)return null;a=n[t];e:switch(t){case"onClick":case"onClickCapture":case"onDoubleClick":case"onDoubleClickCapture":case"onMouseDown":case"onMouseDownCapture":case"onMouseMove":case"onMouseMoveCapture":case"onMouseUp":case"onMouseUpCapture":case"onMouseEnter":(n=!n.disabled)||(e=e.type,n=!(e==="button"||e==="input"||e==="select"||e==="textarea")),e=!n;break e;default:e=!1}if(e)return null;if(a&&typeof a!="function")throw Error(o(231,t,typeof a));return a}var qn=!1;if(S)try{var ui={};Object.defineProperty(ui,"passive",{get:function(){qn=!0}}),window.addEventListener("test",ui,ui),window.removeEventListener("test",ui,ui)}catch{qn=!1}function tf(e,t,a,n,s,l,d,f,h){var k=Array.prototype.slice.call(arguments,3);try{t.apply(a,k)}catch(C){this.onError(C)}}var di=!1,ar=null,ir=!1,Gn=null,af={onError:function(e){di=!0,ar=e}};function rf(e,t,a,n,s,l,d,f,h){di=!1,ar=null,tf.apply(af,arguments)}function nf(e,t,a,n,s,l,d,f,h){if(rf.apply(this,arguments),di){if(di){var k=ar;di=!1,ar=null}else throw Error(o(198));ir||(ir=!0,Gn=k)}}function da(e){var t=e,a=e;if(e.alternate)for(;t.return;)t=t.return;else{e=t;do t=e,(t.flags&4098)!==0&&(a=t.return),e=t.return;while(e)}return t.tag===3?a:null}function vl(e){if(e.tag===13){var t=e.memoizedState;if(t===null&&(e=e.alternate,e!==null&&(t=e.memoizedState)),t!==null)return t.dehydrated}return null}function Cl(e){if(da(e)!==e)throw Error(o(188))}function of(e){var t=e.alternate;if(!t){if(t=da(e),t===null)throw Error(o(188));return t!==e?null:e}for(var a=e,n=t;;){var s=a.return;if(s===null)break;var l=s.alternate;if(l===null){if(n=s.return,n!==null){a=n;continue}break}if(s.child===l.child){for(l=s.child;l;){if(l===a)return Cl(s),e;if(l===n)return Cl(s),t;l=l.sibling}throw Error(o(188))}if(a.return!==n.return)a=s,n=l;else{for(var d=!1,f=s.child;f;){if(f===a){d=!0,a=s,n=l;break}if(f===n){d=!0,n=s,a=l;break}f=f.sibling}if(!d){for(f=l.child;f;){if(f===a){d=!0,a=l,n=s;break}if(f===n){d=!0,n=l,a=s;break}f=f.sibling}if(!d)throw Error(o(189))}}if(a.alternate!==n)throw Error(o(190))}if(a.tag!==3)throw Error(o(188));return a.stateNode.current===a?e:t}function Dl(e){return e=of(e),e!==null?Pl(e):null}function Pl(e){if(e.tag===5||e.tag===6)return e;for(e=e.child;e!==null;){var t=Pl(e);if(t!==null)return t;e=e.sibling}return null}var Al=r.unstable_scheduleCallback,Ll=r.unstable_cancelCallback,sf=r.unstable_shouldYield,lf=r.unstable_requestPaint,me=r.unstable_now,cf=r.unstable_getCurrentPriorityLevel,Kn=r.unstable_ImmediatePriority,Rl=r.unstable_UserBlockingPriority,rr=r.unstable_NormalPriority,uf=r.unstable_LowPriority,Fl=r.unstable_IdlePriority,nr=null,Ct=null;function df(e){if(Ct&&typeof Ct.onCommitFiberRoot=="function")try{Ct.onCommitFiberRoot(nr,e,void 0,(e.current.flags&128)===128)}catch{}}var ft=Math.clz32?Math.clz32:hf,pf=Math.log,ff=Math.LN2;function hf(e){return e>>>=0,e===0?32:31-(pf(e)/ff|0)|0}var or=64,sr=4194304;function pi(e){switch(e&-e){case 1:return 1;case 2:return 2;case 4:return 4;case 8:return 8;case 16:return 16;case 32:return 32;case 64:case 128:case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:return e&4194240;case 4194304:case 8388608:case 16777216:case 33554432:case 67108864:return e&130023424;case 134217728:return 134217728;case 268435456:return 268435456;case 536870912:return 536870912;case 1073741824:return 1073741824;default:return e}}function lr(e,t){var a=e.pendingLanes;if(a===0)return 0;var n=0,s=e.suspendedLanes,l=e.pingedLanes,d=a&268435455;if(d!==0){var f=d&~s;f!==0?n=pi(f):(l&=d,l!==0&&(n=pi(l)))}else d=a&~s,d!==0?n=pi(d):l!==0&&(n=pi(l));if(n===0)return 0;if(t!==0&&t!==n&&(t&s)===0&&(s=n&-n,l=t&-t,s>=l||s===16&&(l&4194240)!==0))return t;if((n&4)!==0&&(n|=a&16),t=e.entangledLanes,t!==0)for(e=e.entanglements,t&=n;0<t;)a=31-ft(t),s=1<<a,n|=e[a],t&=~s;return n}function mf(e,t){switch(e){case 1:case 2:case 4:return t+250;case 8:case 16:case 32:case 64:case 128:case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:return t+5e3;case 4194304:case 8388608:case 16777216:case 33554432:case 67108864:return-1;case 134217728:case 268435456:case 536870912:case 1073741824:return-1;default:return-1}}function gf(e,t){for(var a=e.suspendedLanes,n=e.pingedLanes,s=e.expirationTimes,l=e.pendingLanes;0<l;){var d=31-ft(l),f=1<<d,h=s[d];h===-1?((f&a)===0||(f&n)!==0)&&(s[d]=mf(f,t)):h<=t&&(e.expiredLanes|=f),l&=~f}}function Qn(e){return e=e.pendingLanes&-1073741825,e!==0?e:e&1073741824?1073741824:0}function El(){var e=or;return or<<=1,(or&4194240)===0&&(or=64),e}function Yn(e){for(var t=[],a=0;31>a;a++)t.push(e);return t}function fi(e,t,a){e.pendingLanes|=t,t!==536870912&&(e.suspendedLanes=0,e.pingedLanes=0),e=e.eventTimes,t=31-ft(t),e[t]=a}function bf(e,t){var a=e.pendingLanes&~t;e.pendingLanes=t,e.suspendedLanes=0,e.pingedLanes=0,e.expiredLanes&=t,e.mutableReadLanes&=t,e.entangledLanes&=t,t=e.entanglements;var n=e.eventTimes;for(e=e.expirationTimes;0<a;){var s=31-ft(a),l=1<<s;t[s]=0,n[s]=-1,e[s]=-1,a&=~l}}function $n(e,t){var a=e.entangledLanes|=t;for(e=e.entanglements;a;){var n=31-ft(a),s=1<<n;s&t|e[n]&t&&(e[n]|=t),a&=~s}}var ae=0;function Ml(e){return e&=-e,1<e?4<e?(e&268435455)!==0?16:536870912:4:1}var Il,Jn,xl,Ol,Hl,Xn=!1,cr=[],Vt=null,zt=null,jt=null,hi=new Map,mi=new Map,qt=[],yf="mousedown mouseup touchcancel touchend touchstart auxclick dblclick pointercancel pointerdown pointerup dragend dragstart drop compositionend compositionstart keydown keypress keyup input textInput copy cut paste click change contextmenu reset submit".split(" ");function Nl(e,t){switch(e){case"focusin":case"focusout":Vt=null;break;case"dragenter":case"dragleave":zt=null;break;case"mouseover":case"mouseout":jt=null;break;case"pointerover":case"pointerout":hi.delete(t.pointerId);break;case"gotpointercapture":case"lostpointercapture":mi.delete(t.pointerId)}}function gi(e,t,a,n,s,l){return e===null||e.nativeEvent!==l?(e={blockedOn:t,domEventName:a,eventSystemFlags:n,nativeEvent:l,targetContainers:[s]},t!==null&&(t=Fi(t),t!==null&&Jn(t)),e):(e.eventSystemFlags|=n,t=e.targetContainers,s!==null&&t.indexOf(s)===-1&&t.push(s),e)}function Sf(e,t,a,n,s){switch(t){case"focusin":return Vt=gi(Vt,e,t,a,n,s),!0;case"dragenter":return zt=gi(zt,e,t,a,n,s),!0;case"mouseover":return jt=gi(jt,e,t,a,n,s),!0;case"pointerover":var l=s.pointerId;return hi.set(l,gi(hi.get(l)||null,e,t,a,n,s)),!0;case"gotpointercapture":return l=s.pointerId,mi.set(l,gi(mi.get(l)||null,e,t,a,n,s)),!0}return!1}function Bl(e){var t=pa(e.target);if(t!==null){var a=da(t);if(a!==null){if(t=a.tag,t===13){if(t=vl(a),t!==null){e.blockedOn=t,Hl(e.priority,function(){xl(a)});return}}else if(t===3&&a.stateNode.current.memoizedState.isDehydrated){e.blockedOn=a.tag===3?a.stateNode.containerInfo:null;return}}}e.blockedOn=null}function ur(e){if(e.blockedOn!==null)return!1;for(var t=e.targetContainers;0<t.length;){var a=eo(e.domEventName,e.eventSystemFlags,t[0],e.nativeEvent);if(a===null){a=e.nativeEvent;var n=new a.constructor(a.type,a);_n=n,a.target.dispatchEvent(n),_n=null}else return t=Fi(a),t!==null&&Jn(t),e.blockedOn=a,!1;t.shift()}return!0}function Ul(e,t,a){ur(e)&&a.delete(t)}function Tf(){Xn=!1,Vt!==null&&ur(Vt)&&(Vt=null),zt!==null&&ur(zt)&&(zt=null),jt!==null&&ur(jt)&&(jt=null),hi.forEach(Ul),mi.forEach(Ul)}function bi(e,t){e.blockedOn===t&&(e.blockedOn=null,Xn||(Xn=!0,r.unstable_scheduleCallback(r.unstable_NormalPriority,Tf)))}function yi(e){function t(s){return bi(s,e)}if(0<cr.length){bi(cr[0],e);for(var a=1;a<cr.length;a++){var n=cr[a];n.blockedOn===e&&(n.blockedOn=null)}}for(Vt!==null&&bi(Vt,e),zt!==null&&bi(zt,e),jt!==null&&bi(jt,e),hi.forEach(t),mi.forEach(t),a=0;a<qt.length;a++)n=qt[a],n.blockedOn===e&&(n.blockedOn=null);for(;0<qt.length&&(a=qt[0],a.blockedOn===null);)Bl(a),a.blockedOn===null&&qt.shift()}var Ma=Ae.ReactCurrentBatchConfig,dr=!0;function kf(e,t,a,n){var s=ae,l=Ma.transition;Ma.transition=null;try{ae=1,Zn(e,t,a,n)}finally{ae=s,Ma.transition=l}}function wf(e,t,a,n){var s=ae,l=Ma.transition;Ma.transition=null;try{ae=4,Zn(e,t,a,n)}finally{ae=s,Ma.transition=l}}function Zn(e,t,a,n){if(dr){var s=eo(e,t,a,n);if(s===null)yo(e,t,n,pr,a),Nl(e,n);else if(Sf(s,e,t,a,n))n.stopPropagation();else if(Nl(e,n),t&4&&-1<yf.indexOf(e)){for(;s!==null;){var l=Fi(s);if(l!==null&&Il(l),l=eo(e,t,a,n),l===null&&yo(e,t,n,pr,a),l===s)break;s=l}s!==null&&n.stopPropagation()}else yo(e,t,n,null,a)}}var pr=null;function eo(e,t,a,n){if(pr=null,e=Vn(n),e=pa(e),e!==null)if(t=da(e),t===null)e=null;else if(a=t.tag,a===13){if(e=vl(t),e!==null)return e;e=null}else if(a===3){if(t.stateNode.current.memoizedState.isDehydrated)return t.tag===3?t.stateNode.containerInfo:null;e=null}else t!==e&&(e=null);return pr=e,null}function Wl(e){switch(e){case"cancel":case"click":case"close":case"contextmenu":case"copy":case"cut":case"auxclick":case"dblclick":case"dragend":case"dragstart":case"drop":case"focusin":case"focusout":case"input":case"invalid":case"keydown":case"keypress":case"keyup":case"mousedown":case"mouseup":case"paste":case"pause":case"play":case"pointercancel":case"pointerdown":case"pointerup":case"ratechange":case"reset":case"resize":case"seeked":case"submit":case"touchcancel":case"touchend":case"touchstart":case"volumechange":case"change":case"selectionchange":case"textInput":case"compositionstart":case"compositionend":case"compositionupdate":case"beforeblur":case"afterblur":case"beforeinput":case"blur":case"fullscreenchange":case"focus":case"hashchange":case"popstate":case"select":case"selectstart":return 1;case"drag":case"dragenter":case"dragexit":case"dragleave":case"dragover":case"mousemove":case"mouseout":case"mouseover":case"pointermove":case"pointerout":case"pointerover":case"scroll":case"toggle":case"touchmove":case"wheel":case"mouseenter":case"mouseleave":case"pointerenter":case"pointerleave":return 4;case"message":switch(cf()){case Kn:return 1;case Rl:return 4;case rr:case uf:return 16;case Fl:return 536870912;default:return 16}default:return 16}}var Gt=null,to=null,fr=null;function _l(){if(fr)return fr;var e,t=to,a=t.length,n,s="value"in Gt?Gt.value:Gt.textContent,l=s.length;for(e=0;e<a&&t[e]===s[e];e++);var d=a-e;for(n=1;n<=d&&t[a-n]===s[l-n];n++);return fr=s.slice(e,1<n?1-n:void 0)}function hr(e){var t=e.keyCode;return"charCode"in e?(e=e.charCode,e===0&&t===13&&(e=13)):e=t,e===10&&(e=13),32<=e||e===13?e:0}function mr(){return!0}function Vl(){return!1}function $e(e){function t(a,n,s,l,d){this._reactName=a,this._targetInst=s,this.type=n,this.nativeEvent=l,this.target=d,this.currentTarget=null;for(var f in e)e.hasOwnProperty(f)&&(a=e[f],this[f]=a?a(l):l[f]);return this.isDefaultPrevented=(l.defaultPrevented!=null?l.defaultPrevented:l.returnValue===!1)?mr:Vl,this.isPropagationStopped=Vl,this}return I(t.prototype,{preventDefault:function(){this.defaultPrevented=!0;var a=this.nativeEvent;a&&(a.preventDefault?a.preventDefault():typeof a.returnValue!="unknown"&&(a.returnValue=!1),this.isDefaultPrevented=mr)},stopPropagation:function(){var a=this.nativeEvent;a&&(a.stopPropagation?a.stopPropagation():typeof a.cancelBubble!="unknown"&&(a.cancelBubble=!0),this.isPropagationStopped=mr)},persist:function(){},isPersistent:mr}),t}var Ia={eventPhase:0,bubbles:0,cancelable:0,timeStamp:function(e){return e.timeStamp||Date.now()},defaultPrevented:0,isTrusted:0},ao=$e(Ia),Si=I({},Ia,{view:0,detail:0}),vf=$e(Si),io,ro,Ti,gr=I({},Si,{screenX:0,screenY:0,clientX:0,clientY:0,pageX:0,pageY:0,ctrlKey:0,shiftKey:0,altKey:0,metaKey:0,getModifierState:oo,button:0,buttons:0,relatedTarget:function(e){return e.relatedTarget===void 0?e.fromElement===e.srcElement?e.toElement:e.fromElement:e.relatedTarget},movementX:function(e){return"movementX"in e?e.movementX:(e!==Ti&&(Ti&&e.type==="mousemove"?(io=e.screenX-Ti.screenX,ro=e.screenY-Ti.screenY):ro=io=0,Ti=e),io)},movementY:function(e){return"movementY"in e?e.movementY:ro}}),zl=$e(gr),Cf=I({},gr,{dataTransfer:0}),Df=$e(Cf),Pf=I({},Si,{relatedTarget:0}),no=$e(Pf),Af=I({},Ia,{animationName:0,elapsedTime:0,pseudoElement:0}),Lf=$e(Af),Rf=I({},Ia,{clipboardData:function(e){return"clipboardData"in e?e.clipboardData:window.clipboardData}}),Ff=$e(Rf),Ef=I({},Ia,{data:0}),jl=$e(Ef),Mf={Esc:"Escape",Spacebar:" ",Left:"ArrowLeft",Up:"ArrowUp",Right:"ArrowRight",Down:"ArrowDown",Del:"Delete",Win:"OS",Menu:"ContextMenu",Apps:"ContextMenu",Scroll:"ScrollLock",MozPrintableKey:"Unidentified"},If={8:"Backspace",9:"Tab",12:"Clear",13:"Enter",16:"Shift",17:"Control",18:"Alt",19:"Pause",20:"CapsLock",27:"Escape",32:" ",33:"PageUp",34:"PageDown",35:"End",36:"Home",37:"ArrowLeft",38:"ArrowUp",39:"ArrowRight",40:"ArrowDown",45:"Insert",46:"Delete",112:"F1",113:"F2",114:"F3",115:"F4",116:"F5",117:"F6",118:"F7",119:"F8",120:"F9",121:"F10",122:"F11",123:"F12",144:"NumLock",145:"ScrollLock",224:"Meta"},xf={Alt:"altKey",Control:"ctrlKey",Meta:"metaKey",Shift:"shiftKey"};function Of(e){var t=this.nativeEvent;return t.getModifierState?t.getModifierState(e):(e=xf[e])?!!t[e]:!1}function oo(){return Of}var Hf=I({},Si,{key:function(e){if(e.key){var t=Mf[e.key]||e.key;if(t!=="Unidentified")return t}return e.type==="keypress"?(e=hr(e),e===13?"Enter":String.fromCharCode(e)):e.type==="keydown"||e.type==="keyup"?If[e.keyCode]||"Unidentified":""},code:0,location:0,ctrlKey:0,shiftKey:0,altKey:0,metaKey:0,repeat:0,locale:0,getModifierState:oo,charCode:function(e){return e.type==="keypress"?hr(e):0},keyCode:function(e){return e.type==="keydown"||e.type==="keyup"?e.keyCode:0},which:function(e){return e.type==="keypress"?hr(e):e.type==="keydown"||e.type==="keyup"?e.keyCode:0}}),Nf=$e(Hf),Bf=I({},gr,{pointerId:0,width:0,height:0,pressure:0,tangentialPressure:0,tiltX:0,tiltY:0,twist:0,pointerType:0,isPrimary:0}),ql=$e(Bf),Uf=I({},Si,{touches:0,targetTouches:0,changedTouches:0,altKey:0,metaKey:0,ctrlKey:0,shiftKey:0,getModifierState:oo}),Wf=$e(Uf),_f=I({},Ia,{propertyName:0,elapsedTime:0,pseudoElement:0}),Vf=$e(_f),zf=I({},gr,{deltaX:function(e){return"deltaX"in e?e.deltaX:"wheelDeltaX"in e?-e.wheelDeltaX:0},deltaY:function(e){return"deltaY"in e?e.deltaY:"wheelDeltaY"in e?-e.wheelDeltaY:"wheelDelta"in e?-e.wheelDelta:0},deltaZ:0,deltaMode:0}),jf=$e(zf),qf=[9,13,27,32],so=S&&"CompositionEvent"in window,ki=null;S&&"documentMode"in document&&(ki=document.documentMode);var Gf=S&&"TextEvent"in window&&!ki,Gl=S&&(!so||ki&&8<ki&&11>=ki),Kl=" ",Ql=!1;function Yl(e,t){switch(e){case"keyup":return qf.indexOf(t.keyCode)!==-1;case"keydown":return t.keyCode!==229;case"keypress":case"mousedown":case"focusout":return!0;default:return!1}}function $l(e){return e=e.detail,typeof e=="object"&&"data"in e?e.data:null}var xa=!1;function Kf(e,t){switch(e){case"compositionend":return $l(t);case"keypress":return t.which!==32?null:(Ql=!0,Kl);case"textInput":return e=t.data,e===Kl&&Ql?null:e;default:return null}}function Qf(e,t){if(xa)return e==="compositionend"||!so&&Yl(e,t)?(e=_l(),fr=to=Gt=null,xa=!1,e):null;switch(e){case"paste":return null;case"keypress":if(!(t.ctrlKey||t.altKey||t.metaKey)||t.ctrlKey&&t.altKey){if(t.char&&1<t.char.length)return t.char;if(t.which)return String.fromCharCode(t.which)}return null;case"compositionend":return Gl&&t.locale!=="ko"?null:t.data;default:return null}}var Yf={color:!0,date:!0,datetime:!0,"datetime-local":!0,email:!0,month:!0,number:!0,password:!0,range:!0,search:!0,tel:!0,text:!0,time:!0,url:!0,week:!0};function Jl(e){var t=e&&e.nodeName&&e.nodeName.toLowerCase();return t==="input"?!!Yf[e.type]:t==="textarea"}function Xl(e,t,a,n){yl(n),t=kr(t,"onChange"),0<t.length&&(a=new ao("onChange","change",null,a,n),e.push({event:a,listeners:t}))}var wi=null,vi=null;function $f(e){gc(e,0)}function br(e){var t=Ua(e);if(ol(t))return e}function Jf(e,t){if(e==="change")return t}var Zl=!1;if(S){var lo;if(S){var co="oninput"in document;if(!co){var ec=document.createElement("div");ec.setAttribute("oninput","return;"),co=typeof ec.oninput=="function"}lo=co}else lo=!1;Zl=lo&&(!document.documentMode||9<document.documentMode)}function tc(){wi&&(wi.detachEvent("onpropertychange",ac),vi=wi=null)}function ac(e){if(e.propertyName==="value"&&br(vi)){var t=[];Xl(t,vi,e,Vn(e)),wl($f,t)}}function Xf(e,t,a){e==="focusin"?(tc(),wi=t,vi=a,wi.attachEvent("onpropertychange",ac)):e==="focusout"&&tc()}function Zf(e){if(e==="selectionchange"||e==="keyup"||e==="keydown")return br(vi)}function eh(e,t){if(e==="click")return br(t)}function th(e,t){if(e==="input"||e==="change")return br(t)}function ah(e,t){return e===t&&(e!==0||1/e===1/t)||e!==e&&t!==t}var ht=typeof Object.is=="function"?Object.is:ah;function Ci(e,t){if(ht(e,t))return!0;if(typeof e!="object"||e===null||typeof t!="object"||t===null)return!1;var a=Object.keys(e),n=Object.keys(t);if(a.length!==n.length)return!1;for(n=0;n<a.length;n++){var s=a[n];if(!A.call(t,s)||!ht(e[s],t[s]))return!1}return!0}function ic(e){for(;e&&e.firstChild;)e=e.firstChild;return e}function rc(e,t){var a=ic(e);e=0;for(var n;a;){if(a.nodeType===3){if(n=e+a.textContent.length,e<=t&&n>=t)return{node:a,offset:t-e};e=n}e:{for(;a;){if(a.nextSibling){a=a.nextSibling;break e}a=a.parentNode}a=void 0}a=ic(a)}}function nc(e,t){return e&&t?e===t?!0:e&&e.nodeType===3?!1:t&&t.nodeType===3?nc(e,t.parentNode):"contains"in e?e.contains(t):e.compareDocumentPosition?!!(e.compareDocumentPosition(t)&16):!1:!1}function oc(){for(var e=window,t=er();t instanceof e.HTMLIFrameElement;){try{var a=typeof t.contentWindow.location.href=="string"}catch{a=!1}if(a)e=t.contentWindow;else break;t=er(e.document)}return t}function uo(e){var t=e&&e.nodeName&&e.nodeName.toLowerCase();return t&&(t==="input"&&(e.type==="text"||e.type==="search"||e.type==="tel"||e.type==="url"||e.type==="password")||t==="textarea"||e.contentEditable==="true")}function ih(e){var t=oc(),a=e.focusedElem,n=e.selectionRange;if(t!==a&&a&&a.ownerDocument&&nc(a.ownerDocument.documentElement,a)){if(n!==null&&uo(a)){if(t=n.start,e=n.end,e===void 0&&(e=t),"selectionStart"in a)a.selectionStart=t,a.selectionEnd=Math.min(e,a.value.length);else if(e=(t=a.ownerDocument||document)&&t.defaultView||window,e.getSelection){e=e.getSelection();var s=a.textContent.length,l=Math.min(n.start,s);n=n.end===void 0?l:Math.min(n.end,s),!e.extend&&l>n&&(s=n,n=l,l=s),s=rc(a,l);var d=rc(a,n);s&&d&&(e.rangeCount!==1||e.anchorNode!==s.node||e.anchorOffset!==s.offset||e.focusNode!==d.node||e.focusOffset!==d.offset)&&(t=t.createRange(),t.setStart(s.node,s.offset),e.removeAllRanges(),l>n?(e.addRange(t),e.extend(d.node,d.offset)):(t.setEnd(d.node,d.offset),e.addRange(t)))}}for(t=[],e=a;e=e.parentNode;)e.nodeType===1&&t.push({element:e,left:e.scrollLeft,top:e.scrollTop});for(typeof a.focus=="function"&&a.focus(),a=0;a<t.length;a++)e=t[a],e.element.scrollLeft=e.left,e.element.scrollTop=e.top}}var rh=S&&"documentMode"in document&&11>=document.documentMode,Oa=null,po=null,Di=null,fo=!1;function sc(e,t,a){var n=a.window===a?a.document:a.nodeType===9?a:a.ownerDocument;fo||Oa==null||Oa!==er(n)||(n=Oa,"selectionStart"in n&&uo(n)?n={start:n.selectionStart,end:n.selectionEnd}:(n=(n.ownerDocument&&n.ownerDocument.defaultView||window).getSelection(),n={anchorNode:n.anchorNode,anchorOffset:n.anchorOffset,focusNode:n.focusNode,focusOffset:n.focusOffset}),Di&&Ci(Di,n)||(Di=n,n=kr(po,"onSelect"),0<n.length&&(t=new ao("onSelect","select",null,t,a),e.push({event:t,listeners:n}),t.target=Oa)))}function yr(e,t){var a={};return a[e.toLowerCase()]=t.toLowerCase(),a["Webkit"+e]="webkit"+t,a["Moz"+e]="moz"+t,a}var Ha={animationend:yr("Animation","AnimationEnd"),animationiteration:yr("Animation","AnimationIteration"),animationstart:yr("Animation","AnimationStart"),transitionend:yr("Transition","TransitionEnd")},ho={},lc={};S&&(lc=document.createElement("div").style,"AnimationEvent"in window||(delete Ha.animationend.animation,delete Ha.animationiteration.animation,delete Ha.animationstart.animation),"TransitionEvent"in window||delete Ha.transitionend.transition);function Sr(e){if(ho[e])return ho[e];if(!Ha[e])return e;var t=Ha[e],a;for(a in t)if(t.hasOwnProperty(a)&&a in lc)return ho[e]=t[a];return e}var cc=Sr("animationend"),uc=Sr("animationiteration"),dc=Sr("animationstart"),pc=Sr("transitionend"),fc=new Map,hc="abort auxClick cancel canPlay canPlayThrough click close contextMenu copy cut drag dragEnd dragEnter dragExit dragLeave dragOver dragStart drop durationChange emptied encrypted ended error gotPointerCapture input invalid keyDown keyPress keyUp load loadedData loadedMetadata loadStart lostPointerCapture mouseDown mouseMove mouseOut mouseOver mouseUp paste pause play playing pointerCancel pointerDown pointerMove pointerOut pointerOver pointerUp progress rateChange reset resize seeked seeking stalled submit suspend timeUpdate touchCancel touchEnd touchStart volumeChange scroll toggle touchMove waiting wheel".split(" ");function Kt(e,t){fc.set(e,t),p(t,[e])}for(var mo=0;mo<hc.length;mo++){var go=hc[mo],nh=go.toLowerCase(),oh=go[0].toUpperCase()+go.slice(1);Kt(nh,"on"+oh)}Kt(cc,"onAnimationEnd"),Kt(uc,"onAnimationIteration"),Kt(dc,"onAnimationStart"),Kt("dblclick","onDoubleClick"),Kt("focusin","onFocus"),Kt("focusout","onBlur"),Kt(pc,"onTransitionEnd"),y("onMouseEnter",["mouseout","mouseover"]),y("onMouseLeave",["mouseout","mouseover"]),y("onPointerEnter",["pointerout","pointerover"]),y("onPointerLeave",["pointerout","pointerover"]),p("onChange","change click focusin focusout input keydown keyup selectionchange".split(" ")),p("onSelect","focusout contextmenu dragend focusin keydown keyup mousedown mouseup selectionchange".split(" ")),p("onBeforeInput",["compositionend","keypress","textInput","paste"]),p("onCompositionEnd","compositionend focusout keydown keypress keyup mousedown".split(" ")),p("onCompositionStart","compositionstart focusout keydown keypress keyup mousedown".split(" ")),p("onCompositionUpdate","compositionupdate focusout keydown keypress keyup mousedown".split(" "));var Pi="abort canplay canplaythrough durationchange emptied encrypted ended error loadeddata loadedmetadata loadstart pause play playing progress ratechange resize seeked seeking stalled suspend timeupdate volumechange waiting".split(" "),sh=new Set("cancel close invalid load scroll toggle".split(" ").concat(Pi));function mc(e,t,a){var n=e.type||"unknown-event";e.currentTarget=a,nf(n,t,void 0,e),e.currentTarget=null}function gc(e,t){t=(t&4)!==0;for(var a=0;a<e.length;a++){var n=e[a],s=n.event;n=n.listeners;e:{var l=void 0;if(t)for(var d=n.length-1;0<=d;d--){var f=n[d],h=f.instance,k=f.currentTarget;if(f=f.listener,h!==l&&s.isPropagationStopped())break e;mc(s,f,k),l=h}else for(d=0;d<n.length;d++){if(f=n[d],h=f.instance,k=f.currentTarget,f=f.listener,h!==l&&s.isPropagationStopped())break e;mc(s,f,k),l=h}}}if(ir)throw e=Gn,ir=!1,Gn=null,e}function se(e,t){var a=t[Co];a===void 0&&(a=t[Co]=new Set);var n=e+"__bubble";a.has(n)||(bc(t,e,2,!1),a.add(n))}function bo(e,t,a){var n=0;t&&(n|=4),bc(a,e,n,t)}var Tr="_reactListening"+Math.random().toString(36).slice(2);function Ai(e){if(!e[Tr]){e[Tr]=!0,c.forEach(function(a){a!=="selectionchange"&&(sh.has(a)||bo(a,!1,e),bo(a,!0,e))});var t=e.nodeType===9?e:e.ownerDocument;t===null||t[Tr]||(t[Tr]=!0,bo("selectionchange",!1,t))}}function bc(e,t,a,n){switch(Wl(t)){case 1:var s=kf;break;case 4:s=wf;break;default:s=Zn}a=s.bind(null,t,a,e),s=void 0,!qn||t!=="touchstart"&&t!=="touchmove"&&t!=="wheel"||(s=!0),n?s!==void 0?e.addEventListener(t,a,{capture:!0,passive:s}):e.addEventListener(t,a,!0):s!==void 0?e.addEventListener(t,a,{passive:s}):e.addEventListener(t,a,!1)}function yo(e,t,a,n,s){var l=n;if((t&1)===0&&(t&2)===0&&n!==null)e:for(;;){if(n===null)return;var d=n.tag;if(d===3||d===4){var f=n.stateNode.containerInfo;if(f===s||f.nodeType===8&&f.parentNode===s)break;if(d===4)for(d=n.return;d!==null;){var h=d.tag;if((h===3||h===4)&&(h=d.stateNode.containerInfo,h===s||h.nodeType===8&&h.parentNode===s))return;d=d.return}for(;f!==null;){if(d=pa(f),d===null)return;if(h=d.tag,h===5||h===6){n=l=d;continue e}f=f.parentNode}}n=n.return}wl(function(){var k=l,C=Vn(a),D=[];e:{var w=fc.get(e);if(w!==void 0){var F=ao,x=e;switch(e){case"keypress":if(hr(a)===0)break e;case"keydown":case"keyup":F=Nf;break;case"focusin":x="focus",F=no;break;case"focusout":x="blur",F=no;break;case"beforeblur":case"afterblur":F=no;break;case"click":if(a.button===2)break e;case"auxclick":case"dblclick":case"mousedown":case"mousemove":case"mouseup":case"mouseout":case"mouseover":case"contextmenu":F=zl;break;case"drag":case"dragend":case"dragenter":case"dragexit":case"dragleave":case"dragover":case"dragstart":case"drop":F=Df;break;case"touchcancel":case"touchend":case"touchmove":case"touchstart":F=Wf;break;case cc:case uc:case dc:F=Lf;break;case pc:F=Vf;break;case"scroll":F=vf;break;case"wheel":F=jf;break;case"copy":case"cut":case"paste":F=Ff;break;case"gotpointercapture":case"lostpointercapture":case"pointercancel":case"pointerdown":case"pointermove":case"pointerout":case"pointerover":case"pointerup":F=ql}var H=(t&4)!==0,ge=!H&&e==="scroll",b=H?w!==null?w+"Capture":null:w;H=[];for(var m=k,T;m!==null;){T=m;var P=T.stateNode;if(T.tag===5&&P!==null&&(T=P,b!==null&&(P=ci(m,b),P!=null&&H.push(Li(m,P,T)))),ge)break;m=m.return}0<H.length&&(w=new F(w,x,null,a,C),D.push({event:w,listeners:H}))}}if((t&7)===0){e:{if(w=e==="mouseover"||e==="pointerover",F=e==="mouseout"||e==="pointerout",w&&a!==_n&&(x=a.relatedTarget||a.fromElement)&&(pa(x)||x[Mt]))break e;if((F||w)&&(w=C.window===C?C:(w=C.ownerDocument)?w.defaultView||w.parentWindow:window,F?(x=a.relatedTarget||a.toElement,F=k,x=x?pa(x):null,x!==null&&(ge=da(x),x!==ge||x.tag!==5&&x.tag!==6)&&(x=null)):(F=null,x=k),F!==x)){if(H=zl,P="onMouseLeave",b="onMouseEnter",m="mouse",(e==="pointerout"||e==="pointerover")&&(H=ql,P="onPointerLeave",b="onPointerEnter",m="pointer"),ge=F==null?w:Ua(F),T=x==null?w:Ua(x),w=new H(P,m+"leave",F,a,C),w.target=ge,w.relatedTarget=T,P=null,pa(C)===k&&(H=new H(b,m+"enter",x,a,C),H.target=T,H.relatedTarget=ge,P=H),ge=P,F&&x)t:{for(H=F,b=x,m=0,T=H;T;T=Na(T))m++;for(T=0,P=b;P;P=Na(P))T++;for(;0<m-T;)H=Na(H),m--;for(;0<T-m;)b=Na(b),T--;for(;m--;){if(H===b||b!==null&&H===b.alternate)break t;H=Na(H),b=Na(b)}H=null}else H=null;F!==null&&yc(D,w,F,H,!1),x!==null&&ge!==null&&yc(D,ge,x,H,!0)}}e:{if(w=k?Ua(k):window,F=w.nodeName&&w.nodeName.toLowerCase(),F==="select"||F==="input"&&w.type==="file")var N=Jf;else if(Jl(w))if(Zl)N=th;else{N=Zf;var B=Xf}else(F=w.nodeName)&&F.toLowerCase()==="input"&&(w.type==="checkbox"||w.type==="radio")&&(N=eh);if(N&&(N=N(e,k))){Xl(D,N,a,C);break e}B&&B(e,w,k),e==="focusout"&&(B=w._wrapperState)&&B.controlled&&w.type==="number"&&Hn(w,"number",w.value)}switch(B=k?Ua(k):window,e){case"focusin":(Jl(B)||B.contentEditable==="true")&&(Oa=B,po=k,Di=null);break;case"focusout":Di=po=Oa=null;break;case"mousedown":fo=!0;break;case"contextmenu":case"mouseup":case"dragend":fo=!1,sc(D,a,C);break;case"selectionchange":if(rh)break;case"keydown":case"keyup":sc(D,a,C)}var U;if(so)e:{switch(e){case"compositionstart":var z="onCompositionStart";break e;case"compositionend":z="onCompositionEnd";break e;case"compositionupdate":z="onCompositionUpdate";break e}z=void 0}else xa?Yl(e,a)&&(z="onCompositionEnd"):e==="keydown"&&a.keyCode===229&&(z="onCompositionStart");z&&(Gl&&a.locale!=="ko"&&(xa||z!=="onCompositionStart"?z==="onCompositionEnd"&&xa&&(U=_l()):(Gt=C,to="value"in Gt?Gt.value:Gt.textContent,xa=!0)),B=kr(k,z),0<B.length&&(z=new jl(z,e,null,a,C),D.push({event:z,listeners:B}),U?z.data=U:(U=$l(a),U!==null&&(z.data=U)))),(U=Gf?Kf(e,a):Qf(e,a))&&(k=kr(k,"onBeforeInput"),0<k.length&&(C=new jl("onBeforeInput","beforeinput",null,a,C),D.push({event:C,listeners:k}),C.data=U))}gc(D,t)})}function Li(e,t,a){return{instance:e,listener:t,currentTarget:a}}function kr(e,t){for(var a=t+"Capture",n=[];e!==null;){var s=e,l=s.stateNode;s.tag===5&&l!==null&&(s=l,l=ci(e,a),l!=null&&n.unshift(Li(e,l,s)),l=ci(e,t),l!=null&&n.push(Li(e,l,s))),e=e.return}return n}function Na(e){if(e===null)return null;do e=e.return;while(e&&e.tag!==5);return e||null}function yc(e,t,a,n,s){for(var l=t._reactName,d=[];a!==null&&a!==n;){var f=a,h=f.alternate,k=f.stateNode;if(h!==null&&h===n)break;f.tag===5&&k!==null&&(f=k,s?(h=ci(a,l),h!=null&&d.unshift(Li(a,h,f))):s||(h=ci(a,l),h!=null&&d.push(Li(a,h,f)))),a=a.return}d.length!==0&&e.push({event:t,listeners:d})}var lh=/\r\n?/g,ch=/\u0000|\uFFFD/g;function Sc(e){return(typeof e=="string"?e:""+e).replace(lh,`
39
39
  `).replace(ch,"")}function wr(e,t,a){if(t=Sc(t),Sc(e)!==t&&a)throw Error(o(425))}function vr(){}var So=null,To=null;function ko(e,t){return e==="textarea"||e==="noscript"||typeof t.children=="string"||typeof t.children=="number"||typeof t.dangerouslySetInnerHTML=="object"&&t.dangerouslySetInnerHTML!==null&&t.dangerouslySetInnerHTML.__html!=null}var wo=typeof setTimeout=="function"?setTimeout:void 0,uh=typeof clearTimeout=="function"?clearTimeout:void 0,Tc=typeof Promise=="function"?Promise:void 0,dh=typeof queueMicrotask=="function"?queueMicrotask:typeof Tc<"u"?function(e){return Tc.resolve(null).then(e).catch(ph)}:wo;function ph(e){setTimeout(function(){throw e})}function vo(e,t){var a=t,n=0;do{var s=a.nextSibling;if(e.removeChild(a),s&&s.nodeType===8)if(a=s.data,a==="/$"){if(n===0){e.removeChild(s),yi(t);return}n--}else a!=="$"&&a!=="$?"&&a!=="$!"||n++;a=s}while(a);yi(t)}function Qt(e){for(;e!=null;e=e.nextSibling){var t=e.nodeType;if(t===1||t===3)break;if(t===8){if(t=e.data,t==="$"||t==="$!"||t==="$?")break;if(t==="/$")return null}}return e}function kc(e){e=e.previousSibling;for(var t=0;e;){if(e.nodeType===8){var a=e.data;if(a==="$"||a==="$!"||a==="$?"){if(t===0)return e;t--}else a==="/$"&&t++}e=e.previousSibling}return null}var Ba=Math.random().toString(36).slice(2),Dt="__reactFiber$"+Ba,Ri="__reactProps$"+Ba,Mt="__reactContainer$"+Ba,Co="__reactEvents$"+Ba,fh="__reactListeners$"+Ba,hh="__reactHandles$"+Ba;function pa(e){var t=e[Dt];if(t)return t;for(var a=e.parentNode;a;){if(t=a[Mt]||a[Dt]){if(a=t.alternate,t.child!==null||a!==null&&a.child!==null)for(e=kc(e);e!==null;){if(a=e[Dt])return a;e=kc(e)}return t}e=a,a=e.parentNode}return null}function Fi(e){return e=e[Dt]||e[Mt],!e||e.tag!==5&&e.tag!==6&&e.tag!==13&&e.tag!==3?null:e}function Ua(e){if(e.tag===5||e.tag===6)return e.stateNode;throw Error(o(33))}function Cr(e){return e[Ri]||null}var Do=[],Wa=-1;function Yt(e){return{current:e}}function le(e){0>Wa||(e.current=Do[Wa],Do[Wa]=null,Wa--)}function ne(e,t){Wa++,Do[Wa]=e.current,e.current=t}var $t={},Le=Yt($t),Ve=Yt(!1),fa=$t;function _a(e,t){var a=e.type.contextTypes;if(!a)return $t;var n=e.stateNode;if(n&&n.__reactInternalMemoizedUnmaskedChildContext===t)return n.__reactInternalMemoizedMaskedChildContext;var s={},l;for(l in a)s[l]=t[l];return n&&(e=e.stateNode,e.__reactInternalMemoizedUnmaskedChildContext=t,e.__reactInternalMemoizedMaskedChildContext=s),s}function ze(e){return e=e.childContextTypes,e!=null}function Dr(){le(Ve),le(Le)}function wc(e,t,a){if(Le.current!==$t)throw Error(o(168));ne(Le,t),ne(Ve,a)}function vc(e,t,a){var n=e.stateNode;if(t=t.childContextTypes,typeof n.getChildContext!="function")return a;n=n.getChildContext();for(var s in n)if(!(s in t))throw Error(o(108,re(e)||"Unknown",s));return I({},a,n)}function Pr(e){return e=(e=e.stateNode)&&e.__reactInternalMemoizedMergedChildContext||$t,fa=Le.current,ne(Le,e),ne(Ve,Ve.current),!0}function Cc(e,t,a){var n=e.stateNode;if(!n)throw Error(o(169));a?(e=vc(e,t,fa),n.__reactInternalMemoizedMergedChildContext=e,le(Ve),le(Le),ne(Le,e)):le(Ve),ne(Ve,a)}var It=null,Ar=!1,Po=!1;function Dc(e){It===null?It=[e]:It.push(e)}function mh(e){Ar=!0,Dc(e)}function Jt(){if(!Po&&It!==null){Po=!0;var e=0,t=ae;try{var a=It;for(ae=1;e<a.length;e++){var n=a[e];do n=n(!0);while(n!==null)}It=null,Ar=!1}catch(s){throw It!==null&&(It=It.slice(e+1)),Al(Kn,Jt),s}finally{ae=t,Po=!1}}return null}var Va=[],za=0,Lr=null,Rr=0,it=[],rt=0,ha=null,xt=1,Ot="";function ma(e,t){Va[za++]=Rr,Va[za++]=Lr,Lr=e,Rr=t}function Pc(e,t,a){it[rt++]=xt,it[rt++]=Ot,it[rt++]=ha,ha=e;var n=xt;e=Ot;var s=32-ft(n)-1;n&=~(1<<s),a+=1;var l=32-ft(t)+s;if(30<l){var d=s-s%5;l=(n&(1<<d)-1).toString(32),n>>=d,s-=d,xt=1<<32-ft(t)+s|a<<s|n,Ot=l+e}else xt=1<<l|a<<s|n,Ot=e}function Ao(e){e.return!==null&&(ma(e,1),Pc(e,1,0))}function Lo(e){for(;e===Lr;)Lr=Va[--za],Va[za]=null,Rr=Va[--za],Va[za]=null;for(;e===ha;)ha=it[--rt],it[rt]=null,Ot=it[--rt],it[rt]=null,xt=it[--rt],it[rt]=null}var Je=null,Xe=null,ue=!1,mt=null;function Ac(e,t){var a=lt(5,null,null,0);a.elementType="DELETED",a.stateNode=t,a.return=e,t=e.deletions,t===null?(e.deletions=[a],e.flags|=16):t.push(a)}function Lc(e,t){switch(e.tag){case 5:var a=e.type;return t=t.nodeType!==1||a.toLowerCase()!==t.nodeName.toLowerCase()?null:t,t!==null?(e.stateNode=t,Je=e,Xe=Qt(t.firstChild),!0):!1;case 6:return t=e.pendingProps===""||t.nodeType!==3?null:t,t!==null?(e.stateNode=t,Je=e,Xe=null,!0):!1;case 13:return t=t.nodeType!==8?null:t,t!==null?(a=ha!==null?{id:xt,overflow:Ot}:null,e.memoizedState={dehydrated:t,treeContext:a,retryLane:1073741824},a=lt(18,null,null,0),a.stateNode=t,a.return=e,e.child=a,Je=e,Xe=null,!0):!1;default:return!1}}function Ro(e){return(e.mode&1)!==0&&(e.flags&128)===0}function Fo(e){if(ue){var t=Xe;if(t){var a=t;if(!Lc(e,t)){if(Ro(e))throw Error(o(418));t=Qt(a.nextSibling);var n=Je;t&&Lc(e,t)?Ac(n,a):(e.flags=e.flags&-4097|2,ue=!1,Je=e)}}else{if(Ro(e))throw Error(o(418));e.flags=e.flags&-4097|2,ue=!1,Je=e}}}function Rc(e){for(e=e.return;e!==null&&e.tag!==5&&e.tag!==3&&e.tag!==13;)e=e.return;Je=e}function Fr(e){if(e!==Je)return!1;if(!ue)return Rc(e),ue=!0,!1;var t;if((t=e.tag!==3)&&!(t=e.tag!==5)&&(t=e.type,t=t!=="head"&&t!=="body"&&!ko(e.type,e.memoizedProps)),t&&(t=Xe)){if(Ro(e))throw Fc(),Error(o(418));for(;t;)Ac(e,t),t=Qt(t.nextSibling)}if(Rc(e),e.tag===13){if(e=e.memoizedState,e=e!==null?e.dehydrated:null,!e)throw Error(o(317));e:{for(e=e.nextSibling,t=0;e;){if(e.nodeType===8){var a=e.data;if(a==="/$"){if(t===0){Xe=Qt(e.nextSibling);break e}t--}else a!=="$"&&a!=="$!"&&a!=="$?"||t++}e=e.nextSibling}Xe=null}}else Xe=Je?Qt(e.stateNode.nextSibling):null;return!0}function Fc(){for(var e=Xe;e;)e=Qt(e.nextSibling)}function ja(){Xe=Je=null,ue=!1}function Eo(e){mt===null?mt=[e]:mt.push(e)}var gh=Ae.ReactCurrentBatchConfig;function Ei(e,t,a){if(e=a.ref,e!==null&&typeof e!="function"&&typeof e!="object"){if(a._owner){if(a=a._owner,a){if(a.tag!==1)throw Error(o(309));var n=a.stateNode}if(!n)throw Error(o(147,e));var s=n,l=""+e;return t!==null&&t.ref!==null&&typeof t.ref=="function"&&t.ref._stringRef===l?t.ref:(t=function(d){var f=s.refs;d===null?delete f[l]:f[l]=d},t._stringRef=l,t)}if(typeof e!="string")throw Error(o(284));if(!a._owner)throw Error(o(290,e))}return e}function Er(e,t){throw e=Object.prototype.toString.call(t),Error(o(31,e==="[object Object]"?"object with keys {"+Object.keys(t).join(", ")+"}":e))}function Ec(e){var t=e._init;return t(e._payload)}function Mc(e){function t(b,m){if(e){var T=b.deletions;T===null?(b.deletions=[m],b.flags|=16):T.push(m)}}function a(b,m){if(!e)return null;for(;m!==null;)t(b,m),m=m.sibling;return null}function n(b,m){for(b=new Map;m!==null;)m.key!==null?b.set(m.key,m):b.set(m.index,m),m=m.sibling;return b}function s(b,m){return b=na(b,m),b.index=0,b.sibling=null,b}function l(b,m,T){return b.index=T,e?(T=b.alternate,T!==null?(T=T.index,T<m?(b.flags|=2,m):T):(b.flags|=2,m)):(b.flags|=1048576,m)}function d(b){return e&&b.alternate===null&&(b.flags|=2),b}function f(b,m,T,P){return m===null||m.tag!==6?(m=ws(T,b.mode,P),m.return=b,m):(m=s(m,T),m.return=b,m)}function h(b,m,T,P){var N=T.type;return N===We?C(b,m,T.props.children,P,T.key):m!==null&&(m.elementType===N||typeof N=="object"&&N!==null&&N.$$typeof===_e&&Ec(N)===m.type)?(P=s(m,T.props),P.ref=Ei(b,m,T),P.return=b,P):(P=tn(T.type,T.key,T.props,null,b.mode,P),P.ref=Ei(b,m,T),P.return=b,P)}function k(b,m,T,P){return m===null||m.tag!==4||m.stateNode.containerInfo!==T.containerInfo||m.stateNode.implementation!==T.implementation?(m=vs(T,b.mode,P),m.return=b,m):(m=s(m,T.children||[]),m.return=b,m)}function C(b,m,T,P,N){return m===null||m.tag!==7?(m=va(T,b.mode,P,N),m.return=b,m):(m=s(m,T),m.return=b,m)}function D(b,m,T){if(typeof m=="string"&&m!==""||typeof m=="number")return m=ws(""+m,b.mode,T),m.return=b,m;if(typeof m=="object"&&m!==null){switch(m.$$typeof){case dt:return T=tn(m.type,m.key,m.props,null,b.mode,T),T.ref=Ei(b,null,m),T.return=b,T;case Ie:return m=vs(m,b.mode,T),m.return=b,m;case _e:var P=m._init;return D(b,P(m._payload),T)}if(oi(m)||V(m))return m=va(m,b.mode,T,null),m.return=b,m;Er(b,m)}return null}function w(b,m,T,P){var N=m!==null?m.key:null;if(typeof T=="string"&&T!==""||typeof T=="number")return N!==null?null:f(b,m,""+T,P);if(typeof T=="object"&&T!==null){switch(T.$$typeof){case dt:return T.key===N?h(b,m,T,P):null;case Ie:return T.key===N?k(b,m,T,P):null;case _e:return N=T._init,w(b,m,N(T._payload),P)}if(oi(T)||V(T))return N!==null?null:C(b,m,T,P,null);Er(b,T)}return null}function F(b,m,T,P,N){if(typeof P=="string"&&P!==""||typeof P=="number")return b=b.get(T)||null,f(m,b,""+P,N);if(typeof P=="object"&&P!==null){switch(P.$$typeof){case dt:return b=b.get(P.key===null?T:P.key)||null,h(m,b,P,N);case Ie:return b=b.get(P.key===null?T:P.key)||null,k(m,b,P,N);case _e:var B=P._init;return F(b,m,T,B(P._payload),N)}if(oi(P)||V(P))return b=b.get(T)||null,C(m,b,P,N,null);Er(m,P)}return null}function x(b,m,T,P){for(var N=null,B=null,U=m,z=m=0,Ce=null;U!==null&&z<T.length;z++){U.index>z?(Ce=U,U=null):Ce=U.sibling;var X=w(b,U,T[z],P);if(X===null){U===null&&(U=Ce);break}e&&U&&X.alternate===null&&t(b,U),m=l(X,m,z),B===null?N=X:B.sibling=X,B=X,U=Ce}if(z===T.length)return a(b,U),ue&&ma(b,z),N;if(U===null){for(;z<T.length;z++)U=D(b,T[z],P),U!==null&&(m=l(U,m,z),B===null?N=U:B.sibling=U,B=U);return ue&&ma(b,z),N}for(U=n(b,U);z<T.length;z++)Ce=F(U,b,z,T[z],P),Ce!==null&&(e&&Ce.alternate!==null&&U.delete(Ce.key===null?z:Ce.key),m=l(Ce,m,z),B===null?N=Ce:B.sibling=Ce,B=Ce);return e&&U.forEach(function(oa){return t(b,oa)}),ue&&ma(b,z),N}function H(b,m,T,P){var N=V(T);if(typeof N!="function")throw Error(o(150));if(T=N.call(T),T==null)throw Error(o(151));for(var B=N=null,U=m,z=m=0,Ce=null,X=T.next();U!==null&&!X.done;z++,X=T.next()){U.index>z?(Ce=U,U=null):Ce=U.sibling;var oa=w(b,U,X.value,P);if(oa===null){U===null&&(U=Ce);break}e&&U&&oa.alternate===null&&t(b,U),m=l(oa,m,z),B===null?N=oa:B.sibling=oa,B=oa,U=Ce}if(X.done)return a(b,U),ue&&ma(b,z),N;if(U===null){for(;!X.done;z++,X=T.next())X=D(b,X.value,P),X!==null&&(m=l(X,m,z),B===null?N=X:B.sibling=X,B=X);return ue&&ma(b,z),N}for(U=n(b,U);!X.done;z++,X=T.next())X=F(U,b,z,X.value,P),X!==null&&(e&&X.alternate!==null&&U.delete(X.key===null?z:X.key),m=l(X,m,z),B===null?N=X:B.sibling=X,B=X);return e&&U.forEach(function(Yh){return t(b,Yh)}),ue&&ma(b,z),N}function ge(b,m,T,P){if(typeof T=="object"&&T!==null&&T.type===We&&T.key===null&&(T=T.props.children),typeof T=="object"&&T!==null){switch(T.$$typeof){case dt:e:{for(var N=T.key,B=m;B!==null;){if(B.key===N){if(N=T.type,N===We){if(B.tag===7){a(b,B.sibling),m=s(B,T.props.children),m.return=b,b=m;break e}}else if(B.elementType===N||typeof N=="object"&&N!==null&&N.$$typeof===_e&&Ec(N)===B.type){a(b,B.sibling),m=s(B,T.props),m.ref=Ei(b,B,T),m.return=b,b=m;break e}a(b,B);break}else t(b,B);B=B.sibling}T.type===We?(m=va(T.props.children,b.mode,P,T.key),m.return=b,b=m):(P=tn(T.type,T.key,T.props,null,b.mode,P),P.ref=Ei(b,m,T),P.return=b,b=P)}return d(b);case Ie:e:{for(B=T.key;m!==null;){if(m.key===B)if(m.tag===4&&m.stateNode.containerInfo===T.containerInfo&&m.stateNode.implementation===T.implementation){a(b,m.sibling),m=s(m,T.children||[]),m.return=b,b=m;break e}else{a(b,m);break}else t(b,m);m=m.sibling}m=vs(T,b.mode,P),m.return=b,b=m}return d(b);case _e:return B=T._init,ge(b,m,B(T._payload),P)}if(oi(T))return x(b,m,T,P);if(V(T))return H(b,m,T,P);Er(b,T)}return typeof T=="string"&&T!==""||typeof T=="number"?(T=""+T,m!==null&&m.tag===6?(a(b,m.sibling),m=s(m,T),m.return=b,b=m):(a(b,m),m=ws(T,b.mode,P),m.return=b,b=m),d(b)):a(b,m)}return ge}var qa=Mc(!0),Ic=Mc(!1),Mr=Yt(null),Ir=null,Ga=null,Mo=null;function Io(){Mo=Ga=Ir=null}function xo(e){var t=Mr.current;le(Mr),e._currentValue=t}function Oo(e,t,a){for(;e!==null;){var n=e.alternate;if((e.childLanes&t)!==t?(e.childLanes|=t,n!==null&&(n.childLanes|=t)):n!==null&&(n.childLanes&t)!==t&&(n.childLanes|=t),e===a)break;e=e.return}}function Ka(e,t){Ir=e,Mo=Ga=null,e=e.dependencies,e!==null&&e.firstContext!==null&&((e.lanes&t)!==0&&(je=!0),e.firstContext=null)}function nt(e){var t=e._currentValue;if(Mo!==e)if(e={context:e,memoizedValue:t,next:null},Ga===null){if(Ir===null)throw Error(o(308));Ga=e,Ir.dependencies={lanes:0,firstContext:e}}else Ga=Ga.next=e;return t}var ga=null;function Ho(e){ga===null?ga=[e]:ga.push(e)}function xc(e,t,a,n){var s=t.interleaved;return s===null?(a.next=a,Ho(t)):(a.next=s.next,s.next=a),t.interleaved=a,Ht(e,n)}function Ht(e,t){e.lanes|=t;var a=e.alternate;for(a!==null&&(a.lanes|=t),a=e,e=e.return;e!==null;)e.childLanes|=t,a=e.alternate,a!==null&&(a.childLanes|=t),a=e,e=e.return;return a.tag===3?a.stateNode:null}var Xt=!1;function No(e){e.updateQueue={baseState:e.memoizedState,firstBaseUpdate:null,lastBaseUpdate:null,shared:{pending:null,interleaved:null,lanes:0},effects:null}}function Oc(e,t){e=e.updateQueue,t.updateQueue===e&&(t.updateQueue={baseState:e.baseState,firstBaseUpdate:e.firstBaseUpdate,lastBaseUpdate:e.lastBaseUpdate,shared:e.shared,effects:e.effects})}function Nt(e,t){return{eventTime:e,lane:t,tag:0,payload:null,callback:null,next:null}}function Zt(e,t,a){var n=e.updateQueue;if(n===null)return null;if(n=n.shared,(Y&2)!==0){var s=n.pending;return s===null?t.next=t:(t.next=s.next,s.next=t),n.pending=t,Ht(e,a)}return s=n.interleaved,s===null?(t.next=t,Ho(n)):(t.next=s.next,s.next=t),n.interleaved=t,Ht(e,a)}function xr(e,t,a){if(t=t.updateQueue,t!==null&&(t=t.shared,(a&4194240)!==0)){var n=t.lanes;n&=e.pendingLanes,a|=n,t.lanes=a,$n(e,a)}}function Hc(e,t){var a=e.updateQueue,n=e.alternate;if(n!==null&&(n=n.updateQueue,a===n)){var s=null,l=null;if(a=a.firstBaseUpdate,a!==null){do{var d={eventTime:a.eventTime,lane:a.lane,tag:a.tag,payload:a.payload,callback:a.callback,next:null};l===null?s=l=d:l=l.next=d,a=a.next}while(a!==null);l===null?s=l=t:l=l.next=t}else s=l=t;a={baseState:n.baseState,firstBaseUpdate:s,lastBaseUpdate:l,shared:n.shared,effects:n.effects},e.updateQueue=a;return}e=a.lastBaseUpdate,e===null?a.firstBaseUpdate=t:e.next=t,a.lastBaseUpdate=t}function Or(e,t,a,n){var s=e.updateQueue;Xt=!1;var l=s.firstBaseUpdate,d=s.lastBaseUpdate,f=s.shared.pending;if(f!==null){s.shared.pending=null;var h=f,k=h.next;h.next=null,d===null?l=k:d.next=k,d=h;var C=e.alternate;C!==null&&(C=C.updateQueue,f=C.lastBaseUpdate,f!==d&&(f===null?C.firstBaseUpdate=k:f.next=k,C.lastBaseUpdate=h))}if(l!==null){var D=s.baseState;d=0,C=k=h=null,f=l;do{var w=f.lane,F=f.eventTime;if((n&w)===w){C!==null&&(C=C.next={eventTime:F,lane:0,tag:f.tag,payload:f.payload,callback:f.callback,next:null});e:{var x=e,H=f;switch(w=t,F=a,H.tag){case 1:if(x=H.payload,typeof x=="function"){D=x.call(F,D,w);break e}D=x;break e;case 3:x.flags=x.flags&-65537|128;case 0:if(x=H.payload,w=typeof x=="function"?x.call(F,D,w):x,w==null)break e;D=I({},D,w);break e;case 2:Xt=!0}}f.callback!==null&&f.lane!==0&&(e.flags|=64,w=s.effects,w===null?s.effects=[f]:w.push(f))}else F={eventTime:F,lane:w,tag:f.tag,payload:f.payload,callback:f.callback,next:null},C===null?(k=C=F,h=D):C=C.next=F,d|=w;if(f=f.next,f===null){if(f=s.shared.pending,f===null)break;w=f,f=w.next,w.next=null,s.lastBaseUpdate=w,s.shared.pending=null}}while(!0);if(C===null&&(h=D),s.baseState=h,s.firstBaseUpdate=k,s.lastBaseUpdate=C,t=s.shared.interleaved,t!==null){s=t;do d|=s.lane,s=s.next;while(s!==t)}else l===null&&(s.shared.lanes=0);Sa|=d,e.lanes=d,e.memoizedState=D}}function Nc(e,t,a){if(e=t.effects,t.effects=null,e!==null)for(t=0;t<e.length;t++){var n=e[t],s=n.callback;if(s!==null){if(n.callback=null,n=a,typeof s!="function")throw Error(o(191,s));s.call(n)}}}var Mi={},Pt=Yt(Mi),Ii=Yt(Mi),xi=Yt(Mi);function ba(e){if(e===Mi)throw Error(o(174));return e}function Bo(e,t){switch(ne(xi,t),ne(Ii,e),ne(Pt,Mi),e=t.nodeType,e){case 9:case 11:t=(t=t.documentElement)?t.namespaceURI:Bn(null,"");break;default:e=e===8?t.parentNode:t,t=e.namespaceURI||null,e=e.tagName,t=Bn(t,e)}le(Pt),ne(Pt,t)}function Qa(){le(Pt),le(Ii),le(xi)}function Bc(e){ba(xi.current);var t=ba(Pt.current),a=Bn(t,e.type);t!==a&&(ne(Ii,e),ne(Pt,a))}function Uo(e){Ii.current===e&&(le(Pt),le(Ii))}var de=Yt(0);function Hr(e){for(var t=e;t!==null;){if(t.tag===13){var a=t.memoizedState;if(a!==null&&(a=a.dehydrated,a===null||a.data==="$?"||a.data==="$!"))return t}else if(t.tag===19&&t.memoizedProps.revealOrder!==void 0){if((t.flags&128)!==0)return t}else if(t.child!==null){t.child.return=t,t=t.child;continue}if(t===e)break;for(;t.sibling===null;){if(t.return===null||t.return===e)return null;t=t.return}t.sibling.return=t.return,t=t.sibling}return null}var Wo=[];function _o(){for(var e=0;e<Wo.length;e++)Wo[e]._workInProgressVersionPrimary=null;Wo.length=0}var Nr=Ae.ReactCurrentDispatcher,Vo=Ae.ReactCurrentBatchConfig,ya=0,pe=null,Se=null,we=null,Br=!1,Oi=!1,Hi=0,bh=0;function Re(){throw Error(o(321))}function zo(e,t){if(t===null)return!1;for(var a=0;a<t.length&&a<e.length;a++)if(!ht(e[a],t[a]))return!1;return!0}function jo(e,t,a,n,s,l){if(ya=l,pe=t,t.memoizedState=null,t.updateQueue=null,t.lanes=0,Nr.current=e===null||e.memoizedState===null?kh:wh,e=a(n,s),Oi){l=0;do{if(Oi=!1,Hi=0,25<=l)throw Error(o(301));l+=1,we=Se=null,t.updateQueue=null,Nr.current=vh,e=a(n,s)}while(Oi)}if(Nr.current=_r,t=Se!==null&&Se.next!==null,ya=0,we=Se=pe=null,Br=!1,t)throw Error(o(300));return e}function qo(){var e=Hi!==0;return Hi=0,e}function At(){var e={memoizedState:null,baseState:null,baseQueue:null,queue:null,next:null};return we===null?pe.memoizedState=we=e:we=we.next=e,we}function ot(){if(Se===null){var e=pe.alternate;e=e!==null?e.memoizedState:null}else e=Se.next;var t=we===null?pe.memoizedState:we.next;if(t!==null)we=t,Se=e;else{if(e===null)throw Error(o(310));Se=e,e={memoizedState:Se.memoizedState,baseState:Se.baseState,baseQueue:Se.baseQueue,queue:Se.queue,next:null},we===null?pe.memoizedState=we=e:we=we.next=e}return we}function Ni(e,t){return typeof t=="function"?t(e):t}function Go(e){var t=ot(),a=t.queue;if(a===null)throw Error(o(311));a.lastRenderedReducer=e;var n=Se,s=n.baseQueue,l=a.pending;if(l!==null){if(s!==null){var d=s.next;s.next=l.next,l.next=d}n.baseQueue=s=l,a.pending=null}if(s!==null){l=s.next,n=n.baseState;var f=d=null,h=null,k=l;do{var C=k.lane;if((ya&C)===C)h!==null&&(h=h.next={lane:0,action:k.action,hasEagerState:k.hasEagerState,eagerState:k.eagerState,next:null}),n=k.hasEagerState?k.eagerState:e(n,k.action);else{var D={lane:C,action:k.action,hasEagerState:k.hasEagerState,eagerState:k.eagerState,next:null};h===null?(f=h=D,d=n):h=h.next=D,pe.lanes|=C,Sa|=C}k=k.next}while(k!==null&&k!==l);h===null?d=n:h.next=f,ht(n,t.memoizedState)||(je=!0),t.memoizedState=n,t.baseState=d,t.baseQueue=h,a.lastRenderedState=n}if(e=a.interleaved,e!==null){s=e;do l=s.lane,pe.lanes|=l,Sa|=l,s=s.next;while(s!==e)}else s===null&&(a.lanes=0);return[t.memoizedState,a.dispatch]}function Ko(e){var t=ot(),a=t.queue;if(a===null)throw Error(o(311));a.lastRenderedReducer=e;var n=a.dispatch,s=a.pending,l=t.memoizedState;if(s!==null){a.pending=null;var d=s=s.next;do l=e(l,d.action),d=d.next;while(d!==s);ht(l,t.memoizedState)||(je=!0),t.memoizedState=l,t.baseQueue===null&&(t.baseState=l),a.lastRenderedState=l}return[l,n]}function Uc(){}function Wc(e,t){var a=pe,n=ot(),s=t(),l=!ht(n.memoizedState,s);if(l&&(n.memoizedState=s,je=!0),n=n.queue,Qo(zc.bind(null,a,n,e),[e]),n.getSnapshot!==t||l||we!==null&&we.memoizedState.tag&1){if(a.flags|=2048,Bi(9,Vc.bind(null,a,n,s,t),void 0,null),ve===null)throw Error(o(349));(ya&30)!==0||_c(a,t,s)}return s}function _c(e,t,a){e.flags|=16384,e={getSnapshot:t,value:a},t=pe.updateQueue,t===null?(t={lastEffect:null,stores:null},pe.updateQueue=t,t.stores=[e]):(a=t.stores,a===null?t.stores=[e]:a.push(e))}function Vc(e,t,a,n){t.value=a,t.getSnapshot=n,jc(t)&&qc(e)}function zc(e,t,a){return a(function(){jc(t)&&qc(e)})}function jc(e){var t=e.getSnapshot;e=e.value;try{var a=t();return!ht(e,a)}catch{return!0}}function qc(e){var t=Ht(e,1);t!==null&&St(t,e,1,-1)}function Gc(e){var t=At();return typeof e=="function"&&(e=e()),t.memoizedState=t.baseState=e,e={pending:null,interleaved:null,lanes:0,dispatch:null,lastRenderedReducer:Ni,lastRenderedState:e},t.queue=e,e=e.dispatch=Th.bind(null,pe,e),[t.memoizedState,e]}function Bi(e,t,a,n){return e={tag:e,create:t,destroy:a,deps:n,next:null},t=pe.updateQueue,t===null?(t={lastEffect:null,stores:null},pe.updateQueue=t,t.lastEffect=e.next=e):(a=t.lastEffect,a===null?t.lastEffect=e.next=e:(n=a.next,a.next=e,e.next=n,t.lastEffect=e)),e}function Kc(){return ot().memoizedState}function Ur(e,t,a,n){var s=At();pe.flags|=e,s.memoizedState=Bi(1|t,a,void 0,n===void 0?null:n)}function Wr(e,t,a,n){var s=ot();n=n===void 0?null:n;var l=void 0;if(Se!==null){var d=Se.memoizedState;if(l=d.destroy,n!==null&&zo(n,d.deps)){s.memoizedState=Bi(t,a,l,n);return}}pe.flags|=e,s.memoizedState=Bi(1|t,a,l,n)}function Qc(e,t){return Ur(8390656,8,e,t)}function Qo(e,t){return Wr(2048,8,e,t)}function Yc(e,t){return Wr(4,2,e,t)}function $c(e,t){return Wr(4,4,e,t)}function Jc(e,t){if(typeof t=="function")return e=e(),t(e),function(){t(null)};if(t!=null)return e=e(),t.current=e,function(){t.current=null}}function Xc(e,t,a){return a=a!=null?a.concat([e]):null,Wr(4,4,Jc.bind(null,t,e),a)}function Yo(){}function Zc(e,t){var a=ot();t=t===void 0?null:t;var n=a.memoizedState;return n!==null&&t!==null&&zo(t,n[1])?n[0]:(a.memoizedState=[e,t],e)}function eu(e,t){var a=ot();t=t===void 0?null:t;var n=a.memoizedState;return n!==null&&t!==null&&zo(t,n[1])?n[0]:(e=e(),a.memoizedState=[e,t],e)}function tu(e,t,a){return(ya&21)===0?(e.baseState&&(e.baseState=!1,je=!0),e.memoizedState=a):(ht(a,t)||(a=El(),pe.lanes|=a,Sa|=a,e.baseState=!0),t)}function yh(e,t){var a=ae;ae=a!==0&&4>a?a:4,e(!0);var n=Vo.transition;Vo.transition={};try{e(!1),t()}finally{ae=a,Vo.transition=n}}function au(){return ot().memoizedState}function Sh(e,t,a){var n=ia(e);if(a={lane:n,action:a,hasEagerState:!1,eagerState:null,next:null},iu(e))ru(t,a);else if(a=xc(e,t,a,n),a!==null){var s=Oe();St(a,e,n,s),nu(a,t,n)}}function Th(e,t,a){var n=ia(e),s={lane:n,action:a,hasEagerState:!1,eagerState:null,next:null};if(iu(e))ru(t,s);else{var l=e.alternate;if(e.lanes===0&&(l===null||l.lanes===0)&&(l=t.lastRenderedReducer,l!==null))try{var d=t.lastRenderedState,f=l(d,a);if(s.hasEagerState=!0,s.eagerState=f,ht(f,d)){var h=t.interleaved;h===null?(s.next=s,Ho(t)):(s.next=h.next,h.next=s),t.interleaved=s;return}}catch{}finally{}a=xc(e,t,s,n),a!==null&&(s=Oe(),St(a,e,n,s),nu(a,t,n))}}function iu(e){var t=e.alternate;return e===pe||t!==null&&t===pe}function ru(e,t){Oi=Br=!0;var a=e.pending;a===null?t.next=t:(t.next=a.next,a.next=t),e.pending=t}function nu(e,t,a){if((a&4194240)!==0){var n=t.lanes;n&=e.pendingLanes,a|=n,t.lanes=a,$n(e,a)}}var _r={readContext:nt,useCallback:Re,useContext:Re,useEffect:Re,useImperativeHandle:Re,useInsertionEffect:Re,useLayoutEffect:Re,useMemo:Re,useReducer:Re,useRef:Re,useState:Re,useDebugValue:Re,useDeferredValue:Re,useTransition:Re,useMutableSource:Re,useSyncExternalStore:Re,useId:Re,unstable_isNewReconciler:!1},kh={readContext:nt,useCallback:function(e,t){return At().memoizedState=[e,t===void 0?null:t],e},useContext:nt,useEffect:Qc,useImperativeHandle:function(e,t,a){return a=a!=null?a.concat([e]):null,Ur(4194308,4,Jc.bind(null,t,e),a)},useLayoutEffect:function(e,t){return Ur(4194308,4,e,t)},useInsertionEffect:function(e,t){return Ur(4,2,e,t)},useMemo:function(e,t){var a=At();return t=t===void 0?null:t,e=e(),a.memoizedState=[e,t],e},useReducer:function(e,t,a){var n=At();return t=a!==void 0?a(t):t,n.memoizedState=n.baseState=t,e={pending:null,interleaved:null,lanes:0,dispatch:null,lastRenderedReducer:e,lastRenderedState:t},n.queue=e,e=e.dispatch=Sh.bind(null,pe,e),[n.memoizedState,e]},useRef:function(e){var t=At();return e={current:e},t.memoizedState=e},useState:Gc,useDebugValue:Yo,useDeferredValue:function(e){return At().memoizedState=e},useTransition:function(){var e=Gc(!1),t=e[0];return e=yh.bind(null,e[1]),At().memoizedState=e,[t,e]},useMutableSource:function(){},useSyncExternalStore:function(e,t,a){var n=pe,s=At();if(ue){if(a===void 0)throw Error(o(407));a=a()}else{if(a=t(),ve===null)throw Error(o(349));(ya&30)!==0||_c(n,t,a)}s.memoizedState=a;var l={value:a,getSnapshot:t};return s.queue=l,Qc(zc.bind(null,n,l,e),[e]),n.flags|=2048,Bi(9,Vc.bind(null,n,l,a,t),void 0,null),a},useId:function(){var e=At(),t=ve.identifierPrefix;if(ue){var a=Ot,n=xt;a=(n&~(1<<32-ft(n)-1)).toString(32)+a,t=":"+t+"R"+a,a=Hi++,0<a&&(t+="H"+a.toString(32)),t+=":"}else a=bh++,t=":"+t+"r"+a.toString(32)+":";return e.memoizedState=t},unstable_isNewReconciler:!1},wh={readContext:nt,useCallback:Zc,useContext:nt,useEffect:Qo,useImperativeHandle:Xc,useInsertionEffect:Yc,useLayoutEffect:$c,useMemo:eu,useReducer:Go,useRef:Kc,useState:function(){return Go(Ni)},useDebugValue:Yo,useDeferredValue:function(e){var t=ot();return tu(t,Se.memoizedState,e)},useTransition:function(){var e=Go(Ni)[0],t=ot().memoizedState;return[e,t]},useMutableSource:Uc,useSyncExternalStore:Wc,useId:au,unstable_isNewReconciler:!1},vh={readContext:nt,useCallback:Zc,useContext:nt,useEffect:Qo,useImperativeHandle:Xc,useInsertionEffect:Yc,useLayoutEffect:$c,useMemo:eu,useReducer:Ko,useRef:Kc,useState:function(){return Ko(Ni)},useDebugValue:Yo,useDeferredValue:function(e){var t=ot();return Se===null?t.memoizedState=e:tu(t,Se.memoizedState,e)},useTransition:function(){var e=Ko(Ni)[0],t=ot().memoizedState;return[e,t]},useMutableSource:Uc,useSyncExternalStore:Wc,useId:au,unstable_isNewReconciler:!1};function gt(e,t){if(e&&e.defaultProps){t=I({},t),e=e.defaultProps;for(var a in e)t[a]===void 0&&(t[a]=e[a]);return t}return t}function $o(e,t,a,n){t=e.memoizedState,a=a(n,t),a=a==null?t:I({},t,a),e.memoizedState=a,e.lanes===0&&(e.updateQueue.baseState=a)}var Vr={isMounted:function(e){return(e=e._reactInternals)?da(e)===e:!1},enqueueSetState:function(e,t,a){e=e._reactInternals;var n=Oe(),s=ia(e),l=Nt(n,s);l.payload=t,a!=null&&(l.callback=a),t=Zt(e,l,s),t!==null&&(St(t,e,s,n),xr(t,e,s))},enqueueReplaceState:function(e,t,a){e=e._reactInternals;var n=Oe(),s=ia(e),l=Nt(n,s);l.tag=1,l.payload=t,a!=null&&(l.callback=a),t=Zt(e,l,s),t!==null&&(St(t,e,s,n),xr(t,e,s))},enqueueForceUpdate:function(e,t){e=e._reactInternals;var a=Oe(),n=ia(e),s=Nt(a,n);s.tag=2,t!=null&&(s.callback=t),t=Zt(e,s,n),t!==null&&(St(t,e,n,a),xr(t,e,n))}};function ou(e,t,a,n,s,l,d){return e=e.stateNode,typeof e.shouldComponentUpdate=="function"?e.shouldComponentUpdate(n,l,d):t.prototype&&t.prototype.isPureReactComponent?!Ci(a,n)||!Ci(s,l):!0}function su(e,t,a){var n=!1,s=$t,l=t.contextType;return typeof l=="object"&&l!==null?l=nt(l):(s=ze(t)?fa:Le.current,n=t.contextTypes,l=(n=n!=null)?_a(e,s):$t),t=new t(a,l),e.memoizedState=t.state!==null&&t.state!==void 0?t.state:null,t.updater=Vr,e.stateNode=t,t._reactInternals=e,n&&(e=e.stateNode,e.__reactInternalMemoizedUnmaskedChildContext=s,e.__reactInternalMemoizedMaskedChildContext=l),t}function lu(e,t,a,n){e=t.state,typeof t.componentWillReceiveProps=="function"&&t.componentWillReceiveProps(a,n),typeof t.UNSAFE_componentWillReceiveProps=="function"&&t.UNSAFE_componentWillReceiveProps(a,n),t.state!==e&&Vr.enqueueReplaceState(t,t.state,null)}function Jo(e,t,a,n){var s=e.stateNode;s.props=a,s.state=e.memoizedState,s.refs={},No(e);var l=t.contextType;typeof l=="object"&&l!==null?s.context=nt(l):(l=ze(t)?fa:Le.current,s.context=_a(e,l)),s.state=e.memoizedState,l=t.getDerivedStateFromProps,typeof l=="function"&&($o(e,t,l,a),s.state=e.memoizedState),typeof t.getDerivedStateFromProps=="function"||typeof s.getSnapshotBeforeUpdate=="function"||typeof s.UNSAFE_componentWillMount!="function"&&typeof s.componentWillMount!="function"||(t=s.state,typeof s.componentWillMount=="function"&&s.componentWillMount(),typeof s.UNSAFE_componentWillMount=="function"&&s.UNSAFE_componentWillMount(),t!==s.state&&Vr.enqueueReplaceState(s,s.state,null),Or(e,a,s,n),s.state=e.memoizedState),typeof s.componentDidMount=="function"&&(e.flags|=4194308)}function Ya(e,t){try{var a="",n=t;do a+=$(n),n=n.return;while(n);var s=a}catch(l){s=`
40
40
  Error generating stack: `+l.message+`
41
- `+l.stack}return{value:e,source:t,stack:s,digest:null}}function Xo(e,t,a){return{value:e,source:null,stack:a??null,digest:t??null}}function Zo(e,t){try{console.error(t.value)}catch(a){setTimeout(function(){throw a})}}var Ch=typeof WeakMap=="function"?WeakMap:Map;function cu(e,t,a){a=Nt(-1,a),a.tag=3,a.payload={element:null};var n=t.value;return a.callback=function(){Yr||(Yr=!0,hs=n),Zo(e,t)},a}function uu(e,t,a){a=Nt(-1,a),a.tag=3;var n=e.type.getDerivedStateFromError;if(typeof n=="function"){var s=t.value;a.payload=function(){return n(s)},a.callback=function(){Zo(e,t)}}var l=e.stateNode;return l!==null&&typeof l.componentDidCatch=="function"&&(a.callback=function(){Zo(e,t),typeof n!="function"&&(ta===null?ta=new Set([this]):ta.add(this));var d=t.stack;this.componentDidCatch(t.value,{componentStack:d!==null?d:""})}),a}function du(e,t,a){var n=e.pingCache;if(n===null){n=e.pingCache=new Ch;var s=new Set;n.set(t,s)}else s=n.get(t),s===void 0&&(s=new Set,n.set(t,s));s.has(a)||(s.add(a),e=Bh.bind(null,e,t,a),t.then(e,e))}function pu(e){do{var t;if((t=e.tag===13)&&(t=e.memoizedState,t=t!==null?t.dehydrated!==null:!0),t)return e;e=e.return}while(e!==null);return null}function fu(e,t,a,n,s){return(e.mode&1)===0?(e===t?e.flags|=65536:(e.flags|=128,a.flags|=131072,a.flags&=-52805,a.tag===1&&(a.alternate===null?a.tag=17:(t=Nt(-1,1),t.tag=2,Zt(a,t,1))),a.lanes|=1),e):(e.flags|=65536,e.lanes=s,e)}var Dh=Ae.ReactCurrentOwner,je=!1;function xe(e,t,a,n){t.child=e===null?Ic(t,null,a,n):qa(t,e.child,a,n)}function hu(e,t,a,n,s){a=a.render;var l=t.ref;return Ka(t,s),n=jo(e,t,a,n,l,s),a=qo(),e!==null&&!je?(t.updateQueue=e.updateQueue,t.flags&=-2053,e.lanes&=~s,Bt(e,t,s)):(ue&&a&&Ao(t),t.flags|=1,xe(e,t,n,s),t.child)}function mu(e,t,a,n,s){if(e===null){var l=a.type;return typeof l=="function"&&!ks(l)&&l.defaultProps===void 0&&a.compare===null&&a.defaultProps===void 0?(t.tag=15,t.type=l,gu(e,t,l,n,s)):(e=tn(a.type,null,n,t,t.mode,s),e.ref=t.ref,e.return=t,t.child=e)}if(l=e.child,(e.lanes&s)===0){var d=l.memoizedProps;if(a=a.compare,a=a!==null?a:Ci,a(d,n)&&e.ref===t.ref)return Bt(e,t,s)}return t.flags|=1,e=na(l,n),e.ref=t.ref,e.return=t,t.child=e}function gu(e,t,a,n,s){if(e!==null){var l=e.memoizedProps;if(Ci(l,n)&&e.ref===t.ref)if(je=!1,t.pendingProps=n=l,(e.lanes&s)!==0)(e.flags&131072)!==0&&(je=!0);else return t.lanes=e.lanes,Bt(e,t,s)}return es(e,t,a,n,s)}function bu(e,t,a){var n=t.pendingProps,s=n.children,l=e!==null?e.memoizedState:null;if(n.mode==="hidden")if((t.mode&1)===0)t.memoizedState={baseLanes:0,cachePool:null,transitions:null},ne(Ja,Ze),Ze|=a;else{if((a&1073741824)===0)return e=l!==null?l.baseLanes|a:a,t.lanes=t.childLanes=1073741824,t.memoizedState={baseLanes:e,cachePool:null,transitions:null},t.updateQueue=null,ne(Ja,Ze),Ze|=e,null;t.memoizedState={baseLanes:0,cachePool:null,transitions:null},n=l!==null?l.baseLanes:a,ne(Ja,Ze),Ze|=n}else l!==null?(n=l.baseLanes|a,t.memoizedState=null):n=a,ne(Ja,Ze),Ze|=n;return xe(e,t,s,a),t.child}function yu(e,t){var a=t.ref;(e===null&&a!==null||e!==null&&e.ref!==a)&&(t.flags|=512,t.flags|=2097152)}function es(e,t,a,n,s){var l=ze(a)?fa:Le.current;return l=_a(t,l),Ka(t,s),a=jo(e,t,a,n,l,s),n=qo(),e!==null&&!je?(t.updateQueue=e.updateQueue,t.flags&=-2053,e.lanes&=~s,Bt(e,t,s)):(ue&&n&&Ao(t),t.flags|=1,xe(e,t,a,s),t.child)}function Su(e,t,a,n,s){if(ze(a)){var l=!0;Pr(t)}else l=!1;if(Ka(t,s),t.stateNode===null)jr(e,t),su(t,a,n),Jo(t,a,n,s),n=!0;else if(e===null){var d=t.stateNode,f=t.memoizedProps;d.props=f;var h=d.context,k=a.contextType;typeof k=="object"&&k!==null?k=nt(k):(k=ze(a)?fa:Le.current,k=_a(t,k));var C=a.getDerivedStateFromProps,D=typeof C=="function"||typeof d.getSnapshotBeforeUpdate=="function";D||typeof d.UNSAFE_componentWillReceiveProps!="function"&&typeof d.componentWillReceiveProps!="function"||(f!==n||h!==k)&&lu(t,d,n,k),Xt=!1;var w=t.memoizedState;d.state=w,Or(t,n,d,s),h=t.memoizedState,f!==n||w!==h||Ve.current||Xt?(typeof C=="function"&&($o(t,a,C,n),h=t.memoizedState),(f=Xt||ou(t,a,f,n,w,h,k))?(D||typeof d.UNSAFE_componentWillMount!="function"&&typeof d.componentWillMount!="function"||(typeof d.componentWillMount=="function"&&d.componentWillMount(),typeof d.UNSAFE_componentWillMount=="function"&&d.UNSAFE_componentWillMount()),typeof d.componentDidMount=="function"&&(t.flags|=4194308)):(typeof d.componentDidMount=="function"&&(t.flags|=4194308),t.memoizedProps=n,t.memoizedState=h),d.props=n,d.state=h,d.context=k,n=f):(typeof d.componentDidMount=="function"&&(t.flags|=4194308),n=!1)}else{d=t.stateNode,Oc(e,t),f=t.memoizedProps,k=t.type===t.elementType?f:gt(t.type,f),d.props=k,D=t.pendingProps,w=d.context,h=a.contextType,typeof h=="object"&&h!==null?h=nt(h):(h=ze(a)?fa:Le.current,h=_a(t,h));var F=a.getDerivedStateFromProps;(C=typeof F=="function"||typeof d.getSnapshotBeforeUpdate=="function")||typeof d.UNSAFE_componentWillReceiveProps!="function"&&typeof d.componentWillReceiveProps!="function"||(f!==D||w!==h)&&lu(t,d,n,h),Xt=!1,w=t.memoizedState,d.state=w,Or(t,n,d,s);var x=t.memoizedState;f!==D||w!==x||Ve.current||Xt?(typeof F=="function"&&($o(t,a,F,n),x=t.memoizedState),(k=Xt||ou(t,a,k,n,w,x,h)||!1)?(C||typeof d.UNSAFE_componentWillUpdate!="function"&&typeof d.componentWillUpdate!="function"||(typeof d.componentWillUpdate=="function"&&d.componentWillUpdate(n,x,h),typeof d.UNSAFE_componentWillUpdate=="function"&&d.UNSAFE_componentWillUpdate(n,x,h)),typeof d.componentDidUpdate=="function"&&(t.flags|=4),typeof d.getSnapshotBeforeUpdate=="function"&&(t.flags|=1024)):(typeof d.componentDidUpdate!="function"||f===e.memoizedProps&&w===e.memoizedState||(t.flags|=4),typeof d.getSnapshotBeforeUpdate!="function"||f===e.memoizedProps&&w===e.memoizedState||(t.flags|=1024),t.memoizedProps=n,t.memoizedState=x),d.props=n,d.state=x,d.context=h,n=k):(typeof d.componentDidUpdate!="function"||f===e.memoizedProps&&w===e.memoizedState||(t.flags|=4),typeof d.getSnapshotBeforeUpdate!="function"||f===e.memoizedProps&&w===e.memoizedState||(t.flags|=1024),n=!1)}return ts(e,t,a,n,l,s)}function ts(e,t,a,n,s,l){yu(e,t);var d=(t.flags&128)!==0;if(!n&&!d)return s&&Cc(t,a,!1),Bt(e,t,l);n=t.stateNode,Dh.current=t;var f=d&&typeof a.getDerivedStateFromError!="function"?null:n.render();return t.flags|=1,e!==null&&d?(t.child=qa(t,e.child,null,l),t.child=qa(t,null,f,l)):xe(e,t,f,l),t.memoizedState=n.state,s&&Cc(t,a,!0),t.child}function Tu(e){var t=e.stateNode;t.pendingContext?wc(e,t.pendingContext,t.pendingContext!==t.context):t.context&&wc(e,t.context,!1),Bo(e,t.containerInfo)}function ku(e,t,a,n,s){return ja(),Eo(s),t.flags|=256,xe(e,t,a,n),t.child}var as={dehydrated:null,treeContext:null,retryLane:0};function is(e){return{baseLanes:e,cachePool:null,transitions:null}}function wu(e,t,a){var n=t.pendingProps,s=de.current,l=!1,d=(t.flags&128)!==0,f;if((f=d)||(f=e!==null&&e.memoizedState===null?!1:(s&2)!==0),f?(l=!0,t.flags&=-129):(e===null||e.memoizedState!==null)&&(s|=1),ne(de,s&1),e===null)return Fo(t),e=t.memoizedState,e!==null&&(e=e.dehydrated,e!==null)?((t.mode&1)===0?t.lanes=1:e.data==="$!"?t.lanes=8:t.lanes=1073741824,null):(d=n.children,e=n.fallback,l?(n=t.mode,l=t.child,d={mode:"hidden",children:d},(n&1)===0&&l!==null?(l.childLanes=0,l.pendingProps=d):l=an(d,n,0,null),e=va(e,n,a,null),l.return=t,e.return=t,l.sibling=e,t.child=l,t.child.memoizedState=is(a),t.memoizedState=as,e):rs(t,d));if(s=e.memoizedState,s!==null&&(f=s.dehydrated,f!==null))return Ph(e,t,d,n,f,s,a);if(l){l=n.fallback,d=t.mode,s=e.child,f=s.sibling;var h={mode:"hidden",children:n.children};return(d&1)===0&&t.child!==s?(n=t.child,n.childLanes=0,n.pendingProps=h,t.deletions=null):(n=na(s,h),n.subtreeFlags=s.subtreeFlags&14680064),f!==null?l=na(f,l):(l=va(l,d,a,null),l.flags|=2),l.return=t,n.return=t,n.sibling=l,t.child=n,n=l,l=t.child,d=e.child.memoizedState,d=d===null?is(a):{baseLanes:d.baseLanes|a,cachePool:null,transitions:d.transitions},l.memoizedState=d,l.childLanes=e.childLanes&~a,t.memoizedState=as,n}return l=e.child,e=l.sibling,n=na(l,{mode:"visible",children:n.children}),(t.mode&1)===0&&(n.lanes=a),n.return=t,n.sibling=null,e!==null&&(a=t.deletions,a===null?(t.deletions=[e],t.flags|=16):a.push(e)),t.child=n,t.memoizedState=null,n}function rs(e,t){return t=an({mode:"visible",children:t},e.mode,0,null),t.return=e,e.child=t}function zr(e,t,a,n){return n!==null&&Eo(n),qa(t,e.child,null,a),e=rs(t,t.pendingProps.children),e.flags|=2,t.memoizedState=null,e}function Ph(e,t,a,n,s,l,d){if(a)return t.flags&256?(t.flags&=-257,n=Xo(Error(o(422))),zr(e,t,d,n)):t.memoizedState!==null?(t.child=e.child,t.flags|=128,null):(l=n.fallback,s=t.mode,n=an({mode:"visible",children:n.children},s,0,null),l=va(l,s,d,null),l.flags|=2,n.return=t,l.return=t,n.sibling=l,t.child=n,(t.mode&1)!==0&&qa(t,e.child,null,d),t.child.memoizedState=is(d),t.memoizedState=as,l);if((t.mode&1)===0)return zr(e,t,d,null);if(s.data==="$!"){if(n=s.nextSibling&&s.nextSibling.dataset,n)var f=n.dgst;return n=f,l=Error(o(419)),n=Xo(l,n,void 0),zr(e,t,d,n)}if(f=(d&e.childLanes)!==0,je||f){if(n=ve,n!==null){switch(d&-d){case 4:s=2;break;case 16:s=8;break;case 64:case 128:case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:case 4194304:case 8388608:case 16777216:case 33554432:case 67108864:s=32;break;case 536870912:s=268435456;break;default:s=0}s=(s&(n.suspendedLanes|d))!==0?0:s,s!==0&&s!==l.retryLane&&(l.retryLane=s,Ht(e,s),St(n,e,s,-1))}return Ts(),n=Xo(Error(o(421))),zr(e,t,d,n)}return s.data==="$?"?(t.flags|=128,t.child=e.child,t=Uh.bind(null,e),s._reactRetry=t,null):(e=l.treeContext,Xe=Qt(s.nextSibling),Je=t,ue=!0,mt=null,e!==null&&(it[rt++]=xt,it[rt++]=Ot,it[rt++]=ha,xt=e.id,Ot=e.overflow,ha=t),t=rs(t,n.children),t.flags|=4096,t)}function vu(e,t,a){e.lanes|=t;var n=e.alternate;n!==null&&(n.lanes|=t),Oo(e.return,t,a)}function ns(e,t,a,n,s){var l=e.memoizedState;l===null?e.memoizedState={isBackwards:t,rendering:null,renderingStartTime:0,last:n,tail:a,tailMode:s}:(l.isBackwards=t,l.rendering=null,l.renderingStartTime=0,l.last=n,l.tail=a,l.tailMode=s)}function Cu(e,t,a){var n=t.pendingProps,s=n.revealOrder,l=n.tail;if(xe(e,t,n.children,a),n=de.current,(n&2)!==0)n=n&1|2,t.flags|=128;else{if(e!==null&&(e.flags&128)!==0)e:for(e=t.child;e!==null;){if(e.tag===13)e.memoizedState!==null&&vu(e,a,t);else if(e.tag===19)vu(e,a,t);else if(e.child!==null){e.child.return=e,e=e.child;continue}if(e===t)break e;for(;e.sibling===null;){if(e.return===null||e.return===t)break e;e=e.return}e.sibling.return=e.return,e=e.sibling}n&=1}if(ne(de,n),(t.mode&1)===0)t.memoizedState=null;else switch(s){case"forwards":for(a=t.child,s=null;a!==null;)e=a.alternate,e!==null&&Hr(e)===null&&(s=a),a=a.sibling;a=s,a===null?(s=t.child,t.child=null):(s=a.sibling,a.sibling=null),ns(t,!1,s,a,l);break;case"backwards":for(a=null,s=t.child,t.child=null;s!==null;){if(e=s.alternate,e!==null&&Hr(e)===null){t.child=s;break}e=s.sibling,s.sibling=a,a=s,s=e}ns(t,!0,a,null,l);break;case"together":ns(t,!1,null,null,void 0);break;default:t.memoizedState=null}return t.child}function jr(e,t){(t.mode&1)===0&&e!==null&&(e.alternate=null,t.alternate=null,t.flags|=2)}function Bt(e,t,a){if(e!==null&&(t.dependencies=e.dependencies),Sa|=t.lanes,(a&t.childLanes)===0)return null;if(e!==null&&t.child!==e.child)throw Error(o(153));if(t.child!==null){for(e=t.child,a=na(e,e.pendingProps),t.child=a,a.return=t;e.sibling!==null;)e=e.sibling,a=a.sibling=na(e,e.pendingProps),a.return=t;a.sibling=null}return t.child}function Ah(e,t,a){switch(t.tag){case 3:Tu(t),ja();break;case 5:Bc(t);break;case 1:ze(t.type)&&Pr(t);break;case 4:Bo(t,t.stateNode.containerInfo);break;case 10:var n=t.type._context,s=t.memoizedProps.value;ne(Mr,n._currentValue),n._currentValue=s;break;case 13:if(n=t.memoizedState,n!==null)return n.dehydrated!==null?(ne(de,de.current&1),t.flags|=128,null):(a&t.child.childLanes)!==0?wu(e,t,a):(ne(de,de.current&1),e=Bt(e,t,a),e!==null?e.sibling:null);ne(de,de.current&1);break;case 19:if(n=(a&t.childLanes)!==0,(e.flags&128)!==0){if(n)return Cu(e,t,a);t.flags|=128}if(s=t.memoizedState,s!==null&&(s.rendering=null,s.tail=null,s.lastEffect=null),ne(de,de.current),n)break;return null;case 22:case 23:return t.lanes=0,bu(e,t,a)}return Bt(e,t,a)}var Du,os,Pu,Au;Du=function(e,t){for(var a=t.child;a!==null;){if(a.tag===5||a.tag===6)e.appendChild(a.stateNode);else if(a.tag!==4&&a.child!==null){a.child.return=a,a=a.child;continue}if(a===t)break;for(;a.sibling===null;){if(a.return===null||a.return===t)return;a=a.return}a.sibling.return=a.return,a=a.sibling}},os=function(){},Pu=function(e,t,a,n){var s=e.memoizedProps;if(s!==n){e=t.stateNode,ba(Pt.current);var l=null;switch(a){case"input":s=xn(e,s),n=xn(e,n),l=[];break;case"select":s=I({},s,{value:void 0}),n=I({},n,{value:void 0}),l=[];break;case"textarea":s=Nn(e,s),n=Nn(e,n),l=[];break;default:typeof s.onClick!="function"&&typeof n.onClick=="function"&&(e.onclick=vr)}Un(a,n);var d;a=null;for(k in s)if(!n.hasOwnProperty(k)&&s.hasOwnProperty(k)&&s[k]!=null)if(k==="style"){var f=s[k];for(d in f)f.hasOwnProperty(d)&&(a||(a={}),a[d]="")}else k!=="dangerouslySetInnerHTML"&&k!=="children"&&k!=="suppressContentEditableWarning"&&k!=="suppressHydrationWarning"&&k!=="autoFocus"&&(u.hasOwnProperty(k)?l||(l=[]):(l=l||[]).push(k,null));for(k in n){var h=n[k];if(f=s!=null?s[k]:void 0,n.hasOwnProperty(k)&&h!==f&&(h!=null||f!=null))if(k==="style")if(f){for(d in f)!f.hasOwnProperty(d)||h&&h.hasOwnProperty(d)||(a||(a={}),a[d]="");for(d in h)h.hasOwnProperty(d)&&f[d]!==h[d]&&(a||(a={}),a[d]=h[d])}else a||(l||(l=[]),l.push(k,a)),a=h;else k==="dangerouslySetInnerHTML"?(h=h?h.__html:void 0,f=f?f.__html:void 0,h!=null&&f!==h&&(l=l||[]).push(k,h)):k==="children"?typeof h!="string"&&typeof h!="number"||(l=l||[]).push(k,""+h):k!=="suppressContentEditableWarning"&&k!=="suppressHydrationWarning"&&(u.hasOwnProperty(k)?(h!=null&&k==="onScroll"&&se("scroll",e),l||f===h||(l=[])):(l=l||[]).push(k,h))}a&&(l=l||[]).push("style",a);var k=l;(t.updateQueue=k)&&(t.flags|=4)}},Au=function(e,t,a,n){a!==n&&(t.flags|=4)};function Ui(e,t){if(!ue)switch(e.tailMode){case"hidden":t=e.tail;for(var a=null;t!==null;)t.alternate!==null&&(a=t),t=t.sibling;a===null?e.tail=null:a.sibling=null;break;case"collapsed":a=e.tail;for(var n=null;a!==null;)a.alternate!==null&&(n=a),a=a.sibling;n===null?t||e.tail===null?e.tail=null:e.tail.sibling=null:n.sibling=null}}function Fe(e){var t=e.alternate!==null&&e.alternate.child===e.child,a=0,n=0;if(t)for(var s=e.child;s!==null;)a|=s.lanes|s.childLanes,n|=s.subtreeFlags&14680064,n|=s.flags&14680064,s.return=e,s=s.sibling;else for(s=e.child;s!==null;)a|=s.lanes|s.childLanes,n|=s.subtreeFlags,n|=s.flags,s.return=e,s=s.sibling;return e.subtreeFlags|=n,e.childLanes=a,t}function Lh(e,t,a){var n=t.pendingProps;switch(Lo(t),t.tag){case 2:case 16:case 15:case 0:case 11:case 7:case 8:case 12:case 9:case 14:return Fe(t),null;case 1:return ze(t.type)&&Dr(),Fe(t),null;case 3:return n=t.stateNode,Qa(),le(Ve),le(Le),_o(),n.pendingContext&&(n.context=n.pendingContext,n.pendingContext=null),(e===null||e.child===null)&&(Fr(t)?t.flags|=4:e===null||e.memoizedState.isDehydrated&&(t.flags&256)===0||(t.flags|=1024,mt!==null&&(bs(mt),mt=null))),os(e,t),Fe(t),null;case 5:Uo(t);var s=ba(xi.current);if(a=t.type,e!==null&&t.stateNode!=null)Pu(e,t,a,n,s),e.ref!==t.ref&&(t.flags|=512,t.flags|=2097152);else{if(!n){if(t.stateNode===null)throw Error(o(166));return Fe(t),null}if(e=ba(Pt.current),Fr(t)){n=t.stateNode,a=t.type;var l=t.memoizedProps;switch(n[Dt]=t,n[Ri]=l,e=(t.mode&1)!==0,a){case"dialog":se("cancel",n),se("close",n);break;case"iframe":case"object":case"embed":se("load",n);break;case"video":case"audio":for(s=0;s<Pi.length;s++)se(Pi[s],n);break;case"source":se("error",n);break;case"img":case"image":case"link":se("error",n),se("load",n);break;case"details":se("toggle",n);break;case"input":sl(n,l),se("invalid",n);break;case"select":n._wrapperState={wasMultiple:!!l.multiple},se("invalid",n);break;case"textarea":ul(n,l),se("invalid",n)}Un(a,l),s=null;for(var d in l)if(l.hasOwnProperty(d)){var f=l[d];d==="children"?typeof f=="string"?n.textContent!==f&&(l.suppressHydrationWarning!==!0&&wr(n.textContent,f,e),s=["children",f]):typeof f=="number"&&n.textContent!==""+f&&(l.suppressHydrationWarning!==!0&&wr(n.textContent,f,e),s=["children",""+f]):u.hasOwnProperty(d)&&f!=null&&d==="onScroll"&&se("scroll",n)}switch(a){case"input":Zi(n),cl(n,l,!0);break;case"textarea":Zi(n),pl(n);break;case"select":case"option":break;default:typeof l.onClick=="function"&&(n.onclick=vr)}n=s,t.updateQueue=n,n!==null&&(t.flags|=4)}else{d=s.nodeType===9?s:s.ownerDocument,e==="http://www.w3.org/1999/xhtml"&&(e=fl(a)),e==="http://www.w3.org/1999/xhtml"?a==="script"?(e=d.createElement("div"),e.innerHTML="<script><\/script>",e=e.removeChild(e.firstChild)):typeof n.is=="string"?e=d.createElement(a,{is:n.is}):(e=d.createElement(a),a==="select"&&(d=e,n.multiple?d.multiple=!0:n.size&&(d.size=n.size))):e=d.createElementNS(e,a),e[Dt]=t,e[Ri]=n,Du(e,t,!1,!1),t.stateNode=e;e:{switch(d=Wn(a,n),a){case"dialog":se("cancel",e),se("close",e),s=n;break;case"iframe":case"object":case"embed":se("load",e),s=n;break;case"video":case"audio":for(s=0;s<Pi.length;s++)se(Pi[s],e);s=n;break;case"source":se("error",e),s=n;break;case"img":case"image":case"link":se("error",e),se("load",e),s=n;break;case"details":se("toggle",e),s=n;break;case"input":sl(e,n),s=xn(e,n),se("invalid",e);break;case"option":s=n;break;case"select":e._wrapperState={wasMultiple:!!n.multiple},s=I({},n,{value:void 0}),se("invalid",e);break;case"textarea":ul(e,n),s=Nn(e,n),se("invalid",e);break;default:s=n}Un(a,s),f=s;for(l in f)if(f.hasOwnProperty(l)){var h=f[l];l==="style"?gl(e,h):l==="dangerouslySetInnerHTML"?(h=h?h.__html:void 0,h!=null&&hl(e,h)):l==="children"?typeof h=="string"?(a!=="textarea"||h!=="")&&si(e,h):typeof h=="number"&&si(e,""+h):l!=="suppressContentEditableWarning"&&l!=="suppressHydrationWarning"&&l!=="autoFocus"&&(u.hasOwnProperty(l)?h!=null&&l==="onScroll"&&se("scroll",e):h!=null&&ut(e,l,h,d))}switch(a){case"input":Zi(e),cl(e,n,!1);break;case"textarea":Zi(e),pl(e);break;case"option":n.value!=null&&e.setAttribute("value",""+te(n.value));break;case"select":e.multiple=!!n.multiple,l=n.value,l!=null?Ra(e,!!n.multiple,l,!1):n.defaultValue!=null&&Ra(e,!!n.multiple,n.defaultValue,!0);break;default:typeof s.onClick=="function"&&(e.onclick=vr)}switch(a){case"button":case"input":case"select":case"textarea":n=!!n.autoFocus;break e;case"img":n=!0;break e;default:n=!1}}n&&(t.flags|=4)}t.ref!==null&&(t.flags|=512,t.flags|=2097152)}return Fe(t),null;case 6:if(e&&t.stateNode!=null)Au(e,t,e.memoizedProps,n);else{if(typeof n!="string"&&t.stateNode===null)throw Error(o(166));if(a=ba(xi.current),ba(Pt.current),Fr(t)){if(n=t.stateNode,a=t.memoizedProps,n[Dt]=t,(l=n.nodeValue!==a)&&(e=Je,e!==null))switch(e.tag){case 3:wr(n.nodeValue,a,(e.mode&1)!==0);break;case 5:e.memoizedProps.suppressHydrationWarning!==!0&&wr(n.nodeValue,a,(e.mode&1)!==0)}l&&(t.flags|=4)}else n=(a.nodeType===9?a:a.ownerDocument).createTextNode(n),n[Dt]=t,t.stateNode=n}return Fe(t),null;case 13:if(le(de),n=t.memoizedState,e===null||e.memoizedState!==null&&e.memoizedState.dehydrated!==null){if(ue&&Xe!==null&&(t.mode&1)!==0&&(t.flags&128)===0)Fc(),ja(),t.flags|=98560,l=!1;else if(l=Fr(t),n!==null&&n.dehydrated!==null){if(e===null){if(!l)throw Error(o(318));if(l=t.memoizedState,l=l!==null?l.dehydrated:null,!l)throw Error(o(317));l[Dt]=t}else ja(),(t.flags&128)===0&&(t.memoizedState=null),t.flags|=4;Fe(t),l=!1}else mt!==null&&(bs(mt),mt=null),l=!0;if(!l)return t.flags&65536?t:null}return(t.flags&128)!==0?(t.lanes=a,t):(n=n!==null,n!==(e!==null&&e.memoizedState!==null)&&n&&(t.child.flags|=8192,(t.mode&1)!==0&&(e===null||(de.current&1)!==0?Te===0&&(Te=3):Ts())),t.updateQueue!==null&&(t.flags|=4),Fe(t),null);case 4:return Qa(),os(e,t),e===null&&Ai(t.stateNode.containerInfo),Fe(t),null;case 10:return xo(t.type._context),Fe(t),null;case 17:return ze(t.type)&&Dr(),Fe(t),null;case 19:if(le(de),l=t.memoizedState,l===null)return Fe(t),null;if(n=(t.flags&128)!==0,d=l.rendering,d===null)if(n)Ui(l,!1);else{if(Te!==0||e!==null&&(e.flags&128)!==0)for(e=t.child;e!==null;){if(d=Hr(e),d!==null){for(t.flags|=128,Ui(l,!1),n=d.updateQueue,n!==null&&(t.updateQueue=n,t.flags|=4),t.subtreeFlags=0,n=a,a=t.child;a!==null;)l=a,e=n,l.flags&=14680066,d=l.alternate,d===null?(l.childLanes=0,l.lanes=e,l.child=null,l.subtreeFlags=0,l.memoizedProps=null,l.memoizedState=null,l.updateQueue=null,l.dependencies=null,l.stateNode=null):(l.childLanes=d.childLanes,l.lanes=d.lanes,l.child=d.child,l.subtreeFlags=0,l.deletions=null,l.memoizedProps=d.memoizedProps,l.memoizedState=d.memoizedState,l.updateQueue=d.updateQueue,l.type=d.type,e=d.dependencies,l.dependencies=e===null?null:{lanes:e.lanes,firstContext:e.firstContext}),a=a.sibling;return ne(de,de.current&1|2),t.child}e=e.sibling}l.tail!==null&&me()>Xa&&(t.flags|=128,n=!0,Ui(l,!1),t.lanes=4194304)}else{if(!n)if(e=Hr(d),e!==null){if(t.flags|=128,n=!0,a=e.updateQueue,a!==null&&(t.updateQueue=a,t.flags|=4),Ui(l,!0),l.tail===null&&l.tailMode==="hidden"&&!d.alternate&&!ue)return Fe(t),null}else 2*me()-l.renderingStartTime>Xa&&a!==1073741824&&(t.flags|=128,n=!0,Ui(l,!1),t.lanes=4194304);l.isBackwards?(d.sibling=t.child,t.child=d):(a=l.last,a!==null?a.sibling=d:t.child=d,l.last=d)}return l.tail!==null?(t=l.tail,l.rendering=t,l.tail=t.sibling,l.renderingStartTime=me(),t.sibling=null,a=de.current,ne(de,n?a&1|2:a&1),t):(Fe(t),null);case 22:case 23:return Ss(),n=t.memoizedState!==null,e!==null&&e.memoizedState!==null!==n&&(t.flags|=8192),n&&(t.mode&1)!==0?(Ze&1073741824)!==0&&(Fe(t),t.subtreeFlags&6&&(t.flags|=8192)):Fe(t),null;case 24:return null;case 25:return null}throw Error(o(156,t.tag))}function Rh(e,t){switch(Lo(t),t.tag){case 1:return ze(t.type)&&Dr(),e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 3:return Qa(),le(Ve),le(Le),_o(),e=t.flags,(e&65536)!==0&&(e&128)===0?(t.flags=e&-65537|128,t):null;case 5:return Uo(t),null;case 13:if(le(de),e=t.memoizedState,e!==null&&e.dehydrated!==null){if(t.alternate===null)throw Error(o(340));ja()}return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 19:return le(de),null;case 4:return Qa(),null;case 10:return xo(t.type._context),null;case 22:case 23:return Ss(),null;case 24:return null;default:return null}}var qr=!1,Ee=!1,Fh=typeof WeakSet=="function"?WeakSet:Set,M=null;function $a(e,t){var a=e.ref;if(a!==null)if(typeof a=="function")try{a(null)}catch(n){he(e,t,n)}else a.current=null}function ss(e,t,a){try{a()}catch(n){he(e,t,n)}}var Lu=!1;function Eh(e,t){if(So=dr,e=oc(),uo(e)){if("selectionStart"in e)var a={start:e.selectionStart,end:e.selectionEnd};else e:{a=(a=e.ownerDocument)&&a.defaultView||window;var n=a.getSelection&&a.getSelection();if(n&&n.rangeCount!==0){a=n.anchorNode;var s=n.anchorOffset,l=n.focusNode;n=n.focusOffset;try{a.nodeType,l.nodeType}catch{a=null;break e}var d=0,f=-1,h=-1,k=0,C=0,D=e,w=null;t:for(;;){for(var F;D!==a||s!==0&&D.nodeType!==3||(f=d+s),D!==l||n!==0&&D.nodeType!==3||(h=d+n),D.nodeType===3&&(d+=D.nodeValue.length),(F=D.firstChild)!==null;)w=D,D=F;for(;;){if(D===e)break t;if(w===a&&++k===s&&(f=d),w===l&&++C===n&&(h=d),(F=D.nextSibling)!==null)break;D=w,w=D.parentNode}D=F}a=f===-1||h===-1?null:{start:f,end:h}}else a=null}a=a||{start:0,end:0}}else a=null;for(To={focusedElem:e,selectionRange:a},dr=!1,M=t;M!==null;)if(t=M,e=t.child,(t.subtreeFlags&1028)!==0&&e!==null)e.return=t,M=e;else for(;M!==null;){t=M;try{var x=t.alternate;if((t.flags&1024)!==0)switch(t.tag){case 0:case 11:case 15:break;case 1:if(x!==null){var H=x.memoizedProps,ge=x.memoizedState,b=t.stateNode,m=b.getSnapshotBeforeUpdate(t.elementType===t.type?H:gt(t.type,H),ge);b.__reactInternalSnapshotBeforeUpdate=m}break;case 3:var T=t.stateNode.containerInfo;T.nodeType===1?T.textContent="":T.nodeType===9&&T.documentElement&&T.removeChild(T.documentElement);break;case 5:case 6:case 4:case 17:break;default:throw Error(o(163))}}catch(P){he(t,t.return,P)}if(e=t.sibling,e!==null){e.return=t.return,M=e;break}M=t.return}return x=Lu,Lu=!1,x}function Wi(e,t,a){var n=t.updateQueue;if(n=n!==null?n.lastEffect:null,n!==null){var s=n=n.next;do{if((s.tag&e)===e){var l=s.destroy;s.destroy=void 0,l!==void 0&&ss(t,a,l)}s=s.next}while(s!==n)}}function Gr(e,t){if(t=t.updateQueue,t=t!==null?t.lastEffect:null,t!==null){var a=t=t.next;do{if((a.tag&e)===e){var n=a.create;a.destroy=n()}a=a.next}while(a!==t)}}function ls(e){var t=e.ref;if(t!==null){var a=e.stateNode;switch(e.tag){case 5:e=a;break;default:e=a}typeof t=="function"?t(e):t.current=e}}function Ru(e){var t=e.alternate;t!==null&&(e.alternate=null,Ru(t)),e.child=null,e.deletions=null,e.sibling=null,e.tag===5&&(t=e.stateNode,t!==null&&(delete t[Dt],delete t[Ri],delete t[Co],delete t[fh],delete t[hh])),e.stateNode=null,e.return=null,e.dependencies=null,e.memoizedProps=null,e.memoizedState=null,e.pendingProps=null,e.stateNode=null,e.updateQueue=null}function Fu(e){return e.tag===5||e.tag===3||e.tag===4}function Eu(e){e:for(;;){for(;e.sibling===null;){if(e.return===null||Fu(e.return))return null;e=e.return}for(e.sibling.return=e.return,e=e.sibling;e.tag!==5&&e.tag!==6&&e.tag!==18;){if(e.flags&2||e.child===null||e.tag===4)continue e;e.child.return=e,e=e.child}if(!(e.flags&2))return e.stateNode}}function cs(e,t,a){var n=e.tag;if(n===5||n===6)e=e.stateNode,t?a.nodeType===8?a.parentNode.insertBefore(e,t):a.insertBefore(e,t):(a.nodeType===8?(t=a.parentNode,t.insertBefore(e,a)):(t=a,t.appendChild(e)),a=a._reactRootContainer,a!=null||t.onclick!==null||(t.onclick=vr));else if(n!==4&&(e=e.child,e!==null))for(cs(e,t,a),e=e.sibling;e!==null;)cs(e,t,a),e=e.sibling}function us(e,t,a){var n=e.tag;if(n===5||n===6)e=e.stateNode,t?a.insertBefore(e,t):a.appendChild(e);else if(n!==4&&(e=e.child,e!==null))for(us(e,t,a),e=e.sibling;e!==null;)us(e,t,a),e=e.sibling}var De=null,bt=!1;function ea(e,t,a){for(a=a.child;a!==null;)Mu(e,t,a),a=a.sibling}function Mu(e,t,a){if(Ct&&typeof Ct.onCommitFiberUnmount=="function")try{Ct.onCommitFiberUnmount(nr,a)}catch{}switch(a.tag){case 5:Ee||$a(a,t);case 6:var n=De,s=bt;De=null,ea(e,t,a),De=n,bt=s,De!==null&&(bt?(e=De,a=a.stateNode,e.nodeType===8?e.parentNode.removeChild(a):e.removeChild(a)):De.removeChild(a.stateNode));break;case 18:De!==null&&(bt?(e=De,a=a.stateNode,e.nodeType===8?vo(e.parentNode,a):e.nodeType===1&&vo(e,a),yi(e)):vo(De,a.stateNode));break;case 4:n=De,s=bt,De=a.stateNode.containerInfo,bt=!0,ea(e,t,a),De=n,bt=s;break;case 0:case 11:case 14:case 15:if(!Ee&&(n=a.updateQueue,n!==null&&(n=n.lastEffect,n!==null))){s=n=n.next;do{var l=s,d=l.destroy;l=l.tag,d!==void 0&&((l&2)!==0||(l&4)!==0)&&ss(a,t,d),s=s.next}while(s!==n)}ea(e,t,a);break;case 1:if(!Ee&&($a(a,t),n=a.stateNode,typeof n.componentWillUnmount=="function"))try{n.props=a.memoizedProps,n.state=a.memoizedState,n.componentWillUnmount()}catch(f){he(a,t,f)}ea(e,t,a);break;case 21:ea(e,t,a);break;case 22:a.mode&1?(Ee=(n=Ee)||a.memoizedState!==null,ea(e,t,a),Ee=n):ea(e,t,a);break;default:ea(e,t,a)}}function Iu(e){var t=e.updateQueue;if(t!==null){e.updateQueue=null;var a=e.stateNode;a===null&&(a=e.stateNode=new Fh),t.forEach(function(n){var s=Wh.bind(null,e,n);a.has(n)||(a.add(n),n.then(s,s))})}}function yt(e,t){var a=t.deletions;if(a!==null)for(var n=0;n<a.length;n++){var s=a[n];try{var l=e,d=t,f=d;e:for(;f!==null;){switch(f.tag){case 5:De=f.stateNode,bt=!1;break e;case 3:De=f.stateNode.containerInfo,bt=!0;break e;case 4:De=f.stateNode.containerInfo,bt=!0;break e}f=f.return}if(De===null)throw Error(o(160));Mu(l,d,s),De=null,bt=!1;var h=s.alternate;h!==null&&(h.return=null),s.return=null}catch(k){he(s,t,k)}}if(t.subtreeFlags&12854)for(t=t.child;t!==null;)xu(t,e),t=t.sibling}function xu(e,t){var a=e.alternate,n=e.flags;switch(e.tag){case 0:case 11:case 14:case 15:if(yt(t,e),Lt(e),n&4){try{Wi(3,e,e.return),Gr(3,e)}catch(H){he(e,e.return,H)}try{Wi(5,e,e.return)}catch(H){he(e,e.return,H)}}break;case 1:yt(t,e),Lt(e),n&512&&a!==null&&$a(a,a.return);break;case 5:if(yt(t,e),Lt(e),n&512&&a!==null&&$a(a,a.return),e.flags&32){var s=e.stateNode;try{si(s,"")}catch(H){he(e,e.return,H)}}if(n&4&&(s=e.stateNode,s!=null)){var l=e.memoizedProps,d=a!==null?a.memoizedProps:l,f=e.type,h=e.updateQueue;if(e.updateQueue=null,h!==null)try{f==="input"&&l.type==="radio"&&l.name!=null&&ll(s,l),Wn(f,d);var k=Wn(f,l);for(d=0;d<h.length;d+=2){var C=h[d],D=h[d+1];C==="style"?gl(s,D):C==="dangerouslySetInnerHTML"?hl(s,D):C==="children"?si(s,D):ut(s,C,D,k)}switch(f){case"input":On(s,l);break;case"textarea":dl(s,l);break;case"select":var w=s._wrapperState.wasMultiple;s._wrapperState.wasMultiple=!!l.multiple;var F=l.value;F!=null?Ra(s,!!l.multiple,F,!1):w!==!!l.multiple&&(l.defaultValue!=null?Ra(s,!!l.multiple,l.defaultValue,!0):Ra(s,!!l.multiple,l.multiple?[]:"",!1))}s[Ri]=l}catch(H){he(e,e.return,H)}}break;case 6:if(yt(t,e),Lt(e),n&4){if(e.stateNode===null)throw Error(o(162));s=e.stateNode,l=e.memoizedProps;try{s.nodeValue=l}catch(H){he(e,e.return,H)}}break;case 3:if(yt(t,e),Lt(e),n&4&&a!==null&&a.memoizedState.isDehydrated)try{yi(t.containerInfo)}catch(H){he(e,e.return,H)}break;case 4:yt(t,e),Lt(e);break;case 13:yt(t,e),Lt(e),s=e.child,s.flags&8192&&(l=s.memoizedState!==null,s.stateNode.isHidden=l,!l||s.alternate!==null&&s.alternate.memoizedState!==null||(fs=me())),n&4&&Iu(e);break;case 22:if(C=a!==null&&a.memoizedState!==null,e.mode&1?(Ee=(k=Ee)||C,yt(t,e),Ee=k):yt(t,e),Lt(e),n&8192){if(k=e.memoizedState!==null,(e.stateNode.isHidden=k)&&!C&&(e.mode&1)!==0)for(M=e,C=e.child;C!==null;){for(D=M=C;M!==null;){switch(w=M,F=w.child,w.tag){case 0:case 11:case 14:case 15:Wi(4,w,w.return);break;case 1:$a(w,w.return);var x=w.stateNode;if(typeof x.componentWillUnmount=="function"){n=w,a=w.return;try{t=n,x.props=t.memoizedProps,x.state=t.memoizedState,x.componentWillUnmount()}catch(H){he(n,a,H)}}break;case 5:$a(w,w.return);break;case 22:if(w.memoizedState!==null){Nu(D);continue}}F!==null?(F.return=w,M=F):Nu(D)}C=C.sibling}e:for(C=null,D=e;;){if(D.tag===5){if(C===null){C=D;try{s=D.stateNode,k?(l=s.style,typeof l.setProperty=="function"?l.setProperty("display","none","important"):l.display="none"):(f=D.stateNode,h=D.memoizedProps.style,d=h!=null&&h.hasOwnProperty("display")?h.display:null,f.style.display=ml("display",d))}catch(H){he(e,e.return,H)}}}else if(D.tag===6){if(C===null)try{D.stateNode.nodeValue=k?"":D.memoizedProps}catch(H){he(e,e.return,H)}}else if((D.tag!==22&&D.tag!==23||D.memoizedState===null||D===e)&&D.child!==null){D.child.return=D,D=D.child;continue}if(D===e)break e;for(;D.sibling===null;){if(D.return===null||D.return===e)break e;C===D&&(C=null),D=D.return}C===D&&(C=null),D.sibling.return=D.return,D=D.sibling}}break;case 19:yt(t,e),Lt(e),n&4&&Iu(e);break;case 21:break;default:yt(t,e),Lt(e)}}function Lt(e){var t=e.flags;if(t&2){try{e:{for(var a=e.return;a!==null;){if(Fu(a)){var n=a;break e}a=a.return}throw Error(o(160))}switch(n.tag){case 5:var s=n.stateNode;n.flags&32&&(si(s,""),n.flags&=-33);var l=Eu(e);us(e,l,s);break;case 3:case 4:var d=n.stateNode.containerInfo,f=Eu(e);cs(e,f,d);break;default:throw Error(o(161))}}catch(h){he(e,e.return,h)}e.flags&=-3}t&4096&&(e.flags&=-4097)}function Mh(e,t,a){M=e,Ou(e)}function Ou(e,t,a){for(var n=(e.mode&1)!==0;M!==null;){var s=M,l=s.child;if(s.tag===22&&n){var d=s.memoizedState!==null||qr;if(!d){var f=s.alternate,h=f!==null&&f.memoizedState!==null||Ee;f=qr;var k=Ee;if(qr=d,(Ee=h)&&!k)for(M=s;M!==null;)d=M,h=d.child,d.tag===22&&d.memoizedState!==null?Bu(s):h!==null?(h.return=d,M=h):Bu(s);for(;l!==null;)M=l,Ou(l),l=l.sibling;M=s,qr=f,Ee=k}Hu(e)}else(s.subtreeFlags&8772)!==0&&l!==null?(l.return=s,M=l):Hu(e)}}function Hu(e){for(;M!==null;){var t=M;if((t.flags&8772)!==0){var a=t.alternate;try{if((t.flags&8772)!==0)switch(t.tag){case 0:case 11:case 15:Ee||Gr(5,t);break;case 1:var n=t.stateNode;if(t.flags&4&&!Ee)if(a===null)n.componentDidMount();else{var s=t.elementType===t.type?a.memoizedProps:gt(t.type,a.memoizedProps);n.componentDidUpdate(s,a.memoizedState,n.__reactInternalSnapshotBeforeUpdate)}var l=t.updateQueue;l!==null&&Nc(t,l,n);break;case 3:var d=t.updateQueue;if(d!==null){if(a=null,t.child!==null)switch(t.child.tag){case 5:a=t.child.stateNode;break;case 1:a=t.child.stateNode}Nc(t,d,a)}break;case 5:var f=t.stateNode;if(a===null&&t.flags&4){a=f;var h=t.memoizedProps;switch(t.type){case"button":case"input":case"select":case"textarea":h.autoFocus&&a.focus();break;case"img":h.src&&(a.src=h.src)}}break;case 6:break;case 4:break;case 12:break;case 13:if(t.memoizedState===null){var k=t.alternate;if(k!==null){var C=k.memoizedState;if(C!==null){var D=C.dehydrated;D!==null&&yi(D)}}}break;case 19:case 17:case 21:case 22:case 23:case 25:break;default:throw Error(o(163))}Ee||t.flags&512&&ls(t)}catch(w){he(t,t.return,w)}}if(t===e){M=null;break}if(a=t.sibling,a!==null){a.return=t.return,M=a;break}M=t.return}}function Nu(e){for(;M!==null;){var t=M;if(t===e){M=null;break}var a=t.sibling;if(a!==null){a.return=t.return,M=a;break}M=t.return}}function Bu(e){for(;M!==null;){var t=M;try{switch(t.tag){case 0:case 11:case 15:var a=t.return;try{Gr(4,t)}catch(h){he(t,a,h)}break;case 1:var n=t.stateNode;if(typeof n.componentDidMount=="function"){var s=t.return;try{n.componentDidMount()}catch(h){he(t,s,h)}}var l=t.return;try{ls(t)}catch(h){he(t,l,h)}break;case 5:var d=t.return;try{ls(t)}catch(h){he(t,d,h)}}}catch(h){he(t,t.return,h)}if(t===e){M=null;break}var f=t.sibling;if(f!==null){f.return=t.return,M=f;break}M=t.return}}var Ih=Math.ceil,Kr=Ae.ReactCurrentDispatcher,ds=Ae.ReactCurrentOwner,st=Ae.ReactCurrentBatchConfig,Y=0,ve=null,be=null,Pe=0,Ze=0,Ja=Yt(0),Te=0,_i=null,Sa=0,Qr=0,ps=0,Vi=null,qe=null,fs=0,Xa=1/0,Ut=null,Yr=!1,hs=null,ta=null,$r=!1,aa=null,Jr=0,zi=0,ms=null,Xr=-1,Zr=0;function Oe(){return(Y&6)!==0?me():Xr!==-1?Xr:Xr=me()}function ia(e){return(e.mode&1)===0?1:(Y&2)!==0&&Pe!==0?Pe&-Pe:gh.transition!==null?(Zr===0&&(Zr=El()),Zr):(e=ae,e!==0||(e=window.event,e=e===void 0?16:Wl(e.type)),e)}function St(e,t,a,n){if(50<zi)throw zi=0,ms=null,Error(o(185));fi(e,a,n),((Y&2)===0||e!==ve)&&(e===ve&&((Y&2)===0&&(Qr|=a),Te===4&&ra(e,Pe)),Ge(e,n),a===1&&Y===0&&(t.mode&1)===0&&(Xa=me()+500,Ar&&Jt()))}function Ge(e,t){var a=e.callbackNode;gf(e,t);var n=lr(e,e===ve?Pe:0);if(n===0)a!==null&&Ll(a),e.callbackNode=null,e.callbackPriority=0;else if(t=n&-n,e.callbackPriority!==t){if(a!=null&&Ll(a),t===1)e.tag===0?mh(Wu.bind(null,e)):Dc(Wu.bind(null,e)),dh(function(){(Y&6)===0&&Jt()}),a=null;else{switch(Ml(n)){case 1:a=Kn;break;case 4:a=Rl;break;case 16:a=rr;break;case 536870912:a=Fl;break;default:a=rr}a=Qu(a,Uu.bind(null,e))}e.callbackPriority=t,e.callbackNode=a}}function Uu(e,t){if(Xr=-1,Zr=0,(Y&6)!==0)throw Error(o(327));var a=e.callbackNode;if(Za()&&e.callbackNode!==a)return null;var n=lr(e,e===ve?Pe:0);if(n===0)return null;if((n&30)!==0||(n&e.expiredLanes)!==0||t)t=en(e,n);else{t=n;var s=Y;Y|=2;var l=Vu();(ve!==e||Pe!==t)&&(Ut=null,Xa=me()+500,ka(e,t));do try{Hh();break}catch(f){_u(e,f)}while(!0);Io(),Kr.current=l,Y=s,be!==null?t=0:(ve=null,Pe=0,t=Te)}if(t!==0){if(t===2&&(s=Qn(e),s!==0&&(n=s,t=gs(e,s))),t===1)throw a=_i,ka(e,0),ra(e,n),Ge(e,me()),a;if(t===6)ra(e,n);else{if(s=e.current.alternate,(n&30)===0&&!xh(s)&&(t=en(e,n),t===2&&(l=Qn(e),l!==0&&(n=l,t=gs(e,l))),t===1))throw a=_i,ka(e,0),ra(e,n),Ge(e,me()),a;switch(e.finishedWork=s,e.finishedLanes=n,t){case 0:case 1:throw Error(o(345));case 2:wa(e,qe,Ut);break;case 3:if(ra(e,n),(n&130023424)===n&&(t=fs+500-me(),10<t)){if(lr(e,0)!==0)break;if(s=e.suspendedLanes,(s&n)!==n){Oe(),e.pingedLanes|=e.suspendedLanes&s;break}e.timeoutHandle=wo(wa.bind(null,e,qe,Ut),t);break}wa(e,qe,Ut);break;case 4:if(ra(e,n),(n&4194240)===n)break;for(t=e.eventTimes,s=-1;0<n;){var d=31-ft(n);l=1<<d,d=t[d],d>s&&(s=d),n&=~l}if(n=s,n=me()-n,n=(120>n?120:480>n?480:1080>n?1080:1920>n?1920:3e3>n?3e3:4320>n?4320:1960*Ih(n/1960))-n,10<n){e.timeoutHandle=wo(wa.bind(null,e,qe,Ut),n);break}wa(e,qe,Ut);break;case 5:wa(e,qe,Ut);break;default:throw Error(o(329))}}}return Ge(e,me()),e.callbackNode===a?Uu.bind(null,e):null}function gs(e,t){var a=Vi;return e.current.memoizedState.isDehydrated&&(ka(e,t).flags|=256),e=en(e,t),e!==2&&(t=qe,qe=a,t!==null&&bs(t)),e}function bs(e){qe===null?qe=e:qe.push.apply(qe,e)}function xh(e){for(var t=e;;){if(t.flags&16384){var a=t.updateQueue;if(a!==null&&(a=a.stores,a!==null))for(var n=0;n<a.length;n++){var s=a[n],l=s.getSnapshot;s=s.value;try{if(!ht(l(),s))return!1}catch{return!1}}}if(a=t.child,t.subtreeFlags&16384&&a!==null)a.return=t,t=a;else{if(t===e)break;for(;t.sibling===null;){if(t.return===null||t.return===e)return!0;t=t.return}t.sibling.return=t.return,t=t.sibling}}return!0}function ra(e,t){for(t&=~ps,t&=~Qr,e.suspendedLanes|=t,e.pingedLanes&=~t,e=e.expirationTimes;0<t;){var a=31-ft(t),n=1<<a;e[a]=-1,t&=~n}}function Wu(e){if((Y&6)!==0)throw Error(o(327));Za();var t=lr(e,0);if((t&1)===0)return Ge(e,me()),null;var a=en(e,t);if(e.tag!==0&&a===2){var n=Qn(e);n!==0&&(t=n,a=gs(e,n))}if(a===1)throw a=_i,ka(e,0),ra(e,t),Ge(e,me()),a;if(a===6)throw Error(o(345));return e.finishedWork=e.current.alternate,e.finishedLanes=t,wa(e,qe,Ut),Ge(e,me()),null}function ys(e,t){var a=Y;Y|=1;try{return e(t)}finally{Y=a,Y===0&&(Xa=me()+500,Ar&&Jt())}}function Ta(e){aa!==null&&aa.tag===0&&(Y&6)===0&&Za();var t=Y;Y|=1;var a=st.transition,n=ae;try{if(st.transition=null,ae=1,e)return e()}finally{ae=n,st.transition=a,Y=t,(Y&6)===0&&Jt()}}function Ss(){Ze=Ja.current,le(Ja)}function ka(e,t){e.finishedWork=null,e.finishedLanes=0;var a=e.timeoutHandle;if(a!==-1&&(e.timeoutHandle=-1,uh(a)),be!==null)for(a=be.return;a!==null;){var n=a;switch(Lo(n),n.tag){case 1:n=n.type.childContextTypes,n!=null&&Dr();break;case 3:Qa(),le(Ve),le(Le),_o();break;case 5:Uo(n);break;case 4:Qa();break;case 13:le(de);break;case 19:le(de);break;case 10:xo(n.type._context);break;case 22:case 23:Ss()}a=a.return}if(ve=e,be=e=na(e.current,null),Pe=Ze=t,Te=0,_i=null,ps=Qr=Sa=0,qe=Vi=null,ga!==null){for(t=0;t<ga.length;t++)if(a=ga[t],n=a.interleaved,n!==null){a.interleaved=null;var s=n.next,l=a.pending;if(l!==null){var d=l.next;l.next=s,n.next=d}a.pending=n}ga=null}return e}function _u(e,t){do{var a=be;try{if(Io(),Nr.current=_r,Br){for(var n=pe.memoizedState;n!==null;){var s=n.queue;s!==null&&(s.pending=null),n=n.next}Br=!1}if(ya=0,we=Se=pe=null,Oi=!1,Hi=0,ds.current=null,a===null||a.return===null){Te=1,_i=t,be=null;break}e:{var l=e,d=a.return,f=a,h=t;if(t=Pe,f.flags|=32768,h!==null&&typeof h=="object"&&typeof h.then=="function"){var k=h,C=f,D=C.tag;if((C.mode&1)===0&&(D===0||D===11||D===15)){var w=C.alternate;w?(C.updateQueue=w.updateQueue,C.memoizedState=w.memoizedState,C.lanes=w.lanes):(C.updateQueue=null,C.memoizedState=null)}var F=pu(d);if(F!==null){F.flags&=-257,fu(F,d,f,l,t),F.mode&1&&du(l,k,t),t=F,h=k;var x=t.updateQueue;if(x===null){var H=new Set;H.add(h),t.updateQueue=H}else x.add(h);break e}else{if((t&1)===0){du(l,k,t),Ts();break e}h=Error(o(426))}}else if(ue&&f.mode&1){var ge=pu(d);if(ge!==null){(ge.flags&65536)===0&&(ge.flags|=256),fu(ge,d,f,l,t),Eo(Ya(h,f));break e}}l=h=Ya(h,f),Te!==4&&(Te=2),Vi===null?Vi=[l]:Vi.push(l),l=d;do{switch(l.tag){case 3:l.flags|=65536,t&=-t,l.lanes|=t;var b=cu(l,h,t);Hc(l,b);break e;case 1:f=h;var m=l.type,T=l.stateNode;if((l.flags&128)===0&&(typeof m.getDerivedStateFromError=="function"||T!==null&&typeof T.componentDidCatch=="function"&&(ta===null||!ta.has(T)))){l.flags|=65536,t&=-t,l.lanes|=t;var P=uu(l,f,t);Hc(l,P);break e}}l=l.return}while(l!==null)}ju(a)}catch(N){t=N,be===a&&a!==null&&(be=a=a.return);continue}break}while(!0)}function Vu(){var e=Kr.current;return Kr.current=_r,e===null?_r:e}function Ts(){(Te===0||Te===3||Te===2)&&(Te=4),ve===null||(Sa&268435455)===0&&(Qr&268435455)===0||ra(ve,Pe)}function en(e,t){var a=Y;Y|=2;var n=Vu();(ve!==e||Pe!==t)&&(Ut=null,ka(e,t));do try{Oh();break}catch(s){_u(e,s)}while(!0);if(Io(),Y=a,Kr.current=n,be!==null)throw Error(o(261));return ve=null,Pe=0,Te}function Oh(){for(;be!==null;)zu(be)}function Hh(){for(;be!==null&&!sf();)zu(be)}function zu(e){var t=Ku(e.alternate,e,Ze);e.memoizedProps=e.pendingProps,t===null?ju(e):be=t,ds.current=null}function ju(e){var t=e;do{var a=t.alternate;if(e=t.return,(t.flags&32768)===0){if(a=Lh(a,t,Ze),a!==null){be=a;return}}else{if(a=Rh(a,t),a!==null){a.flags&=32767,be=a;return}if(e!==null)e.flags|=32768,e.subtreeFlags=0,e.deletions=null;else{Te=6,be=null;return}}if(t=t.sibling,t!==null){be=t;return}be=t=e}while(t!==null);Te===0&&(Te=5)}function wa(e,t,a){var n=ae,s=st.transition;try{st.transition=null,ae=1,Nh(e,t,a,n)}finally{st.transition=s,ae=n}return null}function Nh(e,t,a,n){do Za();while(aa!==null);if((Y&6)!==0)throw Error(o(327));a=e.finishedWork;var s=e.finishedLanes;if(a===null)return null;if(e.finishedWork=null,e.finishedLanes=0,a===e.current)throw Error(o(177));e.callbackNode=null,e.callbackPriority=0;var l=a.lanes|a.childLanes;if(bf(e,l),e===ve&&(be=ve=null,Pe=0),(a.subtreeFlags&2064)===0&&(a.flags&2064)===0||$r||($r=!0,Qu(rr,function(){return Za(),null})),l=(a.flags&15990)!==0,(a.subtreeFlags&15990)!==0||l){l=st.transition,st.transition=null;var d=ae;ae=1;var f=Y;Y|=4,ds.current=null,Eh(e,a),xu(a,e),ih(To),dr=!!So,To=So=null,e.current=a,Mh(a),lf(),Y=f,ae=d,st.transition=l}else e.current=a;if($r&&($r=!1,aa=e,Jr=s),l=e.pendingLanes,l===0&&(ta=null),df(a.stateNode),Ge(e,me()),t!==null)for(n=e.onRecoverableError,a=0;a<t.length;a++)s=t[a],n(s.value,{componentStack:s.stack,digest:s.digest});if(Yr)throw Yr=!1,e=hs,hs=null,e;return(Jr&1)!==0&&e.tag!==0&&Za(),l=e.pendingLanes,(l&1)!==0?e===ms?zi++:(zi=0,ms=e):zi=0,Jt(),null}function Za(){if(aa!==null){var e=Ml(Jr),t=st.transition,a=ae;try{if(st.transition=null,ae=16>e?16:e,aa===null)var n=!1;else{if(e=aa,aa=null,Jr=0,(Y&6)!==0)throw Error(o(331));var s=Y;for(Y|=4,M=e.current;M!==null;){var l=M,d=l.child;if((M.flags&16)!==0){var f=l.deletions;if(f!==null){for(var h=0;h<f.length;h++){var k=f[h];for(M=k;M!==null;){var C=M;switch(C.tag){case 0:case 11:case 15:Wi(8,C,l)}var D=C.child;if(D!==null)D.return=C,M=D;else for(;M!==null;){C=M;var w=C.sibling,F=C.return;if(Ru(C),C===k){M=null;break}if(w!==null){w.return=F,M=w;break}M=F}}}var x=l.alternate;if(x!==null){var H=x.child;if(H!==null){x.child=null;do{var ge=H.sibling;H.sibling=null,H=ge}while(H!==null)}}M=l}}if((l.subtreeFlags&2064)!==0&&d!==null)d.return=l,M=d;else e:for(;M!==null;){if(l=M,(l.flags&2048)!==0)switch(l.tag){case 0:case 11:case 15:Wi(9,l,l.return)}var b=l.sibling;if(b!==null){b.return=l.return,M=b;break e}M=l.return}}var m=e.current;for(M=m;M!==null;){d=M;var T=d.child;if((d.subtreeFlags&2064)!==0&&T!==null)T.return=d,M=T;else e:for(d=m;M!==null;){if(f=M,(f.flags&2048)!==0)try{switch(f.tag){case 0:case 11:case 15:Gr(9,f)}}catch(N){he(f,f.return,N)}if(f===d){M=null;break e}var P=f.sibling;if(P!==null){P.return=f.return,M=P;break e}M=f.return}}if(Y=s,Jt(),Ct&&typeof Ct.onPostCommitFiberRoot=="function")try{Ct.onPostCommitFiberRoot(nr,e)}catch{}n=!0}return n}finally{ae=a,st.transition=t}}return!1}function qu(e,t,a){t=Ya(a,t),t=cu(e,t,1),e=Zt(e,t,1),t=Oe(),e!==null&&(fi(e,1,t),Ge(e,t))}function he(e,t,a){if(e.tag===3)qu(e,e,a);else for(;t!==null;){if(t.tag===3){qu(t,e,a);break}else if(t.tag===1){var n=t.stateNode;if(typeof t.type.getDerivedStateFromError=="function"||typeof n.componentDidCatch=="function"&&(ta===null||!ta.has(n))){e=Ya(a,e),e=uu(t,e,1),t=Zt(t,e,1),e=Oe(),t!==null&&(fi(t,1,e),Ge(t,e));break}}t=t.return}}function Bh(e,t,a){var n=e.pingCache;n!==null&&n.delete(t),t=Oe(),e.pingedLanes|=e.suspendedLanes&a,ve===e&&(Pe&a)===a&&(Te===4||Te===3&&(Pe&130023424)===Pe&&500>me()-fs?ka(e,0):ps|=a),Ge(e,t)}function Gu(e,t){t===0&&((e.mode&1)===0?t=1:(t=sr,sr<<=1,(sr&130023424)===0&&(sr=4194304)));var a=Oe();e=Ht(e,t),e!==null&&(fi(e,t,a),Ge(e,a))}function Uh(e){var t=e.memoizedState,a=0;t!==null&&(a=t.retryLane),Gu(e,a)}function Wh(e,t){var a=0;switch(e.tag){case 13:var n=e.stateNode,s=e.memoizedState;s!==null&&(a=s.retryLane);break;case 19:n=e.stateNode;break;default:throw Error(o(314))}n!==null&&n.delete(t),Gu(e,a)}var Ku;Ku=function(e,t,a){if(e!==null)if(e.memoizedProps!==t.pendingProps||Ve.current)je=!0;else{if((e.lanes&a)===0&&(t.flags&128)===0)return je=!1,Ah(e,t,a);je=(e.flags&131072)!==0}else je=!1,ue&&(t.flags&1048576)!==0&&Pc(t,Rr,t.index);switch(t.lanes=0,t.tag){case 2:var n=t.type;jr(e,t),e=t.pendingProps;var s=_a(t,Le.current);Ka(t,a),s=jo(null,t,n,e,s,a);var l=qo();return t.flags|=1,typeof s=="object"&&s!==null&&typeof s.render=="function"&&s.$$typeof===void 0?(t.tag=1,t.memoizedState=null,t.updateQueue=null,ze(n)?(l=!0,Pr(t)):l=!1,t.memoizedState=s.state!==null&&s.state!==void 0?s.state:null,No(t),s.updater=Vr,t.stateNode=s,s._reactInternals=t,Jo(t,n,e,a),t=ts(null,t,n,!0,l,a)):(t.tag=0,ue&&l&&Ao(t),xe(null,t,s,a),t=t.child),t;case 16:n=t.elementType;e:{switch(jr(e,t),e=t.pendingProps,s=n._init,n=s(n._payload),t.type=n,s=t.tag=Vh(n),e=gt(n,e),s){case 0:t=es(null,t,n,e,a);break e;case 1:t=Su(null,t,n,e,a);break e;case 11:t=hu(null,t,n,e,a);break e;case 14:t=mu(null,t,n,gt(n.type,e),a);break e}throw Error(o(306,n,""))}return t;case 0:return n=t.type,s=t.pendingProps,s=t.elementType===n?s:gt(n,s),es(e,t,n,s,a);case 1:return n=t.type,s=t.pendingProps,s=t.elementType===n?s:gt(n,s),Su(e,t,n,s,a);case 3:e:{if(Tu(t),e===null)throw Error(o(387));n=t.pendingProps,l=t.memoizedState,s=l.element,Oc(e,t),Or(t,n,null,a);var d=t.memoizedState;if(n=d.element,l.isDehydrated)if(l={element:n,isDehydrated:!1,cache:d.cache,pendingSuspenseBoundaries:d.pendingSuspenseBoundaries,transitions:d.transitions},t.updateQueue.baseState=l,t.memoizedState=l,t.flags&256){s=Ya(Error(o(423)),t),t=ku(e,t,n,a,s);break e}else if(n!==s){s=Ya(Error(o(424)),t),t=ku(e,t,n,a,s);break e}else for(Xe=Qt(t.stateNode.containerInfo.firstChild),Je=t,ue=!0,mt=null,a=Ic(t,null,n,a),t.child=a;a;)a.flags=a.flags&-3|4096,a=a.sibling;else{if(ja(),n===s){t=Bt(e,t,a);break e}xe(e,t,n,a)}t=t.child}return t;case 5:return Bc(t),e===null&&Fo(t),n=t.type,s=t.pendingProps,l=e!==null?e.memoizedProps:null,d=s.children,ko(n,s)?d=null:l!==null&&ko(n,l)&&(t.flags|=32),yu(e,t),xe(e,t,d,a),t.child;case 6:return e===null&&Fo(t),null;case 13:return wu(e,t,a);case 4:return Bo(t,t.stateNode.containerInfo),n=t.pendingProps,e===null?t.child=qa(t,null,n,a):xe(e,t,n,a),t.child;case 11:return n=t.type,s=t.pendingProps,s=t.elementType===n?s:gt(n,s),hu(e,t,n,s,a);case 7:return xe(e,t,t.pendingProps,a),t.child;case 8:return xe(e,t,t.pendingProps.children,a),t.child;case 12:return xe(e,t,t.pendingProps.children,a),t.child;case 10:e:{if(n=t.type._context,s=t.pendingProps,l=t.memoizedProps,d=s.value,ne(Mr,n._currentValue),n._currentValue=d,l!==null)if(ht(l.value,d)){if(l.children===s.children&&!Ve.current){t=Bt(e,t,a);break e}}else for(l=t.child,l!==null&&(l.return=t);l!==null;){var f=l.dependencies;if(f!==null){d=l.child;for(var h=f.firstContext;h!==null;){if(h.context===n){if(l.tag===1){h=Nt(-1,a&-a),h.tag=2;var k=l.updateQueue;if(k!==null){k=k.shared;var C=k.pending;C===null?h.next=h:(h.next=C.next,C.next=h),k.pending=h}}l.lanes|=a,h=l.alternate,h!==null&&(h.lanes|=a),Oo(l.return,a,t),f.lanes|=a;break}h=h.next}}else if(l.tag===10)d=l.type===t.type?null:l.child;else if(l.tag===18){if(d=l.return,d===null)throw Error(o(341));d.lanes|=a,f=d.alternate,f!==null&&(f.lanes|=a),Oo(d,a,t),d=l.sibling}else d=l.child;if(d!==null)d.return=l;else for(d=l;d!==null;){if(d===t){d=null;break}if(l=d.sibling,l!==null){l.return=d.return,d=l;break}d=d.return}l=d}xe(e,t,s.children,a),t=t.child}return t;case 9:return s=t.type,n=t.pendingProps.children,Ka(t,a),s=nt(s),n=n(s),t.flags|=1,xe(e,t,n,a),t.child;case 14:return n=t.type,s=gt(n,t.pendingProps),s=gt(n.type,s),mu(e,t,n,s,a);case 15:return gu(e,t,t.type,t.pendingProps,a);case 17:return n=t.type,s=t.pendingProps,s=t.elementType===n?s:gt(n,s),jr(e,t),t.tag=1,ze(n)?(e=!0,Pr(t)):e=!1,Ka(t,a),su(t,n,s),Jo(t,n,s,a),ts(null,t,n,!0,e,a);case 19:return Cu(e,t,a);case 22:return bu(e,t,a)}throw Error(o(156,t.tag))};function Qu(e,t){return Al(e,t)}function _h(e,t,a,n){this.tag=e,this.key=a,this.sibling=this.child=this.return=this.stateNode=this.type=this.elementType=null,this.index=0,this.ref=null,this.pendingProps=t,this.dependencies=this.memoizedState=this.updateQueue=this.memoizedProps=null,this.mode=n,this.subtreeFlags=this.flags=0,this.deletions=null,this.childLanes=this.lanes=0,this.alternate=null}function lt(e,t,a,n){return new _h(e,t,a,n)}function ks(e){return e=e.prototype,!(!e||!e.isReactComponent)}function Vh(e){if(typeof e=="function")return ks(e)?1:0;if(e!=null){if(e=e.$$typeof,e===wt)return 11;if(e===vt)return 14}return 2}function na(e,t){var a=e.alternate;return a===null?(a=lt(e.tag,t,e.key,e.mode),a.elementType=e.elementType,a.type=e.type,a.stateNode=e.stateNode,a.alternate=e,e.alternate=a):(a.pendingProps=t,a.type=e.type,a.flags=0,a.subtreeFlags=0,a.deletions=null),a.flags=e.flags&14680064,a.childLanes=e.childLanes,a.lanes=e.lanes,a.child=e.child,a.memoizedProps=e.memoizedProps,a.memoizedState=e.memoizedState,a.updateQueue=e.updateQueue,t=e.dependencies,a.dependencies=t===null?null:{lanes:t.lanes,firstContext:t.firstContext},a.sibling=e.sibling,a.index=e.index,a.ref=e.ref,a}function tn(e,t,a,n,s,l){var d=2;if(n=e,typeof e=="function")ks(e)&&(d=1);else if(typeof e=="string")d=5;else e:switch(e){case We:return va(a.children,s,l,t);case at:d=8,s|=8;break;case _t:return e=lt(12,a,t,s|2),e.elementType=_t,e.lanes=l,e;case Qe:return e=lt(13,a,t,s),e.elementType=Qe,e.lanes=l,e;case pt:return e=lt(19,a,t,s),e.elementType=pt,e.lanes=l,e;case fe:return an(a,s,l,t);default:if(typeof e=="object"&&e!==null)switch(e.$$typeof){case Et:d=10;break e;case ua:d=9;break e;case wt:d=11;break e;case vt:d=14;break e;case _e:d=16,n=null;break e}throw Error(o(130,e==null?e:typeof e,""))}return t=lt(d,a,t,s),t.elementType=e,t.type=n,t.lanes=l,t}function va(e,t,a,n){return e=lt(7,e,n,t),e.lanes=a,e}function an(e,t,a,n){return e=lt(22,e,n,t),e.elementType=fe,e.lanes=a,e.stateNode={isHidden:!1},e}function ws(e,t,a){return e=lt(6,e,null,t),e.lanes=a,e}function vs(e,t,a){return t=lt(4,e.children!==null?e.children:[],e.key,t),t.lanes=a,t.stateNode={containerInfo:e.containerInfo,pendingChildren:null,implementation:e.implementation},t}function zh(e,t,a,n,s){this.tag=t,this.containerInfo=e,this.finishedWork=this.pingCache=this.current=this.pendingChildren=null,this.timeoutHandle=-1,this.callbackNode=this.pendingContext=this.context=null,this.callbackPriority=0,this.eventTimes=Yn(0),this.expirationTimes=Yn(-1),this.entangledLanes=this.finishedLanes=this.mutableReadLanes=this.expiredLanes=this.pingedLanes=this.suspendedLanes=this.pendingLanes=0,this.entanglements=Yn(0),this.identifierPrefix=n,this.onRecoverableError=s,this.mutableSourceEagerHydrationData=null}function Cs(e,t,a,n,s,l,d,f,h){return e=new zh(e,t,a,f,h),t===1?(t=1,l===!0&&(t|=8)):t=0,l=lt(3,null,null,t),e.current=l,l.stateNode=e,l.memoizedState={element:n,isDehydrated:a,cache:null,transitions:null,pendingSuspenseBoundaries:null},No(l),e}function jh(e,t,a){var n=3<arguments.length&&arguments[3]!==void 0?arguments[3]:null;return{$$typeof:Ie,key:n==null?null:""+n,children:e,containerInfo:t,implementation:a}}function Yu(e){if(!e)return $t;e=e._reactInternals;e:{if(da(e)!==e||e.tag!==1)throw Error(o(170));var t=e;do{switch(t.tag){case 3:t=t.stateNode.context;break e;case 1:if(ze(t.type)){t=t.stateNode.__reactInternalMemoizedMergedChildContext;break e}}t=t.return}while(t!==null);throw Error(o(171))}if(e.tag===1){var a=e.type;if(ze(a))return vc(e,a,t)}return t}function $u(e,t,a,n,s,l,d,f,h){return e=Cs(a,n,!0,e,s,l,d,f,h),e.context=Yu(null),a=e.current,n=Oe(),s=ia(a),l=Nt(n,s),l.callback=t??null,Zt(a,l,s),e.current.lanes=s,fi(e,s,n),Ge(e,n),e}function rn(e,t,a,n){var s=t.current,l=Oe(),d=ia(s);return a=Yu(a),t.context===null?t.context=a:t.pendingContext=a,t=Nt(l,d),t.payload={element:e},n=n===void 0?null:n,n!==null&&(t.callback=n),e=Zt(s,t,d),e!==null&&(St(e,s,d,l),xr(e,s,d)),d}function nn(e){if(e=e.current,!e.child)return null;switch(e.child.tag){case 5:return e.child.stateNode;default:return e.child.stateNode}}function Ju(e,t){if(e=e.memoizedState,e!==null&&e.dehydrated!==null){var a=e.retryLane;e.retryLane=a!==0&&a<t?a:t}}function Ds(e,t){Ju(e,t),(e=e.alternate)&&Ju(e,t)}function qh(){return null}var Xu=typeof reportError=="function"?reportError:function(e){console.error(e)};function Ps(e){this._internalRoot=e}on.prototype.render=Ps.prototype.render=function(e){var t=this._internalRoot;if(t===null)throw Error(o(409));rn(e,t,null,null)},on.prototype.unmount=Ps.prototype.unmount=function(){var e=this._internalRoot;if(e!==null){this._internalRoot=null;var t=e.containerInfo;Ta(function(){rn(null,e,null,null)}),t[Mt]=null}};function on(e){this._internalRoot=e}on.prototype.unstable_scheduleHydration=function(e){if(e){var t=Ol();e={blockedOn:null,target:e,priority:t};for(var a=0;a<qt.length&&t!==0&&t<qt[a].priority;a++);qt.splice(a,0,e),a===0&&Bl(e)}};function As(e){return!(!e||e.nodeType!==1&&e.nodeType!==9&&e.nodeType!==11)}function sn(e){return!(!e||e.nodeType!==1&&e.nodeType!==9&&e.nodeType!==11&&(e.nodeType!==8||e.nodeValue!==" react-mount-point-unstable "))}function Zu(){}function Gh(e,t,a,n,s){if(s){if(typeof n=="function"){var l=n;n=function(){var k=nn(d);l.call(k)}}var d=$u(t,n,e,0,null,!1,!1,"",Zu);return e._reactRootContainer=d,e[Mt]=d.current,Ai(e.nodeType===8?e.parentNode:e),Ta(),d}for(;s=e.lastChild;)e.removeChild(s);if(typeof n=="function"){var f=n;n=function(){var k=nn(h);f.call(k)}}var h=Cs(e,0,!1,null,null,!1,!1,"",Zu);return e._reactRootContainer=h,e[Mt]=h.current,Ai(e.nodeType===8?e.parentNode:e),Ta(function(){rn(t,h,a,n)}),h}function ln(e,t,a,n,s){var l=a._reactRootContainer;if(l){var d=l;if(typeof s=="function"){var f=s;s=function(){var h=nn(d);f.call(h)}}rn(t,d,e,s)}else d=Gh(a,t,e,s,n);return nn(d)}Il=function(e){switch(e.tag){case 3:var t=e.stateNode;if(t.current.memoizedState.isDehydrated){var a=pi(t.pendingLanes);a!==0&&($n(t,a|1),Ge(t,me()),(Y&6)===0&&(Xa=me()+500,Jt()))}break;case 13:Ta(function(){var n=Ht(e,1);if(n!==null){var s=Oe();St(n,e,1,s)}}),Ds(e,1)}},Jn=function(e){if(e.tag===13){var t=Ht(e,134217728);if(t!==null){var a=Oe();St(t,e,134217728,a)}Ds(e,134217728)}},xl=function(e){if(e.tag===13){var t=ia(e),a=Ht(e,t);if(a!==null){var n=Oe();St(a,e,t,n)}Ds(e,t)}},Ol=function(){return ae},Hl=function(e,t){var a=ae;try{return ae=e,t()}finally{ae=a}},zn=function(e,t,a){switch(t){case"input":if(On(e,a),t=a.name,a.type==="radio"&&t!=null){for(a=e;a.parentNode;)a=a.parentNode;for(a=a.querySelectorAll("input[name="+JSON.stringify(""+t)+'][type="radio"]'),t=0;t<a.length;t++){var n=a[t];if(n!==e&&n.form===e.form){var s=Cr(n);if(!s)throw Error(o(90));ol(n),On(n,s)}}}break;case"textarea":dl(e,a);break;case"select":t=a.value,t!=null&&Ra(e,!!a.multiple,t,!1)}},Tl=ys,kl=Ta;var Kh={usingClientEntryPoint:!1,Events:[Fi,Ua,Cr,yl,Sl,ys]},ji={findFiberByHostInstance:pa,bundleType:0,version:"18.3.1",rendererPackageName:"react-dom"},Qh={bundleType:ji.bundleType,version:ji.version,rendererPackageName:ji.rendererPackageName,rendererConfig:ji.rendererConfig,overrideHookState:null,overrideHookStateDeletePath:null,overrideHookStateRenamePath:null,overrideProps:null,overridePropsDeletePath:null,overridePropsRenamePath:null,setErrorHandler:null,setSuspenseHandler:null,scheduleUpdate:null,currentDispatcherRef:Ae.ReactCurrentDispatcher,findHostInstanceByFiber:function(e){return e=Dl(e),e===null?null:e.stateNode},findFiberByHostInstance:ji.findFiberByHostInstance||qh,findHostInstancesForRefresh:null,scheduleRefresh:null,scheduleRoot:null,setRefreshHandler:null,getCurrentFiber:null,reconcilerVersion:"18.3.1-next-f1338f8080-20240426"};if(typeof __REACT_DEVTOOLS_GLOBAL_HOOK__<"u"){var cn=__REACT_DEVTOOLS_GLOBAL_HOOK__;if(!cn.isDisabled&&cn.supportsFiber)try{nr=cn.inject(Qh),Ct=cn}catch{}}return Ke.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED=Kh,Ke.createPortal=function(e,t){var a=2<arguments.length&&arguments[2]!==void 0?arguments[2]:null;if(!As(t))throw Error(o(200));return jh(e,t,null,a)},Ke.createRoot=function(e,t){if(!As(e))throw Error(o(299));var a=!1,n="",s=Xu;return t!=null&&(t.unstable_strictMode===!0&&(a=!0),t.identifierPrefix!==void 0&&(n=t.identifierPrefix),t.onRecoverableError!==void 0&&(s=t.onRecoverableError)),t=Cs(e,1,!1,null,null,a,!1,n,s),e[Mt]=t.current,Ai(e.nodeType===8?e.parentNode:e),new Ps(t)},Ke.findDOMNode=function(e){if(e==null)return null;if(e.nodeType===1)return e;var t=e._reactInternals;if(t===void 0)throw typeof e.render=="function"?Error(o(188)):(e=Object.keys(e).join(","),Error(o(268,e)));return e=Dl(t),e=e===null?null:e.stateNode,e},Ke.flushSync=function(e){return Ta(e)},Ke.hydrate=function(e,t,a){if(!sn(t))throw Error(o(200));return ln(null,e,t,!0,a)},Ke.hydrateRoot=function(e,t,a){if(!As(e))throw Error(o(405));var n=a!=null&&a.hydratedSources||null,s=!1,l="",d=Xu;if(a!=null&&(a.unstable_strictMode===!0&&(s=!0),a.identifierPrefix!==void 0&&(l=a.identifierPrefix),a.onRecoverableError!==void 0&&(d=a.onRecoverableError)),t=$u(t,null,e,1,a??null,s,!1,l,d),e[Mt]=t.current,Ai(e),n)for(e=0;e<n.length;e++)a=n[e],s=a._getVersion,s=s(a._source),t.mutableSourceEagerHydrationData==null?t.mutableSourceEagerHydrationData=[a,s]:t.mutableSourceEagerHydrationData.push(a,s);return new on(t)},Ke.render=function(e,t,a){if(!sn(t))throw Error(o(200));return ln(null,e,t,!1,a)},Ke.unmountComponentAtNode=function(e){if(!sn(e))throw Error(o(40));return e._reactRootContainer?(Ta(function(){ln(null,null,e,!1,function(){e._reactRootContainer=null,e[Mt]=null})}),!0):!1},Ke.unstable_batchedUpdates=ys,Ke.unstable_renderSubtreeIntoContainer=function(e,t,a,n){if(!sn(a))throw Error(o(200));if(e==null||e._reactInternals===void 0)throw Error(o(38));return ln(e,t,a,!1,n)},Ke.version="18.3.1-next-f1338f8080-20240426",Ke}var sd;function nm(){if(sd)return Fs.exports;sd=1;function i(){if(!(typeof __REACT_DEVTOOLS_GLOBAL_HOOK__>"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(i)}catch(r){console.error(r)}}return i(),Fs.exports=rm(),Fs.exports}var ld;function om(){if(ld)return un;ld=1;var i=nm();return un.createRoot=i.createRoot,un.hydrateRoot=i.hydrateRoot,un}var sm=om();const lm=Vd(sm),cm="modulepreload",um=function(i){return"/"+i},cd={},Wt=function(r,o,c){let u=Promise.resolve();if(o&&o.length>0){let y=function(O){return Promise.all(O.map(E=>Promise.resolve(E).then(W=>({status:"fulfilled",value:W}),W=>({status:"rejected",reason:W}))))};document.getElementsByTagName("link");const S=document.querySelector("meta[property=csp-nonce]"),A=(S==null?void 0:S.nonce)||(S==null?void 0:S.getAttribute("nonce"));u=y(o.map(O=>{if(O=um(O),O in cd)return;cd[O]=!0;const E=O.endsWith(".css"),W=E?'[rel="stylesheet"]':"";if(document.querySelector(`link[href="${O}"]${W}`))return;const j=document.createElement("link");if(j.rel=E?"stylesheet":cm,E||(j.as="script"),j.crossOrigin="",j.href=O,A&&j.setAttribute("nonce",A),document.head.appendChild(j),E)return new Promise((ye,ie)=>{j.addEventListener("load",ye),j.addEventListener("error",()=>ie(new Error(`Unable to preload CSS for ${O}`)))})}))}function p(y){const S=new Event("vite:preloadError",{cancelable:!0});if(S.payload=y,window.dispatchEvent(S),!S.defaultPrevented)throw y}return u.then(y=>{for(const S of y||[])S.status==="rejected"&&p(S.reason);return r().catch(p)})};var He=Qs();const dm=Vd(He),Xy=Xh({__proto__:null,default:dm},[He]),pm={common:{appName:"CodingNS",loading:"Loading...",retry:"Retry",back:"Back",save:"Save",connectionRouteRelay:"CodingNS Connect",connectionRouteLan:"LAN Direct",connectionRouteLoopback:"Local Direct",connectionRouteTailscale:"Tailscale Direct",connectionRouteDirect:"Direct Connection",logout:"Log out",unknown:"Unknown session",close:"Close",cancel:"Cancel",language:"Language"},auth:{loginTitle:"Resume your coding session",loginSubtitle:"INITIALIZING DEVELOPMENT ENVIRONMENT...",serverPreset:"Server Preset",serverCustomOption:"Use custom server",serverAddress:"Server Address",serverPlaceholder:"For example: http://127.0.0.1:3002",serverHint:"Login, realtime messages, and terminals all connect through this host. Point the client at the Host API endpoint such as http://127.0.0.1:3002; frontend dev ports like 4174 or 5173 are not meant for packaged clients and only work for temporary debugging when proxying and CORS are configured correctly.",serverInvalid:"Invalid server address. Check it and try again.",serverDiscoveredTag:"Auto-discovered",serverCurrent:"Current Server",bootstrapTitle:"Complete the first-time bootstrap",bootstrapSubtitle:"This Host does not have an admin account yet. Create the minimal login entry first.",username:"Username",password:"Password",rememberPassword:"Remember Password",confirmPassword:"Confirm Password",submitLogin:"Enter Workspace",submitBootstrap:"Create Admin Account",bootstrapSuccess:"Bootstrap completed. You can log in now.",bootstrapMismatch:"The two passwords do not match.",authUnavailable:"Host is unreachable right now. Check the server and try again.",logoutSuccess:"The current login state has been cleared.",demoBanner:"Demo environment — all account data is public and cleared on logout",demoSessionExpired:"Demo session expired. Please log in again.",captcha:"Captcha",captchaPlaceholder:"Enter the characters in the image",captchaHint:"After three failed attempts, complete the captcha before trying again.",captchaImageAlt:"Login captcha image",serverSettings:"Server Settings",serverSettingsTitle:"Server Configuration",saveServerSettings:"Save Settings",relayEntryTitle:"Connecting To Remote Host",relayEntryDescription:"Switching to this Host's trusted remote entry. You will be returned to the login page automatically.",relayEntryInvalid:"The remote access entry parameters are incomplete. Open the access URL again.",trustedEntryOnlyTitle:"Open This Through Your Remote Access URL",trustedEntryOnlyDescription:"This trusted frontend only loads the connection UI. It is not the Host API entry itself. Open the device's remote access URL again.",trustedEntryOnlyHintTitle:"How to enter",trustedEntryOnlyHint:"Use a remote access URL like https://xxxx.channel.codingns.com:1443. The tunnel domain will redirect you to the correct trusted entry automatically."},plugins:{listTitle:"Plugins",listDescription:"Review the plugins available to this workspace and decide whether to open or disable them.",loading:"Loading plugins...",listLoadFailed:"Failed to load the plugin list.",emptyTitle:"No plugins are available yet",emptyDescription:"Valid plugins will appear here automatically after Host scans them.",enabled:"Enabled",disabled:"Disabled",frontendTag:"Frontend",backendTag:"Action",detailLoadFailed:"Failed to load the plugin details.",detailMissingTitle:"This plugin could not be found",detailMissingDescription:"The plugin directory may have been removed, or Host has not scanned it again yet.",backToList:"Back to plugins",backToDetail:"Back to details",summaryTitle:"Summary",summaryDescription:"Confirm what this plugin is, where it is installed, and whether it is usable.",pluginIdLabel:"Plugin ID",installRootLabel:"Install directory",runtimeLabel:"Runtime",frontendOnly:"Frontend only, without backend actions",permissionTitle:"Permissions",permissionDescription:"Only explicitly declared permissions are listed here. Anything undeclared stays blocked by default.",workspaceReadAllowed:"Can read the current workspace",workspaceReadDenied:"Workspace read is not declared",networkAllowed:"Network access allowed",networkDenied:"Network access blocked by default",noDesktopPermission:"No desktop permission",actionTitle:"Available actions",actionDescription:"Every action goes through the unified plugin gateway instead of private command entry points.",runHistoryTitle:"Recent runs",runHistoryDescription:"Show the latest 10 runs first so it is easy to see whether actions actually ran.",runHistoryEmptyTitle:"No runs yet",runHistoryEmptyDescription:"A formal run record will appear here after the first action execution.",unknownAction:"Unknown action",openPlugin:"Open plugin",enableAction:"Enable plugin",disableAction:"Disable plugin",permissionNameReadFile:"Read files",permissionNameListDirectory:"List directory contents",permissionNameWriteFile:"Write files",permissionNameOpenFile:"Open files on desktop",permissionNameRevealInFileManager:"Reveal files in the file manager",permissionScopeWorkspace:"The whole current workspace",permissionScopeDirectory:"Directory: {scopePath}",permissionScopeFile:"File: {scopePath}",permissionScopeUnknown:"The target scope is not clear yet",permissionGrantModeOnce:"This time only",permissionGrantModeSession:"While this page stays open",permissionGrantModePersistent:"Keep it long term",permissionPromptTitle:"This plugin needs your approval first",permissionPromptDescription:"Review what it wants to do, then decide how long and how far the permission should go.",permissionPromptSummaryTitle:"What this request is asking for",permissionPromptSummaryDescription:"{pluginName} asked for a controlled capability. Nothing continues until you approve it.",permissionPromptPermissionLabel:"Requested capability",permissionPromptTargetLabel:"Applies to",permissionPromptPendingTag:"Waiting for you",permissionPromptOptionsTitle:"How you can allow it",permissionPromptOptionsDescription:"Start with the smallest scope instead of opening too much by default.",permissionPromptOptionOnce:"Allow only this target once",permissionPromptOptionOnceDescription:"Only continue this request. The plugin must ask again next time.",permissionPromptOptionSession:"Allow for this open session",permissionPromptOptionSessionDescription:"Keep it only while this plugin page stays open, then expire it automatically.",permissionPromptOptionDirectory:"Allow this directory long term",permissionPromptOptionDirectoryDescription:"Future access to {scopePath} and its children will not ask again each time.",permissionPromptDenyAction:"Not now",permissionPromptNoOptionTitle:"No valid approval choice is available",permissionPromptNoOptionDescription:"This request does not provide a safe scope yet. Go back to the plugin details first.",grantedPermissionTitle:"Permissions already allowed in this workspace",grantedPermissionDescription:"This shows only what has already been allowed for the current workspace, so you can pull it back at any time.",grantedPermissionEmptyTitle:"No permission has been granted yet",grantedPermissionEmptyDescription:"A formal grant record appears here after the plugin asks for access and you approve it.",permissionGrantLoading:"Loading permission grants...",permissionGrantLoadFailed:"Failed to load plugin permission grants.",revokeGrantAction:"Revoke",revokeGrantSuccess:"The plugin permission was revoked.",revokeGrantFailed:"Failed to revoke the plugin permission.",permissionAuditTitle:"Recent permission activity",permissionAuditDescription:"Grant, deny, and revoke records stay here so you can trace who opened what later.",permissionAuditEmptyTitle:"No permission activity yet",permissionAuditEmptyDescription:"Grant, deny, or revoke activity will appear here automatically.",permissionEventGranted:"Granted: {permission}",permissionEventRevoked:"Revoked: {permission}",permissionEventDenied:"Denied: {permission}",permissionEventUnknown:"Unknown permission",permissionEventReasonDeclarationMissing:"Denied because the plugin never declared it",permissionEventReasonGrantRequired:"Needs your approval first",enableSuccess:"Plugin enabled.",disableSuccess:"Plugin disabled.",saveFailed:"Failed to save the plugin state.",disabledByUserReason:"Disabled by the user from the plugin detail page",containerDescription:"The plugin frontend runs in an isolated container and does not receive the host desktop bridge directly.",containerLoadFailed:"Failed to load the plugin runtime page.",containerMissingTitle:"This plugin has no runnable page",containerMissingDescription:"This plugin may be backend-only or already disabled."},settings:{title:"Settings",appearance:"Appearance",appearanceSectionSummary:"Language, theme, and interface colors",language:"Language",languageDescription:"Choose the display language used by the interface.",theme:"Theme",themeDescription:"Choose the color theme that fits the way you work.",autoTheme:"Follow system theme automatically",autoThemeDescription:"When enabled, switch between day and night mode based on the system or browser color scheme.",fileManager:"File Manager",workspaceSessionSortMode:"Workspace session sort order",teableEntryTitle:"Teable Forms",teableEntryDescription:"Manage the Teable connection and how CodingNS data syncs into Teable tables.",teableOpenSettingsAction:"Open settings",teableModalTitle:"Teable form settings",teableModalDescription:"Manage the Teable connection, synced tables, and field mappings between CodingNS data and Teable tables.",teableTabConnection:"Connection",teableTabForms:"Forms",teableTabMirrors:"Mirrors",teableTabFieldMappings:"Field mappings",teableTabConnectionSettings:"Connection settings",teableTabFormSettings:"Form settings",teableTabTableSyncSettings:"Table sync settings",teableTabSyncLogs:"Sync logs",teableTestConnectionAction:"Test connection",teableConnectionTestSuccess:"Connection works. Read {tableCount} tables.",teableLoadFailed:"Failed to load Teable settings.",teableStatusUnknown:"Status unavailable",teableStatusIdleHint:"No mirror sync has been triggered yet.",teableStatusBindingLabel:"Connection",teableStatusSourceLabel:"Enabled sources",teableStatusSourceDetail:"{count} source types are currently enabled for Teable sync.",teableStatusMirrorLabel:"Mirror tables",teableStatusMirrorDetail:"{count} mirror table bindings are currently recorded.",teableStatusTaskLabel:"Latest sync",teableBindingSectionTitle:"Connection settings",teableBindingSectionDescription:"Fill in the Teable site, space, base, and access token first, then decide whether to enable sync.",teableEnabledLabel:"Enable Teable sync",teableBaseUrlLabel:"Teable site URL",teableBaseUrlDescription:"Both http:// and https:// are supported. Use a plain http address when Teable is on the same LAN as Host.",teableBaseUrlPlaceholder:"For example: http://192.168.1.20:3000",teableSpaceIdLabel:"Space ID",teableSpaceIdPlaceholder:"Enter the target Space ID",teableBaseIdLabel:"Base ID",teableBaseIdPlaceholder:"Enter the target Base ID",teableAuthRefLabel:"Auth reference",teableAuthRefPlaceholder:"For example: secret://teable/main",teableAuthTokenLabel:"Access token",teableAuthTokenDescription:"Leave this blank if the Host already has a saved token you want to keep using.",teableAuthTokenPlaceholder:"Leave blank to keep the saved token",teableMirrorModeLabel:"Sync mode",teableBindingSaved:"Teable connection settings saved.",teableSyncConfigSectionTitle:"Workbench push scope",teableSyncConfigSectionDescription:"Choose which tags, sessions, and todos are pushed to Teable, and which table each type should use.",teableSyncEnabledLabel:"Allow syncing this source type",teableTargetTableLabel:"Target table",teableTargetTablePlaceholder:"Choose an existing Teable table",teableTagRootsLabel:"Tag trees to sync",teableSessionScopeModeLabel:"Session sync scope",teableSessionScopeAll:"Sync sessions from every workspace",teableSessionScopeSelected:"Sync sessions only from selected workspaces",teableWorkspaceMultiSelectLabel:"Choose workspaces",teableTodoSourceLabel:"Todo sources",teableTodoWorkspaceSource:"Sync workspace todos",teableTodoAffairsSource:"Sync affairs todos",teableTodoWorkspaceHint:"If you choose workspaces here, only todos from those workspaces are included. Leave it empty to avoid extra workspace filtering.",teableTargetTableIdLabel:"Target table ID",teableTargetTableHint:"Leave this blank and Host will create the default mirror table automatically.",teableTargetTableBoundHint:'Currently bound to table "{table}".',teableTargetTableIdPlaceholder:"Optional: reuse an existing table ID",teableScopeJsonLabel:"Sync scope (JSON)",teableScopeJsonPlaceholder:"Enter the sync scope JSON for this source type.",teableScopeJsonInvalid:"The sync scope must be a valid JSON object.",teableSyncConfigSaved:"Teable push scope saved.",teableFormsCatalogTitle:"Existing Teable forms",teableFormsCatalogDescription:"This list shows the form views that already exist in Teable.",teableFormsCatalogEmptyTitle:"No forms are available yet",teableFormsCatalogEmptyDescription:"Create at least one form view in Teable first.",teableFormSettingsLeftTitle:"Legacy form settings",teableFormSettingsLeftDescription:"The settings page no longer configures mirror sync by forms. Mirror sync is configured by Teable tables.",teableFormMappingPanelTitle:"Legacy sync content settings",teableFormMappingPanelDescription:"The settings page no longer configures mirror sync by forms. Mirror sync is configured by Teable tables.",teableAddSyncFormAction:"Add sync form",teableRemoveSyncFormAction:"Remove",teableSyncFormAddedTag:"Added",teableSyncFormAdded:"Sync form added.",teableSyncFormRemoved:"Sync form removed.",teableFormShareReady:"Sharing enabled",teableFormShareMissing:"Sharing disabled",teableSelectSyncFormTitle:"Select a form first",teableSelectSyncFormDescription:"After you select a Teable form on the left, sync content, workspace scope, and field mappings appear here.",teableSelectedFormLabel:"Selected form",teableSyncSourceLabel:"Information to sync",teableSyncSource:{sessions:"Session records",todos:"Todos",tags:"Document library tags"},teableWorkspaceScopeLabel:"Workspace scope",teableWorkspaceScopeAll:"All workspaces",teableWorkspaceScopeSelected:"Selected workspaces",teableWorkspaceScopeEmpty:"No workspace is available yet.",teableDocumentTagRootsLabel:"Document library root tags",teableDocumentTagRootsDescription:"Only the selected root tags and all child tags are synced. This is not a workspace-form binding.",teableDocumentTagRootsEmpty:"No document library root tag is available yet.",teableFieldMappingTitle:"Field mapping",teableFieldMappingInlineDescription:"CodingNS fields are on the left. Choose target fields from the Teable table on the right.",teableSourceFieldsEmpty:"This sync content has no mappable fields.",teableSaveFormSyncSettingsAction:"Save table sync settings",teableFormSyncSettingsSaved:"Table sync settings saved.",teableTableSyncAvailableTitle:"Teable table catalog",teableTableSyncAvailableDescription:"This does not list forms. Choose an existing table from the current Base, then add it to the sync table list on the left.",teableTableSyncListTitle:"Synced tables",teableTableSyncListDescription:"Tables added as mirror sync targets appear here. Select one table, then configure content, scope, and field mappings on the right.",teableTableSyncConfigTitle:"Current table settings",teableTableSyncConfigDescription:"Only the selected table from the left is configured here. The sync table list is not duplicated on this side.",teableTableToAddLabel:"Table to add",teableAllTablesAdded:"All tables have been added",teableAddSyncTableAction:"Add sync table",teableRemoveSyncTableAction:"Remove",teableSyncTableAddedTag:"Added",teableSelectSyncTableTitle:"Add a sync table first",teableSelectSyncTableDescription:"After you add a table from the Teable table catalog on the left, sync content, workspace scope, and field mappings appear here.",teableSelectedSyncTableLabel:"Current sync table",teableTableAssignedDescription:"Configured to sync {source}",teableTableUnassignedDescription:"No sync content configured yet",teableSaveTableSyncSettingsAction:"Save table sync settings",teableTableSyncSettingsSaved:"Table sync settings saved.",teableFieldAutoCreateAction:"Add fields and auto-map",teableFieldAutoCreateModalTitle:"Add Teable fields",teableFieldAutoCreateModalDescription:"Choose CodingNS fields to add to the current Teable table.",teableFieldAutoCreateModalSectionTitle:"Choose fields",teableFieldAutoCreateModalSectionDescription:'These fields will be added to "{table}" and mapped automatically. Existing fields with the same name are reused.',teableFieldAutoCreateConfirmAction:"Add and auto-map",teableFieldAutoCreateSuccess:"Added and mapped {count} fields.",teableFieldAutoCreateEmptyError:"Choose at least one field to add.",teableFieldAlreadyMappedDescription:'Mapped to "{field}".',teableTablesCatalogTitle:"Existing Teable tables",teableTablesCatalogDescription:"This list shows the tables in the current Base so you can choose sync targets and field mappings by table.",teableTablesCatalogEmptyTitle:"No table is available in the current Base",teableTablesCatalogEmptyDescription:"Create a table in Teable first, then come back to configure sync.",teableTableInspectAction:"Inspect table",teableTableCollapseAction:"Collapse details",teableTableFieldsLabel:"Fields in this table",teableTableFieldsEmpty:"This table has no field yet.",teableTableFormViewsLabel:"Form views under this table",teableTableFormViewsEmpty:"This table does not have a form view yet.",teableTableFormReadyTag:"Ready for workbench",teableTableFormShareMissingTag:"Share disabled",teableTableFormCountTag:"{count} forms",teableTableFieldCountPending:"Field count pending",teableTableFieldCountValue:"{count} fields",teableTableFormCountValue:"{count} form views",teableTablesUsageTitle:"What this page is for",teableTablesUsageDescription:"Settings are for sync and field mapping. The Teable block on the workbench is where you choose which form to display.",teableTablesUsageMirrorTitle:"Sync configuration uses tables",teableTablesUsageMirrorDescription:"Tags, sessions, and todos are mapped to Teable tables here.",teableTablesUsageFormTitle:"Workbench blocks use forms",teableTablesUsageFormDescription:"Actual user-facing forms are chosen inside the Teable block on the workbench.",teableSyncActionSectionTitle:"Sync status and actions",teableSyncActionSectionDescription:"Review the latest task result here, or trigger mirror sync manually.",teableLatestTaskTitle:"Latest mirror sync",teableLatestTaskEmpty:"There is no mirror sync record yet.",teableSyncLogsTitle:"Sync logs",teableSyncLogsDescription:"Manual syncs and local-change sync tasks are recorded here so you can confirm whether data has been pushed to Teable.",teableSyncLogsRefreshAction:"Refresh logs",teableSyncLogsEmptyTitle:"No sync log yet",teableSyncLogsEmptyDescription:"Logs will appear here after a manual sync or a local data change triggers sync.",teableSyncLogDescription:"{trigger} · {source} · {time}",teableSyncLogCounts:"Created {created}, updated {updated}, deleted {deleted}, skipped {skipped}",teableSyncLogTrigger:{manual:"Manual",local_change:"Local change",retry:"Retry"},teableFieldMappingSectionTitle:"Field mappings",teableFieldMappingSectionDescription:"Map CodingNS source fields to Teable target fields manually. Sync only writes using the mapping defined here.",teableFieldMappingTargetMissingTitle:"Choose a target table first",teableFieldMappingTargetMissingDescription:"Go to the Mirrors tab, assign a target table for this source type, then come back and map its fields.",teableFieldMappingSaveAction:"Save field mappings",teableFieldMappingSaved:"Field mappings saved.",teableFieldTargetPlaceholder:"Choose a target field",teableFieldRequired:"Required",teableFieldOptional:"Optional",teableMirrorBindingReady:'The mirror table is already bound to "{table}".',teableMirrorBindingMissing:"This source type has not created a mirror table yet.",teableMirrorBindingReadyTag:"Bound",teableMirrorBindingPendingTag:"Pending",teableRefreshAction:"Refresh status",teableSaveBindingAction:"Save connection",teableSaveSyncConfigAction:"Save push scope",teableSyncNowAction:"Sync now",teableBindingStatus:{unbound:"Not bound",ready:"Ready",disabled:"Disabled",config_invalid:"Incomplete"},teableTaskState:{idle:"Not started",queued:"Queued",running:"Running",succeeded:"Succeeded",partial_failed:"Partial failure",failed:"Failed"},teableMirrorMode:{manual:"Manual trigger",scheduled:"Scheduled sync (not available yet)",event_driven:"Auto-sync on local changes"},teableSource:{tags:{title:"Tag mirror",description:"Sync affair tags into a Teable mirror table so business forms can use Link and Lookup.",scopeHint:"Examples include includePaths or manually selected paths. This round only stores the config."},sessions:{title:"Session mirror",description:"Sync lightweight session summaries into Teable so forms can reference recent context.",scopeHint:"Examples include recent and limit. This round only stores the config."},todos:{title:"Todo mirror",description:"Sync workbench todos into Teable so forms can reference current tasks directly.",scopeHint:"Examples include open_only or status filters. This round only stores the config."}},pluginManagement:"Plugin management",pluginManagementDescription:"Review the plugins Host has scanned, then decide whether to enable, disable, or open them.",pluginManagementAction:"Manage plugins",pluginManagementModalTitle:"Plugin management",pluginManagementModalDescription:"See plugin status, permission boundaries, and recent runs here without manually building plugin URLs.",pluginManagementModalListTitle:"Plugin list",pluginManagementModalListDescription:"Select a plugin first, then review its current status and recent runs.",pluginManagementModalDetailTitle:"Plugin details",pluginManagementModalDetailDescription:"Only officially registered Host plugin data and runs are shown here.",pluginManagementSelectPluginTitle:"Select a plugin first",pluginManagementSelectPluginDescription:"After you pick a plugin on the left, its permissions, actions, and recent runs appear here.",pluginManagementWorkspaceRequired:"A current workspace is required before opening a plugin frontend page.",workspaceSessionSortModeDescription:"Controls the default sort order for session lists across the workspace. This setting only applies to the current device.",sessionSortModeCreatedAt:"By session created time",sessionSortModeUpdatedAt:"By session updated time",sessionSortModeTitle:"By session name",showSystemFiles:"Show system files",showSystemFilesDescription:"Display common macOS and Windows system files in the file manager, such as .DS_Store and Thumbs.db. This setting only applies to the current device.",serverConnection:"Server Connection",serverConnectionSectionSummary:"Server address and reconnection behavior",remoteAccess:"Remote Access",remoteAccessSectionSummary:"Connect to this Host from outside through CodingNS Connect or Tailscale.",remoteAccessNavValue:"CodingNS Connect / Tailscale",remoteAccessManageTitle:"Remote Access",remoteAccessManageDescription:"Choose and configure how external devices connect to this Host.",remoteAccessManageAction:"Manage Remote Access",remoteAccessModalTitle:"Access Method Management",remoteAccessModalDescription:"Choose and configure the remote access method you want to use.",remoteAccessTabsLabel:"Remote access method tabs",remoteAccessTunnelTab:"CodingNS Connect",remoteAccessTailscaleTab:"Tailscale Access",remoteAccessFeatureDisabledValue:"Off",abilityManagement:"Capability Management",abilityManagementSectionSummary:"Manage the document library, CLI provider availability, and model profile presets from one place.",abilityManagementNavValue:"Library / Providers / Profiles",affairsLibraryCapabilityTitle:"Document library",affairsLibraryCapabilityDescription:"This switch controls the left document entry and the document or tag indexing services.",affairsLibraryCapabilityToggleLabel:"Enable document library",affairsLibraryCapabilityLoading:"Updating document library status...",affairsLibraryCapabilityEnableSuccess:"Document library enabled.",affairsLibraryCapabilityDisableSuccess:"Document library disabled.",affairsLibraryCapabilityLoadFailed:"Failed to load document library status.",affairsLibraryCapabilitySaveFailed:"Failed to save document library status.",modelManagement:"Model Management",modelManagementNavValue:"Quick switch",modelManagementSectionTitle:"Model Profile Management",providerManagement:"CLI Providers",providerManagementSectionSummary:"Control which CLIs appear in session, fork, assistant, and Skill entry points.",providerManagementNavValue:"Availability",providerManagementDescription:"Control which CLIs this Host is allowed to expose. Open the dialog to review the matrix, status, and enable switches.",providerManagementManageAction:"Manage CLI Providers",providerManagementModalTitle:"CLI Provider Management",providerManagementModalDescription:"Review what each CLI can do in the product, its current state, and whether it stays visible.",providerManagementRefresh:"Refresh list",providerManagementRefreshSuccess:"CLI provider list refreshed.",providerManagementLoading:"Loading available CLI providers...",providerManagementEmpty:"No CLI providers are available to manage yet.",providerManagementEmptyDescription:"This list will appear automatically once the Host reports available CLI providers.",providerManagementLoginRequired:"Sign in before managing CLI providers.",providerManagementLoadFailed:"Failed to load the CLI provider list.",providerManagementSaveFailed:"Failed to save the CLI provider status.",providerManagementSummaryTitle:"Provider Overview",providerManagementSummaryDescription:"Check the totals first, then decide which CLI should stay enabled.",providerManagementSummaryEnabled:"Enabled",providerManagementSummaryDisabled:"Disabled",providerManagementSummaryTotal:"Total",providerManagementMatrixTitle:"Capability Matrix",providerManagementMatrixDescription:"Rows are CLI providers and columns are product capabilities. Turning a provider off hides it across related entry points.",providerManagementTableProvider:"CLI Provider",providerManagementTableStatus:"Status",providerManagementTableEnabled:"Enabled",providerManagementStatusEnabled:"Enabled",providerManagementStatusDisabled:"Disabled",providerManagementInstallReady:"Installed",providerManagementInstallMissing:"Not detected",providerManagementInstallUnknown:"Unknown",providerManagementStateEnabled:"This CLI is currently shown in new session, fork, assistant, and Skill-related entry points.",providerManagementStateDisabled:"This CLI is hidden from new entry points, and its old sessions are also hidden from normal lists.",providerManagementStateMissing:"This CLI is allowed, but the local runtime is not ready yet, so it cannot be used until installation is complete.",providerManagementToggleLabel:"Toggle {provider}",providerManagementEnableSuccess:"{provider} has been enabled again.",providerManagementDisableSuccess:"{provider} has been disabled.",providerManagementCapabilityStreaming:"Streaming output",providerManagementCapabilityToolCalls:"Tool calls",providerManagementCapabilityAssistant:"Assistant service",providerManagementCapabilityFork:"Session fork",providerManagementCapabilitySkill:"Skill usage",providerManagementCapabilityAvailable:"Available",providerManagementCapabilityUnavailable:"Unavailable",providerManagementImpactSessionStart:"new session start",providerManagementImpactFork:"session fork",providerManagementImpactAssistant:"assistant follow-up",providerManagementImpactSkill:"new Skill targets",providerManagementImpactEnabled:"If you turn it off now, old sessions will be hidden and {actions} will be blocked.",providerManagementImpactDisabled:"It is currently blocking {actions}; once re-enabled, those entry points will show up again.",providerManagementImpactEnabledFallback:"If you turn it off now, this CLI will disappear from new entry points across the product.",providerManagementImpactDisabledFallback:"Once re-enabled, this CLI will return to the normal entry points across the product.",channelsManagement:"Messaging Channels",channelsManagementSectionSummary:"Manage external channels, polling accounts, and recent inbound or outbound records in one place.",channelsManagementNavValue:"Accounts / Records",channelsManagementDescription:"Manage channel accounts here and review recent messages and delivery records.",channelsManageAction:"Manage Channel Accounts",channelsModalTitle:"Messaging Channel Accounts",channelsAddAccountAction:"Add Channel Account",channelsModalDescription:"This first phase uses a shared account model. Text messages, fixed provider selection, polling, and Butler control session bridging are the main scope.",channelsActionPending:"Working...",channelsRefresh:"Refresh data",channelsRefreshSuccess:"Channel data refreshed.",channelsLoading:"Loading channel data...",channelsLoadingDetails:"Loading recent threads and messages...",channelsLoadFailed:"Failed to load channel data.",channelsLoadDetailsFailed:"Failed to load recent threads and messages.",channelsSaveFailed:"Failed to save the channel account.",channelsProbeFailed:"Failed to probe the channel account.",channelsPollFailed:"Failed to trigger manual polling.",channelsRemoveFailed:"Failed to remove the channel account.",channelsCreateSuccess:"{account} created.",channelsUpdateSuccess:"{account} saved.",channelsRemoveSuccess:"Removed channel account “{account}”.",channelsSelectAccountFirst:"Select an existing account first, or create a new one.",channelsSummaryTitle:"Channel Overview",channelsSummaryAccounts:"Accounts",channelsSummaryActive:"Healthy",channelsSummaryPlatforms:"Platforms",channelsWizardTitle:"Setup Wizard",channelsWizardCreateDescription:"Choose a channel first, fill that channel's own config form, then bind the account to a fixed assistant engine.",channelsWizardEditDescription:"You are editing an existing account. The platform stays fixed here, and changing the assistant engine only affects new sessions.",channelsWizardStepsTitle:"Channel account setup steps",channelsWizardStepPlatform:"Choose channel",channelsWizardStepConfig:"Channel config",channelsWizardStepBinding:"Bind account",channelsWizardNextToConfig:"Continue to config",channelsWizardNextToBinding:"Continue to binding",channelsWizardBackToPlatform:"Back to channel selection",channelsWizardBackToConfig:"Back to channel config",channelsWizardSelectPlatformHint:"Pick a channel first so the matching platform-specific form can be shown below.",channelsWizardBindingSummary:"Multi-session support",channelsPlatformsTitle:"Platform Catalog",channelsPlatformsDescription:"Channel cards show the phase-one polling model, multi-session support, and the current limits.",channelsPlatformsEmpty:"No platform capabilities are available yet.",channelsPlatformsEmptyDescription:"This list will appear automatically once the Host reports the platform catalog.",channelsPlatformSummary:"Modes: {modes}; multi-session: {multiSession}",channelsAccountsTitle:"Channel Accounts",channelsAccountsDescription:"Each account is fixed to one assistant engine and always uses polling in phase one. New sessions follow the account config, while old sessions keep their original context.",channelsAccountsEmpty:"No channel accounts yet.",channelsAccountsEmptyDescription:"Add one channel account first. Thread mappings and delivery records will appear after real traffic arrives.",channelsAccountRowDescription:"{platform} · {provider} · {mode}",channelsCreateAction:"Create account",channelsSaveAction:"Save account",channelsResetToCreate:"New account form",channelsCreateFormTitle:"Create Channel Account",channelsCreateFormDescription:"Build the shared account fields first. Platform-specific differences stay in the extra JSON config for this phase.",channelsEditFormTitle:"Edit Channel Account",channelsEditFormDescription:"Changing the provider only affects new sessions. Existing sessions keep their original context.",channelsFieldDisplayName:"Account name",channelsFieldDisplayNamePlaceholder:"For example: Feishu Duty Bot",channelsFieldPlatform:"Platform",channelsFieldPlatformDescription:"Choose the platform first, then pick the connection mode and extra config.",channelsFieldProvider:"Assistant engine",channelsFieldProviderDescription:"Phase one only allows Codex or Claude Code, and you cannot switch providers inside the same external thread.",channelsFieldConnectionMode:"Connection mode",channelsFieldConnectionModeDescription:"All six platforms use polling in phase one. You do not switch to another mode here.",channelsFieldStatus:"Account status",channelsFieldStatusDescription:"Use healthy, disabled, or degraded to control whether this account should keep serving traffic.",channelsFieldConfig:"Extra platform config (JSON)",channelsFieldConfigDescription:"Use this only for fields that the dedicated form does not cover yet. The dedicated form stays the primary source.",channelsAdvancedConfigTitle:"Extra fields (advanced)",channelsAdvancedConfigDescription:"Only put fields here when the dedicated form does not cover them yet, such as outbound URLs, temporary switches, or experiment flags.",channelsValidationDisplayName:"Enter an account name first.",channelsValidationPlatform:"Choose a platform first.",channelsValidationConnectionMode:"Choose a connection mode first.",channelsValidationConfigJson:"The extra config is not valid JSON.",channelsValidationConfigObject:"The extra config must be a JSON object.",channelsValidationRequiredField:"Fill in “{field}” first.",channelsValidationFeishuCredential:"Feishu still needs one working credential set: either a Tenant Access Token, or both App ID and App Secret.",channelsConfigWechatUnavailableTitle:"WeChat (claw) does not need manual protocol fields",channelsConfigWechatUnavailableDescription:"QR binding, login state, polling, and outbound delivery are handled by the Host helper, so this step does not require private protocol fields.",channelsDetailTitle:"Selected Account Overview",channelsDetailDescription:"Review the current account state, recent traffic, and whether the account needs manual follow-up.",channelsDetailPlatform:"Platform",channelsDetailProvider:"Assistant engine",channelsDetailConnectionMode:"Connection mode",channelsDetailStatus:"Account status",channelsDetailLastInbound:"Last inbound",channelsDetailLastOutbound:"Last outbound",channelsDetailLastError:"Last error",channelsProbeAction:"Probe account",channelsPollAction:"Run polling",channelsRemoveAction:"Remove account",channelsRemoveConfirmAction:"Confirm removal",channelsRemoveConfirmDescription:"Removing this account also clears its thread mappings, inbound events, and delivery records. This action cannot be undone.",channelsWebhookHint:"This account uses webhook mode, so manual polling is not needed.",channelsConnectionModeFixedHint:"Phase one always models these channels as polling. If a different mode is needed later, the account rules will be upgraded separately.",channelsThreadsTitle:"Thread Mappings",channelsThreadsDescription:"Recent {count} thread mappings between external conversation keys and Butler control sessions.",channelsThreadsEmpty:"No thread mappings yet.",channelsThreadsEmptyDescription:"This list appears automatically after the first external message is received.",channelsEventsTitle:"Inbound Events",channelsEventsDescription:"Recent {count} inbound events so you can verify whether the Host received and dispatched them.",channelsEventsEmpty:"No inbound events yet.",channelsEventsEmptyDescription:"Records will appear here after the channel starts pulling real text messages.",channelsDeliveriesTitle:"Deliveries",channelsDeliveriesDescription:"Recent {count} outbound deliveries so you can confirm whether Butler's first text reached the external platform.",channelsDeliveriesEmpty:"No deliveries yet.",channelsDeliveriesEmptyDescription:"Records will appear here after Butler produces the first outbound text.",channelsConnectionModeWebhook:"Webhook",channelsConnectionModePolling:"Polling",channelsConnectionModeBridge:"Bridge",channelsMultiSessionSupported:"Multi-session ready",channelsMultiSessionLimited:"Limited multi-session",channelsStatusActive:"Healthy",channelsStatusDisabled:"Disabled",channelsStatusDegraded:"Degraded",channelsThreadStatusActive:"Active",channelsThreadStatusClosed:"Closed",channelsThreadStatusFailed:"Failed",channelsEventStatusReceived:"Received",channelsEventStatusDispatched:"Dispatched",channelsEventStatusReplied:"Replied",channelsEventStatusFailed:"Failed",channelsEventStatusIgnored:"Ignored",channelsDeliveryStatusSent:"Sent",channelsDeliveryStatusFailed:"Failed",channelsDeliveryStatusSkipped:"Skipped",channelsThreadSummary:"{status} · conversation key: {conversationKey}",channelsEventSummary:"{status} · conversation key: {conversationKey}",channelsDeliverySummary:"{status} · latest outbound text",channelsMetaCreatedAt:"Created",channelsMetaUpdatedAt:"Updated",channelsMetaReceivedAt:"Received",channelsMetaExternalUser:"External user",channelsMetaEventId:"External event",channelsMetaProviderRef:"Platform ref",channelsMetaError:"Error",channelsTextFallback:"Empty text",channelsTimeUnknown:"Not available",channelsWechatBindingTitle:"WeChat binding",channelsWechatBindingDescription:"This account uses the Host-managed helper for QR login, polling, and outbound delivery.",channelsWechatBoundDescription:"The WeChat account is already bound. You can continue with health checks, manual polling, and later session bridging.",channelsWechatCreateDescription:"Name this WeChat account first. After creation, generate the QR code in the detail panel and finish the bind there.",channelsWechatRuntimeRequiredTitle:"Direct WeChat binding is not available yet",channelsWechatRuntimeRequiredDescription:"The current environment has not enabled the WeChat helper, so this page only shows the account basics. After the helper is enabled, the real QR binding flow appears here.",channelsWechatPendingTitle:"This account is still waiting for binding",channelsWechatPendingDescription:"Finish QR binding first. Polling, outbound delivery, and recent records only appear after the bind succeeds.",channelsWechatBeginBindingAction:"Start binding",channelsWechatContinueBindingAction:"Continue binding",channelsWechatStartLoginAction:"Generate QR code",channelsWechatRestartBindingAction:"Generate a new QR code",channelsWechatRefreshLoginAction:"Refresh binding status",channelsWechatLogoutAction:"Clear binding",channelsWechatBindingModalTitle:"Scan the QR code to bind WeChat",channelsWechatBindingModalDescription:"Scan the QR code below with WeChat, then come back here and click “Refresh binding status”.",channelsWechatBindingModeValue:"QR binding",channelsWechatLoginStatus:"Binding status",channelsWechatLoginStatusNotLoggedIn:"Not bound",channelsWechatLoginStatusWaitingScan:"Waiting for scan",channelsWechatLoginStatusScanConfirmed:"Scanned, waiting confirmation",channelsWechatLoginStatusActive:"Bound",channelsWechatLoginStatusExpired:"QR code expired",channelsWechatQrHint:"After scanning successfully, click “Refresh binding status” to sync the result.",channelsWechatQrAlt:"WeChat claw binding QR code",channelsWechatOpenQrLinkAction:"Open binding QR code",channelsWechatQrRawTitle:"View raw QR content",channelsWechatQrRawDescription:"The raw QR payload returned by the upstream service is kept here first so the scan flow can be debugged.",channelsWechatQrEmpty:"No binding QR code yet",channelsWechatQrEmptyDescription:"Click “Generate QR code” above first, then scan it with WeChat to finish binding.",channelsConfigFieldDingtalkAppKey:"DingTalk AppKey",channelsConfigFieldDingtalkAppKeyDescription:"This identifies the DingTalk app when the real polling API is wired in later.",channelsConfigFieldDingtalkAppKeyPlaceholder:"Enter the DingTalk AppKey",channelsConfigFieldDingtalkAppSecret:"DingTalk AppSecret",channelsConfigFieldDingtalkAppSecretDescription:"Use the production credential for the real duty account so test credentials do not leak into the live polling account.",channelsConfigFieldDingtalkAppSecretPlaceholder:"Enter the DingTalk AppSecret",channelsConfigFieldDingtalkRobotCode:"Robot code",channelsConfigFieldDingtalkRobotCodeDescription:"If replies will eventually be sent through a fixed robot, store the robot code here now.",channelsConfigFieldDingtalkRobotCodePlaceholder:"For example: dingxxxxxxxx",channelsConfigFieldFeishuAppId:"Feishu App ID",channelsConfigFieldFeishuAppIdDescription:"If you do not plan to fill a Tenant Access Token directly, enter this together with the App Secret.",channelsConfigFieldFeishuAppIdPlaceholder:"Enter the Feishu App ID",channelsConfigFieldFeishuAppSecret:"Feishu App Secret",channelsConfigFieldFeishuAppSecretDescription:"If you do not plan to fill a Tenant Access Token directly, enter this together with the App ID.",channelsConfigFieldFeishuAppSecretPlaceholder:"Enter the Feishu App Secret",channelsConfigFieldFeishuTenantAccessToken:"Tenant Access Token",channelsConfigFieldFeishuTenantAccessTokenDescription:"If you can reliably obtain a tenant_access_token, enter it here and you do not need to force App ID plus App Secret as well.",channelsConfigFieldFeishuTenantAccessTokenPlaceholder:"Enter the Feishu tenant_access_token",channelsConfigFieldFeishuChatId:"Target chat ID",channelsConfigFieldFeishuChatIdDescription:"Required. Phase one stays on one fixed chat so the Host knows where to pull messages and send replies.",channelsConfigFieldFeishuChatIdPlaceholder:"For example: oc_xxx or chat_xxx",channelsConfigFieldWechatBaseUrl:"claw service URL",channelsConfigFieldWechatBaseUrlDescription:"Host will use this address to pull messages and send replies. It must be reachable from the Host machine.",channelsConfigFieldWechatBaseUrlPlaceholder:"For example: http://127.0.0.1:8787",channelsConfigFieldWechatBridgeToken:"claw access token",channelsConfigFieldWechatBridgeTokenDescription:"If your claw transport requires an access token, place it here for basic protection.",channelsConfigFieldWechatBridgeTokenPlaceholder:"Enter the claw transport token",channelsConfigFieldWechatPollPath:"Polling path",channelsConfigFieldWechatPollPathDescription:"The default is `/poll`. Override it here if your transport uses another route.",channelsConfigFieldWechatPollPathPlaceholder:"Default: /poll",channelsConfigFieldWechatSendPath:"Send path",channelsConfigFieldWechatSendPathDescription:"The default is `/send`. Override it here if your transport uses another route.",channelsConfigFieldWechatSendPathPlaceholder:"Default: /send",channelsConfigFieldTelegramBotToken:"Telegram Bot Token",channelsConfigFieldTelegramBotTokenDescription:"Telegram polling and outbound replies both require this token. Without it the account cannot work.",channelsConfigFieldTelegramBotTokenPlaceholder:"Enter the Telegram Bot Token",channelsConfigFieldSlackBotToken:"Slack Bot Token",channelsConfigFieldSlackBotTokenDescription:"Required. Slack polling and outbound text replies both depend on this token.",channelsConfigFieldSlackBotTokenPlaceholder:"Enter the Slack Bot Token",channelsConfigFieldSlackAppToken:"Slack App Token",channelsConfigFieldSlackAppTokenDescription:"The minimum working config does not require this. Fill it only when your Slack app setup really needs it.",channelsConfigFieldSlackAppTokenPlaceholder:"Enter the Slack App Token",channelsConfigFieldSlackChannelId:"Channel ID",channelsConfigFieldSlackChannelIdDescription:"Required. Phase one binds the account to one fixed channel so polling and text delivery can work first.",channelsConfigFieldSlackChannelIdPlaceholder:"For example: C0123456789",channelsConfigFieldDiscordBotToken:"Discord Bot Token",channelsConfigFieldDiscordBotTokenDescription:"Required. Discord polling and outbound text replies both depend on this bot token.",channelsConfigFieldDiscordBotTokenPlaceholder:"Enter the Discord Bot Token",channelsConfigFieldDiscordApplicationId:"Application ID",channelsConfigFieldDiscordApplicationIdDescription:"The minimum working config does not require this. Fill it only when your app permissions really depend on it.",channelsConfigFieldDiscordApplicationIdPlaceholder:"Enter the Discord Application ID",channelsConfigFieldDiscordGuildId:"Guild ID",channelsConfigFieldDiscordGuildIdDescription:"Required. Lock the account to one server first. Thread branches will run under this guild.",channelsConfigFieldDiscordGuildIdPlaceholder:"Enter the Discord Guild ID",channelsConfigFieldDiscordChannelId:"Channel ID",channelsConfigFieldDiscordChannelIdDescription:"Required. Lock the account to one channel first. Thread branches will hang under this channel.",channelsConfigFieldDiscordChannelIdPlaceholder:"Enter the Discord Channel ID",channelsConfigChecklistTitle:"Minimum you need for this step",channelsConfigChecklistFeishuSummary:"This Feishu setup stays on fixed-chat polling in phase one, so the Host needs one target chat and one working credential path.",channelsConfigChecklistFeishuItemCredential:"Choose one credential path: either a Tenant Access Token, or both App ID and App Secret.",channelsConfigChecklistFeishuItemChat:"You must enter the target chat ID, otherwise the Host does not know which chat to pull from or reply to.",channelsConfigChecklistFeishuItemScope:"Phase one only handles text messages. Images, files, voice, and cards are not covered yet.",channelsConfigChecklistSlackSummary:"This Slack setup stays on one fixed channel for polling first, so inbound reads and outbound text replies can be verified.",channelsConfigChecklistSlackItemToken:"You must enter the Bot Token. Without it the account cannot read messages or send replies.",channelsConfigChecklistSlackItemChannel:"You must enter the channel ID. This account is fixed to one channel in phase one.",channelsConfigChecklistSlackItemScope:"Phase one only handles text messages, and Slack thread branches are not implemented yet.",channelsConfigChecklistDiscordSummary:"This Discord setup needs one fixed guild and channel first. Later thread branches will live inside that scope.",channelsConfigChecklistDiscordItemToken:"You must enter the Bot Token. Polling reads and outbound text replies both depend on it.",channelsConfigChecklistDiscordItemGuild:"You must enter the Guild ID so the account is fixed to one server first.",channelsConfigChecklistDiscordItemChannel:"You must enter the channel ID. Later thread branches will hang under this channel.",modelManagementTitle:"Quick Model Switching",modelManagementDescription:"This page does not add or edit presets. It only exposes the presets already managed by cc-switch so you can switch quickly.",modelManagementRefresh:"Refresh Models",modelManagementRefreshSuccess:"Model presets refreshed.",modelManagementLoadFailed:"Failed to load model presets.",modelManagementScannedAt:"Last Scanned",modelManagementScannedAtUnknown:"Not scanned yet",modelManagementCurrentProfile:"Current Profile",modelManagementCurrentModel:"Current Model",modelManagementCurrentPreset:"Current Preset",modelManagementModelUnknown:"Unknown",modelManagementPresetMissing:"Not set",modelManagementCurrentTag:"Current",modelManagementOpenSwitcher:"Switch Profile",modelManagementModalTitle:"Provider Profile Switching",modelManagementModalDescription:"Review the existing cc-switch profiles by app and switch the active one here.",modelManagementTabsLabel:"Model app tabs",modelManagementSwitchAction:"Switch",modelManagementSwitchSuccess:"{app} switched to {preset}.",modelManagementOptionsEmpty:"No switchable presets were found.",modelManagementStatusReady:"Ready",modelManagementStatusUnconfigured:"Unconfigured",modelManagementStatusUnavailable:"cc-switch-cli missing",modelManagementStatusError:"Read failed",skills:"Skills",skillsSectionSummary:"Read and sync the local skills owned by each CLI. No marketplace and no remote catalog in this phase.",skillsNavValue:"Local sync",skillManagerTitle:"Local Skill Management",skillManagerDescription:"Read the local skill folders used by Codex, Claude Code, Gemini, and OpenCode, then import unmanaged entries or sync them again.",skillSummaryManagedSkills:"My Skills",skillSummaryManagedEntries:"Active",skillSummaryUnmanagedEntries:"Unmanaged folders",skillSummaryConflictedEntries:"Needs Attention",skillSummaryAssistantRuntimeEntries:"Assistant-only",skillSummaryDiagnostics:"Notices",skillManageAction:"Skill Settings",skillConfigModalTitle:"Skill Settings",skillConfigModalDescription:"Review your skills, built-in assistant skills, and anything that needs your attention.",skillCreateAction:"Add Skill",skillCreateModalTitle:"Add Skill",skillCreateModalDescription:"Bring a new SKILL.md under management. File upload and pasted markdown share the same validation and import flow.",skillCreateSourceTabsLabel:"Add Method",skillCreateSourceFile:"Choose File",skillCreateSourcePaste:"Paste Text",skillCreateSubmitAction:"Add",skillRefresh:"Refresh",skillRefreshSuccess:"Skill list refreshed.",skillScannedAt:"Last Scanned",skillUploadSectionTitle:"Upload Skill",skillUploadSectionDescription:"Choose a SKILL.md file, decide whether it belongs to the workspace or the assistant runtime, then let the app validate, fix, and manage it.",skillUploadPickAction:"Choose SKILL.md",skillUploadSubmitAction:"Upload & Manage",skillUploadEmpty:"No SKILL.md file has been selected yet.",skillUploadPickedFile:"Selected File",skillUploadScopeLabel:"Scope",skillUploadScopeWorkspace:"Workspace Skill",skillUploadScopeAssistant:"Assistant Skill",skillUploadDirectoryLabel:"Directory Name",skillUploadDirectoryPlaceholder:"For example: team-helper",skillUploadDirectoryHint:"Used for the managed folder name and sync target folder. It is generated from the file name or heading by default, so you usually do not need to change it.",skillUploadDirectoryInvalid:"The directory name is invalid. Only letters, numbers, dots, underscores, and dashes are allowed.",skillUploadTargetsLabel:"Target CLI",skillPasteLabel:"Paste SKILL Content",skillPastePlaceholder:"Paste the full SKILL.md content here",skillPasteEmpty:"There is no SKILL content ready to manage yet.",skillUploadDirectoryRequiredNote:"The file name does not produce a valid directory name, so you need to fill one in manually.",skillUploadTargetRequired:"Select at least one target CLI.",skillUploadHeadingNote:"The markdown does not contain a level-one heading. One will be added automatically during import.",skillUploadNormalizedNote:"Whitespace and line endings were normalized for upload.",skillUploadReadFailed:"Failed to read the uploaded SKILL.md file.",skillUploadContentEmpty:"The uploaded SKILL.md file cannot be empty.",skillUploadSuccess:"{name} was added.",skillManagedListTitle:"My Skills",skillManagedEmpty:"You have not added any skills yet.",skillManagedItemDescription:"Added to {targets}.",skillManagedItemNoTarget:"This skill has not been applied to any client yet.",skillUnmanagedListTitle:"Skills to Add",skillUnmanagedEmpty:"There are no new skills to add right now.",skillUnmanagedItemDescription:"Found in {target}. You can add it to your list.",skillUnmanagedItemDisabledDescription:"Found in {target}, but that target is disabled right now, so it cannot be added again yet.",skillAssistantRuntimeListTitle:"Built-in Assistant Skills",skillAssistantRuntimeListDescription:"These skills are provided by the system and only used by the assistant.",skillAssistantRuntimeEmpty:"There are no built-in assistant skills right now.",skillAssistantRuntimeItemDescription:"This is a built-in skill. You do not need to manage it yourself.",skillAssistantRuntimeUsedBy:"Available In",skillAssistantRuntimeSourcePath:"Built-in Source Path",skillConflictedListTitle:"Needs Attention",skillConflictedEmpty:"There is nothing to fix right now.",skillConflictedItemDescription:"This item in {target} needs attention.",skillConflictedItemDisabledDescription:"This item still exists in {target}, but that target is disabled right now.",skillDiagnosticsTitle:"Notices",skillDiagnosticsEmpty:"There are no new notices right now.",skillDiagnosticTargetMissingTitle:"{target} Is Not Ready Yet",skillDiagnosticTargetMissingDetail:"The skill folder for {target} was not found yet.",skillDiagnosticReadFailedTitle:"{target} Is Temporarily Unavailable",skillDiagnosticReadFailedDetail:"The skill information for {target} cannot be read right now. Try again later.",skillDiagnosticSyncMissingTitle:"{target} Needs To Be Applied Again",skillDiagnosticSyncMissingDetail:"Some skills have not taken effect in {target} yet.",skillDiagnosticGenericTitle:"{target} Needs Attention",skillDiagnosticGenericDetail:"Something is not ready yet. Refresh and check again later.",skillDirectoryName:"Directory Name",skillSsotPath:"SSOT Path",skillSourceCli:"Source CLI",skillDirectoryPath:"Directory Path",skillImportAction:"Add",skillImportSuccess:"{name} was added and applied to {target}.",skillSyncAction:"Apply Again",skillSyncSuccess:"{name} was applied again.",skillSyncTargetMissing:"This skill has no target yet, so it cannot be applied again.",skillSyncTargetDisabled:"This skill currently only points at disabled targets. Re-enable a provider before applying it again.",skillLoadFailed:"Failed to load the skill overview.",skillOfficeTemplateCreated:"Document template created.",skillOfficeTemplateUpdated:"Document template updated.",skillOpsTargetCreated:"SSH target created.",skillOpsTargetUpdated:"SSH target updated.",skillOpsApprovalApproved:"Ops approval approved.",skillOpsApprovalRejected:"Ops approval rejected.",skillTargetCodex:"Codex",skillTargetClaudeCode:"Claude Code",skillTargetGemini:"Gemini",skillTargetOpenCode:"OpenCode",skillBindingPending:"Preparing",skillBindingSynced:"Available",skillBindingFailed:"Unavailable",skillBindingConflicted:"Needs Attention",skillUploadTargetDisabled:"All available Skill targets are disabled right now. Re-enable a provider in settings first.",skillTargetDisabledTag:"Disabled",skillTagAssistantOnly:"Assistant Only",skillTagWorkspaceSessionOnly:"Workspace Session Only",securityPrivacy:"Security & Privacy",securityPrivacySectionSummary:"Session permissions, risk boundaries, and default approval policy",softwareUpdate:"Software Update",softwareUpdateSectionSummary:"Server and client versions",updateOneClickValue:"One check",updateOneClickTitle:"Unified updates",updateOneClickDescription:"Check server and desktop versions first, then install available updates in order.",updateOptions:"Update options",updateInstallAll:"Install all updates",updateCheckFailed:"Update check failed",updateInstallingSequential:"Preparing updates",updateInstallingServerFirst:"Updating the server",updateInstallingClientNext:"Updating the desktop app",updateBothReady:"Server and desktop updates are available",updateServerReadyOnly:"Server update is available",updateClientReadyOnly:"Desktop update is available",updateAllUpToDate:"Everything is up to date",updateCheckIncomplete:"Some update details are unavailable right now. Please try again.",updateServerReadyClientCheckFailed:"Server update is available, but desktop details are unavailable right now.",updateClientReadyServiceCheckFailed:"Desktop update is available, but server details are unavailable right now.",serverAddress:"Server Address",serverDescription:"Login, API requests, and realtime connections all use this Host entry, while the frontend UI is bundled inside the client itself.",serverRelayTunnelProfileTitle:"CodingNS Connect Entry For This Host",serverRelayTunnelProfileDescription:"Attach a CodingNS Connect entry to the saved Host profile. When enabled, the client connects through the CodingNS Connect domain and control site with end-to-end encryption instead of calling this address directly.",serverRelayTunnelEnabled:"Connect Through CodingNS Connect",serverRelayTunnelUsageHint:"The server address should usually stay as this Host's public entry, for example https://demo.codingns.example .",serverRelayTunnelDomain:"CodingNS Connect Domain",serverRelayTunnelDomainPlaceholder:"For example: demo.codingns.example",serverRelayTunnelControlBaseUrl:"Control Site URL",serverRelayTunnelControlBaseUrlPlaceholder:"For example: https://control.codingns.example",relayTunnelServerAddressDescription:"The official CodingNS Connect address is used by default. If you know the current control site address, you can override it in advanced settings.",relayTunnelServerAddressHint:"This only changes the CodingNS Connect control site used for login, binding, and traffic queries. It does not change the current Host's local API address.",relayTunnelStatus:"CodingNS Connect Status",relayTunnelDescription:"Use CodingNS Connect to let external devices reach this Host securely.",relayTunnelMasterSwitchLabel:"Enable CodingNS Connect",relayTunnelActivationHint:"Turn this on before checking CodingNS Connect status or allowing this Host to accept external access.",relayTunnelPhase:"Current State",relayTunnelDomain:"Access Address",relayTunnelUnbound:"Not bound yet",relayTunnelTrafficRemaining:"Remaining Traffic",relayTunnelHostFingerprint:"Host Fingerprint",relayTunnelTrustBoundaryNotice:"CodingNS Connect only forwards encrypted traffic and cannot read the content between the client and this Host.",relayTunnelRecentError:"Recent error: {message}",relayTunnelAccessTitle:"Connection Settings",relayTunnelAccessDescription:"Sign in with your CodingNS Connect account first, then turn the switch on to bring this device online for external access.",relayTunnelLearnService:"Learn About CodingNS Connect",relayTunnelWizardTitle:"Remote Access Wizard",relayTunnelWizardDescription:"Finish account login, host label confirmation, and CodingNS Connect startup in three steps. After that, the panel stays focused on the actual remote access info.",relayTunnelStatusErrorTitle:"Remote access status is unavailable right now",relayTunnelStatusNetworkError:"The client cannot reach this Host right now ({address}), so the remote access status may be outdated. Check the server address, port, and network connection first.",relayTunnelStepPending:"Pending",relayTunnelStepCurrent:"In Progress",relayTunnelStepDone:"Done",relayTunnelStepLocked:"Finish the previous step first.",relayTunnelStepLoginTitle:"Log In",relayTunnelStepLoginDescription:"Connect your CodingNS Connect account first. Host label checks and traffic queries both depend on it.",relayTunnelStepLoginConnected:"The account is already connected. Continue to the next step.",relayTunnelStepHostLabelTitle:"Set Host Label",relayTunnelStepHostLabelDescription:"Choose the fourth-level domain prefix you will use later and verify that it is available now.",relayTunnelStepStartTitle:"Start CodingNS Connect",relayTunnelStepStartDescription:"After the first two steps are ready, bring the current Host online through CodingNS Connect.",relayTunnelStepStartReady:"The host label is confirmed. You can start CodingNS Connect now.",relayTunnelStartAction:"Start CodingNS Connect",relayTunnelLoginErrorTitle:"Failed to log in to CodingNS Connect",relayTunnelAdvancedSettings:"Advanced Settings",relayTunnelAdvancedSettingsHide:"Hide Advanced Settings",relayTunnelAdvancedSettingsDescription:"The official CodingNS Connect address is used by default. Only override it when you know the exact control site address.",relayTunnelLoginNetworkError:"The login request never reached this Host because it is unavailable right now ({address}). Check the server address and network connection, then try again.",relayTunnelReadyTitle:"Remote Access Is Ready",relayTunnelReadyDescription:"The setup is complete. This view now keeps only the access URL, traffic info, and maintenance actions.",relayTunnelAccessUrlLabel:"Remote Access URL",relayTunnelCopyAccessUrl:"Copy URL",relayTunnelOpenAccessUrl:"Open Page",relayTunnelAccessUrlCopied:"The access URL has been copied.",relayTunnelCopyAccessUrlFailed:"Failed to copy the access URL.",relayTunnelOpenAccessUrlFailed:"Failed to open the access URL.",relayTunnelClientRouteLabel:"Current Client Route",relayTunnelClientRouteAddressLabel:"Current Client Address",relayTunnelClientRouteHintRelay:"The client is still using CodingNS Connect for this Host. If a reachable local address is confirmed, it will switch to a lower-traffic direct route automatically.",relayTunnelClientRouteHintRelayProbing:"The client is checking local direct addresses now. When the check finishes, it will switch to the lower-traffic route automatically.",relayTunnelClientRouteHintLan:"The client has already switched to a LAN direct route, which uses less traffic. The remote access URL can still be used on external devices.",relayTunnelClientRouteHintLoopback:"The client is connecting to this device through its local address, without going through CodingNS Connect.",relayTunnelClientRouteHintTailscale:"The client has already switched to a Tailscale address, without going through CodingNS Connect.",relayTunnelClientRouteHintDirect:"The client is requesting this Host address directly, without going through CodingNS Connect.",relayTunnelReconnectAction:"Reconnect",relayTunnelManageAccountAction:"Manage Account",relayTunnelDisconnectDeviceAction:"Sign Out Device",relayTunnelEnableToggleLabel:"Enable CodingNS Connect",relayTunnelConfigTitle:"CodingNS Connect Site Configuration",relayTunnelConfigDescription:"Configure the CodingNS Connect endpoint and control site here. Login, binding, and traffic operations below all use these addresses.",relayTunnelConfigErrorTitle:"Failed to save the CodingNS Connect site address",relayTunnelConfigNetworkError:"The new tunnel site address has not been saved to this Host because it is unavailable right now ({address}). Check the server address and network connection first.",relayTunnelRelayBaseUrl:"CodingNS Connect Endpoint URL",relayTunnelControlBaseUrl:"Control Site URL",relayTunnelSaveConfig:"Save Configuration",relayTunnelRefresh:"Refresh Status",relayTunnelAccountTitle:"CodingNS Connect Account",relayTunnelAccountDescription:"Sign in with your CodingNS Connect account to bind this Host and review the remaining traffic quota.",relayTunnelAccountEmail:"Email",relayTunnelAccountEmailPlaceholder:"Enter your email",relayTunnelAccountPassword:"Password",relayTunnelAccountPasswordPlaceholder:"Enter your password",relayTunnelLoginAccount:"Log In",relayTunnelLoggedInAs:"Logged in as: {email}",relayTunnelConnectedBannerTitle:"Account Connected",relayTunnelConnectedBannerDescription:"You can now turn on CodingNS Connect so external devices can reach this Host.",relayTunnelConnectedBannerActiveTitle:"CodingNS Connect Is On",relayTunnelConnectedBannerActiveDescription:"This device is now reachable from outside through CodingNS Connect.",relayTunnelConnectedDevice:"Current device: {name}",relayTunnelBoundDomain:"Current access address: {domain}",relayTunnelBindTitle:"Bind Current Host",relayTunnelBindDescription:"Binding first reads the current Host long-term public key, then registers this machine on CodingNS Connect.",relayTunnelHostLabelTitle:"Device Name",relayTunnelHostLabelDescription:"After you sign in, enter the fourth-level domain prefix you plan to use later and check whether that name is currently available.",relayTunnelHostLabel:"Host Label",relayTunnelHostLabelPlaceholder:"Enter the prefix",relayTunnelHostLabelSuffix:".channel.codingns.com",relayTunnelHostLabelCheck:"Check Name",relayTunnelHostLabelChecking:"Checking whether this name is available.",relayTunnelHostLabelAvailable:"This name is available. The public access address will be {domain}",relayTunnelHostLabelReserved:"This name hits a reserved prefix. Choose a different name.",relayTunnelHostLabelOccupied:"This name is already taken. Choose a different name.",relayTunnelHostLabelUnavailable:"The name cannot be verified right now. Try again later.",relayTunnelHostLabelRequired:"Enter a device name first.",relayTunnelBindAction:"Login And Bind Host",relayTunnelActionsTitle:"CodingNS Connect Controls",relayTunnelActionsDescription:"After binding, you can enable, disable, or unbind CodingNS Connect here.",relayTunnelEnable:"Enable CodingNS Connect",relayTunnelDisable:"Disable CodingNS Connect",relayTunnelUnbind:"Disconnect This Device",relayTunnelWalletTitle:"Traffic Wallet",relayTunnelWalletDescription:"This shows the total traffic granted, traffic used, and remaining quota recorded by the control site.",relayTunnelTrafficGranted:"Granted Traffic",relayTunnelTrafficUsed:"Used Traffic",relayTunnelPackagesTitle:"Traffic Packages",relayTunnelPackagesDescription:"Selecting a package opens the official checkout page. After payment succeeds, the quota is granted to the current account automatically.",relayTunnelFeaturedPackage:"Featured",relayTunnelBuyPackage:"Buy Traffic",relayTunnelOrdersTitle:"Recent Orders",relayTunnelOrdersDescription:"Only the most recent orders are shown here so you can confirm payment and quota status quickly.",relayTunnelOrderPending:"Pending",relayTunnelOrderPaid:"Paid",relayTunnelOrderExpired:"Expired",relayTunnelOrderFailed:"Failed",relayTunnelControlBaseUrlRequired:"Fill in the control site URL first.",relayTunnelAccountRequired:"Enter the CodingNS Connect account email and password first.",relayTunnelIdentityUnavailable:"The current Host identity key is not ready yet. Try again later.",relayTunnelLoadFailed:"Failed to load the CodingNS Connect status.",relayTunnelPhaseDisabled:"Disabled",relayTunnelPhaseBlockedUninitialized:"Blocked Until Bootstrap Finishes",relayTunnelPhaseUnbound:"Not Bound",relayTunnelPhaseBinding:"Binding",relayTunnelPhaseConnecting:"Connecting",relayTunnelPhaseRunning:"Running",relayTunnelPhaseQuotaExhausted:"Quota Exhausted",relayTunnelPhaseError:"Error",tailscaleBrand:"Tailscale",tailscaleSectionTitle:"Tailscale Access",tailscaleSectionDescription:"Let this Host stay reachable across your devices with Tailscale.",tailscaleMasterSwitchLabel:"Enable Tailscale",tailscaleActivationHint:"Turn this on before checking Tailscale status or continuing with setup and account binding.",tailscaleCurrentState:"Current State",tailscaleSwitchLabel:"Enabled",tailscaleStatusIndicator:"Status",tailscaleServerAddress:"Server Address",tailscaleAccountName:"Account",tailscaleIpAddress:"IP Address",tailscaleConfigure:"Configure",tailscaleConfigModalTitle:"Configure Tailscale",tailscaleConfigModalDescription:"Edit connectivity settings",tailscaleControlServer:"Control Server",tailscaleControlServerDescription:"Leave empty to use the default control server.",tailscaleControlServerPlaceholder:"Leave empty to use the default control server",tailscaleHostname:"Hostname",tailscaleHostnameDescription:"Optional.",tailscaleHostnamePlaceholder:"For example: codingns-host",tailscaleReachableBaseUrl:"Reachable Base URL",tailscaleTailnetFqdn:"Tailnet FQDN",tailscaleTailnetIpv4:"Tailnet IPv4",tailscaleTailnetIpv6:"Tailnet IPv6",tailscaleDetailAddresses:"Detailed Addresses",tailscaleRefresh:"Refresh",tailscaleInstallAction:"Install Tailscale",tailscaleInstallOpenFailed:"Failed to open the Tailscale install page.",tailscaleEnable:"Enable Tailscale",tailscaleDisable:"Disable Tailscale",tailscaleLogin:"Bind Account",tailscaleLogout:"Unbind Account",tailscaleUnavailable:"Unavailable",tailscaleLoadFailed:"Failed to load Tailscale status.",tailscalePhaseDisabled:"Disabled",tailscalePhaseBlockedUninitialized:"Blocked until bootstrap finishes",tailscalePhaseStarting:"Starting",tailscalePhaseNeedsLogin:"Waiting for login",tailscalePhaseRunning:"Running",tailscalePhaseStopping:"Stopping",tailscalePhaseError:"Error",tailscaleOverviewDisabled:"Remote access is not enabled yet.",tailscaleOverviewBlockedUninitialized:"Finish bootstrap before enabling remote access.",tailscaleOverviewStarting:"Connecting to Tailscale. Please wait.",tailscaleOverviewNeedsLogin:"Tailscale is enabled, but account binding is still required.",tailscaleOverviewRunning:"This instance is reachable through Tailscale now.",tailscaleOverviewStopping:"Remote access is being turned off.",tailscaleOverviewError:"Remote access hit an error. Refresh or reconfigure it first.",autoReconnect:"Auto Reconnect",autoReconnectDescription:"Retry HTTP and WebSocket links automatically when Host is briefly unavailable.",autoCheckUpdate:"Auto check updates",autoCheckUpdateDescription:"Notify you when a new client version is found.",autoDownloadUpdate:"Download updates before prompting",autoDownloadUpdateDescription:"Download the client package first, then prompt you to install it.",defaultPermissionMode:"Default Session Permissions",defaultPermissionModeDescription:"Controls the default tool permissions for new and resumed sessions. Full access disables approval prompts and should only be used for trusted projects and environments.",authDeviceManagement:"Login Devices",authDeviceManagementDescription:"View the current device, other active devices, and the latest 10 login records, and sign out specific active devices one by one from a primary device.",authDeviceEntryHint:"Open device management to view the current device, other active devices, and recent login records in a dialog.",authDeviceOpenManager:"Manage Devices",authDeviceCurrentTitle:"Current Device",authDeviceOthersTitle:"Other Active Devices",authDeviceRecentTitle:"Recent Login Records",authDeviceCurrentTag:"Current",authDevicePrimaryTag:"Primary",authDeviceLegacyTag:"Legacy",authDeviceLegacyHiddenHint:"Detected {count} compatibility records from legacy sessions. They are hidden by default.",authDeviceLegacyReveal:"Show Compatibility Records",authDeviceLegacyHide:"Hide Compatibility Records",authDeviceLegacyDevicesTitle:"Legacy Active Records",authDeviceLegacyRecentTitle:"Legacy Login Records",authDeviceLegacyLabel:"Unknown Device (Legacy Session)",authDeviceClientDesktop:"Desktop",authDeviceClientWeb:"Web",authDeviceClientIos:"iOS",authDeviceClientAndroid:"Android",authDeviceClientUnknown:"Unknown Device",authDeviceCurrentEmpty:"The current session does not have identifiable device metadata yet. Please sign in again.",authDeviceOthersEmpty:"There are no other active devices.",authDeviceRecentEmpty:"There are no recent login records yet.",authDeviceBrowserValue:"Browser: {value}",authDeviceOsValue:"OS: {value}",authDeviceLastSeen:"Last seen: {value}",authDeviceLoginAt:"Login time: {value}",authDeviceSourceAddressValue:"Source address: {value}",authDeviceSourceAddressUnknown:"Source address: unknown",authDeviceEnablePrimary:"Set as Primary",authDeviceDisablePrimary:"Remove Primary",authDevicePrimaryUnavailable:"The current session does not have a stable device identity yet, so it cannot become a primary device.",authDeviceLogoutOthers:"Sign Out Other Devices",authDeviceLogoutDevice:"Sign Out Device",authDevicePrimaryEnabled:"The current device is now a primary device.",authDevicePrimaryDisabled:"The current device is no longer a primary device.",authDeviceLogoutOthersSuccess:"Signed out other devices. Processed {count}.",authDeviceLogoutDeviceSuccess:'Signed out device "{device}". Processed {count} session(s).',authDeviceLoadFailed:"Failed to load login device information.",authDeviceEnablePrimaryModalTitle:"Set as Primary Device",authDeviceEnablePrimaryModalDescription:"Enter the admin password to confirm that the current device should become a primary device.",authDeviceDisablePrimaryModalTitle:"Remove Primary Device",authDeviceDisablePrimaryModalDescription:"Enter the admin password to confirm that the current device should no longer be a primary device.",authDevicePasswordLabel:"Admin password",userManagementEntryTitle:"User Management",userManagementEntryDescription:"Manage who can sign in to this Host and review each user's sessions and model usage.",userManagementOpenAction:"Manage Users",userManagementTitle:"User Management",userManagementDescription:"Manage login users here. Users with business data cannot be deleted directly, so workspaces and sessions are not removed by mistake.",userManagementTabsLabel:"User management tabs",userManagementUsersTab:"User List",userManagementUsageTab:"Usage Details",userManagementUsersTitle:"User List",userManagementUsersDescription:"Add, edit, enable, or disable login users. Delete is only available for new users without data.",userManagementAddUser:"Add User",userManagementEditUser:"Edit",userManagementDeleteUser:"Delete",userManagementEnableUser:"Enable",userManagementDisableUser:"Disable",userManagementStatusActive:"Enabled",userManagementStatusDisabled:"Disabled",userManagementUserMeta:"Created: {createdAt}",userManagementLoading:"Loading users.",userManagementUsersEmptyTitle:"No users yet",userManagementUsersEmptyDescription:"After adding a user, login accounts will appear here.",userManagementAddDescription:"Enter a username and password. The new user can sign in immediately.",userManagementEditDescription:"Change the username. Leave password empty to keep the current password.",userManagementUsernameLabel:"Username",userManagementPasswordLabel:"Password",userManagementPasswordEditHint:"Leave empty if you do not need to change the password.",userManagementDeleteConfirmTitle:"Delete User",userManagementDeleteConfirmDescription:'Delete "{username}"? If this user already has data, the system will block deletion.',userManagementCreateSuccess:"User added.",userManagementUpdateSuccess:"User updated.",userManagementDeleteSuccess:"User deleted.",userManagementEnableSuccess:"User enabled.",userManagementDisableSuccess:"User disabled.",userManagementLoadFailed:"Failed to load users.",userManagementSaveFailed:"Failed to save user.",userManagementDeleteFailed:"Failed to delete user.",userManagementStatusFailed:"Failed to update user status.",userManagementUsageTitle:"Usage Details",userManagementUsageDescription:"Review sessions, models, CLI providers, and model providers by user.",userManagementUsageLoading:"Loading usage details.",userManagementUsageLoadFailed:"Failed to load usage details.",userManagementUsageEmptyTitle:"No usage yet",userManagementUsageEmptyDescription:"Usage appears here after users create sessions.",userManagementPeriodLabel:"Period",userManagementPeriodDay:"By Day",userManagementPeriodWeek:"By Week",userManagementPeriodMonth:"By Month",userManagementSessionCount:"{count} sessions",userManagementMetricSessions:"Sessions",userManagementMetricTotalTokens:"Total Tokens",userManagementMetricInputTokens:"Input Tokens",userManagementMetricOutputTokens:"Output Tokens",userManagementTokenUnavailable:"This Host does not persist model token usage yet, so token charts show 0. Session, model, and provider counts come from real session records.",userManagementTokenChartTitle:"Model Token Usage",userManagementTokenChartEmptyTitle:"No token records",userManagementTokenChartEmptyDescription:"After token usage is written to session records, trends will appear here.",userManagementModelUsage:"Model Usage",userManagementCliProviderUsage:"CLI Provider Usage",userManagementModelProviderUsage:"Model Provider Usage",userManagementUsageGroupEmpty:"No records",permissionModeDefault:"Follow CLI defaults",permissionModeAcceptEdits:"Allow workspace edits without asking",permissionModeBypassPermissions:"Full access without asking",enabled:"Enabled",disabled:"Disabled",serverUpdate:"Server Update",serverUpdateDescription:"",clientUpdate:"Client Update",clientUpdateDescription:"",serverCurrentVersion:"Server Current Version",serverTargetVersion:"Server Target Version",serverPackageName:"npm Package",serverUpdateCommand:"Upgrade Command",serverCheckNow:"Check Server",serverOpenPage:"Open npm",serverLatestUnknown:"Unavailable",serverUpdateReady:"New version found",serverUpToDate:"Up to date",serverCheckFailed:"Check failed",serverInstallWarning:"Installing the update will restart the CodingNS service through PM2 and briefly interrupt the connection.",serverInstallConfirmTitle:"Install Server Update",serverInstallConfirmDescription:"Continuing will install the new version first, then let PM2 restart the current CodingNS service automatically.",serverInstallConfirmAction:"Install And Restart",serverRestarting:"Update installed. Restarting the CodingNS service",serverProgressLabel:"Server update progress",serverProgressPreparing:"Preparing server update",serverProgressQueued:"Queued",serverProgressInstalling:"Updating the server",serverProgressRestarting:"Restarting service",serverProgressHint:"Server updates can take a few minutes. Keep the app open.",serverProgressCurrentStage:"Current stage: {stage}",serverOpenPageFailed:"Failed to open page",updateCheckAll:"Check updates",updateChecking:"Checking",releaseCurrentVersion:"Current Version",releaseTargetVersion:"Target Version",releaseTargetTag:"Target Tag",releasePublishedAt:"Published At",releaseUnknownVersion:"Unknown",releaseNotes:"What's New",releaseNotesEmpty:"No details",releaseCheckNow:"Check Client",releaseInstallNow:"Install",releaseDownloading:"Downloading desktop update",releaseDownloadedReady:"Desktop update is ready to install.",releaseDownloadedReadyWithProgress:"Desktop update is ready to install ({percent}%).",releaseDownloadFailed:"Download failed",releaseInstallReadyDialogTitle:"Update package downloaded",releaseInstallReadyDialogDescription:"Version {version} is ready to install.",releaseInstallReadyWarning:"Restart the app after installation.",releaseInstallReadyConfirm:"Install and restart",releaseDownloadedNotificationTitle:"Client update downloaded",releaseDownloadedNotificationBody:"Version {version} is ready. Open Settings to install it.",releaseOpenPage:"Open Release",releaseRollback:"Rollback",releaseUpdateBadge:"Update",releaseUpdateReady:"New version found",releaseUpToDate:"Up to date",releaseCheckFailed:"Check failed",releaseInstallerMissing:"A new version is available, but this release does not include a supported installer yet.",releaseSignatureMissing:"A new version is available, but this release does not provide checksum information yet.",releaseInstallStarted:"Install started",releaseInstallFailed:"Install failed",releaseRestartRequired:"Update installed. Restart the app to apply it.",releaseRestartDialogTitle:"Install completed",releaseRestartDialogDescription:"Version {version} has been installed. Restart the app to finish switching to the new build.",releaseRestartLater:"Later",releaseRestartConfirm:"Yes, restart now",releaseRestartFailed:"Failed to restart the app",releasePageOpenFailed:"Failed to open page",androidInstallerStarted:"Handed off to the Android installer. You can still cancel there.",androidInstallPermissionRequired:"Allow installs from this source before retrying.",androidInstallCancelled:"Install was cancelled or not completed. You can try again.",androidInstallSucceeded:"The new version has been detected as installed.",releaseRollbackStarted:"Rollback started",releaseRollbackFailed:"Rollback failed",clientUpdateUnsupported:"Install updates are not supported here",logout:"Log out"},home:{title:"Continue from a session, not from a backend table",subtitle:"Pick a workspace and session here first. The real work starts in the next step.",terminalsEntry:"Open Terminal",workspaceSection:"Workspaces",sessionSection:"Recent Sessions",emptyWorkspaces:"No workspace has been imported yet. Import one on the Host side first, and the entry will appear here.",emptySessions:"There is no session to continue in the current workspace yet.",noActivity:"No activity yet"},shell:{hostSwitcherTitle:"Switch HOST",hostSwitcherAriaLabel:"Switch HOST",hostSwitcherSavedSection:"Saved manually",hostSwitcherDiscoveredSection:"Discovered",hostSwitcherCurrentBadge:"Current",hostSwitcherDiscoveredBadge:"Found",hostSwitcherPeerBadge:"Peer",hostSwitcherSwitching:"Switching",hostSwitcherDetailAction:"Details",hostSwitcherDetailAriaLabel:"{name} details",hostSwitcherAddAction:"Add HOST",hostSwitcherAddPeerHostAction:"Add Peer Host",hostSwitcherNameLabel:"HOST name",hostSwitcherNamePlaceholder:"For example: Office HOST",hostSwitcherUrlLabel:"HOST address",hostSwitcherUrlPlaceholder:"For example: http://10.10.1.8:3002",hostSwitcherSaveAction:"Save HOST",hostSwitcherDetailTitle:"HOST details",hostSwitcherPrimaryHostTitle:"Primary HOST",hostSwitcherDetailStatusLabel:"Connection",hostSwitcherDetailStatusDirect:"Direct",hostSwitcherDetailStatusRelay:"Relay",hostSwitcherDetailRouteLabel:"Route",hostSwitcherDetailAddressLabel:"Address",hostSwitcherDetailLatencyLabel:"Latency",hostSwitcherDetailTrafficLabel:"Traffic",hostSwitcherDetailResourceTitle:"Resource usage",hostSwitcherDetailLatencyLoading:"Checking",hostSwitcherDetailUnavailable:"Unavailable",hostSwitcherDetailCpuLabel:"CPU",hostSwitcherDetailCpuValue:"{usage} · {cores} cores",hostSwitcherDetailMemoryLabel:"Memory",hostSwitcherDetailDiskLabel:"Disk",hostSwitcherAliasLabel:"HOST alias",hostSwitcherAliasPlaceholder:"4 English letters",hostSwitcherAliasRule:"Aliases can only use English letters, up to 4.",hostSwitcherAliasInvalid:"Aliases can only use English letters, up to 4.",hostSwitcherAliasSaveAction:"Save alias",hostSwitcherAliasSaveSuccess:"HOST alias saved.",hostSwitcherPeerTitle:"Use as Peer HOST",hostSwitcherPeerSectionTitle:"Peer HOST",hostSwitcherPeerDescription:"Before enabling, the primary HOST checks network reachability, version compatibility, and sign-in. Only then can workspaces use this HOST through the primary HOST.",hostSwitcherPeerStatusLabel:"Peer status",hostSwitcherPeerEnableAction:"Enable Peer",hostSwitcherPeerReconnectAction:"Reconnect",hostSwitcherPeerDisableAction:"Disable Peer",hostSwitcherPeerChecking:"Checking",hostSwitcherPeerPasswordOneTimeHint:"The target HOST password is only used for this enable check and is not saved to the primary HOST.",hostSwitcherPeerLoginRequired:"Enter the target HOST username and password first.",hostSwitcherPeerEnableSuccess:"Peer HOST enabled.",hostSwitcherPeerReconnectSuccess:"Peer HOST reconnected.",hostSwitcherPeerEnableFailed:"Failed to enable Peer HOST.",hostSwitcherPeerReconnectFailed:"Failed to reconnect Peer HOST.",hostSwitcherPeerDisableSuccess:"Peer HOST disabled.",hostSwitcherPeerDisableFailed:"Failed to disable Peer HOST.",hostAddInvalidUrl:"HOST address is invalid.",hostAddDuplicate:"This HOST is already saved.",hostAddIncompleteCredentials:"Username and password must be entered together.",hostAddSuccess:"{name} saved.",hostAddFailed:"Failed to save HOST.",hostDeleteAction:"Delete HOST",hostDeleteAriaLabel:"Delete HOST {name}",hostDeleteConfirmAction:"Confirm delete",hostDeleteBusy:"Deleting",hostDeleteSuccess:"{name} deleted.",hostDeleteFailed:"Failed to delete {name}.",hostSwitchFailed:"Failed to switch HOST.",hostSwitchMissing:"This HOST cannot be found.",hostSwitchUnreachable:"{name} is unreachable.",hostDiscoveryRefreshing:"Looking for LAN HOSTs…",hostDiscoveryFailed:"Failed to discover LAN HOSTs.",manageWorkspaceHostLabel:"HOST used",manageWorkspaceHostSelectLabel:"Choose the HOST for this project",manageWorkspaceHostCurrentOption:"Primary HOST · {alias}",manageWorkspaceHostPeerOption:"Peer HOST · {alias}",manageWorkspaceHostHint:"This project will open through {hostName}.",manageWorkspaceHiddenSectionTitle:"Hidden Projects",manageWorkspaceRemotePathTitle:"Choose the project folder on Peer HOST",manageWorkspaceRemotePathDescription:"No project named “{name}” was found on the Peer HOST. Choose the matching folder on that HOST; it will be registered before switching.",manageWorkspaceRemotePathSubmit:"Use this folder",hostSwitcherPeerWorkspaceDescription:"From {hostName} · {path}",hostSwitcherPeerWorkspaceUnavailableDescription:"{hostName} is unavailable, so this workspace cannot be opened yet.",hostSwitcherPeerUnavailableBadge:"Unavailable",hostSwitcherPeerUnavailable:"{hostName} is unavailable right now.",hostSwitcherPeerVersionMismatchBadge:"Version mismatch",hostSwitcherPeerVersionMismatch:"{hostName} is on a different version and cannot be opened yet.",hostSwitcherPeerUnauthorizedBadge:"Sign-in required",hostSwitcherPeerUnauthorized:"{hostName} needs sign-in before you can open it.",hostSwitcherPeerWorkspaceRouteUnsupported:"This workspace cannot be opened yet.",hostSwitcherPeerWorkspaceRouteUnsupportedDescription:"{hostName}'s workspace is listed now. It will open from here after the proxy API is connected."},terminal:{title:"Terminal",heroTitle:"Keep the real PTY on Host, keep the control surface in the workspace",heroSubtitle:"This page does not fake output and does not mix terminal with process management. It only consumes the real terminal stream managed by Host.",workspaceSection:"Workspace & Terminal",workspaceField:"Current Workspace",shellField:"Shell for New Terminal",runtimeField:"Runtime",runtimeAutoOption:"Auto",runtimeAutoShortLabel:"auto",runtimeAutoDescription:"Use the Host default policy for this terminal runtime.",runtimePersistentLabel:"Persistent Session",runtimePersistentShortLabel:"persist",runtimeTmuxDescription:"Use a persistent external session, ideal for development terminals that should stay alive.",runtimeWindowsPersistentDescription:"Use a Windows persistent session backed by ConPTY so the shell can survive Host restarts.",runtimeEmbeddedDescription:"Managed directly by the current Host and useful as the lightweight fallback.",runtimeConptyPowerShellLabel:"PowerShell Persistent",runtimeConptyCmdLabel:"CMD Persistent",runtimeConptyGitBashLabel:"Git Bash Persistent",runtimeMissingDialogTitle:"tmux is not installed on this system",runtimeMissingDialogDescription:"The tmux runtime cannot create a persistent terminal right now. Install tmux first, or temporarily switch to embedded-pty to continue.",runtimeMissingInstallDescription:"Installing tmux is recommended if you want terminals to survive Host restarts.",runtimeMissingInstallMacArm:"macOS (Apple Silicon / Homebrew): arch -arm64 brew install tmux",runtimeMissingInstallMacIntel:"macOS (Intel Mac / Homebrew): brew install tmux",runtimeMissingInstallDebian:"Ubuntu / Debian: sudo apt install tmux",runtimeMissingInstallFedora:"Fedora: sudo dnf install tmux",runtimeMissingFallbackDescription:"If you switch to embedded-pty now, the terminal can still start, but it will not stay as an external persistent session.",runtimeMissingKeepAction:"Not now",runtimeMissingFallbackAction:"Switch to embedded-pty",runtimeMissingFallbackPending:"Switching...",shellUnavailable:"Unavailable",workspaceLoadFailed:"The workspace or terminal list is not available right now.",terminalSection:"Terminal Instances",templateSection:"Command Templates",stageEmptyTitle:"No terminal selected yet",stageEmptySubtitle:"Create a terminal first, or run a command template.",emptyTerminals:"There is no terminal instance in the current workspace yet.",emptyTemplates:"There is no command template in the current workspace yet.",createButton:"Create Terminal",creating:"Creating terminal...",creationPendingDescription:"Host is starting the real PTY. This pane will take over as soon as the stream is ready.",defaultTerminalName:"Workspace Terminal",created:"The terminal has been created and connected to Host.",createFailed:"Failed to create terminal.",closeButton:"Close Terminal",closing:"Closing terminal...",closed:"The terminal close request has been submitted.",closeCompleted:"Terminal closed.",closePendingDescription:"The close request has been sent to Host. The page stays responsive and keeps syncing the final result in the background.",closeSyncDelayed:"Host is still finishing the close in the background. The list will keep syncing on the next refresh.",closeFailed:"Failed to close terminal.",inputLabel:"Send command to current terminal",inputPlaceholder:"For example: npm test",sendButton:"Send to Terminal",inputFailed:"Failed to send terminal input.",outputEmpty:"The terminal is connected, but there is no output yet.",outputTruncated:"Some output exceeded the cache window while disconnected. Only the retained part has been restored.",connectedHint:"Current output is coming from the real PTY stream on Host.",moreActions:"Terminal Actions",duplicateAction:"Duplicate Tab",duplicateSuccess:"A new terminal tab has been created with the same setup.",duplicateFailed:"Failed to duplicate the terminal tab.",disconnectAction:"Disconnect",disconnected:"Terminal connection has been disconnected.",reconnectAction:"Reconnect",reconnectRequested:"Reconnect request sent.",deleteAction:"Delete",deleting:"Deleting terminal...",deleted:"Terminal record deleted.",deletePendingDescription:"The delete request has been sent to Host. The page stays responsive and keeps syncing the list in the background.",deleteSyncDelayed:"Host is still finishing the delete in the background. The list will keep syncing on the next refresh.",deleteFailed:"Failed to delete the terminal record.",closePendingBadge:"Closing",deletePendingBadge:"Deleting",pinAction:"Pin",unpinAction:"Unpin",zoomLabel:"Terminal Zoom",zoomInAction:"Zoom in terminal display",zoomOutAction:"Zoom out terminal display",zoomResetAction:"Reset terminal zoom",openExternalAction:"Open in Separate Window",openExternalFailed:"Failed to open the detached terminal window.",toolbarToggleAction:"Open terminal tools menu",mobileSwipeHint:"Swipe left or right to switch terminals",mobileSwipePosition:"{current} / {total}",mobileDrawerAction:"Open quick terminal list",mobileDrawerTitle:"Quick Terminals",mobileDrawerDescription:"Swipe right to reveal the list, then tap to jump to another terminal.",mobilePinnedSectionTitle:"Pinned Terminals",mobileDrawerEmptyTitle:"No terminals yet",mobileDrawerEmptyDescription:"Create one first and the quick switcher will appear here.",mobileCreateSheetTitle:"Create Terminal",mobileCreateShellLabel:"Terminal Type",mobileCreateShellDescription:"Pick the shell for this terminal instead of squeezing desktop dropdowns onto mobile.",mobileCreateRuntimeLabel:"Session Type",mobileCreateRuntimeDescription:"Choose whether this terminal should stay persistent or only live in the current runtime.",mobileCreateLoadingShells:"Loading available terminal types for this system...",mobileCreateConfirm:"Create this terminal",createDialogTitle:"Create Terminal",createDialogShellDescription:"Choose the shell for this terminal before creation. On Windows we should not silently fall back to CMD anymore.",createDialogRuntimeDescription:"Choose whether this terminal should stay persistent or only live in the current runtime.",createDialogConfirm:"Create Terminal",mobileRuntimePersistentTitle:"Persistent Session",mobileRuntimePersistentDescription:"Best for development terminals that should stay alive and reconnect as a recoverable session.",mobileRuntimeSessionTitle:"runtime (current session)",mobileRuntimeSessionDescription:"Managed directly by the current Host. Lighter, but not an external persistent session.",mobileWorkspaceSwitcherPlaceholder:"Choose Workspace",mobileEmptyTitle:"No terminal content yet",mobileEmptyDescription:"Create a terminal first, or swipe right to open the quick list and switch to an existing one.",layoutLabel:"Layout",layoutSingleAction:"Single pane",layoutVerticalAction:"Split left and right",layoutHorizontalAction:"Split top and bottom",saveLogAction:"Save Log",saveLogSuccess:"The terminal log has been saved.",saveLogFailed:"Failed to save the terminal log.",logEmpty:"There is no terminal log to save yet.",bindToPaneAction:"Bind to current pane",bindToPrimaryPaneAction:"Bind to main pane",bindToSecondaryPaneAction:"Bind to side pane",panePrimary:"Main Pane",paneSecondary:"Side Pane",splitEmptySubtitle:"Pick a tab or create a terminal first, then bind it to this pane.",statusBadge:{creating:"starting",running:"running",closed:"closed",error:"error"},recoveryComplete:"Recovered to the terminal from before refresh. Key cached output has been restored.",recoveryTruncated:"Recovered to the previous terminal, but some disconnected output exceeded the cache window.",recoveryIdleClosed:"The previous terminal was auto-closed by Host after being idle too long. You are seeing the output kept before close.",reconnect:"Reconnect",liveConnected:"Live stream connected",templateName:"Template Name",templateCommand:"Main Command",templateArgs:"Arguments (space separated)",templateCreateButton:"Save Template",templateCreated:"The command template has been saved.",templateCreateFailed:"Failed to save the command template.",templateRunSent:"The command template has been sent to the current terminal.",templateRunCreatedTerminal:"The command template started in a new terminal.",templateRunFailed:"Failed to run the command template.",connection:{connected:"Connected",reconnecting:"Reconnecting",reconnect_failed:"Reconnect failed",closed:"Closed"}},conversation:{titleFallback:"Continue Conversation",historyLoading:"Loading message history from Host...",historyLoadingOlder:"Loading older messages...",historyLoadFailed:"Message history is not available right now. Try again later.",timelineEmpty:"There are no messages in this session yet. Your first message will go straight into the Host chain.",turnAbortedUser:"The previous turn was stopped by you.",turnAbortedUnexpected:"The previous turn was interrupted unexpectedly and did not finish cleanly.",turnAbortedGeneric:"The previous turn was interrupted before it finished cleanly.",scrollToBottomAction:"Jump to bottom",rawRefLabel:"Source",copyAction:"Copy",copyContentSuccess:"Content copied.",copyContentFailed:"Failed to copy the content.",selectionTodoAction:"Todo",selectionActionButton:"Action",selectionActionSubmit:"Open action child session",selectionActionPromptLabel:"What should it do",selectionActionPromptPlaceholder:"For example: explain this, turn it into notes, or send it to a specific API",selectionActionIncludeContext:"Include current context",selectionActionContextUnavailable:"This selection spans multiple messages, so context inheritance is disabled for safety.",selectionActionDefaultPrompt:"Please process this content.",selectionActionQuotedLabel:"Selected text",selectionActionFailed:"Failed to create the action child session.",actionSessionBadge:"Action",actionInheritedSelectionSummary:'Collapsed the selected text from "{parentTitle}" by default.',forkFromHereAction:"Fork from here",forkingAction:"Forking...",forkMessageSucceeded:"Created a new branch from this message.",forkMessageFailed:"Failed to fork from this message.",forkDraftLabel:"Fork Quote",forkDraftEmpty:"This message does not contain text to quote.",forkDraftClear:"Cancel this fork quote",forkTargetProviderLabel:"Target CLI",forkTargetModelLabel:"Target Model",forkTargetSummary:"Source CLI: {sourceProvider} · Target CLI: {targetProvider}",forkInlineModelLoading:"Loading model options...",forkInlineNativeHint:"Stay on the same CLI and use native fork.",forkInlineCrossHint:"Switched to another CLI. The child session will be reconstructed from text history.",forkSwitchConfirmTitle:"Switch to another CLI?",forkSwitchConfirmDescription:"Using the same CLI keeps the native fork experience. Switching CLI changes this into a cross-provider fork.",forkSwitchConfirmKeepTitle:"Will keep",forkSwitchConfirmKeepBody:"User messages and assistant text before the fork point.",forkSwitchConfirmConvertTitle:"Will convert",forkSwitchConfirmConvertBody:"Reusable text history will be rebuilt into the new CLI session.",forkSwitchConfirmDropTitle:"Will lose",forkSwitchConfirmDropBody:"Tool calls, permission prompts, attachments, and running state.",forkSwitchConfirmAction:"Confirm switch",forkSwitchKeepNative:"Keep native",forkProviderNativeUnsupported:"This provider does not support native fork yet",forkProviderReconstructedUnsupported:"This provider cannot be used as a cross-provider fork target yet",loadMore:"Load More",composerPlaceholder:"State the next step clearly. Let the rest continue inside this session.",sendButton:"Send Message",queueTitle:"Queued Messages",queueDescription:"After the current run finishes, these messages will be processed automatically in order.",queueOrderPrefix:"Queue Position",queueStatusQueued:"Queued",queueStatusFailed:"Dispatch Failed",queueDelete:"Delete",queueDeleting:"Deleting",queueImageOnly:"Image attachments only",sendGuidanceButton:"Add Guidance",queueGuidanceButton:"Queue Guidance",queueSteer:"Steer",queueSteering:"Steering",resendButton:"Resend",quickPhraseTrigger:"Quick Phrases",quickPhraseModalTitle:"Quick Phrases",quickPhraseModalDescription:"Keep the prompts you reuse often in one place and drop them straight into the current composer.",quickPhraseCreateLabel:"New Phrase",quickPhraseOpenCreateAction:"Add Phrase",quickPhraseCreateModalTitle:"Create Quick Phrase",quickPhraseCreateModalDescription:"Save a reusable prompt on its own so it is ready across devices whenever you need it.",quickPhraseCreatePlaceholder:"Write a phrase you want to reuse later.",quickPhraseCreateAction:"Add Phrase",quickPhraseListLabel:"Quick phrase list",quickPhraseEmpty:"There are no quick phrases yet. Add the first one you actually reuse.",quickPhraseOrderLabel:"Item {index}",quickPhraseMoveUp:"Move phrase up",quickPhraseMoveDown:"Move phrase down",quickPhraseDelete:"Delete phrase",quickPhraseSaveFailed:"Failed to save quick phrases. Try again later.",sendingState:"Sending",sentState:"Synced",failedState:"Send failed",contextUsageTitle:"Context Usage",contextUsageUnavailable:"Context usage is not available yet",contextUsageEstimated:"Window is estimated",contextUsageCachedTokens:"{count} cached",contextUsageSourceProviderLog:"window from provider log",contextUsageSourceProviderRuntime:"window from provider runtime",contextUsageSourceProviderConfig:"window from provider config",contextUsageSourceModelMap:"window from model map",headerWorkspace:"Workspace",headerProvider:"Provider",headerCapability:"Capability Summary",connectionConnected:"Connected",connectionReconnecting:"Reconnecting",connectionReconnectFailed:"Reconnect failed",connectionClosed:"Connection closed",runtimeErrorTitle:"Session run failed",runtimeErrorFallbackDetail:"The CLI provider returned an error without additional detail.",runtimeErrorCodeLabel:"Error code",runtimeErrorDetailLabel:"Error detail",permissionRequestSectionTitle:"Pending approvals",permissionRequestSectionDescription:"Provider-side approvals are unified here so you do not need to learn three different dialogs.",permissionRequestToastTitle:"Approval needed",permissionRequestReplyFailed:"Failed to reply to the approval request.",permissionRequestSubmitting:"Submitting...",permissionRequestReasonLabel:"Reason",permissionRequestCommandLabel:"Command",permissionRequestToolLabel:"Tool",permissionRequestCwdLabel:"Working directory",permissionRequestPathsLabel:"Related paths",permissionRequestPermissionsLabel:"Requested permissions",permissionRequestReadLabel:"Read",permissionRequestWriteLabel:"Write",permissionRequestNetworkLabel:"Network",permissionRequestQuestionsLabel:"Questions",permissionRequestDetailLabel:"Details",permissionRequestEmpty:"None",permissionRequestUnknown:"Unknown",permissionRequestKindCommand:"Command",permissionRequestKindFileChange:"File Change",permissionRequestKindPermissions:"Permissions",permissionRequestKindUserInput:"User Input",permissionRequestKindToolCall:"Tool Call",reconnectExplain:"The realtime link is broken. The system is replaying missing messages.",reconnectFailedExplain:"Automatic recovery failed. Retry manually, or reopen the session later.",reconnectExplainWithRoute:"The realtime link is broken. The system is replaying missing messages. Current route: {route}.",reconnectFailedExplainWithRoute:"Automatic recovery failed. Retry manually, or reopen the session later. Current route: {route}.",capabilityDenied:"This action is not supported in the current session.",capabilitySendDisabled:"The current provider does not support sending new messages.",capabilityAttachmentDisabled:"This session does not support attachment input yet.",capabilityInterruptDisabled:"This session does not support interruption.",sidebarTitle:"Current Session Context",sidebarSubtitle:"This sidebar only keeps the minimum capability summary. It does not turn the page into an admin console.",reconnectButton:"Restore Realtime Sync",headerResumedAt:"Last Resumed",headerLastSyncAt:"Last Synced",historyPages:"History Pages",syncStatusIdle:"Sync Idle",syncStatusSyncing:"Syncing",syncStatusError:"Sync Error",capabilityResume:"Resumable",capabilitySend:"Send Enabled",capabilityInterrupt:"Interrupt Enabled",capabilityTools:"Tool Calls",attachmentsLabel:"Attachments",filePanelTitle:"File Manager",filePanelSubtitle:"File capabilities here only serve the current session. This is not a heavy IDE shell.",filePanelNoWorkspace:"There is no selected workspace yet. Browsing or attaching files is unavailable.",filePanelRefresh:"Refresh",filePanelCopyPath:"Copy Path",filePanelCopyAbsolutePath:"Copy Absolute Path",filePanelCopyRelativePath:"Copy Relative Path",filePanelCopyAbsolutePathSuccess:"Absolute path copied.",filePanelCopyRelativePathSuccess:"Relative path copied.",filePanelCopyPathFailed:"Failed to copy the path.",filePanelCopy:"Copy",filePanelCut:"Cut",filePanelPaste:"Paste",filePanelCopySelectionSuccess:"{count} item(s) copied. Paste them into a target folder.",filePanelCutSelectionSuccess:"{count} item(s) cut. Paste them into a target folder.",filePanelPasteSuccess:"{count} item(s) pasted.",filePanelPasteFailed:"Paste failed. Check the target folder and name conflicts.",filePanelSelectionCount:"{count} item(s) selected",filePanelClipboardCopyReady:"{count} item(s) ready to copy",filePanelClipboardCutReady:"{count} item(s) ready to move",filePanelOpenFile:"Open File",filePanelExpandDirectory:"Expand Folder",filePanelCollapseDirectory:"Collapse Folder",filePanelActionsMenu:"File Actions",filePanelSearchPlaceholder:"Enter a file name or path fragment",filePanelSearchButton:"Search",filePanelShowSearch:"Open Search",filePanelHideSearch:"Hide Search",filePanelSearchEmpty:"No matching files found.",filePanelSearchResults:"Search Results",filePanelSearchFailed:"File search failed. Try again later.",filePanelBrowse:"Workspace Files",filePanelCollapseCurrent:"Collapse Current",filePanelCollapseAll:"Collapse All",filePanelBackDirectory:"Go to Parent",filePanelEmptyDirectory:"There are no files to show in this directory.",filePanelRecentTitle:"Recently Opened",filePanelEmptyRecent:"There is no recently opened file yet.",filePanelContextTitle:"Attached Files",filePanelEmptyContexts:"No file is attached to the current session yet.",filePanelEditorTitle:"Preview & Editor",filePanelEditorPlaceholder:"This is a lightweight text editor, not a full IDE.",filePanelSelectHint:"Pick a file first from browse, search, or recent items.",filePanelUnsupported:"This file cannot be edited directly in the sidebar right now.",filePanelAttach:"Attach to Session",filePanelAttached:"Attached",filePanelDetach:"Detach",filePanelSave:"Save",filePanelSaving:"Saving...",filePanelLoadFailed:"Failed to load the file panel.",filePanelOpenFailed:"Failed to open the file.",filePanelSaveSuccess:"File saved.",filePanelSaveFailed:"Failed to save the file.",fileViewerHint:"Opened in {language} mode. Preview and save after editing are supported.",fileViewerModeLabel:"File View Mode",fileViewerPreview:"Preview",fileViewerPresentation:"Presentation",fileViewerCode:"Code",fileViewerEdit:"Edit",fileViewerPlainText:"Plain Text",fileViewerHtml:"HTML",fileViewerImage:"Image",fileViewerPdf:"PDF",fileViewerRefreshPreview:"Refresh",fileViewerRefreshFailed:"Failed to refresh the file preview.",fileViewerExportPdf:"Export PDF",fileViewerExportPdfRunning:"Exporting...",fileViewerExportPdfSuccess:"PDF exported to {path}",fileViewerExportPdfFailed:"Failed to export the PDF.",fileViewerExportPdfTimeout:"PDF export timed out. Try again later.",fileViewerExportPdfMissingHtml:"No HTML content is available for export.",fileViewerExportPptx:"Export PPTX",fileViewerExportPptxRunning:"Exporting...",fileViewerExportPptxSuccess:"PPTX exported to {path}",fileViewerExportPptxFailed:"Failed to export the PPTX.",fileViewerExportPptxMissingHtml:"No HTML content is available for export.",fileViewerExportTaskTimeout:"Export timed out. Try again later.",fileViewerOpenExternal:"Open Externally",fileViewerOpenExternalFailed:"Failed to open the file externally.",fileViewerOpenInWindow:"Separate Window",fileViewerOpenInWindowFailed:"Failed to open the separate window.",fileViewerWindowTitle:"File Preview",fileViewerCollapse:"Collapse Preview",fileViewerExpand:"Expand Preview",fileViewerZoomIn:"Zoom In",fileViewerZoomOut:"Zoom Out",fileViewerFit:"Fit",fileViewerActualSize:"Actual Size",fileViewerFitWidth:"Fit Width",fileViewerPreviousPage:"Previous Page",fileViewerNextPage:"Next Page",fileViewerPageIndicator:"Page {page}",fileViewerSizeLabel:"Viewer Size",fileViewerSizeDefault:"Default",fileViewerSizeWide:"Wide",fileViewerSizeFull:"Full",fileViewerDiffModified:"Modified",fileViewerDiffAdded:"Added Content",fileViewerImageUnavailable:"The image preview is unavailable right now. Try refreshing or opening it externally.",fileViewerPdfUnavailable:"The PDF preview is unavailable right now. Try refreshing or opening it externally.",fileViewerOfficeLoading:"Loading the ONLYOFFICE preview...",fileViewerOfficeUnavailable:"The Office preview is unavailable right now. Check the ONLYOFFICE configuration and service status.",fileViewerOfficeScriptUnavailable:"Failed to load the ONLYOFFICE editor script. Check whether the service URL is reachable.",fileViewerEnterFullscreen:"Full Screen",fileViewerExitFullscreen:"Exit",fileViewerOpenInBrowser:"Open in Browser",fileViewerOpenInBrowserFailed:"Failed to open the browser preview.",fileViewerHtmlPreviewLoading:"Loading the HTML preview...",fileViewerHtmlPreviewUnavailable:"The HTML preview is unavailable right now. Switch to code view instead.",fileViewerHtmlPreviewFailed:"Failed to create the HTML preview link.",fileViewerPresentationBadge:"Static HTML",fileViewerPresentationSummary:"{count} pages detected, canvas {size}",fileViewerPresentationWarningCount:"{count} import warnings detected.",fileViewerPresentationCurrentPage:"Current Page",fileViewerPresentationUntitled:"Untitled Page",fileViewerPresentationReadOnlyHint:"Select a component to view text and layout editing tools.",fileViewerPresentationEditHint:"This pass supports node selection plus basic text and style edits. Complex structures stay read-only.",fileViewerPresentationCanvasSelectHint:"Click a component on the canvas to edit it from the top toolbar, or switch from the component list on the right.",fileViewerPresentationUnsupported:"This HTML file is not ready for presentation view yet.",fileViewerPresentationUnsupportedReason:"Reason: {reason}",fileViewerPresentationSelectNode:"Pick an editable node from the component list on the right first.",fileViewerPresentationAddPage:"Add Page",fileViewerPresentationDuplicatePage:"Duplicate Page",fileViewerPresentationDeletePage:"Delete Page",fileViewerPresentationMovePageUp:"Move Page Up",fileViewerPresentationMovePageDown:"Move Page Down",fileViewerPresentationPageActions:"Page Actions",fileViewerPresentationDragToSort:"Drag to Sort",fileViewerPresentationUndoAction:"Undo Last Action",fileViewerPresentationInspector:"Inspector",fileViewerPresentationComponentList:"Components",fileViewerPresentationEditable:"Editable",fileViewerPresentationReadOnly:"Read Only",fileViewerPresentationTextLabel:"Text Content",fileViewerPresentationTextDescription:"Edit the copy here and the canvas preview updates immediately.",fileViewerPresentationTextToolbar:"Text Toolbar",fileViewerPresentationFontFamilyLabel:"Font Family",fileViewerPresentationFontPresetTitle:"DengXian Light (Headings)",fileViewerPresentationFontPresetSans:"Noto Sans SC",fileViewerPresentationFontPresetSerif:"Serif Body",fileViewerPresentationFontPresetMono:"Monospace",fileViewerPresentationBoldAction:"Bold",fileViewerPresentationItalicAction:"Italic",fileViewerPresentationUnderlineAction:"Underline",fileViewerPresentationFontSizeIncreaseAction:"Increase Font Size",fileViewerPresentationFontSizeDecreaseAction:"Decrease Font Size",fileViewerPresentationLineHeightAuto:"Default Line Spacing",fileViewerPresentationFontSizeLabel:"Font Size",fileViewerPresentationFontWeightLabel:"Font Weight",fileViewerPresentationTextColorLabel:"Text Color",fileViewerPresentationBackgroundColorLabel:"Background Color",fileViewerPresentationTextAlignLabel:"Alignment",fileViewerPresentationLineHeightLabel:"Line Height",fileViewerPresentationPaddingLabel:"Padding",fileViewerPresentationRadiusLabel:"Radius",fileViewerPresentationPositionXLabel:"Position X",fileViewerPresentationPositionYLabel:"Position Y",fileViewerPresentationWidthLabel:"Width",fileViewerPresentationHeightLabel:"Height",fileViewerPresentationDuplicateAction:"Duplicate Selected Node",fileViewerPresentationKeepOriginal:"Keep Original",fileViewerPresentationAlignLeft:"Align Left",fileViewerPresentationAlignCenter:"Align Center",fileViewerPresentationAlignRight:"Align Right",fileViewerPresentationTextMode:"Text",fileViewerPresentationLayoutMode:"Layout",fileViewerPresentationLayoutHint:"This toolbar edits component position and size. Canvas dragging and saving follow the same geometry.",fileViewerPresentationLayoutSelectNode:"Pick a component that supports layout editing first.",fileViewerPresentationLayoutEditable:"Layout Editable",fileViewerPresentationLayoutLocked:"Layout Locked",fileViewerPresentationLayoutUnsupported:"This component is not safe for layout editing yet.",fileViewerPresentationLayoutStrictLocked:"This component is still in flow layout. Convert its container to free layout before dragging it.",fileViewerPresentationLayoutFreezeContainer:"Convert Container to Free Layout",fileViewerPresentationLayoutRootLocked:"Page root containers stay locked in this pass.",fileViewerPresentationLayoutSelectionCount:"{count} components selected",fileViewerPresentationLayoutAlignLeft:"Align Left Edge",fileViewerPresentationLayoutAlignRight:"Align Right Edge",fileViewerPresentationLayoutAlignTop:"Align Top Edge",fileViewerPresentationLayoutAlignBottom:"Align Bottom Edge",fileViewerPresentationResizeHandle:"Resize Component",filePanelAttachSuccess:"The file has been attached to the current session.",filePanelAttachFailed:"Failed to attach the file.",filePanelDetachSuccess:"The file has been detached from the current session.",filePanelDetachFailed:"Failed to detach the file.",filePanelNewFile:"New File",filePanelNewDirectory:"New Directory",filePanelUpload:"Upload File",filePanelDownload:"Download File",filePanelUploadSuccess:"{name} uploaded.",filePanelUploadFailed:"Failed to upload the file.",filePanelDownloadSuccess:"Started downloading {name}.",filePanelDownloadFailed:"Failed to download the file.",filePanelDelete:"Delete",filePanelDeleting:"Deleting...",filePanelDeleteSuccess:"Deleted {name}.",filePanelDeleteConfirmTitle:"Confirm Deletion",filePanelDeleteConfirmDescription:"The selected item will be removed from this workspace immediately and cannot be undone.",filePanelDeleteSelectionConfirm:"Delete the selected {count} items?",filePanelDeleteSelectionSuccess:"Deleted {count} items.",filePanelRenameMove:"Rename / Move",filePanelRenameSuccess:"Renamed to {name}.",filePanelMutateFailed:"File operation failed. Check the path and current state.",filePanelCreateFilePrompt:"Enter the relative path of the file to create",filePanelCreateDirectoryPrompt:"Enter the relative path of the directory to create",filePanelCreateFileDescription:"Enter a relative path inside the workspace. The file will be created immediately.",filePanelCreateDirectoryDescription:"Enter a relative path inside the workspace. The folder will be created immediately.",filePanelPathFieldLabel:"Relative Path",filePanelPathFieldPlaceholder:"For example: src/features/files/index.ts",filePanelCreateFileSubmit:"Create File",filePanelCreateDirectorySubmit:"Create Folder",filePanelCreatingFile:"Creating file...",filePanelCreatingDirectory:"Creating folder...",exportAction:"Export Session",exportDialogTitle:"Export Current Session",exportDialogDescription:"Export the full session as Markdown, or print the current message layout and save it as PDF.",exportMarkdownAction:"Export Markdown",exportMarkdownHint:"Exports the full message content for editing, archiving, or commit history.",exportPdfAction:"Export PDF",exportPdfHint:"Downloads a PDF file directly and keeps the current conversation content layout.",exportHtmlAction:"Export HTML",exportPreparing:"Preparing the export content...",exportMarkdownSuccess:"The Markdown export has started.",exportPdfPreparing:"The PDF download has started.",exportHtmlSuccess:"The HTML export has started.",exportLoadFailed:"Export failed because the full session content could not be loaded.",exportDownloadFailed:"Failed to export the file.",exportPrintFailed:"Failed to open the print dialog.",exportPrintContainerTitle:"Session Export",exportMarkdownSessionIdLabel:"Session ID",exportMarkdownProviderLabel:"Provider",exportMarkdownWorkspaceLabel:"Workspace ID",exportMarkdownCreatedAtLabel:"Created At",exportMarkdownExportedAtLabel:"Exported At",exportMarkdownTimeLabel:"Time",exportMarkdownTypeLabel:"Type",exportMarkdownAttachmentsLabel:"Attachment Count",exportMarkdownAttachmentsSectionTitle:"Attachments",exportMarkdownToolSectionTitle:"Tool Call",exportMarkdownToolNameLabel:"Tool Name",exportMarkdownToolStatusLabel:"Status",exportMarkdownToolInputLabel:"Input",exportMarkdownToolOutputLabel:"Output",exportMarkdownToolErrorLabel:"Error",exportMarkdownToolCallType:"Tool Call",exportMarkdownToolResultType:"Tool Result",exportMarkdownTextType:"Text",exportMarkdownUnknownSize:"Unknown Size",filePanelFilterChanges:"Changes Only",filePanelShowAll:"Show All",filePanelNoChanges:"No changed files.",filePanelBinaryPreview:"Binary files cannot be previewed.",filePanelDeleteFileConfirm:"Delete this file? {path}",filePanelDeleteDirectoryConfirm:"Delete this folder? {path}",filePanelRenameMovePrompt:"Enter the new relative path",filePanelRenameDescription:"Only the path changes. Use a new relative path if you also want to move it.",filePanelRenameSubmit:"Confirm Rename",filePanelRenaming:"Renaming...",unavailableAction:"Unavailable",roleUser:"User",roleAssistant:"Assistant",roleTool:"Tool",toolViewImageActiveLabel:"AI is viewing an image",assistantCapabilityBadgeSubAgent:"Sub-agent",codexAgentToolCreateTitle:"Create Sub-agent",codexAgentToolReadTitle:"Read Sub-agent",codexAgentToolUpdateTitle:"Update Sub-agent",codexAgentToolReplyTitle:"Reply to Sub-agent",codexAgentToolCloseTitle:"Close Sub-agent",codexAgentToolCreateSummary:"A separate task was delegated to a sub-agent.",codexAgentToolReadSummary:"Reading the latest sub-agent status and response.",codexAgentToolUpdateSummary:"The sub-agent task was redirected or updated.",codexAgentToolReplySummary:"A follow-up message was sent to the sub-agent.",codexAgentToolCloseSummary:"This sub-agent session was closed.",codexAgentToolLabelAgent:"Agent",codexAgentToolLabelNickname:"Nickname",codexAgentToolLabelRole:"Type",codexAgentToolLabelModel:"Model",codexAgentToolLabelTargets:"Targets",codexAgentToolLabelTimeout:"Wait",codexAgentToolLabelMessage:"Message",codexAgentToolLabelReason:"Result",subagentNotificationTitle:"Sub-agent Report",subagentNotificationSummary:"The sub-agent returned the task result.",subagentNotificationLabelSummary:"Summary",subagentNotificationStatusCancelled:"Cancelled",roleSystem:"System"},git:{title:"Git Context",subtitle:"This is the session-side support area. It only handles Git facts inside the current workspace.",loading:"Loading Git context for the current workspace...",refresh:"Refresh",panelLoadFailed:"Git context is not available right now.",uninitializedTitle:"Git is not enabled in this folder yet",uninitializedDescription:"Initialize a Git workspace here first, then you can review changes, commit, and browse history.",initRepository:"Initialize Git Workspace",initInProgress:"Initializing...",initSuccess:"The Git workspace has been initialized.",initFailed:"Failed to initialize the Git workspace.",ahead:"Ahead",behind:"Behind",dirty:"Dirty",clean:"Clean",changeCount:"{count} changed files in the current workspace",noChanges:"There are no pending changes right now.",changesTitle:"Current Changes",rulesFirstHint:"Rules come first. Drafts must not bypass validation.",stage:"Stage",unstage:"Unstage",preview:"Preview",stageFailed:"Stage operation failed.",diffTitle:"Diff Preview",diffLoadFailed:"Diff content is not available right now.",binaryDiff:"This file is a binary change. The sidebar does not render its content directly.",stagedDiff:"Staged diff",worktreeDiff:"Working tree diff",emptyDiff:"There is no text diff to display right now.",diffTruncated:"The diff is too long and has been truncated for safety.",commitTitle:"Commit Draft",defaultRuleName:"Default Commit Rule",language:"Language",maxLength:"Max Length",bodyRequired:"Body Required",bodyOptional:"Body Optional",issueRequired:"Issue Required",issueOptional:"Issue Optional",commitSubject:"Commit Subject",commitSubjectPlaceholder:"Enter the commit message here",commitBody:"Commit Body",commitBodyPlaceholder:"Explain the change clearly. Do not write empty words.",commitFooter:"Commit Footer",commitFooterPlaceholder:"For example: Refs: #123",generateDraft:"AI Draft",validate:"Validate Draft",commit:"Commit",draftFailed:"Failed to generate the commit draft.",validateFailed:"Commit rule validation failed.",commitFailed:"Commit failed.",commitSuccess:"The commit has been written to the current repository.",validationPassed:"Rule validation passed. You can continue to commit.",validationFailed:"Rule validation failed. Fix the issues below first.",branchTitle:"Branch",branchPlaceholder:"Enter the branch name to switch to or create",switchBranch:"Switch",createBranch:"Create",branchFailed:"Branch operation failed.",historyTitle:"Recent History",historyHint:"Only keep the latest few entries here. This is not a graphical history tree.",noHistory:"There is no commit history to show right now.",viewAllVersions:"View All Versions",viewAllVersionsDescription:"Loaded commit history for the current repository. Total entries: {count}.",viewCommitChanges:"View Changed Files and DIFF",copyCommitMessage:"Copy Commit Message",copyCommitMessageSuccess:"The commit message has been copied.",copyCommitVersion:"Copy Git Version",copyCommitVersionSuccess:"The Git version has been copied.",commitDetailTitle:"Commit Detail",commitDetailDescription:"Showing the full change for commit {hash}.",commitDetailLoading:"Loading commit detail...",commitDetailEmpty:"There is no commit detail to show right now.",commitDetailLoadFailed:"The commit detail is not available right now.",commitVersionLabel:"Git Version",commitHashLabel:"Commit Hash",commitAuthorLabel:"Author",commitTimeLabel:"Commit Time",commitMessageLabel:"Commit Message",changedFilesTitle:"Changed Files",commitDiffLabel:"Commit DIFF",renamedFromLabel:"Renamed from {path}",explainCommitTitle:"Explain Commit Change",explainCommitDescription:"Choose a CLI provider first, then start a new session to analyze this commit.",explainCommitAction:"Explain Change",startExplainCommit:"Start Explaining",explainCommitStarted:"The explanation session has been created.",explainCommitFailed:"Failed to explain the commit change.",remoteTitle:"Remote Sync",remoteReady:"A remote is configured for the current repository.",remoteMissing:"The current repository has no remote configured yet.",fetch:"Fetch",pull:"Pull",push:"Push",pushNow:"Push Now",publish:"Publish",remoteFailed:"Remote sync failed.",remoteAuthAction:"Remote Auth",remoteAuthTitle:"Configure Remote Authentication",remoteAuthDescription:"Enter the username, password, or token to use for authenticated remote operations in this page session.",remoteAuthDescriptionGithub:"The current remote points to GitHub. For GitHub HTTPS Git operations, use a Personal Access Token (PAT) instead of your GitHub login password.",remoteAuthStatusLabel:"Authentication",remoteAuthManageHint:"Review and configure per remote",remoteAuthManageTitle:"Manage Remote Authentication",remoteAuthManageDescription:"Each remote repository shows its own credential status and should be configured separately here.",remoteAuthConfigured:"Configured",remoteAuthConfiguredInSession:"Configured In Session",remoteAuthConfiguredOnHost:"Saved On Host",remoteAuthNotConfigured:"Not Configured",remoteAuthGithubPatLabel:"Personal Access Token (PAT)",remoteAuthGithubPatPlaceholder:"Enter GitHub PAT",remoteAuthGithubUsernamePlaceholder:"Enter GitHub username",remoteAuthGithubPatHint:"GitHub does not support account passwords for Git HTTPS authentication. In basic mode, enter GitHub username + PAT. In token mode, you can paste the PAT directly.",remoteAuthRemember:"Remember On Host",remoteAuthSessionHint:"By default this only applies to the current page session. If you enable “Remember On Host”, the credential will be stored on the Host after a successful remote sync and reused later.",remoteAuthRememberHint:"When remember is enabled, this credential will be written to the Host after the remote sync succeeds.",remoteAuthSave:"Save Auth",remoteAuthSaved:"Remote authentication saved. Retry the remote sync now.",remoteAuthCleared:"Remote authentication for this page session has been cleared.",selectRemoteTitle:"Select Remote to Push",selectRemoteDesc:"Select remote repositories to push to. Multiple selection supported.",noRemotes:"No remote repositories are configured.",pushSelected:"Push ({count})",pushing:"Pushing…",pushAllSuccess:"Successfully pushed to {count} remote(s).",errors:{unauthorized:"The current login is no longer valid. Log in again and retry.",workspaceNotFound:"The workspace bound to the current session does not exist. Check whether it is still available.",invalidWorkspace:"The current workspace config is invalid. The Git sidebar must not operate outside the repo root.",notGitRepository:"The current workspace is not a Git repository. The Git sidebar will not fake a state.",repoNotFound:"No usable Git repository root was found for the current workspace.",pathOutOfWorkspace:"The Git target is outside the current workspace repository boundary. The operation was blocked.",invalidTarget:"The Git target path is invalid. Refresh the sidebar and try again.",notStaged:"The target file is not staged yet. Check the current change state first.",emptyStagedChanges:"The staging area is empty. Stage the changes before committing.",branchConflict:"The current branch has conflicts or is not a fast-forward update. Sync and resolve differences first.",branchNotFound:"The target branch does not exist. Check the branch name first.",remoteNotFound:"The current repository does not have a usable origin remote yet.",remoteAuthFailed:"Remote repository authentication failed. Check the current credentials first.",pushFailed:"Push failed. Check remote state and local commits first.",pullFailed:"Pull failed. Check the remote branch state first.",remoteFailed:"Remote sync failed. Check Git output and network state.",initFailed:"Failed to initialize the Git workspace. Make sure the directory is writable and Git is available.",commitValidationFailed:"The commit draft has not passed validation yet. Fix validation issues first.",commandTimeout:"The Git operation timed out. Check repository state and network conditions."}},theme:{light:"浅色",dark:"深色",skyBlue:"赛博",eyeGreen:"护眼",switchLabel:"Theme"},locale:{zhCN:"Simplified Chinese",enUS:"English"}},fm={common:{appName:"CodingNS",loading:"正在准备会话工作区…",retry:"重新尝试",back:"返回",save:"保存",close:"关闭",cancel:"取消",connectionRouteRelay:"CodingNS Connect",connectionRouteLan:"局域网直连",connectionRouteLoopback:"本机直连",connectionRouteTailscale:"Tailscale 直连",connectionRouteDirect:"直接连接",logout:"退出登录",unknown:"未命名会话"},auth:{loginTitle:"继续你的编码会话",loginSubtitle:"INITIALIZING DEVELOPMENT ENVIRONMENT...",serverPreset:"服务器列表",serverCustomOption:"使用自定义服务器",serverAddress:"服务器地址",serverPlaceholder:"例如:http://127.0.0.1:3002",serverHint:"登录、实时消息和终端都会连接到这里。客户端应填写 Host API 地址,例如 http://127.0.0.1:3002;4174、5173 这类前端开发端口不是给正式客户端直接连接的,只有代理和跨域都配好时才适合临时调试。",serverInvalid:"服务器地址无效,请检查后再试。",serverDiscoveredTag:"自动发现",serverCurrent:"当前服务器",bootstrapTitle:"先完成首次初始化",bootstrapSubtitle:"这个 Host 还没有管理员账号,先创建一个最小登录入口。",username:"用户名",password:"密码",rememberPassword:"保存密码",confirmPassword:"确认密码",submitLogin:"进入工作台",submitBootstrap:"创建管理员账号",bootstrapSuccess:"初始化完成,现在可以登录了。",bootstrapMismatch:"两次输入的密码不一致。",authUnavailable:"暂时连不上 Host,请确认服务可访问。",logoutSuccess:"当前登录态已经清空。",demoBanner:"演示环境 — 所有账号数据公开可见,注销后自动清除",demoSessionExpired:"演示会话已过期,请重新登录",captcha:"图形验证码",captchaPlaceholder:"输入图中的字符",captchaHint:"连续输错三次后,需要先完成图形验证码才能继续登录。",captchaImageAlt:"登录图形验证码",serverSettings:"服务器设置",serverSettingsTitle:"服务器配置",saveServerSettings:"保存设置",relayEntryTitle:"正在连接远程 Host",relayEntryDescription:"正在切换到这台 Host 的可信连接入口,完成后会自动回到登录页。",relayEntryInvalid:"当前远程访问入口参数不完整,请重新打开访问地址。",trustedEntryOnlyTitle:"请通过远程访问地址进入",trustedEntryOnlyDescription:"这个可信前端站点只负责加载连接页面,不直接承载 Host API。请重新打开设备的远程访问地址。",trustedEntryOnlyHintTitle:"如何进入",trustedEntryOnlyHint:"请使用类似 https://xxxx.channel.codingns.com:1443 的远程访问地址进入;四级域名会自动把你带到正确的连接入口。"},plugins:{listTitle:"插件",listDescription:"这里统一查看当前工作区可用的插件,并决定要不要继续打开或停用。",loading:"正在读取插件列表…",listLoadFailed:"插件列表加载失败。",emptyTitle:"当前还没有可用插件",emptyDescription:"等 Host 扫描到合法插件后,这里会自动出现。",enabled:"已启用",disabled:"已停用",frontendTag:"前端",backendTag:"动作",detailLoadFailed:"插件详情加载失败。",detailMissingTitle:"没找到这个插件",detailMissingDescription:"可能是插件目录被移除了,或者当前 Host 还没重新扫描到它。",backToList:"返回插件列表",backToDetail:"返回插件详情",summaryTitle:"基本信息",summaryDescription:"先确认这个插件是谁、装在哪里、现在能不能用。",pluginIdLabel:"插件标识",installRootLabel:"安装目录",runtimeLabel:"运行方式",frontendOnly:"只有前端页面,没有后端动作",permissionTitle:"权限边界",permissionDescription:"这里只显示插件明确声明过的权限。没声明的能力默认不放开。",workspaceReadAllowed:"可读取当前工作区",workspaceReadDenied:"未声明工作区读取权限",networkAllowed:"允许联网",networkDenied:"默认不联网",noDesktopPermission:"没有桌面权限",actionTitle:"可调用动作",actionDescription:"这些动作都走统一插件网关,不会私长命令入口。",runHistoryTitle:"最近运行记录",runHistoryDescription:"这里先看最近 10 条,方便排查动作有没有跑起来。",runHistoryEmptyTitle:"还没有运行记录",runHistoryEmptyDescription:"等你第一次运行插件动作后,这里会出现正式记录。",unknownAction:"未知动作",openPlugin:"打开插件",enableAction:"启用插件",disableAction:"停用插件",permissionNameReadFile:"读取文件",permissionNameListDirectory:"查看目录内容",permissionNameWriteFile:"写入文件",permissionNameOpenFile:"在桌面里打开文件",permissionNameRevealInFileManager:"在文件管理器里显示文件",permissionScopeWorkspace:"整个当前工作区",permissionScopeDirectory:"目录:{scopePath}",permissionScopeFile:"文件:{scopePath}",permissionScopeUnknown:"目标范围未明确",permissionGrantModeOnce:"仅这一次",permissionGrantModeSession:"本次打开期间",permissionGrantModePersistent:"长期保留",permissionPromptTitle:"插件需要你先授权",permissionPromptDescription:"先确认这次要放开什么能力,再决定给多久、放到哪里为止。",permissionPromptSummaryTitle:"这次申请什么权限",permissionPromptSummaryDescription:"{pluginName} 这次请求了受控能力,没点同意前不会继续执行。",permissionPromptPermissionLabel:"申请能力",permissionPromptTargetLabel:"作用范围",permissionPromptPendingTag:"待你确认",permissionPromptOptionsTitle:"你可以怎么放权",permissionPromptOptionsDescription:"先给最小范围,别一上来就放大。",permissionPromptOptionOnce:"只放行这一个目标",permissionPromptOptionOnceDescription:"只允许这次请求继续,后面再用时还会重新问你。",permissionPromptOptionSession:"当前打开期间都允许",permissionPromptOptionSessionDescription:"只在这次插件页面打开期间有效,关掉后自动失效。",permissionPromptOptionDirectory:"长期允许这个目录",permissionPromptOptionDirectoryDescription:"后续访问 {scopePath} 和它下面的内容时,不用每次再确认。",permissionPromptDenyAction:"先不授权",permissionPromptNoOptionTitle:"这次没有可用授权方式",permissionPromptNoOptionDescription:"当前请求缺少可放权范围,先返回插件详情再看。",grantedPermissionTitle:"当前工作区已授权内容",grantedPermissionDescription:"这里只看这个工作区已经放开的能力,方便你随时收回。",grantedPermissionEmptyTitle:"当前还没有授权记录",grantedPermissionEmptyDescription:"等插件第一次申请并被你同意后,这里会出现正式授权记录。",permissionGrantLoading:"正在读取授权记录…",permissionGrantLoadFailed:"插件授权记录加载失败。",revokeGrantAction:"撤销授权",revokeGrantSuccess:"插件授权已撤销。",revokeGrantFailed:"撤销插件授权失败。",permissionAuditTitle:"最近授权相关记录",permissionAuditDescription:"这里会记录授权、拒绝和撤销,方便回头排查是谁放开的。",permissionAuditEmptyTitle:"还没有授权相关记录",permissionAuditEmptyDescription:"等出现授权、拒绝或撤销后,这里会自动显示。",permissionEventGranted:"已授权:{permission}",permissionEventRevoked:"已撤销:{permission}",permissionEventDenied:"已拒绝:{permission}",permissionEventUnknown:"未知权限",permissionEventReasonDeclarationMissing:"插件没声明,直接拒绝",permissionEventReasonGrantRequired:"需要你先授权",enableSuccess:"插件已启用。",disableSuccess:"插件已停用。",saveFailed:"插件状态保存失败。",disabledByUserReason:"由用户在插件详情页停用",containerDescription:"插件前端运行在独立容器里,不会直接拿到宿主桌面桥。",containerLoadFailed:"插件运行页加载失败。",containerMissingTitle:"当前插件没有可运行页面",containerMissingDescription:"这个插件可能只有后端动作,或者已经被停用。"},settings:{title:"设置",appearance:"外观",appearanceSectionSummary:"语言、主题与界面配色",language:"语言",languageDescription:"选择界面显示语言,切换后立即应用到当前页面。",theme:"主题",themeDescription:"选择适合你的界面配色方案",autoTheme:"自动跟随系统主题",autoThemeDescription:"开启后根据系统或浏览器的深浅色偏好自动切换日间和夜间模式。",fileManager:"文件管理",workspaceSessionSortMode:"工作区的会话显示排序方式",teableEntryTitle:"Teable 表单",teableEntryDescription:"统一管理 Teable 连接,以及 CodingNS 数据同步到 Teable 表的方式。",teableOpenSettingsAction:"打开设置",teableModalTitle:"Teable 表单设置",teableModalDescription:"这里统一管理 Teable 连接、需要同步的表,以及 CodingNS 数据和 Teable 字段的对应关系。",teableTabConnection:"连接",teableTabForms:"表单",teableTabMirrors:"镜像",teableTabFieldMappings:"字段映射",teableTabConnectionSettings:"连接设置",teableTabFormSettings:"表单设置",teableTabTableSyncSettings:"表同步设置",teableTabSyncLogs:"同步日志",teableTestConnectionAction:"测试连接",teableConnectionTestSuccess:"连接可用,已读取 {tableCount} 张表。",teableLoadFailed:"Teable 设置加载失败。",teableStatusUnknown:"暂未读取到状态",teableStatusIdleHint:"还没有发起过镜像同步。",teableStatusBindingLabel:"连接状态",teableStatusSourceLabel:"已开启数据源",teableStatusSourceDetail:"当前有 {count} 类数据会推送到 Teable。",teableStatusMirrorLabel:"镜像表",teableStatusMirrorDetail:"当前已经记录 {count} 张镜像表绑定。",teableStatusTaskLabel:"最近同步",teableBindingSectionTitle:"连接设置",teableBindingSectionDescription:"先把 Teable 站点、空间、Base 和访问 Token 填对,再决定是否启用。",teableEnabledLabel:"启用 Teable 同步",teableBaseUrlLabel:"Teable 站点地址",teableBaseUrlDescription:"支持 http:// 和 https://。如果 Teable 跟 Host 在同一局域网,可以直接填 http 地址。",teableBaseUrlPlaceholder:"例如:http://192.168.1.20:3000",teableSpaceIdLabel:"Space ID",teableSpaceIdPlaceholder:"填写要绑定的 Space ID",teableBaseIdLabel:"Base ID",teableBaseIdPlaceholder:"填写目标 Base ID",teableAuthRefLabel:"认证引用",teableAuthRefPlaceholder:"例如:secret://teable/main",teableAuthTokenLabel:"访问 Token",teableAuthTokenDescription:"如果已经在 Host 里保存过 token,这里可以留空不改。",teableAuthTokenPlaceholder:"留空表示继续使用已保存 token",teableMirrorModeLabel:"同步方式",teableBindingSaved:"Teable 连接设置已保存。",teableSyncConfigSectionTitle:"工作台推送范围",teableSyncConfigSectionDescription:"这里决定标签、会话和代办哪些会同步到 Teable,以及各自落到哪张表。",teableSyncEnabledLabel:"允许同步这一类数据",teableTargetTableLabel:"目标表",teableTargetTablePlaceholder:"请选择 Teable 已有表",teableTagRootsLabel:"同步哪些标签树",teableSessionScopeModeLabel:"会话同步范围",teableSessionScopeAll:"同步全部工作区会话",teableSessionScopeSelected:"只同步选中的工作区会话",teableWorkspaceMultiSelectLabel:"选择工作区",teableTodoSourceLabel:"代办来源",teableTodoWorkspaceSource:"同步工作区代办",teableTodoAffairsSource:"同步事务代办",teableTodoWorkspaceHint:"如果这里选了工作区,只同步这些工作区里的代办;留空表示不按工作区额外筛选。",teableTargetTableIdLabel:"目标表 ID",teableTargetTableHint:"不填时,Host 会按默认镜像表名自动创建。",teableTargetTableBoundHint:"当前已经绑定到表“{table}”。",teableTargetTableIdPlaceholder:"可选,填已有表 ID 直接复用",teableScopeJsonLabel:"同步范围(JSON)",teableScopeJsonPlaceholder:"这里填这一类数据的同步范围 JSON。",teableScopeJsonInvalid:"同步范围必须是合法 JSON 对象。",teableSyncConfigSaved:"Teable 推送范围已保存。",teableFormsCatalogTitle:"Teable 已有表单",teableFormsCatalogDescription:"这里列出 Teable 里已经存在的表单视图。",teableFormsCatalogEmptyTitle:"还没有可用表单",teableFormsCatalogEmptyDescription:"先到 Teable 里创建表单视图。",teableFormSettingsLeftTitle:"已废弃的表单设置",teableFormSettingsLeftDescription:"设置页不再按表单配置同步,镜像同步只按 Teable 表配置。",teableFormMappingPanelTitle:"已废弃的同步内容设置",teableFormMappingPanelDescription:"设置页不再按表单配置同步,镜像同步只按 Teable 表配置。",teableAddSyncFormAction:"添加同步表单",teableRemoveSyncFormAction:"移除",teableSyncFormAddedTag:"已添加",teableSyncFormAdded:"同步表单已添加。",teableSyncFormRemoved:"同步表单已移除。",teableFormShareReady:"已开启分享",teableFormShareMissing:"未开启分享",teableSelectSyncFormTitle:"先选择一个表单",teableSelectSyncFormDescription:"左侧选择 Teable 表单后,这里会显示同步内容、工作区范围和字段映射。",teableSelectedFormLabel:"当前表单",teableSyncSourceLabel:"同步的信息",teableSyncSource:{sessions:"会话记录",todos:"代办",tags:"文档库标签"},teableWorkspaceScopeLabel:"工作区范围",teableWorkspaceScopeAll:"全部工作区",teableWorkspaceScopeSelected:"指定工作区",teableWorkspaceScopeEmpty:"还没有可选工作区。",teableDocumentTagRootsLabel:"文档库根标签",teableDocumentTagRootsDescription:"只同步选中根标签及其所有子标签;这不是工作区表单绑定。",teableDocumentTagRootsEmpty:"还没有可选的文档库根标签。",teableFieldMappingTitle:"字段映射",teableFieldMappingInlineDescription:"左边是 CodingNS 字段,右边选择 Teable 表里的目标字段。",teableSourceFieldsEmpty:"当前同步内容没有可映射字段。",teableSaveFormSyncSettingsAction:"保存表同步设置",teableFormSyncSettingsSaved:"表同步设置已保存。",teableTableSyncAvailableTitle:"Teable 表目录",teableTableSyncAvailableDescription:"这里不列出表单,只选择当前 Base 下已有的表。选中一张表后点添加,它会进入左侧同步表列表。",teableTableSyncListTitle:"同步表列表",teableTableSyncListDescription:"这里显示已经添加为镜像同步目标的表。选中一张表后,在右侧配置同步内容、范围和字段映射。",teableTableSyncConfigTitle:"当前表配置",teableTableSyncConfigDescription:"这里只配置左侧选中的同步表,不再堆积同步表记录。",teableTableToAddLabel:"选择要添加的表",teableAllTablesAdded:"所有表都已添加",teableAddSyncTableAction:"添加同步表",teableRemoveSyncTableAction:"移除",teableSyncTableAddedTag:"已添加",teableSelectSyncTableTitle:"先添加一张同步表",teableSelectSyncTableDescription:"从左侧 Teable 表目录里添加表后,这里会显示同步内容、工作区范围和字段映射。",teableSelectedSyncTableLabel:"当前同步表",teableTableAssignedDescription:"已配置为同步 {source}",teableTableUnassignedDescription:"还没有配置同步内容",teableSaveTableSyncSettingsAction:"保存表同步设置",teableTableSyncSettingsSaved:"表同步设置已保存。",teableFieldAutoCreateAction:"添加字段并自动映射",teableFieldAutoCreateModalTitle:"添加 Teable 字段",teableFieldAutoCreateModalDescription:"选择要添加到当前 Teable 表的 CodingNS 字段。",teableFieldAutoCreateModalSectionTitle:"选择字段",teableFieldAutoCreateModalSectionDescription:"这些字段会添加到“{table}”,并自动写入字段映射。已经存在同名字段时会直接复用。",teableFieldAutoCreateConfirmAction:"添加并自动映射",teableFieldAutoCreateSuccess:"已添加并映射 {count} 个字段。",teableFieldAutoCreateEmptyError:"请先选择要添加的字段。",teableFieldAlreadyMappedDescription:"已映射到“{field}”。",teableTablesCatalogTitle:"Teable 已有表",teableTablesCatalogDescription:"这里列出当前 Base 下已有的表,方便你给镜像同步和字段映射选目标表。",teableTablesCatalogEmptyTitle:"当前 Base 里还没有可用表",teableTablesCatalogEmptyDescription:"先到 Teable 里创建表,再回来配置同步。",teableTableInspectAction:"查看表结构",teableTableCollapseAction:"收起详情",teableTableFieldsLabel:"当前表字段",teableTableFieldsEmpty:"这张表暂时还没有字段。",teableTableFormViewsLabel:"这张表下的表单视图",teableTableFormViewsEmpty:"这张表当前还没有表单视图。",teableTableFormReadyTag:"可用于工作台",teableTableFormShareMissingTag:"未开启分享",teableTableFormCountTag:"{count} 个表单",teableTableFieldCountPending:"字段数待读取",teableTableFieldCountValue:"{count} 个字段",teableTableFormCountValue:"{count} 个表单视图",teableTablesUsageTitle:"这里主要做什么",teableTablesUsageDescription:"设置页负责配同步和字段映射;工作台里的 Teable 块才负责显示表单。",teableTablesUsageMirrorTitle:"同步配置看表",teableTablesUsageMirrorDescription:"标签、会话、代办同步到哪张 Teable 表,都是在这里按表来配。",teableTablesUsageFormTitle:"工作台块看表单",teableTablesUsageFormDescription:"真正要显示给用户填写的表单,会在工作台画布里的 Teable 块中选择。",teableSyncActionSectionTitle:"同步状态与操作",teableSyncActionSectionDescription:"这里看最近一次任务结果,也可以手动重新发起镜像同步。",teableLatestTaskTitle:"最近一次镜像同步",teableLatestTaskEmpty:"还没有镜像同步记录。",teableSyncLogsTitle:"同步日志",teableSyncLogsDescription:"这里记录手动同步和本地变化触发的同步任务,方便确认数据是否已经推送到 Teable。",teableSyncLogsRefreshAction:"刷新日志",teableSyncLogsEmptyTitle:"还没有同步日志",teableSyncLogsEmptyDescription:"手动同步或本地数据变化触发同步后,这里会显示记录。",teableSyncLogDescription:"{trigger} · {source} · {time}",teableSyncLogCounts:"新增 {created},更新 {updated},删除 {deleted},跳过 {skipped}",teableSyncLogTrigger:{manual:"手动触发",local_change:"本地变化",retry:"重试"},teableFieldMappingSectionTitle:"字段映射",teableFieldMappingSectionDescription:"把 CodingNS 的源字段手动对应到 Teable 目标表字段。同步时只会按这里的关系写入。",teableFieldMappingTargetMissingTitle:"先给这一类数据选择目标表",teableFieldMappingTargetMissingDescription:"先在“镜像”标签页为这类数据指定目标表,再回来做字段映射。",teableFieldMappingSaveAction:"保存字段映射",teableFieldMappingSaved:"字段映射已保存。",teableFieldTargetPlaceholder:"请选择目标字段",teableFieldRequired:"必填",teableFieldOptional:"可选",teableMirrorBindingReady:"镜像表已绑定到“{table}”。",teableMirrorBindingMissing:"这类数据还没有生成镜像表。",teableMirrorBindingReadyTag:"已绑定",teableMirrorBindingPendingTag:"待创建",teableRefreshAction:"刷新状态",teableSaveBindingAction:"保存连接",teableSaveSyncConfigAction:"保存推送范围",teableSyncNowAction:"立即同步",teableBindingStatus:{unbound:"未绑定",ready:"已就绪",disabled:"已关闭",config_invalid:"配置不完整"},teableTaskState:{idle:"未开始",queued:"排队中",running:"同步中",succeeded:"已完成",partial_failed:"部分失败",failed:"失败"},teableMirrorMode:{manual:"手动触发",scheduled:"定时同步(暂未开放)",event_driven:"本地变化自动同步"},teableSource:{tags:{title:"标签镜像",description:"把事务标签同步成 Teable 镜像表,给业务表单做 Link / Lookup 引用。",scopeHint:"例如 includePaths、手动筛选路径。当前后端先保存配置,不在这一轮强解释。"},sessions:{title:"会话镜像",description:"把事务会话摘要同步到 Teable,方便表单引用最近会话和上下文。",scopeHint:"例如 recent / limit 这类范围控制。当前后端先保存配置,不在这一轮强解释。"},todos:{title:"代办镜像",description:"把工作台代办同步到 Teable,方便表单直接引用当前任务。",scopeHint:"例如 open_only、状态筛选。当前后端先保存配置,不在这一轮强解释。"}},pluginManagement:"插件管理",pluginManagementDescription:"统一查看当前 Host 已扫描到的插件,并决定是否启用、停用或继续打开插件页面。",pluginManagementAction:"管理插件",pluginManagementModalTitle:"插件管理",pluginManagementModalDescription:"这里集中查看插件状态、权限边界和最近运行记录,不需要再手动拼路由。",pluginManagementModalListTitle:"插件列表",pluginManagementModalListDescription:"先选一个插件,再看它现在的状态和最近运行情况。",pluginManagementModalDetailTitle:"插件详情",pluginManagementModalDetailDescription:"这里只展示已经通过 Host 正式注册的插件信息和运行记录。",pluginManagementSelectPluginTitle:"先选一个插件",pluginManagementSelectPluginDescription:"左边选中插件后,这里会显示它的权限、动作和最近运行记录。",pluginManagementWorkspaceRequired:"只有绑定到当前工作区后,才能继续打开插件前端页面。",workspaceSessionSortModeDescription:"控制工作区里各处会话列表的默认排序,只影响当前设备。",sessionSortModeCreatedAt:"按照会话创建时间",sessionSortModeUpdatedAt:"按照会话更新时间",sessionSortModeTitle:"按照会话名称",showSystemFiles:"显示系统文件",showSystemFilesDescription:"在文件管理里显示 macOS 和 Windows 常见的系统文件,例如 .DS_Store、Thumbs.db。这个开关只影响当前设备。",serverConnection:"服务器连接",serverConnectionSectionSummary:"服务器地址与连接恢复策略",remoteAccess:"远程访问",remoteAccessSectionSummary:"通过 CodingNS Connect 或 Tailscale,从外部设备连接这台 Host。",remoteAccessNavValue:"CodingNS Connect / Tailscale",remoteAccessManageTitle:"远程访问方式",remoteAccessManageDescription:"需要从外部访问这台 Host 时,在这里选择并配置连接方式。",remoteAccessManageAction:"管理远程访问",remoteAccessModalTitle:"访问方式管理",remoteAccessModalDescription:"选择并配置你要使用的远程访问方式。",remoteAccessTabsLabel:"远程访问方式标签",remoteAccessTunnelTab:"CodingNS Connect",remoteAccessTailscaleTab:"Tailscale接入",remoteAccessFeatureDisabledValue:"未开启",abilityManagement:"能力管理",abilityManagementSectionSummary:"统一管理文档库、CLI 提供方的启用状态,以及模型配置文件的快速切换入口。",abilityManagementNavValue:"文档库 / 提供方 / 配置文件",affairsLibraryCapabilityTitle:"文档库",affairsLibraryCapabilityDescription:"该开关控制左侧文档入口,以及文档索引、标签索引等后台服务。",affairsLibraryCapabilityToggleLabel:"启用文档库",affairsLibraryCapabilityLoading:"正在更新文档库状态...",affairsLibraryCapabilityEnableSuccess:"文档库已启用。",affairsLibraryCapabilityDisableSuccess:"文档库已关闭。",affairsLibraryCapabilityLoadFailed:"文档库状态加载失败。",affairsLibraryCapabilitySaveFailed:"文档库状态保存失败。",modelManagement:"模型管理",modelManagementNavValue:"快速切换",modelManagementSectionTitle:"模型配置文件管理",providerManagement:"CLI 提供方",providerManagementSectionSummary:"控制哪些 CLI 会出现在会话、Fork、助手和 Skill 入口里。",providerManagementNavValue:"启用控制",providerManagementDescription:"统一控制这台 Host 当前允许使用的 CLI。能力矩阵、状态和启用开关都放在弹窗里查看和修改。",providerManagementManageAction:"管理 CLI 提供方",providerManagementModalTitle:"CLI 提供方管理",providerManagementModalDescription:"查看每个 CLI 在项目里的能力、当前状态,以及是否继续对外显示。",providerManagementRefresh:"刷新列表",providerManagementRefreshSuccess:"CLI 提供方列表已刷新。",providerManagementLoading:"正在读取可管理的 CLI 提供方...",providerManagementEmpty:"当前还没有可管理的 CLI 提供方。",providerManagementEmptyDescription:"等 Host 注册出可用的 CLI 提供方后,这里会自动出现。",providerManagementLoginRequired:"登录后才能管理 CLI 提供方。",providerManagementLoadFailed:"CLI 提供方列表加载失败。",providerManagementSaveFailed:"CLI 提供方状态保存失败。",providerManagementSummaryTitle:"提供方概况",providerManagementSummaryDescription:"这里先看总量,再决定要不要禁用某个 CLI。",providerManagementSummaryEnabled:"已启用",providerManagementSummaryDisabled:"已禁用",providerManagementSummaryTotal:"总数",providerManagementMatrixTitle:"能力矩阵",providerManagementMatrixDescription:"纵向是 CLI 提供方,横向是产品能力。关闭某个提供方后,它会从项目里的相关入口整体消失。",providerManagementTableProvider:"CLI 提供方",providerManagementTableStatus:"状态",providerManagementTableEnabled:"启用",providerManagementStatusEnabled:"已启用",providerManagementStatusDisabled:"已禁用",providerManagementInstallReady:"已安装",providerManagementInstallMissing:"未检测到",providerManagementInstallUnknown:"状态未知",providerManagementStateEnabled:"当前会出现在新的会话、Fork、助手和 Skill 相关入口里。",providerManagementStateDisabled:"当前已经从新的会话入口里隐藏,旧会话也会从正常列表里收起。",providerManagementStateMissing:"已经允许显示,但本地 CLI 还没准备好,等安装完成后才会真正可用。",providerManagementToggleLabel:"切换 {provider} 的启用状态",providerManagementEnableSuccess:"{provider} 已重新启用。",providerManagementDisableSuccess:"{provider} 已禁用。",providerManagementCapabilityStreaming:"流式输出",providerManagementCapabilityToolCalls:"工具调用",providerManagementCapabilityAssistant:"助手服务",providerManagementCapabilityFork:"会话 Fork",providerManagementCapabilitySkill:"Skill 使用",providerManagementCapabilityAvailable:"可用",providerManagementCapabilityUnavailable:"不可用",providerManagementImpactSessionStart:"新会话启动",providerManagementImpactFork:"会话 Fork",providerManagementImpactAssistant:"助手跟进",providerManagementImpactSkill:"Skill 新目标",providerManagementImpactEnabled:"如果现在关掉,会隐藏旧会话,并阻止 {actions}。",providerManagementImpactDisabled:"当前已经阻止 {actions};重新打开后,这些入口会重新出现。",providerManagementImpactEnabledFallback:"如果现在关掉,这个 CLI 会从项目里的新入口中一起消失。",providerManagementImpactDisabledFallback:"重新打开后,这个 CLI 会重新回到项目里的正常入口中。",channelsManagement:"通讯平台",channelsManagementSectionSummary:"统一管理外部通讯渠道、轮询账号和最近的收发流水。",channelsManagementNavValue:"账号 / 流水",channelsManagementDescription:"在这里管理通讯账号,并查看最近的消息和发送记录。",channelsManageAction:"管理通讯账号",channelsModalTitle:"通讯平台账号管理",channelsAddAccountAction:"添加通讯账号",channelsModalDescription:"先用统一账号模型接入外部通讯平台。第一阶段先把文本消息、固定 provider、polling 和 Butler control session 的映射链路接好。",channelsActionPending:"处理中...",channelsRefresh:"刷新数据",channelsRefreshSuccess:"通讯平台数据已刷新。",channelsLoading:"正在读取通讯平台配置...",channelsLoadingDetails:"正在读取最近的线程和消息...",channelsLoadFailed:"通讯平台列表加载失败。",channelsLoadDetailsFailed:"最近线程和消息加载失败。",channelsSaveFailed:"通讯账号保存失败。",channelsProbeFailed:"账号探活失败。",channelsPollFailed:"手动轮询失败。",channelsRemoveFailed:"通讯账号移除失败。",channelsCreateSuccess:"{account} 已创建。",channelsUpdateSuccess:"{account} 已保存。",channelsRemoveSuccess:"已移除通讯账号“{account}”。",channelsSelectAccountFirst:"请先选择一个已有账号,或者直接新建账号。",channelsSummaryTitle:"通讯平台概况",channelsSummaryAccounts:"账号数",channelsSummaryActive:"正常账号",channelsSummaryPlatforms:"已用平台",channelsWizardTitle:"配置向导",channelsWizardCreateDescription:"先选通讯渠道,再填这个渠道自己的配置,最后把账号绑定到固定的助手引擎。",channelsWizardEditDescription:"当前正在编辑已有账号。平台不在这里切换,改助手引擎只影响新会话,旧会话继续保留原上下文。",channelsWizardStepsTitle:"通讯账号配置步骤",channelsWizardStepPlatform:"选择渠道",channelsWizardStepConfig:"填写渠道配置",channelsWizardStepBinding:"绑定账号",channelsWizardNextToConfig:"继续填写配置",channelsWizardNextToBinding:"继续绑定账号",channelsWizardBackToPlatform:"返回选渠道",channelsWizardBackToConfig:"返回渠道配置",channelsWizardSelectPlatformHint:"先从上面选一个通讯渠道,下面才会出现对应的专用表单。",channelsWizardBindingSummary:"多会话支持",channelsPlatformsTitle:"平台能力清单",channelsPlatformsDescription:"这里按渠道卡片展示第一阶段的 polling 口径、多会话支持情况和当前限制。",channelsPlatformsEmpty:"当前没有可展示的平台能力。",channelsPlatformsEmptyDescription:"等 Host 注册出平台目录后,这里会自动显示。",channelsPlatformSummary:"接入方式:{modes};多会话:{multiSession}",channelsAccountsTitle:"通讯账号",channelsAccountsDescription:"每个账号固定绑定一个助手引擎,并固定走 polling。新会话按账号配置启动,旧会话继续保留原上下文。",channelsAccountsEmpty:"还没有通讯账号。",channelsAccountsEmptyDescription:"先添加一个通讯账号,后面收到消息后这里会开始积累线程和流水。",channelsAccountRowDescription:"{platform} · {provider} · {mode}",channelsCreateAction:"新建账号",channelsSaveAction:"保存账号",channelsResetToCreate:"切到新建",channelsCreateFormTitle:"新建通讯账号",channelsCreateFormDescription:"先把统一字段建出来。平台差异先放进补充配置 JSON,避免第一阶段表单失控。",channelsEditFormTitle:"编辑通讯账号",channelsEditFormDescription:"改 provider 后只会影响新会话,旧会话仍保留原上下文。",channelsFieldDisplayName:"账号显示名",channelsFieldDisplayNamePlaceholder:"例如:飞书值班号",channelsFieldPlatform:"通讯平台",channelsFieldPlatformDescription:"先选平台,再决定接入方式和补充配置。",channelsFieldProvider:"助手引擎",channelsFieldProviderDescription:"第一阶段只允许固定成 Codex 或 Claude Code,不能在同一外部线程里临时切换。",channelsFieldConnectionMode:"接入方式",channelsFieldConnectionModeDescription:"第一阶段六个平台统一按 polling 接入,不在这里切换别的模式。",channelsFieldStatus:"账号状态",channelsFieldStatusDescription:"先用正常、停用、异常降级这三个状态管理账号可用性。",channelsFieldConfig:"平台补充配置(JSON)",channelsFieldConfigDescription:"这里放当前表单里没覆盖到的补充字段。专用表单优先,补充 JSON 只做兜底。",channelsAdvancedConfigTitle:"补充字段(高级)",channelsAdvancedConfigDescription:"只有当前表单没覆盖的字段才放这里,例如回发地址、临时开关或实验参数。",channelsValidationDisplayName:"请先填写账号显示名。",channelsValidationPlatform:"请先选择通讯平台。",channelsValidationConnectionMode:"请先选择接入方式。",channelsValidationConfigJson:"补充配置不是合法 JSON。",channelsValidationConfigObject:"补充配置必须是 JSON 对象。",channelsValidationRequiredField:"请先填写“{field}”。",channelsValidationFeishuCredential:"飞书最少还要补一组凭证:直接填 Tenant Access Token,或者同时填 App ID 和 App Secret。",channelsConfigWechatUnavailableTitle:"个人微信(claw)不需要手填协议参数",channelsConfigWechatUnavailableDescription:"这个通道的扫码、登录态、轮询和回发都交给 Host helper 处理,这一步不用再手填私有协议参数。",channelsDetailTitle:"当前账号概况",channelsDetailDescription:"这里先看当前账号的接入状态、最近收发时间和是否需要人工补查。",channelsDetailPlatform:"平台",channelsDetailProvider:"助手引擎",channelsDetailConnectionMode:"接入方式",channelsDetailStatus:"账号状态",channelsDetailLastInbound:"最近入站",channelsDetailLastOutbound:"最近回发",channelsDetailLastError:"最近错误",channelsProbeAction:"检查连通性",channelsPollAction:"手动轮询",channelsRemoveAction:"移除账号",channelsRemoveConfirmAction:"确认移除",channelsRemoveConfirmDescription:"移除后会同时清理这个账号下的线程映射、入站消息和回发记录。这个操作不能撤回。",channelsWebhookHint:"这个账号是 webhook 模式,不需要手动轮询。",channelsConnectionModeFixedHint:"当前阶段固定按 polling 建模;如果以后换模式,会单独升级账号配置规则。",channelsThreadsTitle:"线程映射",channelsThreadsDescription:"最近 {count} 条线程映射,按 external conversation key 关联到 Butler control session。",channelsThreadsEmpty:"还没有线程映射。",channelsThreadsEmptyDescription:"收到第一条外部消息后,这里会自动出现。",channelsEventsTitle:"入站消息",channelsEventsDescription:"最近 {count} 条入站消息,方便排查消息是否被 Host 接住并成功分发。",channelsEventsEmpty:"还没有入站消息。",channelsEventsEmptyDescription:"等渠道开始真正拉到文本消息后,这里会出现记录。",channelsDeliveriesTitle:"回发记录",channelsDeliveriesDescription:"最近 {count} 条回发记录,用来确认 Butler 首条文本有没有成功送回外部平台。",channelsDeliveriesEmpty:"还没有回发记录。",channelsDeliveriesEmptyDescription:"当 Butler 产出首条文本并触发回发后,这里才会有记录。",channelsConnectionModeWebhook:"Webhook",channelsConnectionModePolling:"Polling",channelsConnectionModeBridge:"Bridge",channelsMultiSessionSupported:"支持多会话",channelsMultiSessionLimited:"有限支持",channelsStatusActive:"正常",channelsStatusDisabled:"已停用",channelsStatusDegraded:"异常降级",channelsThreadStatusActive:"活跃",channelsThreadStatusClosed:"已关闭",channelsThreadStatusFailed:"失败",channelsEventStatusReceived:"已接收",channelsEventStatusDispatched:"已分发",channelsEventStatusReplied:"已回复",channelsEventStatusFailed:"失败",channelsEventStatusIgnored:"已忽略",channelsDeliveryStatusSent:"已发出",channelsDeliveryStatusFailed:"失败",channelsDeliveryStatusSkipped:"已跳过",channelsThreadSummary:"{status} · 会话键:{conversationKey}",channelsEventSummary:"{status} · 会话键:{conversationKey}",channelsDeliverySummary:"{status} · 最近一条回发文本",channelsMetaCreatedAt:"创建时间",channelsMetaUpdatedAt:"更新时间",channelsMetaReceivedAt:"接收时间",channelsMetaExternalUser:"外部用户",channelsMetaEventId:"外部事件",channelsMetaProviderRef:"平台回执",channelsMetaError:"错误",channelsTextFallback:"空文本",channelsTimeUnknown:"暂无",channelsWechatBindingTitle:"微信绑定",channelsWechatBindingDescription:"这个账号会通过 Host 托管的 helper 完成扫码登录、轮询收信和消息回发。",channelsWechatBoundDescription:"微信账号已经绑定成功。现在可以继续做探活、手动轮询和后续会话桥接。",channelsWechatCreateDescription:"先给这个微信账号起个名字。创建完成后,下一步就在详情区生成二维码并扫码绑定。",channelsWechatRuntimeRequiredTitle:"当前还不能直接绑定个人微信",channelsWechatRuntimeRequiredDescription:"当前环境没有启用微信 helper,所以这里只能看到账号基础信息。启用 helper 后,这里会切回真实扫码绑定。",channelsWechatPendingTitle:"这个账号还没完成绑定",channelsWechatPendingDescription:"先完成扫码绑定,绑定成功后才会出现轮询、回发和最近记录。",channelsWechatBeginBindingAction:"开始绑定",channelsWechatContinueBindingAction:"继续绑定",channelsWechatStartLoginAction:"生成二维码",channelsWechatRestartBindingAction:"重新生成二维码",channelsWechatRefreshLoginAction:"刷新绑定状态",channelsWechatLogoutAction:"清除绑定",channelsWechatBindingModalTitle:"扫描二维码绑定微信",channelsWechatBindingModalDescription:"请用微信扫描下面的二维码。扫码后回到这里,点“刷新绑定状态”。",channelsWechatBindingModeValue:"扫码绑定",channelsWechatLoginStatus:"绑定状态",channelsWechatLoginStatusNotLoggedIn:"未绑定",channelsWechatLoginStatusWaitingScan:"等待扫码",channelsWechatLoginStatusScanConfirmed:"已扫码,待确认",channelsWechatLoginStatusActive:"已绑定",channelsWechatLoginStatusExpired:"二维码已过期",channelsWechatQrHint:"扫码成功后,点“刷新绑定状态”同步结果。",channelsWechatQrAlt:"个人微信绑定二维码",channelsWechatOpenQrLinkAction:"打开绑定二维码",channelsWechatQrRawTitle:"查看二维码原始内容",channelsWechatQrRawDescription:"上游返回的原始二维码内容会先保存在这里,方便排查扫码链路。",channelsWechatQrEmpty:"还没有绑定二维码",channelsWechatQrEmptyDescription:"先点上面的“生成二维码”,再用微信扫码完成绑定。",channelsConfigFieldDingtalkAppKey:"钉钉 AppKey",channelsConfigFieldDingtalkAppKeyDescription:"后续接真实拉取接口时,会用这个字段识别钉钉应用。",channelsConfigFieldDingtalkAppKeyPlaceholder:"填写钉钉应用 AppKey",channelsConfigFieldDingtalkAppSecret:"钉钉 AppSecret",channelsConfigFieldDingtalkAppSecretDescription:"建议只填正式值班账号的密钥,避免把测试凭证混进生产轮询账号。",channelsConfigFieldDingtalkAppSecretPlaceholder:"填写钉钉应用 AppSecret",channelsConfigFieldDingtalkRobotCode:"机器人编码",channelsConfigFieldDingtalkRobotCodeDescription:"如果后续消息要回发到固定机器人,可以先把机器人编码记在这里。",channelsConfigFieldDingtalkRobotCodePlaceholder:"例如:dingxxxxxxxx",channelsConfigFieldFeishuAppId:"飞书 App ID",channelsConfigFieldFeishuAppIdDescription:"如果你不打算直接填 Tenant Access Token,这里要和 App Secret 一起填写。",channelsConfigFieldFeishuAppIdPlaceholder:"填写飞书应用 App ID",channelsConfigFieldFeishuAppSecret:"飞书 App Secret",channelsConfigFieldFeishuAppSecretDescription:"如果你不打算直接填 Tenant Access Token,这里要和 App ID 一起填写。",channelsConfigFieldFeishuAppSecretPlaceholder:"填写飞书应用 App Secret",channelsConfigFieldFeishuTenantAccessToken:"Tenant Access Token",channelsConfigFieldFeishuTenantAccessTokenDescription:"如果你已经能稳定拿到 tenant_access_token,直接填这里就行,不用再强制填 App ID 和 App Secret。",channelsConfigFieldFeishuTenantAccessTokenPlaceholder:"填写飞书 tenant_access_token",channelsConfigFieldFeishuChatId:"目标会话 Chat ID",channelsConfigFieldFeishuChatIdDescription:"必填。第一阶段先固定一个群或会话,Host 才知道去哪里拉消息和回发文本。",channelsConfigFieldFeishuChatIdPlaceholder:"例如:oc_xxx 或 chat_xxx",channelsConfigFieldWechatBaseUrl:"claw 服务地址",channelsConfigFieldWechatBaseUrlDescription:"Host 会通过这个地址去拉取消息和发送回复。这里必须能从 Host 所在机器访问到。",channelsConfigFieldWechatBaseUrlPlaceholder:"例如:http://127.0.0.1:8787",channelsConfigFieldWechatBridgeToken:"claw 访问令牌",channelsConfigFieldWechatBridgeTokenDescription:"如果你的 claw transport 有访问令牌,这里填进去做最基本的校验。",channelsConfigFieldWechatBridgeTokenPlaceholder:"填写 claw transport token",channelsConfigFieldWechatPollPath:"拉取路径",channelsConfigFieldWechatPollPathDescription:"默认会用 `/poll`。如果你的 transport 路径不同,可以在这里改。",channelsConfigFieldWechatPollPathPlaceholder:"默认 /poll",channelsConfigFieldWechatSendPath:"发送路径",channelsConfigFieldWechatSendPathDescription:"默认会用 `/send`。如果你的 transport 路径不同,可以在这里改。",channelsConfigFieldWechatSendPathPlaceholder:"默认 /send",channelsConfigFieldTelegramBotToken:"Telegram Bot Token",channelsConfigFieldTelegramBotTokenDescription:"Telegram 真实轮询和回发都要靠这个 token,没填就不能工作。",channelsConfigFieldTelegramBotTokenPlaceholder:"填写 Telegram Bot Token",channelsConfigFieldSlackBotToken:"Slack Bot Token",channelsConfigFieldSlackBotTokenDescription:"必填。Slack 轮询读消息和回发文本都靠这个 token。",channelsConfigFieldSlackBotTokenPlaceholder:"填写 Slack Bot Token",channelsConfigFieldSlackAppToken:"Slack App Token",channelsConfigFieldSlackAppTokenDescription:"当前最少可用配置不强制要它。只有你的 Slack 应用确实额外要求时再填写。",channelsConfigFieldSlackAppTokenPlaceholder:"填写 Slack App Token",channelsConfigFieldSlackChannelId:"频道 ID",channelsConfigFieldSlackChannelIdDescription:"必填。第一阶段先固定一个频道,先把轮询和文本回发链路打通。",channelsConfigFieldSlackChannelIdPlaceholder:"例如:C0123456789",channelsConfigFieldDiscordBotToken:"Discord Bot Token",channelsConfigFieldDiscordBotTokenDescription:"必填。Discord 轮询读消息和回发文本都要靠这个 bot token。",channelsConfigFieldDiscordBotTokenPlaceholder:"填写 Discord Bot Token",channelsConfigFieldDiscordApplicationId:"Application ID",channelsConfigFieldDiscordApplicationIdDescription:"当前最少可用配置不强制要它。只有你的应用权限配置确实依赖它时再填写。",channelsConfigFieldDiscordApplicationIdPlaceholder:"填写 Discord Application ID",channelsConfigFieldDiscordGuildId:"Guild ID",channelsConfigFieldDiscordGuildIdDescription:"必填。先固定一个服务器,后面的 thread 子分支会在这个服务器下工作。",channelsConfigFieldDiscordGuildIdPlaceholder:"填写 Discord Guild ID",channelsConfigFieldDiscordChannelId:"频道 ID",channelsConfigFieldDiscordChannelIdDescription:"必填。先固定一个频道,后面的 thread 子分支会挂在这个频道下面。",channelsConfigFieldDiscordChannelIdPlaceholder:"填写 Discord Channel ID",channelsConfigChecklistTitle:"这一步最少要准备什么",channelsConfigChecklistFeishuSummary:"飞书这一版先按固定会话做 polling,最少要给 Host 一个目标会话和一套可用凭证。",channelsConfigChecklistFeishuItemCredential:"凭证二选一:直接填 Tenant Access Token,或者同时填 App ID 和 App Secret。",channelsConfigChecklistFeishuItemChat:"必须填目标会话 Chat ID,不然 Host 不知道要跟哪一个群或会话对接。",channelsConfigChecklistFeishuItemScope:"先按文本消息打通,不处理图片、文件、语音和卡片。",channelsConfigChecklistSlackSummary:"Slack 这一版先固定一个频道做 polling,先把读消息和回发文本跑通。",channelsConfigChecklistSlackItemToken:"必须填 Bot Token,缺它就没法拉消息也没法发回复。",channelsConfigChecklistSlackItemChannel:"必须填频道 ID,当前账号先固定绑定到一个频道。",channelsConfigChecklistSlackItemScope:"第一阶段只处理文本消息,thread 子分支暂不在 Slack 里实现。",channelsConfigChecklistDiscordSummary:"Discord 这一版最少要固定服务器和频道,后面的 thread 子分支会落在这个范围里。",channelsConfigChecklistDiscordItemToken:"必须填 Bot Token,轮询读消息和回发文本都要靠它。",channelsConfigChecklistDiscordItemGuild:"必须填 Guild ID,先把账号固定到一个服务器。",channelsConfigChecklistDiscordItemChannel:"必须填频道 ID,后面的 thread 子分支会挂在这个频道下面。",modelManagementTitle:"模型快速切换",modelManagementDescription:"这里不新增也不编辑预设,只把 cc-switch 已有预设图形化展示出来,方便你一键切换。",modelManagementRefresh:"刷新模型",modelManagementRefreshSuccess:"模型预设列表已刷新。",modelManagementLoadFailed:"模型预设加载失败。",modelManagementScannedAt:"最近扫描",modelManagementScannedAtUnknown:"暂未扫描",modelManagementCurrentProfile:"当前配置文件",modelManagementCurrentModel:"当前模型",modelManagementCurrentPreset:"当前预设",modelManagementModelUnknown:"未识别",modelManagementPresetMissing:"未设置",modelManagementCurrentTag:"当前",modelManagementOpenSwitcher:"切换配置",modelManagementModalTitle:"供应商配置切换",modelManagementModalDescription:"这里按应用查看 cc-switch 已有配置文件,并切换当前启用项。",modelManagementTabsLabel:"模型应用标签",modelManagementSwitchAction:"切换",modelManagementSwitchSuccess:"{app} 已切换到 {preset}。",modelManagementOptionsEmpty:"当前没有可切换的预设。",modelManagementStatusReady:"可切换",modelManagementStatusUnconfigured:"未配置",modelManagementStatusUnavailable:"未安装 cc-switch-cli",modelManagementStatusError:"读取失败",skills:"Skills",skillsSectionSummary:"读取并同步各个 CLI 自己的本地 skill,不做市场,不接远端仓库。",skillsNavValue:"本地同步",skillManagerTitle:"本地 Skill 管理",skillManagerDescription:"统一读取 Codex、Claude Code、Gemini、OpenCode 的 skill 目录,支持导入未纳管项并重新同步。",skillSummaryManagedSkills:"我的技能",skillSummaryManagedEntries:"已生效",skillSummaryUnmanagedEntries:"未纳管目录",skillSummaryConflictedEntries:"待处理",skillSummaryAssistantRuntimeEntries:"助手专用目录",skillSummaryDiagnostics:"提醒",skillManageAction:"技能配置",skillConfigModalTitle:"技能配置",skillConfigModalDescription:"在这里查看你的技能、系统自带技能和需要处理的项目。",skillCreateAction:"添加技能",skillCreateModalTitle:"添加技能",skillCreateModalDescription:"把新的 SKILL.md 纳管进来。文件上传和粘贴文本都走同一套校验与纳管流程。",skillCreateSourceTabsLabel:"添加方式",skillCreateSourceFile:"选择文件",skillCreateSourcePaste:"粘贴文本",skillCreateSubmitAction:"添加",skillRefresh:"刷新",skillRefreshSuccess:"技能列表已刷新。",skillScannedAt:"最近扫描",skillUploadSectionTitle:"上传 Skill",skillUploadSectionDescription:"选择一个 SKILL.md 文件,先选它属于工作区还是助手运行时,再做基础校验和轻量纠正并纳管。",skillUploadPickAction:"选择 SKILL.md",skillUploadSubmitAction:"上传并纳管",skillUploadEmpty:"当前还没有选择要上传的 SKILL.md 文件。",skillUploadPickedFile:"已选文件",skillUploadScopeLabel:"作用域",skillUploadScopeWorkspace:"工作区 Skill",skillUploadScopeAssistant:"助手专用 Skill",skillUploadDirectoryLabel:"目录名",skillUploadDirectoryPlaceholder:"例如 team-helper",skillUploadDirectoryHint:"用于生成纳管目录和同步目标目录。默认按文件名或标题自动生成,通常不用手动改。",skillUploadDirectoryInvalid:"目录名不合法,只允许字母、数字、点、下划线和短横线。",skillUploadTargetsLabel:"应用 CLI",skillPasteLabel:"粘贴 SKILL 内容",skillPastePlaceholder:"直接粘贴完整的 SKILL.md 内容",skillPasteEmpty:"当前还没有可纳管的 SKILL 内容。",skillUploadDirectoryRequiredNote:"当前文件名推不出合法目录名,请手动补一个。",skillUploadTargetRequired:"至少选择一个目标 CLI。",skillUploadHeadingNote:"当前 markdown 缺少一级标题,纳管时会自动补一个。",skillUploadNormalizedNote:"已按系统规则预处理空白和换行。",skillUploadReadFailed:"读取上传的 SKILL.md 失败。",skillUploadContentEmpty:"上传的 SKILL.md 不能为空。",skillUploadSuccess:"已添加 {name}。",skillManagedListTitle:"我的技能",skillManagedEmpty:"你还没有添加任何技能。",skillManagedItemDescription:"已添加到 {targets}。",skillManagedItemNoTarget:"这项技能还没有应用到任何客户端。",skillUnmanagedListTitle:"待添加技能",skillUnmanagedEmpty:"目前没有新的技能可添加。",skillUnmanagedItemDescription:"已在 {target} 中发现,你可以把它添加到列表。",skillUnmanagedItemDisabledDescription:"已在 {target} 中发现,但这个目标当前已禁用,暂时不能继续添加。",skillAssistantRuntimeListTitle:"助手内置技能",skillAssistantRuntimeListDescription:"这些技能由系统自动提供,只给助手自己使用。",skillAssistantRuntimeEmpty:"当前没有助手内置技能。",skillAssistantRuntimeItemDescription:"这是系统自带技能,你不需要手动处理。",skillAssistantRuntimeUsedBy:"可用于",skillAssistantRuntimeSourcePath:"内置来源路径",skillConflictedListTitle:"待处理",skillConflictedEmpty:"当前没有需要处理的项目。",skillConflictedItemDescription:"{target} 里的这项内容需要处理。",skillConflictedItemDisabledDescription:"{target} 里的这项内容还保留着,但这个目标当前已禁用。",skillDiagnosticsTitle:"提醒",skillDiagnosticsEmpty:"当前没有新的提醒。",skillDiagnosticTargetMissingTitle:"{target} 还没准备好",skillDiagnosticTargetMissingDetail:"当前还没有找到 {target} 的技能目录。",skillDiagnosticReadFailedTitle:"{target} 暂时不可用",skillDiagnosticReadFailedDetail:"暂时无法读取 {target} 的技能信息,请稍后再试。",skillDiagnosticSyncMissingTitle:"{target} 需要重新应用",skillDiagnosticSyncMissingDetail:"有技能还没有在 {target} 中生效。",skillDiagnosticGenericTitle:"{target} 需要留意",skillDiagnosticGenericDetail:"有一项内容暂时没准备好,可以稍后刷新再看。",skillDirectoryName:"目录名",skillSsotPath:"统一存储目录",skillSourceCli:"来源 CLI",skillDirectoryPath:"目录路径",skillImportAction:"添加",skillImportSuccess:"已添加 {name},并应用到 {target}。",skillSyncAction:"重新应用",skillSyncSuccess:"已重新应用 {name}。",skillSyncTargetMissing:"这项技能还没有应用目标,暂时不能重新应用。",skillSyncTargetDisabled:"这项技能当前只剩已禁用目标,先重新启用对应 provider 再继续。",skillLoadFailed:"Skill 概况加载失败。",skillOfficeTemplateCreated:"文档模板已创建。",skillOfficeTemplateUpdated:"文档模板已更新。",skillOpsTargetCreated:"SSH 主机已创建。",skillOpsTargetUpdated:"SSH 主机已更新。",skillOpsApprovalApproved:"运维审批已批准。",skillOpsApprovalRejected:"运维审批已拒绝。",skillTargetCodex:"Codex",skillTargetClaudeCode:"Claude Code",skillTargetGemini:"Gemini",skillTargetOpenCode:"OpenCode",skillBindingPending:"准备中",skillBindingSynced:"可用",skillBindingFailed:"暂不可用",skillBindingConflicted:"需要处理",skillUploadTargetDisabled:"当前可选的 Skill 目标都已经被禁用,先去 provider 设置里重新启用一个。",skillTargetDisabledTag:"已禁用",skillTagAssistantOnly:"仅助手使用",skillTagWorkspaceSessionOnly:"工作区会话使用",securityPrivacy:"安全与隐私",securityPrivacySectionSummary:"会话权限、风险边界与默认授权策略",softwareUpdate:"软件更新",softwareUpdateSectionSummary:"服务端和客户端版本",updateOneClickValue:"一次检查",updateOneClickTitle:"统一更新",updateOneClickDescription:"先检查服务端和桌面端版本,再按顺序安装可用更新。",updateOptions:"更新选项",updateInstallAll:"安装全部更新",updateCheckFailed:"检查更新失败",updateInstallingSequential:"正在准备安装更新",updateInstallingServerFirst:"正在更新服务端",updateInstallingClientNext:"正在更新桌面端",updateBothReady:"发现服务端和桌面端新版本",updateServerReadyOnly:"发现服务端新版本",updateClientReadyOnly:"发现桌面端新版本",updateAllUpToDate:"当前已是最新版本",updateCheckIncomplete:"部分更新信息暂时无法获取,请稍后重试",updateServerReadyClientCheckFailed:"发现服务端新版本,桌面端信息暂时无法获取",updateClientReadyServiceCheckFailed:"发现桌面端新版本,服务端信息暂时无法获取",serverAddress:"服务器地址",serverDescription:"客户端的登录、接口请求和实时连接都通过这个 Host 入口工作;前端界面资源由应用自身携带。",serverRelayTunnelProfileTitle:"当前 Host 的 CodingNS Connect 入口",serverRelayTunnelProfileDescription:"给当前保存的 Host profile 指定 CodingNS Connect 入口。开启后,客户端会通过 CodingNS Connect 域名和控制站点建立端到端加密连接,而不是直接请求这个地址。",serverRelayTunnelEnabled:"通过 CodingNS Connect 连接",serverRelayTunnelUsageHint:"服务器地址建议填写这台 Host 的公开入口地址,例如 https://demo.codingns.example 。",serverRelayTunnelDomain:"CodingNS Connect 域名",serverRelayTunnelDomainPlaceholder:"例如:demo.codingns.example",serverRelayTunnelControlBaseUrl:"控制站点地址",serverRelayTunnelControlBaseUrlPlaceholder:"例如:https://control.codingns.example",relayTunnelServerAddressDescription:"默认使用官方 CodingNS Connect 地址;如果你明确知道当前控制站地址,也可以在高级设置里手动覆盖。",relayTunnelServerAddressHint:"这里只改 CodingNS Connect 控制站点地址,用来覆盖登录、绑定和流量查询使用的站点,不影响当前 Host 的本地 API 地址。",relayTunnelStatus:"CodingNS Connect 状态",relayTunnelDescription:"通过 CodingNS Connect,让外部设备安全连接到这台 Host。",relayTunnelMasterSwitchLabel:"启用 CodingNS Connect",relayTunnelActivationHint:"开启后才会检查 CodingNS Connect 状态,并允许这台 Host 接入公网访问。",relayTunnelPhase:"当前状态",relayTunnelDomain:"访问地址",relayTunnelUnbound:"还没有绑定",relayTunnelTrafficRemaining:"剩余流量",relayTunnelHostFingerprint:"Host 指纹",relayTunnelTrustBoundaryNotice:"CodingNS Connect 只负责转发加密后的流量,无法看到你和 Host 之间的通信内容。",relayTunnelRecentError:"最近错误:{message}",relayTunnelAccessTitle:"连接设置",relayTunnelAccessDescription:"先登录 CodingNS Connect 账号,再打开开关把这台设备接入公网访问。",relayTunnelLearnService:"了解 CodingNS Connect",relayTunnelWizardTitle:"远程访问向导",relayTunnelWizardDescription:"按下面三步完成账号登录、主机名确认和 CodingNS Connect 启动,收住以后就能稳定从外部访问这台 Host。",relayTunnelStatusErrorTitle:"暂时无法读取远程访问状态",relayTunnelStatusNetworkError:"当前连不上这台 Host({address}),远程访问状态可能不是最新的。请先确认服务器地址、端口和网络连接。",relayTunnelStepPending:"待完成",relayTunnelStepCurrent:"进行中",relayTunnelStepDone:"已完成",relayTunnelStepLocked:"先完成上一步,这一步才会开放。",relayTunnelStepLoginTitle:"登录账号",relayTunnelStepLoginDescription:"先连接你的 CodingNS Connect 账号,后续的主机名检查和流量读取都依赖这个账号。",relayTunnelStepLoginConnected:"账号已经连接,可以继续下一步。",relayTunnelStepHostLabelTitle:"设置主机名",relayTunnelStepHostLabelDescription:"填写你以后要访问的四级域名前缀,并先检查这个名称现在能不能用。",relayTunnelStepStartTitle:"启动 CodingNS Connect",relayTunnelStepStartDescription:"前两步都完成后,再把当前 Host 正式接入 CodingNS Connect。",relayTunnelStepStartReady:"主机名已经确认,可以启动 CodingNS Connect 了。",relayTunnelStartAction:"启动 CodingNS Connect",relayTunnelLoginErrorTitle:"登录 CodingNS Connect 账号失败",relayTunnelAdvancedSettings:"高级设置",relayTunnelAdvancedSettingsHide:"收起高级设置",relayTunnelAdvancedSettingsDescription:"默认使用官方 CodingNS Connect 地址。只有在你明确知道当前控制站地址时,才需要在这里覆盖。",relayTunnelLoginNetworkError:"登录请求没有发出去,因为当前连不上这台 Host({address})。请先确认服务器地址和网络连接,再重新尝试。",relayTunnelReadyTitle:"远程访问已开启",relayTunnelReadyDescription:"当前配置已经收住。这里仅保留访问地址、流量信息和维护动作。",relayTunnelAccessUrlLabel:"远程访问地址",relayTunnelCopyAccessUrl:"复制地址",relayTunnelOpenAccessUrl:"打开页面",relayTunnelAccessUrlCopied:"访问地址已复制。",relayTunnelCopyAccessUrlFailed:"访问地址复制失败。",relayTunnelOpenAccessUrlFailed:"访问地址打开失败。",relayTunnelClientRouteLabel:"当前客户端链路",relayTunnelClientRouteAddressLabel:"当前客户端地址",relayTunnelClientRouteHintRelay:"当前客户端还在通过 CodingNS Connect 连接这台 Host;如果系统确认本地地址可达,会自动切到更省流量的直连链路。",relayTunnelClientRouteHintRelayProbing:"正在检查本地可直连地址。检查完成后,会自动切到更省流量的链路。",relayTunnelClientRouteHintLan:"当前客户端已经切到局域网直连,这条链路更省流量;远程访问地址仍然可以继续给外部设备使用。",relayTunnelClientRouteHintLoopback:"当前客户端直接连到这台设备的本机地址,不经过 CodingNS Connect。",relayTunnelClientRouteHintTailscale:"当前客户端已经切到 Tailscale 地址,不经过 CodingNS Connect。",relayTunnelClientRouteHintDirect:"当前客户端直接请求这个 Host 地址,不经过 CodingNS Connect。",relayTunnelReconnectAction:"重新连接",relayTunnelManageAccountAction:"管理账号",relayTunnelDisconnectDeviceAction:"注销设备",relayTunnelEnableToggleLabel:"启用 CodingNS Connect",relayTunnelConfigTitle:"CodingNS Connect 站点配置",relayTunnelConfigDescription:"这里填写 CodingNS Connect 接入地址和控制面的地址。保存后,下面的登录、绑定和流量操作都会走这里。",relayTunnelConfigErrorTitle:"服务地址保存失败",relayTunnelConfigNetworkError:"新的服务地址还没有保存到这台 Host,因为当前连不上它({address})。请先确认服务器地址和网络连接。",relayTunnelRelayBaseUrl:"CodingNS Connect 接入地址",relayTunnelControlBaseUrl:"控制站点地址",relayTunnelSaveConfig:"保存配置",relayTunnelRefresh:"刷新状态",relayTunnelAccountTitle:"CodingNS Connect 账号登录",relayTunnelAccountDescription:"使用 CodingNS Connect 账号登录后,可以绑定当前 Host 并查看剩余流量。",relayTunnelAccountEmail:"邮箱",relayTunnelAccountEmailPlaceholder:"输入你的邮箱",relayTunnelAccountPassword:"密码",relayTunnelAccountPasswordPlaceholder:"输入你的密码",relayTunnelLoginAccount:"登录",relayTunnelLoggedInAs:"当前已登录:{email}",relayTunnelConnectedBannerTitle:"账号已连接",relayTunnelConnectedBannerDescription:"现在可以打开 CodingNS Connect 开关,让外部设备访问这台 Host。",relayTunnelConnectedBannerActiveTitle:"CodingNS Connect 已开启",relayTunnelConnectedBannerActiveDescription:"这台设备已经可以通过 CodingNS Connect 从外部访问。",relayTunnelConnectedDevice:"当前设备:{name}",relayTunnelBoundDomain:"当前访问地址:{domain}",relayTunnelBindTitle:"绑定当前 Host",relayTunnelBindDescription:"绑定时会先读取当前 Host 的长期公钥,再把这台机器登记到 CodingNS Connect 站点。",relayTunnelHostLabelTitle:"设备名称",relayTunnelHostLabelDescription:"登录成功后,在这里填写你将来要使用的四级域名前缀,并检查这个名称当前能不能使用。",relayTunnelHostLabel:"Host 名称",relayTunnelHostLabelPlaceholder:"填写前缀",relayTunnelHostLabelSuffix:".channel.codingns.com",relayTunnelHostLabelCheck:"检查名称",relayTunnelHostLabelChecking:"正在检查这个名称是否可用。",relayTunnelHostLabelAvailable:"名称可用,公开访问地址将会是 {domain}",relayTunnelHostLabelReserved:"这个名称会命中保留前缀,请换一个名称。",relayTunnelHostLabelOccupied:"这个名称已经被占用,请换一个名称。",relayTunnelHostLabelUnavailable:"暂时无法确认这个名称是否可用,请稍后重试。",relayTunnelHostLabelRequired:"请先填写设备名称。",relayTunnelBindAction:"登录并绑定 Host",relayTunnelActionsTitle:"CodingNS Connect 开关",relayTunnelActionsDescription:"绑定完成后,可以在这里启用、停用或解绑 CodingNS Connect。",relayTunnelEnable:"启用 CodingNS Connect",relayTunnelDisable:"停用 CodingNS Connect",relayTunnelUnbind:"断开此设备",relayTunnelWalletTitle:"流量钱包",relayTunnelWalletDescription:"这里显示控制站点记录的总流量、已用流量和剩余额度。",relayTunnelTrafficGranted:"总流量",relayTunnelTrafficUsed:"已用流量",relayTunnelPackagesTitle:"流量套餐",relayTunnelPackagesDescription:"选择一个套餐后会跳转到官方支付页完成付款,支付成功后自动发放到当前账号钱包。",relayTunnelFeaturedPackage:"推荐",relayTunnelBuyPackage:"购买流量",relayTunnelOrdersTitle:"最近订单",relayTunnelOrdersDescription:"这里只显示最近几笔套餐订单,方便确认支付和到账状态。",relayTunnelOrderPending:"待支付",relayTunnelOrderPaid:"已支付",relayTunnelOrderExpired:"已过期",relayTunnelOrderFailed:"支付失败",relayTunnelControlBaseUrlRequired:"请先填写控制站点地址。",relayTunnelAccountRequired:"请先输入 CodingNS Connect 账号邮箱和密码。",relayTunnelIdentityUnavailable:"当前 Host 身份公钥还没有准备好,请稍后重试。",relayTunnelLoadFailed:"CodingNS Connect 状态读取失败。",relayTunnelPhaseDisabled:"未启用",relayTunnelPhaseBlockedUninitialized:"实例未初始化,已阻断暴露",relayTunnelPhaseUnbound:"还没有绑定",relayTunnelPhaseBinding:"正在绑定",relayTunnelPhaseConnecting:"正在连接",relayTunnelPhaseRunning:"运行中",relayTunnelPhaseQuotaExhausted:"流量耗尽",relayTunnelPhaseError:"状态异常",tailscaleBrand:"Tailscale",tailscaleSectionTitle:"Tailscale 接入",tailscaleSectionDescription:"让这台 Host 通过 Tailscale 在你的设备间可访问。",tailscaleMasterSwitchLabel:"启用 Tailscale",tailscaleActivationHint:"开启后才会检查 Tailscale 状态,并允许继续配置和绑定账号。",tailscaleCurrentState:"当前状态",tailscaleSwitchLabel:"启用开关",tailscaleStatusIndicator:"状态指示器",tailscaleServerAddress:"服务器地址",tailscaleAccountName:"账号名",tailscaleIpAddress:"IP 地址",tailscaleConfigure:"配置",tailscaleConfigModalTitle:"配置 Tailscale",tailscaleConfigModalDescription:"修改接入参数",tailscaleControlServer:"Control Server",tailscaleControlServerDescription:"留空时使用默认 control server。",tailscaleControlServerPlaceholder:"留空表示使用默认 control server",tailscaleHostname:"设备名称",tailscaleHostnameDescription:"可选。",tailscaleHostnamePlaceholder:"例如:codingns-host",tailscaleReachableBaseUrl:"外部访问地址",tailscaleTailnetFqdn:"Tailnet FQDN",tailscaleTailnetIpv4:"Tailnet IPv4",tailscaleTailnetIpv6:"Tailnet IPv6",tailscaleDetailAddresses:"详细地址",tailscaleRefresh:"刷新状态",tailscaleInstallAction:"安装 Tailscale",tailscaleInstallOpenFailed:"打开 Tailscale 安装页面失败。",tailscaleEnable:"启用 Tailscale",tailscaleDisable:"停用 Tailscale",tailscaleLogin:"开始绑定",tailscaleLogout:"解绑账号",tailscaleUnavailable:"暂不可用",tailscaleLoadFailed:"Tailscale 状态读取失败。",tailscalePhaseDisabled:"未启用",tailscalePhaseBlockedUninitialized:"实例未初始化,已阻断暴露",tailscalePhaseStarting:"正在启动",tailscalePhaseNeedsLogin:"等待绑定账号",tailscalePhaseRunning:"运行中",tailscalePhaseStopping:"正在停止",tailscalePhaseError:"状态异常",tailscaleOverviewDisabled:"当前还没有启用远程访问。",tailscaleOverviewBlockedUninitialized:"先完成初始化,再启用远程访问。",tailscaleOverviewStarting:"正在接入 Tailscale,请稍等。",tailscaleOverviewNeedsLogin:"启用完成后,还需要绑定账号。",tailscaleOverviewRunning:"当前实例已经可以通过 Tailscale 访问。",tailscaleOverviewStopping:"正在关闭远程访问。",tailscaleOverviewError:"远程访问状态异常,请先刷新或重新配置。",autoReconnect:"自动重连",autoReconnectDescription:"当 Host 短暂不可达时,自动尝试恢复 HTTP 和 WebSocket 链路。",autoCheckUpdate:"自动检查更新",autoCheckUpdateDescription:"发现客户端新版本时提醒你处理。",autoDownloadUpdate:"自动下载更新包后提示更新",autoDownloadUpdateDescription:"发现客户端新版本后先下载资源,下载完成再提示你安装。",defaultPermissionMode:"默认会话权限",defaultPermissionModeDescription:"控制新建和继续会话时默认使用的工具权限。完整权限会关闭询问,只适合你已经信任当前项目和运行环境时使用。",authDeviceManagement:"登录设备管理",authDeviceManagementDescription:"查看当前设备、其他在线设备和最近 10 条登录记录,并在主设备上按设备逐个退出其他在线设备。",authDeviceEntryHint:"点击“设备管理”后,可在弹窗中查看当前设备、其他在线设备和最近登录记录。",authDeviceOpenManager:"设备管理",authDeviceCurrentTitle:"当前设备",authDeviceOthersTitle:"其他在线设备",authDeviceRecentTitle:"最近登录记录",authDeviceCurrentTag:"当前设备",authDevicePrimaryTag:"主设备",authDeviceLegacyTag:"旧登录态",authDeviceLegacyHiddenHint:"检测到 {count} 条兼容旧登录态记录,默认已隐藏。",authDeviceLegacyReveal:"查看兼容记录",authDeviceLegacyHide:"隐藏兼容记录",authDeviceLegacyDevicesTitle:"兼容旧在线记录",authDeviceLegacyRecentTitle:"兼容旧登录记录",authDeviceLegacyLabel:"未知设备(旧登录态)",authDeviceClientDesktop:"Desktop",authDeviceClientWeb:"Web",authDeviceClientIos:"iOS",authDeviceClientAndroid:"Android",authDeviceClientUnknown:"未知设备",authDeviceCurrentEmpty:"当前登录态还没有可识别的设备信息,请重新登录后重试。",authDeviceOthersEmpty:"当前没有其他在线设备。",authDeviceRecentEmpty:"当前还没有最近登录记录。",authDeviceBrowserValue:"浏览器:{value}",authDeviceOsValue:"系统:{value}",authDeviceLastSeen:"最近在线:{value}",authDeviceLoginAt:"登录时间:{value}",authDeviceSourceAddressValue:"来源地址:{value}",authDeviceSourceAddressUnknown:"来源地址:未知",authDeviceEnablePrimary:"设为主设备",authDeviceDisablePrimary:"取消主设备",authDevicePrimaryUnavailable:"当前登录态缺少稳定设备标识,暂时不能设置主设备。",authDeviceLogoutOthers:"退出其他设备",authDeviceLogoutDevice:"退出设备",authDevicePrimaryEnabled:"当前设备已设为主设备。",authDevicePrimaryDisabled:"当前设备已取消主设备。",authDeviceLogoutOthersSuccess:"已退出其他设备,共处理 {count} 台。",authDeviceLogoutDeviceSuccess:"已退出设备“{device}”,共处理 {count} 个会话。",authDeviceLoadFailed:"登录设备信息加载失败。",authDeviceEnablePrimaryModalTitle:"设为主设备",authDeviceEnablePrimaryModalDescription:"请输入管理员密码,确认把当前设备设为主设备。",authDeviceDisablePrimaryModalTitle:"取消主设备",authDeviceDisablePrimaryModalDescription:"请输入管理员密码,确认取消当前设备的主设备状态。",authDevicePasswordLabel:"管理员密码",userManagementEntryTitle:"用户管理",userManagementEntryDescription:"管理可以登录这台 Host 的用户,并查看每个用户的会话和模型使用情况。",userManagementOpenAction:"用户管理",userManagementTitle:"用户管理",userManagementDescription:"这里管理登录用户。已有业务数据的用户不会被直接删除,避免误删工作区和会话。",userManagementTabsLabel:"用户管理标签页",userManagementUsersTab:"用户列表",userManagementUsageTab:"使用详情",userManagementUsersTitle:"用户列表",userManagementUsersDescription:"新增、编辑、启用或停用登录用户。删除只允许用于还没有产生数据的新用户。",userManagementAddUser:"添加用户",userManagementEditUser:"编辑",userManagementDeleteUser:"删除",userManagementEnableUser:"启用",userManagementDisableUser:"禁用",userManagementStatusActive:"已启用",userManagementStatusDisabled:"已禁用",userManagementUserMeta:"创建时间:{createdAt}",userManagementLoading:"正在读取用户列表。",userManagementUsersEmptyTitle:"还没有用户",userManagementUsersEmptyDescription:"添加第一个用户后,这里会显示可登录账号。",userManagementAddDescription:"输入用户名和密码,新用户创建后可以立即登录。",userManagementEditDescription:"可以修改用户名。密码留空时不会改变原密码。",userManagementUsernameLabel:"用户名",userManagementPasswordLabel:"密码",userManagementPasswordEditHint:"不需要改密码时留空。",userManagementDeleteConfirmTitle:"删除用户",userManagementDeleteConfirmDescription:"确认删除“{username}”?如果该用户已经产生数据,系统会阻止删除。",userManagementCreateSuccess:"用户已添加。",userManagementUpdateSuccess:"用户已更新。",userManagementDeleteSuccess:"用户已删除。",userManagementEnableSuccess:"用户已启用。",userManagementDisableSuccess:"用户已禁用。",userManagementLoadFailed:"用户列表读取失败。",userManagementSaveFailed:"用户保存失败。",userManagementDeleteFailed:"用户删除失败。",userManagementStatusFailed:"用户状态修改失败。",userManagementUsageTitle:"使用详情",userManagementUsageDescription:"按用户查看会话数量、模型、CLI 提供商和模型供应商使用情况。",userManagementUsageLoading:"正在读取使用详情。",userManagementUsageLoadFailed:"使用详情读取失败。",userManagementUsageEmptyTitle:"还没有使用记录",userManagementUsageEmptyDescription:"用户创建会话后,这里会显示使用情况。",userManagementPeriodLabel:"统计周期",userManagementPeriodDay:"按天",userManagementPeriodWeek:"按周",userManagementPeriodMonth:"按月",userManagementSessionCount:"{count} 个会话",userManagementMetricSessions:"会话",userManagementMetricTotalTokens:"总 Token",userManagementMetricInputTokens:"输入 Token",userManagementMetricOutputTokens:"输出 Token",userManagementTokenUnavailable:"当前 Host 还没有落库保存模型 Token 用量,所以 Token 图表会显示为 0;会话、模型和提供商统计来自真实会话记录。",userManagementTokenChartTitle:"模型 Token 用量",userManagementTokenChartEmptyTitle:"暂无 Token 记录",userManagementTokenChartEmptyDescription:"等会话记录里写入 Token 用量后,这里会显示趋势。",userManagementModelUsage:"模型使用情况",userManagementCliProviderUsage:"CLI 提供商使用情况",userManagementModelProviderUsage:"模型供应商使用情况",userManagementUsageGroupEmpty:"暂无记录",permissionModeDefault:"跟随 CLI 默认策略",permissionModeAcceptEdits:"允许编辑工作区,不询问",permissionModeBypassPermissions:"完整权限,不询问",enabled:"已启用",disabled:"已关闭",serverUpdate:"服务端更新",serverUpdateDescription:"",clientUpdate:"客户端更新",clientUpdateDescription:"",serverCurrentVersion:"服务端当前版本",serverTargetVersion:"服务端目标版本",serverPackageName:"npm 包名",serverUpdateCommand:"升级命令",serverCheckNow:"检查服务端",serverOpenPage:"打开 npm",serverLatestUnknown:"暂未获取",serverUpdateReady:"发现新版本",serverUpToDate:"已是最新版本",serverCheckFailed:"检查失败",serverInstallWarning:"安装更新会通过 PM2 自动重启 CodingNS 服务,连接会短暂中断。",serverInstallConfirmTitle:"安装服务端更新",serverInstallConfirmDescription:"继续后会先安装新版本,再由 PM2 自动重启当前 CodingNS 服务。",serverInstallConfirmAction:"继续安装并重启服务",serverRestarting:"更新已安装,正在重启 CodingNS 服务",serverProgressLabel:"服务端更新进度",serverProgressPreparing:"正在准备服务端更新",serverProgressQueued:"已进入更新队列",serverProgressInstalling:"正在更新服务端",serverProgressRestarting:"正在重启服务",serverProgressHint:"服务端更新通常需要几分钟,请保持应用打开。",serverProgressCurrentStage:"当前阶段:{stage}",serverOpenPageFailed:"打开页面失败",updateCheckAll:"检查更新",updateChecking:"正在检查",releaseCurrentVersion:"当前版本",releaseTargetVersion:"目标版本",releaseTargetTag:"目标 Tag",releasePublishedAt:"发布时间",releaseUnknownVersion:"未知",releaseNotes:"更新内容",releaseNotesEmpty:"暂无更新内容",releaseCheckNow:"检查客户端",releaseInstallNow:"安装更新",releaseDownloading:"正在下载桌面端更新",releaseDownloadedReady:"桌面端更新已准备好,可以安装",releaseDownloadedReadyWithProgress:"桌面端更新已准备好({percent}%),可以安装",releaseDownloadFailed:"下载失败",releaseInstallReadyDialogTitle:"更新包已下载完成",releaseInstallReadyDialogDescription:"新版本 {version} 已准备好,现在可以安装。",releaseInstallReadyWarning:"安装后需要重启应用。",releaseInstallReadyConfirm:"安装并重启",releaseDownloadedNotificationTitle:"客户端更新已下载",releaseDownloadedNotificationBody:"新版本 {version} 已准备好,请到设置里安装。",releaseOpenPage:"打开发布页",releaseRollback:"回退版本",releaseUpdateBadge:"新版本",releaseUpdateReady:"发现新版本",releaseUpToDate:"已是最新版本",releaseCheckFailed:"检查失败",releaseInstallerMissing:"有新版本,暂无安装包",releaseSignatureMissing:"有新版本,缺少校验信息",releaseInstallStarted:"安装已开始",releaseInstallFailed:"安装失败",releaseRestartRequired:"更新已安装,重启应用后生效",releaseRestartDialogTitle:"安装成功",releaseRestartDialogDescription:"新版本 {version} 已安装完成,请重启应用程序后继续使用。",releaseRestartLater:"稍后",releaseRestartConfirm:"是,立即重启",releaseRestartFailed:"重启应用失败",releasePageOpenFailed:"打开页面失败",androidInstallerStarted:"已交给系统安装器,安装完成前你仍可以取消",androidInstallPermissionRequired:"请先允许当前应用安装未知来源应用",androidInstallCancelled:"安装已取消或未完成,可重新触发安装",androidInstallSucceeded:"已检测到新版本完成安装",releaseRollbackStarted:"已开始回退",releaseRollbackFailed:"回退失败",clientUpdateUnsupported:"当前不支持安装更新",logout:"退出登录"},home:{title:"从一条会话继续,而不是从后台表格开始",subtitle:"这里先挑一个工作区和会话,真正的工作区在下一步。",terminalsEntry:"进入终端页",workspaceSection:"工作区",sessionSection:"最近会话",emptyWorkspaces:"还没有导入工作区。先在 Host 侧导入后,这里会出现入口。",emptySessions:"当前工作区还没有可继续的会话。",noActivity:"暂时还没有活动"},shell:{hostSwitcherTitle:"HOST 切换",hostSwitcherAriaLabel:"切换 HOST",hostSwitcherSavedSection:"手动保存",hostSwitcherDiscoveredSection:"自动发现",hostSwitcherCurrentBadge:"当前",hostSwitcherDiscoveredBadge:"发现",hostSwitcherPeerBadge:"Peer",hostSwitcherSwitching:"切换中",hostSwitcherDetailAction:"详情",hostSwitcherDetailAriaLabel:"{name} 详情",hostSwitcherAddAction:"新增 HOST",hostSwitcherAddPeerHostAction:"添加 Peer Host",hostSwitcherNameLabel:"HOST 名称",hostSwitcherNamePlaceholder:"例如:办公室 HOST",hostSwitcherUrlLabel:"HOST 地址",hostSwitcherUrlPlaceholder:"例如:http://10.10.1.8:3002",hostSwitcherSaveAction:"保存 HOST",hostSwitcherDetailTitle:"HOST 详情",hostSwitcherPrimaryHostTitle:"主 HOST",hostSwitcherDetailStatusLabel:"连接状态",hostSwitcherDetailStatusDirect:"直接连接",hostSwitcherDetailStatusRelay:"中继连接",hostSwitcherDetailRouteLabel:"连接方式",hostSwitcherDetailAddressLabel:"地址",hostSwitcherDetailLatencyLabel:"延迟",hostSwitcherDetailTrafficLabel:"流量",hostSwitcherDetailResourceTitle:"资源占用",hostSwitcherDetailLatencyLoading:"检测中",hostSwitcherDetailUnavailable:"不可用",hostSwitcherDetailCpuLabel:"CPU",hostSwitcherDetailCpuValue:"{usage} · {cores} 核",hostSwitcherDetailMemoryLabel:"内存",hostSwitcherDetailDiskLabel:"磁盘",hostSwitcherAliasLabel:"HOST 别名",hostSwitcherAliasPlaceholder:"4 个英文字母",hostSwitcherAliasRule:"别名只能使用英文字母,最多 4 个。",hostSwitcherAliasInvalid:"别名只能使用英文字母,最多 4 个。",hostSwitcherAliasSaveAction:"保存别名",hostSwitcherAliasSaveSuccess:"HOST 别名已保存。",hostSwitcherPeerTitle:"作为 Peer HOST 使用",hostSwitcherPeerSectionTitle:"Peer HOST",hostSwitcherPeerDescription:"启用前会检查主 HOST 到目标 HOST 的网络、版本和登录状态。全部通过后,工作区才能通过主 HOST 访问它。",hostSwitcherPeerStatusLabel:"Peer 状态",hostSwitcherPeerEnableAction:"启用 Peer",hostSwitcherPeerReconnectAction:"手动重连",hostSwitcherPeerDisableAction:"停用 Peer",hostSwitcherPeerChecking:"检查中",hostSwitcherPeerPasswordOneTimeHint:"目标 HOST 密码只用于本次启用检查,不会保存到主 HOST。",hostSwitcherPeerLoginRequired:"请先填写目标 HOST 的用户名和密码。",hostSwitcherPeerEnableSuccess:"Peer HOST 已启用。",hostSwitcherPeerReconnectSuccess:"Peer HOST 已重新连接。",hostSwitcherPeerEnableFailed:"启用 Peer HOST 失败。",hostSwitcherPeerReconnectFailed:"Peer HOST 重连失败。",hostSwitcherPeerDisableSuccess:"Peer HOST 已停用。",hostSwitcherPeerDisableFailed:"停用 Peer HOST 失败。",hostAddInvalidUrl:"HOST 地址不正确。",hostAddDuplicate:"这个 HOST 已经保存过。",hostAddIncompleteCredentials:"用户名和密码需要一起填写。",hostAddSuccess:"{name} 已保存。",hostAddFailed:"保存 HOST 失败。",hostDeleteAction:"删除 HOST",hostDeleteAriaLabel:"删除 HOST {name}",hostDeleteConfirmAction:"确认删除",hostDeleteBusy:"删除中",hostDeleteSuccess:"{name} 已删除。",hostDeleteFailed:"删除 {name} 失败。",hostSwitchFailed:"切换 HOST 失败。",hostSwitchMissing:"找不到这个 HOST。",hostSwitchUnreachable:"{name} 当前不可达。",hostDiscoveryRefreshing:"正在查找局域网 HOST…",hostDiscoveryFailed:"局域网 HOST 查找失败。",manageWorkspaceHostLabel:"使用的 HOST",manageWorkspaceHostSelectLabel:"选择这个项目使用的 HOST",manageWorkspaceHostCurrentOption:"主 HOST · {alias}",manageWorkspaceHostPeerOption:"Peer HOST · {alias}",manageWorkspaceHostHint:"当前项目会通过 {hostName} 打开。",manageWorkspaceHiddenSectionTitle:"已隐藏项目",manageWorkspaceRemotePathTitle:"选择 Peer HOST 上的项目目录",manageWorkspaceRemotePathDescription:"Peer HOST 上没有找到同名项目“{name}”。请选择它在这台 HOST 上对应的目录,保存后会先注册为项目再切换。",manageWorkspaceRemotePathSubmit:"使用这个目录",hostSwitcherPeerWorkspaceDescription:"来自 {hostName} · {path}",hostSwitcherPeerWorkspaceUnavailableDescription:"{hostName} 当前不可用,暂时不能打开这个工作区。",hostSwitcherPeerUnavailableBadge:"不可用",hostSwitcherPeerUnavailable:"{hostName} 当前不可用",hostSwitcherPeerVersionMismatchBadge:"版本不一致",hostSwitcherPeerVersionMismatch:"{hostName} 版本不一致,暂时不能打开",hostSwitcherPeerUnauthorizedBadge:"需要登录",hostSwitcherPeerUnauthorized:"{hostName} 需要先登录后才能打开",hostSwitcherPeerWorkspaceRouteUnsupported:"这个工作区暂时还不能打开",hostSwitcherPeerWorkspaceRouteUnsupportedDescription:"{hostName} 的工作区已经显示出来了,等代理接口接好后就能从这里进入。"},terminal:{title:"终端",heroTitle:"把真实 PTY 留在 Host,把操作入口留在工作台",heroSubtitle:"这里不伪造输出,不把终端和进程搅在一起,只消费 Host 统一托管的真实终端流。",workspaceSection:"工作区与终端",workspaceField:"当前工作区",shellField:"新终端使用的 Shell",runtimeField:"Runtime",runtimeAutoOption:"自动选择",runtimeAutoShortLabel:"auto",runtimeAutoDescription:"按 Host 默认策略选择当前终端 runtime。",runtimePersistentLabel:"持久会话",runtimePersistentShortLabel:"持久",runtimeTmuxDescription:"持久化外部会话,适合需要后台常驻的开发终端。",runtimeWindowsPersistentDescription:"使用基于 ConPTY 的 Windows 持久化会话,让终端在 Host 重启后仍可继续保留。",runtimeEmbeddedDescription:"由当前 Host 直接托管,适合作为轻量回退方案。",runtimeConptyPowerShellLabel:"PowerShell 持久会话",runtimeConptyCmdLabel:"CMD 持久会话",runtimeConptyGitBashLabel:"Git Bash 持久会话",runtimeMissingDialogTitle:"当前系统没有安装 tmux",runtimeMissingDialogDescription:"tmux runtime 无法继续创建持久化终端。你可以先安装 tmux,或者临时切换到 embedded-pty 继续。",runtimeMissingInstallDescription:"建议优先安装 tmux,这样终端才能在 Host 重启后继续保留。",runtimeMissingInstallMacArm:"macOS(Apple Silicon / Homebrew):arch -arm64 brew install tmux",runtimeMissingInstallMacIntel:"macOS(Intel Mac / Homebrew):brew install tmux",runtimeMissingInstallDebian:"Ubuntu / Debian:sudo apt install tmux",runtimeMissingInstallFedora:"Fedora:sudo dnf install tmux",runtimeMissingFallbackDescription:"如果现在先切到 embedded-pty,本次终端可以继续创建,但它不会作为外部持久会话保留。",runtimeMissingKeepAction:"先不切换",runtimeMissingFallbackAction:"切换到 embedded-pty 并继续",runtimeMissingFallbackPending:"正在切换…",shellUnavailable:"当前不可用",workspaceLoadFailed:"工作区或终端列表暂时没有拉回来。",terminalSection:"终端实例",templateSection:"命令模板",stageEmptyTitle:"还没有选中终端",stageEmptySubtitle:"先创建一个终端,或者运行一个命令模板。",emptyTerminals:"当前工作区还没有终端实例。",emptyTemplates:"当前工作区还没有命令模板。",createButton:"新建终端",creating:"正在创建终端…",creationPendingDescription:"Host 正在启动真实 PTY,连上以后这个窗口会立刻接管显示。",defaultTerminalName:"工作终端",created:"终端已经创建并接入 Host。",createFailed:"终端创建失败。",closeButton:"关闭终端",closing:"正在关闭终端…",closed:"终端关闭请求已经提交。",closeCompleted:"终端已关闭。",closePendingDescription:"关闭请求已经发给 Host,前台不会阻塞,系统会继续同步最终结果。",closeSyncDelayed:"Host 还在后台处理关闭,列表会在后续刷新时继续同步。",closeFailed:"终端关闭失败。",inputLabel:"向当前终端发送命令",inputPlaceholder:"例如:pnpm test",sendButton:"发送到终端",inputFailed:"终端输入发送失败。",outputEmpty:"终端已经连上,但暂时还没有输出。",outputTruncated:"断线期间有一段输出超出缓存窗口,当前只补回了仍保留的部分。",connectedHint:"当前输出来自 Host 真实 PTY 流。",moreActions:"终端操作",duplicateAction:"复制标签",duplicateSuccess:"已按当前终端配置新建一个标签。",duplicateFailed:"复制终端标签失败。",disconnectAction:"断开",disconnected:"终端连接已断开。",reconnectAction:"重连",reconnectRequested:"终端重连请求已发出。",deleteAction:"删除",deleting:"正在删除终端…",deleted:"终端记录已删除。",deletePendingDescription:"删除请求已经发给 Host,前台不会阻塞,系统会在后台继续同步列表。",deleteSyncDelayed:"Host 还在后台处理删除,列表会在后续刷新时继续同步。",deleteFailed:"终端记录删除失败。",closePendingBadge:"关闭中",deletePendingBadge:"删除中",pinAction:"固定",unpinAction:"取消固定",zoomLabel:"终端缩放",zoomInAction:"放大终端显示",zoomOutAction:"缩小终端显示",zoomResetAction:"恢复默认缩放",openExternalAction:"独立窗口",openExternalFailed:"打开终端独立窗口失败。",toolbarToggleAction:"展开终端工具菜单",mobileSwipeHint:"左右滑动切换终端",mobileSwipePosition:"{current} / {total}",mobileDrawerAction:"打开快捷终端列表",mobileDrawerTitle:"快捷终端",mobileDrawerDescription:"右滑呼出列表,点一下就切到别的终端。",mobilePinnedSectionTitle:"已固定终端",mobileDrawerEmptyTitle:"当前还没有终端",mobileDrawerEmptyDescription:"先新建一个终端,这里才会出现可切换的列表。",mobileCreateSheetTitle:"新建终端",mobileCreateShellLabel:"终端类型",mobileCreateShellDescription:"先选这次要开的 Shell,别把桌面端那套下拉框搬到手机上。",mobileCreateRuntimeLabel:"会话方式",mobileCreateRuntimeDescription:"再决定它是持久保留,还是只作为当前 runtime 会话。",mobileCreateLoadingShells:"正在读取当前系统可用的终端类型…",mobileCreateConfirm:"创建这个终端",createDialogTitle:"新建终端",createDialogShellDescription:"先选这次要开的 Shell,再创建终端。Windows 下不再偷偷按默认值直接起。",createDialogRuntimeDescription:"再决定它是持久保留,还是只作为当前 runtime 会话。",createDialogConfirm:"创建终端",mobileRuntimePersistentTitle:"持久会话",mobileRuntimePersistentDescription:"适合需要一直挂着的开发终端,创建后会作为可恢复会话保留。",mobileRuntimeSessionTitle:"runtime(当前会话)",mobileRuntimeSessionDescription:"直接由当前 Host 托管,创建更轻,但不会保留成外部持久会话。",mobileWorkspaceSwitcherPlaceholder:"选择项目",mobileEmptyTitle:"这里还没有终端内容",mobileEmptyDescription:"先新建一个终端,或者右滑呼出快捷列表,切到当前工作区已有的终端。",layoutLabel:"分栏布局",layoutSingleAction:"单栏显示",layoutVerticalAction:"左右分栏",layoutHorizontalAction:"上下分栏",saveLogAction:"保存日志",saveLogSuccess:"终端日志已保存。",saveLogFailed:"终端日志保存失败。",logEmpty:"当前终端还没有可保存的日志内容。",bindToPaneAction:"绑定到当前分栏",bindToPrimaryPaneAction:"绑定到主分栏",bindToSecondaryPaneAction:"绑定到副分栏",panePrimary:"主分栏",paneSecondary:"副分栏",splitEmptySubtitle:"先点一个标签,或者新建一个终端,把它绑定到当前分栏。",statusBadge:{creating:"启动中",running:"运行中",closed:"已关闭",error:"异常"},recoveryComplete:"已回到刷新前的终端,缓存内的关键输出已经补回。",recoveryTruncated:"已恢复到上一个终端,但断线期间的部分输出已经超出缓存窗口。",recoveryIdleClosed:"上一个终端已因空闲超时被 Host 自动关闭,你现在看到的是关闭前保留的输出。",reconnect:"手动重连",liveConnected:"实时流已接入",templateName:"模板名称",templateCommand:"主命令",templateArgs:"参数(空格分隔)",templateCreateButton:"保存模板",templateCreated:"命令模板已经保存。",templateCreateFailed:"命令模板保存失败。",templateRunSent:"命令模板已经发送到当前终端。",templateRunCreatedTerminal:"命令模板已在新终端中启动。",templateRunFailed:"命令模板执行失败。",connection:{connected:"已连接",reconnecting:"正在重连",reconnect_failed:"重连失败",closed:"已关闭"}},conversation:{titleFallback:"继续对话",historyLoading:"正在从 Host 拉取消息历史…",historyLoadingOlder:"正在加载更早的消息…",historyLoadFailed:"历史消息暂时没有拉回来,可以稍后再试。",timelineEmpty:"这条会话还没有消息。你发出的第一句话会直接进入 Host 链路。",turnAbortedUser:"上一轮已由你手动停止。",turnAbortedUnexpected:"上一轮意外中断,没有正常结束。",turnAbortedGeneric:"上一轮已中断,没有正常结束。",scrollToBottomAction:"回到底部",rawRefLabel:"来源",copyAction:"复制",copyContentSuccess:"内容已复制。",copyContentFailed:"内容复制失败。",selectionTodoAction:"代办",selectionActionButton:"操作",selectionActionSubmit:"新开操作子会话",selectionActionPromptLabel:"你想让它做什么",selectionActionPromptPlaceholder:"比如:解释这段话、整理成笔记,或调用指定接口处理它",selectionActionIncludeContext:"包含当前上下文",selectionActionContextUnavailable:"当前选区跨了多条消息,没法安全继承上下文,只能按无上下文新建子会话。",selectionActionDefaultPrompt:"请处理这段内容。",selectionActionPreviewLabel:"已选内容",selectionActionTargetLabel:"新会话设置",selectionActionQuotedLabel:"选中文本",selectionActionFailed:"创建操作子会话失败。",actionSessionBadge:"操作",actionInheritedSelectionSummary:"已默认折叠来自“{parentTitle}”的一段选中文本。",forkFromHereAction:"从这里分叉",forkingAction:"正在分叉…",forkMessageSucceeded:"已从这条消息创建新分支。",forkMessageFailed:"从这条消息分叉失败。",forkDraftLabel:"分叉引用",forkDraftEmpty:"这条消息没有可引用的文本内容。",forkDraftClear:"取消这次分叉引用",forkTargetProviderLabel:"目标 CLI",forkTargetModelLabel:"目标模型",forkTargetSummary:"源 CLI:{sourceProvider} · 目标 CLI:{targetProvider}",forkInlineModelLoading:"正在读取模型列表…",forkInlineNativeHint:"保持同一 CLI,继续走原生分叉。",forkInlineCrossHint:"已切到不同 CLI,将按文本历史重建新会话。",forkSwitchConfirmTitle:"切换到其他 CLI?",forkSwitchConfirmDescription:"同一 CLI 会尽量保留原生分叉体验;切到其他 CLI 会改成跨供应商分叉。",forkSwitchConfirmKeepTitle:"会保留",forkSwitchConfirmKeepBody:"分叉点之前的用户消息和助手文本。",forkSwitchConfirmConvertTitle:"会转换",forkSwitchConfirmConvertBody:"可继承文本会重建到新的 CLI 会话里。",forkSwitchConfirmDropTitle:"会丢失",forkSwitchConfirmDropBody:"工具调用、权限交互、附件和运行中状态。",forkSwitchConfirmAction:"确认切换",forkSwitchKeepNative:"保持原生",forkProviderNativeUnsupported:"当前 provider 还不支持原生 fork",forkProviderReconstructedUnsupported:"当前 provider 还不能作为跨 provider 分叉目标",loadMore:"加载更多消息",composerPlaceholder:"把下一步交代清楚,剩下的交给这条会话继续跑。",sendButton:"发送消息",queueTitle:"待发队列",queueDescription:"当前这轮结束后,队列里的消息会按顺序自动继续处理。",queueOrderPrefix:"队列序号",queueStatusQueued:"等待中",queueStatusFailed:"发送失败",queueDelete:"删除",queueDeleting:"删除中",queueImageOnly:"仅图片附件",sendGuidanceButton:"追加引导",queueGuidanceButton:"加入队列",queueSteer:"引导",queueSteering:"引导中",resendButton:"重试发送",quickPhraseTrigger:"快捷短语",quickPhraseModalTitle:"快捷短语",quickPhraseModalDescription:"这里集中管理你常用的会话指令,点一下就能直接填回当前输入框。",quickPhraseCreateLabel:"新增短语",quickPhraseOpenCreateAction:"新增短语",quickPhraseCreateModalTitle:"新增快捷短语",quickPhraseCreateModalDescription:"把常用指令单独存起来,后面在任何设备上都能直接复用。",quickPhraseCreatePlaceholder:"输入一条常用短语,保存后下次可以直接复用。",quickPhraseCreateAction:"添加短语",quickPhraseListLabel:"快捷短语列表",quickPhraseEmpty:"还没有可用的快捷短语,先加一条最常用的。",quickPhraseOrderLabel:"第 {index} 条",quickPhraseMoveUp:"上移短语",quickPhraseMoveDown:"下移短语",quickPhraseDelete:"删除短语",quickPhraseSaveFailed:"快捷短语保存失败,请稍后再试。",sendingState:"发送中",sentState:"已同步",failedState:"发送失败",contextUsageTitle:"当前上下文占用",contextUsageUnavailable:"当前上下文占用暂时不可用",contextUsageEstimated:"上限为估算值",contextUsageCachedTokens:"缓存命中 {count}",contextUsageSourceProviderLog:"上限来自 provider 运行日志",contextUsageSourceProviderRuntime:"上限来自 provider runtime",contextUsageSourceProviderConfig:"上限来自 provider 配置",contextUsageSourceModelMap:"上限来自模型映射",headerWorkspace:"工作区",headerProvider:"Provider",headerCapability:"能力摘要",connectionConnected:"已连接",connectionReconnecting:"正在重连",connectionReconnectFailed:"重连失败",connectionClosed:"连接已关闭",runtimeErrorTitle:"会话运行失败",runtimeErrorFallbackDetail:"CLI 提供商返回了错误,但没有提供更多细节。",runtimeErrorCodeLabel:"错误码",runtimeErrorDetailLabel:"错误详情",reconnectExplain:"实时链路断开了,系统正在补回缺失消息。",reconnectFailedExplain:"自动恢复没有成功。你可以手动重试,或者稍后重新进入会话。",reconnectExplainWithRoute:"实时链路断开了,系统正在补回缺失消息。当前连接方式:{route}。",reconnectFailedExplainWithRoute:"自动恢复没有成功。你可以手动重试,或者稍后重新进入会话。当前连接方式:{route}。",capabilityDenied:"当前会话不支持这个动作",capabilitySendDisabled:"当前 provider 不支持发送新消息",capabilityAttachmentDisabled:"当前会话还不支持附件输入",capabilityInterruptDisabled:"当前会话不支持中断运行",sidebarTitle:"当前会话上下文",sidebarSubtitle:"这里只保留最小能力摘要,不把页面做成后台控制台。",reconnectButton:"手动恢复实时同步",headerResumedAt:"最近续接",headerLastSyncAt:"最近同步",historyPages:"历史分页",syncStatusIdle:"同步空闲",syncStatusSyncing:"同步中",syncStatusError:"同步异常",capabilityResume:"可续接",capabilitySend:"可发送",capabilityInterrupt:"可中断",capabilityTools:"工具调用",attachmentsLabel:"附件",filePanelTitle:"文件管理",filePanelSubtitle:"这里的文件能力只服务当前会话,不把页面拉成重型 IDE。",filePanelNoWorkspace:"当前还没有选中项目,暂时不能浏览或挂载文件。",filePanelRefresh:"刷新",filePanelCopyPath:"复制路径",filePanelCopyAbsolutePath:"复制绝对路径",filePanelCopyRelativePath:"复制相对路径",filePanelCopyAbsolutePathSuccess:"绝对路径已复制。",filePanelCopyRelativePathSuccess:"相对路径已复制。",filePanelCopyPathFailed:"路径复制失败。",filePanelCopy:"复制",filePanelCut:"剪切",filePanelPaste:"粘贴",filePanelCopySelectionSuccess:"已复制 {count} 项,可到目标目录粘贴。",filePanelCutSelectionSuccess:"已剪切 {count} 项,可到目标目录粘贴。",filePanelPasteSuccess:"已粘贴 {count} 项。",filePanelPasteFailed:"粘贴失败,请检查目标目录和重名冲突。",filePanelSelectionCount:"已选 {count} 项",filePanelClipboardCopyReady:"剪贴板中有 {count} 个待复制项目",filePanelClipboardCutReady:"剪贴板中有 {count} 个待移动项目",filePanelOpenFile:"打开文件",filePanelExpandDirectory:"展开文件夹",filePanelCollapseDirectory:"折叠文件夹",filePanelActionsMenu:"文件操作",filePanelSearchPlaceholder:"输入文件名或路径片段",filePanelSearchButton:"搜索",filePanelShowSearch:"打开搜索",filePanelHideSearch:"收起搜索",filePanelSearchEmpty:"没有找到匹配的文件。",filePanelSearchResults:"搜索结果",filePanelSearchFailed:"文件搜索失败,请稍后再试。",filePanelBrowse:"工作区文件",filePanelCollapseCurrent:"折叠当前选中",filePanelCollapseAll:"全部折叠",filePanelBackDirectory:"返回上级",filePanelEmptyDirectory:"这个目录里暂时没有可显示的文件。",filePanelRecentTitle:"最近打开",filePanelEmptyRecent:"最近还没有打开记录。",filePanelContextTitle:"已挂载文件",filePanelEmptyContexts:"当前会话还没有挂载文件管理。",filePanelEditorTitle:"预览与编辑",filePanelEditorPlaceholder:"这里只做轻量文本编辑,不在这里做完整 IDE。",filePanelSelectHint:"先从目录、搜索或最近打开里选一个文件。",filePanelUnsupported:"这个文件当前不能在侧栏里直接编辑。",filePanelAttach:"挂到会话",filePanelAttached:"已挂载",filePanelDetach:"解绑",filePanelSave:"保存",filePanelSaving:"保存中",filePanelLoadFailed:"文件管理面板加载失败。",filePanelOpenFailed:"文件打开失败。",filePanelSaveSuccess:"文件已经保存。",filePanelSaveFailed:"文件保存失败。",fileViewerHint:"当前以 {language} 模式打开,支持预览与编辑保存。",fileViewerModeLabel:"文件查看模式",fileViewerPreview:"预览",fileViewerPresentation:"演示文档",fileViewerCode:"代码",fileViewerEdit:"编辑",fileViewerPlainText:"纯文本",fileViewerHtml:"HTML",fileViewerImage:"图片",fileViewerPdf:"PDF",fileViewerRefreshPreview:"刷新",fileViewerRefreshFailed:"文件预览刷新失败。",fileViewerExportPdf:"导出 PDF",fileViewerExportPdfRunning:"导出中",fileViewerExportPdfSuccess:"PDF 已导出到 {path}",fileViewerExportPdfFailed:"PDF 导出失败。",fileViewerExportPdfTimeout:"PDF 导出超时,请稍后重试。",fileViewerExportPdfMissingHtml:"当前没有可导出的 HTML 内容。",fileViewerExportPptx:"导出 PPTX",fileViewerExportPptxRunning:"导出中",fileViewerExportPptxSuccess:"PPTX 已导出到 {path}",fileViewerExportPptxFailed:"PPTX 导出失败。",fileViewerExportPptxMissingHtml:"当前没有可导出的 HTML 内容。",fileViewerExportTaskTimeout:"导出超时,请稍后重试。",fileViewerOpenExternal:"外部打开",fileViewerOpenExternalFailed:"外部打开失败。",fileViewerOpenInWindow:"独立窗口",fileViewerOpenInWindowFailed:"独立窗口打开失败。",fileViewerWindowTitle:"文件预览",fileViewerCollapse:"收起预览",fileViewerExpand:"展开预览",fileViewerZoomIn:"放大",fileViewerZoomOut:"缩小",fileViewerFit:"适配",fileViewerActualSize:"原始大小",fileViewerFitWidth:"适宽",fileViewerPreviousPage:"上一页",fileViewerNextPage:"下一页",fileViewerPageIndicator:"第 {page} 页",fileViewerSizeLabel:"查看器尺寸",fileViewerSizeDefault:"默认",fileViewerSizeWide:"加宽",fileViewerSizeFull:"铺满",fileViewerDiffModified:"已修改",fileViewerDiffAdded:"新增内容",fileViewerImageUnavailable:"当前无法显示图片预览,请尝试刷新或外部打开。",fileViewerPdfUnavailable:"当前无法显示 PDF 预览,请尝试刷新或外部打开。",fileViewerOfficeLoading:"正在加载 ONLYOFFICE 预览…",fileViewerOfficeUnavailable:"当前无法显示 Office 预览,请先检查 ONLYOFFICE 配置和服务状态。",fileViewerOfficeScriptUnavailable:"ONLYOFFICE 编辑器脚本加载失败,请检查服务地址是否可访问。",fileViewerEnterFullscreen:"全屏",fileViewerExitFullscreen:"退出",fileViewerOpenInBrowser:"在浏览器中打开",fileViewerOpenInBrowserFailed:"打开浏览器预览失败。",fileViewerHtmlPreviewLoading:"正在加载 HTML 预览...",fileViewerHtmlPreviewUnavailable:"当前无法显示 HTML 预览,请先切到代码模式查看。",fileViewerHtmlPreviewFailed:"HTML 预览链接生成失败。",fileViewerPresentationBadge:"静态 HTML",fileViewerPresentationSummary:"已识别 {count} 页,画布基准 {size}",fileViewerPresentationWarningCount:"当前有 {count} 条导入提醒。",fileViewerPresentationCurrentPage:"当前页面",fileViewerPresentationUntitled:"未命名页面",fileViewerPresentationReadOnlyHint:"请选择要编辑的组件以查看文本和布局编辑工具",fileViewerPresentationEditHint:"这一版已经支持选中组件、修改文字和基础样式,复杂结构继续保持只读。",fileViewerPresentationCanvasSelectHint:"可以直接点击画布里的组件进入顶部编辑栏,也可以在右侧组件列表里切换。",fileViewerPresentationUnsupported:"这份 HTML 还不适合进入演示文档视图。",fileViewerPresentationUnsupportedReason:"原因:{reason}",fileViewerPresentationSelectNode:"先在右侧组件列表里选一个可编辑节点。",fileViewerPresentationAddPage:"新增页面",fileViewerPresentationDuplicatePage:"复制页面",fileViewerPresentationDeletePage:"删除页面",fileViewerPresentationMovePageUp:"上移页面",fileViewerPresentationMovePageDown:"下移页面",fileViewerPresentationPageActions:"页面操作",fileViewerPresentationDragToSort:"拖拽排序",fileViewerPresentationUndoAction:"撤销上一步",fileViewerPresentationInspector:"组件属性",fileViewerPresentationComponentList:"组件列表",fileViewerPresentationEditable:"可编辑",fileViewerPresentationReadOnly:"只读",fileViewerPresentationTextLabel:"文字内容",fileViewerPresentationTextDescription:"这里直接改组件文案,中间画布会实时刷新。",fileViewerPresentationTextToolbar:"文字工具栏",fileViewerPresentationFontFamilyLabel:"字体",fileViewerPresentationFontPresetTitle:"等线 Light(标题)",fileViewerPresentationFontPresetSans:"思源黑体",fileViewerPresentationFontPresetSerif:"衬线正文",fileViewerPresentationFontPresetMono:"等宽字体",fileViewerPresentationBoldAction:"加粗",fileViewerPresentationItalicAction:"倾斜",fileViewerPresentationUnderlineAction:"下划线",fileViewerPresentationFontSizeIncreaseAction:"字体放大",fileViewerPresentationFontSizeDecreaseAction:"字体缩小",fileViewerPresentationLineHeightAuto:"默认行距",fileViewerPresentationFontSizeLabel:"字号",fileViewerPresentationFontWeightLabel:"字重",fileViewerPresentationTextColorLabel:"文字颜色",fileViewerPresentationBackgroundColorLabel:"背景颜色",fileViewerPresentationTextAlignLabel:"对齐",fileViewerPresentationLineHeightLabel:"行高",fileViewerPresentationPaddingLabel:"内边距",fileViewerPresentationRadiusLabel:"圆角",fileViewerPresentationPositionXLabel:"水平位置",fileViewerPresentationPositionYLabel:"垂直位置",fileViewerPresentationWidthLabel:"组件宽度",fileViewerPresentationHeightLabel:"组件高度",fileViewerPresentationDuplicateAction:"复制当前组件",fileViewerPresentationKeepOriginal:"保持原样",fileViewerPresentationAlignLeft:"左对齐",fileViewerPresentationAlignCenter:"居中",fileViewerPresentationAlignRight:"右对齐",fileViewerPresentationTextMode:"文本",fileViewerPresentationLayoutMode:"布局",fileViewerPresentationLayoutHint:"这里改的是组件位置和尺寸,画布拖拽与保存会一起生效。",fileViewerPresentationLayoutSelectNode:"先选一个支持布局编辑的组件。",fileViewerPresentationLayoutEditable:"可做布局编辑",fileViewerPresentationLayoutLocked:"当前不能做布局编辑",fileViewerPresentationLayoutUnsupported:"这个组件当前还不能安全做布局编辑。",fileViewerPresentationLayoutStrictLocked:"该组件处在流式布局里,不能直接自由拖动。先把它所在容器转换成自由布局。",fileViewerPresentationLayoutFreezeContainer:"转换当前容器为自由布局",fileViewerPresentationLayoutRootLocked:"页面根容器这轮不允许直接改布局。",fileViewerPresentationLayoutSelectionCount:"已选中 {count} 个组件",fileViewerPresentationLayoutAlignLeft:"左边对齐",fileViewerPresentationLayoutAlignRight:"右边对齐",fileViewerPresentationLayoutAlignTop:"顶部对齐",fileViewerPresentationLayoutAlignBottom:"底部对齐",fileViewerPresentationResizeHandle:"调整组件大小",filePanelAttachSuccess:"文件已经挂到当前会话。",filePanelAttachFailed:"文件挂载失败。",filePanelDetachSuccess:"文件已经从当前会话解绑。",filePanelDetachFailed:"文件解绑失败。",filePanelNewFile:"新建文件",filePanelNewDirectory:"新建目录",filePanelUpload:"上传文件",filePanelDownload:"下载文件",filePanelUploadSuccess:"已上传 {name}。",filePanelUploadFailed:"文件上传失败。",filePanelDownloadSuccess:"已开始下载 {name}。",filePanelDownloadFailed:"文件下载失败。",filePanelDelete:"删除",filePanelDeleting:"删除中...",filePanelDeleteSuccess:"已删除 {name}。",filePanelDeleteConfirmTitle:"确认删除",filePanelDeleteConfirmDescription:"删除后会立即从当前项目移除,这一步不能撤销。",filePanelDeleteSelectionConfirm:"确认删除选中的 {count} 项吗?",filePanelDeleteSelectionSuccess:"已删除 {count} 项。",filePanelRenameMove:"重命名/移动",filePanelRenameSuccess:"已重命名为 {name}。",filePanelMutateFailed:"文件操作失败,请检查路径和当前状态。",filePanelCreateFilePrompt:"输入要创建的相对文件路径",filePanelCreateDirectoryPrompt:"输入要创建的相对目录路径",filePanelCreateFileDescription:"输入工作区内的相对路径,文件会立刻创建出来。",filePanelCreateDirectoryDescription:"输入工作区内的相对路径,文件夹会立刻创建出来。",filePanelPathFieldLabel:"相对路径",filePanelPathFieldPlaceholder:"例如 src/features/files/index.ts",filePanelCreateFileSubmit:"创建文件",filePanelCreateDirectorySubmit:"创建文件夹",filePanelCreatingFile:"创建文件中...",filePanelCreatingDirectory:"创建文件夹中...",exportAction:"导出会话",exportDialogTitle:"导出当前会话",exportDialogDescription:"可以导出成 Markdown 文件,或者按当前消息样式打印并保存为 PDF。",exportMarkdownAction:"导出 Markdown",exportMarkdownHint:"导出完整消息内容,适合继续编辑、归档和提交。",exportPdfAction:"导出 PDF",exportPdfHint:"会直接下载 PDF 文件,保留当前会话内容排版。",exportHtmlAction:"导出 HTML",exportPreparing:"正在准备导出内容...",exportMarkdownSuccess:"Markdown 已开始导出。",exportPdfPreparing:"PDF 已开始下载。",exportHtmlSuccess:"HTML 已开始导出。",exportLoadFailed:"导出失败,当前会话内容没有完整拉取下来。",exportDownloadFailed:"导出文件失败。",exportPrintFailed:"打开打印窗口失败。",exportPrintContainerTitle:"会话导出",exportMarkdownSessionIdLabel:"会话 ID",exportMarkdownProviderLabel:"Provider",exportMarkdownWorkspaceLabel:"工作区 ID",exportMarkdownCreatedAtLabel:"创建时间",exportMarkdownExportedAtLabel:"导出时间",exportMarkdownTimeLabel:"时间",exportMarkdownTypeLabel:"类型",exportMarkdownAttachmentsLabel:"附件数量",exportMarkdownAttachmentsSectionTitle:"附件",exportMarkdownToolSectionTitle:"工具调用",exportMarkdownToolNameLabel:"工具名",exportMarkdownToolStatusLabel:"状态",exportMarkdownToolInputLabel:"输入",exportMarkdownToolOutputLabel:"输出",exportMarkdownToolErrorLabel:"错误",exportMarkdownToolCallType:"工具调用",exportMarkdownToolResultType:"工具结果",exportMarkdownTextType:"正文",exportMarkdownUnknownSize:"大小未知",filePanelFilterChanges:"仅显示变更",filePanelShowAll:"显示全部",filePanelNoChanges:"当前没有变更文件。",filePanelBinaryPreview:"二进制文件不支持预览。",filePanelDeleteFileConfirm:"确认删除这个文件吗?{path}",filePanelDeleteDirectoryConfirm:"确认删除这个文件夹吗?{path}",filePanelRenameMovePrompt:"输入新的相对路径",filePanelRenameDescription:"只改路径,不改文件内容。填新路径就会同时支持移动目录层级。",filePanelRenameSubmit:"确认重命名",filePanelRenaming:"重命名中...",unavailableAction:"当前不可用",roleUser:"你",roleAssistant:"助手",roleTool:"工具",toolViewImageActiveLabel:"AI正在查看图片",assistantCapabilityBadgeSubAgent:"子会话",codexAgentToolCreateTitle:"创建子会话",codexAgentToolReadTitle:"查看子会话",codexAgentToolUpdateTitle:"更新子会话",codexAgentToolReplyTitle:"回复子会话",codexAgentToolCloseTitle:"关闭子会话",codexAgentToolCreateSummary:"已把一段独立任务交给子 agent 处理。",codexAgentToolReadSummary:"正在读取子 agent 的最新状态和回复。",codexAgentToolUpdateSummary:"已向子 agent 改派或更新当前任务。",codexAgentToolReplySummary:"已把补充消息发给子 agent。",codexAgentToolCloseSummary:"已关闭这个子 agent 会话。",codexAgentToolLabelAgent:"Agent",codexAgentToolLabelNickname:"昵称",codexAgentToolLabelRole:"类型",codexAgentToolLabelModel:"模型",codexAgentToolLabelTargets:"目标",codexAgentToolLabelTimeout:"等待",codexAgentToolLabelMessage:"消息",codexAgentToolLabelReason:"结果",subagentNotificationTitle:"子 agent 汇报",subagentNotificationSummary:"子 agent 已返回本次任务结果。",subagentNotificationLabelSummary:"摘要",subagentNotificationStatusCancelled:"已取消",roleSystem:"系统"},git:{title:"Git 上下文",subtitle:"这里是会话侧边的辅助区,只处理当前工作区里的 Git 事实。",loading:"正在读取当前工作区的 Git 上下文。",refresh:"刷新",panelLoadFailed:"Git 上下文暂时没有加载出来。",uninitializedTitle:"当前目录还没有启用 Git",uninitializedDescription:"先初始化这个目录的 Git 工作区,后面才能查看改动、写提交和追踪历史。",initRepository:"初始化 Git 工作区",initInProgress:"正在初始化…",initSuccess:"Git 工作区已初始化。",initFailed:"初始化 Git 工作区失败。",ahead:"领先",behind:"落后",dirty:"有改动",clean:"已干净",changeCount:"当前有 {count} 个变更文件",noChanges:"当前没有待处理改动。",changesTitle:"当前变更",rulesFirstHint:"规则先于生成,草稿不能绕过校验。",stage:"暂存",unstage:"取消暂存",preview:"预览",stageFailed:"暂存操作失败。",diffTitle:"差异预览",diffLoadFailed:"差异内容暂时没有拉回来。",binaryDiff:"这个文件是二进制改动,侧栏不直接展示内容。",stagedDiff:"暂存区 diff",worktreeDiff:"工作区 diff",emptyDiff:"当前没有可展示的文本差异。",diffTruncated:"差异内容过长,已经做了截断保护。",commitTitle:"提交草稿",defaultRuleName:"默认提交规则",language:"语言",maxLength:"长度",bodyRequired:"正文必填",bodyOptional:"正文可选",issueRequired:"Issue 必填",issueOptional:"Issue 可选",commitSubject:"提交标题",commitSubjectPlaceholder:"在这里输入提交信息",commitBody:"提交正文",commitBodyPlaceholder:"把这次改动说清楚,别写空话。",commitFooter:"提交脚注",commitFooterPlaceholder:"例如:Refs: #123",generateDraft:"AI 起草",validate:"校验草稿",commit:"执行提交",draftFailed:"提交草稿生成失败。",validateFailed:"提交规则校验失败。",commitFailed:"提交失败。",commitSuccess:"提交已经写入当前仓库。",validationPassed:"规则校验通过,可以继续提交。",validationFailed:"规则校验没有通过,先把下面的问题修掉。",branchTitle:"分支",branchPlaceholder:"输入要切换或创建的分支名",switchBranch:"切换",createBranch:"新建",branchFailed:"分支操作失败。",historyTitle:"最近历史",historyHint:"只放最近几条,不做图形历史树。",noHistory:"当前没有可展示的提交历史。",viewAllVersions:"查看所有版本",viewAllVersionsDescription:"这里展示当前仓库已加载的版本历史,共 {count} 条。",viewCommitChanges:"查看更改文件与 DIFF",copyCommitMessage:"复制提交信息",copyCommitMessageSuccess:"提交信息已复制。",copyCommitVersion:"复制 Git 版本号",copyCommitVersionSuccess:"Git 版本号已复制。",commitDetailTitle:"版本详情",commitDetailDescription:"当前查看提交 {hash} 的完整改动。",commitDetailLoading:"正在读取提交详情…",commitDetailEmpty:"当前没有可展示的提交详情。",commitDetailLoadFailed:"提交详情暂时没有拉回来。",commitVersionLabel:"Git 版本号",commitHashLabel:"提交 Hash",commitAuthorLabel:"作者",commitTimeLabel:"提交时间",commitMessageLabel:"提交信息",changedFilesTitle:"变更文件",commitDiffLabel:"提交 DIFF",renamedFromLabel:"从 {path} 重命名",explainCommitTitle:"解释版本更改",explainCommitDescription:"先选择一个 CLI 供应商,再新建会话分析这个提交。",explainCommitAction:"解释更改",startExplainCommit:"开始解释",explainCommitStarted:"解释会话已经创建。",explainCommitFailed:"解释更改失败。",remoteTitle:"远程同步",remoteReady:"当前仓库已配置远程。",remoteMissing:"当前仓库还没有远程。",fetch:"Fetch",pull:"Pull",push:"Push",pushNow:"立即推送",publish:"Publish",remoteFailed:"远程同步失败。",remoteAuthAction:"远程认证",remoteAuthTitle:"设置远程仓库认证",remoteAuthDescription:"需要认证的远程仓库,在这里填写本次页面会话使用的用户名、密码或 token。",remoteAuthDescriptionGithub:"检测到当前远程仓库来自 GitHub。GitHub 的 HTTPS Git 操作请使用 Personal Access Token (PAT),不要填写 GitHub 登录密码。",remoteAuthStatusLabel:"认证状态",remoteAuthManageHint:"按仓库分别查看和配置",remoteAuthManageTitle:"管理远程仓库认证",remoteAuthManageDescription:"每个远程仓库单独显示自己的凭据状态,也在这里分别配置。",remoteAuthConfigured:"已配置",remoteAuthConfiguredInSession:"当前页面已配置",remoteAuthConfiguredOnHost:"Host 已配置",remoteAuthNotConfigured:"未配置",remoteAuthGithubPatLabel:"Personal Access Token (PAT)",remoteAuthGithubPatPlaceholder:"输入 GitHub PAT",remoteAuthGithubUsernamePlaceholder:"输入 GitHub 用户名",remoteAuthGithubPatHint:"GitHub 不支持用账号密码做 Git HTTPS 认证。basic 模式请填写 GitHub 用户名 + PAT;token 模式可以直接填写 PAT。",remoteAuthRemember:"记住账号密码到 Host",remoteAuthSessionHint:"默认只在当前页面会话里生效;勾选“记住账号密码到 Host”后,远程同步成功时会写到 Host,后续自动复用。",remoteAuthRememberHint:"勾选记住后,本次远程同步成功时会把认证写到 Host。",remoteAuthSave:"保存认证",remoteAuthSaved:"远程仓库认证已保存,请重新执行同步。",remoteAuthCleared:"已清除当前页面会话里的远程认证设置。",selectRemoteTitle:"选择推送仓库",selectRemoteDesc:"勾选要推送到的远程仓库,支持多选。",noRemotes:"当前仓库没有配置任何远程仓库。",pushSelected:"推送 ({count})",pushing:"推送中…",pushAllSuccess:"已成功推送到 {count} 个远程仓库。",errors:{unauthorized:"当前登录态已经失效,请重新登录后再试。",workspaceNotFound:"当前会话绑定的工作区不存在,先确认工作区是否还可用。",invalidWorkspace:"当前工作区配置无效,Git 侧栏不能脱离仓库根目录执行。",notGitRepository:"当前工作区不是 Git 仓库,Git 侧栏不会伪造状态。",repoNotFound:"当前工作区找不到可用的 Git 仓库根目录。",pathOutOfWorkspace:"Git 目标超出了当前工作区仓库边界,操作已被拦截。",invalidTarget:"Git 目标路径无效,请先刷新侧栏后重试。",notStaged:"目标文件还不在暂存区里,先确认当前变更状态。",emptyStagedChanges:"暂存区为空,先把要提交的改动放进暂存区。",branchConflict:"当前分支存在冲突或不是快进更新,先同步并处理差异。",branchNotFound:"目标分支不存在,先确认分支名是否正确。",remoteNotFound:"当前仓库还没有可用的 origin 远程,先配置远程再同步。",remoteAuthFailed:"远程仓库认证失败,请先确认当前仓库凭据可用。",pushFailed:"推送失败,请先检查远程状态和本地提交。",pullFailed:"拉取失败,请先确认远程分支状态。",remoteFailed:"远程同步失败,请检查 Git 输出和网络状态。",initFailed:"Git 工作区初始化失败,请确认当前目录可写且 Git 可用。",commitValidationFailed:"提交草稿还没通过规则校验,先把校验问题修掉。",commandTimeout:"Git 操作超时了,先确认仓库状态和网络环境。"}}},Ys="default-host";function zd(i){return!!(i&&"discoveryKey"in i&&typeof i.discoveryKey=="string")}function hm(i,r){var o;return r?i.hosts.find(c=>c.id===r)??((o=i.discoveredHosts)==null?void 0:o.find(c=>c.id===r))??null:null}function mm(i,r){var o;return r?i.hosts.find(c=>c.baseUrl===r)??((o=i.discoveredHosts)==null?void 0:o.find(c=>c.baseUrl===r))??null:null}function Tn(i){var r,o,c,u;return i.activeDiscoveredHostId&&((r=i.discoveredHosts)!=null&&r.some(p=>p.id===i.activeDiscoveredHostId))?i.activeDiscoveredHostId:i.activeHostId&&i.hosts.some(p=>p.id===i.activeHostId)?i.activeHostId:((o=i.hosts[0])==null?void 0:o.id)??((u=(c=i.discoveredHosts)==null?void 0:c[0])==null?void 0:u.id)??null}function Da(i){return hm(i,Tn(i))}function gm(i){var r;return((r=Da(i))==null?void 0:r.baseUrl)??null}function bm(i){return i==="http:"||i==="https:"}function Ue(i){const r=i.trim();if(!r)throw new Error("EMPTY_SERVER_URL");const o=/^[a-zA-Z][a-zA-Z\d+.-]*:\/\//.test(r)?r:`http://${r}`,c=new URL(o);if(!bm(c.protocol))throw new Error("INVALID_SERVER_PROTOCOL");c.hash="",c.search="";const u=c.pathname.replace(/\/+$/,"");return`${c.origin}${u==="/"?"":u}`}const Tt="codingns.auth.remembered-login";function Ji(){return typeof window<"u"&&typeof window.localStorage<"u"}function Zy(i){return i.isNativeMobile?!0:i.isDesktop?i.ui.osFamily==="windows"||i.ui.osFamily==="macos":!1}function ym(i){const r={credentials:null,legacyServerBaseUrl:null};if(!Ji())return r;const o=window.localStorage.getItem(Tt);if(!o)return r;try{const c=JSON.parse(o);if($s(c))return{credentials:i?c[i]??null:null,legacyServerBaseUrl:null};const u=qd(c);if(!u||!i)return{credentials:null,legacyServerBaseUrl:(u==null?void 0:u.serverBaseUrl)??null};const p={hostId:i,username:u.username,password:u.password,savedAt:Date.now()},y={[i]:p};return window.localStorage.setItem(Tt,JSON.stringify(y)),{credentials:p,legacyServerBaseUrl:u.serverBaseUrl}}catch{return window.localStorage.removeItem(Tt),r}}function eS(i){return ym(i).credentials}function tS(i){if(!Ji())return;const r=jd(),o={hostId:i.hostId,username:i.username.trim(),password:i.password,savedAt:Date.now()};!o.hostId||!o.username||!o.password||window.localStorage.setItem(Tt,JSON.stringify({...r,[o.hostId]:o}))}function Sm(i){if(!Ji())return;const r=window.localStorage.getItem(Tt);if(r)try{const o=JSON.parse(r);if($s(o))return;const c=qd(o);if(!c){window.localStorage.removeItem(Tt);return}window.localStorage.setItem(Tt,JSON.stringify({...c,serverBaseUrl:Ue(i)}))}catch{window.localStorage.removeItem(Tt)}}function aS(i){if(!Ji()||!i)return;const r=jd();if(!r[i])return;const o={...r};if(delete o[i],Object.keys(o).length===0){window.localStorage.removeItem(Tt);return}window.localStorage.setItem(Tt,JSON.stringify(o))}function jd(){if(!Ji())return{};const i=window.localStorage.getItem(Tt);if(!i)return{};try{const r=JSON.parse(i);return $s(r)?r:{}}catch{return{}}}function $s(i){return typeof i!="object"||i===null||Array.isArray(i)?!1:Object.values(i).every(r=>Tm(r))}function Tm(i){if(typeof i!="object"||i===null)return!1;const r=i;return typeof r.hostId=="string"&&typeof r.username=="string"&&typeof r.password=="string"&&typeof r.savedAt=="number"&&r.username.trim().length>0&&r.password.length>0}function qd(i){if(typeof i!="object"||i===null)return null;const r=i;if(typeof r.username!="string"||typeof r.password!="string"||typeof r.serverBaseUrl!="string")return null;const o=r.username.trim(),c=r.password,u=Ue(r.serverBaseUrl);return!o||!c?null:{username:o,password:c,serverBaseUrl:u}}function km(i){return{filePath:(i==null?void 0:i.filePath)??null,routePath:(i==null?void 0:i.routePath)??null}}function Gd(i={}){return{x:i.x??null,y:i.y??null,width:i.width??1200,height:i.height??780,minWidth:i.minWidth??720,minHeight:i.minHeight??480}}function iS(i){return{windowId:i.windowId,kind:i.kind,workspaceId:i.workspaceId??null,workspaceName:i.workspaceName??null,sessionId:i.sessionId??null,mode:i.mode??"docked",bounds:Gd(i.bounds),focusOwner:i.focusOwner??null,payload:km(i.payload)}}function ti(i){return{...i,bounds:{...i.bounds},payload:{...i.payload}}}function wm(i){return{descriptors:Object.fromEntries(Object.entries(i.descriptors).map(([o,c])=>[o,ti(c)])),openWindowIds:[...i.openWindowIds],lastActiveWindowId:i.lastActiveWindowId}}function ud(){return{descriptors:{},openWindowIds:[],lastActiveWindowId:null}}function vm(i,r){return{...i,...r,windowId:i.windowId,bounds:Gd({...i.bounds,...r.bounds}),payload:{...i.payload,...r.payload}}}class Cm{constructor(){L(this,"state",ud());L(this,"listeners",new Set);L(this,"subscribe",r=>(this.listeners.add(r),()=>{this.listeners.delete(r)}));L(this,"getState",()=>wm(this.state))}registerDescriptor(r){const o=ti(r),c=this.state.openWindowIds.includes(o.windowId);return this.state={...this.state,descriptors:{...this.state.descriptors,[o.windowId]:o},lastActiveWindowId:c?o.windowId:this.state.lastActiveWindowId},this.emit(),ti(o)}updateDescriptor(r,o){const c=this.state.descriptors[r];if(!c)return null;const u=vm(c,o);return this.state={...this.state,descriptors:{...this.state.descriptors,[r]:u}},this.emit(),ti(u)}getDescriptor(r){const o=this.state.descriptors[r];return o?ti(o):null}getWindows(){return Object.values(this.state.descriptors).map(r=>({descriptor:ti(r),isOpen:this.state.openWindowIds.includes(r.windowId)}))}markWindowOpen(r){if(!this.state.descriptors[r])return!1;const o=this.state.openWindowIds.filter(c=>c!==r);return this.state={...this.state,openWindowIds:[...o,r],lastActiveWindowId:r},this.emit(),!0}markWindowClosed(r){if(!this.state.openWindowIds.includes(r))return!1;const o=this.state.openWindowIds.filter(c=>c!==r);return this.state={...this.state,openWindowIds:o,lastActiveWindowId:this.state.lastActiveWindowId===r?o.at(-1)??null:this.state.lastActiveWindowId},this.emit(),!0}isWindowOpen(r){return this.state.openWindowIds.includes(r)}removeWindow(r){if(!this.state.descriptors[r])return!1;const o={...this.state.descriptors};delete o[r];const c=this.state.openWindowIds.filter(u=>u!==r);return this.state={descriptors:o,openWindowIds:c,lastActiveWindowId:this.state.lastActiveWindowId===r?c.at(-1)??null:this.state.lastActiveWindowId},this.emit(),!0}clear(){const r=this.state.openWindowIds.length>0||this.state.lastActiveWindowId!==null||Object.keys(this.state.descriptors).length>0;this.state=ud(),r&&this.emit()}emit(){for(const r of this.listeners)r()}}function Dm(){return new Cm}const Bs=Dm();function Pm(){return Bs}function rS(i){return He.useSyncExternalStore(Bs.subscribe,()=>i(Bs.getState()))}const Am=Pm();function Kd(){return typeof window<"u"&&typeof window.__TAURI_INTERNALS__<"u"}function Qd(){var p,y;if(typeof navigator>"u")return"unknown";const i=navigator.userAgent.toLowerCase(),r=navigator.userAgentData,o=((p=r==null?void 0:r.platform)==null?void 0:p.toLowerCase())??((y=navigator.platform)==null?void 0:y.toLowerCase())??"",c=`${o} ${i}`,u=o.includes("mac")&&navigator.maxTouchPoints>1;return c.includes("android")?"android":c.includes("iphone")||c.includes("ipad")||c.includes("ipod")||u?"ios":c.includes("mac")?"macos":c.includes("win")?"windows":c.includes("linux")?"linux":"unknown"}function Lm(i){var r;return typeof i=="number"&&Number.isFinite(i)&&i>0?i:typeof window<"u"&&Number.isFinite(window.innerWidth)&&window.innerWidth>0?window.innerWidth:typeof document<"u"&&Number.isFinite((r=document.documentElement)==null?void 0:r.clientWidth)&&document.documentElement.clientWidth>0?document.documentElement.clientWidth:1280}function Rm(i){const r=Lm(i);return r<768?"compact":r<1024?"medium":"expanded"}function Fm(i){const r=Qd();return i==="desktop"?{osFamily:r,windowControlsStyle:r==="macos"?"traffic-lights":r==="windows"?"windows":"none",prefersDesktopChrome:!0,prefersOverlayTitlebar:r==="macos",prefersSystemFontStack:!0}:{osFamily:r,windowControlsStyle:"none",prefersDesktopChrome:!1,prefersOverlayTitlebar:!1,prefersSystemFontStack:!0}}function _(i){return{ok:!1,errorCode:"PLATFORM_NOT_SUPPORTED",detail:i}}function Em(i){const r=i instanceof Error?i.message:"桌面壳调用失败。",o=r.match(/^([A-Z0-9_]+):\s*(.+)$/);return o?{errorCode:o[1],detail:o[2]}:{errorCode:"SHELL_BRIDGE_ERROR",detail:r}}async function oe(i,r){return Qi(i,r)}async function Qi(i,r){if(!Kd())return _("当前运行环境不支持桌面壳能力。");try{return{ok:!0,value:await window.__TAURI_INTERNALS__.invoke(i,r)}}catch(o){return{ok:!1,...Em(o)}}}function Mm(i){switch(i){case"selection":return 10;case"action":return[12];case"gesture":return[10,18,10];case"success":return[16,30,20];case"warning":return[20,36,18];case"error":return[24,40,24,40,20];default:return 10}}function Yd(){return typeof navigator<"u"&&typeof navigator.vibrate=="function"}async function $d(i){if(Yd())try{navigator.vibrate(Mm(i))}catch{return}}async function Js(i,r){if(typeof window>"u"||typeof Notification>"u")return _("当前环境不支持系统通知。");try{if(Notification.permission==="default"&&await Notification.requestPermission()!=="granted"||Notification.permission!=="granted")return _("系统通知权限未授予。");const o=new Notification(i,{body:r});return o.onerror=()=>{},{ok:!0}}catch(o){return{ok:!1,errorCode:"NOTIFICATION_FAILED",detail:o instanceof Error?o.message:"系统通知发送失败。"}}}class Im{constructor(){L(this,"supported",!1)}openExternal(r){return typeof window>"u"?Promise.resolve(_("当前环境无法打开外部链接。")):(window.open(r,"_blank","noopener,noreferrer"),Promise.resolve({ok:!0}))}openLocalFile(){return Promise.resolve(_("当前不是桌面端运行环境。"))}revealInFileManager(){return Promise.resolve(_("当前不是桌面端运行环境。"))}getPlatformInfo(){return Promise.resolve(_("当前不是桌面端运行环境。"))}showNotification(r,o){return Js(r,o)}writeClipboardText(){return Promise.resolve(_("当前不是桌面端运行环境。"))}setWindowState(){return Promise.resolve(_("当前不是桌面端运行环境。"))}readDesktopConfig(){return Promise.resolve(_("当前不是桌面端运行环境。"))}writeDesktopConfig(){return Promise.resolve(_("当前不是桌面端运行环境。"))}scanLocalHosts(){return Promise.resolve(_("当前不是桌面端运行环境。"))}getRuntimeInfo(){return Promise.resolve(_("当前不是桌面端运行环境。"))}checkForUpdate(){return Promise.resolve(_("当前不是桌面端运行环境。"))}downloadUpdate(){return Promise.resolve({ok:!1,errorCode:"PLATFORM_NOT_SUPPORTED",detail:"当前不是桌面端运行环境。"})}installUpdate(){return Promise.resolve({ok:!1,errorCode:"PLATFORM_NOT_SUPPORTED",detail:"当前不是桌面端运行环境。"})}getAndroidRuntimeInfo(){return Promise.resolve(_("当前不是 Android 原生运行环境。"))}installAndroidUpdate(){return Promise.resolve({ok:!1,status:"failed",detail:"当前不是 Android 原生运行环境。"})}rollbackToPreviousVersion(){return Promise.resolve(_("当前不是桌面端运行环境。"))}pickDirectory(){return Promise.resolve(_("当前不是桌面端运行环境。"))}createWindow(){return Promise.resolve(_("当前不是桌面端运行环境。"))}closeWindow(){return Promise.resolve(_("当前不是桌面端运行环境。"))}focusWindow(){return Promise.resolve(_("当前不是桌面端运行环境。"))}listWindows(){return Promise.resolve(_("当前不是桌面端运行环境。"))}isWindowOpen(){return Promise.resolve(_("当前不是桌面端运行环境。"))}getWindowDescriptor(){return Promise.resolve(_("当前不是桌面端运行环境。"))}syncWindowDescriptor(){return Promise.resolve(_("当前不是桌面端运行环境。"))}updateWindowBounds(){return Promise.resolve(_("当前不是桌面端运行环境。"))}syncNativeSidebarLayout(){return Promise.resolve(_("当前不是桌面端运行环境。"))}}class xm{constructor(){L(this,"supported",Yd())}trigger(r){return $d(r)}}class Om{constructor(){L(this,"supported",!0)}openExternal(r){return oe("open_external",{url:r})}openLocalFile(r){return oe("open_local_file",{path:r})}revealInFileManager(r){return oe("reveal_in_file_manager",{path:r})}getPlatformInfo(){return oe("get_platform_info")}async showNotification(r,o){const c=await Js(r,o);return c.ok?c:oe("show_notification",{title:r,body:o})}writeClipboardText(r){return oe("copy_text",{text:r})}setWindowState(r){return oe("set_window_state",{state:r})}readDesktopConfig(){return oe("read_desktop_config")}writeDesktopConfig(r){return oe("write_desktop_config",{patch:r})}scanLocalHosts(){return oe("scan_local_hosts")}getRuntimeInfo(){return oe("get_runtime_info")}checkForUpdate(r){return oe("check_for_update",{channel:r})}async downloadUpdate(r){const o=await oe("download_update",{channel:r});return o.ok?o.value??{ok:!0}:{ok:!1,errorCode:o.errorCode,detail:o.detail}}async installUpdate(r){const o=await oe("install_update",{channel:r});return o.ok?o.value??{ok:!0}:{ok:!1,errorCode:o.errorCode,detail:o.detail}}getAndroidRuntimeInfo(){return Promise.resolve(_("当前不是 Android 原生运行环境。"))}installAndroidUpdate(){return Promise.resolve({ok:!1,status:"failed",detail:"当前不是 Android 原生运行环境。"})}rollbackToPreviousVersion(){return oe("rollback_to_previous_version")}pickDirectory(){return oe("pick_directory")}createWindow(r){return oe("create_window",{descriptor:r})}closeWindow(r){return oe("close_window",{windowId:r})}focusWindow(r){return oe("focus_window",{windowId:r})}listWindows(){return oe("list_windows")}isWindowOpen(r){return oe("is_window_open",{windowId:r})}getWindowDescriptor(r){return typeof r=="string"?oe("get_window_descriptor",{windowId:r}):oe("get_window_descriptor")}syncWindowDescriptor(r){return oe("sync_window_descriptor",{descriptor:r})}updateWindowBounds(r,o){return oe("update_window_bounds",{windowId:r,bounds:o})}syncNativeSidebarLayout(r){return oe("sync_native_sidebar_layout",{layout:r})}}class Hm{constructor(){L(this,"supported",!0)}async trigger(r){(await Qi("perform_haptic_feedback",{kind:r})).ok||await $d(r)}}class Nm{constructor(r){L(this,"supported",!0);this.platform=r}openExternal(r){return typeof window>"u"?Promise.resolve(_("当前环境无法打开外部链接。")):(window.open(r,"_blank","noopener,noreferrer"),Promise.resolve({ok:!0}))}openLocalFile(){return Promise.resolve(_("当前不是桌面端运行环境。"))}revealInFileManager(){return Promise.resolve(_("当前不是桌面端运行环境。"))}getPlatformInfo(){return Promise.resolve(_("当前不是桌面端运行环境。"))}showNotification(r,o){return Js(r,o)}writeClipboardText(r){return Qi("copy_text",{text:r})}setWindowState(){return Promise.resolve(_("当前平台不支持窗口控制。"))}readDesktopConfig(){return Promise.resolve(_("当前不是桌面端运行环境。"))}writeDesktopConfig(){return Promise.resolve(_("当前不是桌面端运行环境。"))}scanLocalHosts(){return Promise.resolve(_("当前不是桌面端运行环境。"))}getRuntimeInfo(){return Promise.resolve(_("当前不是桌面端运行环境。"))}checkForUpdate(){return Promise.resolve(_("当前不是桌面端运行环境。"))}downloadUpdate(){return Promise.resolve({ok:!1,errorCode:"PLATFORM_NOT_SUPPORTED",detail:"当前不是桌面端运行环境。"})}installUpdate(){return Promise.resolve({ok:!1,errorCode:"PLATFORM_NOT_SUPPORTED",detail:"当前不是桌面端运行环境。"})}getAndroidRuntimeInfo(){return this.platform!=="android"?Promise.resolve(_("当前不是 Android 原生运行环境。")):Qi("get_android_runtime_info")}async installAndroidUpdate(r){if(this.platform!=="android")return{ok:!1,status:"failed",detail:"当前不是 Android 原生运行环境。"};const o=await Qi("install_android_update",{manifest:r});return o.ok?o.value??{ok:!1,status:"failed",detail:"Android 更新结果为空。"}:{ok:!1,status:"failed",detail:o.detail}}rollbackToPreviousVersion(){return Promise.resolve(_("当前不是桌面端运行环境。"))}pickDirectory(){return Promise.resolve(_("当前不是桌面端运行环境。"))}createWindow(){return Promise.resolve(_("当前不是桌面端运行环境。"))}closeWindow(){return Promise.resolve(_("当前不是桌面端运行环境。"))}focusWindow(){return Promise.resolve(_("当前不是桌面端运行环境。"))}listWindows(){return Promise.resolve(_("当前不是桌面端运行环境。"))}isWindowOpen(){return Promise.resolve(_("当前不是桌面端运行环境。"))}getWindowDescriptor(){return Promise.resolve(_("当前不是桌面端运行环境。"))}syncWindowDescriptor(){return Promise.resolve(_("当前不是桌面端运行环境。"))}updateWindowBounds(){return Promise.resolve(_("当前不是桌面端运行环境。"))}syncNativeSidebarLayout(){return Promise.resolve(_("当前不是桌面端运行环境。"))}}function Xs(){if(!Kd())return"web";const i=Qd();return i==="ios"?"ios":i==="android"?"android":"desktop"}function Rn(i={}){const r=Xs(),o=Rm(i.viewportWidth),c=r==="ios"||r==="android";return{platform:r,isDesktop:r==="desktop",isWeb:r==="web",isMobile:o!=="expanded",isNativeMobile:c,viewportClass:o,ui:Fm(r),bridge:r==="desktop"?new Om:c?new Nm(r):new Im,windows:Am,haptics:c?new Hm:new xm}}const Us="codingns.client.runtime-config",Bm=4,Is="HOST";function Um(i){return i==="desktop"||i==="ios"||i==="android"}function Ws(i){return i==="en"||i==="en-US"?"en-US":"zh-CN"}function Wm(){return typeof navigator>"u"?"zh-CN":Ws(navigator.language)}function dd(i){return i==="acceptEdits"||i==="bypassPermissions"?i:"default"}function Jd(){return typeof window<"u"&&typeof window.localStorage<"u"}function _m(){if(!Jd())return null;const i=window.localStorage.getItem(Us);if(!i)return null;try{return JSON.parse(i)}catch{return window.localStorage.removeItem(Us),null}}function Xd(i){Jd()&&window.localStorage.setItem(Us,JSON.stringify(ip(i)))}function Vm(){var i;return typeof window>"u"||!((i=window.location)!=null&&i.origin)?null:window.location.origin}function zm(i){if(!i)return null;try{return Ue(i)}catch{return null}}function Zd(i){if(i==="web"){const r=zm(Vm());if(r)return r}return Ue("http://127.0.0.1:3002")}function ep(){return new Date().toISOString()}function jm(){return{status:"idle",lastScannedAt:null,cooldownUntil:null,errorCode:null,errorDetail:null}}function ke(i){return typeof i=="string"&&i.trim()?i.trim():null}function pd(i,r){return ke(i)??r}function tp(i){try{const r=new URL(i).hostname.toLowerCase();return r==="localhost"||r==="127.0.0.1"||r==="::1"||r==="[::1]"?"local":/^10\./.test(r)||/^192\.168\./.test(r)||/^172\.(1[6-9]|2\d|3[0-1])\./.test(r)?"lan":"remote"}catch{return"custom"}}function ap(i){try{const r=new URL(i),o=r.pathname==="/"?"":r.pathname.replace(/\/+$/,"");return`${r.host}${o}`}catch{return i}}function _s(i){var o;const r=typeof i=="string"?(o=i.match(/[A-Za-z]/g))==null?void 0:o.join("").toUpperCase().slice(0,Bm):null;return r||null}function qm(i){try{const r=new URL(i),c=r.hostname.replace(/^\[|\]$/g,"").split(".").filter(Boolean),u=c.length>0?c[c.length-1]==="localhost"?Is:c[c.length-1]:r.host;return _s(u)??Is}catch{return _s(i)??Is}}function kn(i,r,o={}){const c=Ue(i);return{id:ke(o.id)??Ys,name:ke(o.name)??ap(c),alias:_s(o.alias)??qm(c),baseUrl:c,kind:o.kind??tp(c),peerEnabled:o.peerEnabled===!0,peerHostId:ke(o.peerHostId)??null,createdAt:pd(o.createdAt,r),updatedAt:pd(o.updatedAt,r),lastConnectedAt:ke(o.lastConnectedAt)??null,lastUserId:ke(o.lastUserId)??null,lastUsername:ke(o.lastUsername)??null,relayTunnel:Qm(o.relayTunnel)}}function Gm(i){return typeof i=="object"&&i!==null}function fd(i,r){if(!Array.isArray(i))return[];const o=new Set,c=[];for(let u=0;u<i.length;u+=1){const p=i[u];if(!Gm(p))continue;const y=ke(p.baseUrl);if(y)try{const S=u===0?Ys:`host-${u+1}`,A=kn(y,r,{...p,id:ke(p.id)??S});if(o.has(A.id))continue;o.add(A.id),c.push(A)}catch{continue}}return c}function Km(i){return typeof i=="object"&&i!==null}function Qm(i){if(typeof i!="object"||i===null||Array.isArray(i))return null;const r=ke(i.provider),o=i.enabled,c=ke(i.tunnelDomain),u=ke(i.controlBaseUrl),p=ke(i.bindingId),y=ke(i.hostFingerprint),S=Ym(i.candidateEndpoints);if(r!=="codingns_relay"||typeof o!="boolean"||!c||!u)return null;try{const A=Ue(u);return/^[a-z0-9-]+(\.[a-z0-9-]+)+$/i.test(c)?{provider:r,enabled:o,tunnelDomain:c.trim().toLowerCase(),controlBaseUrl:A,bindingId:p,hostFingerprint:y,candidateEndpoints:S}:null}catch{return null}}function Ym(i){if(!Array.isArray(i))return[];const r=[],o=new Set;for(const c of i){if(typeof c!="object"||c===null||Array.isArray(c))continue;const u=ke(c.endpointId),p=ke(c.kind),y=ke(c.url),S=c.priority,A=ke(c.expiresAt),O=ke(c.source);if(!(!u||!y||typeof S!="number"||!Number.isFinite(S)||p!=="relay"&&p!=="lan"&&p!=="loopback"&&p!=="tailscale"&&p!=="custom"||O!=="host_reported"&&O!=="desktop_scan"&&O!=="user_saved"))try{const E=Ue(y);if(o.has(E))continue;r.push({endpointId:u,kind:p,url:E,priority:S,expiresAt:A,source:O}),o.add(E)}catch{continue}}return r.sort((c,u)=>c.priority!==u.priority?c.priority-u.priority:c.url.localeCompare(u.url))}function hd(i,r,o){const c=Ue(r),u=Da(i);return u?i.hosts.map(p=>p.id===u.id?kn(c,o,{...p,name:ap(c),kind:tp(c),createdAt:p.createdAt,updatedAt:o}):p):[kn(c,o)]}function Zs(i){const r=ep();return{platform:i,activeHostId:Ys,hosts:[kn(Zd(i),r)],discoveredHosts:[],activeDiscoveredHostId:null,localHostDiscovery:jm(),releaseChannel:"stable",autoReconnect:!0,autoCheckUpdate:i==="desktop",autoDownloadUpdate:!1,language:Wm(),defaultPermissionMode:"default"}}function wn(i,r){var A,O;if(!r||!Km(r))return i;const o=r.platform??i.platform,c=Zs(o),u=ep();if(!Um(o)){let E=r.hosts!==void 0?fd(r.hosts,u):c.hosts;r.hostBaseUrl&&(E=hd(i,r.hostBaseUrl,u)),E.length===0&&(E=c.hosts);const W=r.activeHostId??i.activeHostId??c.activeHostId,j=E.some(ye=>ye.id===W)?W:((A=E[0])==null?void 0:A.id)??null;return{platform:o,activeHostId:j,hosts:E,discoveredHosts:i.discoveredHosts,activeDiscoveredHostId:null,localHostDiscovery:i.localHostDiscovery,releaseChannel:r.releaseChannel??i.releaseChannel,autoReconnect:r.autoReconnect??i.autoReconnect,autoCheckUpdate:r.autoCheckUpdate??i.autoCheckUpdate,autoDownloadUpdate:r.autoDownloadUpdate??i.autoDownloadUpdate,language:Ws(r.language??i.language),defaultPermissionMode:dd(r.defaultPermissionMode??i.defaultPermissionMode)}}let p=r.hosts!==void 0?fd(r.hosts,u):i.hosts;r.hostBaseUrl&&(p=hd(i,r.hostBaseUrl,u)),p.length===0&&(p=c.hosts);const y=r.activeHostId??i.activeHostId,S=p.some(E=>E.id===y)?y:((O=p[0])==null?void 0:O.id)??null;return{platform:o,activeHostId:S,hosts:p,discoveredHosts:i.discoveredHosts,activeDiscoveredHostId:i.activeDiscoveredHostId&&i.discoveredHosts.some(E=>E.id===i.activeDiscoveredHostId)?i.activeDiscoveredHostId:null,localHostDiscovery:i.localHostDiscovery,releaseChannel:r.releaseChannel??i.releaseChannel,autoReconnect:r.autoReconnect??i.autoReconnect,autoCheckUpdate:r.autoCheckUpdate??i.autoCheckUpdate,autoDownloadUpdate:r.autoDownloadUpdate??i.autoDownloadUpdate,language:Ws(r.language??i.language),defaultPermissionMode:dd(r.defaultPermissionMode??i.defaultPermissionMode)}}function ip(i){return{platform:i.platform,activeHostId:i.activeHostId,hosts:i.hosts,releaseChannel:i.releaseChannel,autoReconnect:i.autoReconnect,autoCheckUpdate:i.autoCheckUpdate,autoDownloadUpdate:i.autoDownloadUpdate,language:i.language,defaultPermissionMode:i.defaultPermissionMode}}function rp(i,r){return wn(Zs(r),i)}async function $m(){const i=Rn(),r=Zs(i.platform),o=_m();let c=null;if(i.isDesktop){const p=await i.bridge.readDesktopConfig();p.ok&&p.value&&(c=p.value)}const u=wn(wn(r,o),c);return Xd(u),u}async function Jm(i,r){var p;const o=wn(i,r);Xd(o);const c=(p=Da(o))==null?void 0:p.baseUrl;c&&Sm(c);const u=Rn();return u.isDesktop&&await u.bridge.writeDesktopConfig(ip(o)),o}function Xm(){return rp(null,Xs())}class Zm{constructor(){L(this,"state",Xm());L(this,"initialized",!1);L(this,"listeners",new Set);L(this,"subscribe",r=>(this.listeners.add(r),()=>{this.listeners.delete(r)}));L(this,"getState",()=>this.state);L(this,"isInitialized",()=>this.initialized)}hydrate(r){this.state=rp(r,this.state.platform),this.initialized=!0,this.emit()}updateRuntime(r){const o=r.discoveredHosts??this.state.discoveredHosts,c=r.activeDiscoveredHostId!==void 0?r.activeDiscoveredHostId:this.state.activeDiscoveredHostId,u=c&&o.some(y=>y.id===c)?c:null,p=r.localHostDiscovery??this.state.localHostDiscovery;o===this.state.discoveredHosts&&u===this.state.activeDiscoveredHostId&&p===this.state.localHostDiscovery||(this.state={...this.state,discoveredHosts:o,activeDiscoveredHostId:u,localHostDiscovery:p},this.emit())}async initialize(){const r=await $m();return this.hydrate(r),r}async update(r){const o=await Jm(this.state,r);return this.hydrate(o),o}emit(){for(const r of this.listeners)r()}}const Z=new Zm;function nS(i){return He.useSyncExternalStore(Z.subscribe,()=>i(Z.getState()))}function eg(i){return i.endsWith("/")?i:`${i}/`}function tg(i){return i.replace(/^\/+/,"")}function vn(){const i=Z.getState();return gm(i)??Zd(i.platform)}function Fn(i,r=vn()){return new URL(tg(i),eg(r)).toString()}function oS(i,r=vn()){const o=new URL(Fn(i,r));return o.protocol=o.protocol==="https:"?"wss:":"ws:",o.toString()}const ag=3e4;class ig{constructor(){L(this,"hints",new Map);L(this,"listeners",new Set);L(this,"subscribe",r=>(this.listeners.add(r),()=>{this.listeners.delete(r)}))}remember(r,o){const c=r.trim(),u=o.trim();!c||!u||(this.hints.set(c,{hostId:c,baseUrl:u,savedAt:Date.now()}),this.emit())}forget(r){const o=r==null?void 0:r.trim();!o||!this.hints.delete(o)||this.emit()}clear(){this.hints.size!==0&&(this.hints.clear(),this.emit())}get(r){const o=r==null?void 0:r.trim();if(!o)return null;const c=this.hints.get(o);return c?Date.now()-c.savedAt>ag?(this.hints.delete(o),this.emit(),null):c:null}emit(){for(const r of this.listeners)r()}}const Ca=new ig;let el=!1,md=!1;function gd(){return rg(),el}function rg(){md||typeof window>"u"||(md=!0,window.addEventListener("beforeunload",bd,{capture:!0}),window.addEventListener("pagehide",bd,{capture:!0}),window.addEventListener("pageshow",ng,{capture:!0}))}function bd(){el=!0}function ng(){el=!1}class et extends Error{constructor(o,c){super(c.detail);L(this,"status");L(this,"errorCode");L(this,"field");L(this,"data");this.name="ApiError",this.status=o,this.errorCode=c.error_code,this.field=c.field,this.data=c.data}}function sS(i){return i instanceof et&&i.errorCode==="NETWORK_ERROR"}function lS(i){return i instanceof et&&i.errorCode==="INVALID_RESPONSE"}const yd="codingns.auth.client-instance-id",og="x-codingns-client-type",sg="x-codingns-client-instance-id";let sa=null;function np(){return{[og]:lg(),[sg]:cg()}}function lg(){const i=Xs();switch(i){case"desktop":case"ios":case"android":return i;default:return"web"}}function cg(){var o;if(sa)return sa;if(!ug())return sa=Sd(),sa;const i=(o=window.localStorage.getItem(yd))==null?void 0:o.trim();if(i)return sa=i,sa;const r=Sd();return window.localStorage.setItem(yd,r),sa=r,sa}function Sd(){var i;return typeof((i=globalThis.crypto)==null?void 0:i.randomUUID)=="function"?globalThis.crypto.randomUUID():`client-${Math.random().toString(36).slice(2)}-${Date.now().toString(36)}`}function ug(){return typeof window<"u"&&typeof window.localStorage<"u"}const dn="codingns.auth.session",Td=3e3,dg=15e3;class pg{constructor(){L(this,"state",{status:"anonymous",session:null,sessionReady:!0});L(this,"listeners",new Set);L(this,"sessionMap",{});L(this,"lastRuntimeConfigSyncKey",null);L(this,"lastStoredSessionValidationKey",null);L(this,"refreshInFlight",null);L(this,"subscribe",r=>(this.listeners.add(r),()=>{this.listeners.delete(r)}));L(this,"getState",()=>this.state);this.syncCurrentHostSession(),Z.subscribe(()=>{this.syncCurrentHostSession()})}async login(r,o){const c=this.getCurrentHost();if(!c){const{loginRequest:p}=await Wt(async()=>{const{loginRequest:S}=await Promise.resolve().then(()=>Ns);return{loginRequest:S}},void 0),y=await p(r,o);return this.updateState({status:"authenticated",session:y,sessionReady:!0}),y}const u=await this.loginForHost(c,r,o);return this.updateState({status:"authenticated",session:u,sessionReady:!0}),u}async loginForHost(r,o,c){var O;const{loginRequest:u}=await Wt(async()=>{const{loginRequest:E}=await Promise.resolve().then(()=>Ns);return{loginRequest:E}},void 0),{resolveLoginBaseUrlWithDirectCandidates:p}=await Wt(async()=>{const{resolveLoginBaseUrlWithDirectCandidates:E}=await import("./login-direct-candidate-resolver-Bvs5uPix.js");return{resolveLoginBaseUrlWithDirectCandidates:E}},[]),y=c??r.baseUrl,S=await p({host:r,requestedBaseUrl:y,platform:Z.getState().platform}),A=await u(o,S);return S!==r.baseUrl?Ca.remember(r.id,S):Ca.forget(r.id),this.persistSession(r,A),((O=this.getCurrentHost())==null?void 0:O.id)===r.id&&(this.updateState({status:"authenticated",session:A,sessionReady:!0}),this.scheduleRuntimeConfigSync(r,A)),A}async bootstrap(r,o,c){const{setupRequest:u}=await Wt(async()=>{const{setupRequest:p}=await Promise.resolve().then(()=>Ns);return{setupRequest:p}},void 0);await u({username:r,password:o},c)}hydrate(r){if(!r){this.clear();return}this.setSession(r)}async refresh(){if(this.refreshInFlight)return await this.refreshInFlight;const r=this.runRefresh();this.refreshInFlight=r;try{return await r}finally{this.refreshInFlight===r&&(this.refreshInFlight=null)}}shouldRefreshCurrentSession(r=Date.now()){return Tg(this.getCurrentSessionEnvelope(),r)}async runRefresh(){const r=this.state.session,o=r==null?void 0:r.refreshToken,c=this.getCurrentHost();if(!o)return this.clear(),{status:"invalid",session:null};this.state={...this.state,status:"refreshing"},this.emit();try{const u=await vd(o,c==null?void 0:c.baseUrl);return this.setSession(u,c),this.scheduleRuntimeConfigSync(c,u),{status:"refreshed",session:u}}catch(u){return wd(u)?(this.clear(),{status:"invalid",session:null}):(this.state={status:r?"authenticated":"anonymous",session:r,sessionReady:this.state.sessionReady},this.emit(),{status:"deferred",session:r,error:u})}}clear(){const r=this.getCurrentHost();if(this.lastRuntimeConfigSyncKey=null,this.lastStoredSessionValidationKey=null,!r){Ca.clear(),this.sessionMap={},this.persistSessionMap(),this.updateState({status:"anonymous",session:null,sessionReady:!0});return}if(Ca.forget(r.id),this.sessionMap[r.id]){const o={...this.sessionMap};delete o[r.id],this.sessionMap=o,this.persistSessionMap()}this.updateState({status:"anonymous",session:null,sessionReady:!0})}clearHostSession(r){var c;if(!r||(Ca.forget(r),!this.sessionMap[r]))return;const o={...this.sessionMap};delete o[r],this.sessionMap=o,this.persistSessionMap(),((c=this.getCurrentHost())==null?void 0:c.id)===r&&(this.lastRuntimeConfigSyncKey=null,this.lastStoredSessionValidationKey=null,this.updateState({status:"anonymous",session:null,sessionReady:!0}))}setSession(r,o=this.getCurrentHost(),c={}){o&&(this.persistSession(o,r),this.lastStoredSessionValidationKey=pn(o,r),this.updateState({status:"authenticated",session:r,sessionReady:c.sessionReady??!0}))}persistSession(r,o){this.lastStoredSessionValidationKey=pn(r,o),this.sessionMap={...this.sessionMap,[r.id]:{hostId:r.id,session:o,savedAt:Date.now()}},this.persistSessionMap();const c=new Date().toISOString();if(zd(r)){Z.updateRuntime({discoveredHosts:Z.getState().discoveredHosts.map(u=>u.id===r.id?{...u,lastConnectedAt:c,lastUserId:o.user.userId,lastUsername:o.user.username,updatedAt:c}:u)});return}Z.update({hosts:Z.getState().hosts.map(u=>u.id===r.id?{...u,lastConnectedAt:c,lastUserId:o.user.userId,lastUsername:o.user.username,updatedAt:c}:u)}).catch(()=>{})}syncCurrentHostSession(){var S;if(!Z.isInitialized())return;const r=this.getCurrentHost(),{sessionMap:o,migrated:c}=this.readSessionMapFromStorage(r),u=yg(o);this.sessionMap=u,(c||Object.keys(u).length!==Object.keys(o).length)&&this.persistSessionMap();const p=r?((S=u[r.id])==null?void 0:S.session)??null:null;if(!r||!p){this.lastStoredSessionValidationKey=null,this.updateState({status:"anonymous",session:null,sessionReady:!0}),this.lastRuntimeConfigSyncKey=null;return}const y=pn(r,p);if(this.lastStoredSessionValidationKey===y){this.updateState({status:"authenticated",session:p,sessionReady:!0});return}this.updateState({status:"authenticated",session:p,sessionReady:!1}),this.scheduleStoredSessionValidation(r,p)}getCurrentHost(){return Da(Z.getState())}getCurrentSessionEnvelope(){const r=this.getCurrentHost();return r?this.sessionMap[r.id]??null:null}readSessionMapFromStorage(r){if(typeof window>"u"||typeof window.localStorage>"u")return{sessionMap:{},migrated:!1};const o=window.localStorage.getItem(dn);if(!o)return{sessionMap:{},migrated:!1};try{const c=JSON.parse(o);if(hg(c))return{sessionMap:c,migrated:!1};const u=gg(c,r);if(u)return{sessionMap:u,migrated:!0}}catch{}return window.localStorage.removeItem(dn),{sessionMap:{},migrated:!1}}persistSessionMap(){if(!(typeof window>"u"||typeof window.localStorage>"u")){if(Object.keys(this.sessionMap).length===0){window.localStorage.removeItem(dn);return}window.localStorage.setItem(dn,JSON.stringify(this.sessionMap))}}updateState(r){this.state.status===r.status&&this.state.session===r.session&&this.state.sessionReady===r.sessionReady||(this.state=r,this.emit())}async ensureRuntimeConfigSynced(r,o){var u;if(!r||!o||gd()){this.lastRuntimeConfigSyncKey=null;return}if(((u=this.getCurrentHost())==null?void 0:u.id)!==r.id)return;const c=`${r.id}:${o.accessToken}`;if(this.lastRuntimeConfigSyncKey!==c){this.lastRuntimeConfigSyncKey=c;try{const{syncActiveHostAuthenticatedRuntimeConfig:p}=await Wt(async()=>{const{syncActiveHostAuthenticatedRuntimeConfig:S}=await import("./client-runtime-manager-CGVLChqs.js");return{syncActiveHostAuthenticatedRuntimeConfig:S}},[]);await kd(p(),Td,"runtime_config_sync_timeout");const{syncPeerHostsIntoClientConfig:y}=await Wt(async()=>{const{syncPeerHostsIntoClientConfig:S}=await import("./peer-host-config-sync-oelf2T0_.js");return{syncPeerHostsIntoClientConfig:S}},__vite__mapDeps([0,1]));await kd(y(),Td,"peer_host_config_sync_timeout")}catch{this.lastRuntimeConfigSyncKey===c&&(this.lastRuntimeConfigSyncKey=null)}}}scheduleRuntimeConfigSync(r,o){this.ensureRuntimeConfigSynced(r,o)}scheduleStoredSessionValidation(r,o){this.ensureStoredSessionValidated(r,o)}async ensureStoredSessionValidated(r,o){var u,p,y,S,A,O;if(gd()||((u=this.getCurrentHost())==null?void 0:u.id)!==r.id||((p=this.state.session)==null?void 0:p.refreshToken)!==o.refreshToken)return;const c=pn(r,o);try{const E=await vd(o.refreshToken,r.baseUrl);if(((y=this.getCurrentHost())==null?void 0:y.id)!==r.id||((S=this.state.session)==null?void 0:S.refreshToken)!==o.refreshToken)return;this.lastStoredSessionValidationKey=c,this.setSession(E,r,{sessionReady:!0}),this.scheduleRuntimeConfigSync(r,E)}catch(E){if(((A=this.getCurrentHost())==null?void 0:A.id)!==r.id||((O=this.state.session)==null?void 0:O.refreshToken)!==o.refreshToken)return;if(wd(E)){this.clear();return}this.lastStoredSessionValidationKey=c,this.updateState({status:"authenticated",session:o,sessionReady:!0})}}emit(){for(const r of this.listeners)r()}}const Me=new pg;function cS(i){return He.useSyncExternalStore(Me.subscribe,()=>i(Me.getState()))}function fg(i){if(typeof i!="object"||i===null)return!1;const r=i;return typeof r.hostId=="string"&&typeof r.savedAt=="number"&&En(r.session)}function kd(i,r,o){return new Promise((c,u)=>{const p=globalThis.setTimeout(()=>{u(new Error(o))},r);i.then(y=>{globalThis.clearTimeout(p),c(y)},y=>{globalThis.clearTimeout(p),u(y)})})}function hg(i){return typeof i!="object"||i===null||Array.isArray(i)?!1:Object.values(i).every(r=>fg(r))}function mg(i){return typeof i!="object"||i===null?!1:"session"in i&&En(i.session)}function En(i){if(typeof i!="object"||i===null)return!1;const r=i;return typeof r.accessToken=="string"&&typeof r.refreshToken=="string"&&typeof r.expiresIn=="number"&&typeof r.user=="object"&&r.user!==null}function gg(i,r){const o=(r==null?void 0:r.id)??null;if(!o)return null;if(mg(i)){const c=bg(i.serverBaseUrl,r)??o;return{[c]:{hostId:c,session:i.session,savedAt:Date.now()}}}return En(i)?{[o]:{hostId:o,session:i,savedAt:Date.now()}}:null}function bg(i,r){if(!i)return(r==null?void 0:r.id)??null;const c=Z.getState().hosts.find(u=>u.baseUrl===i);return(c==null?void 0:c.id)??(r==null?void 0:r.id)??null}function wd(i){return i instanceof et?i.status===401?!0:i.status===403&&i.errorCode==="BOOTSTRAP_REQUIRED":!1}function yg(i){const r=Object.entries(i).filter(([,o])=>!Sg(o));return Object.fromEntries(r)}function Sg(i){var o;const r=(o=i.session)==null?void 0:o.expiresIn;return typeof r!="number"||!Number.isFinite(r)||r<=0?!0:i.savedAt+r*1e3<=Date.now()}function Tg(i,r){var c;const o=(c=i==null?void 0:i.session)==null?void 0:c.expiresIn;return!(i!=null&&i.session)||typeof o!="number"||!Number.isFinite(o)||o<=0?!1:i.savedAt+o*1e3<=r+dg}function pn(i,r){return`${i.id}:${r.refreshToken}`}async function vd(i,r){const o=await fetch(Fn("/api/auth/refresh",r),{method:"POST",headers:{...np(),"Content-Type":"application/json"},body:JSON.stringify({refreshToken:i})}),c=await o.text(),u=c?kg(c):null;if(!o.ok)throw new et(o.status,{detail:(u==null?void 0:u.detail)??`请求失败(HTTP ${o.status})`,error_code:(u==null?void 0:u.error_code)??(o.status===401?"UNAUTHORIZED":"HTTP_ERROR"),field:u==null?void 0:u.field,data:u==null?void 0:u.data,timestamp:u==null?void 0:u.timestamp});if(!u||!En(u))throw new et(o.status,{detail:"刷新登录态返回了无效响应",error_code:"HTTP_ERROR"});return u}function kg(i){try{return JSON.parse(i)}catch{return null}}const ai=new Map,op=48;function Pa(){return typeof window<"u"&&typeof window.sessionStorage<"u"}function Cd(i,r){return!Number.isFinite(i)||Date.now()-i>r}function wg(i){return!i||typeof i!="object"||!("savedAt"in i)||!("value"in i)?!1:Number.isFinite(i.savedAt)}function sp(i){try{const r=JSON.parse(i);return wg(r)?r:null}catch{return null}}function vg(){if(!Pa())return[];try{return Array.from({length:window.sessionStorage.length},(i,r)=>window.sessionStorage.key(r)).filter(i=>typeof i=="string"&&i.length>0)}catch{return[]}}function lp(){if(!Pa())return[];const i=[];for(const r of vg()){let o=null;try{o=window.sessionStorage.getItem(r)}catch{continue}if(!o)continue;const c=sp(o);c&&i.push({key:r,savedAt:c.savedAt})}return i.sort((r,o)=>r.savedAt-o.savedAt)}function Yi(i){if(Pa())try{window.sessionStorage.removeItem(i)}catch{}}function fn(i){const r=new Set((i==null?void 0:i.preserveKeys)??[]),o=(i==null?void 0:i.maxCount)??op,c=lp().filter(p=>!r.has(p.key)),u=Math.max(0,r.size+c.length-o);for(let p=0;p<u;p+=1){const y=c[p];if(!y)break;Yi(y.key)}}function Cg(i){return i instanceof DOMException&&(i.name==="QuotaExceededError"||i.name==="NS_ERROR_DOM_QUOTA_REACHED"||i.code===22||i.code===1014)}function xs(i,r){if(!Pa())return"failed";try{return window.sessionStorage.setItem(i,r),"success"}catch(o){return Cg(o)?"quota_exceeded":"failed"}}function Dg(i,r){const o=xs(i,r);if(o==="success"){fn({preserveKeys:[i]});return}if(o==="quota_exceeded"){if(Yi(i),fn({maxCount:Math.max(0,op-1)}),xs(i,r)==="success"){fn({preserveKeys:[i]});return}for(const c of lp())if(c.key!==i&&(Yi(c.key),xs(i,r)==="success")){fn({preserveKeys:[i]});return}}}function Pg(i,r){const o=ai.get(i);if(o){if(!Cd(o.savedAt,r))return o.value;ai.delete(i)}if(!Pa())return null;let c=null;try{c=window.sessionStorage.getItem(i)}catch{return null}if(!c)return null;const u=sp(c);return!u||Cd(u.savedAt,r)?(Yi(i),ai.delete(i),null):(ai.set(i,u),u.value)}function Ag(i,r){const o={savedAt:Date.now(),value:r};if(ai.set(i,o),!!Pa())try{Dg(i,JSON.stringify(o))}catch{}}function uS(i){ai.delete(i),Pa()&&Yi(i)}const Lg="workbench.affairs.dashboard.",cp=7,Rg=365*24*60*60*1e3,Fg=/\.(html?|HTML?)$/,dS="affairs-global",Eg="codingns:affairs-dashboard-state-updated";function up(i){return`${Lg}${i}`}function Aa(i){var r;return typeof((r=globalThis.crypto)==null?void 0:r.randomUUID)=="function"?`${i}-${globalThis.crypto.randomUUID()}`:`${i}-${Date.now()}-${Math.random().toString(16).slice(2)}`}function Rt(i){return!!i&&typeof i=="object"&&!Array.isArray(i)}function hn(i){return Number.isInteger(i)&&Number(i)>0}function Dd(i){return Number.isInteger(i)&&Number(i)>=0}function tl(i){const r=i.trim().replace(/\\/g,"/"),o=r.split("/").filter(Boolean);return o[o.length-1]??r}function pS(i){const r=(i==null?void 0:i.trim())??"";return r.length>0&&Fg.test(r)}function dp(i,r,o="embed"){return i==="todo"?tt("shell.affairsTodoAllFilter"):i==="automation"?tt("shell.affairsAutomationStageTitle"):i==="teable"?tt("shell.teableRuntimeDefaultBlockTitle"):r!=null&&r.trim()?tl(r):Mg(o)}function Mg(i){return tt(i==="app"?"shell.affairsWorkbenchHtmlAppDefaultTitle":i==="stat"?"shell.affairsWorkbenchHtmlStatDefaultTitle":"shell.affairsWorkbenchHtmlEmbedDefaultTitle")}function pp(i,r=new Date().toISOString()){var c,u,p;const o=i.type==="html"?Vs(i.variant)??"embed":void 0;return{id:Aa("dashboard-widget"),type:i.type,variant:o,title:((c=i.title)==null?void 0:c.trim())||dp(i.type,(u=i.sourceRef)==null?void 0:u.sourceId,o),sourceRef:i.sourceRef?{...i.sourceRef,workspaceId:((p=i.sourceRef.workspaceId)==null?void 0:p.trim())||void 0}:void 0,config:Rt(i.config)?i.config:{},createdAt:r,updatedAt:r}}function Ig(i){return pp({type:"todo",title:tt("shell.affairsTodoAllFilter"),config:{filter:"all",view:"compact"}},i)}function xg(i){return pp({type:"automation",title:tt("shell.affairsAutomationStageTitle"),config:{scope:"all",view:"list"}},i)}function fp(i){return i.map((r,o)=>({widgetId:r.id,x:o===0?0:6,y:0,w:6,h:5,minW:4,minH:3}))}function fS(i,r=new Date().toISOString()){return{id:Aa("dashboard-tab"),title:i.trim()||tt("shell.affairsWorkbenchDefaultTabTitle"),widgets:[],layout:[],createdAt:r,updatedAt:r}}function Og(i=new Date().toISOString()){const r=[Ig(i),xg(i)];return{id:Aa("dashboard-tab"),title:tt("shell.affairsWorkbenchDefaultTabTitle"),widgets:r,layout:fp(r),createdAt:i,updatedAt:i}}function hS(i,r=new Date().toISOString()){var y,S;const o=i.entryPath.trim(),c=i.workspaceId.trim(),u=((y=i.sourceId)==null?void 0:y.trim())||o,p=i.sourceKind==="affairs_library"?"affairs_library":"workspace";return{id:Aa("shortcut-app"),title:((S=i.title)==null?void 0:S.trim())||tl(o),sourceKind:p,workspaceId:c,sourceId:u,entryPath:o,createdAt:r,updatedAt:r}}function Hg(i,r=new Date().toISOString()){const o=Og(r);return{workspaceId:i,version:cp,layoutLocked:!0,activeTabId:o.id,tabs:[o],shortcutApps:[],updatedAt:r}}function Ng(i,r){if(!Rt(i))return null;const o=Vg(i.type,Rt(i.config)?i.config.variant:void 0,i.variant);if(!o)return null;const c=Rt(i.sourceRef)?{kind:i.sourceRef.kind==="html_shortcut"?"html_shortcut":i.sourceRef.kind==="affairs_library_html"?"affairs_library_html":"plugin_runtime",workspaceId:typeof i.sourceRef.workspaceId=="string"&&i.sourceRef.workspaceId.trim()?i.sourceRef.workspaceId.trim():void 0,sourceId:typeof i.sourceRef.sourceId=="string"?i.sourceRef.sourceId.trim():"",entryId:typeof i.sourceRef.entryId=="string"&&i.sourceRef.entryId.trim()?i.sourceRef.entryId.trim():void 0}:void 0;return o.type==="html"&&!(c!=null&&c.sourceId)||o.type==="teable"&&!Rt(i.config)?null:{id:typeof i.id=="string"&&i.id.trim()?i.id.trim():Aa("dashboard-widget"),type:o.type,variant:o.variant,title:typeof i.title=="string"&&i.title.trim()?i.title.trim():dp(o.type,c==null?void 0:c.sourceId,o.variant??"embed"),sourceRef:c,config:zg(Rt(i.config)?i.config:{}),createdAt:typeof i.createdAt=="string"&&i.createdAt.trim()?i.createdAt:r,updatedAt:typeof i.updatedAt=="string"&&i.updatedAt.trim()?i.updatedAt:r}}function Bg(i){return!Rt(i)||typeof i.widgetId!="string"||!i.widgetId.trim()||!Dd(i.x)||!Dd(i.y)||!hn(i.w)||!hn(i.h)?null:{widgetId:i.widgetId.trim(),x:i.x,y:i.y,w:i.w,h:i.h,minW:hn(i.minW)?i.minW:void 0,minH:hn(i.minH)?i.minH:void 0}}function Ug(i,r){if(!Rt(i))return null;const o=i.sourceKind==="affairs_library"?"affairs_library":"workspace",c=typeof i.workspaceId=="string"?i.workspaceId.trim():"",u=typeof i.entryPath=="string"?i.entryPath.trim():"";if(!c||!u)return null;const p=typeof i.sourceId=="string"&&i.sourceId.trim()?i.sourceId.trim():u;return{id:typeof i.id=="string"&&i.id.trim()?i.id.trim():Aa("shortcut-app"),title:typeof i.title=="string"&&i.title.trim()?i.title.trim():tl(u),sourceKind:o,workspaceId:c,sourceId:p,entryPath:u,createdAt:typeof i.createdAt=="string"&&i.createdAt.trim()?i.createdAt:r,updatedAt:typeof i.updatedAt=="string"&&i.updatedAt.trim()?i.updatedAt:r}}function Wg(i,r){if(!Rt(i))return null;const o=(Array.isArray(i.widgets)?i.widgets:[]).map(p=>Ng(p,r)).filter(p=>p!==null),c=new Map((Array.isArray(i.layout)?i.layout:[]).map(p=>Bg(p)).filter(p=>p!==null).map(p=>[p.widgetId,p])),u=fp(o);return{id:typeof i.id=="string"&&i.id.trim()?i.id.trim():Aa("dashboard-tab"),title:typeof i.title=="string"&&i.title.trim()?i.title.trim():tt("shell.affairsWorkbenchDefaultTabTitle"),widgets:o,layout:o.map((p,y)=>c.get(p.id)??u[y]),createdAt:typeof i.createdAt=="string"&&i.createdAt.trim()?i.createdAt:r,updatedAt:typeof i.updatedAt=="string"&&i.updatedAt.trim()?i.updatedAt:r}}function hp(i,r){if(!Rt(r))return null;const o=new Date().toISOString(),c=(Array.isArray(r.tabs)?r.tabs:[]).map(S=>Wg(S,o)).filter(S=>S!==null),u=(Array.isArray(r.shortcutApps)?r.shortcutApps:[]).map(S=>Ug(S,o)).filter(S=>S!==null);if(c.length===0)return{...Hg(i,o),shortcutApps:u};const p=typeof r.activeTabId=="string"?r.activeTabId.trim():"",y=c.some(S=>S.id===p)?p:c[0].id;return{workspaceId:i,version:cp,layoutLocked:typeof r.layoutLocked=="boolean"?r.layoutLocked:!0,activeTabId:y,tabs:c,shortcutApps:u,updatedAt:typeof r.updatedAt=="string"&&r.updatedAt.trim()?r.updatedAt:o}}function Vs(i){return i==="app"||i==="stat"||i==="embed"?i:null}function _g(i){return i==="html_app"?"app":i==="html_stat"?"stat":i==="html_embed"?"embed":null}function Vg(i,r,o){if(i==="todo"||i==="automation"||i==="teable")return{type:i};if(i==="html")return{type:"html",variant:Vs(o)??Vs(r)??"embed"};const c=_g(i);return c?{type:"html",variant:c}:null}function zg(i){if(!("variant"in i))return i;const{variant:r,...o}=i;return o}function mS(i){const r=i==null?void 0:i.trim();if(!r)return null;const o=Pg(up(r),Rg);return o?hp(r,o):null}function gS(i){Ag(up(i.workspaceId),i),typeof window<"u"&&window.dispatchEvent(new CustomEvent(Eg,{detail:{workspaceId:i.workspaceId}}))}const Mn=["claude-code","codex","opencode","gemini","kimi"],mp="codingns.account.preferences.shadow",jg="codingns.client.runtime-config",qg="codingns-theme",Gg="composer-selected-model:",Kg="composer-reasoning-level:",al={start:43e3,end:47999};function Xi(){return typeof window<"u"&&typeof window.localStorage<"u"}function il(i){return i==="en-US"||i==="en"?"en-US":i==="zh-CN"?"zh-CN":null}function Qg(){return typeof navigator>"u"?"zh-CN":il(navigator.language)??"zh-CN"}function gp(i){return i==="light"||i==="dark"||i==="sky-blue"||i==="eye-green"?i:null}function Yg(){return typeof window>"u"||typeof window.matchMedia!="function"?"light":window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light"}function $g(i){return typeof i=="boolean"?i:null}function bp(i){return i==="acceptEdits"||i==="bypassPermissions"||i==="default"?i:null}function yp(i){return i==="low"||i==="medium"||i==="high"||i==="xhigh"?i:null}function Sp(){return{"claude-code":{defaultModel:null,defaultReasoningLevel:null},codex:{defaultModel:null,defaultReasoningLevel:null},opencode:{defaultModel:null,defaultReasoningLevel:null},gemini:{defaultModel:null,defaultReasoningLevel:null},kimi:{defaultModel:null,defaultReasoningLevel:null}}}function Tp(){return{initialized:!0,profile:{language:Qg(),theme:Yg(),autoTheme:!1,defaultPermissionMode:"default",debugPortPools:Pn(al)},providers:Sp(),affairsDashboardStatesByWorkspace:{},updatedAt:null,source:"default"}}function Jg(){const i=Z.getState(),r={language:i.language,defaultPermissionMode:i.defaultPermissionMode};if(!Xi())return r;const o=window.localStorage.getItem(jg);if(!o)return r;try{const c=JSON.parse(o);return{language:il(c.language)??r.language,defaultPermissionMode:bp(c.defaultPermissionMode)??r.defaultPermissionMode}}catch{return r}}function Xg(){return Xi()?gp(window.localStorage.getItem(qg)):null}function Zg(){var r;if(!Xi())return;const i={};for(const o of Mn){const c=((r=window.localStorage.getItem(`${Gg}${o}`))==null?void 0:r.trim())||null,u=yp(window.localStorage.getItem(`${Kg}${o}`));c===null&&u===null||(i[o]={defaultModel:c,defaultReasoningLevel:u})}return Object.keys(i).length>0?i:void 0}function kp(){const i=Jg(),r=Xg(),o=Zg(),c={};return i.language&&(c.language=i.language),r&&(c.theme=r),i.defaultPermissionMode&&(c.defaultPermissionMode=i.defaultPermissionMode),o&&(c.providers=o),wp(c)?c:null}function wp(i){return i?i.language!==void 0||i.theme!==void 0||i.autoTheme!==void 0||i.defaultPermissionMode!==void 0||i.debugPortPools!==void 0||i.affairsDashboardStatesByWorkspace!==void 0||i.providers!==void 0&&Object.keys(i.providers).length>0:!1}function Cn(i){var c;const r=Tp(),o=Sp();for(const u of Mn){const p=(c=i==null?void 0:i.providers)==null?void 0:c[u];o[u]={defaultModel:typeof(p==null?void 0:p.defaultModel)=="string"&&p.defaultModel.trim()||null,defaultReasoningLevel:yp(p==null?void 0:p.defaultReasoningLevel)??null}}return{language:il(i==null?void 0:i.language)??r.profile.language,theme:gp(i==null?void 0:i.theme)??r.profile.theme,autoTheme:$g(i==null?void 0:i.autoTheme)??r.profile.autoTheme,defaultPermissionMode:bp(i==null?void 0:i.defaultPermissionMode)??r.profile.defaultPermissionMode,debugPortPools:tb(i==null?void 0:i.debugPortPools)??r.profile.debugPortPools,providers:o,affairsDashboardStatesByWorkspace:Cp(i==null?void 0:i.affairsDashboardStatesByWorkspace),updatedAt:typeof(i==null?void 0:i.updatedAt)=="string"?i.updatedAt:null}}function eb(){var r,o,c,u,p;if(!Xi())return null;const i=window.localStorage.getItem(mp);if(!i)return null;try{const y=JSON.parse(i),S=Cn({language:(r=y.profile)==null?void 0:r.language,theme:(o=y.profile)==null?void 0:o.theme,autoTheme:(c=y.profile)==null?void 0:c.autoTheme,defaultPermissionMode:(u=y.profile)==null?void 0:u.defaultPermissionMode,debugPortPools:(p=y.profile)==null?void 0:p.debugPortPools,providers:y.providers,affairsDashboardStatesByWorkspace:y.affairsDashboardStatesByWorkspace,updatedAt:y.updatedAt});return{profile:{language:S.language,theme:S.theme,autoTheme:S.autoTheme,defaultPermissionMode:S.defaultPermissionMode,debugPortPools:S.debugPortPools},providers:S.providers,affairsDashboardStatesByWorkspace:S.affairsDashboardStatesByWorkspace,updatedAt:S.updatedAt}}catch{return null}}function Dn(i){if(!Xi())return;const r={profile:i.profile,providers:i.providers,affairsDashboardStatesByWorkspace:i.affairsDashboardStatesByWorkspace,updatedAt:i.updatedAt};window.localStorage.setItem(mp,JSON.stringify(r))}function ei(){const i=Tp(),r=kp(),o=r?vp(i,r,"default"):i,c=eb();return c?{initialized:!0,profile:c.profile,providers:c.providers,affairsDashboardStatesByWorkspace:c.affairsDashboardStatesByWorkspace,updatedAt:c.updatedAt,source:"shadow"}:o}function zs(i,r){return{initialized:!0,profile:{language:i.language,theme:i.theme,autoTheme:i.autoTheme,defaultPermissionMode:i.defaultPermissionMode,debugPortPools:Pn(i.debugPortPools??al)},providers:i.providers,affairsDashboardStatesByWorkspace:i.affairsDashboardStatesByWorkspace??{},updatedAt:i.updatedAt,source:r}}function vp(i,r,o){const c={...i.providers};if(r.providers)for(const u of Mn){const p=r.providers[u];p&&(c[u]={defaultModel:p.defaultModel!==void 0?p.defaultModel??null:i.providers[u].defaultModel,defaultReasoningLevel:p.defaultReasoningLevel!==void 0?p.defaultReasoningLevel??null:i.providers[u].defaultReasoningLevel})}return{initialized:!0,profile:{language:r.language??i.profile.language,theme:r.theme??i.profile.theme,autoTheme:r.autoTheme??i.profile.autoTheme,defaultPermissionMode:r.defaultPermissionMode??i.profile.defaultPermissionMode,debugPortPools:r.debugPortPools?Pn(r.debugPortPools):i.profile.debugPortPools??Pn(al)},providers:c,affairsDashboardStatesByWorkspace:r.affairsDashboardStatesByWorkspace!==void 0?Cp(r.affairsDashboardStatesByWorkspace):i.affairsDashboardStatesByWorkspace??{},updatedAt:i.updatedAt,source:o}}function Cp(i){if(!i||typeof i!="object"||Array.isArray(i))return{};const r={};for(const[o,c]of Object.entries(i)){const u=o.trim();if(!u)continue;const p=hp(u,c);p&&(r[u]=p)}return r}function tb(i){if(!i||typeof i!="object"||Array.isArray(i))return null;const r=Dp(i);return r||ab(i)}function Pd(i){if(!Number.isInteger(i))return null;const r=Number(i);return r>=1024&&r<=65535?r:null}function Dp(i){if(!i||typeof i!="object"||Array.isArray(i))return null;const r=i;if(!Object.prototype.hasOwnProperty.call(r,"start")||!Object.prototype.hasOwnProperty.call(r,"end"))return null;const o=Pd(r.start),c=Pd(r.end);return o===null||c===null||o>=c?null:{start:o,end:c}}function ab(i){if(!i||typeof i!="object"||Array.isArray(i))return null;const r=["frontend","backend","worker","mock","custom"];let o=Number.POSITIVE_INFINITY,c=Number.NEGATIVE_INFINITY;for(const u of r){const p=Dp(i[u]);if(!p)return null;o=Math.min(o,p.start),c=Math.max(c,p.end)}return Number.isFinite(o)&&Number.isFinite(c)&&o<c?{start:o,end:c}:null}function Pn(i){return{...i}}async function ib(){const{fetchPreferencesProfile:i,updatePreferencesProfile:r}=await Wt(async()=>{const{fetchPreferencesProfile:u,updatePreferencesProfile:p}=await import("./preferences-service-Dys1mbBy.js");return{fetchPreferencesProfile:u,updatePreferencesProfile:p}},[]),o=Cn(await i());if(o.updatedAt===null){const u=kp();if(wp(u)){const p=Cn(await r(u)),y=zs(p,"remote");return Dn(y),y}}const c=zs(o,"remote");return Dn(c),c}class rb{constructor(){L(this,"state",ei());L(this,"listeners",new Set);L(this,"subscribe",r=>(this.listeners.add(r),()=>{this.listeners.delete(r)}));L(this,"getState",()=>this.state);Z.subscribe(()=>{Me.getState().session||this.state.source==="remote"||this.hydrate(ei())})}hydrate(r){this.state=r,this.emit()}resetToLocalFallback(){this.hydrate(ei())}async initialize(){if(!Me.getState().session){const r=ei();return this.hydrate(r),r}return this.refreshForAuthenticatedUser()}async refreshForAuthenticatedUser(){if(!Me.getState().session){const r=ei();return this.hydrate(r),r}try{const r=await ib();return this.hydrate(r),r}catch{const r=ei();return this.hydrate(r),r}}async updateProfile(r){const o=this.state,c=vp(o,r,o.source);if(this.hydrate(c),!Me.getState().session)return Dn(c),c;try{const{updatePreferencesProfile:u}=await Wt(async()=>{const{updatePreferencesProfile:S}=await import("./preferences-service-Dys1mbBy.js");return{updatePreferencesProfile:S}},[]),p=Cn(await u(r)),y=zs(p,"remote");return Dn(y),this.hydrate(y),y}catch(u){throw this.hydrate(o),u}}async updateProviderPreference(r,o){return this.updateProfile({providers:{[r]:o}})}emit(){for(const r of this.listeners)r()}}const ri=new rb;function Pp(i){return He.useSyncExternalStore(ri.subscribe,()=>i(ri.getState()))}function nb(i){return Mn.includes(i)}const bS=Object.freeze(Object.defineProperty({__proto__:null,isPreferenceProviderId:nb,useUserPreferenceSelector:Pp,userPreferenceStore:ri},Symbol.toStringTag,{value:"Module"}));function ob(){return ri.initialize()}function yS(i){return ri.updateProfile(i)}function sb(i){return Pp(r=>i({profile:{...r.profile,providers:r.providers,affairsDashboardStatesByWorkspace:r.affairsDashboardStatesByWorkspace??{},updatedAt:r.updatedAt},isFetching:!1,error:null}))}const lb={common:{close:"关闭",cancel:"取消",copy:"复制",copyFailed:"复制失败",enabled:"已启用",disabled:"已关闭",logout:"退出登录",language:"语言",none:"无"},locale:{zhCN:"简体中文",enUS:"English"},settings:{title:"设置",appearance:"外观",language:"语言",languageDescription:"选择界面显示语言,切换后立即应用到当前页面。",theme:"主题",themeDescription:"选择适合你的界面配色方案",connection:"连接与更新",serverAddress:"服务地址",serverDescription:"桌面端和 H5 都通过这个 Host 入口工作。",autoReconnect:"自动重连",autoReconnectDescription:"当 Host 短暂不可达时,自动尝试恢复 HTTP 和 WebSocket 链路。",autoCheckUpdate:"自动检查更新",autoCheckUpdateDescription:"发现客户端新版本时提醒你处理。",autoDownloadUpdate:"自动下载更新包后提示更新",autoDownloadUpdateDescription:"发现客户端新版本后先下载资源,下载完成再提示你安装。",notificationSettings:"通知",notificationSettingsDescription:"单独控制会话相关的系统通知提醒。",notifyOnPermissionRequest:"会话等待审批时通知",notifyOnPermissionRequestDescription:"后台会话出现新的权限申请时推送通知。",notifyOnSessionCompleted:"会话完成时通知",notifyOnSessionCompletedDescription:"后台会话变为已完成时推送通知。",notifyOnSessionFailed:"会话异常时通知",notifyOnSessionFailedDescription:"后台会话运行失败时推送通知。",enabled:"已启用",disabled:"已关闭",serverUpdate:"服务端更新",serverUpdateDescription:"",clientUpdate:"客户端更新",clientUpdateDescription:"",serverCurrentVersion:"服务端当前版本",serverTargetVersion:"服务端目标版本",serverPackageName:"npm 包名",serverUpdateCommand:"升级命令",serverCheckNow:"检查服务端",serverInstallNow:"安装更新",serverOpenPage:"打开 npm",serverLatestUnknown:"暂未获取",serverUpdateReady:"发现新版本",serverUpToDate:"已是最新版本",serverCheckFailed:"检查失败",serverInstallWarning:"安装更新会通过 PM2 自动重启 CodingNS 服务,连接会短暂中断。",serverInstallConfirmTitle:"安装服务端更新",serverInstallConfirmDescription:"继续后会先安装新版本,再由 PM2 自动重启当前 CodingNS 服务。",serverInstallConfirmAction:"继续安装并重启服务",serverRestarting:"更新已安装,正在重启 CodingNS 服务",serverProgressLabel:"服务端更新进度",serverProgressPreparing:"正在准备服务端更新",serverProgressQueued:"已加入更新队列",serverProgressInstalling:"正在安装服务端更新",serverProgressRestarting:"正在重启服务",serverProgressHint:"服务端升级由 npm 和 PM2 执行,当前只能显示阶段,不能显示准确百分比。",serverProgressCurrentStage:"当前阶段:{stage}",updateCheckAll:"检查更新",updateChecking:"正在检查",serverInstallQueued:"已加入更新队列",serverInstalling:"正在安装更新",serverInstallSucceeded:"更新已完成",serverInstallFailed:"安装失败",serverInstallCancelled:"安装已取消",serverInstallTimeout:"安装超时",serverRestartRequired:"新版本已安装,重启 Host 后生效",serverOpenPageFailed:"打开页面失败",runtimePlatform:"当前运行平台",runtimePlatformDescription:"用来确认现在是 Web/H5、Desktop、iOS 还是 Android 运行环境。",platformDesktop:"Desktop",platformWeb:"Web",platformIos:"iOS",platformAndroid:"Android",releaseDesktopOnly:"当前是 Web/H5 运行环境,不支持桌面更新。",releaseCurrentVersion:"当前版本",releaseTargetVersion:"目标版本",releaseUnknownVersion:"未知",releaseNotes:"更新内容",releaseNotesEmpty:"暂无更新内容",releaseCheckNow:"检查客户端",releaseInstallNow:"安装更新",releaseDownloading:"正在下载更新包",releaseDownloadedReady:"更新包已下载完成,可以安装",releaseDownloadedReadyWithProgress:"更新包已下载完成({percent}%),可以安装",releaseDownloadFailed:"下载失败",releaseInstallReadyDialogTitle:"更新包已下载完成",releaseInstallReadyDialogDescription:"新版本 {version} 已准备好,现在可以安装。",releaseInstallReadyWarning:"安装完成后需要重启应用才能切到新版本。",releaseInstallReadyConfirm:"安装并重启",releaseDownloadedNotificationTitle:"客户端更新已下载",releaseDownloadedNotificationBody:"新版本 {version} 已下载完成,请到设置里安装。",releaseOpenPage:"打开发布页",releaseManualOnly:"当前版本只能手动安装",releaseUpdateBadge:"新版本",releaseUpdateReady:"发现新版本",releaseUpToDate:"已是最新版本",releaseCheckFailed:"检查失败",releaseInstallStarted:"安装已开始",releaseInstallFailed:"安装失败",releasePageOpenFailed:"打开发布页失败",androidInstallerStarted:"已交给系统安装器,安装完成前你仍可以取消",androidInstallPermissionRequired:"请先允许当前应用安装未知来源应用",androidInstallCancelled:"安装已取消或未完成,可重新触发安装",androidInstallSucceeded:"已检测到新版本完成安装",clientUpdateUnsupported:"当前不支持安装更新",account:"账号",logout:"退出登录",logoutDescription:"退出当前账号并返回登录页面",advancedSettings:"高级设置",parallelTaskDebug:"并行任务调试",parallelTaskDebugDescription:"打开后才会启用运行时采样,用来实时看后台任务、调度器和主线程压力指标。",debugPortPool:"调试端口池",debugPortPoolDescription:"给子工作区的已登记启动项分配可用端口。所有调试服务统一从这个范围里拿空闲端口,不再分前后端和 Worker。",debugPortPoolRangeLabel:"端口范围",debugPortPoolRangeHint:"子工作区里的前端、后端、Worker、Mock 和自定义服务统一从这里取可用端口",debugPortPoolStart:"起始",debugPortPoolEnd:"结束",debugPortPoolRangeSeparator:"到",debugPortPoolSaveAction:"保存端口池",debugPortPoolSaved:"端口池已保存",debugPortPoolSaveFailed:"端口池保存失败",debugPortPoolValidationInteger:"端口池的起止值必须是整数",debugPortPoolValidationRange:"端口池必须在 1024 到 65535 之间,且起始值必须小于结束值",debugPortPoolValidationOverlap:"各角色的端口池不能重叠",debugPortPoolRoleFrontend:"前端",debugPortPoolRoleBackend:"后端",debugPortPoolRoleWorker:"Worker",debugPortPoolRoleMock:"Mock",debugPortPoolRoleCustom:"自定义",debugPortPoolRoleHint:"{role} 统一从这个范围里拿可用端口",parallelTaskDebugAction:"打开调试面板",parallelTaskDebugModalTitle:"并行任务调试",parallelTaskDebugModalDescription:"这个窗口打开时才会继续采集任务活动和 event loop 指标,关掉后立即停止。",parallelTaskDebugClose:"关闭并行任务调试",parallelTaskDebugLoading:"正在建立观测会话并拉取快照…",parallelTaskDebugLoadFailed:"加载并行任务调试信息失败",parallelTaskDebugEmpty:"当前没有可展示的执行记录。",parallelTaskDebugStatusActive:"采集中",parallelTaskDebugStatusError:"采集异常",parallelTaskDebugObservedAt:"最后更新",parallelTaskDebugSessionExpireAt:"会话到期时间",parallelTaskDebugSessionTtl:"会话 TTL",parallelTaskDebugCollectorState:"采集器状态",parallelTaskDebugCollectorEnabled:"已启用",parallelTaskDebugCollectorDisabled:"未启用",parallelTaskDebugAutoRefresh:"每秒自动刷新",parallelTaskDebugCountersTitle:"总指标",parallelTaskDebugRegisteredTasksTitle:"已注册任务列表",parallelTaskDebugRegisteredTasksEmpty:"当前没有可展示的已注册任务。",parallelTaskDebugTaskMetricsTitle:"最近活跃任务指标",parallelTaskDebugActiveTaskMetricsEmpty:"当前观测窗口内还没有活跃任务指标。",parallelTaskDebugSchedulerTitle:"调度器指标",parallelTaskDebugEventLoopTitle:"Event Loop",parallelTaskDebugRecentActivitiesTitle:"最近执行记录",parallelTaskDebugWaitAvg:"平均等待",parallelTaskDebugRunAvg:"平均执行",parallelTaskDebugRunMax:"最长执行",parallelTaskDebugStartedCount:"启动次数",parallelTaskDebugFinishedCount:"完成次数",parallelTaskDebugFailedCount:"失败次数",parallelTaskDebugCacheHitCount:"缓存命中",parallelTaskDebugIdle:"空转",parallelTaskDebugBusy:"已命中任务",parallelTaskDebugTickTotal:"tick 总数",parallelTaskDebugIdleTickTotal:"空转 tick",parallelTaskDebugTaskCountTotal:"命中任务",parallelTaskDebugSchedulerErrorTotal:"异常次数",parallelTaskDebugLastDuration:"上次耗时",parallelTaskDebugNextDelay:"下次延迟",parallelTaskDebugEventLoopResolution:"采样粒度",parallelTaskDebugEventLoopMean:"平均延迟",parallelTaskDebugEventLoopP95:"P95 延迟",parallelTaskDebugEventLoopP99:"P99 延迟",parallelTaskDebugEventLoopMax:"最大延迟",parallelTaskDebugTaskTimeout:"超时设置",parallelTaskDebugTaskConcurrency:"并发限制",parallelTaskDebugTaskRetry:"重试次数",parallelTaskDebugTaskCategory:"任务类型",parallelTaskDebugTaskCategoryBuiltinIndexer:"内置索引器",parallelTaskDebugTaskCategoryGeneric:"常规后台任务",parallelTaskDebugTaskRuntime:"运行方式",parallelTaskDebugTaskRuntimeBuiltinHelper:"Host 内置 Helper",parallelTaskDebugTaskRuntimeHelperProcess:"通用 Helper 进程",parallelTaskDebugTaskRuntimeHostBackground:"Host 后台内执行",parallelTaskDebugTaskRuntimeExternalProcess:"外部进程",parallelTaskDebugTaskRuntimeMainThread:"请求主线程",parallelTaskDebugTaskHelper:"Helper 处理器",parallelTaskDebugTaskKey:"任务 Key",parallelTaskDebugStatus:"状态",parallelTaskDebugAttempt:"尝试",parallelTaskDebugWaitMs:"等待",parallelTaskDebugRunMs:"执行",parallelTaskDebugSource:"来源",parallelTaskDebugError:"错误",parallelTaskDebugMetricEnqueue:"入队",parallelTaskDebugMetricDedupe:"去重",parallelTaskDebugMetricStarted:"已启动",parallelTaskDebugMetricFinished:"已完成",parallelTaskDebugMetricFailed:"失败",parallelTaskDebugMetricCancelled:"已取消",parallelTaskDebugMetricTimeout:"超时",parallelTaskDebugMetricCacheHit:"缓存命中",parallelTaskDebugLaneRequestMainThread:"请求主线程",parallelTaskDebugLaneHostBackground:"Host 后台",parallelTaskDebugLaneHelperProcess:"Helper 进程",parallelTaskDebugLaneExternalProcess:"外部进程",parallelTaskDebugEventEnqueued:"入队",parallelTaskDebugEventDeduped:"去重复用",parallelTaskDebugEventStarted:"开始",parallelTaskDebugEventFinished:"完成",parallelTaskDebugEventFailed:"失败",parallelTaskDebugEventCancelled:"取消",parallelTaskDebugEventTimeout:"超时",parallelTaskDebugEventCacheHit:"命中缓存",parallelTaskDebugTaskStatusQueued:"排队中",parallelTaskDebugTaskStatusRunning:"运行中",parallelTaskDebugTaskStatusSucceeded:"已成功",parallelTaskDebugTaskStatusFailed:"已失败",parallelTaskDebugTaskStatusCancelled:"已取消",parallelTaskDebugTaskStatusTimeout:"已超时",opencliSectionTitle:"OpenCLI 接入",opencliSectionDescription:"这里管理 CodingNS 会话里可见的 OpenCLI CLI技能,不改你机器上的全局安装。",opencliEnableAction:"启用",opencliRefreshAction:"刷新",opencliSaveAction:"保存",opencliLoading:"正在读取 OpenCLI 状态…",opencliLoadFailed:"读取 OpenCLI 状态失败",opencliSummaryInstallState:"安装状态",opencliSummaryCatalogCount:"目录总数",opencliSummaryEnabledCount:"当前启用",opencliSummaryBrowserCount:"依赖浏览器",opencliProviderToggleLabel:"在新会话里启用 OpenCLI",opencliProviderHint:"这里控制的是 CodingNS 托管会话里能不能用,不会改你自己终端里的全局 opencli。",opencliVersionLabel:"版本",opencliCatalogSourceLabel:"目录来源",opencliLastCheckedLabel:"最近检查",opencliCatalogRefreshedLabel:"最近刷新",opencliInstallPathLabel:"安装目录",opencliInstallInstalled:"已安装",opencliInstallBroken:"安装损坏",opencliInstallMissing:"未安装",opencliHealthReady:"可运行",opencliHealthBridgeMissing:"浏览器桥缺失",opencliHealthBinaryReady:"命令可用",opencliHealthRuntimeBuildFailed:"运行时构建失败",opencliHealthUnknown:"未检查",opencliCatalogSourceManifest:"安装目录 manifest",opencliCatalogSourceCliList:"opencli list",opencliCatalogSourceLocalManifest:"本地 manifest",opencliCatalogSourceCache:"最近一次缓存",opencliRuntimeReady:"裁剪运行时已就绪",opencliRuntimeFailed:"裁剪运行时失败",opencliRuntimePending:"裁剪运行时构建中",opencliRuntimeStale:"裁剪运行时已过期",opencliRuntimeIdle:"还没生成运行时",opencliRefreshDone:"OpenCLI 状态已刷新",opencliRefreshReady:"OpenCLI 状态已刷新,新会话可使用当前运行时",opencliRefreshCacheRetained:"刷新失败,已保留最近一次成功目录缓存",opencliRefreshUnavailable:"当前无法读取 OpenCLI 目录",opencliSaveReady:"OpenCLI 设置已保存,新会话会使用新的裁剪运行时",opencliSaveEnabled:"OpenCLI 设置已保存,但当前运行时还不可用",opencliSaveDisabled:"OpenCLI 已从新会话里关闭",opencliEmpty:"当前没有可展示的 OpenCLI 命令目录。",opencliEmptyNotInstalled:"当前机器还没发现 OpenCLI 安装,先装好后再回来刷新。",opencliCatalogGridTitle:"CLI技能目录",opencliCatalogGridDescription:"先用标签缩小范围,再按站点卡片查看和切换具体命令。",opencliDetailAction:"详情",opencliDetailTitle:"OpenCLI 详情",opencliDetailStatusHeading:"当前状态",opencliDetailRuntimeIdLabel:"运行时 ID",opencliDetailRuntimeRootLabel:"运行时目录",opencliDetailErrorHeading:"最近错误",opencliEnabledStateLabel:"新会话启用",opencliEnabledStateOn:"已启用",opencliEnabledStateOff:"已关闭",opencliFilterTabsLabel:"OpenCLI CLI技能筛选",opencliFilterAll:"全部",opencliFilterEnabled:"已启用",opencliFilterBrowser:"依赖浏览器",opencliFilterDirect:"可直接运行",opencliFilterStrategy:"策略 {strategy}",opencliFilteredEmpty:"当前筛选条件下没有可展示的 CLI技能。",opencliSiteToggleLabel:"切换站点 {site}",opencliSiteSummary:"已启用 {enabled}/{total},其中 {browser} 条依赖浏览器桥。",opencliSiteSummaryCompact:"{enabled}/{total} 已启用",opencliSiteBrowserCompact:"{count} 条依赖浏览器",opencliSiteDirectCompact:"无需浏览器桥",opencliSiteCommandCount:"{count} 条命令",opencliSiteDescriptionEmpty:"这个站点暂时没有补充说明,你可以展开下面的命令明细继续筛选。",opencliSiteViewAction:"查看",opencliSiteSelectedAction:"正在查看",opencliSiteEnableAction:"启用",opencliSiteDetailTitle:"{site} 命令",opencliSiteDetailDescription:"当前筛选命中 {count} 条,可在这里逐条控制;这个站点总共 {total} 条。",opencliSiteDescriptionHeading:"站点说明",opencliCommandModalFallbackTitle:"命令列表",opencliCommandModalEmpty:"当前筛选条件下,这个 CLI技能站点没有可展示的命令。",opencliCommandSearchLabel:"搜索命令",opencliCommandSearchPlaceholder:"按命令名、说明或策略筛选",opencliCommandSortLabel:"排序方式",opencliCommandSortStatus:"按状态",opencliCommandSortBrowser:"浏览器优先",opencliCommandSortName:"按名称",opencliCommandResultCount:"当前显示 {count} 条",opencliCommandToggleLabel:"切换命令 {commandId}",opencliBrowserTag:"浏览器桥",opencliHttpTag:"HTTP",opencliCommandDescriptionEmpty:"这条目录项没有提供额外说明。",opencliStrategyUnknown:"策略未知",opencliStrategyLabel:"类型:{strategy}",opencliStrategyShortLabel:"{strategy}",opencliStrategyCookie:"Cookie",opencliStrategyHeader:"请求头",opencliStrategyIntercept:"拦截",opencliStrategyLocal:"本地",opencliStrategyPublic:"公开",opencliStrategyUi:"界面",skillConfigTabsLabel:"技能管理标签页",skillConfigTabSkills:"SKILL",skillConfigTabOffice:"办公",skillConfigTabOps:"运维",skillConfigTabOpenCli:"OpenCLI",skillOfficeTemplateCount:"模板数量",skillOfficeBrowserProfileCount:"浏览器配置",skillOfficeBrowserTaskCount:"浏览器任务",skillOnlyOfficeStatusLabel:"Office 集成",skillOnlyOfficeSectionTitle:"ONLYOFFICE 集成",skillOnlyOfficeSectionDescription:"这里配置外部 ONLYOFFICE 服务地址,不开启不影响正常使用。",skillOnlyOfficeSectionEmpty:"当前还没有 ONLYOFFICE 配置。",skillOnlyOfficeEnabledLabel:"启用 ONLYOFFICE 文档预览与编辑",skillOnlyOfficeServerUrlLabel:"ONLYOFFICE 服务地址",skillOnlyOfficeServerUrlPlaceholder:"例如:http://127.0.0.1:8088",skillOnlyOfficePublicBaseUrlLabel:"CodingNS 对外地址",skillOnlyOfficePublicBaseUrlPlaceholder:"例如:http://host.docker.internal:3002",skillOnlyOfficeCallbackBaseUrlLabel:"回调地址(可选)",skillOnlyOfficeCallbackBaseUrlPlaceholder:"留空时默认复用 CodingNS 对外地址",skillOnlyOfficeUserDisplayNameLabel:"ONLYOFFICE 显示名称(可选)",skillOnlyOfficeUserDisplayNameDescription:"留空时默认使用当前登录用户名:{username}",skillOnlyOfficeUserDisplayNamePlaceholder:"留空时自动带入当前登录用户名",skillOnlyOfficeUserAvatarUrlLabel:"ONLYOFFICE 头像地址(可选)",skillOnlyOfficeUserAvatarUrlDescription:"留空时不传头像,填写后会显示在协作用户信息里。",skillOnlyOfficeUserAvatarUrlPlaceholder:"例如:https://example.com/avatar.png",skillOnlyOfficeJwtSecretLabel:"JWT 密钥(可选)",skillOnlyOfficeJwtSecretPlaceholder:"如果 ONLYOFFICE 开了 JWT,这里填同一份密钥",skillOnlyOfficeJwtSecretKeepPlaceholder:"当前已保存 JWT 密钥;留空表示保持不变",skillOnlyOfficeClearJwtSecretLabel:"清空当前 JWT 密钥",skillOnlyOfficeOpenSettingsAction:"设置",skillOnlyOfficeModalTitle:"配置 ONLYOFFICE",skillOnlyOfficeModalDescription:"在这里填写 ONLYOFFICE 服务地址、CodingNS 对外地址和回调地址。保存后会影响 docx、xlsx、pptx 的预览和回写。",skillOnlyOfficeSaveAction:"保存配置",skillOnlyOfficeCheckAction:"重新检测",skillOnlyOfficeSaveSuccess:"ONLYOFFICE 配置已保存。",skillOnlyOfficeCheckSuccess:"ONLYOFFICE 状态已刷新。",skillOnlyOfficeStatusReady:"可用",skillOnlyOfficeStatusWarning:"有风险",skillOnlyOfficeStatusError:"不可用",skillOnlyOfficeStatusMisconfigured:"未配好",skillOnlyOfficeStatusDisabled:"未启用",skillOnlyOfficeStatusUnknown:"状态未知",skillOnlyOfficeCheckPass:"通过",skillOnlyOfficeCheckWarn:"警告",skillOnlyOfficeCheckFail:"失败",skillOnlyOfficeCheckSkip:"跳过",skillOfficeBrowserBridgeSummaryLabel:"真实浏览器调试",skillOfficeWorkspaceScope:"当前范围",skillOfficeScoped:"当前工作区",skillOfficeGlobal:"全局",skillOfficeTemplateFormTitle:"文档模板配置",skillOfficeTemplateFormDescription:"在这里登记或更新当前可用的文档模板。模板 key 已存在时会按同 key 更新当前模板配置。",skillOfficeTemplateKeyLabel:"模板 Key",skillOfficeTemplateNameLabel:"模板名称",skillOfficeTemplateVersionLabel:"模板版本",skillOfficeTemplateFormatsLabel:"输出格式",skillOfficeTemplatePathLabel:"模板来源路径",skillOfficeTemplateSchemaLabel:"模板 Schema JSON",skillOfficeTemplateMappingLabel:"模板 Mapping JSON",skillOfficeTemplateSaveAction:"保存模板",skillOfficeTemplateCreated:"文档模板已创建。",skillOfficeTemplateUpdated:"文档模板已更新。",skillOfficeTemplateImported:"文档模板已导入。",skillOfficeTemplateListTitle:"可用模板",skillOfficeTemplateListDescription:"这里展示当前 Host 已登记的文档模板。",skillOfficeTemplateEmpty:"当前还没有可用的文档模板。",skillOfficeTemplateListMeta:"Key:{key} · 版本:{version}",skillOfficeTemplateEditAction:"模板文件",skillOfficeTemplateOpenCreateAction:"添加模板",skillOfficeTemplateModalTitle:"添加文档模板",skillOfficeTemplateModalDescription:"直接上传 .domt 或 .doct 模板文件,Host 会自动保存并识别模板信息。",skillOfficeTemplateUploadLabel:"模板文件",skillOfficeTemplateUploadDescription:"当前先支持 doct 模板文件导入,会自动生成模板 key、版本和默认映射。",skillOfficeTemplatePickAction:"选择模板文件",skillOfficeTemplateAutoDetectHint:"导入后会按文件名自动生成模板 key,并写入 Host 的模板目录。",skillOfficeBrowserProfileListTitle:"浏览器配置文件",skillOfficeBrowserProfileListDescription:"这里管理办公能力复用的真实浏览器配置,登录态、用户目录和接管方式都在这里看。",skillOfficeBrowserBridgeSummaryDetail:"{provider} 桥接状态:{status}。{detail}",skillOfficeBrowserBridgeDetailReady:"当前可以直接走真实浏览器调试。",skillOfficeBrowserBridgeAvailabilityUnknown:"状态未知",skillOfficeBrowserBridgeAvailabilityReady:"可用",skillOfficeBrowserBridgeAvailabilityDaemonMissing:"Daemon 未就绪",skillOfficeBrowserBridgeAvailabilityExtensionMissing:"扩展未连接",skillOfficeBrowserBridgeAvailabilityUnavailable:"不可用",skillOfficeBrowserProfileEmpty:"当前还没有可用的浏览器配置文件。",skillOfficeBrowserProfileOnlyCurrentWorkspace:"仅显示当前工作区记录",skillOfficeBrowserProfileListMeta:"{engine} · {mode} · {scope}",skillOfficeBrowserProfileOpenCreateAction:"添加浏览器配置",skillOfficeBrowserProfileModalTitle:"添加浏览器配置",skillOfficeBrowserProfileModalDescription:"创建独立浏览器配置,或接管已经开启远程调试端口的浏览器实例。",skillOfficeBrowserProfileFormTitle:"浏览器配置",skillOfficeBrowserProfileNameLabel:"配置名称",skillOfficeBrowserProfileEngineLabel:"浏览器",skillOfficeBrowserProfileModeLabel:"接入方式",skillOfficeBrowserProfileScopeLabel:"归属范围",skillOfficeBrowserProfileCdpEndpointLabel:"CDP 地址",skillOfficeBrowserProfileCdpEndpointDescription:"只有接管现有浏览器时才需要填写,例如 http://127.0.0.1:9222。",skillOfficeBrowserProfileSaveAction:"保存配置",skillOfficeBrowserProfileCreated:"浏览器配置已创建。",skillOfficeBrowserProfileEngineChrome:"Chrome",skillOfficeBrowserProfileEngineEdge:"Edge",skillOfficeBrowserProfileModePersistent:"独立配置",skillOfficeBrowserProfileModeCdpAttached:"接管现有浏览器",skillOfficeBrowserProfileScopeUser:"仅自己可用",skillOfficeBrowserProfileScopeWorkspace:"当前工作区可复用",skillOfficeBrowserProfileScopeTarget:"绑定到目标",skillOfficeBrowserProfileStatusActive:"可用",skillOfficeBrowserProfileStatusLocked:"占用中",skillOfficeBrowserProfileStatusArchived:"已归档",skillOfficeBrowserProfileStatusError:"异常",skillOfficeBrowserProfileUserDataDirLabel:"用户目录",skillOfficeBrowserProfileWorkspaceTag:"工作区:{workspaceName}",skillOfficeBrowserProfileWorkspaceUnbound:"未绑定工作区",skillOfficeBrowserProfileWorkspaceUnknown:"未知工作区",skillOfficeBrowserProfileCrossWorkspaceTag:"跨工作区可用",skillOfficeBrowserProfileOptionAction:"选项",skillOfficeBrowserProfileAllowCrossWorkspaceAction:"允许跨工作区使用",skillOfficeBrowserProfileSetWorkspaceOnlyAction:"设为仅当前工作区可用",skillOfficeBrowserProfileCrossWorkspaceEnabled:"浏览器配置已允许跨工作区使用。",skillOfficeBrowserProfileWorkspaceOnlyEnabled:"浏览器配置已改为仅当前工作区可用。",skillOfficeBrowserProfileWorkspaceRequired:"这个浏览器配置没有绑定工作区,不能切回仅当前工作区可用。",skillOfficeBrowserProfileOptionsModalTitle:"{profileName} 的选项",skillOfficeBrowserProfileOptionsModalDescription:"在这里调整这个浏览器配置的使用范围。",skillOfficeBrowserProfileOptionsSectionTitle:"使用范围",skillOfficeBrowserProfileCrossWorkspaceFieldLabel:"跨工作区使用",skillOfficeBrowserProfileCrossWorkspaceFieldDescription:"开启后,这个浏览器配置可以在其他工作区复用;关闭后,只允许当前工作区使用。",skillOfficeBrowserProfileTaskAction:"查看任务",skillOfficeBrowserProfileDeleteAction:"删除配置",skillOfficeBrowserProfileDeleted:"浏览器配置已删除。",skillOfficeBrowserProfileDeleteModalTitle:"确认删除浏览器配置",skillOfficeBrowserProfileDeleteModalDescription:"删除前会再确认一次,避免误删当前正在使用的配置。",skillOfficeBrowserProfileDeleteModalWarning:"删除后,这个浏览器配置会从办公能力里移除;未开始的关联任务会自动取消。",skillOfficeBrowserProfileDeleteConfirmAction:"确认删除",skillOfficeBrowserProfileCdpEndpointTag:"已接管",skillOfficeBrowserProfileTaskModalTitle:"{profileName} 的任务记录",skillOfficeBrowserProfileTaskModalDescription:"这里集中查看这个浏览器配置对应的任务记录和执行状态。",skillOfficeBrowserProfileTaskListTitle:"任务记录",skillOfficeBrowserProfileTaskListDescription:"所属工作区:{workspaceName}",skillOfficeBrowserProfileTaskEmpty:"这个浏览器配置还没有任务记录。",skillOfficeBrowserInstanceListTitle:"浏览器实例",skillOfficeBrowserInstanceListDescription:"实例本质上就是浏览器任务。这里可以新建、执行、查看当前运行状态,也能直接取消运行中的实例。",skillOfficeBrowserInstanceEmpty:"当前还没有浏览器实例。",skillOfficeBrowserInstanceListMeta:"{profileName} · {status} · 风险 {risk}",skillOfficeBrowserInstanceExecutionIdle:"未启动",skillOfficeBrowserInstanceExecutionQueued:"排队中",skillOfficeBrowserInstanceExecutionRunning:"运行中",skillOfficeBrowserInstanceExecutionSucceeded:"已完成",skillOfficeBrowserInstanceExecutionFailed:"执行失败",skillOfficeBrowserInstanceExecutionCancelled:"已取消",skillOfficeBrowserInstanceExecutionTimeout:"已超时",skillOfficeBrowserExecutionBackendPlaywright:"无头浏览器",skillOfficeBrowserExecutionBackendOpenCliBridge:"真实浏览器调试",skillOfficeBrowserInstanceDetailAction:"查看详情",skillOfficeBrowserInstanceExecuteAction:"启动实例",skillOfficeBrowserInstanceCancelAction:"取消实例",skillOfficeBrowserInstanceStarted:"浏览器实例已开始执行。",skillOfficeBrowserInstanceCancelled:"浏览器实例已取消。",skillOfficeBrowserInstanceSnapshotPending:"还没有执行快照",skillOfficeBrowserInstanceSnapshotMeta:"状态:{status} · 尝试次数:{attempt} · 开始:{startedAt} · 结束:{finishedAt}",skillOpsTaskCount:"当前任务",skillOpsTargetCount:"SSH 主机",skillOpsWorkspaceScope:"当前范围",skillOpsTaskListTitle:"运维任务",skillOpsTaskListDescription:"这里只看运维类型任务,方便快速检查当前工作区的执行状态和审批状态。",skillOpsTaskEmpty:"当前还没有运维任务。",skillOpsTaskListMeta:"状态:{status} · 风险:{risk}",skillOpsTaskDetailAction:"查看详情",skillOpsApprovalApproveAction:"批准",skillOpsApprovalApproveNote:"已在技能面板中批准执行。",skillOpsApprovalRejectNote:"已在技能面板中拒绝执行。",skillOpsApprovalApproved:"运维审批已批准。",skillOpsApprovalRejected:"运维审批已拒绝。",skillOpsTargetFormTitle:"SSH 主机配置",skillOpsTargetFormDescription:"这里先接当前已经真正支持的 SSH 主机字段:主机、用户名、端口、密钥路径和凭据引用。",skillOpsPasswordNotice:"当前正式能力只保证密钥路径和凭据引用链路可用,密码认证链路还没有完整接通。",skillOpsTargetNameLabel:"主机名称",skillOpsTargetEnvironmentLabel:"环境",skillOpsTargetHostLabel:"主机地址",skillOpsTargetPortLabel:"端口",skillOpsTargetUsernameLabel:"登录用户",skillOpsTargetPrivateKeyPathLabel:"私钥路径",skillOpsTargetKnownHostsPathLabel:"known_hosts 路径",skillOpsTargetJumpHostLabel:"跳板机",skillOpsTargetWorkspacePathLabel:"默认工作目录",skillOpsTargetCredentialRefLabel:"凭据引用",skillOpsTargetHostKeyPolicyLabel:"主机校验策略",skillOpsTargetSaveAction:"保存主机",skillOpsTargetResetAction:"清空表单",skillOpsTargetCreated:"SSH 主机已创建。",skillOpsTargetUpdated:"SSH 主机已更新。",skillOpsTargetListTitle:"已保存主机",skillOpsTargetListDescription:"这里展示当前范围内已保存的 SSH 主机配置。",skillOpsTargetEmpty:"当前还没有已保存的 SSH 主机。",skillOpsTargetEditAction:"载入编辑",skillOpsTargetOpenCreateAction:"添加主机",skillOpsTargetModalTitle:"添加 SSH 主机",skillOpsTargetModalDescription:"在这个窗口里登记当前工作区可用的 SSH 主机配置。",skillWorkspaceSessionMcpStatusAction:"查看 MCP 状态",skillWorkspaceSessionMcpModalTitle:"工作区会话 MCP 状态",skillWorkspaceSessionMcpModalDescription:"这里同时检查当前工作区会话 runtime、全局 CLI 安装状态,以及各个 CLI 是否已经具备调用 office MCP 的条件。",skillWorkspaceSessionMcpLoading:"正在读取 MCP 状态…",skillWorkspaceSessionMcpRuntimeTitle:"当前会话 runtime",skillWorkspaceSessionMcpRuntimeDescription:"先看当前工作区会话在全局 CodingNS 目录下的专用 runtime 是否真的落出了 scoped 认证、说明文件和专用 skill;Codex 的 office MCP 依赖这些运行时资产做启动时注入,不再要求写入全局 home。",skillWorkspaceSessionMcpReadyCliCount:"可直接调用",skillWorkspaceSessionMcpConfiguredCliCount:"已写配置/已注入",skillWorkspaceSessionMcpTotalCliCount:"CLI 数量",skillWorkspaceSessionMcpOverallLabel:"总体状态",skillWorkspaceSessionMcpCurrentSessionLabel:"当前会话",skillWorkspaceSessionMcpCodexLabel:"Codex",skillWorkspaceSessionMcpRuntimeHomeLabel:"runtime 目录",skillWorkspaceSessionMcpAuthFileLabel:"scoped 认证文件",skillWorkspaceSessionMcpInstructionFileLabel:"组合说明文件",skillWorkspaceSessionMcpSkillDirLabel:"工作区会话 skill 目录",skillWorkspaceSessionMcpCommandTitle:"CLI 命令状态",skillWorkspaceSessionMcpCommandDescription:"这里区分仓库里的实现是否已具备,和你机器当前全局安装的 CLI 是否已经升级到可用版本。",skillWorkspaceSessionMcpGlobalCodingnsLabel:"全局 codingns",skillWorkspaceSessionMcpGlobalStandaloneLabel:"全局 codingns-workspace-office-mcp",skillWorkspaceSessionMcpGlobalStandaloneMissing:"当前机器还没有这个独立命令入口。",skillWorkspaceSessionMcpRepoCodingnsLabel:"仓库内 codingns.mjs",skillWorkspaceSessionMcpCliTitle:"各 CLI 调用状态",skillWorkspaceSessionMcpCliDescription:"这里按各 CLI 的真实接入方式判断是否可用:Codex 看运行时注入链路,Claude Code / OpenCode 继续看 runtime 配置是否落地。",skillWorkspaceSessionMcpRefreshAction:"刷新 MCP 状态",skillWorkspaceSessionMcpStateReady:"已就绪",skillWorkspaceSessionMcpStatePartial:"部分就绪",skillWorkspaceSessionMcpStateMissing:"未就绪",skillWorkspaceSessionMcpBrowserBridgeLabel:"真实浏览器调试",skillWorkspaceSessionMcpBrowserBridgeDetail:"这里指的是 browser.opencli_bridge。它不是 profile 型任务,不需要先查或先建浏览器 Profile。",skillWorkspaceSessionMcpRecommendedPathLabel:"推荐调用链路",skillWorkspaceSessionMcpValueMissing:"当前没有可用路径",skillWorkspaceSessionMcpEmptyTitle:"还没有拿到 MCP 状态",skillWorkspaceSessionMcpEmptyDescription:"请先确认当前已经进入工作区普通会话,并且这个会话已经在全局 CodingNS 目录下生成专用 runtime。"},shell:{title:"工作台",subtitle:"管理代码项目里的 AI 会话",mobileWorkspacesEntry:"工作区",mobileTerminalsEntry:"终端",mobileSessionsEntry:"对话",mobileToolsEntry:"工具",mobileSettingsEntry:"设置",mobileNavigationAction:"打开工作台菜单",mobileSearchAction:"打开搜索",mobileAuxiliaryAction:"打开工具面板",mobileRevealNavigationAction:"显示主导航",mobileHideNavigationAction:"收起主导航",mobileConversationPreviewTitle:"快速预览",mobileConversationCurrentWorkspaceSection:"当前工作区",mobileConversationCollapsePreviewAction:"收起预览",mobileConversationRestorePreviewAction:"恢复会话预览",iosMoreAction:"更多操作",androidMoreAction:"更多操作",conversationEntry:"对话",terminalsEntry:"终端",butlerEntry:"助手",skillsEntry:"技能",codeShortcutRailTitle:"快捷应用",codeShortcutSystemBadge:"系统应用",codeShortcutTerminalTitle:"终端",codeShortcutTerminalAction:"打开终端面板",codeShortcutSkillsTitle:"技能",codeTerminalDockTitle:"终端",codeTerminalDockWorkspaceFallback:"当前工作区",codeTerminalDockCloseAction:"关闭终端面板",codeTerminalDockLayoutLabel:"终端布局",codeTerminalDockLayoutVertical:"上下布局",codeTerminalDockLayoutHorizontal:"左右布局",codeTerminalDockSwitchToVerticalAction:"切换到上下布局",codeTerminalDockSwitchToHorizontalAction:"切换到左右布局",codeTerminalDockResizeLabel:"调整对话区和终端区比例",globalNotificationsAction:"通知",globalNotificationsUnreadAria:"未读通知 {count}",globalNotificationsPanelTitle:"通知中心",globalNotificationsPanelDescription:"这里集中看需要你拍板、代办分析结果、跟进状态和验证失败的提醒。",globalNotificationsEmpty:"当前没有新的全局通知。",globalNotificationsShowArchived:"显示已归档通知",globalNotificationsArchiveAction:"归档",globalNotificationsRemoveArchiveAction:"移除归档",globalNotificationsArchiveFailed:"通知归档更新失败",globalNotificationKindWaitingUser:"等待你决定",globalNotificationKindTodoAnalyzed:"代办分析完成",globalNotificationKindTodoAnalyzeFailed:"代办分析失败",globalNotificationKindFollowUpFailed:"跟进失败",globalNotificationKindFollowUpCompleted:"跟进完成",globalNotificationKindVerificationFailed:"验证失败",globalNotificationTodoAnalyzedTitle:"代办分析完成:{title}",globalNotificationTodoAnalyzeFailedTitle:"代办分析失败:{title}",globalNotificationFollowUpWaitingTitle:"需要你决定:{title}",globalNotificationFollowUpFailedTitle:"跟进失败:{title}",globalNotificationFollowUpCompletedTitle:"跟进完成:{title}",globalNotificationVerificationFailedTitle:"验证失败:{title}",globalNotificationVerificationFailedFallback:"最近一次验证没有通过,请尽快查看。",searchEntry:"搜索",workbenchModeTabsLabel:"工作台模式",workbenchModeCode:"代码",workbenchModeAffairs:"事务",affairsInitPill:"文档与工作台",workbenchModeCodeOpenInNewWindow:"在新窗口打开代码",affairsSectionGroupPrimary:"分区入口",affairsSectionGroupFavorites:"收藏",affairsSectionGroupRecent:"最近打开",affairsNavigationDescription:"这里先收口事务分区、收藏和最近对象,别再把对象入口散在各个角落。",affairsLibraryNav:"文档",affairsLibraryNavSummary:"当前先把文档对象和相关操作接进来。",affairsLibrarySummary:"文档对象先落在中间主舞台,右侧再给详情和事务助手。",affairsWorkbenchNav:"工作台",affairsWorkbenchSummary:"把代办、自动化和 HTML 工具都收进统一工作台。",affairsWorkbenchSidebarTitle:"工作台",affairsWorkbenchSidebarDescription:"先把代办和自动化收在一起,再把右侧整块区域交给画布。当前共 {todoCount} 条代办、{automationCount} 个自动化。",affairsWorkbenchSidebarGroupOverview:"总览",affairsWorkbenchStageTitle:"工作台",affairsWorkbenchStageDescription:"这里会逐步长成整块画布式工作台。当前先保留总览、代办和自动化入口,共 {count} 项。",affairsWorkbenchEmpty:"当前还没有可展示的工作台内容。",affairsWorkbenchEmptyBody:"这一块后面会变成可摆放代办、自动化和 HTML 插件的画布。现在先用它收口旧入口,避免继续分散。",affairsWorkbenchEyebrow:"工作台预览",affairsWorkbenchDefaultTabTitle:"默认工作台",affairsWorkbenchDefaultTabShortTitle:"默认",affairsWorkbenchNewTabTitle:"工作台 {count}",affairsWorkbenchAddTabAction:"新建标签页",affairsWorkbenchRenameTabAction:"重命名标签页",affairsWorkbenchDeleteTabAction:"删除标签页",affairsWorkbenchCanvasTitle:"工作台画布",affairsWorkbenchCanvasDescription:"这块区域现在就是完整工作台画布。顶部切标签页,下面的块可以直接拖动位置,也可以直接拖拽调整大小。",affairsWorkbenchCanvasEmptyTitle:"这个标签页还没有块",affairsWorkbenchCanvasEmptyBody:"先在这里添加第一块,后面这里会变成可调整布局的正式画布。",affairsWorkbenchWidgetHtmlAppHint:"把工作区里的静态 HTML 页面直接钉进画布,适合常用工具或小应用。",affairsWorkbenchWidgetHtmlStatHint:"把 HTML 统计页面作为指标块固定在画布里,适合盯数据。",affairsWorkbenchWidgetHtmlEmbedHint:"把受控 HTML 页面嵌进工作台,适合展示页面块或只读页面。",affairsWorkbenchWidgetOpenTodoAction:"打开代办列表",affairsWorkbenchWidgetOpenAutomationAction:"打开自动化列表",affairsWorkbenchWidgetCountValue:"共 {count} 项",affairsWorkbenchWidgetTeableBadge:"Teable",affairsWorkbenchHtmlWidgetBadge:"HTML",affairsWorkbenchHtmlAppDefaultTitle:"HTML 应用",affairsWorkbenchHtmlStatDefaultTitle:"HTML 统计",affairsWorkbenchHtmlEmbedDefaultTitle:"HTML 页面",affairsWorkbenchCancelAction:"取消",affairsWorkbenchAddWidgetAction:"添加块",affairsWorkbenchResetLayoutAction:"恢复默认布局",affairsWorkbenchLockLayoutAction:"锁定布局",affairsWorkbenchUnlockLayoutAction:"解锁布局",affairsWorkbenchWidgetTypeTodo:"代办块",affairsWorkbenchWidgetTypeAutomation:"自动化块",affairsWorkbenchWidgetTypeTeable:"Teable 块",affairsWorkbenchWidgetTypeHtml:"HTML 块",affairsWorkbenchWidgetTypeHtmlApp:"HTML 应用块",affairsWorkbenchWidgetTypeHtmlStat:"HTML 统计块",affairsWorkbenchWidgetTypeHtmlEmbed:"HTML 页面块",affairsWorkbenchHtmlVariantField:"用途预设",affairsWorkbenchHtmlVariantHelper:"这里只是创建时的默认用途预设,主要影响默认标题、推荐尺寸和后续呈现语义。",affairsWorkbenchHtmlVariantApp:"应用",affairsWorkbenchHtmlVariantStat:"统计",affairsWorkbenchHtmlVariantEmbed:"页面",affairsWorkbenchWidgetTitleField:"块标题",affairsWorkbenchWidgetTitlePlaceholder:"不填就用默认标题",affairsWorkbenchHtmlSourceWorkspaceField:"来源工作区",affairsWorkbenchHtmlSourceWorkspaceHelper:"先选择代码工作区,再从这个工作区里选 HTML 文件。HTML 预览和权限会沿用该工作区。",affairsWorkbenchHtmlSourceWorkspaceCurrentLibraryOption:"当前文档库",affairsWorkbenchHtmlSourceWorkspaceCurrentLibraryHelper:"当前文档库路径:{path}。下面的文件列表直接来自这份全局文档库配置。",affairsWorkbenchHtmlSourceField:"HTML 文件路径",affairsWorkbenchHtmlSourcePlaceholder:"例如:tools/report/index.html",affairsWorkbenchHtmlSourceSelectField:"HTML 文件",affairsWorkbenchHtmlSourceSelectPlaceholder:"请选择一个 HTML 文件",affairsWorkbenchHtmlSourceHelper:"先选来源工作区,再从下面的文件列表里选 HTML 文件。",affairsWorkbenchHtmlSourceListFailed:"读取工作区 HTML 文件列表失败",affairsWorkbenchHtmlSourceInvalid:"只允许添加 .html 或 .htm 文件。",affairsWorkbenchHtmlSourceUnsupported:"这个文件当前不能作为工作台 HTML 来源。",affairsWorkbenchHtmlSourceMissing:"当前块还没有可用的 HTML 来源。",affairsWorkbenchHtmlSourceLoadFailed:"加载 HTML 页面失败",affairsWorkbenchConfirmAddWidgetAction:"确认添加",affairsWorkbenchAddWidgetFailed:"添加工作台块失败",affairsWorkbenchWidgetSizeGroup:"块尺寸",affairsWorkbenchWidgetSizeSmall:"小",affairsWorkbenchWidgetSizeMedium:"中",affairsWorkbenchWidgetSizeLarge:"大",affairsWorkbenchMoveWidgetBackwardAction:"向前移动",affairsWorkbenchMoveWidgetForwardAction:"向后移动",affairsWorkbenchDragWidgetAction:"拖动块",affairsWorkbenchResizeWidgetAction:"调整块大小",affairsWorkbenchRemoveWidgetAction:"删除块",affairsWorkbenchWidgetErrorTitle:"这个块加载失败了",affairsWorkbenchWidgetErrorBody:"先保留其他块继续用,再检查这个块的配置或来源。",affairsWorkbenchWidgetTodoViewLabel:"代办块视图",affairsWorkbenchWidgetCompactView:"紧凑",affairsWorkbenchWidgetDetailView:"明细",affairsWorkbenchWidgetAutomationViewLabel:"自动化块视图",affairsWorkbenchWidgetAutomationListView:"任务",affairsWorkbenchWidgetAutomationRecentView:"最近运行",affairsWorkbenchWidgetAutomationRunFallbackTitle:"自动化运行",affairsWorkbenchOpenHtmlAction:"新窗口打开",teableRuntimeDefaultBlockTitle:"Teable 数据",teableRuntimeTableField:"Teable 表",teableRuntimeViewField:"Teable 视图",teableRuntimeCreateFormViewField:"新建记录表单视图",teableRuntimeEditFormViewField:"编辑记录表单视图",teableRuntimeViewGrid:"表格",teableRuntimeViewForm:"表单",teableRuntimeViewCalendar:"日历",teableRuntimeViewKanban:"看板",teableRuntimeTablesLoadFailed:"读取 Teable 表失败",teableRuntimeViewsLoadFailed:"读取 Teable 视图失败",teableRuntimeTablesEmpty:"当前 Base 里还没有可选表。请先到 Teable 创建表,或检查连接设置。",teableRuntimeViewsEmpty:"这张表没有可用的表格、表单、日历或看板视图。",teableRuntimeFormViewsEmpty:"这张表没有可用的表单视图。请先在 Teable 里创建表单视图,再添加这个块。",teableRuntimeSelectionRequired:"请先选择 Teable 表和视图。",teableRuntimeBlockLoadFailed:"加载 Teable 数据失败",teableRuntimeConfigMissing:"这个 Teable 块缺少表配置。",teableRuntimeRefreshAction:"刷新记录",teableRuntimeRecordsEmpty:"当前视图还没有记录。",teableRuntimeEmptyValue:"空",teableRuntimePrimaryFieldMissing:"这张表没有可用的主字段。",teableRuntimeRecordDrawerTitle:"编辑记录",teableRuntimeRecordDrawerDescription:"普通字段可以编辑;公式、查找和汇总字段只读,由 Teable 计算。",teableRuntimeRecordFieldsTitle:"记录字段",teableRuntimeReadonlyHint:"保存后会重新读取记录,显示 Teable 计算后的最新值。",teableRuntimeSaveRecordAction:"保存记录",teableRuntimeDeleteRecordAction:"删除记录",teableRuntimeDeleteConfirm:"确定删除这条 Teable 记录吗?",teableRuntimeSaveFailed:"保存记录失败",teableRuntimeDeleteFailed:"删除记录失败",teableRuntimeCreateFailed:"新建记录失败",teableRuntimeCreateRecordAction:"新建记录",teableRuntimeCreateRecordModalTitle:"新建 Teable 记录",teableRuntimeCreateRecordModalDescription:"正在向「{table}」添加一条新记录。",teableRuntimeCreateRecordFieldsTitle:"填写记录内容",teableRuntimeCreateRecordFieldsDescription:"这里按 Teable 表单视图能读取到的字段顺序、可见字段和必填规则展示。",teableRuntimeNoWritableFields:"这张表没有可填写的字段。",teableRuntimeRequiredMark:" *",teableRuntimeRequiredFieldMissing:"请填写「{field}」。",teableRuntimeUnsupportedEditor:"暂不支持编辑,当前值:{value}",teableRuntimeLinkOptionsLoadFailed:"读取关联记录失败",teableRuntimeLinkFieldMissing:"这个关联字段缺少关联表配置。",teableRuntimeLinkEmptyOption:"不选择",teableRuntimeCalendarDateMissing:"日历视图需要一个日期字段。请在 Teable 视图或块设置里选择日期字段。",teableRuntimeKanbanGroupMissing:"看板视图需要一个单选字段。请在 Teable 视图或块设置里选择分组字段。",affairsShortcutRailTitle:"快捷应用",affairsShortcutRailDescription:"暂无",affairsShortcutRailEmpty:"暂无",affairsShortcutRailEditAction:"编辑",affairsShortcutRailDoneAction:"完成",affairsShortcutRailAddAction:"添加应用",affairsShortcutRailTitleField:"应用名称",affairsShortcutRailTitlePlaceholder:"不填就用文件名",affairsShortcutRailSourceSelectField:"文件",affairsShortcutRailSourceSelectPlaceholder:"请选择一个文件",affairsShortcutRailSourceHelper:"先选来源工作区,再从下面的文件列表里选一个文件。打开时会复用该工作区的预览和权限。",affairsShortcutRailSourceListFailed:"读取工作区文件列表失败",affairsShortcutRailSourceInvalid:"请选择一个文件。",affairsShortcutRailSourceUnsupported:"这个文件当前不能作为快捷应用打开。",affairsShortcutRailSourcePickerTitle:"选择文件",affairsShortcutRailSourcePickerDescription:"从工作区目录里选一个文件,保存后会作为快捷应用打开。",affairsShortcutRailSourcePickerCurrentField:"当前文件",affairsShortcutRailSourcePickerCurrentEmpty:"还没选文件",affairsShortcutRailSourcePickerTreeTitle:"工作区文件",affairsShortcutRailSourcePickerTreeEmpty:"当前没有可选文件",affairsShortcutRailSourcePickerTreeEmptyDescription:"先展开目录,再选一个能预览的文件。",affairsShortcutRailSourcePickerRetryAction:"重新加载",affairsShortcutRailSourcePickerConfirmAction:"使用这个文件",affairsShortcutRailConfirmAddAction:"添加到快捷应用",affairsShortcutRailConfirmEditAction:"保存快捷应用",affairsShortcutRailAddedTitle:"快捷应用已添加",affairsShortcutRailUpdatedTitle:"快捷应用已更新",affairsShortcutRailAddFailed:"添加快捷应用失败",affairsShortcutRailUpdateFailed:"更新快捷应用失败",affairsShortcutRailOpenAction:"打开",affairsShortcutRailOpenFailed:"打开快捷应用失败",affairsShortcutRailRemoveAction:"移除",affairsShortcutRailExpandAction:"展开",affairsShortcutRailCollapseAction:"收起",affairsShortcutRailMoveLeftAction:"移到左侧",affairsShortcutRailMoveRightAction:"移到右侧",affairsShortcutRailLaunchAction:"打开快捷应用:{title}",affairsShortcutRailEditEntryAction:"编辑快捷应用:{title}",affairsShortcutRailPreviewEditDisabled:"快捷应用当前只支持预览,不支持直接编辑。",codeShortcutRailStateSaveFailed:"快捷应用栏状态保存失败",affairsWorkbenchDetailTitle:"工作台总览",affairsWorkbenchDetailDescription:"这里先展示工作台的标签页和画布方向,等块系统接完后,再把更多细节放进来。",affairsWorkbenchOverviewLabel:"总览",affairsWorkbenchOverviewSummary:"先收口 {todoCount} 条代办和 {automationCount} 个自动化,后面再接画布块。",affairsWorkbenchAssistantContextTitle:"当前工作台代办",affairsWorkbenchAssistantContextSummary:"当前筛选是 {scopeLabel},共 {count} 条代办。优先关注:{titles}",affairsWorkbenchAssistantContextSummaryCompact:"当前筛选是 {scopeLabel},共 {count} 条代办。",affairsWorkbenchAssistantContextEmpty:"当前筛选下还没有代办,先帮我判断下一步该补什么。",affairsWorkbenchStepTodoTitle:"先看代办",affairsWorkbenchStepTodoDescription:"代办先按来源收进工作台,后面会变成可拖拽的块。",affairsWorkbenchStepAutomationTitle:"再看自动化",affairsWorkbenchStepAutomationDescription:"自动化任务先保留现有列表,后面再接进画布。",affairsWorkbenchStepHtmlTitle:"最后接 HTML 块",affairsWorkbenchStepHtmlDescription:"静态 HTML 快捷应用和统计插件后面统一按工作台块接入。",affairsConversationNav:"纯对话",affairsConversationSummary:"这里放纯对话历史和快速问答入口,不去碰当前项目文件。",affairsConversationSidebarTitle:"纯对话",affairsConversationSidebarListTitle:"会话列表",affairsConversationSidebarGroupModes:"创建入口",affairsConversationStageTitle:"纯对话",affairsConversationStageDescription:"先把事务对话入口和创建方式收口,后面再一条条接真实运行时。",affairsConversationEmpty:"当前还没有纯对话,先新建一条。",affairsConversationEmptyEyebrow:"开始",affairsConversationEmptyBody:"从这里新建一条纯对话,用来快速提问、联网搜索和轻量分析。",affairsConversationEmptyCreateTitle:"新建",affairsConversationEmptyCreateBody:"点击“新建对话”后,选择纯对话使用的模型再开始。",affairsConversationEmptyModeTitle:"先选会话模式",affairsConversationEmptyModeBody:"纯对话适合快速问答、联网搜索和轻量分析,不会读取本地项目文件。",affairsConversationEmptySelectedTitle:"当前准备创建的会话",affairsConversationEmptyCompanionTitle:"右侧配合使用",affairsConversationEmptyCompanionBody:"如果要继续处理代码,请回到上方项目对话。",affairsConversationEmptyTip:"这里的纯对话只负责快速问答和轻量分析。",affairsConversationEmptyDescription:"这里复用正式聊天页样式,但先把创建入口、模式分组和 provider 选择钉住,避免后面越做越乱。",affairsConversationEntryBadge:"正式入口",affairsConversationCreateAction:"新建对话",affairsConversationCreateHint:"新建纯对话",affairsConversationSidebarLoadingAll:"正在补全会话列表…",affairsConversationSidebarLoadingLightweight:"正在加载纯对话历史…",affairsConversationSidebarLoadingAgent:"正在补全助手会话…",affairsConversationAgentSessionHint:"当前工作区还没有可复用的助手会话。",affairsConversationLightweightCapabilityHint:"纯对话只支持快速问答、联网搜索和轻量分析,不会调用本地项目工具。",affairsConversationLightweightLoadFailed:"读取纯对话历史失败",affairsConversationAgentLoadFailed:"读取助手会话列表失败",affairsConversationCreateModalDescription:"先选模式,再选 provider。纯对话模式只放适合快速问答和轻量分析的 provider。",affairsConversationCreateModalDescriptionWithWorkspace:"当前文档库:{workspace}。先选会话模式,再选 provider。",affairsConversationLightweightTitle:"纯对话模式",affairsConversationLightweightDescription:"适合快速提问、联网搜索和轻量分析,不会读取或修改当前项目文件。",affairsConversationAssistantTitle:"助手模式",affairsConversationAssistantDescription:"这里复用完整助手链路和 AGENTS.md 注入,适合继续做 Agent 任务。",affairsConversationModePickerTitle:"先选会话模式,再选 provider",affairsConversationModePickerDescription:"轻量和 Agent 说的是能力级别,Codex 和 Claude Code 说的是底层 provider,这两件事不能混。",affairsConversationBoundaryTitle:"这一页当前先定什么",affairsConversationBoundaryDescription:"这一步先把入口、壳层和边界钉住,不急着把所有运行时一次接完。",affairsConversationBoundaryLightweight:"纯对话只做快速问答、联网搜索和轻量分析,不带完整本地工具。",affairsConversationBoundaryAgent:"Agent 会话后面复用完整助手链路,围绕当前文档库和事务对象继续工作。",affairsConversationBoundaryProvider:"轻量模式和助手模式是两类会话,不是 provider 别名;provider 只负责底层模型来源。",affairsInitSubmit:"完成助手初始化",affairsInitSuccess:"助手初始化已完成",affairsInitFailed:"助手初始化失败",affairsInitPreviewRuleLabel:"文档和工作台助手",affairsInitLibraryTitle:"文档库设置",affairsInitLibraryDescription:"这里决定第一次进入文档和工作台时,要不要直接把文档库接上。",affairsInitLibraryEnabledLabel:"是否启用文档库",affairsInitLibraryEnabledHint:"启用后会在初始化完成后直接绑定文档库,并开始可用。",affairsInitLibraryPathHint:"这里填事务文档库根目录,后面还能在文档库设置里再改。",affairsInitLibraryPathRequired:"启用文档库时,必须先选择文档库路径",affairsInitRouteGuardHint:"文档和工作台需要先完成助手初始化,完成后会回到你刚才要打开的位置。",affairsInitRouteGuardSidebarEmpty:"先完成初始化,左侧分区内容才会出现。",affairsInitRouteGuardAuxiliaryEmpty:"先完成初始化,右侧详情区才会展示对象内容。",affairsConnectionCheckingTitle:"正在检查助手服务",affairsConnectionCheckingDescription:"先确认 Host 是否可用,再加载文档、工作台和助手能力。",affairsConnectionCheckingSidebarEmpty:"正在检查连接状态,纯对话历史稍后再加载。",affairsConnectionCheckingAuxiliaryEmpty:"正在检查连接状态,纯对话详情稍后再加载。",affairsHostUnavailableTitle:"暂时连不上助手服务",affairsHostUnavailableDescription:"现在不是初始化问题,而是前端还连不上 Host。先把连接恢复,再回来继续。",affairsHostUnavailableRetryAction:"重新连接",affairsHostUnavailableRetryHint:"重试不会改你的初始化状态,只会重新检查 Host 是否恢复可用。",affairsHostUnavailableErrorTitle:"连接报错",affairsHostUnavailableSidebarEmpty:"连接恢复前,左侧分区内容暂时加载不出来。",affairsHostUnavailableAuxiliaryEmpty:"连接恢复前,右侧详情区暂时拿不到对象内容。",affairsConversationKindLightweight:"纯对话",affairsConversationKindAgent:"Agent 会话",affairsConversationOptionLabel:"{kind} · {provider}",affairsConversationOptionSummaryLightweight:"用 {provider} 开一条轻量对话,优先做快速问答、联网搜索和轻分析。",affairsConversationOptionSummaryAgent:"用 {provider} 开一条助手对话,后面复用完整助手链路和当前事务上下文。",affairsTodoNav:"待办",affairsTodoSummary:"这里后面承接待办拆解、优先级和执行跟踪。",affairsAutomationNav:"自动化",affairsAutomationSummary:"这里后面承接自动化流程、浏览器任务和运维结果。",affairsPluginsNav:"插件",affairsPluginsSummary:"这里后面承接事务插件和对象级扩展入口。",affairsComingSoon:"这块先占位,后面按 spec 继续接。",affairsLibraryTitle:"文档库",affairsToolbarCount:"{count} 项",affairsToolbarSummary:"当前工作区:{workspaceName} · 共 {count} 个对象",affairsToolbarExpand:"展开工具区",affairsToolbarCollapse:"收起工具区",affairsToolbarPlaceholderNew:"新建",affairsToolbarPlaceholderSearch:"搜索",affairsToolbarPlaceholderFilter:"筛选",affairsLibraryResultTitle:"对象结果",affairsLibraryEmpty:"当前还没有可用对象,先从左侧切分区或回到代码视图沉淀内容。",affairsSectionPlaceholderBadge:"规划中",affairsTodoPlaceholderTitle:"待办区稍后接入",affairsTodoPlaceholderDescription:"这块先保留正式入口,后面把待办拆解、标签整理和执行跟踪接进来。",affairsAutomationPlaceholderTitle:"自动化区稍后接入",affairsAutomationPlaceholderDescription:"这块先保留正式入口,后面把浏览器任务、自动化流程和运维动作接进来。",affairsPluginsPlaceholderTitle:"插件区稍后接入",affairsPluginsPlaceholderDescription:"这块先保留正式入口,后面把事务插件和对象级扩展入口接进来。",affairsDetailTitle:"对象详情",affairsDetailEmpty:"先从中间选一个对象,右侧再给你详情和助手。",affairsObjectTypeDocument:"文档",affairsAssistantTitle:"事务助手",affairsAssistantDescription:"这里的助手先围绕当前对象工作,不再把代码会话当默认语境。",affairsAssistantPlaceholder:"围绕《{title}》继续处理文档、标签、待办或浏览器任务",affairsAssistantPlaceholderEmpty:"先选一个对象,再让助手围着它做事。",affairsAssistantContextFallback:"当前对象还没有更多摘要。",affairsAssistantPromptPreamble:`当前事务对象:{title}
41
+ `+l.stack}return{value:e,source:t,stack:s,digest:null}}function Xo(e,t,a){return{value:e,source:null,stack:a??null,digest:t??null}}function Zo(e,t){try{console.error(t.value)}catch(a){setTimeout(function(){throw a})}}var Ch=typeof WeakMap=="function"?WeakMap:Map;function cu(e,t,a){a=Nt(-1,a),a.tag=3,a.payload={element:null};var n=t.value;return a.callback=function(){Yr||(Yr=!0,hs=n),Zo(e,t)},a}function uu(e,t,a){a=Nt(-1,a),a.tag=3;var n=e.type.getDerivedStateFromError;if(typeof n=="function"){var s=t.value;a.payload=function(){return n(s)},a.callback=function(){Zo(e,t)}}var l=e.stateNode;return l!==null&&typeof l.componentDidCatch=="function"&&(a.callback=function(){Zo(e,t),typeof n!="function"&&(ta===null?ta=new Set([this]):ta.add(this));var d=t.stack;this.componentDidCatch(t.value,{componentStack:d!==null?d:""})}),a}function du(e,t,a){var n=e.pingCache;if(n===null){n=e.pingCache=new Ch;var s=new Set;n.set(t,s)}else s=n.get(t),s===void 0&&(s=new Set,n.set(t,s));s.has(a)||(s.add(a),e=Bh.bind(null,e,t,a),t.then(e,e))}function pu(e){do{var t;if((t=e.tag===13)&&(t=e.memoizedState,t=t!==null?t.dehydrated!==null:!0),t)return e;e=e.return}while(e!==null);return null}function fu(e,t,a,n,s){return(e.mode&1)===0?(e===t?e.flags|=65536:(e.flags|=128,a.flags|=131072,a.flags&=-52805,a.tag===1&&(a.alternate===null?a.tag=17:(t=Nt(-1,1),t.tag=2,Zt(a,t,1))),a.lanes|=1),e):(e.flags|=65536,e.lanes=s,e)}var Dh=Ae.ReactCurrentOwner,je=!1;function xe(e,t,a,n){t.child=e===null?Ic(t,null,a,n):qa(t,e.child,a,n)}function hu(e,t,a,n,s){a=a.render;var l=t.ref;return Ka(t,s),n=jo(e,t,a,n,l,s),a=qo(),e!==null&&!je?(t.updateQueue=e.updateQueue,t.flags&=-2053,e.lanes&=~s,Bt(e,t,s)):(ue&&a&&Ao(t),t.flags|=1,xe(e,t,n,s),t.child)}function mu(e,t,a,n,s){if(e===null){var l=a.type;return typeof l=="function"&&!ks(l)&&l.defaultProps===void 0&&a.compare===null&&a.defaultProps===void 0?(t.tag=15,t.type=l,gu(e,t,l,n,s)):(e=tn(a.type,null,n,t,t.mode,s),e.ref=t.ref,e.return=t,t.child=e)}if(l=e.child,(e.lanes&s)===0){var d=l.memoizedProps;if(a=a.compare,a=a!==null?a:Ci,a(d,n)&&e.ref===t.ref)return Bt(e,t,s)}return t.flags|=1,e=na(l,n),e.ref=t.ref,e.return=t,t.child=e}function gu(e,t,a,n,s){if(e!==null){var l=e.memoizedProps;if(Ci(l,n)&&e.ref===t.ref)if(je=!1,t.pendingProps=n=l,(e.lanes&s)!==0)(e.flags&131072)!==0&&(je=!0);else return t.lanes=e.lanes,Bt(e,t,s)}return es(e,t,a,n,s)}function bu(e,t,a){var n=t.pendingProps,s=n.children,l=e!==null?e.memoizedState:null;if(n.mode==="hidden")if((t.mode&1)===0)t.memoizedState={baseLanes:0,cachePool:null,transitions:null},ne(Ja,Ze),Ze|=a;else{if((a&1073741824)===0)return e=l!==null?l.baseLanes|a:a,t.lanes=t.childLanes=1073741824,t.memoizedState={baseLanes:e,cachePool:null,transitions:null},t.updateQueue=null,ne(Ja,Ze),Ze|=e,null;t.memoizedState={baseLanes:0,cachePool:null,transitions:null},n=l!==null?l.baseLanes:a,ne(Ja,Ze),Ze|=n}else l!==null?(n=l.baseLanes|a,t.memoizedState=null):n=a,ne(Ja,Ze),Ze|=n;return xe(e,t,s,a),t.child}function yu(e,t){var a=t.ref;(e===null&&a!==null||e!==null&&e.ref!==a)&&(t.flags|=512,t.flags|=2097152)}function es(e,t,a,n,s){var l=ze(a)?fa:Le.current;return l=_a(t,l),Ka(t,s),a=jo(e,t,a,n,l,s),n=qo(),e!==null&&!je?(t.updateQueue=e.updateQueue,t.flags&=-2053,e.lanes&=~s,Bt(e,t,s)):(ue&&n&&Ao(t),t.flags|=1,xe(e,t,a,s),t.child)}function Su(e,t,a,n,s){if(ze(a)){var l=!0;Pr(t)}else l=!1;if(Ka(t,s),t.stateNode===null)jr(e,t),su(t,a,n),Jo(t,a,n,s),n=!0;else if(e===null){var d=t.stateNode,f=t.memoizedProps;d.props=f;var h=d.context,k=a.contextType;typeof k=="object"&&k!==null?k=nt(k):(k=ze(a)?fa:Le.current,k=_a(t,k));var C=a.getDerivedStateFromProps,D=typeof C=="function"||typeof d.getSnapshotBeforeUpdate=="function";D||typeof d.UNSAFE_componentWillReceiveProps!="function"&&typeof d.componentWillReceiveProps!="function"||(f!==n||h!==k)&&lu(t,d,n,k),Xt=!1;var w=t.memoizedState;d.state=w,Or(t,n,d,s),h=t.memoizedState,f!==n||w!==h||Ve.current||Xt?(typeof C=="function"&&($o(t,a,C,n),h=t.memoizedState),(f=Xt||ou(t,a,f,n,w,h,k))?(D||typeof d.UNSAFE_componentWillMount!="function"&&typeof d.componentWillMount!="function"||(typeof d.componentWillMount=="function"&&d.componentWillMount(),typeof d.UNSAFE_componentWillMount=="function"&&d.UNSAFE_componentWillMount()),typeof d.componentDidMount=="function"&&(t.flags|=4194308)):(typeof d.componentDidMount=="function"&&(t.flags|=4194308),t.memoizedProps=n,t.memoizedState=h),d.props=n,d.state=h,d.context=k,n=f):(typeof d.componentDidMount=="function"&&(t.flags|=4194308),n=!1)}else{d=t.stateNode,Oc(e,t),f=t.memoizedProps,k=t.type===t.elementType?f:gt(t.type,f),d.props=k,D=t.pendingProps,w=d.context,h=a.contextType,typeof h=="object"&&h!==null?h=nt(h):(h=ze(a)?fa:Le.current,h=_a(t,h));var F=a.getDerivedStateFromProps;(C=typeof F=="function"||typeof d.getSnapshotBeforeUpdate=="function")||typeof d.UNSAFE_componentWillReceiveProps!="function"&&typeof d.componentWillReceiveProps!="function"||(f!==D||w!==h)&&lu(t,d,n,h),Xt=!1,w=t.memoizedState,d.state=w,Or(t,n,d,s);var x=t.memoizedState;f!==D||w!==x||Ve.current||Xt?(typeof F=="function"&&($o(t,a,F,n),x=t.memoizedState),(k=Xt||ou(t,a,k,n,w,x,h)||!1)?(C||typeof d.UNSAFE_componentWillUpdate!="function"&&typeof d.componentWillUpdate!="function"||(typeof d.componentWillUpdate=="function"&&d.componentWillUpdate(n,x,h),typeof d.UNSAFE_componentWillUpdate=="function"&&d.UNSAFE_componentWillUpdate(n,x,h)),typeof d.componentDidUpdate=="function"&&(t.flags|=4),typeof d.getSnapshotBeforeUpdate=="function"&&(t.flags|=1024)):(typeof d.componentDidUpdate!="function"||f===e.memoizedProps&&w===e.memoizedState||(t.flags|=4),typeof d.getSnapshotBeforeUpdate!="function"||f===e.memoizedProps&&w===e.memoizedState||(t.flags|=1024),t.memoizedProps=n,t.memoizedState=x),d.props=n,d.state=x,d.context=h,n=k):(typeof d.componentDidUpdate!="function"||f===e.memoizedProps&&w===e.memoizedState||(t.flags|=4),typeof d.getSnapshotBeforeUpdate!="function"||f===e.memoizedProps&&w===e.memoizedState||(t.flags|=1024),n=!1)}return ts(e,t,a,n,l,s)}function ts(e,t,a,n,s,l){yu(e,t);var d=(t.flags&128)!==0;if(!n&&!d)return s&&Cc(t,a,!1),Bt(e,t,l);n=t.stateNode,Dh.current=t;var f=d&&typeof a.getDerivedStateFromError!="function"?null:n.render();return t.flags|=1,e!==null&&d?(t.child=qa(t,e.child,null,l),t.child=qa(t,null,f,l)):xe(e,t,f,l),t.memoizedState=n.state,s&&Cc(t,a,!0),t.child}function Tu(e){var t=e.stateNode;t.pendingContext?wc(e,t.pendingContext,t.pendingContext!==t.context):t.context&&wc(e,t.context,!1),Bo(e,t.containerInfo)}function ku(e,t,a,n,s){return ja(),Eo(s),t.flags|=256,xe(e,t,a,n),t.child}var as={dehydrated:null,treeContext:null,retryLane:0};function is(e){return{baseLanes:e,cachePool:null,transitions:null}}function wu(e,t,a){var n=t.pendingProps,s=de.current,l=!1,d=(t.flags&128)!==0,f;if((f=d)||(f=e!==null&&e.memoizedState===null?!1:(s&2)!==0),f?(l=!0,t.flags&=-129):(e===null||e.memoizedState!==null)&&(s|=1),ne(de,s&1),e===null)return Fo(t),e=t.memoizedState,e!==null&&(e=e.dehydrated,e!==null)?((t.mode&1)===0?t.lanes=1:e.data==="$!"?t.lanes=8:t.lanes=1073741824,null):(d=n.children,e=n.fallback,l?(n=t.mode,l=t.child,d={mode:"hidden",children:d},(n&1)===0&&l!==null?(l.childLanes=0,l.pendingProps=d):l=an(d,n,0,null),e=va(e,n,a,null),l.return=t,e.return=t,l.sibling=e,t.child=l,t.child.memoizedState=is(a),t.memoizedState=as,e):rs(t,d));if(s=e.memoizedState,s!==null&&(f=s.dehydrated,f!==null))return Ph(e,t,d,n,f,s,a);if(l){l=n.fallback,d=t.mode,s=e.child,f=s.sibling;var h={mode:"hidden",children:n.children};return(d&1)===0&&t.child!==s?(n=t.child,n.childLanes=0,n.pendingProps=h,t.deletions=null):(n=na(s,h),n.subtreeFlags=s.subtreeFlags&14680064),f!==null?l=na(f,l):(l=va(l,d,a,null),l.flags|=2),l.return=t,n.return=t,n.sibling=l,t.child=n,n=l,l=t.child,d=e.child.memoizedState,d=d===null?is(a):{baseLanes:d.baseLanes|a,cachePool:null,transitions:d.transitions},l.memoizedState=d,l.childLanes=e.childLanes&~a,t.memoizedState=as,n}return l=e.child,e=l.sibling,n=na(l,{mode:"visible",children:n.children}),(t.mode&1)===0&&(n.lanes=a),n.return=t,n.sibling=null,e!==null&&(a=t.deletions,a===null?(t.deletions=[e],t.flags|=16):a.push(e)),t.child=n,t.memoizedState=null,n}function rs(e,t){return t=an({mode:"visible",children:t},e.mode,0,null),t.return=e,e.child=t}function zr(e,t,a,n){return n!==null&&Eo(n),qa(t,e.child,null,a),e=rs(t,t.pendingProps.children),e.flags|=2,t.memoizedState=null,e}function Ph(e,t,a,n,s,l,d){if(a)return t.flags&256?(t.flags&=-257,n=Xo(Error(o(422))),zr(e,t,d,n)):t.memoizedState!==null?(t.child=e.child,t.flags|=128,null):(l=n.fallback,s=t.mode,n=an({mode:"visible",children:n.children},s,0,null),l=va(l,s,d,null),l.flags|=2,n.return=t,l.return=t,n.sibling=l,t.child=n,(t.mode&1)!==0&&qa(t,e.child,null,d),t.child.memoizedState=is(d),t.memoizedState=as,l);if((t.mode&1)===0)return zr(e,t,d,null);if(s.data==="$!"){if(n=s.nextSibling&&s.nextSibling.dataset,n)var f=n.dgst;return n=f,l=Error(o(419)),n=Xo(l,n,void 0),zr(e,t,d,n)}if(f=(d&e.childLanes)!==0,je||f){if(n=ve,n!==null){switch(d&-d){case 4:s=2;break;case 16:s=8;break;case 64:case 128:case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:case 4194304:case 8388608:case 16777216:case 33554432:case 67108864:s=32;break;case 536870912:s=268435456;break;default:s=0}s=(s&(n.suspendedLanes|d))!==0?0:s,s!==0&&s!==l.retryLane&&(l.retryLane=s,Ht(e,s),St(n,e,s,-1))}return Ts(),n=Xo(Error(o(421))),zr(e,t,d,n)}return s.data==="$?"?(t.flags|=128,t.child=e.child,t=Uh.bind(null,e),s._reactRetry=t,null):(e=l.treeContext,Xe=Qt(s.nextSibling),Je=t,ue=!0,mt=null,e!==null&&(it[rt++]=xt,it[rt++]=Ot,it[rt++]=ha,xt=e.id,Ot=e.overflow,ha=t),t=rs(t,n.children),t.flags|=4096,t)}function vu(e,t,a){e.lanes|=t;var n=e.alternate;n!==null&&(n.lanes|=t),Oo(e.return,t,a)}function ns(e,t,a,n,s){var l=e.memoizedState;l===null?e.memoizedState={isBackwards:t,rendering:null,renderingStartTime:0,last:n,tail:a,tailMode:s}:(l.isBackwards=t,l.rendering=null,l.renderingStartTime=0,l.last=n,l.tail=a,l.tailMode=s)}function Cu(e,t,a){var n=t.pendingProps,s=n.revealOrder,l=n.tail;if(xe(e,t,n.children,a),n=de.current,(n&2)!==0)n=n&1|2,t.flags|=128;else{if(e!==null&&(e.flags&128)!==0)e:for(e=t.child;e!==null;){if(e.tag===13)e.memoizedState!==null&&vu(e,a,t);else if(e.tag===19)vu(e,a,t);else if(e.child!==null){e.child.return=e,e=e.child;continue}if(e===t)break e;for(;e.sibling===null;){if(e.return===null||e.return===t)break e;e=e.return}e.sibling.return=e.return,e=e.sibling}n&=1}if(ne(de,n),(t.mode&1)===0)t.memoizedState=null;else switch(s){case"forwards":for(a=t.child,s=null;a!==null;)e=a.alternate,e!==null&&Hr(e)===null&&(s=a),a=a.sibling;a=s,a===null?(s=t.child,t.child=null):(s=a.sibling,a.sibling=null),ns(t,!1,s,a,l);break;case"backwards":for(a=null,s=t.child,t.child=null;s!==null;){if(e=s.alternate,e!==null&&Hr(e)===null){t.child=s;break}e=s.sibling,s.sibling=a,a=s,s=e}ns(t,!0,a,null,l);break;case"together":ns(t,!1,null,null,void 0);break;default:t.memoizedState=null}return t.child}function jr(e,t){(t.mode&1)===0&&e!==null&&(e.alternate=null,t.alternate=null,t.flags|=2)}function Bt(e,t,a){if(e!==null&&(t.dependencies=e.dependencies),Sa|=t.lanes,(a&t.childLanes)===0)return null;if(e!==null&&t.child!==e.child)throw Error(o(153));if(t.child!==null){for(e=t.child,a=na(e,e.pendingProps),t.child=a,a.return=t;e.sibling!==null;)e=e.sibling,a=a.sibling=na(e,e.pendingProps),a.return=t;a.sibling=null}return t.child}function Ah(e,t,a){switch(t.tag){case 3:Tu(t),ja();break;case 5:Bc(t);break;case 1:ze(t.type)&&Pr(t);break;case 4:Bo(t,t.stateNode.containerInfo);break;case 10:var n=t.type._context,s=t.memoizedProps.value;ne(Mr,n._currentValue),n._currentValue=s;break;case 13:if(n=t.memoizedState,n!==null)return n.dehydrated!==null?(ne(de,de.current&1),t.flags|=128,null):(a&t.child.childLanes)!==0?wu(e,t,a):(ne(de,de.current&1),e=Bt(e,t,a),e!==null?e.sibling:null);ne(de,de.current&1);break;case 19:if(n=(a&t.childLanes)!==0,(e.flags&128)!==0){if(n)return Cu(e,t,a);t.flags|=128}if(s=t.memoizedState,s!==null&&(s.rendering=null,s.tail=null,s.lastEffect=null),ne(de,de.current),n)break;return null;case 22:case 23:return t.lanes=0,bu(e,t,a)}return Bt(e,t,a)}var Du,os,Pu,Au;Du=function(e,t){for(var a=t.child;a!==null;){if(a.tag===5||a.tag===6)e.appendChild(a.stateNode);else if(a.tag!==4&&a.child!==null){a.child.return=a,a=a.child;continue}if(a===t)break;for(;a.sibling===null;){if(a.return===null||a.return===t)return;a=a.return}a.sibling.return=a.return,a=a.sibling}},os=function(){},Pu=function(e,t,a,n){var s=e.memoizedProps;if(s!==n){e=t.stateNode,ba(Pt.current);var l=null;switch(a){case"input":s=xn(e,s),n=xn(e,n),l=[];break;case"select":s=I({},s,{value:void 0}),n=I({},n,{value:void 0}),l=[];break;case"textarea":s=Nn(e,s),n=Nn(e,n),l=[];break;default:typeof s.onClick!="function"&&typeof n.onClick=="function"&&(e.onclick=vr)}Un(a,n);var d;a=null;for(k in s)if(!n.hasOwnProperty(k)&&s.hasOwnProperty(k)&&s[k]!=null)if(k==="style"){var f=s[k];for(d in f)f.hasOwnProperty(d)&&(a||(a={}),a[d]="")}else k!=="dangerouslySetInnerHTML"&&k!=="children"&&k!=="suppressContentEditableWarning"&&k!=="suppressHydrationWarning"&&k!=="autoFocus"&&(u.hasOwnProperty(k)?l||(l=[]):(l=l||[]).push(k,null));for(k in n){var h=n[k];if(f=s!=null?s[k]:void 0,n.hasOwnProperty(k)&&h!==f&&(h!=null||f!=null))if(k==="style")if(f){for(d in f)!f.hasOwnProperty(d)||h&&h.hasOwnProperty(d)||(a||(a={}),a[d]="");for(d in h)h.hasOwnProperty(d)&&f[d]!==h[d]&&(a||(a={}),a[d]=h[d])}else a||(l||(l=[]),l.push(k,a)),a=h;else k==="dangerouslySetInnerHTML"?(h=h?h.__html:void 0,f=f?f.__html:void 0,h!=null&&f!==h&&(l=l||[]).push(k,h)):k==="children"?typeof h!="string"&&typeof h!="number"||(l=l||[]).push(k,""+h):k!=="suppressContentEditableWarning"&&k!=="suppressHydrationWarning"&&(u.hasOwnProperty(k)?(h!=null&&k==="onScroll"&&se("scroll",e),l||f===h||(l=[])):(l=l||[]).push(k,h))}a&&(l=l||[]).push("style",a);var k=l;(t.updateQueue=k)&&(t.flags|=4)}},Au=function(e,t,a,n){a!==n&&(t.flags|=4)};function Ui(e,t){if(!ue)switch(e.tailMode){case"hidden":t=e.tail;for(var a=null;t!==null;)t.alternate!==null&&(a=t),t=t.sibling;a===null?e.tail=null:a.sibling=null;break;case"collapsed":a=e.tail;for(var n=null;a!==null;)a.alternate!==null&&(n=a),a=a.sibling;n===null?t||e.tail===null?e.tail=null:e.tail.sibling=null:n.sibling=null}}function Fe(e){var t=e.alternate!==null&&e.alternate.child===e.child,a=0,n=0;if(t)for(var s=e.child;s!==null;)a|=s.lanes|s.childLanes,n|=s.subtreeFlags&14680064,n|=s.flags&14680064,s.return=e,s=s.sibling;else for(s=e.child;s!==null;)a|=s.lanes|s.childLanes,n|=s.subtreeFlags,n|=s.flags,s.return=e,s=s.sibling;return e.subtreeFlags|=n,e.childLanes=a,t}function Lh(e,t,a){var n=t.pendingProps;switch(Lo(t),t.tag){case 2:case 16:case 15:case 0:case 11:case 7:case 8:case 12:case 9:case 14:return Fe(t),null;case 1:return ze(t.type)&&Dr(),Fe(t),null;case 3:return n=t.stateNode,Qa(),le(Ve),le(Le),_o(),n.pendingContext&&(n.context=n.pendingContext,n.pendingContext=null),(e===null||e.child===null)&&(Fr(t)?t.flags|=4:e===null||e.memoizedState.isDehydrated&&(t.flags&256)===0||(t.flags|=1024,mt!==null&&(bs(mt),mt=null))),os(e,t),Fe(t),null;case 5:Uo(t);var s=ba(xi.current);if(a=t.type,e!==null&&t.stateNode!=null)Pu(e,t,a,n,s),e.ref!==t.ref&&(t.flags|=512,t.flags|=2097152);else{if(!n){if(t.stateNode===null)throw Error(o(166));return Fe(t),null}if(e=ba(Pt.current),Fr(t)){n=t.stateNode,a=t.type;var l=t.memoizedProps;switch(n[Dt]=t,n[Ri]=l,e=(t.mode&1)!==0,a){case"dialog":se("cancel",n),se("close",n);break;case"iframe":case"object":case"embed":se("load",n);break;case"video":case"audio":for(s=0;s<Pi.length;s++)se(Pi[s],n);break;case"source":se("error",n);break;case"img":case"image":case"link":se("error",n),se("load",n);break;case"details":se("toggle",n);break;case"input":sl(n,l),se("invalid",n);break;case"select":n._wrapperState={wasMultiple:!!l.multiple},se("invalid",n);break;case"textarea":ul(n,l),se("invalid",n)}Un(a,l),s=null;for(var d in l)if(l.hasOwnProperty(d)){var f=l[d];d==="children"?typeof f=="string"?n.textContent!==f&&(l.suppressHydrationWarning!==!0&&wr(n.textContent,f,e),s=["children",f]):typeof f=="number"&&n.textContent!==""+f&&(l.suppressHydrationWarning!==!0&&wr(n.textContent,f,e),s=["children",""+f]):u.hasOwnProperty(d)&&f!=null&&d==="onScroll"&&se("scroll",n)}switch(a){case"input":Zi(n),cl(n,l,!0);break;case"textarea":Zi(n),pl(n);break;case"select":case"option":break;default:typeof l.onClick=="function"&&(n.onclick=vr)}n=s,t.updateQueue=n,n!==null&&(t.flags|=4)}else{d=s.nodeType===9?s:s.ownerDocument,e==="http://www.w3.org/1999/xhtml"&&(e=fl(a)),e==="http://www.w3.org/1999/xhtml"?a==="script"?(e=d.createElement("div"),e.innerHTML="<script><\/script>",e=e.removeChild(e.firstChild)):typeof n.is=="string"?e=d.createElement(a,{is:n.is}):(e=d.createElement(a),a==="select"&&(d=e,n.multiple?d.multiple=!0:n.size&&(d.size=n.size))):e=d.createElementNS(e,a),e[Dt]=t,e[Ri]=n,Du(e,t,!1,!1),t.stateNode=e;e:{switch(d=Wn(a,n),a){case"dialog":se("cancel",e),se("close",e),s=n;break;case"iframe":case"object":case"embed":se("load",e),s=n;break;case"video":case"audio":for(s=0;s<Pi.length;s++)se(Pi[s],e);s=n;break;case"source":se("error",e),s=n;break;case"img":case"image":case"link":se("error",e),se("load",e),s=n;break;case"details":se("toggle",e),s=n;break;case"input":sl(e,n),s=xn(e,n),se("invalid",e);break;case"option":s=n;break;case"select":e._wrapperState={wasMultiple:!!n.multiple},s=I({},n,{value:void 0}),se("invalid",e);break;case"textarea":ul(e,n),s=Nn(e,n),se("invalid",e);break;default:s=n}Un(a,s),f=s;for(l in f)if(f.hasOwnProperty(l)){var h=f[l];l==="style"?gl(e,h):l==="dangerouslySetInnerHTML"?(h=h?h.__html:void 0,h!=null&&hl(e,h)):l==="children"?typeof h=="string"?(a!=="textarea"||h!=="")&&si(e,h):typeof h=="number"&&si(e,""+h):l!=="suppressContentEditableWarning"&&l!=="suppressHydrationWarning"&&l!=="autoFocus"&&(u.hasOwnProperty(l)?h!=null&&l==="onScroll"&&se("scroll",e):h!=null&&ut(e,l,h,d))}switch(a){case"input":Zi(e),cl(e,n,!1);break;case"textarea":Zi(e),pl(e);break;case"option":n.value!=null&&e.setAttribute("value",""+te(n.value));break;case"select":e.multiple=!!n.multiple,l=n.value,l!=null?Ra(e,!!n.multiple,l,!1):n.defaultValue!=null&&Ra(e,!!n.multiple,n.defaultValue,!0);break;default:typeof s.onClick=="function"&&(e.onclick=vr)}switch(a){case"button":case"input":case"select":case"textarea":n=!!n.autoFocus;break e;case"img":n=!0;break e;default:n=!1}}n&&(t.flags|=4)}t.ref!==null&&(t.flags|=512,t.flags|=2097152)}return Fe(t),null;case 6:if(e&&t.stateNode!=null)Au(e,t,e.memoizedProps,n);else{if(typeof n!="string"&&t.stateNode===null)throw Error(o(166));if(a=ba(xi.current),ba(Pt.current),Fr(t)){if(n=t.stateNode,a=t.memoizedProps,n[Dt]=t,(l=n.nodeValue!==a)&&(e=Je,e!==null))switch(e.tag){case 3:wr(n.nodeValue,a,(e.mode&1)!==0);break;case 5:e.memoizedProps.suppressHydrationWarning!==!0&&wr(n.nodeValue,a,(e.mode&1)!==0)}l&&(t.flags|=4)}else n=(a.nodeType===9?a:a.ownerDocument).createTextNode(n),n[Dt]=t,t.stateNode=n}return Fe(t),null;case 13:if(le(de),n=t.memoizedState,e===null||e.memoizedState!==null&&e.memoizedState.dehydrated!==null){if(ue&&Xe!==null&&(t.mode&1)!==0&&(t.flags&128)===0)Fc(),ja(),t.flags|=98560,l=!1;else if(l=Fr(t),n!==null&&n.dehydrated!==null){if(e===null){if(!l)throw Error(o(318));if(l=t.memoizedState,l=l!==null?l.dehydrated:null,!l)throw Error(o(317));l[Dt]=t}else ja(),(t.flags&128)===0&&(t.memoizedState=null),t.flags|=4;Fe(t),l=!1}else mt!==null&&(bs(mt),mt=null),l=!0;if(!l)return t.flags&65536?t:null}return(t.flags&128)!==0?(t.lanes=a,t):(n=n!==null,n!==(e!==null&&e.memoizedState!==null)&&n&&(t.child.flags|=8192,(t.mode&1)!==0&&(e===null||(de.current&1)!==0?Te===0&&(Te=3):Ts())),t.updateQueue!==null&&(t.flags|=4),Fe(t),null);case 4:return Qa(),os(e,t),e===null&&Ai(t.stateNode.containerInfo),Fe(t),null;case 10:return xo(t.type._context),Fe(t),null;case 17:return ze(t.type)&&Dr(),Fe(t),null;case 19:if(le(de),l=t.memoizedState,l===null)return Fe(t),null;if(n=(t.flags&128)!==0,d=l.rendering,d===null)if(n)Ui(l,!1);else{if(Te!==0||e!==null&&(e.flags&128)!==0)for(e=t.child;e!==null;){if(d=Hr(e),d!==null){for(t.flags|=128,Ui(l,!1),n=d.updateQueue,n!==null&&(t.updateQueue=n,t.flags|=4),t.subtreeFlags=0,n=a,a=t.child;a!==null;)l=a,e=n,l.flags&=14680066,d=l.alternate,d===null?(l.childLanes=0,l.lanes=e,l.child=null,l.subtreeFlags=0,l.memoizedProps=null,l.memoizedState=null,l.updateQueue=null,l.dependencies=null,l.stateNode=null):(l.childLanes=d.childLanes,l.lanes=d.lanes,l.child=d.child,l.subtreeFlags=0,l.deletions=null,l.memoizedProps=d.memoizedProps,l.memoizedState=d.memoizedState,l.updateQueue=d.updateQueue,l.type=d.type,e=d.dependencies,l.dependencies=e===null?null:{lanes:e.lanes,firstContext:e.firstContext}),a=a.sibling;return ne(de,de.current&1|2),t.child}e=e.sibling}l.tail!==null&&me()>Xa&&(t.flags|=128,n=!0,Ui(l,!1),t.lanes=4194304)}else{if(!n)if(e=Hr(d),e!==null){if(t.flags|=128,n=!0,a=e.updateQueue,a!==null&&(t.updateQueue=a,t.flags|=4),Ui(l,!0),l.tail===null&&l.tailMode==="hidden"&&!d.alternate&&!ue)return Fe(t),null}else 2*me()-l.renderingStartTime>Xa&&a!==1073741824&&(t.flags|=128,n=!0,Ui(l,!1),t.lanes=4194304);l.isBackwards?(d.sibling=t.child,t.child=d):(a=l.last,a!==null?a.sibling=d:t.child=d,l.last=d)}return l.tail!==null?(t=l.tail,l.rendering=t,l.tail=t.sibling,l.renderingStartTime=me(),t.sibling=null,a=de.current,ne(de,n?a&1|2:a&1),t):(Fe(t),null);case 22:case 23:return Ss(),n=t.memoizedState!==null,e!==null&&e.memoizedState!==null!==n&&(t.flags|=8192),n&&(t.mode&1)!==0?(Ze&1073741824)!==0&&(Fe(t),t.subtreeFlags&6&&(t.flags|=8192)):Fe(t),null;case 24:return null;case 25:return null}throw Error(o(156,t.tag))}function Rh(e,t){switch(Lo(t),t.tag){case 1:return ze(t.type)&&Dr(),e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 3:return Qa(),le(Ve),le(Le),_o(),e=t.flags,(e&65536)!==0&&(e&128)===0?(t.flags=e&-65537|128,t):null;case 5:return Uo(t),null;case 13:if(le(de),e=t.memoizedState,e!==null&&e.dehydrated!==null){if(t.alternate===null)throw Error(o(340));ja()}return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 19:return le(de),null;case 4:return Qa(),null;case 10:return xo(t.type._context),null;case 22:case 23:return Ss(),null;case 24:return null;default:return null}}var qr=!1,Ee=!1,Fh=typeof WeakSet=="function"?WeakSet:Set,M=null;function $a(e,t){var a=e.ref;if(a!==null)if(typeof a=="function")try{a(null)}catch(n){he(e,t,n)}else a.current=null}function ss(e,t,a){try{a()}catch(n){he(e,t,n)}}var Lu=!1;function Eh(e,t){if(So=dr,e=oc(),uo(e)){if("selectionStart"in e)var a={start:e.selectionStart,end:e.selectionEnd};else e:{a=(a=e.ownerDocument)&&a.defaultView||window;var n=a.getSelection&&a.getSelection();if(n&&n.rangeCount!==0){a=n.anchorNode;var s=n.anchorOffset,l=n.focusNode;n=n.focusOffset;try{a.nodeType,l.nodeType}catch{a=null;break e}var d=0,f=-1,h=-1,k=0,C=0,D=e,w=null;t:for(;;){for(var F;D!==a||s!==0&&D.nodeType!==3||(f=d+s),D!==l||n!==0&&D.nodeType!==3||(h=d+n),D.nodeType===3&&(d+=D.nodeValue.length),(F=D.firstChild)!==null;)w=D,D=F;for(;;){if(D===e)break t;if(w===a&&++k===s&&(f=d),w===l&&++C===n&&(h=d),(F=D.nextSibling)!==null)break;D=w,w=D.parentNode}D=F}a=f===-1||h===-1?null:{start:f,end:h}}else a=null}a=a||{start:0,end:0}}else a=null;for(To={focusedElem:e,selectionRange:a},dr=!1,M=t;M!==null;)if(t=M,e=t.child,(t.subtreeFlags&1028)!==0&&e!==null)e.return=t,M=e;else for(;M!==null;){t=M;try{var x=t.alternate;if((t.flags&1024)!==0)switch(t.tag){case 0:case 11:case 15:break;case 1:if(x!==null){var H=x.memoizedProps,ge=x.memoizedState,b=t.stateNode,m=b.getSnapshotBeforeUpdate(t.elementType===t.type?H:gt(t.type,H),ge);b.__reactInternalSnapshotBeforeUpdate=m}break;case 3:var T=t.stateNode.containerInfo;T.nodeType===1?T.textContent="":T.nodeType===9&&T.documentElement&&T.removeChild(T.documentElement);break;case 5:case 6:case 4:case 17:break;default:throw Error(o(163))}}catch(P){he(t,t.return,P)}if(e=t.sibling,e!==null){e.return=t.return,M=e;break}M=t.return}return x=Lu,Lu=!1,x}function Wi(e,t,a){var n=t.updateQueue;if(n=n!==null?n.lastEffect:null,n!==null){var s=n=n.next;do{if((s.tag&e)===e){var l=s.destroy;s.destroy=void 0,l!==void 0&&ss(t,a,l)}s=s.next}while(s!==n)}}function Gr(e,t){if(t=t.updateQueue,t=t!==null?t.lastEffect:null,t!==null){var a=t=t.next;do{if((a.tag&e)===e){var n=a.create;a.destroy=n()}a=a.next}while(a!==t)}}function ls(e){var t=e.ref;if(t!==null){var a=e.stateNode;switch(e.tag){case 5:e=a;break;default:e=a}typeof t=="function"?t(e):t.current=e}}function Ru(e){var t=e.alternate;t!==null&&(e.alternate=null,Ru(t)),e.child=null,e.deletions=null,e.sibling=null,e.tag===5&&(t=e.stateNode,t!==null&&(delete t[Dt],delete t[Ri],delete t[Co],delete t[fh],delete t[hh])),e.stateNode=null,e.return=null,e.dependencies=null,e.memoizedProps=null,e.memoizedState=null,e.pendingProps=null,e.stateNode=null,e.updateQueue=null}function Fu(e){return e.tag===5||e.tag===3||e.tag===4}function Eu(e){e:for(;;){for(;e.sibling===null;){if(e.return===null||Fu(e.return))return null;e=e.return}for(e.sibling.return=e.return,e=e.sibling;e.tag!==5&&e.tag!==6&&e.tag!==18;){if(e.flags&2||e.child===null||e.tag===4)continue e;e.child.return=e,e=e.child}if(!(e.flags&2))return e.stateNode}}function cs(e,t,a){var n=e.tag;if(n===5||n===6)e=e.stateNode,t?a.nodeType===8?a.parentNode.insertBefore(e,t):a.insertBefore(e,t):(a.nodeType===8?(t=a.parentNode,t.insertBefore(e,a)):(t=a,t.appendChild(e)),a=a._reactRootContainer,a!=null||t.onclick!==null||(t.onclick=vr));else if(n!==4&&(e=e.child,e!==null))for(cs(e,t,a),e=e.sibling;e!==null;)cs(e,t,a),e=e.sibling}function us(e,t,a){var n=e.tag;if(n===5||n===6)e=e.stateNode,t?a.insertBefore(e,t):a.appendChild(e);else if(n!==4&&(e=e.child,e!==null))for(us(e,t,a),e=e.sibling;e!==null;)us(e,t,a),e=e.sibling}var De=null,bt=!1;function ea(e,t,a){for(a=a.child;a!==null;)Mu(e,t,a),a=a.sibling}function Mu(e,t,a){if(Ct&&typeof Ct.onCommitFiberUnmount=="function")try{Ct.onCommitFiberUnmount(nr,a)}catch{}switch(a.tag){case 5:Ee||$a(a,t);case 6:var n=De,s=bt;De=null,ea(e,t,a),De=n,bt=s,De!==null&&(bt?(e=De,a=a.stateNode,e.nodeType===8?e.parentNode.removeChild(a):e.removeChild(a)):De.removeChild(a.stateNode));break;case 18:De!==null&&(bt?(e=De,a=a.stateNode,e.nodeType===8?vo(e.parentNode,a):e.nodeType===1&&vo(e,a),yi(e)):vo(De,a.stateNode));break;case 4:n=De,s=bt,De=a.stateNode.containerInfo,bt=!0,ea(e,t,a),De=n,bt=s;break;case 0:case 11:case 14:case 15:if(!Ee&&(n=a.updateQueue,n!==null&&(n=n.lastEffect,n!==null))){s=n=n.next;do{var l=s,d=l.destroy;l=l.tag,d!==void 0&&((l&2)!==0||(l&4)!==0)&&ss(a,t,d),s=s.next}while(s!==n)}ea(e,t,a);break;case 1:if(!Ee&&($a(a,t),n=a.stateNode,typeof n.componentWillUnmount=="function"))try{n.props=a.memoizedProps,n.state=a.memoizedState,n.componentWillUnmount()}catch(f){he(a,t,f)}ea(e,t,a);break;case 21:ea(e,t,a);break;case 22:a.mode&1?(Ee=(n=Ee)||a.memoizedState!==null,ea(e,t,a),Ee=n):ea(e,t,a);break;default:ea(e,t,a)}}function Iu(e){var t=e.updateQueue;if(t!==null){e.updateQueue=null;var a=e.stateNode;a===null&&(a=e.stateNode=new Fh),t.forEach(function(n){var s=Wh.bind(null,e,n);a.has(n)||(a.add(n),n.then(s,s))})}}function yt(e,t){var a=t.deletions;if(a!==null)for(var n=0;n<a.length;n++){var s=a[n];try{var l=e,d=t,f=d;e:for(;f!==null;){switch(f.tag){case 5:De=f.stateNode,bt=!1;break e;case 3:De=f.stateNode.containerInfo,bt=!0;break e;case 4:De=f.stateNode.containerInfo,bt=!0;break e}f=f.return}if(De===null)throw Error(o(160));Mu(l,d,s),De=null,bt=!1;var h=s.alternate;h!==null&&(h.return=null),s.return=null}catch(k){he(s,t,k)}}if(t.subtreeFlags&12854)for(t=t.child;t!==null;)xu(t,e),t=t.sibling}function xu(e,t){var a=e.alternate,n=e.flags;switch(e.tag){case 0:case 11:case 14:case 15:if(yt(t,e),Lt(e),n&4){try{Wi(3,e,e.return),Gr(3,e)}catch(H){he(e,e.return,H)}try{Wi(5,e,e.return)}catch(H){he(e,e.return,H)}}break;case 1:yt(t,e),Lt(e),n&512&&a!==null&&$a(a,a.return);break;case 5:if(yt(t,e),Lt(e),n&512&&a!==null&&$a(a,a.return),e.flags&32){var s=e.stateNode;try{si(s,"")}catch(H){he(e,e.return,H)}}if(n&4&&(s=e.stateNode,s!=null)){var l=e.memoizedProps,d=a!==null?a.memoizedProps:l,f=e.type,h=e.updateQueue;if(e.updateQueue=null,h!==null)try{f==="input"&&l.type==="radio"&&l.name!=null&&ll(s,l),Wn(f,d);var k=Wn(f,l);for(d=0;d<h.length;d+=2){var C=h[d],D=h[d+1];C==="style"?gl(s,D):C==="dangerouslySetInnerHTML"?hl(s,D):C==="children"?si(s,D):ut(s,C,D,k)}switch(f){case"input":On(s,l);break;case"textarea":dl(s,l);break;case"select":var w=s._wrapperState.wasMultiple;s._wrapperState.wasMultiple=!!l.multiple;var F=l.value;F!=null?Ra(s,!!l.multiple,F,!1):w!==!!l.multiple&&(l.defaultValue!=null?Ra(s,!!l.multiple,l.defaultValue,!0):Ra(s,!!l.multiple,l.multiple?[]:"",!1))}s[Ri]=l}catch(H){he(e,e.return,H)}}break;case 6:if(yt(t,e),Lt(e),n&4){if(e.stateNode===null)throw Error(o(162));s=e.stateNode,l=e.memoizedProps;try{s.nodeValue=l}catch(H){he(e,e.return,H)}}break;case 3:if(yt(t,e),Lt(e),n&4&&a!==null&&a.memoizedState.isDehydrated)try{yi(t.containerInfo)}catch(H){he(e,e.return,H)}break;case 4:yt(t,e),Lt(e);break;case 13:yt(t,e),Lt(e),s=e.child,s.flags&8192&&(l=s.memoizedState!==null,s.stateNode.isHidden=l,!l||s.alternate!==null&&s.alternate.memoizedState!==null||(fs=me())),n&4&&Iu(e);break;case 22:if(C=a!==null&&a.memoizedState!==null,e.mode&1?(Ee=(k=Ee)||C,yt(t,e),Ee=k):yt(t,e),Lt(e),n&8192){if(k=e.memoizedState!==null,(e.stateNode.isHidden=k)&&!C&&(e.mode&1)!==0)for(M=e,C=e.child;C!==null;){for(D=M=C;M!==null;){switch(w=M,F=w.child,w.tag){case 0:case 11:case 14:case 15:Wi(4,w,w.return);break;case 1:$a(w,w.return);var x=w.stateNode;if(typeof x.componentWillUnmount=="function"){n=w,a=w.return;try{t=n,x.props=t.memoizedProps,x.state=t.memoizedState,x.componentWillUnmount()}catch(H){he(n,a,H)}}break;case 5:$a(w,w.return);break;case 22:if(w.memoizedState!==null){Nu(D);continue}}F!==null?(F.return=w,M=F):Nu(D)}C=C.sibling}e:for(C=null,D=e;;){if(D.tag===5){if(C===null){C=D;try{s=D.stateNode,k?(l=s.style,typeof l.setProperty=="function"?l.setProperty("display","none","important"):l.display="none"):(f=D.stateNode,h=D.memoizedProps.style,d=h!=null&&h.hasOwnProperty("display")?h.display:null,f.style.display=ml("display",d))}catch(H){he(e,e.return,H)}}}else if(D.tag===6){if(C===null)try{D.stateNode.nodeValue=k?"":D.memoizedProps}catch(H){he(e,e.return,H)}}else if((D.tag!==22&&D.tag!==23||D.memoizedState===null||D===e)&&D.child!==null){D.child.return=D,D=D.child;continue}if(D===e)break e;for(;D.sibling===null;){if(D.return===null||D.return===e)break e;C===D&&(C=null),D=D.return}C===D&&(C=null),D.sibling.return=D.return,D=D.sibling}}break;case 19:yt(t,e),Lt(e),n&4&&Iu(e);break;case 21:break;default:yt(t,e),Lt(e)}}function Lt(e){var t=e.flags;if(t&2){try{e:{for(var a=e.return;a!==null;){if(Fu(a)){var n=a;break e}a=a.return}throw Error(o(160))}switch(n.tag){case 5:var s=n.stateNode;n.flags&32&&(si(s,""),n.flags&=-33);var l=Eu(e);us(e,l,s);break;case 3:case 4:var d=n.stateNode.containerInfo,f=Eu(e);cs(e,f,d);break;default:throw Error(o(161))}}catch(h){he(e,e.return,h)}e.flags&=-3}t&4096&&(e.flags&=-4097)}function Mh(e,t,a){M=e,Ou(e)}function Ou(e,t,a){for(var n=(e.mode&1)!==0;M!==null;){var s=M,l=s.child;if(s.tag===22&&n){var d=s.memoizedState!==null||qr;if(!d){var f=s.alternate,h=f!==null&&f.memoizedState!==null||Ee;f=qr;var k=Ee;if(qr=d,(Ee=h)&&!k)for(M=s;M!==null;)d=M,h=d.child,d.tag===22&&d.memoizedState!==null?Bu(s):h!==null?(h.return=d,M=h):Bu(s);for(;l!==null;)M=l,Ou(l),l=l.sibling;M=s,qr=f,Ee=k}Hu(e)}else(s.subtreeFlags&8772)!==0&&l!==null?(l.return=s,M=l):Hu(e)}}function Hu(e){for(;M!==null;){var t=M;if((t.flags&8772)!==0){var a=t.alternate;try{if((t.flags&8772)!==0)switch(t.tag){case 0:case 11:case 15:Ee||Gr(5,t);break;case 1:var n=t.stateNode;if(t.flags&4&&!Ee)if(a===null)n.componentDidMount();else{var s=t.elementType===t.type?a.memoizedProps:gt(t.type,a.memoizedProps);n.componentDidUpdate(s,a.memoizedState,n.__reactInternalSnapshotBeforeUpdate)}var l=t.updateQueue;l!==null&&Nc(t,l,n);break;case 3:var d=t.updateQueue;if(d!==null){if(a=null,t.child!==null)switch(t.child.tag){case 5:a=t.child.stateNode;break;case 1:a=t.child.stateNode}Nc(t,d,a)}break;case 5:var f=t.stateNode;if(a===null&&t.flags&4){a=f;var h=t.memoizedProps;switch(t.type){case"button":case"input":case"select":case"textarea":h.autoFocus&&a.focus();break;case"img":h.src&&(a.src=h.src)}}break;case 6:break;case 4:break;case 12:break;case 13:if(t.memoizedState===null){var k=t.alternate;if(k!==null){var C=k.memoizedState;if(C!==null){var D=C.dehydrated;D!==null&&yi(D)}}}break;case 19:case 17:case 21:case 22:case 23:case 25:break;default:throw Error(o(163))}Ee||t.flags&512&&ls(t)}catch(w){he(t,t.return,w)}}if(t===e){M=null;break}if(a=t.sibling,a!==null){a.return=t.return,M=a;break}M=t.return}}function Nu(e){for(;M!==null;){var t=M;if(t===e){M=null;break}var a=t.sibling;if(a!==null){a.return=t.return,M=a;break}M=t.return}}function Bu(e){for(;M!==null;){var t=M;try{switch(t.tag){case 0:case 11:case 15:var a=t.return;try{Gr(4,t)}catch(h){he(t,a,h)}break;case 1:var n=t.stateNode;if(typeof n.componentDidMount=="function"){var s=t.return;try{n.componentDidMount()}catch(h){he(t,s,h)}}var l=t.return;try{ls(t)}catch(h){he(t,l,h)}break;case 5:var d=t.return;try{ls(t)}catch(h){he(t,d,h)}}}catch(h){he(t,t.return,h)}if(t===e){M=null;break}var f=t.sibling;if(f!==null){f.return=t.return,M=f;break}M=t.return}}var Ih=Math.ceil,Kr=Ae.ReactCurrentDispatcher,ds=Ae.ReactCurrentOwner,st=Ae.ReactCurrentBatchConfig,Y=0,ve=null,be=null,Pe=0,Ze=0,Ja=Yt(0),Te=0,_i=null,Sa=0,Qr=0,ps=0,Vi=null,qe=null,fs=0,Xa=1/0,Ut=null,Yr=!1,hs=null,ta=null,$r=!1,aa=null,Jr=0,zi=0,ms=null,Xr=-1,Zr=0;function Oe(){return(Y&6)!==0?me():Xr!==-1?Xr:Xr=me()}function ia(e){return(e.mode&1)===0?1:(Y&2)!==0&&Pe!==0?Pe&-Pe:gh.transition!==null?(Zr===0&&(Zr=El()),Zr):(e=ae,e!==0||(e=window.event,e=e===void 0?16:Wl(e.type)),e)}function St(e,t,a,n){if(50<zi)throw zi=0,ms=null,Error(o(185));fi(e,a,n),((Y&2)===0||e!==ve)&&(e===ve&&((Y&2)===0&&(Qr|=a),Te===4&&ra(e,Pe)),Ge(e,n),a===1&&Y===0&&(t.mode&1)===0&&(Xa=me()+500,Ar&&Jt()))}function Ge(e,t){var a=e.callbackNode;gf(e,t);var n=lr(e,e===ve?Pe:0);if(n===0)a!==null&&Ll(a),e.callbackNode=null,e.callbackPriority=0;else if(t=n&-n,e.callbackPriority!==t){if(a!=null&&Ll(a),t===1)e.tag===0?mh(Wu.bind(null,e)):Dc(Wu.bind(null,e)),dh(function(){(Y&6)===0&&Jt()}),a=null;else{switch(Ml(n)){case 1:a=Kn;break;case 4:a=Rl;break;case 16:a=rr;break;case 536870912:a=Fl;break;default:a=rr}a=Qu(a,Uu.bind(null,e))}e.callbackPriority=t,e.callbackNode=a}}function Uu(e,t){if(Xr=-1,Zr=0,(Y&6)!==0)throw Error(o(327));var a=e.callbackNode;if(Za()&&e.callbackNode!==a)return null;var n=lr(e,e===ve?Pe:0);if(n===0)return null;if((n&30)!==0||(n&e.expiredLanes)!==0||t)t=en(e,n);else{t=n;var s=Y;Y|=2;var l=Vu();(ve!==e||Pe!==t)&&(Ut=null,Xa=me()+500,ka(e,t));do try{Hh();break}catch(f){_u(e,f)}while(!0);Io(),Kr.current=l,Y=s,be!==null?t=0:(ve=null,Pe=0,t=Te)}if(t!==0){if(t===2&&(s=Qn(e),s!==0&&(n=s,t=gs(e,s))),t===1)throw a=_i,ka(e,0),ra(e,n),Ge(e,me()),a;if(t===6)ra(e,n);else{if(s=e.current.alternate,(n&30)===0&&!xh(s)&&(t=en(e,n),t===2&&(l=Qn(e),l!==0&&(n=l,t=gs(e,l))),t===1))throw a=_i,ka(e,0),ra(e,n),Ge(e,me()),a;switch(e.finishedWork=s,e.finishedLanes=n,t){case 0:case 1:throw Error(o(345));case 2:wa(e,qe,Ut);break;case 3:if(ra(e,n),(n&130023424)===n&&(t=fs+500-me(),10<t)){if(lr(e,0)!==0)break;if(s=e.suspendedLanes,(s&n)!==n){Oe(),e.pingedLanes|=e.suspendedLanes&s;break}e.timeoutHandle=wo(wa.bind(null,e,qe,Ut),t);break}wa(e,qe,Ut);break;case 4:if(ra(e,n),(n&4194240)===n)break;for(t=e.eventTimes,s=-1;0<n;){var d=31-ft(n);l=1<<d,d=t[d],d>s&&(s=d),n&=~l}if(n=s,n=me()-n,n=(120>n?120:480>n?480:1080>n?1080:1920>n?1920:3e3>n?3e3:4320>n?4320:1960*Ih(n/1960))-n,10<n){e.timeoutHandle=wo(wa.bind(null,e,qe,Ut),n);break}wa(e,qe,Ut);break;case 5:wa(e,qe,Ut);break;default:throw Error(o(329))}}}return Ge(e,me()),e.callbackNode===a?Uu.bind(null,e):null}function gs(e,t){var a=Vi;return e.current.memoizedState.isDehydrated&&(ka(e,t).flags|=256),e=en(e,t),e!==2&&(t=qe,qe=a,t!==null&&bs(t)),e}function bs(e){qe===null?qe=e:qe.push.apply(qe,e)}function xh(e){for(var t=e;;){if(t.flags&16384){var a=t.updateQueue;if(a!==null&&(a=a.stores,a!==null))for(var n=0;n<a.length;n++){var s=a[n],l=s.getSnapshot;s=s.value;try{if(!ht(l(),s))return!1}catch{return!1}}}if(a=t.child,t.subtreeFlags&16384&&a!==null)a.return=t,t=a;else{if(t===e)break;for(;t.sibling===null;){if(t.return===null||t.return===e)return!0;t=t.return}t.sibling.return=t.return,t=t.sibling}}return!0}function ra(e,t){for(t&=~ps,t&=~Qr,e.suspendedLanes|=t,e.pingedLanes&=~t,e=e.expirationTimes;0<t;){var a=31-ft(t),n=1<<a;e[a]=-1,t&=~n}}function Wu(e){if((Y&6)!==0)throw Error(o(327));Za();var t=lr(e,0);if((t&1)===0)return Ge(e,me()),null;var a=en(e,t);if(e.tag!==0&&a===2){var n=Qn(e);n!==0&&(t=n,a=gs(e,n))}if(a===1)throw a=_i,ka(e,0),ra(e,t),Ge(e,me()),a;if(a===6)throw Error(o(345));return e.finishedWork=e.current.alternate,e.finishedLanes=t,wa(e,qe,Ut),Ge(e,me()),null}function ys(e,t){var a=Y;Y|=1;try{return e(t)}finally{Y=a,Y===0&&(Xa=me()+500,Ar&&Jt())}}function Ta(e){aa!==null&&aa.tag===0&&(Y&6)===0&&Za();var t=Y;Y|=1;var a=st.transition,n=ae;try{if(st.transition=null,ae=1,e)return e()}finally{ae=n,st.transition=a,Y=t,(Y&6)===0&&Jt()}}function Ss(){Ze=Ja.current,le(Ja)}function ka(e,t){e.finishedWork=null,e.finishedLanes=0;var a=e.timeoutHandle;if(a!==-1&&(e.timeoutHandle=-1,uh(a)),be!==null)for(a=be.return;a!==null;){var n=a;switch(Lo(n),n.tag){case 1:n=n.type.childContextTypes,n!=null&&Dr();break;case 3:Qa(),le(Ve),le(Le),_o();break;case 5:Uo(n);break;case 4:Qa();break;case 13:le(de);break;case 19:le(de);break;case 10:xo(n.type._context);break;case 22:case 23:Ss()}a=a.return}if(ve=e,be=e=na(e.current,null),Pe=Ze=t,Te=0,_i=null,ps=Qr=Sa=0,qe=Vi=null,ga!==null){for(t=0;t<ga.length;t++)if(a=ga[t],n=a.interleaved,n!==null){a.interleaved=null;var s=n.next,l=a.pending;if(l!==null){var d=l.next;l.next=s,n.next=d}a.pending=n}ga=null}return e}function _u(e,t){do{var a=be;try{if(Io(),Nr.current=_r,Br){for(var n=pe.memoizedState;n!==null;){var s=n.queue;s!==null&&(s.pending=null),n=n.next}Br=!1}if(ya=0,we=Se=pe=null,Oi=!1,Hi=0,ds.current=null,a===null||a.return===null){Te=1,_i=t,be=null;break}e:{var l=e,d=a.return,f=a,h=t;if(t=Pe,f.flags|=32768,h!==null&&typeof h=="object"&&typeof h.then=="function"){var k=h,C=f,D=C.tag;if((C.mode&1)===0&&(D===0||D===11||D===15)){var w=C.alternate;w?(C.updateQueue=w.updateQueue,C.memoizedState=w.memoizedState,C.lanes=w.lanes):(C.updateQueue=null,C.memoizedState=null)}var F=pu(d);if(F!==null){F.flags&=-257,fu(F,d,f,l,t),F.mode&1&&du(l,k,t),t=F,h=k;var x=t.updateQueue;if(x===null){var H=new Set;H.add(h),t.updateQueue=H}else x.add(h);break e}else{if((t&1)===0){du(l,k,t),Ts();break e}h=Error(o(426))}}else if(ue&&f.mode&1){var ge=pu(d);if(ge!==null){(ge.flags&65536)===0&&(ge.flags|=256),fu(ge,d,f,l,t),Eo(Ya(h,f));break e}}l=h=Ya(h,f),Te!==4&&(Te=2),Vi===null?Vi=[l]:Vi.push(l),l=d;do{switch(l.tag){case 3:l.flags|=65536,t&=-t,l.lanes|=t;var b=cu(l,h,t);Hc(l,b);break e;case 1:f=h;var m=l.type,T=l.stateNode;if((l.flags&128)===0&&(typeof m.getDerivedStateFromError=="function"||T!==null&&typeof T.componentDidCatch=="function"&&(ta===null||!ta.has(T)))){l.flags|=65536,t&=-t,l.lanes|=t;var P=uu(l,f,t);Hc(l,P);break e}}l=l.return}while(l!==null)}ju(a)}catch(N){t=N,be===a&&a!==null&&(be=a=a.return);continue}break}while(!0)}function Vu(){var e=Kr.current;return Kr.current=_r,e===null?_r:e}function Ts(){(Te===0||Te===3||Te===2)&&(Te=4),ve===null||(Sa&268435455)===0&&(Qr&268435455)===0||ra(ve,Pe)}function en(e,t){var a=Y;Y|=2;var n=Vu();(ve!==e||Pe!==t)&&(Ut=null,ka(e,t));do try{Oh();break}catch(s){_u(e,s)}while(!0);if(Io(),Y=a,Kr.current=n,be!==null)throw Error(o(261));return ve=null,Pe=0,Te}function Oh(){for(;be!==null;)zu(be)}function Hh(){for(;be!==null&&!sf();)zu(be)}function zu(e){var t=Ku(e.alternate,e,Ze);e.memoizedProps=e.pendingProps,t===null?ju(e):be=t,ds.current=null}function ju(e){var t=e;do{var a=t.alternate;if(e=t.return,(t.flags&32768)===0){if(a=Lh(a,t,Ze),a!==null){be=a;return}}else{if(a=Rh(a,t),a!==null){a.flags&=32767,be=a;return}if(e!==null)e.flags|=32768,e.subtreeFlags=0,e.deletions=null;else{Te=6,be=null;return}}if(t=t.sibling,t!==null){be=t;return}be=t=e}while(t!==null);Te===0&&(Te=5)}function wa(e,t,a){var n=ae,s=st.transition;try{st.transition=null,ae=1,Nh(e,t,a,n)}finally{st.transition=s,ae=n}return null}function Nh(e,t,a,n){do Za();while(aa!==null);if((Y&6)!==0)throw Error(o(327));a=e.finishedWork;var s=e.finishedLanes;if(a===null)return null;if(e.finishedWork=null,e.finishedLanes=0,a===e.current)throw Error(o(177));e.callbackNode=null,e.callbackPriority=0;var l=a.lanes|a.childLanes;if(bf(e,l),e===ve&&(be=ve=null,Pe=0),(a.subtreeFlags&2064)===0&&(a.flags&2064)===0||$r||($r=!0,Qu(rr,function(){return Za(),null})),l=(a.flags&15990)!==0,(a.subtreeFlags&15990)!==0||l){l=st.transition,st.transition=null;var d=ae;ae=1;var f=Y;Y|=4,ds.current=null,Eh(e,a),xu(a,e),ih(To),dr=!!So,To=So=null,e.current=a,Mh(a),lf(),Y=f,ae=d,st.transition=l}else e.current=a;if($r&&($r=!1,aa=e,Jr=s),l=e.pendingLanes,l===0&&(ta=null),df(a.stateNode),Ge(e,me()),t!==null)for(n=e.onRecoverableError,a=0;a<t.length;a++)s=t[a],n(s.value,{componentStack:s.stack,digest:s.digest});if(Yr)throw Yr=!1,e=hs,hs=null,e;return(Jr&1)!==0&&e.tag!==0&&Za(),l=e.pendingLanes,(l&1)!==0?e===ms?zi++:(zi=0,ms=e):zi=0,Jt(),null}function Za(){if(aa!==null){var e=Ml(Jr),t=st.transition,a=ae;try{if(st.transition=null,ae=16>e?16:e,aa===null)var n=!1;else{if(e=aa,aa=null,Jr=0,(Y&6)!==0)throw Error(o(331));var s=Y;for(Y|=4,M=e.current;M!==null;){var l=M,d=l.child;if((M.flags&16)!==0){var f=l.deletions;if(f!==null){for(var h=0;h<f.length;h++){var k=f[h];for(M=k;M!==null;){var C=M;switch(C.tag){case 0:case 11:case 15:Wi(8,C,l)}var D=C.child;if(D!==null)D.return=C,M=D;else for(;M!==null;){C=M;var w=C.sibling,F=C.return;if(Ru(C),C===k){M=null;break}if(w!==null){w.return=F,M=w;break}M=F}}}var x=l.alternate;if(x!==null){var H=x.child;if(H!==null){x.child=null;do{var ge=H.sibling;H.sibling=null,H=ge}while(H!==null)}}M=l}}if((l.subtreeFlags&2064)!==0&&d!==null)d.return=l,M=d;else e:for(;M!==null;){if(l=M,(l.flags&2048)!==0)switch(l.tag){case 0:case 11:case 15:Wi(9,l,l.return)}var b=l.sibling;if(b!==null){b.return=l.return,M=b;break e}M=l.return}}var m=e.current;for(M=m;M!==null;){d=M;var T=d.child;if((d.subtreeFlags&2064)!==0&&T!==null)T.return=d,M=T;else e:for(d=m;M!==null;){if(f=M,(f.flags&2048)!==0)try{switch(f.tag){case 0:case 11:case 15:Gr(9,f)}}catch(N){he(f,f.return,N)}if(f===d){M=null;break e}var P=f.sibling;if(P!==null){P.return=f.return,M=P;break e}M=f.return}}if(Y=s,Jt(),Ct&&typeof Ct.onPostCommitFiberRoot=="function")try{Ct.onPostCommitFiberRoot(nr,e)}catch{}n=!0}return n}finally{ae=a,st.transition=t}}return!1}function qu(e,t,a){t=Ya(a,t),t=cu(e,t,1),e=Zt(e,t,1),t=Oe(),e!==null&&(fi(e,1,t),Ge(e,t))}function he(e,t,a){if(e.tag===3)qu(e,e,a);else for(;t!==null;){if(t.tag===3){qu(t,e,a);break}else if(t.tag===1){var n=t.stateNode;if(typeof t.type.getDerivedStateFromError=="function"||typeof n.componentDidCatch=="function"&&(ta===null||!ta.has(n))){e=Ya(a,e),e=uu(t,e,1),t=Zt(t,e,1),e=Oe(),t!==null&&(fi(t,1,e),Ge(t,e));break}}t=t.return}}function Bh(e,t,a){var n=e.pingCache;n!==null&&n.delete(t),t=Oe(),e.pingedLanes|=e.suspendedLanes&a,ve===e&&(Pe&a)===a&&(Te===4||Te===3&&(Pe&130023424)===Pe&&500>me()-fs?ka(e,0):ps|=a),Ge(e,t)}function Gu(e,t){t===0&&((e.mode&1)===0?t=1:(t=sr,sr<<=1,(sr&130023424)===0&&(sr=4194304)));var a=Oe();e=Ht(e,t),e!==null&&(fi(e,t,a),Ge(e,a))}function Uh(e){var t=e.memoizedState,a=0;t!==null&&(a=t.retryLane),Gu(e,a)}function Wh(e,t){var a=0;switch(e.tag){case 13:var n=e.stateNode,s=e.memoizedState;s!==null&&(a=s.retryLane);break;case 19:n=e.stateNode;break;default:throw Error(o(314))}n!==null&&n.delete(t),Gu(e,a)}var Ku;Ku=function(e,t,a){if(e!==null)if(e.memoizedProps!==t.pendingProps||Ve.current)je=!0;else{if((e.lanes&a)===0&&(t.flags&128)===0)return je=!1,Ah(e,t,a);je=(e.flags&131072)!==0}else je=!1,ue&&(t.flags&1048576)!==0&&Pc(t,Rr,t.index);switch(t.lanes=0,t.tag){case 2:var n=t.type;jr(e,t),e=t.pendingProps;var s=_a(t,Le.current);Ka(t,a),s=jo(null,t,n,e,s,a);var l=qo();return t.flags|=1,typeof s=="object"&&s!==null&&typeof s.render=="function"&&s.$$typeof===void 0?(t.tag=1,t.memoizedState=null,t.updateQueue=null,ze(n)?(l=!0,Pr(t)):l=!1,t.memoizedState=s.state!==null&&s.state!==void 0?s.state:null,No(t),s.updater=Vr,t.stateNode=s,s._reactInternals=t,Jo(t,n,e,a),t=ts(null,t,n,!0,l,a)):(t.tag=0,ue&&l&&Ao(t),xe(null,t,s,a),t=t.child),t;case 16:n=t.elementType;e:{switch(jr(e,t),e=t.pendingProps,s=n._init,n=s(n._payload),t.type=n,s=t.tag=Vh(n),e=gt(n,e),s){case 0:t=es(null,t,n,e,a);break e;case 1:t=Su(null,t,n,e,a);break e;case 11:t=hu(null,t,n,e,a);break e;case 14:t=mu(null,t,n,gt(n.type,e),a);break e}throw Error(o(306,n,""))}return t;case 0:return n=t.type,s=t.pendingProps,s=t.elementType===n?s:gt(n,s),es(e,t,n,s,a);case 1:return n=t.type,s=t.pendingProps,s=t.elementType===n?s:gt(n,s),Su(e,t,n,s,a);case 3:e:{if(Tu(t),e===null)throw Error(o(387));n=t.pendingProps,l=t.memoizedState,s=l.element,Oc(e,t),Or(t,n,null,a);var d=t.memoizedState;if(n=d.element,l.isDehydrated)if(l={element:n,isDehydrated:!1,cache:d.cache,pendingSuspenseBoundaries:d.pendingSuspenseBoundaries,transitions:d.transitions},t.updateQueue.baseState=l,t.memoizedState=l,t.flags&256){s=Ya(Error(o(423)),t),t=ku(e,t,n,a,s);break e}else if(n!==s){s=Ya(Error(o(424)),t),t=ku(e,t,n,a,s);break e}else for(Xe=Qt(t.stateNode.containerInfo.firstChild),Je=t,ue=!0,mt=null,a=Ic(t,null,n,a),t.child=a;a;)a.flags=a.flags&-3|4096,a=a.sibling;else{if(ja(),n===s){t=Bt(e,t,a);break e}xe(e,t,n,a)}t=t.child}return t;case 5:return Bc(t),e===null&&Fo(t),n=t.type,s=t.pendingProps,l=e!==null?e.memoizedProps:null,d=s.children,ko(n,s)?d=null:l!==null&&ko(n,l)&&(t.flags|=32),yu(e,t),xe(e,t,d,a),t.child;case 6:return e===null&&Fo(t),null;case 13:return wu(e,t,a);case 4:return Bo(t,t.stateNode.containerInfo),n=t.pendingProps,e===null?t.child=qa(t,null,n,a):xe(e,t,n,a),t.child;case 11:return n=t.type,s=t.pendingProps,s=t.elementType===n?s:gt(n,s),hu(e,t,n,s,a);case 7:return xe(e,t,t.pendingProps,a),t.child;case 8:return xe(e,t,t.pendingProps.children,a),t.child;case 12:return xe(e,t,t.pendingProps.children,a),t.child;case 10:e:{if(n=t.type._context,s=t.pendingProps,l=t.memoizedProps,d=s.value,ne(Mr,n._currentValue),n._currentValue=d,l!==null)if(ht(l.value,d)){if(l.children===s.children&&!Ve.current){t=Bt(e,t,a);break e}}else for(l=t.child,l!==null&&(l.return=t);l!==null;){var f=l.dependencies;if(f!==null){d=l.child;for(var h=f.firstContext;h!==null;){if(h.context===n){if(l.tag===1){h=Nt(-1,a&-a),h.tag=2;var k=l.updateQueue;if(k!==null){k=k.shared;var C=k.pending;C===null?h.next=h:(h.next=C.next,C.next=h),k.pending=h}}l.lanes|=a,h=l.alternate,h!==null&&(h.lanes|=a),Oo(l.return,a,t),f.lanes|=a;break}h=h.next}}else if(l.tag===10)d=l.type===t.type?null:l.child;else if(l.tag===18){if(d=l.return,d===null)throw Error(o(341));d.lanes|=a,f=d.alternate,f!==null&&(f.lanes|=a),Oo(d,a,t),d=l.sibling}else d=l.child;if(d!==null)d.return=l;else for(d=l;d!==null;){if(d===t){d=null;break}if(l=d.sibling,l!==null){l.return=d.return,d=l;break}d=d.return}l=d}xe(e,t,s.children,a),t=t.child}return t;case 9:return s=t.type,n=t.pendingProps.children,Ka(t,a),s=nt(s),n=n(s),t.flags|=1,xe(e,t,n,a),t.child;case 14:return n=t.type,s=gt(n,t.pendingProps),s=gt(n.type,s),mu(e,t,n,s,a);case 15:return gu(e,t,t.type,t.pendingProps,a);case 17:return n=t.type,s=t.pendingProps,s=t.elementType===n?s:gt(n,s),jr(e,t),t.tag=1,ze(n)?(e=!0,Pr(t)):e=!1,Ka(t,a),su(t,n,s),Jo(t,n,s,a),ts(null,t,n,!0,e,a);case 19:return Cu(e,t,a);case 22:return bu(e,t,a)}throw Error(o(156,t.tag))};function Qu(e,t){return Al(e,t)}function _h(e,t,a,n){this.tag=e,this.key=a,this.sibling=this.child=this.return=this.stateNode=this.type=this.elementType=null,this.index=0,this.ref=null,this.pendingProps=t,this.dependencies=this.memoizedState=this.updateQueue=this.memoizedProps=null,this.mode=n,this.subtreeFlags=this.flags=0,this.deletions=null,this.childLanes=this.lanes=0,this.alternate=null}function lt(e,t,a,n){return new _h(e,t,a,n)}function ks(e){return e=e.prototype,!(!e||!e.isReactComponent)}function Vh(e){if(typeof e=="function")return ks(e)?1:0;if(e!=null){if(e=e.$$typeof,e===wt)return 11;if(e===vt)return 14}return 2}function na(e,t){var a=e.alternate;return a===null?(a=lt(e.tag,t,e.key,e.mode),a.elementType=e.elementType,a.type=e.type,a.stateNode=e.stateNode,a.alternate=e,e.alternate=a):(a.pendingProps=t,a.type=e.type,a.flags=0,a.subtreeFlags=0,a.deletions=null),a.flags=e.flags&14680064,a.childLanes=e.childLanes,a.lanes=e.lanes,a.child=e.child,a.memoizedProps=e.memoizedProps,a.memoizedState=e.memoizedState,a.updateQueue=e.updateQueue,t=e.dependencies,a.dependencies=t===null?null:{lanes:t.lanes,firstContext:t.firstContext},a.sibling=e.sibling,a.index=e.index,a.ref=e.ref,a}function tn(e,t,a,n,s,l){var d=2;if(n=e,typeof e=="function")ks(e)&&(d=1);else if(typeof e=="string")d=5;else e:switch(e){case We:return va(a.children,s,l,t);case at:d=8,s|=8;break;case _t:return e=lt(12,a,t,s|2),e.elementType=_t,e.lanes=l,e;case Qe:return e=lt(13,a,t,s),e.elementType=Qe,e.lanes=l,e;case pt:return e=lt(19,a,t,s),e.elementType=pt,e.lanes=l,e;case fe:return an(a,s,l,t);default:if(typeof e=="object"&&e!==null)switch(e.$$typeof){case Et:d=10;break e;case ua:d=9;break e;case wt:d=11;break e;case vt:d=14;break e;case _e:d=16,n=null;break e}throw Error(o(130,e==null?e:typeof e,""))}return t=lt(d,a,t,s),t.elementType=e,t.type=n,t.lanes=l,t}function va(e,t,a,n){return e=lt(7,e,n,t),e.lanes=a,e}function an(e,t,a,n){return e=lt(22,e,n,t),e.elementType=fe,e.lanes=a,e.stateNode={isHidden:!1},e}function ws(e,t,a){return e=lt(6,e,null,t),e.lanes=a,e}function vs(e,t,a){return t=lt(4,e.children!==null?e.children:[],e.key,t),t.lanes=a,t.stateNode={containerInfo:e.containerInfo,pendingChildren:null,implementation:e.implementation},t}function zh(e,t,a,n,s){this.tag=t,this.containerInfo=e,this.finishedWork=this.pingCache=this.current=this.pendingChildren=null,this.timeoutHandle=-1,this.callbackNode=this.pendingContext=this.context=null,this.callbackPriority=0,this.eventTimes=Yn(0),this.expirationTimes=Yn(-1),this.entangledLanes=this.finishedLanes=this.mutableReadLanes=this.expiredLanes=this.pingedLanes=this.suspendedLanes=this.pendingLanes=0,this.entanglements=Yn(0),this.identifierPrefix=n,this.onRecoverableError=s,this.mutableSourceEagerHydrationData=null}function Cs(e,t,a,n,s,l,d,f,h){return e=new zh(e,t,a,f,h),t===1?(t=1,l===!0&&(t|=8)):t=0,l=lt(3,null,null,t),e.current=l,l.stateNode=e,l.memoizedState={element:n,isDehydrated:a,cache:null,transitions:null,pendingSuspenseBoundaries:null},No(l),e}function jh(e,t,a){var n=3<arguments.length&&arguments[3]!==void 0?arguments[3]:null;return{$$typeof:Ie,key:n==null?null:""+n,children:e,containerInfo:t,implementation:a}}function Yu(e){if(!e)return $t;e=e._reactInternals;e:{if(da(e)!==e||e.tag!==1)throw Error(o(170));var t=e;do{switch(t.tag){case 3:t=t.stateNode.context;break e;case 1:if(ze(t.type)){t=t.stateNode.__reactInternalMemoizedMergedChildContext;break e}}t=t.return}while(t!==null);throw Error(o(171))}if(e.tag===1){var a=e.type;if(ze(a))return vc(e,a,t)}return t}function $u(e,t,a,n,s,l,d,f,h){return e=Cs(a,n,!0,e,s,l,d,f,h),e.context=Yu(null),a=e.current,n=Oe(),s=ia(a),l=Nt(n,s),l.callback=t??null,Zt(a,l,s),e.current.lanes=s,fi(e,s,n),Ge(e,n),e}function rn(e,t,a,n){var s=t.current,l=Oe(),d=ia(s);return a=Yu(a),t.context===null?t.context=a:t.pendingContext=a,t=Nt(l,d),t.payload={element:e},n=n===void 0?null:n,n!==null&&(t.callback=n),e=Zt(s,t,d),e!==null&&(St(e,s,d,l),xr(e,s,d)),d}function nn(e){if(e=e.current,!e.child)return null;switch(e.child.tag){case 5:return e.child.stateNode;default:return e.child.stateNode}}function Ju(e,t){if(e=e.memoizedState,e!==null&&e.dehydrated!==null){var a=e.retryLane;e.retryLane=a!==0&&a<t?a:t}}function Ds(e,t){Ju(e,t),(e=e.alternate)&&Ju(e,t)}function qh(){return null}var Xu=typeof reportError=="function"?reportError:function(e){console.error(e)};function Ps(e){this._internalRoot=e}on.prototype.render=Ps.prototype.render=function(e){var t=this._internalRoot;if(t===null)throw Error(o(409));rn(e,t,null,null)},on.prototype.unmount=Ps.prototype.unmount=function(){var e=this._internalRoot;if(e!==null){this._internalRoot=null;var t=e.containerInfo;Ta(function(){rn(null,e,null,null)}),t[Mt]=null}};function on(e){this._internalRoot=e}on.prototype.unstable_scheduleHydration=function(e){if(e){var t=Ol();e={blockedOn:null,target:e,priority:t};for(var a=0;a<qt.length&&t!==0&&t<qt[a].priority;a++);qt.splice(a,0,e),a===0&&Bl(e)}};function As(e){return!(!e||e.nodeType!==1&&e.nodeType!==9&&e.nodeType!==11)}function sn(e){return!(!e||e.nodeType!==1&&e.nodeType!==9&&e.nodeType!==11&&(e.nodeType!==8||e.nodeValue!==" react-mount-point-unstable "))}function Zu(){}function Gh(e,t,a,n,s){if(s){if(typeof n=="function"){var l=n;n=function(){var k=nn(d);l.call(k)}}var d=$u(t,n,e,0,null,!1,!1,"",Zu);return e._reactRootContainer=d,e[Mt]=d.current,Ai(e.nodeType===8?e.parentNode:e),Ta(),d}for(;s=e.lastChild;)e.removeChild(s);if(typeof n=="function"){var f=n;n=function(){var k=nn(h);f.call(k)}}var h=Cs(e,0,!1,null,null,!1,!1,"",Zu);return e._reactRootContainer=h,e[Mt]=h.current,Ai(e.nodeType===8?e.parentNode:e),Ta(function(){rn(t,h,a,n)}),h}function ln(e,t,a,n,s){var l=a._reactRootContainer;if(l){var d=l;if(typeof s=="function"){var f=s;s=function(){var h=nn(d);f.call(h)}}rn(t,d,e,s)}else d=Gh(a,t,e,s,n);return nn(d)}Il=function(e){switch(e.tag){case 3:var t=e.stateNode;if(t.current.memoizedState.isDehydrated){var a=pi(t.pendingLanes);a!==0&&($n(t,a|1),Ge(t,me()),(Y&6)===0&&(Xa=me()+500,Jt()))}break;case 13:Ta(function(){var n=Ht(e,1);if(n!==null){var s=Oe();St(n,e,1,s)}}),Ds(e,1)}},Jn=function(e){if(e.tag===13){var t=Ht(e,134217728);if(t!==null){var a=Oe();St(t,e,134217728,a)}Ds(e,134217728)}},xl=function(e){if(e.tag===13){var t=ia(e),a=Ht(e,t);if(a!==null){var n=Oe();St(a,e,t,n)}Ds(e,t)}},Ol=function(){return ae},Hl=function(e,t){var a=ae;try{return ae=e,t()}finally{ae=a}},zn=function(e,t,a){switch(t){case"input":if(On(e,a),t=a.name,a.type==="radio"&&t!=null){for(a=e;a.parentNode;)a=a.parentNode;for(a=a.querySelectorAll("input[name="+JSON.stringify(""+t)+'][type="radio"]'),t=0;t<a.length;t++){var n=a[t];if(n!==e&&n.form===e.form){var s=Cr(n);if(!s)throw Error(o(90));ol(n),On(n,s)}}}break;case"textarea":dl(e,a);break;case"select":t=a.value,t!=null&&Ra(e,!!a.multiple,t,!1)}},Tl=ys,kl=Ta;var Kh={usingClientEntryPoint:!1,Events:[Fi,Ua,Cr,yl,Sl,ys]},ji={findFiberByHostInstance:pa,bundleType:0,version:"18.3.1",rendererPackageName:"react-dom"},Qh={bundleType:ji.bundleType,version:ji.version,rendererPackageName:ji.rendererPackageName,rendererConfig:ji.rendererConfig,overrideHookState:null,overrideHookStateDeletePath:null,overrideHookStateRenamePath:null,overrideProps:null,overridePropsDeletePath:null,overridePropsRenamePath:null,setErrorHandler:null,setSuspenseHandler:null,scheduleUpdate:null,currentDispatcherRef:Ae.ReactCurrentDispatcher,findHostInstanceByFiber:function(e){return e=Dl(e),e===null?null:e.stateNode},findFiberByHostInstance:ji.findFiberByHostInstance||qh,findHostInstancesForRefresh:null,scheduleRefresh:null,scheduleRoot:null,setRefreshHandler:null,getCurrentFiber:null,reconcilerVersion:"18.3.1-next-f1338f8080-20240426"};if(typeof __REACT_DEVTOOLS_GLOBAL_HOOK__<"u"){var cn=__REACT_DEVTOOLS_GLOBAL_HOOK__;if(!cn.isDisabled&&cn.supportsFiber)try{nr=cn.inject(Qh),Ct=cn}catch{}}return Ke.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED=Kh,Ke.createPortal=function(e,t){var a=2<arguments.length&&arguments[2]!==void 0?arguments[2]:null;if(!As(t))throw Error(o(200));return jh(e,t,null,a)},Ke.createRoot=function(e,t){if(!As(e))throw Error(o(299));var a=!1,n="",s=Xu;return t!=null&&(t.unstable_strictMode===!0&&(a=!0),t.identifierPrefix!==void 0&&(n=t.identifierPrefix),t.onRecoverableError!==void 0&&(s=t.onRecoverableError)),t=Cs(e,1,!1,null,null,a,!1,n,s),e[Mt]=t.current,Ai(e.nodeType===8?e.parentNode:e),new Ps(t)},Ke.findDOMNode=function(e){if(e==null)return null;if(e.nodeType===1)return e;var t=e._reactInternals;if(t===void 0)throw typeof e.render=="function"?Error(o(188)):(e=Object.keys(e).join(","),Error(o(268,e)));return e=Dl(t),e=e===null?null:e.stateNode,e},Ke.flushSync=function(e){return Ta(e)},Ke.hydrate=function(e,t,a){if(!sn(t))throw Error(o(200));return ln(null,e,t,!0,a)},Ke.hydrateRoot=function(e,t,a){if(!As(e))throw Error(o(405));var n=a!=null&&a.hydratedSources||null,s=!1,l="",d=Xu;if(a!=null&&(a.unstable_strictMode===!0&&(s=!0),a.identifierPrefix!==void 0&&(l=a.identifierPrefix),a.onRecoverableError!==void 0&&(d=a.onRecoverableError)),t=$u(t,null,e,1,a??null,s,!1,l,d),e[Mt]=t.current,Ai(e),n)for(e=0;e<n.length;e++)a=n[e],s=a._getVersion,s=s(a._source),t.mutableSourceEagerHydrationData==null?t.mutableSourceEagerHydrationData=[a,s]:t.mutableSourceEagerHydrationData.push(a,s);return new on(t)},Ke.render=function(e,t,a){if(!sn(t))throw Error(o(200));return ln(null,e,t,!1,a)},Ke.unmountComponentAtNode=function(e){if(!sn(e))throw Error(o(40));return e._reactRootContainer?(Ta(function(){ln(null,null,e,!1,function(){e._reactRootContainer=null,e[Mt]=null})}),!0):!1},Ke.unstable_batchedUpdates=ys,Ke.unstable_renderSubtreeIntoContainer=function(e,t,a,n){if(!sn(a))throw Error(o(200));if(e==null||e._reactInternals===void 0)throw Error(o(38));return ln(e,t,a,!1,n)},Ke.version="18.3.1-next-f1338f8080-20240426",Ke}var sd;function nm(){if(sd)return Fs.exports;sd=1;function i(){if(!(typeof __REACT_DEVTOOLS_GLOBAL_HOOK__>"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(i)}catch(r){console.error(r)}}return i(),Fs.exports=rm(),Fs.exports}var ld;function om(){if(ld)return un;ld=1;var i=nm();return un.createRoot=i.createRoot,un.hydrateRoot=i.hydrateRoot,un}var sm=om();const lm=Vd(sm),cm="modulepreload",um=function(i){return"/"+i},cd={},Wt=function(r,o,c){let u=Promise.resolve();if(o&&o.length>0){let y=function(O){return Promise.all(O.map(E=>Promise.resolve(E).then(W=>({status:"fulfilled",value:W}),W=>({status:"rejected",reason:W}))))};document.getElementsByTagName("link");const S=document.querySelector("meta[property=csp-nonce]"),A=(S==null?void 0:S.nonce)||(S==null?void 0:S.getAttribute("nonce"));u=y(o.map(O=>{if(O=um(O),O in cd)return;cd[O]=!0;const E=O.endsWith(".css"),W=E?'[rel="stylesheet"]':"";if(document.querySelector(`link[href="${O}"]${W}`))return;const j=document.createElement("link");if(j.rel=E?"stylesheet":cm,E||(j.as="script"),j.crossOrigin="",j.href=O,A&&j.setAttribute("nonce",A),document.head.appendChild(j),E)return new Promise((ye,ie)=>{j.addEventListener("load",ye),j.addEventListener("error",()=>ie(new Error(`Unable to preload CSS for ${O}`)))})}))}function p(y){const S=new Event("vite:preloadError",{cancelable:!0});if(S.payload=y,window.dispatchEvent(S),!S.defaultPrevented)throw y}return u.then(y=>{for(const S of y||[])S.status==="rejected"&&p(S.reason);return r().catch(p)})};var He=Qs();const dm=Vd(He),Xy=Xh({__proto__:null,default:dm},[He]),pm={common:{appName:"CodingNS",loading:"Loading...",retry:"Retry",back:"Back",save:"Save",connectionRouteRelay:"CodingNS Connect",connectionRouteLan:"LAN Direct",connectionRouteLoopback:"Local Direct",connectionRouteTailscale:"Tailscale Direct",connectionRouteDirect:"Direct Connection",logout:"Log out",unknown:"Unknown session",close:"Close",cancel:"Cancel",language:"Language"},auth:{loginTitle:"Resume your coding session",loginSubtitle:"INITIALIZING DEVELOPMENT ENVIRONMENT...",serverPreset:"Server Preset",serverCustomOption:"Use custom server",serverAddress:"Server Address",serverPlaceholder:"For example: http://127.0.0.1:3002",serverHint:"Login, realtime messages, and terminals all connect through this host. Point the client at the Host API endpoint such as http://127.0.0.1:3002; frontend dev ports like 4174 or 5173 are not meant for packaged clients and only work for temporary debugging when proxying and CORS are configured correctly.",serverInvalid:"Invalid server address. Check it and try again.",serverDiscoveredTag:"Auto-discovered",serverCurrent:"Current Server",bootstrapTitle:"Complete the first-time bootstrap",bootstrapSubtitle:"This Host does not have an admin account yet. Create the minimal login entry first.",username:"Username",password:"Password",rememberPassword:"Remember Password",confirmPassword:"Confirm Password",submitLogin:"Enter Workspace",submitBootstrap:"Create Admin Account",bootstrapSuccess:"Bootstrap completed. You can log in now.",bootstrapMismatch:"The two passwords do not match.",authUnavailable:"Host is unreachable right now. Check the server and try again.",logoutSuccess:"The current login state has been cleared.",demoBanner:"Demo environment — all account data is public and cleared on logout",demoSessionExpired:"Demo session expired. Please log in again.",captcha:"Captcha",captchaPlaceholder:"Enter the characters in the image",captchaHint:"After three failed attempts, complete the captcha before trying again.",captchaImageAlt:"Login captcha image",serverSettings:"Server Settings",serverSettingsTitle:"Server Configuration",saveServerSettings:"Save Settings",relayEntryTitle:"Connecting To Remote Host",relayEntryDescription:"Switching to this Host's trusted remote entry. You will be returned to the login page automatically.",relayEntryInvalid:"The remote access entry parameters are incomplete. Open the access URL again.",trustedEntryOnlyTitle:"Open This Through Your Remote Access URL",trustedEntryOnlyDescription:"This trusted frontend only loads the connection UI. It is not the Host API entry itself. Open the device's remote access URL again.",trustedEntryOnlyHintTitle:"How to enter",trustedEntryOnlyHint:"Use a remote access URL like https://xxxx.channel.codingns.com:1443. The tunnel domain will redirect you to the correct trusted entry automatically."},plugins:{listTitle:"Plugins",listDescription:"Review the plugins available to this workspace and decide whether to open or disable them.",loading:"Loading plugins...",listLoadFailed:"Failed to load the plugin list.",emptyTitle:"No plugins are available yet",emptyDescription:"Valid plugins will appear here automatically after Host scans them.",enabled:"Enabled",disabled:"Disabled",frontendTag:"Frontend",backendTag:"Action",detailLoadFailed:"Failed to load the plugin details.",detailMissingTitle:"This plugin could not be found",detailMissingDescription:"The plugin directory may have been removed, or Host has not scanned it again yet.",backToList:"Back to plugins",backToDetail:"Back to details",summaryTitle:"Summary",summaryDescription:"Confirm what this plugin is, where it is installed, and whether it is usable.",pluginIdLabel:"Plugin ID",installRootLabel:"Install directory",runtimeLabel:"Runtime",frontendOnly:"Frontend only, without backend actions",permissionTitle:"Permissions",permissionDescription:"Only explicitly declared permissions are listed here. Anything undeclared stays blocked by default.",workspaceReadAllowed:"Can read the current workspace",workspaceReadDenied:"Workspace read is not declared",networkAllowed:"Network access allowed",networkDenied:"Network access blocked by default",noDesktopPermission:"No desktop permission",actionTitle:"Available actions",actionDescription:"Every action goes through the unified plugin gateway instead of private command entry points.",runHistoryTitle:"Recent runs",runHistoryDescription:"Show the latest 10 runs first so it is easy to see whether actions actually ran.",runHistoryEmptyTitle:"No runs yet",runHistoryEmptyDescription:"A formal run record will appear here after the first action execution.",unknownAction:"Unknown action",openPlugin:"Open plugin",enableAction:"Enable plugin",disableAction:"Disable plugin",permissionNameReadFile:"Read files",permissionNameListDirectory:"List directory contents",permissionNameWriteFile:"Write files",permissionNameOpenFile:"Open files on desktop",permissionNameRevealInFileManager:"Reveal files in the file manager",permissionScopeWorkspace:"The whole current workspace",permissionScopeDirectory:"Directory: {scopePath}",permissionScopeFile:"File: {scopePath}",permissionScopeUnknown:"The target scope is not clear yet",permissionGrantModeOnce:"This time only",permissionGrantModeSession:"While this page stays open",permissionGrantModePersistent:"Keep it long term",permissionPromptTitle:"This plugin needs your approval first",permissionPromptDescription:"Review what it wants to do, then decide how long and how far the permission should go.",permissionPromptSummaryTitle:"What this request is asking for",permissionPromptSummaryDescription:"{pluginName} asked for a controlled capability. Nothing continues until you approve it.",permissionPromptPermissionLabel:"Requested capability",permissionPromptTargetLabel:"Applies to",permissionPromptPendingTag:"Waiting for you",permissionPromptOptionsTitle:"How you can allow it",permissionPromptOptionsDescription:"Start with the smallest scope instead of opening too much by default.",permissionPromptOptionOnce:"Allow only this target once",permissionPromptOptionOnceDescription:"Only continue this request. The plugin must ask again next time.",permissionPromptOptionSession:"Allow for this open session",permissionPromptOptionSessionDescription:"Keep it only while this plugin page stays open, then expire it automatically.",permissionPromptOptionDirectory:"Allow this directory long term",permissionPromptOptionDirectoryDescription:"Future access to {scopePath} and its children will not ask again each time.",permissionPromptDenyAction:"Not now",permissionPromptNoOptionTitle:"No valid approval choice is available",permissionPromptNoOptionDescription:"This request does not provide a safe scope yet. Go back to the plugin details first.",grantedPermissionTitle:"Permissions already allowed in this workspace",grantedPermissionDescription:"This shows only what has already been allowed for the current workspace, so you can pull it back at any time.",grantedPermissionEmptyTitle:"No permission has been granted yet",grantedPermissionEmptyDescription:"A formal grant record appears here after the plugin asks for access and you approve it.",permissionGrantLoading:"Loading permission grants...",permissionGrantLoadFailed:"Failed to load plugin permission grants.",revokeGrantAction:"Revoke",revokeGrantSuccess:"The plugin permission was revoked.",revokeGrantFailed:"Failed to revoke the plugin permission.",permissionAuditTitle:"Recent permission activity",permissionAuditDescription:"Grant, deny, and revoke records stay here so you can trace who opened what later.",permissionAuditEmptyTitle:"No permission activity yet",permissionAuditEmptyDescription:"Grant, deny, or revoke activity will appear here automatically.",permissionEventGranted:"Granted: {permission}",permissionEventRevoked:"Revoked: {permission}",permissionEventDenied:"Denied: {permission}",permissionEventUnknown:"Unknown permission",permissionEventReasonDeclarationMissing:"Denied because the plugin never declared it",permissionEventReasonGrantRequired:"Needs your approval first",enableSuccess:"Plugin enabled.",disableSuccess:"Plugin disabled.",saveFailed:"Failed to save the plugin state.",disabledByUserReason:"Disabled by the user from the plugin detail page",containerDescription:"The plugin frontend runs in an isolated container and does not receive the host desktop bridge directly.",containerLoadFailed:"Failed to load the plugin runtime page.",containerMissingTitle:"This plugin has no runnable page",containerMissingDescription:"This plugin may be backend-only or already disabled."},settings:{title:"Settings",appearance:"Appearance",appearanceSectionSummary:"Language, theme, and interface colors",language:"Language",languageDescription:"Choose the display language used by the interface.",theme:"Theme",themeDescription:"Choose the color theme that fits the way you work.",autoTheme:"Follow system theme automatically",autoThemeDescription:"When enabled, switch between day and night mode based on the system or browser color scheme.",fileManager:"File Manager",workspaceSessionSortMode:"Workspace session sort order",teableEntryTitle:"Teable Forms",teableEntryDescription:"Manage the Teable connection and how CodingNS data syncs into Teable tables.",teableOpenSettingsAction:"Open settings",teableModalTitle:"Teable form settings",teableModalDescription:"Manage the Teable connection, synced tables, and field mappings between CodingNS data and Teable tables.",teableTabConnection:"Connection",teableTabForms:"Forms",teableTabMirrors:"Mirrors",teableTabFieldMappings:"Field mappings",teableTabConnectionSettings:"Connection settings",teableTabFormSettings:"Form settings",teableTabTableSyncSettings:"Table sync settings",teableTabSyncLogs:"Sync logs",teableTestConnectionAction:"Test connection",teableConnectionTestSuccess:"Connection works. Read {tableCount} tables.",teableLoadFailed:"Failed to load Teable settings.",teableStatusUnknown:"Status unavailable",teableStatusIdleHint:"No mirror sync has been triggered yet.",teableStatusBindingLabel:"Connection",teableStatusSourceLabel:"Enabled sources",teableStatusSourceDetail:"{count} source types are currently enabled for Teable sync.",teableStatusMirrorLabel:"Mirror tables",teableStatusMirrorDetail:"{count} mirror table bindings are currently recorded.",teableStatusTaskLabel:"Latest sync",teableBindingSectionTitle:"Connection settings",teableBindingSectionDescription:"Fill in the Teable site, space, base, and access token first, then decide whether to enable sync.",teableEnabledLabel:"Enable Teable sync",teableBaseUrlLabel:"Teable site URL",teableBaseUrlDescription:"Both http:// and https:// are supported. Use a plain http address when Teable is on the same LAN as Host.",teableBaseUrlPlaceholder:"For example: http://192.168.1.20:3000",teableSpaceIdLabel:"Space ID",teableSpaceIdPlaceholder:"Enter the target Space ID",teableBaseIdLabel:"Base ID",teableBaseIdPlaceholder:"Enter the target Base ID",teableAuthRefLabel:"Auth reference",teableAuthRefPlaceholder:"For example: secret://teable/main",teableAuthTokenLabel:"Access token",teableAuthTokenDescription:"Leave this blank if the Host already has a saved token you want to keep using.",teableAuthTokenPlaceholder:"Leave blank to keep the saved token",teableMirrorModeLabel:"Sync mode",teableBindingSaved:"Teable connection settings saved.",teableSyncConfigSectionTitle:"Workbench push scope",teableSyncConfigSectionDescription:"Choose which tags, sessions, and todos are pushed to Teable, and which table each type should use.",teableSyncEnabledLabel:"Allow syncing this source type",teableTargetTableLabel:"Target table",teableTargetTablePlaceholder:"Choose an existing Teable table",teableTagRootsLabel:"Tag trees to sync",teableSessionScopeModeLabel:"Session sync scope",teableSessionScopeAll:"Sync sessions from every workspace",teableSessionScopeSelected:"Sync sessions only from selected workspaces",teableWorkspaceMultiSelectLabel:"Choose workspaces",teableTodoSourceLabel:"Todo sources",teableTodoWorkspaceSource:"Sync workspace todos",teableTodoAffairsSource:"Sync affairs todos",teableTodoWorkspaceHint:"If you choose workspaces here, only todos from those workspaces are included. Leave it empty to avoid extra workspace filtering.",teableTargetTableIdLabel:"Target table ID",teableTargetTableHint:"Leave this blank and Host will create the default mirror table automatically.",teableTargetTableBoundHint:'Currently bound to table "{table}".',teableTargetTableIdPlaceholder:"Optional: reuse an existing table ID",teableScopeJsonLabel:"Sync scope (JSON)",teableScopeJsonPlaceholder:"Enter the sync scope JSON for this source type.",teableScopeJsonInvalid:"The sync scope must be a valid JSON object.",teableSyncConfigSaved:"Teable push scope saved.",teableFormsCatalogTitle:"Existing Teable forms",teableFormsCatalogDescription:"This list shows the form views that already exist in Teable.",teableFormsCatalogEmptyTitle:"No forms are available yet",teableFormsCatalogEmptyDescription:"Create at least one form view in Teable first.",teableFormSettingsLeftTitle:"Legacy form settings",teableFormSettingsLeftDescription:"The settings page no longer configures mirror sync by forms. Mirror sync is configured by Teable tables.",teableFormMappingPanelTitle:"Legacy sync content settings",teableFormMappingPanelDescription:"The settings page no longer configures mirror sync by forms. Mirror sync is configured by Teable tables.",teableAddSyncFormAction:"Add sync form",teableRemoveSyncFormAction:"Remove",teableSyncFormAddedTag:"Added",teableSyncFormAdded:"Sync form added.",teableSyncFormRemoved:"Sync form removed.",teableFormShareReady:"Sharing enabled",teableFormShareMissing:"Sharing disabled",teableSelectSyncFormTitle:"Select a form first",teableSelectSyncFormDescription:"After you select a Teable form on the left, sync content, workspace scope, and field mappings appear here.",teableSelectedFormLabel:"Selected form",teableSyncSourceLabel:"Information to sync",teableSyncSource:{sessions:"Session records",todos:"Todos",tags:"Document library tags"},teableWorkspaceScopeLabel:"Workspace scope",teableWorkspaceScopeAll:"All workspaces",teableWorkspaceScopeSelected:"Selected workspaces",teableWorkspaceScopeEmpty:"No workspace is available yet.",teableDocumentTagRootsLabel:"Document library root tags",teableDocumentTagRootsDescription:"Only the selected root tags and all child tags are synced. This is not a workspace-form binding.",teableDocumentTagRootsEmpty:"No document library root tag is available yet.",teableFieldMappingTitle:"Field mapping",teableFieldMappingInlineDescription:"CodingNS fields are on the left. Choose target fields from the Teable table on the right.",teableSourceFieldsEmpty:"This sync content has no mappable fields.",teableSaveFormSyncSettingsAction:"Save table sync settings",teableFormSyncSettingsSaved:"Table sync settings saved.",teableTableSyncAvailableTitle:"Teable table catalog",teableTableSyncAvailableDescription:"This does not list forms. Choose an existing table from the current Base, then add it to the sync table list on the left.",teableTableSyncListTitle:"Synced tables",teableTableSyncListDescription:"Tables added as mirror sync targets appear here. Select one table, then configure content, scope, and field mappings on the right.",teableTableSyncConfigTitle:"Current table settings",teableTableSyncConfigDescription:"Only the selected table from the left is configured here. The sync table list is not duplicated on this side.",teableTableToAddLabel:"Table to add",teableAllTablesAdded:"All tables have been added",teableAddSyncTableAction:"Add sync table",teableRemoveSyncTableAction:"Remove",teableSyncTableAddedTag:"Added",teableSelectSyncTableTitle:"Add a sync table first",teableSelectSyncTableDescription:"After you add a table from the Teable table catalog on the left, sync content, workspace scope, and field mappings appear here.",teableSelectedSyncTableLabel:"Current sync table",teableTableAssignedDescription:"Configured to sync {source}",teableTableUnassignedDescription:"No sync content configured yet",teableSaveTableSyncSettingsAction:"Save table sync settings",teableTableSyncSettingsSaved:"Table sync settings saved.",teableFieldAutoCreateAction:"Add fields and auto-map",teableFieldAutoCreateModalTitle:"Add Teable fields",teableFieldAutoCreateModalDescription:"Choose CodingNS fields to add to the current Teable table.",teableFieldAutoCreateModalSectionTitle:"Choose fields",teableFieldAutoCreateModalSectionDescription:'These fields will be added to "{table}" and mapped automatically. Existing fields with the same name are reused.',teableFieldAutoCreateConfirmAction:"Add and auto-map",teableFieldAutoCreateSuccess:"Added and mapped {count} fields.",teableFieldAutoCreateEmptyError:"Choose at least one field to add.",teableFieldAlreadyMappedDescription:'Mapped to "{field}".',teableTablesCatalogTitle:"Existing Teable tables",teableTablesCatalogDescription:"This list shows the tables in the current Base so you can choose sync targets and field mappings by table.",teableTablesCatalogEmptyTitle:"No table is available in the current Base",teableTablesCatalogEmptyDescription:"Create a table in Teable first, then come back to configure sync.",teableTableInspectAction:"Inspect table",teableTableCollapseAction:"Collapse details",teableTableFieldsLabel:"Fields in this table",teableTableFieldsEmpty:"This table has no field yet.",teableTableFormViewsLabel:"Form views under this table",teableTableFormViewsEmpty:"This table does not have a form view yet.",teableTableFormReadyTag:"Ready for workbench",teableTableFormShareMissingTag:"Share disabled",teableTableFormCountTag:"{count} forms",teableTableFieldCountPending:"Field count pending",teableTableFieldCountValue:"{count} fields",teableTableFormCountValue:"{count} form views",teableTablesUsageTitle:"What this page is for",teableTablesUsageDescription:"Settings are for sync and field mapping. The Teable block on the workbench is where you choose which form to display.",teableTablesUsageMirrorTitle:"Sync configuration uses tables",teableTablesUsageMirrorDescription:"Tags, sessions, and todos are mapped to Teable tables here.",teableTablesUsageFormTitle:"Workbench blocks use forms",teableTablesUsageFormDescription:"Actual user-facing forms are chosen inside the Teable block on the workbench.",teableSyncActionSectionTitle:"Sync status and actions",teableSyncActionSectionDescription:"Review the latest task result here, or trigger mirror sync manually.",teableLatestTaskTitle:"Latest mirror sync",teableLatestTaskEmpty:"There is no mirror sync record yet.",teableSyncLogsTitle:"Sync logs",teableSyncLogsDescription:"Manual syncs and local-change sync tasks are recorded here so you can confirm whether data has been pushed to Teable.",teableSyncLogsRefreshAction:"Refresh logs",teableSyncLogsEmptyTitle:"No sync log yet",teableSyncLogsEmptyDescription:"Logs will appear here after a manual sync or a local data change triggers sync.",teableSyncLogDescription:"{trigger} · {source} · {time}",teableSyncLogCounts:"Created {created}, updated {updated}, deleted {deleted}, skipped {skipped}",teableSyncLogTrigger:{manual:"Manual",local_change:"Local change",retry:"Retry"},teableFieldMappingSectionTitle:"Field mappings",teableFieldMappingSectionDescription:"Map CodingNS source fields to Teable target fields manually. Sync only writes using the mapping defined here.",teableFieldMappingTargetMissingTitle:"Choose a target table first",teableFieldMappingTargetMissingDescription:"Go to the Mirrors tab, assign a target table for this source type, then come back and map its fields.",teableFieldMappingSaveAction:"Save field mappings",teableFieldMappingSaved:"Field mappings saved.",teableFieldTargetPlaceholder:"Choose a target field",teableFieldRequired:"Required",teableFieldOptional:"Optional",teableMirrorBindingReady:'The mirror table is already bound to "{table}".',teableMirrorBindingMissing:"This source type has not created a mirror table yet.",teableMirrorBindingReadyTag:"Bound",teableMirrorBindingPendingTag:"Pending",teableRefreshAction:"Refresh status",teableSaveBindingAction:"Save connection",teableSaveSyncConfigAction:"Save push scope",teableSyncNowAction:"Sync now",teableBindingStatus:{unbound:"Not bound",ready:"Ready",disabled:"Disabled",config_invalid:"Incomplete"},teableTaskState:{idle:"Not started",queued:"Queued",running:"Running",succeeded:"Succeeded",partial_failed:"Partial failure",failed:"Failed"},teableMirrorMode:{manual:"Manual trigger",scheduled:"Scheduled sync (not available yet)",event_driven:"Auto-sync on local changes"},teableSource:{tags:{title:"Tag mirror",description:"Sync affair tags into a Teable mirror table so business forms can use Link and Lookup.",scopeHint:"Examples include includePaths or manually selected paths. This round only stores the config."},sessions:{title:"Session mirror",description:"Sync lightweight session summaries into Teable so forms can reference recent context.",scopeHint:"Examples include recent and limit. This round only stores the config."},todos:{title:"Todo mirror",description:"Sync workbench todos into Teable so forms can reference current tasks directly.",scopeHint:"Examples include open_only or status filters. This round only stores the config."}},pluginManagement:"Plugin management",pluginManagementDescription:"Review the plugins Host has scanned, then decide whether to enable, disable, or open them.",pluginManagementAction:"Manage plugins",pluginManagementModalTitle:"Plugin management",pluginManagementModalDescription:"See plugin status, permission boundaries, and recent runs here without manually building plugin URLs.",pluginManagementModalListTitle:"Plugin list",pluginManagementModalListDescription:"Select a plugin first, then review its current status and recent runs.",pluginManagementModalDetailTitle:"Plugin details",pluginManagementModalDetailDescription:"Only officially registered Host plugin data and runs are shown here.",pluginManagementSelectPluginTitle:"Select a plugin first",pluginManagementSelectPluginDescription:"After you pick a plugin on the left, its permissions, actions, and recent runs appear here.",pluginManagementWorkspaceRequired:"A current workspace is required before opening a plugin frontend page.",workspaceSessionSortModeDescription:"Controls the default sort order for session lists across the workspace. This setting only applies to the current device.",sessionSortModeCreatedAt:"By session created time",sessionSortModeUpdatedAt:"By session updated time",sessionSortModeTitle:"By session name",showSystemFiles:"Show system files",showSystemFilesDescription:"Display common macOS and Windows system files in the file manager, such as .DS_Store and Thumbs.db. This setting only applies to the current device.",serverConnection:"Server Connection",serverConnectionSectionSummary:"Server address and reconnection behavior",remoteAccess:"Remote Access",remoteAccessSectionSummary:"Connect to this Host from outside through CodingNS Connect or Tailscale.",remoteAccessNavValue:"CodingNS Connect / Tailscale",remoteAccessManageTitle:"Remote Access",remoteAccessManageDescription:"Choose and configure how external devices connect to this Host.",remoteAccessManageAction:"Manage Remote Access",remoteAccessModalTitle:"Access Method Management",remoteAccessModalDescription:"Choose and configure the remote access method you want to use.",remoteAccessTabsLabel:"Remote access method tabs",remoteAccessTunnelTab:"CodingNS Connect",remoteAccessTailscaleTab:"Tailscale Access",remoteAccessFeatureDisabledValue:"Off",abilityManagement:"Capability Management",abilityManagementSectionSummary:"Manage the document library, CLI provider availability, and model profile presets from one place.",abilityManagementNavValue:"Library / Providers / Profiles",affairsLibraryCapabilityTitle:"Document library",affairsLibraryCapabilityDescription:"This switch controls the left document entry and the document or tag indexing services.",affairsLibraryCapabilityToggleLabel:"Enable document library",affairsLibraryCapabilityLoading:"Updating document library status...",affairsLibraryCapabilityEnableSuccess:"Document library enabled.",affairsLibraryCapabilityDisableSuccess:"Document library disabled.",affairsLibraryCapabilityLoadFailed:"Failed to load document library status.",affairsLibraryCapabilitySaveFailed:"Failed to save document library status.",modelManagement:"Model Management",modelManagementNavValue:"Quick switch",modelManagementSectionTitle:"Model Profile Management",providerManagement:"CLI Providers",providerManagementSectionSummary:"Control which CLIs appear in session, fork, assistant, and Skill entry points.",providerManagementNavValue:"Availability",providerManagementDescription:"Control which CLIs this Host is allowed to expose. Open the dialog to review the matrix, status, and enable switches.",providerManagementManageAction:"Manage CLI Providers",providerManagementModalTitle:"CLI Provider Management",providerManagementModalDescription:"Review what each CLI can do in the product, its current state, and whether it stays visible.",providerManagementRefresh:"Refresh list",providerManagementRefreshSuccess:"CLI provider list refreshed.",providerManagementLoading:"Loading available CLI providers...",providerManagementEmpty:"No CLI providers are available to manage yet.",providerManagementEmptyDescription:"This list will appear automatically once the Host reports available CLI providers.",providerManagementLoginRequired:"Sign in before managing CLI providers.",providerManagementLoadFailed:"Failed to load the CLI provider list.",providerManagementSaveFailed:"Failed to save the CLI provider status.",providerManagementSummaryTitle:"Provider Overview",providerManagementSummaryDescription:"Check the totals first, then decide which CLI should stay enabled.",providerManagementSummaryEnabled:"Enabled",providerManagementSummaryDisabled:"Disabled",providerManagementSummaryTotal:"Total",providerManagementMatrixTitle:"Capability Matrix",providerManagementMatrixDescription:"Rows are CLI providers and columns are product capabilities. Turning a provider off hides it across related entry points.",providerManagementTableProvider:"CLI Provider",providerManagementTableStatus:"Status",providerManagementTableEnabled:"Enabled",providerManagementStatusEnabled:"Enabled",providerManagementStatusDisabled:"Disabled",providerManagementInstallReady:"Installed",providerManagementInstallMissing:"Not detected",providerManagementInstallUnknown:"Unknown",providerManagementStateEnabled:"This CLI is currently shown in new session, fork, assistant, and Skill-related entry points.",providerManagementStateDisabled:"This CLI is hidden from new entry points, and its old sessions are also hidden from normal lists.",providerManagementStateMissing:"This CLI is allowed, but the local runtime is not ready yet, so it cannot be used until installation is complete.",providerManagementToggleLabel:"Toggle {provider}",providerManagementEnableSuccess:"{provider} has been enabled again.",providerManagementDisableSuccess:"{provider} has been disabled.",providerManagementCapabilityStreaming:"Streaming output",providerManagementCapabilityToolCalls:"Tool calls",providerManagementCapabilityAssistant:"Assistant service",providerManagementCapabilityFork:"Session fork",providerManagementCapabilitySkill:"Skill usage",providerManagementCapabilityAvailable:"Available",providerManagementCapabilityUnavailable:"Unavailable",providerManagementImpactSessionStart:"new session start",providerManagementImpactFork:"session fork",providerManagementImpactAssistant:"assistant follow-up",providerManagementImpactSkill:"new Skill targets",providerManagementImpactEnabled:"If you turn it off now, old sessions will be hidden and {actions} will be blocked.",providerManagementImpactDisabled:"It is currently blocking {actions}; once re-enabled, those entry points will show up again.",providerManagementImpactEnabledFallback:"If you turn it off now, this CLI will disappear from new entry points across the product.",providerManagementImpactDisabledFallback:"Once re-enabled, this CLI will return to the normal entry points across the product.",channelsManagement:"Messaging Channels",channelsManagementSectionSummary:"Manage external channels, polling accounts, and recent inbound or outbound records in one place.",channelsManagementNavValue:"Accounts / Records",channelsManagementDescription:"Manage channel accounts here and review recent messages and delivery records.",channelsManageAction:"Manage Channel Accounts",channelsModalTitle:"Messaging Channel Accounts",channelsAddAccountAction:"Add Channel Account",channelsModalDescription:"This first phase uses a shared account model. Text messages, fixed provider selection, polling, and Butler control session bridging are the main scope.",channelsActionPending:"Working...",channelsRefresh:"Refresh data",channelsRefreshSuccess:"Channel data refreshed.",channelsLoading:"Loading channel data...",channelsLoadingDetails:"Loading recent threads and messages...",channelsLoadFailed:"Failed to load channel data.",channelsLoadDetailsFailed:"Failed to load recent threads and messages.",channelsSaveFailed:"Failed to save the channel account.",channelsProbeFailed:"Failed to probe the channel account.",channelsPollFailed:"Failed to trigger manual polling.",channelsRemoveFailed:"Failed to remove the channel account.",channelsCreateSuccess:"{account} created.",channelsUpdateSuccess:"{account} saved.",channelsRemoveSuccess:"Removed channel account “{account}”.",channelsSelectAccountFirst:"Select an existing account first, or create a new one.",channelsSummaryTitle:"Channel Overview",channelsSummaryAccounts:"Accounts",channelsSummaryActive:"Healthy",channelsSummaryPlatforms:"Platforms",channelsWizardTitle:"Setup Wizard",channelsWizardCreateDescription:"Choose a channel first, fill that channel's own config form, then bind the account to a fixed assistant engine.",channelsWizardEditDescription:"You are editing an existing account. The platform stays fixed here, and changing the assistant engine only affects new sessions.",channelsWizardStepsTitle:"Channel account setup steps",channelsWizardStepPlatform:"Choose channel",channelsWizardStepConfig:"Channel config",channelsWizardStepBinding:"Bind account",channelsWizardNextToConfig:"Continue to config",channelsWizardNextToBinding:"Continue to binding",channelsWizardBackToPlatform:"Back to channel selection",channelsWizardBackToConfig:"Back to channel config",channelsWizardSelectPlatformHint:"Pick a channel first so the matching platform-specific form can be shown below.",channelsWizardBindingSummary:"Multi-session support",channelsPlatformsTitle:"Platform Catalog",channelsPlatformsDescription:"Channel cards show the phase-one polling model, multi-session support, and the current limits.",channelsPlatformsEmpty:"No platform capabilities are available yet.",channelsPlatformsEmptyDescription:"This list will appear automatically once the Host reports the platform catalog.",channelsPlatformSummary:"Modes: {modes}; multi-session: {multiSession}",channelsAccountsTitle:"Channel Accounts",channelsAccountsDescription:"Each account is fixed to one assistant engine and always uses polling in phase one. New sessions follow the account config, while old sessions keep their original context.",channelsAccountsEmpty:"No channel accounts yet.",channelsAccountsEmptyDescription:"Add one channel account first. Thread mappings and delivery records will appear after real traffic arrives.",channelsAccountRowDescription:"{platform} · {provider} · {mode}",channelsCreateAction:"Create account",channelsSaveAction:"Save account",channelsResetToCreate:"New account form",channelsCreateFormTitle:"Create Channel Account",channelsCreateFormDescription:"Build the shared account fields first. Platform-specific differences stay in the extra JSON config for this phase.",channelsEditFormTitle:"Edit Channel Account",channelsEditFormDescription:"Changing the provider only affects new sessions. Existing sessions keep their original context.",channelsFieldDisplayName:"Account name",channelsFieldDisplayNamePlaceholder:"For example: Feishu Duty Bot",channelsFieldPlatform:"Platform",channelsFieldPlatformDescription:"Choose the platform first, then pick the connection mode and extra config.",channelsFieldProvider:"Assistant engine",channelsFieldProviderDescription:"Phase one only allows Codex or Claude Code, and you cannot switch providers inside the same external thread.",channelsFieldConnectionMode:"Connection mode",channelsFieldConnectionModeDescription:"All six platforms use polling in phase one. You do not switch to another mode here.",channelsFieldStatus:"Account status",channelsFieldStatusDescription:"Use healthy, disabled, or degraded to control whether this account should keep serving traffic.",channelsFieldConfig:"Extra platform config (JSON)",channelsFieldConfigDescription:"Use this only for fields that the dedicated form does not cover yet. The dedicated form stays the primary source.",channelsAdvancedConfigTitle:"Extra fields (advanced)",channelsAdvancedConfigDescription:"Only put fields here when the dedicated form does not cover them yet, such as outbound URLs, temporary switches, or experiment flags.",channelsValidationDisplayName:"Enter an account name first.",channelsValidationPlatform:"Choose a platform first.",channelsValidationConnectionMode:"Choose a connection mode first.",channelsValidationConfigJson:"The extra config is not valid JSON.",channelsValidationConfigObject:"The extra config must be a JSON object.",channelsValidationRequiredField:"Fill in “{field}” first.",channelsValidationFeishuCredential:"Feishu still needs one working credential set: either a Tenant Access Token, or both App ID and App Secret.",channelsConfigWechatUnavailableTitle:"WeChat (claw) does not need manual protocol fields",channelsConfigWechatUnavailableDescription:"QR binding, login state, polling, and outbound delivery are handled by the Host helper, so this step does not require private protocol fields.",channelsDetailTitle:"Selected Account Overview",channelsDetailDescription:"Review the current account state, recent traffic, and whether the account needs manual follow-up.",channelsDetailPlatform:"Platform",channelsDetailProvider:"Assistant engine",channelsDetailConnectionMode:"Connection mode",channelsDetailStatus:"Account status",channelsDetailLastInbound:"Last inbound",channelsDetailLastOutbound:"Last outbound",channelsDetailLastError:"Last error",channelsProbeAction:"Probe account",channelsPollAction:"Run polling",channelsRemoveAction:"Remove account",channelsRemoveConfirmAction:"Confirm removal",channelsRemoveConfirmDescription:"Removing this account also clears its thread mappings, inbound events, and delivery records. This action cannot be undone.",channelsWebhookHint:"This account uses webhook mode, so manual polling is not needed.",channelsConnectionModeFixedHint:"Phase one always models these channels as polling. If a different mode is needed later, the account rules will be upgraded separately.",channelsThreadsTitle:"Thread Mappings",channelsThreadsDescription:"Recent {count} thread mappings between external conversation keys and Butler control sessions.",channelsThreadsEmpty:"No thread mappings yet.",channelsThreadsEmptyDescription:"This list appears automatically after the first external message is received.",channelsEventsTitle:"Inbound Events",channelsEventsDescription:"Recent {count} inbound events so you can verify whether the Host received and dispatched them.",channelsEventsEmpty:"No inbound events yet.",channelsEventsEmptyDescription:"Records will appear here after the channel starts pulling real text messages.",channelsDeliveriesTitle:"Deliveries",channelsDeliveriesDescription:"Recent {count} outbound deliveries so you can confirm whether Butler's first text reached the external platform.",channelsDeliveriesEmpty:"No deliveries yet.",channelsDeliveriesEmptyDescription:"Records will appear here after Butler produces the first outbound text.",channelsConnectionModeWebhook:"Webhook",channelsConnectionModePolling:"Polling",channelsConnectionModeBridge:"Bridge",channelsMultiSessionSupported:"Multi-session ready",channelsMultiSessionLimited:"Limited multi-session",channelsStatusActive:"Healthy",channelsStatusDisabled:"Disabled",channelsStatusDegraded:"Degraded",channelsThreadStatusActive:"Active",channelsThreadStatusClosed:"Closed",channelsThreadStatusFailed:"Failed",channelsEventStatusReceived:"Received",channelsEventStatusDispatched:"Dispatched",channelsEventStatusReplied:"Replied",channelsEventStatusFailed:"Failed",channelsEventStatusIgnored:"Ignored",channelsDeliveryStatusSent:"Sent",channelsDeliveryStatusFailed:"Failed",channelsDeliveryStatusSkipped:"Skipped",channelsThreadSummary:"{status} · conversation key: {conversationKey}",channelsEventSummary:"{status} · conversation key: {conversationKey}",channelsDeliverySummary:"{status} · latest outbound text",channelsMetaCreatedAt:"Created",channelsMetaUpdatedAt:"Updated",channelsMetaReceivedAt:"Received",channelsMetaExternalUser:"External user",channelsMetaEventId:"External event",channelsMetaProviderRef:"Platform ref",channelsMetaError:"Error",channelsTextFallback:"Empty text",channelsTimeUnknown:"Not available",channelsWechatBindingTitle:"WeChat binding",channelsWechatBindingDescription:"This account uses the Host-managed helper for QR login, polling, and outbound delivery.",channelsWechatBoundDescription:"The WeChat account is already bound. You can continue with health checks, manual polling, and later session bridging.",channelsWechatCreateDescription:"Name this WeChat account first. After creation, generate the QR code in the detail panel and finish the bind there.",channelsWechatRuntimeRequiredTitle:"Direct WeChat binding is not available yet",channelsWechatRuntimeRequiredDescription:"The current environment has not enabled the WeChat helper, so this page only shows the account basics. After the helper is enabled, the real QR binding flow appears here.",channelsWechatPendingTitle:"This account is still waiting for binding",channelsWechatPendingDescription:"Finish QR binding first. Polling, outbound delivery, and recent records only appear after the bind succeeds.",channelsWechatBeginBindingAction:"Start binding",channelsWechatContinueBindingAction:"Continue binding",channelsWechatStartLoginAction:"Generate QR code",channelsWechatRestartBindingAction:"Generate a new QR code",channelsWechatRefreshLoginAction:"Refresh binding status",channelsWechatLogoutAction:"Clear binding",channelsWechatBindingModalTitle:"Scan the QR code to bind WeChat",channelsWechatBindingModalDescription:"Scan the QR code below with WeChat, then come back here and click “Refresh binding status”.",channelsWechatBindingModeValue:"QR binding",channelsWechatLoginStatus:"Binding status",channelsWechatLoginStatusNotLoggedIn:"Not bound",channelsWechatLoginStatusWaitingScan:"Waiting for scan",channelsWechatLoginStatusScanConfirmed:"Scanned, waiting confirmation",channelsWechatLoginStatusActive:"Bound",channelsWechatLoginStatusExpired:"QR code expired",channelsWechatQrHint:"After scanning successfully, click “Refresh binding status” to sync the result.",channelsWechatQrAlt:"WeChat claw binding QR code",channelsWechatOpenQrLinkAction:"Open binding QR code",channelsWechatQrRawTitle:"View raw QR content",channelsWechatQrRawDescription:"The raw QR payload returned by the upstream service is kept here first so the scan flow can be debugged.",channelsWechatQrEmpty:"No binding QR code yet",channelsWechatQrEmptyDescription:"Click “Generate QR code” above first, then scan it with WeChat to finish binding.",channelsConfigFieldDingtalkAppKey:"DingTalk AppKey",channelsConfigFieldDingtalkAppKeyDescription:"This identifies the DingTalk app when the real polling API is wired in later.",channelsConfigFieldDingtalkAppKeyPlaceholder:"Enter the DingTalk AppKey",channelsConfigFieldDingtalkAppSecret:"DingTalk AppSecret",channelsConfigFieldDingtalkAppSecretDescription:"Use the production credential for the real duty account so test credentials do not leak into the live polling account.",channelsConfigFieldDingtalkAppSecretPlaceholder:"Enter the DingTalk AppSecret",channelsConfigFieldDingtalkRobotCode:"Robot code",channelsConfigFieldDingtalkRobotCodeDescription:"If replies will eventually be sent through a fixed robot, store the robot code here now.",channelsConfigFieldDingtalkRobotCodePlaceholder:"For example: dingxxxxxxxx",channelsConfigFieldFeishuAppId:"Feishu App ID",channelsConfigFieldFeishuAppIdDescription:"If you do not plan to fill a Tenant Access Token directly, enter this together with the App Secret.",channelsConfigFieldFeishuAppIdPlaceholder:"Enter the Feishu App ID",channelsConfigFieldFeishuAppSecret:"Feishu App Secret",channelsConfigFieldFeishuAppSecretDescription:"If you do not plan to fill a Tenant Access Token directly, enter this together with the App ID.",channelsConfigFieldFeishuAppSecretPlaceholder:"Enter the Feishu App Secret",channelsConfigFieldFeishuTenantAccessToken:"Tenant Access Token",channelsConfigFieldFeishuTenantAccessTokenDescription:"If you can reliably obtain a tenant_access_token, enter it here and you do not need to force App ID plus App Secret as well.",channelsConfigFieldFeishuTenantAccessTokenPlaceholder:"Enter the Feishu tenant_access_token",channelsConfigFieldFeishuChatId:"Target chat ID",channelsConfigFieldFeishuChatIdDescription:"Required. Phase one stays on one fixed chat so the Host knows where to pull messages and send replies.",channelsConfigFieldFeishuChatIdPlaceholder:"For example: oc_xxx or chat_xxx",channelsConfigFieldWechatBaseUrl:"claw service URL",channelsConfigFieldWechatBaseUrlDescription:"Host will use this address to pull messages and send replies. It must be reachable from the Host machine.",channelsConfigFieldWechatBaseUrlPlaceholder:"For example: http://127.0.0.1:8787",channelsConfigFieldWechatBridgeToken:"claw access token",channelsConfigFieldWechatBridgeTokenDescription:"If your claw transport requires an access token, place it here for basic protection.",channelsConfigFieldWechatBridgeTokenPlaceholder:"Enter the claw transport token",channelsConfigFieldWechatPollPath:"Polling path",channelsConfigFieldWechatPollPathDescription:"The default is `/poll`. Override it here if your transport uses another route.",channelsConfigFieldWechatPollPathPlaceholder:"Default: /poll",channelsConfigFieldWechatSendPath:"Send path",channelsConfigFieldWechatSendPathDescription:"The default is `/send`. Override it here if your transport uses another route.",channelsConfigFieldWechatSendPathPlaceholder:"Default: /send",channelsConfigFieldTelegramBotToken:"Telegram Bot Token",channelsConfigFieldTelegramBotTokenDescription:"Telegram polling and outbound replies both require this token. Without it the account cannot work.",channelsConfigFieldTelegramBotTokenPlaceholder:"Enter the Telegram Bot Token",channelsConfigFieldSlackBotToken:"Slack Bot Token",channelsConfigFieldSlackBotTokenDescription:"Required. Slack polling and outbound text replies both depend on this token.",channelsConfigFieldSlackBotTokenPlaceholder:"Enter the Slack Bot Token",channelsConfigFieldSlackAppToken:"Slack App Token",channelsConfigFieldSlackAppTokenDescription:"The minimum working config does not require this. Fill it only when your Slack app setup really needs it.",channelsConfigFieldSlackAppTokenPlaceholder:"Enter the Slack App Token",channelsConfigFieldSlackChannelId:"Channel ID",channelsConfigFieldSlackChannelIdDescription:"Required. Phase one binds the account to one fixed channel so polling and text delivery can work first.",channelsConfigFieldSlackChannelIdPlaceholder:"For example: C0123456789",channelsConfigFieldDiscordBotToken:"Discord Bot Token",channelsConfigFieldDiscordBotTokenDescription:"Required. Discord polling and outbound text replies both depend on this bot token.",channelsConfigFieldDiscordBotTokenPlaceholder:"Enter the Discord Bot Token",channelsConfigFieldDiscordApplicationId:"Application ID",channelsConfigFieldDiscordApplicationIdDescription:"The minimum working config does not require this. Fill it only when your app permissions really depend on it.",channelsConfigFieldDiscordApplicationIdPlaceholder:"Enter the Discord Application ID",channelsConfigFieldDiscordGuildId:"Guild ID",channelsConfigFieldDiscordGuildIdDescription:"Required. Lock the account to one server first. Thread branches will run under this guild.",channelsConfigFieldDiscordGuildIdPlaceholder:"Enter the Discord Guild ID",channelsConfigFieldDiscordChannelId:"Channel ID",channelsConfigFieldDiscordChannelIdDescription:"Required. Lock the account to one channel first. Thread branches will hang under this channel.",channelsConfigFieldDiscordChannelIdPlaceholder:"Enter the Discord Channel ID",channelsConfigChecklistTitle:"Minimum you need for this step",channelsConfigChecklistFeishuSummary:"This Feishu setup stays on fixed-chat polling in phase one, so the Host needs one target chat and one working credential path.",channelsConfigChecklistFeishuItemCredential:"Choose one credential path: either a Tenant Access Token, or both App ID and App Secret.",channelsConfigChecklistFeishuItemChat:"You must enter the target chat ID, otherwise the Host does not know which chat to pull from or reply to.",channelsConfigChecklistFeishuItemScope:"Phase one only handles text messages. Images, files, voice, and cards are not covered yet.",channelsConfigChecklistSlackSummary:"This Slack setup stays on one fixed channel for polling first, so inbound reads and outbound text replies can be verified.",channelsConfigChecklistSlackItemToken:"You must enter the Bot Token. Without it the account cannot read messages or send replies.",channelsConfigChecklistSlackItemChannel:"You must enter the channel ID. This account is fixed to one channel in phase one.",channelsConfigChecklistSlackItemScope:"Phase one only handles text messages, and Slack thread branches are not implemented yet.",channelsConfigChecklistDiscordSummary:"This Discord setup needs one fixed guild and channel first. Later thread branches will live inside that scope.",channelsConfigChecklistDiscordItemToken:"You must enter the Bot Token. Polling reads and outbound text replies both depend on it.",channelsConfigChecklistDiscordItemGuild:"You must enter the Guild ID so the account is fixed to one server first.",channelsConfigChecklistDiscordItemChannel:"You must enter the channel ID. Later thread branches will hang under this channel.",modelManagementTitle:"Quick Model Switching",modelManagementDescription:"This page does not add or edit presets. It only exposes the presets already managed by cc-switch so you can switch quickly.",modelManagementRefresh:"Refresh Models",modelManagementRefreshSuccess:"Model presets refreshed.",modelManagementLoadFailed:"Failed to load model presets.",modelManagementScannedAt:"Last Scanned",modelManagementScannedAtUnknown:"Not scanned yet",modelManagementCurrentProfile:"Current Profile",modelManagementCurrentModel:"Current Model",modelManagementCurrentPreset:"Current Preset",modelManagementModelUnknown:"Unknown",modelManagementPresetMissing:"Not set",modelManagementCurrentTag:"Current",modelManagementOpenSwitcher:"Switch Profile",modelManagementModalTitle:"Provider Profile Switching",modelManagementModalDescription:"Review the existing cc-switch profiles by app and switch the active one here.",modelManagementTabsLabel:"Model app tabs",modelManagementSwitchAction:"Switch",modelManagementSwitchSuccess:"{app} switched to {preset}.",modelManagementOptionsEmpty:"No switchable presets were found.",modelManagementStatusReady:"Ready",modelManagementStatusUnconfigured:"Unconfigured",modelManagementStatusUnavailable:"cc-switch-cli missing",modelManagementStatusError:"Read failed",skills:"Skills",skillsSectionSummary:"Read and sync the local skills owned by each CLI. No marketplace and no remote catalog in this phase.",skillsNavValue:"Local sync",skillManagerTitle:"Local Skill Management",skillManagerDescription:"Read the local skill folders used by Codex, Claude Code, Gemini, and OpenCode, then import unmanaged entries or sync them again.",skillSummaryManagedSkills:"My Skills",skillSummaryManagedEntries:"Active",skillSummaryUnmanagedEntries:"Unmanaged folders",skillSummaryConflictedEntries:"Needs Attention",skillSummaryAssistantRuntimeEntries:"Assistant-only",skillSummaryDiagnostics:"Notices",skillManageAction:"Skill Settings",skillConfigModalTitle:"Skill Settings",skillConfigModalDescription:"Review your skills, built-in assistant skills, and anything that needs your attention.",skillCreateAction:"Add Skill",skillCreateModalTitle:"Add Skill",skillCreateModalDescription:"Bring a new SKILL.md under management. File upload and pasted markdown share the same validation and import flow.",skillCreateSourceTabsLabel:"Add Method",skillCreateSourceFile:"Choose File",skillCreateSourcePaste:"Paste Text",skillCreateSubmitAction:"Add",skillRefresh:"Refresh",skillRefreshSuccess:"Skill list refreshed.",skillScannedAt:"Last Scanned",skillUploadSectionTitle:"Upload Skill",skillUploadSectionDescription:"Choose a SKILL.md file, decide whether it belongs to the workspace or the assistant runtime, then let the app validate, fix, and manage it.",skillUploadPickAction:"Choose SKILL.md",skillUploadSubmitAction:"Upload & Manage",skillUploadEmpty:"No SKILL.md file has been selected yet.",skillUploadPickedFile:"Selected File",skillUploadScopeLabel:"Scope",skillUploadScopeWorkspace:"Workspace Skill",skillUploadScopeAssistant:"Assistant Skill",skillUploadDirectoryLabel:"Directory Name",skillUploadDirectoryPlaceholder:"For example: team-helper",skillUploadDirectoryHint:"Used for the managed folder name and sync target folder. It is generated from the file name or heading by default, so you usually do not need to change it.",skillUploadDirectoryInvalid:"The directory name is invalid. Only letters, numbers, dots, underscores, and dashes are allowed.",skillUploadTargetsLabel:"Target CLI",skillPasteLabel:"Paste SKILL Content",skillPastePlaceholder:"Paste the full SKILL.md content here",skillPasteEmpty:"There is no SKILL content ready to manage yet.",skillUploadDirectoryRequiredNote:"The file name does not produce a valid directory name, so you need to fill one in manually.",skillUploadTargetRequired:"Select at least one target CLI.",skillUploadHeadingNote:"The markdown does not contain a level-one heading. One will be added automatically during import.",skillUploadNormalizedNote:"Whitespace and line endings were normalized for upload.",skillUploadReadFailed:"Failed to read the uploaded SKILL.md file.",skillUploadContentEmpty:"The uploaded SKILL.md file cannot be empty.",skillUploadSuccess:"{name} was added.",skillManagedListTitle:"My Skills",skillManagedEmpty:"You have not added any skills yet.",skillManagedItemDescription:"Added to {targets}.",skillManagedItemNoTarget:"This skill has not been applied to any client yet.",skillUnmanagedListTitle:"Skills to Add",skillUnmanagedEmpty:"There are no new skills to add right now.",skillUnmanagedItemDescription:"Found in {target}. You can add it to your list.",skillUnmanagedItemDisabledDescription:"Found in {target}, but that target is disabled right now, so it cannot be added again yet.",skillAssistantRuntimeListTitle:"Built-in Assistant Skills",skillAssistantRuntimeListDescription:"These skills are provided by the system and only used by the assistant.",skillAssistantRuntimeEmpty:"There are no built-in assistant skills right now.",skillAssistantRuntimeItemDescription:"This is a built-in skill. You do not need to manage it yourself.",skillAssistantRuntimeUsedBy:"Available In",skillAssistantRuntimeSourcePath:"Built-in Source Path",skillConflictedListTitle:"Needs Attention",skillConflictedEmpty:"There is nothing to fix right now.",skillConflictedItemDescription:"This item in {target} needs attention.",skillConflictedItemDisabledDescription:"This item still exists in {target}, but that target is disabled right now.",skillDiagnosticsTitle:"Notices",skillDiagnosticsEmpty:"There are no new notices right now.",skillDiagnosticTargetMissingTitle:"{target} Is Not Ready Yet",skillDiagnosticTargetMissingDetail:"The skill folder for {target} was not found yet.",skillDiagnosticReadFailedTitle:"{target} Is Temporarily Unavailable",skillDiagnosticReadFailedDetail:"The skill information for {target} cannot be read right now. Try again later.",skillDiagnosticSyncMissingTitle:"{target} Needs To Be Applied Again",skillDiagnosticSyncMissingDetail:"Some skills have not taken effect in {target} yet.",skillDiagnosticGenericTitle:"{target} Needs Attention",skillDiagnosticGenericDetail:"Something is not ready yet. Refresh and check again later.",skillDirectoryName:"Directory Name",skillSsotPath:"SSOT Path",skillSourceCli:"Source CLI",skillDirectoryPath:"Directory Path",skillImportAction:"Add",skillImportSuccess:"{name} was added and applied to {target}.",skillSyncAction:"Apply Again",skillSyncSuccess:"{name} was applied again.",skillSyncTargetMissing:"This skill has no target yet, so it cannot be applied again.",skillSyncTargetDisabled:"This skill currently only points at disabled targets. Re-enable a provider before applying it again.",skillLoadFailed:"Failed to load the skill overview.",skillOfficeTemplateCreated:"Document template created.",skillOfficeTemplateUpdated:"Document template updated.",skillOpsTargetCreated:"SSH target created.",skillOpsTargetUpdated:"SSH target updated.",skillOpsApprovalApproved:"Ops approval approved.",skillOpsApprovalRejected:"Ops approval rejected.",skillTargetCodex:"Codex",skillTargetClaudeCode:"Claude Code",skillTargetGemini:"Gemini",skillTargetOpenCode:"OpenCode",skillBindingPending:"Preparing",skillBindingSynced:"Available",skillBindingFailed:"Unavailable",skillBindingConflicted:"Needs Attention",skillUploadTargetDisabled:"All available Skill targets are disabled right now. Re-enable a provider in settings first.",skillTargetDisabledTag:"Disabled",skillTagAssistantOnly:"Assistant Only",skillTagWorkspaceSessionOnly:"Workspace Session Only",securityPrivacy:"Security & Privacy",securityPrivacySectionSummary:"Session permissions, risk boundaries, and default approval policy",softwareUpdate:"Software Update",softwareUpdateSectionSummary:"Server and client versions",updateOneClickValue:"One check",updateOneClickTitle:"Unified updates",updateOneClickDescription:"Check server and desktop versions first, then install available updates in order.",updateOptions:"Update options",releaseChannel:"Update channel",releaseChannelDescription:"Choose whether you receive stable or beta updates",releaseChannelStable:"Stable",releaseChannelBeta:"Beta",betaChannelConsentTitle:"Switch to beta channel",betaChannelConsentDescription:"Beta gets new features earlier, but may be less stable.",betaChannelConsentRisk1:"Beta may include changes that haven't been fully verified",betaChannelConsentRisk2:"You may encounter unknown bugs, compatibility issues, or decreased stability",betaChannelConsentCheckbox:"I understand beta may be unstable, still want to switch",betaChannelConsentConfirm:"Confirm switch",updateInstallAll:"Install all updates",updateCheckFailed:"Update check failed",updateInstallingSequential:"Preparing updates",updateInstallingServerFirst:"Updating the server",updateInstallingClientNext:"Updating the desktop app",updateBothReady:"Server and desktop updates are available",updateServerReadyOnly:"Server update is available",updateClientReadyOnly:"Desktop update is available",updateAllUpToDate:"Everything is up to date",updateCheckIncomplete:"Some update details are unavailable right now. Please try again.",updateServerReadyClientCheckFailed:"Server update is available, but desktop details are unavailable right now.",updateClientReadyServiceCheckFailed:"Desktop update is available, but server details are unavailable right now.",serverAddress:"Server Address",serverDescription:"Login, API requests, and realtime connections all use this Host entry, while the frontend UI is bundled inside the client itself.",serverRelayTunnelProfileTitle:"CodingNS Connect Entry For This Host",serverRelayTunnelProfileDescription:"Attach a CodingNS Connect entry to the saved Host profile. When enabled, the client connects through the CodingNS Connect domain and control site with end-to-end encryption instead of calling this address directly.",serverRelayTunnelEnabled:"Connect Through CodingNS Connect",serverRelayTunnelUsageHint:"The server address should usually stay as this Host's public entry, for example https://demo.codingns.example .",serverRelayTunnelDomain:"CodingNS Connect Domain",serverRelayTunnelDomainPlaceholder:"For example: demo.codingns.example",serverRelayTunnelControlBaseUrl:"Control Site URL",serverRelayTunnelControlBaseUrlPlaceholder:"For example: https://control.codingns.example",relayTunnelServerAddressDescription:"The official CodingNS Connect address is used by default. If you know the current control site address, you can override it in advanced settings.",relayTunnelServerAddressHint:"This only changes the CodingNS Connect control site used for login, binding, and traffic queries. It does not change the current Host's local API address.",relayTunnelStatus:"CodingNS Connect Status",relayTunnelDescription:"Use CodingNS Connect to let external devices reach this Host securely.",relayTunnelMasterSwitchLabel:"Enable CodingNS Connect",relayTunnelActivationHint:"Turn this on before checking CodingNS Connect status or allowing this Host to accept external access.",relayTunnelPhase:"Current State",relayTunnelDomain:"Access Address",relayTunnelUnbound:"Not bound yet",relayTunnelTrafficRemaining:"Remaining Traffic",relayTunnelHostFingerprint:"Host Fingerprint",relayTunnelTrustBoundaryNotice:"CodingNS Connect only forwards encrypted traffic and cannot read the content between the client and this Host.",relayTunnelRecentError:"Recent error: {message}",relayTunnelAccessTitle:"Connection Settings",relayTunnelAccessDescription:"Sign in with your CodingNS Connect account first, then turn the switch on to bring this device online for external access.",relayTunnelLearnService:"Learn About CodingNS Connect",relayTunnelWizardTitle:"Remote Access Wizard",relayTunnelWizardDescription:"Finish account login, host label confirmation, and CodingNS Connect startup in three steps. After that, the panel stays focused on the actual remote access info.",relayTunnelStatusErrorTitle:"Remote access status is unavailable right now",relayTunnelStatusNetworkError:"The client cannot reach this Host right now ({address}), so the remote access status may be outdated. Check the server address, port, and network connection first.",relayTunnelStepPending:"Pending",relayTunnelStepCurrent:"In Progress",relayTunnelStepDone:"Done",relayTunnelStepLocked:"Finish the previous step first.",relayTunnelStepLoginTitle:"Log In",relayTunnelStepLoginDescription:"Connect your CodingNS Connect account first. Host label checks and traffic queries both depend on it.",relayTunnelStepLoginConnected:"The account is already connected. Continue to the next step.",relayTunnelStepHostLabelTitle:"Set Host Label",relayTunnelStepHostLabelDescription:"Choose the fourth-level domain prefix you will use later and verify that it is available now.",relayTunnelStepStartTitle:"Start CodingNS Connect",relayTunnelStepStartDescription:"After the first two steps are ready, bring the current Host online through CodingNS Connect.",relayTunnelStepStartReady:"The host label is confirmed. You can start CodingNS Connect now.",relayTunnelStartAction:"Start CodingNS Connect",relayTunnelLoginErrorTitle:"Failed to log in to CodingNS Connect",relayTunnelAdvancedSettings:"Advanced Settings",relayTunnelAdvancedSettingsHide:"Hide Advanced Settings",relayTunnelAdvancedSettingsDescription:"The official CodingNS Connect address is used by default. Only override it when you know the exact control site address.",relayTunnelLoginNetworkError:"The login request never reached this Host because it is unavailable right now ({address}). Check the server address and network connection, then try again.",relayTunnelReadyTitle:"Remote Access Is Ready",relayTunnelReadyDescription:"The setup is complete. This view now keeps only the access URL, traffic info, and maintenance actions.",relayTunnelAccessUrlLabel:"Remote Access URL",relayTunnelCopyAccessUrl:"Copy URL",relayTunnelOpenAccessUrl:"Open Page",relayTunnelAccessUrlCopied:"The access URL has been copied.",relayTunnelCopyAccessUrlFailed:"Failed to copy the access URL.",relayTunnelOpenAccessUrlFailed:"Failed to open the access URL.",relayTunnelClientRouteLabel:"Current Client Route",relayTunnelClientRouteAddressLabel:"Current Client Address",relayTunnelClientRouteHintRelay:"The client is still using CodingNS Connect for this Host. If a reachable local address is confirmed, it will switch to a lower-traffic direct route automatically.",relayTunnelClientRouteHintRelayProbing:"The client is checking local direct addresses now. When the check finishes, it will switch to the lower-traffic route automatically.",relayTunnelClientRouteHintLan:"The client has already switched to a LAN direct route, which uses less traffic. The remote access URL can still be used on external devices.",relayTunnelClientRouteHintLoopback:"The client is connecting to this device through its local address, without going through CodingNS Connect.",relayTunnelClientRouteHintTailscale:"The client has already switched to a Tailscale address, without going through CodingNS Connect.",relayTunnelClientRouteHintDirect:"The client is requesting this Host address directly, without going through CodingNS Connect.",relayTunnelReconnectAction:"Reconnect",relayTunnelManageAccountAction:"Manage Account",relayTunnelDisconnectDeviceAction:"Sign Out Device",relayTunnelEnableToggleLabel:"Enable CodingNS Connect",relayTunnelConfigTitle:"CodingNS Connect Site Configuration",relayTunnelConfigDescription:"Configure the CodingNS Connect endpoint and control site here. Login, binding, and traffic operations below all use these addresses.",relayTunnelConfigErrorTitle:"Failed to save the CodingNS Connect site address",relayTunnelConfigNetworkError:"The new tunnel site address has not been saved to this Host because it is unavailable right now ({address}). Check the server address and network connection first.",relayTunnelRelayBaseUrl:"CodingNS Connect Endpoint URL",relayTunnelControlBaseUrl:"Control Site URL",relayTunnelSaveConfig:"Save Configuration",relayTunnelRefresh:"Refresh Status",relayTunnelAccountTitle:"CodingNS Connect Account",relayTunnelAccountDescription:"Sign in with your CodingNS Connect account to bind this Host and review the remaining traffic quota.",relayTunnelAccountEmail:"Email",relayTunnelAccountEmailPlaceholder:"Enter your email",relayTunnelAccountPassword:"Password",relayTunnelAccountPasswordPlaceholder:"Enter your password",relayTunnelLoginAccount:"Log In",relayTunnelLoggedInAs:"Logged in as: {email}",relayTunnelConnectedBannerTitle:"Account Connected",relayTunnelConnectedBannerDescription:"You can now turn on CodingNS Connect so external devices can reach this Host.",relayTunnelConnectedBannerActiveTitle:"CodingNS Connect Is On",relayTunnelConnectedBannerActiveDescription:"This device is now reachable from outside through CodingNS Connect.",relayTunnelConnectedDevice:"Current device: {name}",relayTunnelBoundDomain:"Current access address: {domain}",relayTunnelBindTitle:"Bind Current Host",relayTunnelBindDescription:"Binding first reads the current Host long-term public key, then registers this machine on CodingNS Connect.",relayTunnelHostLabelTitle:"Device Name",relayTunnelHostLabelDescription:"After you sign in, enter the fourth-level domain prefix you plan to use later and check whether that name is currently available.",relayTunnelHostLabel:"Host Label",relayTunnelHostLabelPlaceholder:"Enter the prefix",relayTunnelHostLabelSuffix:".channel.codingns.com",relayTunnelHostLabelCheck:"Check Name",relayTunnelHostLabelChecking:"Checking whether this name is available.",relayTunnelHostLabelAvailable:"This name is available. The public access address will be {domain}",relayTunnelHostLabelReserved:"This name hits a reserved prefix. Choose a different name.",relayTunnelHostLabelOccupied:"This name is already taken. Choose a different name.",relayTunnelHostLabelUnavailable:"The name cannot be verified right now. Try again later.",relayTunnelHostLabelRequired:"Enter a device name first.",relayTunnelBindAction:"Login And Bind Host",relayTunnelActionsTitle:"CodingNS Connect Controls",relayTunnelActionsDescription:"After binding, you can enable, disable, or unbind CodingNS Connect here.",relayTunnelEnable:"Enable CodingNS Connect",relayTunnelDisable:"Disable CodingNS Connect",relayTunnelUnbind:"Disconnect This Device",relayTunnelWalletTitle:"Traffic Wallet",relayTunnelWalletDescription:"This shows the total traffic granted, traffic used, and remaining quota recorded by the control site.",relayTunnelTrafficGranted:"Granted Traffic",relayTunnelTrafficUsed:"Used Traffic",relayTunnelPackagesTitle:"Traffic Packages",relayTunnelPackagesDescription:"Selecting a package opens the official checkout page. After payment succeeds, the quota is granted to the current account automatically.",relayTunnelFeaturedPackage:"Featured",relayTunnelBuyPackage:"Buy Traffic",relayTunnelOrdersTitle:"Recent Orders",relayTunnelOrdersDescription:"Only the most recent orders are shown here so you can confirm payment and quota status quickly.",relayTunnelOrderPending:"Pending",relayTunnelOrderPaid:"Paid",relayTunnelOrderExpired:"Expired",relayTunnelOrderFailed:"Failed",relayTunnelControlBaseUrlRequired:"Fill in the control site URL first.",relayTunnelAccountRequired:"Enter the CodingNS Connect account email and password first.",relayTunnelIdentityUnavailable:"The current Host identity key is not ready yet. Try again later.",relayTunnelLoadFailed:"Failed to load the CodingNS Connect status.",relayTunnelPhaseDisabled:"Disabled",relayTunnelPhaseBlockedUninitialized:"Blocked Until Bootstrap Finishes",relayTunnelPhaseUnbound:"Not Bound",relayTunnelPhaseBinding:"Binding",relayTunnelPhaseConnecting:"Connecting",relayTunnelPhaseRunning:"Running",relayTunnelPhaseQuotaExhausted:"Quota Exhausted",relayTunnelPhaseError:"Error",tailscaleBrand:"Tailscale",tailscaleSectionTitle:"Tailscale Access",tailscaleSectionDescription:"Let this Host stay reachable across your devices with Tailscale.",tailscaleMasterSwitchLabel:"Enable Tailscale",tailscaleActivationHint:"Turn this on before checking Tailscale status or continuing with setup and account binding.",tailscaleCurrentState:"Current State",tailscaleSwitchLabel:"Enabled",tailscaleStatusIndicator:"Status",tailscaleServerAddress:"Server Address",tailscaleAccountName:"Account",tailscaleIpAddress:"IP Address",tailscaleConfigure:"Configure",tailscaleConfigModalTitle:"Configure Tailscale",tailscaleConfigModalDescription:"Edit connectivity settings",tailscaleControlServer:"Control Server",tailscaleControlServerDescription:"Leave empty to use the default control server.",tailscaleControlServerPlaceholder:"Leave empty to use the default control server",tailscaleHostname:"Hostname",tailscaleHostnameDescription:"Optional.",tailscaleHostnamePlaceholder:"For example: codingns-host",tailscaleReachableBaseUrl:"Reachable Base URL",tailscaleTailnetFqdn:"Tailnet FQDN",tailscaleTailnetIpv4:"Tailnet IPv4",tailscaleTailnetIpv6:"Tailnet IPv6",tailscaleDetailAddresses:"Detailed Addresses",tailscaleRefresh:"Refresh",tailscaleInstallAction:"Install Tailscale",tailscaleInstallOpenFailed:"Failed to open the Tailscale install page.",tailscaleEnable:"Enable Tailscale",tailscaleDisable:"Disable Tailscale",tailscaleLogin:"Bind Account",tailscaleLogout:"Unbind Account",tailscaleUnavailable:"Unavailable",tailscaleLoadFailed:"Failed to load Tailscale status.",tailscalePhaseDisabled:"Disabled",tailscalePhaseBlockedUninitialized:"Blocked until bootstrap finishes",tailscalePhaseStarting:"Starting",tailscalePhaseNeedsLogin:"Waiting for login",tailscalePhaseRunning:"Running",tailscalePhaseStopping:"Stopping",tailscalePhaseError:"Error",tailscaleOverviewDisabled:"Remote access is not enabled yet.",tailscaleOverviewBlockedUninitialized:"Finish bootstrap before enabling remote access.",tailscaleOverviewStarting:"Connecting to Tailscale. Please wait.",tailscaleOverviewNeedsLogin:"Tailscale is enabled, but account binding is still required.",tailscaleOverviewRunning:"This instance is reachable through Tailscale now.",tailscaleOverviewStopping:"Remote access is being turned off.",tailscaleOverviewError:"Remote access hit an error. Refresh or reconfigure it first.",autoReconnect:"Auto Reconnect",autoReconnectDescription:"Retry HTTP and WebSocket links automatically when Host is briefly unavailable.",autoCheckUpdate:"Auto check updates",autoCheckUpdateDescription:"Notify you when a new client version is found.",autoDownloadUpdate:"Download updates before prompting",autoDownloadUpdateDescription:"Download the client package first, then prompt you to install it.",defaultPermissionMode:"Default Session Permissions",defaultPermissionModeDescription:"Controls the default tool permissions for new and resumed sessions. Full access disables approval prompts and should only be used for trusted projects and environments.",authDeviceManagement:"Login Devices",authDeviceManagementDescription:"View the current device, other active devices, and the latest 10 login records, and sign out specific active devices one by one from a primary device.",authDeviceEntryHint:"Open device management to view the current device, other active devices, and recent login records in a dialog.",authDeviceOpenManager:"Manage Devices",authDeviceCurrentTitle:"Current Device",authDeviceOthersTitle:"Other Active Devices",authDeviceRecentTitle:"Recent Login Records",authDeviceCurrentTag:"Current",authDevicePrimaryTag:"Primary",authDeviceLegacyTag:"Legacy",authDeviceLegacyHiddenHint:"Detected {count} compatibility records from legacy sessions. They are hidden by default.",authDeviceLegacyReveal:"Show Compatibility Records",authDeviceLegacyHide:"Hide Compatibility Records",authDeviceLegacyDevicesTitle:"Legacy Active Records",authDeviceLegacyRecentTitle:"Legacy Login Records",authDeviceLegacyLabel:"Unknown Device (Legacy Session)",authDeviceClientDesktop:"Desktop",authDeviceClientWeb:"Web",authDeviceClientIos:"iOS",authDeviceClientAndroid:"Android",authDeviceClientUnknown:"Unknown Device",authDeviceCurrentEmpty:"The current session does not have identifiable device metadata yet. Please sign in again.",authDeviceOthersEmpty:"There are no other active devices.",authDeviceRecentEmpty:"There are no recent login records yet.",authDeviceBrowserValue:"Browser: {value}",authDeviceOsValue:"OS: {value}",authDeviceLastSeen:"Last seen: {value}",authDeviceLoginAt:"Login time: {value}",authDeviceSourceAddressValue:"Source address: {value}",authDeviceSourceAddressUnknown:"Source address: unknown",authDeviceEnablePrimary:"Set as Primary",authDeviceDisablePrimary:"Remove Primary",authDevicePrimaryUnavailable:"The current session does not have a stable device identity yet, so it cannot become a primary device.",authDeviceLogoutOthers:"Sign Out Other Devices",authDeviceLogoutDevice:"Sign Out Device",authDevicePrimaryEnabled:"The current device is now a primary device.",authDevicePrimaryDisabled:"The current device is no longer a primary device.",authDeviceLogoutOthersSuccess:"Signed out other devices. Processed {count}.",authDeviceLogoutDeviceSuccess:'Signed out device "{device}". Processed {count} session(s).',authDeviceLoadFailed:"Failed to load login device information.",authDeviceEnablePrimaryModalTitle:"Set as Primary Device",authDeviceEnablePrimaryModalDescription:"Enter the admin password to confirm that the current device should become a primary device.",authDeviceDisablePrimaryModalTitle:"Remove Primary Device",authDeviceDisablePrimaryModalDescription:"Enter the admin password to confirm that the current device should no longer be a primary device.",authDevicePasswordLabel:"Admin password",userManagementEntryTitle:"User Management",userManagementEntryDescription:"Manage who can sign in to this Host and review each user's sessions and model usage.",userManagementOpenAction:"Manage Users",userManagementTitle:"User Management",userManagementDescription:"Manage login users here. Users with business data cannot be deleted directly, so workspaces and sessions are not removed by mistake.",userManagementTabsLabel:"User management tabs",userManagementUsersTab:"User List",userManagementUsageTab:"Usage Details",userManagementUsersTitle:"User List",userManagementUsersDescription:"Add, edit, enable, or disable login users. Delete is only available for new users without data.",userManagementAddUser:"Add User",userManagementEditUser:"Edit",userManagementDeleteUser:"Delete",userManagementEnableUser:"Enable",userManagementDisableUser:"Disable",userManagementStatusActive:"Enabled",userManagementStatusDisabled:"Disabled",userManagementUserMeta:"Created: {createdAt}",userManagementLoading:"Loading users.",userManagementUsersEmptyTitle:"No users yet",userManagementUsersEmptyDescription:"After adding a user, login accounts will appear here.",userManagementAddDescription:"Enter a username and password. The new user can sign in immediately.",userManagementEditDescription:"Change the username. Leave password empty to keep the current password.",userManagementUsernameLabel:"Username",userManagementPasswordLabel:"Password",userManagementPasswordEditHint:"Leave empty if you do not need to change the password.",userManagementDeleteConfirmTitle:"Delete User",userManagementDeleteConfirmDescription:'Delete "{username}"? If this user already has data, the system will block deletion.',userManagementCreateSuccess:"User added.",userManagementUpdateSuccess:"User updated.",userManagementDeleteSuccess:"User deleted.",userManagementEnableSuccess:"User enabled.",userManagementDisableSuccess:"User disabled.",userManagementLoadFailed:"Failed to load users.",userManagementSaveFailed:"Failed to save user.",userManagementDeleteFailed:"Failed to delete user.",userManagementStatusFailed:"Failed to update user status.",userManagementUsageTitle:"Usage Details",userManagementUsageDescription:"Review sessions, models, CLI providers, and model providers by user.",userManagementUsageLoading:"Loading usage details.",userManagementUsageLoadFailed:"Failed to load usage details.",userManagementUsageEmptyTitle:"No usage yet",userManagementUsageEmptyDescription:"Usage appears here after users create sessions.",userManagementPeriodLabel:"Period",userManagementPeriodDay:"By Day",userManagementPeriodWeek:"By Week",userManagementPeriodMonth:"By Month",userManagementSessionCount:"{count} sessions",userManagementMetricSessions:"Sessions",userManagementMetricTotalTokens:"Total Tokens",userManagementMetricInputTokens:"Input Tokens",userManagementMetricOutputTokens:"Output Tokens",userManagementTokenUnavailable:"This Host does not persist model token usage yet, so token charts show 0. Session, model, and provider counts come from real session records.",userManagementTokenChartTitle:"Model Token Usage",userManagementTokenChartEmptyTitle:"No token records",userManagementTokenChartEmptyDescription:"After token usage is written to session records, trends will appear here.",userManagementModelUsage:"Model Usage",userManagementCliProviderUsage:"CLI Provider Usage",userManagementModelProviderUsage:"Model Provider Usage",userManagementUsageGroupEmpty:"No records",permissionModeDefault:"Follow CLI defaults",permissionModeAcceptEdits:"Allow workspace edits without asking",permissionModeBypassPermissions:"Full access without asking",enabled:"Enabled",disabled:"Disabled",serverUpdate:"Server Update",serverUpdateDescription:"",clientUpdate:"Client Update",clientUpdateDescription:"",serverCurrentVersion:"Server Current Version",serverTargetVersion:"Server Target Version",serverPackageName:"npm Package",serverUpdateCommand:"Upgrade Command",serverCheckNow:"Check Server",serverOpenPage:"Open npm",serverLatestUnknown:"Unavailable",serverUpdateReady:"New version found",serverUpToDate:"Up to date",serverCheckFailed:"Check failed",serverInstallWarning:"Installing the update will restart the CodingNS service through PM2 and briefly interrupt the connection.",serverInstallConfirmTitle:"Install Server Update",serverInstallConfirmDescription:"Continuing will install the new version first, then let PM2 restart the current CodingNS service automatically.",serverInstallConfirmAction:"Install And Restart",serverRestarting:"Update installed. Restarting the CodingNS service",serverProgressLabel:"Server update progress",serverProgressPreparing:"Preparing server update",serverProgressQueued:"Queued",serverProgressInstalling:"Updating the server",serverProgressRestarting:"Restarting service",serverProgressHint:"Server updates can take a few minutes. Keep the app open.",serverProgressCurrentStage:"Current stage: {stage}",serverOpenPageFailed:"Failed to open page",updateCheckAll:"Check updates",updateChecking:"Checking",releaseCurrentVersion:"Current Version",releaseTargetVersion:"Target Version",releaseTargetTag:"Target Tag",releasePublishedAt:"Published At",releaseUnknownVersion:"Unknown",releaseNotes:"What's New",releaseNotesEmpty:"No release notes for this version",releaseNotesView:"View release notes",releaseNotesPublishedAt:"Published at",releaseCheckNow:"Check Client",releaseInstallNow:"Install",releaseDownloading:"Downloading desktop update",releaseDownloadedReady:"Desktop update is ready to install.",releaseDownloadedReadyWithProgress:"Desktop update is ready to install ({percent}%).",releaseDownloadFailed:"Download failed",releaseInstallReadyDialogTitle:"Update package downloaded",releaseInstallReadyDialogDescription:"Version {version} is ready to install.",releaseInstallReadyWarning:"Restart the app after installation.",releaseInstallReadyConfirm:"Install and restart",releaseDownloadedNotificationTitle:"Client update downloaded",releaseDownloadedNotificationBody:"Version {version} is ready. Open Settings to install it.",releaseOpenPage:"Open Release",releaseRollback:"Rollback",releaseUpdateBadge:"Update",releaseUpdateReady:"New version found",releaseUpToDate:"Up to date",releaseCheckFailed:"Check failed",releaseInstallerMissing:"A new version is available, but this release does not include a supported installer yet.",releaseSignatureMissing:"A new version is available, but this release does not provide checksum information yet.",releaseInstallStarted:"Install started",releaseInstallFailed:"Install failed",releaseRestartRequired:"Update installed. Restart the app to apply it.",releaseRestartDialogTitle:"Install completed",releaseRestartDialogDescription:"Version {version} has been installed. Restart the app to finish switching to the new build.",releaseRestartLater:"Later",releaseRestartConfirm:"Yes, restart now",releaseRestartFailed:"Failed to restart the app",releasePageOpenFailed:"Failed to open page",androidInstallerStarted:"Handed off to the Android installer. You can still cancel there.",androidInstallPermissionRequired:"Allow installs from this source before retrying.",androidInstallCancelled:"Install was cancelled or not completed. You can try again.",androidInstallSucceeded:"The new version has been detected as installed.",releaseRollbackStarted:"Rollback started",releaseRollbackFailed:"Rollback failed",clientUpdateUnsupported:"Install updates are not supported here",logout:"Log out"},home:{title:"Continue from a session, not from a backend table",subtitle:"Pick a workspace and session here first. The real work starts in the next step.",terminalsEntry:"Open Terminal",workspaceSection:"Workspaces",sessionSection:"Recent Sessions",emptyWorkspaces:"No workspace has been imported yet. Import one on the Host side first, and the entry will appear here.",emptySessions:"There is no session to continue in the current workspace yet.",noActivity:"No activity yet"},shell:{hostSwitcherTitle:"Switch HOST",hostSwitcherAriaLabel:"Switch HOST",hostSwitcherSavedSection:"Saved manually",hostSwitcherDiscoveredSection:"Discovered",hostSwitcherCurrentBadge:"Current",hostSwitcherDiscoveredBadge:"Found",hostSwitcherPeerBadge:"Peer",hostSwitcherSwitching:"Switching",hostSwitcherDetailAction:"Details",hostSwitcherDetailAriaLabel:"{name} details",hostSwitcherAddAction:"Add HOST",hostSwitcherAddDirectHostAction:"Add Direct HOST",hostSwitcherAddPeerHostAction:"Add Peer Host",hostSwitcherNameLabel:"HOST name",hostSwitcherNamePlaceholder:"For example: Office HOST",hostSwitcherUrlLabel:"HOST address",hostSwitcherUrlPlaceholder:"For example: http://10.10.1.8:3002",hostSwitcherSaveAction:"Save HOST",hostSwitcherDetailTitle:"HOST details",hostSwitcherPrimaryHostTitle:"Primary HOST",hostSwitcherDirectSectionTitle:"Direct HOST",hostSwitcherDetailStatusLabel:"Connection",hostSwitcherDetailStatusDirect:"Direct",hostSwitcherDetailStatusRelay:"Relay",hostSwitcherDetailRouteLabel:"Route",hostSwitcherDetailAddressLabel:"Address",hostSwitcherDetailLatencyLabel:"Latency",hostSwitcherDetailTrafficLabel:"Traffic",hostSwitcherDetailResourceTitle:"Resource usage",hostSwitcherDetailLatencyLoading:"Checking",hostSwitcherDetailUnavailable:"Unavailable",hostSwitcherDetailCpuLabel:"CPU",hostSwitcherDetailCpuValue:"{usage} · {cores} cores",hostSwitcherDetailMemoryLabel:"Memory",hostSwitcherDetailDiskLabel:"Disk",hostSwitcherAliasLabel:"HOST alias",hostSwitcherAliasPlaceholder:"4 English letters",hostSwitcherAliasRule:"Aliases can only use English letters, up to 4.",hostSwitcherAliasInvalid:"Aliases can only use English letters, up to 4.",hostSwitcherAliasSaveAction:"Save alias",hostSwitcherAliasSaveSuccess:"HOST alias saved.",hostSwitcherPeerTitle:"Use as Peer HOST",hostSwitcherPeerSectionTitle:"Peer HOST",hostSwitcherPeerDescription:"Before enabling, the primary HOST checks network reachability, version compatibility, and sign-in. Only then can workspaces use this HOST through the primary HOST.",hostSwitcherPeerReconnectDescription:"This Peer HOST is already connected. You can reconnect manually to re-check the target HOST and restore proxy access with the saved sign-in state.",hostSwitcherPeerStatusLabel:"Peer status",hostSwitcherPeerFailureReasonLabel:"Failure reason",hostSwitcherPeerEnableAction:"Enable Peer",hostSwitcherPeerReconnectAction:"Reconnect",hostSwitcherPeerDisableAction:"Disable Peer",hostSwitcherPeerChecking:"Checking",hostSwitcherPeerPasswordOneTimeHint:"The target HOST password is only used for this enable check and is not saved to the primary HOST.",hostSwitcherPeerLoginRequired:"Enter the target HOST username and password first.",hostSwitcherPeerEnableSuccess:"Peer HOST enabled.",hostSwitcherPeerReconnectSuccess:"Peer HOST reconnected.",hostSwitcherPeerEnableFailed:"Failed to enable Peer HOST.",hostSwitcherPeerReconnectFailed:"Failed to reconnect Peer HOST.",hostSwitcherPeerDisableSuccess:"Peer HOST disabled.",hostSwitcherPeerDisableFailed:"Failed to disable Peer HOST.",hostAddInvalidUrl:"HOST address is invalid.",hostAddDuplicate:"This HOST is already saved.",hostAddIncompleteCredentials:"Username and password must be entered together.",hostAddSuccess:"{name} saved.",hostAddFailed:"Failed to save HOST.",hostDeleteAction:"Delete HOST",hostDeleteAriaLabel:"Delete HOST {name}",hostDeleteConfirmAction:"Confirm delete",hostDeleteBusy:"Deleting",hostDeleteSuccess:"{name} deleted.",hostDeleteFailed:"Failed to delete {name}.",hostSwitchFailed:"Failed to switch HOST.",hostSwitchMissing:"This HOST cannot be found.",hostSwitchUnreachable:"{name} is unreachable.",hostDiscoveryRefreshing:"Looking for LAN HOSTs…",hostDiscoveryFailed:"Failed to discover LAN HOSTs.",manageWorkspaceHostLabel:"HOST used",manageWorkspaceHostSelectLabel:"Choose the HOST for this project",manageWorkspaceHostCurrentOption:"Primary HOST · {alias}",manageWorkspaceHostPeerOption:"Peer HOST · {alias}",manageWorkspaceHostHint:"This project will open through {hostName}.",manageWorkspaceHiddenSectionTitle:"Hidden Projects",manageWorkspaceRemotePathTitle:"Choose the project folder on Peer HOST",manageWorkspaceRemotePathDescription:"No project named “{name}” was found on the Peer HOST. Choose the matching folder on that HOST; it will be registered before switching.",manageWorkspaceRemotePathSubmit:"Use this folder",hostSwitcherPeerWorkspaceDescription:"From {hostName} · {path}",hostSwitcherPeerWorkspaceUnavailableDescription:"{hostName} is unavailable, so this workspace cannot be opened yet.",hostSwitcherPeerUnavailableBadge:"Unavailable",hostSwitcherPeerUnavailable:"{hostName} is unavailable right now.",hostSwitcherPeerVersionMismatchBadge:"Version mismatch",hostSwitcherPeerVersionMismatch:"{hostName} is on a different version and cannot be opened yet.",hostSwitcherPeerUnauthorizedBadge:"Sign-in required",hostSwitcherPeerUnauthorized:"{hostName} needs sign-in before you can open it.",hostSwitcherPeerWorkspaceRouteUnsupported:"This workspace cannot be opened yet.",hostSwitcherPeerWorkspaceRouteUnsupportedDescription:"{hostName}'s workspace is listed now. It will open from here after the proxy API is connected."},terminal:{title:"Terminal",heroTitle:"Keep the real PTY on Host, keep the control surface in the workspace",heroSubtitle:"This page does not fake output and does not mix terminal with process management. It only consumes the real terminal stream managed by Host.",workspaceSection:"Workspace & Terminal",workspaceField:"Current Workspace",shellField:"Shell for New Terminal",runtimeField:"Runtime",runtimeAutoOption:"Auto",runtimeAutoShortLabel:"auto",runtimeAutoDescription:"Use the Host default policy for this terminal runtime.",runtimePersistentLabel:"Persistent Session",runtimePersistentShortLabel:"persist",runtimeTmuxDescription:"Use a persistent external session, ideal for development terminals that should stay alive.",runtimeWindowsPersistentDescription:"Use a Windows persistent session backed by ConPTY so the shell can survive Host restarts.",runtimeEmbeddedDescription:"Managed directly by the current Host and useful as the lightweight fallback.",runtimeConptyPowerShellLabel:"PowerShell Persistent",runtimeConptyCmdLabel:"CMD Persistent",runtimeConptyGitBashLabel:"Git Bash Persistent",runtimeMissingDialogTitle:"tmux is not installed on this system",runtimeMissingDialogDescription:"The tmux runtime cannot create a persistent terminal right now. Install tmux first, or temporarily switch to embedded-pty to continue.",runtimeMissingInstallDescription:"Installing tmux is recommended if you want terminals to survive Host restarts.",runtimeMissingInstallMacArm:"macOS (Apple Silicon / Homebrew): arch -arm64 brew install tmux",runtimeMissingInstallMacIntel:"macOS (Intel Mac / Homebrew): brew install tmux",runtimeMissingInstallDebian:"Ubuntu / Debian: sudo apt install tmux",runtimeMissingInstallFedora:"Fedora: sudo dnf install tmux",runtimeMissingFallbackDescription:"If you switch to embedded-pty now, the terminal can still start, but it will not stay as an external persistent session.",runtimeMissingKeepAction:"Not now",runtimeMissingFallbackAction:"Switch to embedded-pty",runtimeMissingFallbackPending:"Switching...",shellUnavailable:"Unavailable",workspaceLoadFailed:"The workspace or terminal list is not available right now.",terminalSection:"Terminal Instances",templateSection:"Command Templates",stageEmptyTitle:"No terminal selected yet",stageEmptySubtitle:"Create a terminal first, or run a command template.",emptyTerminals:"There is no terminal instance in the current workspace yet.",emptyTemplates:"There is no command template in the current workspace yet.",createButton:"Create Terminal",creating:"Creating terminal...",creationPendingDescription:"Host is starting the real PTY. This pane will take over as soon as the stream is ready.",defaultTerminalName:"Workspace Terminal",created:"The terminal has been created and connected to Host.",createFailed:"Failed to create terminal.",closeButton:"Close Terminal",closing:"Closing terminal...",closed:"The terminal close request has been submitted.",closeCompleted:"Terminal closed.",closePendingDescription:"The close request has been sent to Host. The page stays responsive and keeps syncing the final result in the background.",closeSyncDelayed:"Host is still finishing the close in the background. The list will keep syncing on the next refresh.",closeFailed:"Failed to close terminal.",inputLabel:"Send command to current terminal",inputPlaceholder:"For example: npm test",sendButton:"Send to Terminal",inputFailed:"Failed to send terminal input.",outputEmpty:"The terminal is connected, but there is no output yet.",outputTruncated:"Some output exceeded the cache window while disconnected. Only the retained part has been restored.",connectedHint:"Current output is coming from the real PTY stream on Host.",moreActions:"Terminal Actions",duplicateAction:"Duplicate Tab",duplicateSuccess:"A new terminal tab has been created with the same setup.",duplicateFailed:"Failed to duplicate the terminal tab.",disconnectAction:"Disconnect",disconnected:"Terminal connection has been disconnected.",reconnectAction:"Reconnect",reconnectRequested:"Reconnect request sent.",deleteAction:"Delete",deleting:"Deleting terminal...",deleted:"Terminal record deleted.",deletePendingDescription:"The delete request has been sent to Host. The page stays responsive and keeps syncing the list in the background.",deleteSyncDelayed:"Host is still finishing the delete in the background. The list will keep syncing on the next refresh.",deleteFailed:"Failed to delete the terminal record.",closePendingBadge:"Closing",deletePendingBadge:"Deleting",pinAction:"Pin",unpinAction:"Unpin",zoomLabel:"Terminal Zoom",zoomInAction:"Zoom in terminal display",zoomOutAction:"Zoom out terminal display",zoomResetAction:"Reset terminal zoom",openExternalAction:"Open in Separate Window",openExternalFailed:"Failed to open the detached terminal window.",toolbarToggleAction:"Open terminal tools menu",mobileSwipeHint:"Swipe left or right to switch terminals",mobileSwipePosition:"{current} / {total}",mobileDrawerAction:"Open quick terminal list",mobileDrawerTitle:"Quick Terminals",mobileDrawerDescription:"Swipe right to reveal the list, then tap to jump to another terminal.",mobilePinnedSectionTitle:"Pinned Terminals",mobileDrawerEmptyTitle:"No terminals yet",mobileDrawerEmptyDescription:"Create one first and the quick switcher will appear here.",mobileCreateSheetTitle:"Create Terminal",mobileCreateShellLabel:"Terminal Type",mobileCreateShellDescription:"Pick the shell for this terminal instead of squeezing desktop dropdowns onto mobile.",mobileCreateRuntimeLabel:"Session Type",mobileCreateRuntimeDescription:"Choose whether this terminal should stay persistent or only live in the current runtime.",mobileCreateLoadingShells:"Loading available terminal types for this system...",mobileCreateConfirm:"Create this terminal",createDialogTitle:"Create Terminal",createDialogShellDescription:"Choose the shell for this terminal before creation. On Windows we should not silently fall back to CMD anymore.",createDialogRuntimeDescription:"Choose whether this terminal should stay persistent or only live in the current runtime.",createDialogConfirm:"Create Terminal",mobileRuntimePersistentTitle:"Persistent Session",mobileRuntimePersistentDescription:"Best for development terminals that should stay alive and reconnect as a recoverable session.",mobileRuntimeSessionTitle:"runtime (current session)",mobileRuntimeSessionDescription:"Managed directly by the current Host. Lighter, but not an external persistent session.",mobileWorkspaceSwitcherPlaceholder:"Choose Workspace",mobileEmptyTitle:"No terminal content yet",mobileEmptyDescription:"Create a terminal first, or swipe right to open the quick list and switch to an existing one.",layoutLabel:"Layout",layoutSingleAction:"Single pane",layoutVerticalAction:"Split left and right",layoutHorizontalAction:"Split top and bottom",saveLogAction:"Save Log",saveLogSuccess:"The terminal log has been saved.",saveLogFailed:"Failed to save the terminal log.",logEmpty:"There is no terminal log to save yet.",bindToPaneAction:"Bind to current pane",bindToPrimaryPaneAction:"Bind to main pane",bindToSecondaryPaneAction:"Bind to side pane",panePrimary:"Main Pane",paneSecondary:"Side Pane",splitEmptySubtitle:"Pick a tab or create a terminal first, then bind it to this pane.",statusBadge:{creating:"starting",running:"running",closed:"closed",error:"error"},recoveryComplete:"Recovered to the terminal from before refresh. Key cached output has been restored.",recoveryTruncated:"Recovered to the previous terminal, but some disconnected output exceeded the cache window.",recoveryIdleClosed:"The previous terminal was auto-closed by Host after being idle too long. You are seeing the output kept before close.",reconnect:"Reconnect",liveConnected:"Live stream connected",templateName:"Template Name",templateCommand:"Main Command",templateArgs:"Arguments (space separated)",templateCreateButton:"Save Template",templateCreated:"The command template has been saved.",templateCreateFailed:"Failed to save the command template.",templateRunSent:"The command template has been sent to the current terminal.",templateRunCreatedTerminal:"The command template started in a new terminal.",templateRunFailed:"Failed to run the command template.",connection:{connected:"Connected",reconnecting:"Reconnecting",reconnect_failed:"Reconnect failed",closed:"Closed"}},conversation:{titleFallback:"Continue Conversation",historyLoading:"Loading message history from Host...",historyLoadingOlder:"Loading older messages...",historyLoadFailed:"Message history is not available right now. Try again later.",timelineEmpty:"There are no messages in this session yet. Your first message will go straight into the Host chain.",turnAbortedUser:"The previous turn was stopped by you.",turnAbortedUnexpected:"The previous turn was interrupted unexpectedly and did not finish cleanly.",turnAbortedGeneric:"The previous turn was interrupted before it finished cleanly.",scrollToBottomAction:"Jump to bottom",rawRefLabel:"Source",copyAction:"Copy",copyContentSuccess:"Content copied.",copyContentFailed:"Failed to copy the content.",selectionTodoAction:"Todo",selectionActionButton:"Action",selectionActionSubmit:"Open action child session",selectionActionPromptLabel:"What should it do",selectionActionPromptPlaceholder:"For example: explain this, turn it into notes, or send it to a specific API",selectionActionIncludeContext:"Include current context",selectionActionContextUnavailable:"This selection spans multiple messages, so context inheritance is disabled for safety.",selectionActionDefaultPrompt:"Please process this content.",selectionActionQuotedLabel:"Selected text",selectionActionFailed:"Failed to create the action child session.",actionSessionBadge:"Action",actionInheritedSelectionSummary:'Collapsed the selected text from "{parentTitle}" by default.',forkFromHereAction:"Fork from here",forkingAction:"Forking...",forkMessageSucceeded:"Created a new branch from this message.",forkMessageFailed:"Failed to fork from this message.",forkDraftLabel:"Fork Quote",forkDraftEmpty:"This message does not contain text to quote.",forkDraftClear:"Cancel this fork quote",forkTargetProviderLabel:"Target CLI",forkTargetModelLabel:"Target Model",forkTargetSummary:"Source CLI: {sourceProvider} · Target CLI: {targetProvider}",forkInlineModelLoading:"Loading model options...",forkInlineNativeHint:"Stay on the same CLI and use native fork.",forkInlineCrossHint:"Switched to another CLI. The child session will be reconstructed from text history.",forkSwitchConfirmTitle:"Switch to another CLI?",forkSwitchConfirmDescription:"Using the same CLI keeps the native fork experience. Switching CLI changes this into a cross-provider fork.",forkSwitchConfirmKeepTitle:"Will keep",forkSwitchConfirmKeepBody:"User messages and assistant text before the fork point.",forkSwitchConfirmConvertTitle:"Will convert",forkSwitchConfirmConvertBody:"Reusable text history will be rebuilt into the new CLI session.",forkSwitchConfirmDropTitle:"Will lose",forkSwitchConfirmDropBody:"Tool calls, permission prompts, attachments, and running state.",forkSwitchConfirmAction:"Confirm switch",forkSwitchKeepNative:"Keep native",forkProviderNativeUnsupported:"This provider does not support native fork yet",forkProviderReconstructedUnsupported:"This provider cannot be used as a cross-provider fork target yet",loadMore:"Load More",composerPlaceholder:"State the next step clearly. Let the rest continue inside this session.",sendButton:"Send Message",queueTitle:"Queued Messages",queueDescription:"After the current run finishes, these messages will be processed automatically in order.",queueOrderPrefix:"Queue Position",queueStatusQueued:"Queued",queueStatusFailed:"Dispatch Failed",queueDelete:"Delete",queueDeleting:"Deleting",queueImageOnly:"Image attachments only",sendGuidanceButton:"Add Guidance",queueGuidanceButton:"Queue Guidance",queueSteer:"Steer",queueSteering:"Steering",resendButton:"Resend",quickPhraseTrigger:"Quick Phrases",quickPhraseModalTitle:"Quick Phrases",quickPhraseModalDescription:"Keep the prompts you reuse often in one place and drop them straight into the current composer.",quickPhraseCreateLabel:"New Phrase",quickPhraseOpenCreateAction:"Add Phrase",quickPhraseCreateModalTitle:"Create Quick Phrase",quickPhraseCreateModalDescription:"Save a reusable prompt on its own so it is ready across devices whenever you need it.",quickPhraseCreatePlaceholder:"Write a phrase you want to reuse later.",quickPhraseCreateAction:"Add Phrase",quickPhraseListLabel:"Quick phrase list",quickPhraseEmpty:"There are no quick phrases yet. Add the first one you actually reuse.",quickPhraseOrderLabel:"Item {index}",quickPhraseMoveUp:"Move phrase up",quickPhraseMoveDown:"Move phrase down",quickPhraseDelete:"Delete phrase",quickPhraseSaveFailed:"Failed to save quick phrases. Try again later.",sendingState:"Sending",sentState:"Synced",failedState:"Send failed",contextUsageTitle:"Context Usage",contextUsageUnavailable:"Context usage is not available yet",contextUsageEstimated:"Window is estimated",contextUsageCachedTokens:"{count} cached",contextUsageSourceProviderLog:"window from provider log",contextUsageSourceProviderRuntime:"window from provider runtime",contextUsageSourceProviderConfig:"window from provider config",contextUsageSourceModelMap:"window from model map",headerWorkspace:"Workspace",headerProvider:"Provider",headerCapability:"Capability Summary",connectionConnected:"Connected",connectionReconnecting:"Reconnecting",connectionReconnectFailed:"Reconnect failed",connectionClosed:"Connection closed",runtimeErrorTitle:"Session run failed",runtimeErrorFallbackDetail:"The CLI provider returned an error without additional detail.",runtimeErrorCodeLabel:"Error code",runtimeErrorDetailLabel:"Error detail",permissionRequestSectionTitle:"Pending approvals",permissionRequestSectionDescription:"Provider-side approvals are unified here so you do not need to learn three different dialogs.",permissionRequestToastTitle:"Approval needed",permissionRequestReplyFailed:"Failed to reply to the approval request.",permissionRequestSubmitting:"Submitting...",permissionRequestReasonLabel:"Reason",permissionRequestCommandLabel:"Command",permissionRequestToolLabel:"Tool",permissionRequestCwdLabel:"Working directory",permissionRequestPathsLabel:"Related paths",permissionRequestPermissionsLabel:"Requested permissions",permissionRequestReadLabel:"Read",permissionRequestWriteLabel:"Write",permissionRequestNetworkLabel:"Network",permissionRequestQuestionsLabel:"Questions",permissionRequestDetailLabel:"Details",permissionRequestEmpty:"None",permissionRequestUnknown:"Unknown",permissionRequestKindCommand:"Command",permissionRequestKindFileChange:"File Change",permissionRequestKindPermissions:"Permissions",permissionRequestKindUserInput:"User Input",permissionRequestKindToolCall:"Tool Call",reconnectExplain:"The realtime link is broken. The system is replaying missing messages.",reconnectFailedExplain:"Automatic recovery failed. Retry manually, or reopen the session later.",reconnectExplainWithRoute:"The realtime link is broken. The system is replaying missing messages. Current route: {route}.",reconnectFailedExplainWithRoute:"Automatic recovery failed. Retry manually, or reopen the session later. Current route: {route}.",capabilityDenied:"This action is not supported in the current session.",capabilitySendDisabled:"The current provider does not support sending new messages.",capabilityAttachmentDisabled:"This session does not support attachment input yet.",capabilityInterruptDisabled:"This session does not support interruption.",sidebarTitle:"Current Session Context",sidebarSubtitle:"This sidebar only keeps the minimum capability summary. It does not turn the page into an admin console.",reconnectButton:"Restore Realtime Sync",headerResumedAt:"Last Resumed",headerLastSyncAt:"Last Synced",historyPages:"History Pages",syncStatusIdle:"Sync Idle",syncStatusSyncing:"Syncing",syncStatusError:"Sync Error",capabilityResume:"Resumable",capabilitySend:"Send Enabled",capabilityInterrupt:"Interrupt Enabled",capabilityTools:"Tool Calls",attachmentsLabel:"Attachments",filePanelTitle:"File Manager",filePanelSubtitle:"File capabilities here only serve the current session. This is not a heavy IDE shell.",filePanelNoWorkspace:"There is no selected workspace yet. Browsing or attaching files is unavailable.",filePanelRefresh:"Refresh",filePanelCopyPath:"Copy Path",filePanelCopyAbsolutePath:"Copy Absolute Path",filePanelCopyRelativePath:"Copy Relative Path",filePanelCopyAbsolutePathSuccess:"Absolute path copied.",filePanelCopyRelativePathSuccess:"Relative path copied.",filePanelCopyPathFailed:"Failed to copy the path.",filePanelCopy:"Copy",filePanelCut:"Cut",filePanelPaste:"Paste",filePanelCopySelectionSuccess:"{count} item(s) copied. Paste them into a target folder.",filePanelCutSelectionSuccess:"{count} item(s) cut. Paste them into a target folder.",filePanelPasteSuccess:"{count} item(s) pasted.",filePanelPasteFailed:"Paste failed. Check the target folder and name conflicts.",filePanelSelectionCount:"{count} item(s) selected",filePanelClipboardCopyReady:"{count} item(s) ready to copy",filePanelClipboardCutReady:"{count} item(s) ready to move",filePanelOpenFile:"Open File",filePanelExpandDirectory:"Expand Folder",filePanelCollapseDirectory:"Collapse Folder",filePanelActionsMenu:"File Actions",filePanelSearchPlaceholder:"Enter a file name or path fragment",filePanelSearchButton:"Search",filePanelShowSearch:"Open Search",filePanelHideSearch:"Hide Search",filePanelSearchEmpty:"No matching files found.",filePanelSearchResults:"Search Results",filePanelSearchFailed:"File search failed. Try again later.",filePanelBrowse:"Workspace Files",filePanelCollapseCurrent:"Collapse Current",filePanelCollapseAll:"Collapse All",filePanelBackDirectory:"Go to Parent",filePanelEmptyDirectory:"There are no files to show in this directory.",filePanelRecentTitle:"Recently Opened",filePanelEmptyRecent:"There is no recently opened file yet.",filePanelContextTitle:"Attached Files",filePanelEmptyContexts:"No file is attached to the current session yet.",filePanelEditorTitle:"Preview & Editor",filePanelEditorPlaceholder:"This is a lightweight text editor, not a full IDE.",filePanelSelectHint:"Pick a file first from browse, search, or recent items.",filePanelUnsupported:"This file cannot be edited directly in the sidebar right now.",filePanelAttach:"Attach to Session",filePanelAttached:"Attached",filePanelDetach:"Detach",filePanelSave:"Save",filePanelSaving:"Saving...",filePanelLoadFailed:"Failed to load the file panel.",filePanelOpenFailed:"Failed to open the file.",filePanelSaveSuccess:"File saved.",filePanelSaveFailed:"Failed to save the file.",fileViewerHint:"Opened in {language} mode. Preview and save after editing are supported.",fileViewerModeLabel:"File View Mode",fileViewerPreview:"Preview",fileViewerPresentation:"Presentation",fileViewerCode:"Code",fileViewerEdit:"Edit",fileViewerPlainText:"Plain Text",fileViewerHtml:"HTML",fileViewerImage:"Image",fileViewerPdf:"PDF",fileViewerRefreshPreview:"Refresh",fileViewerRefreshFailed:"Failed to refresh the file preview.",fileViewerExportPdf:"Export PDF",fileViewerExportPdfRunning:"Exporting...",fileViewerExportPdfSuccess:"PDF exported to {path}",fileViewerExportPdfFailed:"Failed to export the PDF.",fileViewerExportPdfTimeout:"PDF export timed out. Try again later.",fileViewerExportPdfMissingHtml:"No HTML content is available for export.",fileViewerExportPptx:"Export PPTX",fileViewerExportPptxRunning:"Exporting...",fileViewerExportPptxSuccess:"PPTX exported to {path}",fileViewerExportPptxFailed:"Failed to export the PPTX.",fileViewerExportPptxMissingHtml:"No HTML content is available for export.",fileViewerExportTaskTimeout:"Export timed out. Try again later.",fileViewerOpenExternal:"Open Externally",fileViewerOpenExternalFailed:"Failed to open the file externally.",fileViewerOpenInWindow:"Separate Window",fileViewerOpenInWindowFailed:"Failed to open the separate window.",fileViewerWindowTitle:"File Preview",fileViewerCollapse:"Collapse Preview",fileViewerExpand:"Expand Preview",fileViewerZoomIn:"Zoom In",fileViewerZoomOut:"Zoom Out",fileViewerFit:"Fit",fileViewerActualSize:"Actual Size",fileViewerFitWidth:"Fit Width",fileViewerPreviousPage:"Previous Page",fileViewerNextPage:"Next Page",fileViewerPageIndicator:"Page {page}",fileViewerSizeLabel:"Viewer Size",fileViewerSizeDefault:"Default",fileViewerSizeWide:"Wide",fileViewerSizeFull:"Full",fileViewerDiffModified:"Modified",fileViewerDiffAdded:"Added Content",fileViewerImageUnavailable:"The image preview is unavailable right now. Try refreshing or opening it externally.",fileViewerPdfUnavailable:"The PDF preview is unavailable right now. Try refreshing or opening it externally.",fileViewerOfficeLoading:"Loading the ONLYOFFICE preview...",fileViewerOfficeUnavailable:"The Office preview is unavailable right now. Check the ONLYOFFICE configuration and service status.",fileViewerOfficeScriptUnavailable:"Failed to load the ONLYOFFICE editor script. Check whether the service URL is reachable.",fileViewerEnterFullscreen:"Full Screen",fileViewerExitFullscreen:"Exit",fileViewerOpenInBrowser:"Open in Browser",fileViewerOpenInBrowserFailed:"Failed to open the browser preview.",fileViewerHtmlPreviewLoading:"Loading the HTML preview...",fileViewerHtmlPreviewUnavailable:"The HTML preview is unavailable right now. Switch to code view instead.",fileViewerHtmlPreviewFailed:"Failed to create the HTML preview link.",fileViewerPresentationBadge:"Static HTML",fileViewerPresentationSummary:"{count} pages detected, canvas {size}",fileViewerPresentationWarningCount:"{count} import warnings detected.",fileViewerPresentationCurrentPage:"Current Page",fileViewerPresentationUntitled:"Untitled Page",fileViewerPresentationReadOnlyHint:"Select a component to view text and layout editing tools.",fileViewerPresentationEditHint:"This pass supports node selection plus basic text and style edits. Complex structures stay read-only.",fileViewerPresentationCanvasSelectHint:"Click a component on the canvas to edit it from the top toolbar, or switch from the component list on the right.",fileViewerPresentationUnsupported:"This HTML file is not ready for presentation view yet.",fileViewerPresentationUnsupportedReason:"Reason: {reason}",fileViewerPresentationSelectNode:"Pick an editable node from the component list on the right first.",fileViewerPresentationAddPage:"Add Page",fileViewerPresentationDuplicatePage:"Duplicate Page",fileViewerPresentationDeletePage:"Delete Page",fileViewerPresentationMovePageUp:"Move Page Up",fileViewerPresentationMovePageDown:"Move Page Down",fileViewerPresentationPageActions:"Page Actions",fileViewerPresentationDragToSort:"Drag to Sort",fileViewerPresentationUndoAction:"Undo Last Action",fileViewerPresentationInspector:"Inspector",fileViewerPresentationComponentList:"Components",fileViewerPresentationEditable:"Editable",fileViewerPresentationReadOnly:"Read Only",fileViewerPresentationTextLabel:"Text Content",fileViewerPresentationTextDescription:"Edit the copy here and the canvas preview updates immediately.",fileViewerPresentationTextToolbar:"Text Toolbar",fileViewerPresentationFontFamilyLabel:"Font Family",fileViewerPresentationFontPresetTitle:"DengXian Light (Headings)",fileViewerPresentationFontPresetSans:"Noto Sans SC",fileViewerPresentationFontPresetSerif:"Serif Body",fileViewerPresentationFontPresetMono:"Monospace",fileViewerPresentationBoldAction:"Bold",fileViewerPresentationItalicAction:"Italic",fileViewerPresentationUnderlineAction:"Underline",fileViewerPresentationFontSizeIncreaseAction:"Increase Font Size",fileViewerPresentationFontSizeDecreaseAction:"Decrease Font Size",fileViewerPresentationLineHeightAuto:"Default Line Spacing",fileViewerPresentationFontSizeLabel:"Font Size",fileViewerPresentationFontWeightLabel:"Font Weight",fileViewerPresentationTextColorLabel:"Text Color",fileViewerPresentationBackgroundColorLabel:"Background Color",fileViewerPresentationTextAlignLabel:"Alignment",fileViewerPresentationLineHeightLabel:"Line Height",fileViewerPresentationPaddingLabel:"Padding",fileViewerPresentationRadiusLabel:"Radius",fileViewerPresentationPositionXLabel:"Position X",fileViewerPresentationPositionYLabel:"Position Y",fileViewerPresentationWidthLabel:"Width",fileViewerPresentationHeightLabel:"Height",fileViewerPresentationDuplicateAction:"Duplicate Selected Node",fileViewerPresentationKeepOriginal:"Keep Original",fileViewerPresentationAlignLeft:"Align Left",fileViewerPresentationAlignCenter:"Align Center",fileViewerPresentationAlignRight:"Align Right",fileViewerPresentationTextMode:"Text",fileViewerPresentationLayoutMode:"Layout",fileViewerPresentationLayoutHint:"This toolbar edits component position and size. Canvas dragging and saving follow the same geometry.",fileViewerPresentationLayoutSelectNode:"Pick a component that supports layout editing first.",fileViewerPresentationLayoutEditable:"Layout Editable",fileViewerPresentationLayoutLocked:"Layout Locked",fileViewerPresentationLayoutUnsupported:"This component is not safe for layout editing yet.",fileViewerPresentationLayoutStrictLocked:"This component is still in flow layout. Convert its container to free layout before dragging it.",fileViewerPresentationLayoutFreezeContainer:"Convert Container to Free Layout",fileViewerPresentationLayoutRootLocked:"Page root containers stay locked in this pass.",fileViewerPresentationLayoutSelectionCount:"{count} components selected",fileViewerPresentationLayoutAlignLeft:"Align Left Edge",fileViewerPresentationLayoutAlignRight:"Align Right Edge",fileViewerPresentationLayoutAlignTop:"Align Top Edge",fileViewerPresentationLayoutAlignBottom:"Align Bottom Edge",fileViewerPresentationResizeHandle:"Resize Component",filePanelAttachSuccess:"The file has been attached to the current session.",filePanelAttachFailed:"Failed to attach the file.",filePanelDetachSuccess:"The file has been detached from the current session.",filePanelDetachFailed:"Failed to detach the file.",filePanelNewFile:"New File",filePanelNewDirectory:"New Directory",filePanelUpload:"Upload File",filePanelDownload:"Download File",filePanelUploadSuccess:"{name} uploaded.",filePanelUploadFailed:"Failed to upload the file.",filePanelDownloadSuccess:"Started downloading {name}.",filePanelDownloadFailed:"Failed to download the file.",filePanelDelete:"Delete",filePanelDeleting:"Deleting...",filePanelDeleteSuccess:"Deleted {name}.",filePanelDeleteConfirmTitle:"Confirm Deletion",filePanelDeleteConfirmDescription:"The selected item will be removed from this workspace immediately and cannot be undone.",filePanelDeleteSelectionConfirm:"Delete the selected {count} items?",filePanelDeleteSelectionSuccess:"Deleted {count} items.",filePanelRenameMove:"Rename / Move",filePanelRenameSuccess:"Renamed to {name}.",filePanelMutateFailed:"File operation failed. Check the path and current state.",filePanelCreateFilePrompt:"Enter the relative path of the file to create",filePanelCreateDirectoryPrompt:"Enter the relative path of the directory to create",filePanelCreateFileDescription:"Enter a relative path inside the workspace. The file will be created immediately.",filePanelCreateDirectoryDescription:"Enter a relative path inside the workspace. The folder will be created immediately.",filePanelPathFieldLabel:"Relative Path",filePanelPathFieldPlaceholder:"For example: src/features/files/index.ts",filePanelCreateFileSubmit:"Create File",filePanelCreateDirectorySubmit:"Create Folder",filePanelCreatingFile:"Creating file...",filePanelCreatingDirectory:"Creating folder...",exportAction:"Export Session",exportDialogTitle:"Export Current Session",exportDialogDescription:"Export the full session as Markdown, or print the current message layout and save it as PDF.",exportMarkdownAction:"Export Markdown",exportMarkdownHint:"Exports the full message content for editing, archiving, or commit history.",exportPdfAction:"Export PDF",exportPdfHint:"Downloads a PDF file directly and keeps the current conversation content layout.",exportHtmlAction:"Export HTML",exportPreparing:"Preparing the export content...",exportMarkdownSuccess:"The Markdown export has started.",exportPdfPreparing:"The PDF download has started.",exportHtmlSuccess:"The HTML export has started.",exportLoadFailed:"Export failed because the full session content could not be loaded.",exportDownloadFailed:"Failed to export the file.",exportPrintFailed:"Failed to open the print dialog.",exportPrintContainerTitle:"Session Export",exportMarkdownSessionIdLabel:"Session ID",exportMarkdownProviderLabel:"Provider",exportMarkdownWorkspaceLabel:"Workspace ID",exportMarkdownCreatedAtLabel:"Created At",exportMarkdownExportedAtLabel:"Exported At",exportMarkdownTimeLabel:"Time",exportMarkdownTypeLabel:"Type",exportMarkdownAttachmentsLabel:"Attachment Count",exportMarkdownAttachmentsSectionTitle:"Attachments",exportMarkdownToolSectionTitle:"Tool Call",exportMarkdownToolNameLabel:"Tool Name",exportMarkdownToolStatusLabel:"Status",exportMarkdownToolInputLabel:"Input",exportMarkdownToolOutputLabel:"Output",exportMarkdownToolErrorLabel:"Error",exportMarkdownToolCallType:"Tool Call",exportMarkdownToolResultType:"Tool Result",exportMarkdownTextType:"Text",exportMarkdownUnknownSize:"Unknown Size",filePanelFilterChanges:"Changes Only",filePanelShowAll:"Show All",filePanelNoChanges:"No changed files.",filePanelBinaryPreview:"Binary files cannot be previewed.",filePanelDeleteFileConfirm:"Delete this file? {path}",filePanelDeleteDirectoryConfirm:"Delete this folder? {path}",filePanelRenameMovePrompt:"Enter the new relative path",filePanelRenameDescription:"Only the path changes. Use a new relative path if you also want to move it.",filePanelRenameSubmit:"Confirm Rename",filePanelRenaming:"Renaming...",unavailableAction:"Unavailable",roleUser:"User",roleAssistant:"Assistant",roleTool:"Tool",toolViewImageActiveLabel:"AI is viewing an image",assistantCapabilityBadgeSubAgent:"Sub-agent",codexAgentToolCreateTitle:"Create Sub-agent",codexAgentToolReadTitle:"Read Sub-agent",codexAgentToolUpdateTitle:"Update Sub-agent",codexAgentToolReplyTitle:"Reply to Sub-agent",codexAgentToolCloseTitle:"Close Sub-agent",codexAgentToolCreateSummary:"A separate task was delegated to a sub-agent.",codexAgentToolReadSummary:"Reading the latest sub-agent status and response.",codexAgentToolUpdateSummary:"The sub-agent task was redirected or updated.",codexAgentToolReplySummary:"A follow-up message was sent to the sub-agent.",codexAgentToolCloseSummary:"This sub-agent session was closed.",codexAgentToolLabelAgent:"Agent",codexAgentToolLabelNickname:"Nickname",codexAgentToolLabelRole:"Type",codexAgentToolLabelModel:"Model",codexAgentToolLabelTargets:"Targets",codexAgentToolLabelTimeout:"Wait",codexAgentToolLabelMessage:"Message",codexAgentToolLabelReason:"Result",subagentNotificationTitle:"Sub-agent Report",subagentNotificationSummary:"The sub-agent returned the task result.",subagentNotificationLabelSummary:"Summary",subagentNotificationStatusCancelled:"Cancelled",roleSystem:"System"},git:{title:"Git Context",subtitle:"This is the session-side support area. It only handles Git facts inside the current workspace.",loading:"Loading Git context for the current workspace...",refresh:"Refresh",panelLoadFailed:"Git context is not available right now.",uninitializedTitle:"Git is not enabled in this folder yet",uninitializedDescription:"Initialize a Git workspace here first, then you can review changes, commit, and browse history.",initRepository:"Initialize Git Workspace",initInProgress:"Initializing...",initSuccess:"The Git workspace has been initialized.",initFailed:"Failed to initialize the Git workspace.",ahead:"Ahead",behind:"Behind",dirty:"Dirty",clean:"Clean",changeCount:"{count} changed files in the current workspace",noChanges:"There are no pending changes right now.",changesTitle:"Current Changes",rulesFirstHint:"Rules come first. Drafts must not bypass validation.",stage:"Stage",unstage:"Unstage",preview:"Preview",stageFailed:"Stage operation failed.",diffTitle:"Diff Preview",diffLoadFailed:"Diff content is not available right now.",binaryDiff:"This file is a binary change. The sidebar does not render its content directly.",stagedDiff:"Staged diff",worktreeDiff:"Working tree diff",emptyDiff:"There is no text diff to display right now.",diffTruncated:"The diff is too long and has been truncated for safety.",commitTitle:"Commit Draft",defaultRuleName:"Default Commit Rule",language:"Language",maxLength:"Max Length",bodyRequired:"Body Required",bodyOptional:"Body Optional",issueRequired:"Issue Required",issueOptional:"Issue Optional",commitSubject:"Commit Subject",commitSubjectPlaceholder:"Enter the commit message here",commitBody:"Commit Body",commitBodyPlaceholder:"Explain the change clearly. Do not write empty words.",commitFooter:"Commit Footer",commitFooterPlaceholder:"For example: Refs: #123",generateDraft:"AI Draft",validate:"Validate Draft",commit:"Commit",draftFailed:"Failed to generate the commit draft.",validateFailed:"Commit rule validation failed.",commitFailed:"Commit failed.",commitSuccess:"The commit has been written to the current repository.",validationPassed:"Rule validation passed. You can continue to commit.",validationFailed:"Rule validation failed. Fix the issues below first.",branchTitle:"Branch",branchPlaceholder:"Enter the branch name to switch to or create",switchBranch:"Switch",createBranch:"Create",branchFailed:"Branch operation failed.",historyTitle:"Recent History",historyHint:"Only keep the latest few entries here. This is not a graphical history tree.",noHistory:"There is no commit history to show right now.",viewAllVersions:"View All Versions",viewAllVersionsDescription:"Loaded commit history for the current repository. Total entries: {count}.",viewCommitChanges:"View Changed Files and DIFF",copyCommitMessage:"Copy Commit Message",copyCommitMessageSuccess:"The commit message has been copied.",copyCommitVersion:"Copy Git Version",copyCommitVersionSuccess:"The Git version has been copied.",commitDetailTitle:"Commit Detail",commitDetailDescription:"Showing the full change for commit {hash}.",commitDetailLoading:"Loading commit detail...",commitDetailEmpty:"There is no commit detail to show right now.",commitDetailLoadFailed:"The commit detail is not available right now.",commitVersionLabel:"Git Version",commitHashLabel:"Commit Hash",commitAuthorLabel:"Author",commitTimeLabel:"Commit Time",commitMessageLabel:"Commit Message",changedFilesTitle:"Changed Files",commitDiffLabel:"Commit DIFF",renamedFromLabel:"Renamed from {path}",explainCommitTitle:"Explain Commit Change",explainCommitDescription:"Choose a CLI provider first, then start a new session to analyze this commit.",explainCommitAction:"Explain Change",startExplainCommit:"Start Explaining",explainCommitStarted:"The explanation session has been created.",explainCommitFailed:"Failed to explain the commit change.",remoteTitle:"Remote Sync",remoteReady:"A remote is configured for the current repository.",remoteMissing:"The current repository has no remote configured yet.",fetch:"Fetch",pull:"Pull",push:"Push",pushNow:"Push Now",publish:"Publish",remoteFailed:"Remote sync failed.",remoteAuthAction:"Remote Auth",remoteAuthTitle:"Configure Remote Authentication",remoteAuthDescription:"Enter the username, password, or token to use for authenticated remote operations in this page session.",remoteAuthDescriptionGithub:"The current remote points to GitHub. For GitHub HTTPS Git operations, use a Personal Access Token (PAT) instead of your GitHub login password.",remoteAuthStatusLabel:"Authentication",remoteAuthManageHint:"Review and configure per remote",remoteAuthManageTitle:"Manage Remote Authentication",remoteAuthManageDescription:"Each remote repository shows its own credential status and should be configured separately here.",remoteAuthConfigured:"Configured",remoteAuthConfiguredInSession:"Configured In Session",remoteAuthConfiguredOnHost:"Saved On Host",remoteAuthNotConfigured:"Not Configured",remoteAuthGithubPatLabel:"Personal Access Token (PAT)",remoteAuthGithubPatPlaceholder:"Enter GitHub PAT",remoteAuthGithubUsernamePlaceholder:"Enter GitHub username",remoteAuthGithubPatHint:"GitHub does not support account passwords for Git HTTPS authentication. In basic mode, enter GitHub username + PAT. In token mode, you can paste the PAT directly.",remoteAuthRemember:"Remember On Host",remoteAuthSessionHint:"By default this only applies to the current page session. If you enable “Remember On Host”, the credential will be stored on the Host after a successful remote sync and reused later.",remoteAuthRememberHint:"When remember is enabled, this credential will be written to the Host after the remote sync succeeds.",remoteAuthSave:"Save Auth",remoteAuthSaved:"Remote authentication saved. Retry the remote sync now.",remoteAuthCleared:"Remote authentication for this page session has been cleared.",selectRemoteTitle:"Select Remote to Push",selectRemoteDesc:"Select remote repositories to push to. Multiple selection supported.",noRemotes:"No remote repositories are configured.",pushSelected:"Push ({count})",pushing:"Pushing…",pushAllSuccess:"Successfully pushed to {count} remote(s).",errors:{unauthorized:"The current login is no longer valid. Log in again and retry.",workspaceNotFound:"The workspace bound to the current session does not exist. Check whether it is still available.",invalidWorkspace:"The current workspace config is invalid. The Git sidebar must not operate outside the repo root.",notGitRepository:"The current workspace is not a Git repository. The Git sidebar will not fake a state.",repoNotFound:"No usable Git repository root was found for the current workspace.",pathOutOfWorkspace:"The Git target is outside the current workspace repository boundary. The operation was blocked.",invalidTarget:"The Git target path is invalid. Refresh the sidebar and try again.",notStaged:"The target file is not staged yet. Check the current change state first.",emptyStagedChanges:"The staging area is empty. Stage the changes before committing.",branchConflict:"The current branch has conflicts or is not a fast-forward update. Sync and resolve differences first.",branchNotFound:"The target branch does not exist. Check the branch name first.",remoteNotFound:"The current repository does not have a usable origin remote yet.",remoteAuthFailed:"Remote repository authentication failed. Check the current credentials first.",pushFailed:"Push failed. Check remote state and local commits first.",pullFailed:"Pull failed. Check the remote branch state first.",remoteFailed:"Remote sync failed. Check Git output and network state.",initFailed:"Failed to initialize the Git workspace. Make sure the directory is writable and Git is available.",commitValidationFailed:"The commit draft has not passed validation yet. Fix validation issues first.",commandTimeout:"The Git operation timed out. Check repository state and network conditions."}},theme:{light:"浅色",dark:"深色",skyBlue:"赛博",eyeGreen:"护眼",switchLabel:"Theme"},locale:{zhCN:"Simplified Chinese",enUS:"English"}},fm={common:{appName:"CodingNS",loading:"正在准备会话工作区…",retry:"重新尝试",back:"返回",save:"保存",close:"关闭",cancel:"取消",connectionRouteRelay:"CodingNS Connect",connectionRouteLan:"局域网直连",connectionRouteLoopback:"本机直连",connectionRouteTailscale:"Tailscale 直连",connectionRouteDirect:"直接连接",logout:"退出登录",unknown:"未命名会话"},auth:{loginTitle:"继续你的编码会话",loginSubtitle:"INITIALIZING DEVELOPMENT ENVIRONMENT...",serverPreset:"服务器列表",serverCustomOption:"使用自定义服务器",serverAddress:"服务器地址",serverPlaceholder:"例如:http://127.0.0.1:3002",serverHint:"登录、实时消息和终端都会连接到这里。客户端应填写 Host API 地址,例如 http://127.0.0.1:3002;4174、5173 这类前端开发端口不是给正式客户端直接连接的,只有代理和跨域都配好时才适合临时调试。",serverInvalid:"服务器地址无效,请检查后再试。",serverDiscoveredTag:"自动发现",serverCurrent:"当前服务器",bootstrapTitle:"先完成首次初始化",bootstrapSubtitle:"这个 Host 还没有管理员账号,先创建一个最小登录入口。",username:"用户名",password:"密码",rememberPassword:"保存密码",confirmPassword:"确认密码",submitLogin:"进入工作台",submitBootstrap:"创建管理员账号",bootstrapSuccess:"初始化完成,现在可以登录了。",bootstrapMismatch:"两次输入的密码不一致。",authUnavailable:"暂时连不上 Host,请确认服务可访问。",logoutSuccess:"当前登录态已经清空。",demoBanner:"演示环境 — 所有账号数据公开可见,注销后自动清除",demoSessionExpired:"演示会话已过期,请重新登录",captcha:"图形验证码",captchaPlaceholder:"输入图中的字符",captchaHint:"连续输错三次后,需要先完成图形验证码才能继续登录。",captchaImageAlt:"登录图形验证码",serverSettings:"服务器设置",serverSettingsTitle:"服务器配置",saveServerSettings:"保存设置",relayEntryTitle:"正在连接远程 Host",relayEntryDescription:"正在切换到这台 Host 的可信连接入口,完成后会自动回到登录页。",relayEntryInvalid:"当前远程访问入口参数不完整,请重新打开访问地址。",trustedEntryOnlyTitle:"请通过远程访问地址进入",trustedEntryOnlyDescription:"这个可信前端站点只负责加载连接页面,不直接承载 Host API。请重新打开设备的远程访问地址。",trustedEntryOnlyHintTitle:"如何进入",trustedEntryOnlyHint:"请使用类似 https://xxxx.channel.codingns.com:1443 的远程访问地址进入;四级域名会自动把你带到正确的连接入口。"},plugins:{listTitle:"插件",listDescription:"这里统一查看当前工作区可用的插件,并决定要不要继续打开或停用。",loading:"正在读取插件列表…",listLoadFailed:"插件列表加载失败。",emptyTitle:"当前还没有可用插件",emptyDescription:"等 Host 扫描到合法插件后,这里会自动出现。",enabled:"已启用",disabled:"已停用",frontendTag:"前端",backendTag:"动作",detailLoadFailed:"插件详情加载失败。",detailMissingTitle:"没找到这个插件",detailMissingDescription:"可能是插件目录被移除了,或者当前 Host 还没重新扫描到它。",backToList:"返回插件列表",backToDetail:"返回插件详情",summaryTitle:"基本信息",summaryDescription:"先确认这个插件是谁、装在哪里、现在能不能用。",pluginIdLabel:"插件标识",installRootLabel:"安装目录",runtimeLabel:"运行方式",frontendOnly:"只有前端页面,没有后端动作",permissionTitle:"权限边界",permissionDescription:"这里只显示插件明确声明过的权限。没声明的能力默认不放开。",workspaceReadAllowed:"可读取当前工作区",workspaceReadDenied:"未声明工作区读取权限",networkAllowed:"允许联网",networkDenied:"默认不联网",noDesktopPermission:"没有桌面权限",actionTitle:"可调用动作",actionDescription:"这些动作都走统一插件网关,不会私长命令入口。",runHistoryTitle:"最近运行记录",runHistoryDescription:"这里先看最近 10 条,方便排查动作有没有跑起来。",runHistoryEmptyTitle:"还没有运行记录",runHistoryEmptyDescription:"等你第一次运行插件动作后,这里会出现正式记录。",unknownAction:"未知动作",openPlugin:"打开插件",enableAction:"启用插件",disableAction:"停用插件",permissionNameReadFile:"读取文件",permissionNameListDirectory:"查看目录内容",permissionNameWriteFile:"写入文件",permissionNameOpenFile:"在桌面里打开文件",permissionNameRevealInFileManager:"在文件管理器里显示文件",permissionScopeWorkspace:"整个当前工作区",permissionScopeDirectory:"目录:{scopePath}",permissionScopeFile:"文件:{scopePath}",permissionScopeUnknown:"目标范围未明确",permissionGrantModeOnce:"仅这一次",permissionGrantModeSession:"本次打开期间",permissionGrantModePersistent:"长期保留",permissionPromptTitle:"插件需要你先授权",permissionPromptDescription:"先确认这次要放开什么能力,再决定给多久、放到哪里为止。",permissionPromptSummaryTitle:"这次申请什么权限",permissionPromptSummaryDescription:"{pluginName} 这次请求了受控能力,没点同意前不会继续执行。",permissionPromptPermissionLabel:"申请能力",permissionPromptTargetLabel:"作用范围",permissionPromptPendingTag:"待你确认",permissionPromptOptionsTitle:"你可以怎么放权",permissionPromptOptionsDescription:"先给最小范围,别一上来就放大。",permissionPromptOptionOnce:"只放行这一个目标",permissionPromptOptionOnceDescription:"只允许这次请求继续,后面再用时还会重新问你。",permissionPromptOptionSession:"当前打开期间都允许",permissionPromptOptionSessionDescription:"只在这次插件页面打开期间有效,关掉后自动失效。",permissionPromptOptionDirectory:"长期允许这个目录",permissionPromptOptionDirectoryDescription:"后续访问 {scopePath} 和它下面的内容时,不用每次再确认。",permissionPromptDenyAction:"先不授权",permissionPromptNoOptionTitle:"这次没有可用授权方式",permissionPromptNoOptionDescription:"当前请求缺少可放权范围,先返回插件详情再看。",grantedPermissionTitle:"当前工作区已授权内容",grantedPermissionDescription:"这里只看这个工作区已经放开的能力,方便你随时收回。",grantedPermissionEmptyTitle:"当前还没有授权记录",grantedPermissionEmptyDescription:"等插件第一次申请并被你同意后,这里会出现正式授权记录。",permissionGrantLoading:"正在读取授权记录…",permissionGrantLoadFailed:"插件授权记录加载失败。",revokeGrantAction:"撤销授权",revokeGrantSuccess:"插件授权已撤销。",revokeGrantFailed:"撤销插件授权失败。",permissionAuditTitle:"最近授权相关记录",permissionAuditDescription:"这里会记录授权、拒绝和撤销,方便回头排查是谁放开的。",permissionAuditEmptyTitle:"还没有授权相关记录",permissionAuditEmptyDescription:"等出现授权、拒绝或撤销后,这里会自动显示。",permissionEventGranted:"已授权:{permission}",permissionEventRevoked:"已撤销:{permission}",permissionEventDenied:"已拒绝:{permission}",permissionEventUnknown:"未知权限",permissionEventReasonDeclarationMissing:"插件没声明,直接拒绝",permissionEventReasonGrantRequired:"需要你先授权",enableSuccess:"插件已启用。",disableSuccess:"插件已停用。",saveFailed:"插件状态保存失败。",disabledByUserReason:"由用户在插件详情页停用",containerDescription:"插件前端运行在独立容器里,不会直接拿到宿主桌面桥。",containerLoadFailed:"插件运行页加载失败。",containerMissingTitle:"当前插件没有可运行页面",containerMissingDescription:"这个插件可能只有后端动作,或者已经被停用。"},settings:{title:"设置",appearance:"外观",appearanceSectionSummary:"语言、主题与界面配色",language:"语言",languageDescription:"选择界面显示语言,切换后立即应用到当前页面。",theme:"主题",themeDescription:"选择适合你的界面配色方案",autoTheme:"自动跟随系统主题",autoThemeDescription:"开启后根据系统或浏览器的深浅色偏好自动切换日间和夜间模式。",fileManager:"文件管理",workspaceSessionSortMode:"工作区的会话显示排序方式",teableEntryTitle:"Teable 表单",teableEntryDescription:"统一管理 Teable 连接,以及 CodingNS 数据同步到 Teable 表的方式。",teableOpenSettingsAction:"打开设置",teableModalTitle:"Teable 表单设置",teableModalDescription:"这里统一管理 Teable 连接、需要同步的表,以及 CodingNS 数据和 Teable 字段的对应关系。",teableTabConnection:"连接",teableTabForms:"表单",teableTabMirrors:"镜像",teableTabFieldMappings:"字段映射",teableTabConnectionSettings:"连接设置",teableTabFormSettings:"表单设置",teableTabTableSyncSettings:"表同步设置",teableTabSyncLogs:"同步日志",teableTestConnectionAction:"测试连接",teableConnectionTestSuccess:"连接可用,已读取 {tableCount} 张表。",teableLoadFailed:"Teable 设置加载失败。",teableStatusUnknown:"暂未读取到状态",teableStatusIdleHint:"还没有发起过镜像同步。",teableStatusBindingLabel:"连接状态",teableStatusSourceLabel:"已开启数据源",teableStatusSourceDetail:"当前有 {count} 类数据会推送到 Teable。",teableStatusMirrorLabel:"镜像表",teableStatusMirrorDetail:"当前已经记录 {count} 张镜像表绑定。",teableStatusTaskLabel:"最近同步",teableBindingSectionTitle:"连接设置",teableBindingSectionDescription:"先把 Teable 站点、空间、Base 和访问 Token 填对,再决定是否启用。",teableEnabledLabel:"启用 Teable 同步",teableBaseUrlLabel:"Teable 站点地址",teableBaseUrlDescription:"支持 http:// 和 https://。如果 Teable 跟 Host 在同一局域网,可以直接填 http 地址。",teableBaseUrlPlaceholder:"例如:http://192.168.1.20:3000",teableSpaceIdLabel:"Space ID",teableSpaceIdPlaceholder:"填写要绑定的 Space ID",teableBaseIdLabel:"Base ID",teableBaseIdPlaceholder:"填写目标 Base ID",teableAuthRefLabel:"认证引用",teableAuthRefPlaceholder:"例如:secret://teable/main",teableAuthTokenLabel:"访问 Token",teableAuthTokenDescription:"如果已经在 Host 里保存过 token,这里可以留空不改。",teableAuthTokenPlaceholder:"留空表示继续使用已保存 token",teableMirrorModeLabel:"同步方式",teableBindingSaved:"Teable 连接设置已保存。",teableSyncConfigSectionTitle:"工作台推送范围",teableSyncConfigSectionDescription:"这里决定标签、会话和代办哪些会同步到 Teable,以及各自落到哪张表。",teableSyncEnabledLabel:"允许同步这一类数据",teableTargetTableLabel:"目标表",teableTargetTablePlaceholder:"请选择 Teable 已有表",teableTagRootsLabel:"同步哪些标签树",teableSessionScopeModeLabel:"会话同步范围",teableSessionScopeAll:"同步全部工作区会话",teableSessionScopeSelected:"只同步选中的工作区会话",teableWorkspaceMultiSelectLabel:"选择工作区",teableTodoSourceLabel:"代办来源",teableTodoWorkspaceSource:"同步工作区代办",teableTodoAffairsSource:"同步事务代办",teableTodoWorkspaceHint:"如果这里选了工作区,只同步这些工作区里的代办;留空表示不按工作区额外筛选。",teableTargetTableIdLabel:"目标表 ID",teableTargetTableHint:"不填时,Host 会按默认镜像表名自动创建。",teableTargetTableBoundHint:"当前已经绑定到表“{table}”。",teableTargetTableIdPlaceholder:"可选,填已有表 ID 直接复用",teableScopeJsonLabel:"同步范围(JSON)",teableScopeJsonPlaceholder:"这里填这一类数据的同步范围 JSON。",teableScopeJsonInvalid:"同步范围必须是合法 JSON 对象。",teableSyncConfigSaved:"Teable 推送范围已保存。",teableFormsCatalogTitle:"Teable 已有表单",teableFormsCatalogDescription:"这里列出 Teable 里已经存在的表单视图。",teableFormsCatalogEmptyTitle:"还没有可用表单",teableFormsCatalogEmptyDescription:"先到 Teable 里创建表单视图。",teableFormSettingsLeftTitle:"已废弃的表单设置",teableFormSettingsLeftDescription:"设置页不再按表单配置同步,镜像同步只按 Teable 表配置。",teableFormMappingPanelTitle:"已废弃的同步内容设置",teableFormMappingPanelDescription:"设置页不再按表单配置同步,镜像同步只按 Teable 表配置。",teableAddSyncFormAction:"添加同步表单",teableRemoveSyncFormAction:"移除",teableSyncFormAddedTag:"已添加",teableSyncFormAdded:"同步表单已添加。",teableSyncFormRemoved:"同步表单已移除。",teableFormShareReady:"已开启分享",teableFormShareMissing:"未开启分享",teableSelectSyncFormTitle:"先选择一个表单",teableSelectSyncFormDescription:"左侧选择 Teable 表单后,这里会显示同步内容、工作区范围和字段映射。",teableSelectedFormLabel:"当前表单",teableSyncSourceLabel:"同步的信息",teableSyncSource:{sessions:"会话记录",todos:"代办",tags:"文档库标签"},teableWorkspaceScopeLabel:"工作区范围",teableWorkspaceScopeAll:"全部工作区",teableWorkspaceScopeSelected:"指定工作区",teableWorkspaceScopeEmpty:"还没有可选工作区。",teableDocumentTagRootsLabel:"文档库根标签",teableDocumentTagRootsDescription:"只同步选中根标签及其所有子标签;这不是工作区表单绑定。",teableDocumentTagRootsEmpty:"还没有可选的文档库根标签。",teableFieldMappingTitle:"字段映射",teableFieldMappingInlineDescription:"左边是 CodingNS 字段,右边选择 Teable 表里的目标字段。",teableSourceFieldsEmpty:"当前同步内容没有可映射字段。",teableSaveFormSyncSettingsAction:"保存表同步设置",teableFormSyncSettingsSaved:"表同步设置已保存。",teableTableSyncAvailableTitle:"Teable 表目录",teableTableSyncAvailableDescription:"这里不列出表单,只选择当前 Base 下已有的表。选中一张表后点添加,它会进入左侧同步表列表。",teableTableSyncListTitle:"同步表列表",teableTableSyncListDescription:"这里显示已经添加为镜像同步目标的表。选中一张表后,在右侧配置同步内容、范围和字段映射。",teableTableSyncConfigTitle:"当前表配置",teableTableSyncConfigDescription:"这里只配置左侧选中的同步表,不再堆积同步表记录。",teableTableToAddLabel:"选择要添加的表",teableAllTablesAdded:"所有表都已添加",teableAddSyncTableAction:"添加同步表",teableRemoveSyncTableAction:"移除",teableSyncTableAddedTag:"已添加",teableSelectSyncTableTitle:"先添加一张同步表",teableSelectSyncTableDescription:"从左侧 Teable 表目录里添加表后,这里会显示同步内容、工作区范围和字段映射。",teableSelectedSyncTableLabel:"当前同步表",teableTableAssignedDescription:"已配置为同步 {source}",teableTableUnassignedDescription:"还没有配置同步内容",teableSaveTableSyncSettingsAction:"保存表同步设置",teableTableSyncSettingsSaved:"表同步设置已保存。",teableFieldAutoCreateAction:"添加字段并自动映射",teableFieldAutoCreateModalTitle:"添加 Teable 字段",teableFieldAutoCreateModalDescription:"选择要添加到当前 Teable 表的 CodingNS 字段。",teableFieldAutoCreateModalSectionTitle:"选择字段",teableFieldAutoCreateModalSectionDescription:"这些字段会添加到“{table}”,并自动写入字段映射。已经存在同名字段时会直接复用。",teableFieldAutoCreateConfirmAction:"添加并自动映射",teableFieldAutoCreateSuccess:"已添加并映射 {count} 个字段。",teableFieldAutoCreateEmptyError:"请先选择要添加的字段。",teableFieldAlreadyMappedDescription:"已映射到“{field}”。",teableTablesCatalogTitle:"Teable 已有表",teableTablesCatalogDescription:"这里列出当前 Base 下已有的表,方便你给镜像同步和字段映射选目标表。",teableTablesCatalogEmptyTitle:"当前 Base 里还没有可用表",teableTablesCatalogEmptyDescription:"先到 Teable 里创建表,再回来配置同步。",teableTableInspectAction:"查看表结构",teableTableCollapseAction:"收起详情",teableTableFieldsLabel:"当前表字段",teableTableFieldsEmpty:"这张表暂时还没有字段。",teableTableFormViewsLabel:"这张表下的表单视图",teableTableFormViewsEmpty:"这张表当前还没有表单视图。",teableTableFormReadyTag:"可用于工作台",teableTableFormShareMissingTag:"未开启分享",teableTableFormCountTag:"{count} 个表单",teableTableFieldCountPending:"字段数待读取",teableTableFieldCountValue:"{count} 个字段",teableTableFormCountValue:"{count} 个表单视图",teableTablesUsageTitle:"这里主要做什么",teableTablesUsageDescription:"设置页负责配同步和字段映射;工作台里的 Teable 块才负责显示表单。",teableTablesUsageMirrorTitle:"同步配置看表",teableTablesUsageMirrorDescription:"标签、会话、代办同步到哪张 Teable 表,都是在这里按表来配。",teableTablesUsageFormTitle:"工作台块看表单",teableTablesUsageFormDescription:"真正要显示给用户填写的表单,会在工作台画布里的 Teable 块中选择。",teableSyncActionSectionTitle:"同步状态与操作",teableSyncActionSectionDescription:"这里看最近一次任务结果,也可以手动重新发起镜像同步。",teableLatestTaskTitle:"最近一次镜像同步",teableLatestTaskEmpty:"还没有镜像同步记录。",teableSyncLogsTitle:"同步日志",teableSyncLogsDescription:"这里记录手动同步和本地变化触发的同步任务,方便确认数据是否已经推送到 Teable。",teableSyncLogsRefreshAction:"刷新日志",teableSyncLogsEmptyTitle:"还没有同步日志",teableSyncLogsEmptyDescription:"手动同步或本地数据变化触发同步后,这里会显示记录。",teableSyncLogDescription:"{trigger} · {source} · {time}",teableSyncLogCounts:"新增 {created},更新 {updated},删除 {deleted},跳过 {skipped}",teableSyncLogTrigger:{manual:"手动触发",local_change:"本地变化",retry:"重试"},teableFieldMappingSectionTitle:"字段映射",teableFieldMappingSectionDescription:"把 CodingNS 的源字段手动对应到 Teable 目标表字段。同步时只会按这里的关系写入。",teableFieldMappingTargetMissingTitle:"先给这一类数据选择目标表",teableFieldMappingTargetMissingDescription:"先在“镜像”标签页为这类数据指定目标表,再回来做字段映射。",teableFieldMappingSaveAction:"保存字段映射",teableFieldMappingSaved:"字段映射已保存。",teableFieldTargetPlaceholder:"请选择目标字段",teableFieldRequired:"必填",teableFieldOptional:"可选",teableMirrorBindingReady:"镜像表已绑定到“{table}”。",teableMirrorBindingMissing:"这类数据还没有生成镜像表。",teableMirrorBindingReadyTag:"已绑定",teableMirrorBindingPendingTag:"待创建",teableRefreshAction:"刷新状态",teableSaveBindingAction:"保存连接",teableSaveSyncConfigAction:"保存推送范围",teableSyncNowAction:"立即同步",teableBindingStatus:{unbound:"未绑定",ready:"已就绪",disabled:"已关闭",config_invalid:"配置不完整"},teableTaskState:{idle:"未开始",queued:"排队中",running:"同步中",succeeded:"已完成",partial_failed:"部分失败",failed:"失败"},teableMirrorMode:{manual:"手动触发",scheduled:"定时同步(暂未开放)",event_driven:"本地变化自动同步"},teableSource:{tags:{title:"标签镜像",description:"把事务标签同步成 Teable 镜像表,给业务表单做 Link / Lookup 引用。",scopeHint:"例如 includePaths、手动筛选路径。当前后端先保存配置,不在这一轮强解释。"},sessions:{title:"会话镜像",description:"把事务会话摘要同步到 Teable,方便表单引用最近会话和上下文。",scopeHint:"例如 recent / limit 这类范围控制。当前后端先保存配置,不在这一轮强解释。"},todos:{title:"代办镜像",description:"把工作台代办同步到 Teable,方便表单直接引用当前任务。",scopeHint:"例如 open_only、状态筛选。当前后端先保存配置,不在这一轮强解释。"}},pluginManagement:"插件管理",pluginManagementDescription:"统一查看当前 Host 已扫描到的插件,并决定是否启用、停用或继续打开插件页面。",pluginManagementAction:"管理插件",pluginManagementModalTitle:"插件管理",pluginManagementModalDescription:"这里集中查看插件状态、权限边界和最近运行记录,不需要再手动拼路由。",pluginManagementModalListTitle:"插件列表",pluginManagementModalListDescription:"先选一个插件,再看它现在的状态和最近运行情况。",pluginManagementModalDetailTitle:"插件详情",pluginManagementModalDetailDescription:"这里只展示已经通过 Host 正式注册的插件信息和运行记录。",pluginManagementSelectPluginTitle:"先选一个插件",pluginManagementSelectPluginDescription:"左边选中插件后,这里会显示它的权限、动作和最近运行记录。",pluginManagementWorkspaceRequired:"只有绑定到当前工作区后,才能继续打开插件前端页面。",workspaceSessionSortModeDescription:"控制工作区里各处会话列表的默认排序,只影响当前设备。",sessionSortModeCreatedAt:"按照会话创建时间",sessionSortModeUpdatedAt:"按照会话更新时间",sessionSortModeTitle:"按照会话名称",showSystemFiles:"显示系统文件",showSystemFilesDescription:"在文件管理里显示 macOS 和 Windows 常见的系统文件,例如 .DS_Store、Thumbs.db。这个开关只影响当前设备。",serverConnection:"服务器连接",serverConnectionSectionSummary:"服务器地址与连接恢复策略",remoteAccess:"远程访问",remoteAccessSectionSummary:"通过 CodingNS Connect 或 Tailscale,从外部设备连接这台 Host。",remoteAccessNavValue:"CodingNS Connect / Tailscale",remoteAccessManageTitle:"远程访问方式",remoteAccessManageDescription:"需要从外部访问这台 Host 时,在这里选择并配置连接方式。",remoteAccessManageAction:"管理远程访问",remoteAccessModalTitle:"访问方式管理",remoteAccessModalDescription:"选择并配置你要使用的远程访问方式。",remoteAccessTabsLabel:"远程访问方式标签",remoteAccessTunnelTab:"CodingNS Connect",remoteAccessTailscaleTab:"Tailscale接入",remoteAccessFeatureDisabledValue:"未开启",abilityManagement:"能力管理",abilityManagementSectionSummary:"统一管理文档库、CLI 提供方的启用状态,以及模型配置文件的快速切换入口。",abilityManagementNavValue:"文档库 / 提供方 / 配置文件",affairsLibraryCapabilityTitle:"文档库",affairsLibraryCapabilityDescription:"该开关控制左侧文档入口,以及文档索引、标签索引等后台服务。",affairsLibraryCapabilityToggleLabel:"启用文档库",affairsLibraryCapabilityLoading:"正在更新文档库状态...",affairsLibraryCapabilityEnableSuccess:"文档库已启用。",affairsLibraryCapabilityDisableSuccess:"文档库已关闭。",affairsLibraryCapabilityLoadFailed:"文档库状态加载失败。",affairsLibraryCapabilitySaveFailed:"文档库状态保存失败。",modelManagement:"模型管理",modelManagementNavValue:"快速切换",modelManagementSectionTitle:"模型配置文件管理",providerManagement:"CLI 提供方",providerManagementSectionSummary:"控制哪些 CLI 会出现在会话、Fork、助手和 Skill 入口里。",providerManagementNavValue:"启用控制",providerManagementDescription:"统一控制这台 Host 当前允许使用的 CLI。能力矩阵、状态和启用开关都放在弹窗里查看和修改。",providerManagementManageAction:"管理 CLI 提供方",providerManagementModalTitle:"CLI 提供方管理",providerManagementModalDescription:"查看每个 CLI 在项目里的能力、当前状态,以及是否继续对外显示。",providerManagementRefresh:"刷新列表",providerManagementRefreshSuccess:"CLI 提供方列表已刷新。",providerManagementLoading:"正在读取可管理的 CLI 提供方...",providerManagementEmpty:"当前还没有可管理的 CLI 提供方。",providerManagementEmptyDescription:"等 Host 注册出可用的 CLI 提供方后,这里会自动出现。",providerManagementLoginRequired:"登录后才能管理 CLI 提供方。",providerManagementLoadFailed:"CLI 提供方列表加载失败。",providerManagementSaveFailed:"CLI 提供方状态保存失败。",providerManagementSummaryTitle:"提供方概况",providerManagementSummaryDescription:"这里先看总量,再决定要不要禁用某个 CLI。",providerManagementSummaryEnabled:"已启用",providerManagementSummaryDisabled:"已禁用",providerManagementSummaryTotal:"总数",providerManagementMatrixTitle:"能力矩阵",providerManagementMatrixDescription:"纵向是 CLI 提供方,横向是产品能力。关闭某个提供方后,它会从项目里的相关入口整体消失。",providerManagementTableProvider:"CLI 提供方",providerManagementTableStatus:"状态",providerManagementTableEnabled:"启用",providerManagementStatusEnabled:"已启用",providerManagementStatusDisabled:"已禁用",providerManagementInstallReady:"已安装",providerManagementInstallMissing:"未检测到",providerManagementInstallUnknown:"状态未知",providerManagementStateEnabled:"当前会出现在新的会话、Fork、助手和 Skill 相关入口里。",providerManagementStateDisabled:"当前已经从新的会话入口里隐藏,旧会话也会从正常列表里收起。",providerManagementStateMissing:"已经允许显示,但本地 CLI 还没准备好,等安装完成后才会真正可用。",providerManagementToggleLabel:"切换 {provider} 的启用状态",providerManagementEnableSuccess:"{provider} 已重新启用。",providerManagementDisableSuccess:"{provider} 已禁用。",providerManagementCapabilityStreaming:"流式输出",providerManagementCapabilityToolCalls:"工具调用",providerManagementCapabilityAssistant:"助手服务",providerManagementCapabilityFork:"会话 Fork",providerManagementCapabilitySkill:"Skill 使用",providerManagementCapabilityAvailable:"可用",providerManagementCapabilityUnavailable:"不可用",providerManagementImpactSessionStart:"新会话启动",providerManagementImpactFork:"会话 Fork",providerManagementImpactAssistant:"助手跟进",providerManagementImpactSkill:"Skill 新目标",providerManagementImpactEnabled:"如果现在关掉,会隐藏旧会话,并阻止 {actions}。",providerManagementImpactDisabled:"当前已经阻止 {actions};重新打开后,这些入口会重新出现。",providerManagementImpactEnabledFallback:"如果现在关掉,这个 CLI 会从项目里的新入口中一起消失。",providerManagementImpactDisabledFallback:"重新打开后,这个 CLI 会重新回到项目里的正常入口中。",channelsManagement:"通讯平台",channelsManagementSectionSummary:"统一管理外部通讯渠道、轮询账号和最近的收发流水。",channelsManagementNavValue:"账号 / 流水",channelsManagementDescription:"在这里管理通讯账号,并查看最近的消息和发送记录。",channelsManageAction:"管理通讯账号",channelsModalTitle:"通讯平台账号管理",channelsAddAccountAction:"添加通讯账号",channelsModalDescription:"先用统一账号模型接入外部通讯平台。第一阶段先把文本消息、固定 provider、polling 和 Butler control session 的映射链路接好。",channelsActionPending:"处理中...",channelsRefresh:"刷新数据",channelsRefreshSuccess:"通讯平台数据已刷新。",channelsLoading:"正在读取通讯平台配置...",channelsLoadingDetails:"正在读取最近的线程和消息...",channelsLoadFailed:"通讯平台列表加载失败。",channelsLoadDetailsFailed:"最近线程和消息加载失败。",channelsSaveFailed:"通讯账号保存失败。",channelsProbeFailed:"账号探活失败。",channelsPollFailed:"手动轮询失败。",channelsRemoveFailed:"通讯账号移除失败。",channelsCreateSuccess:"{account} 已创建。",channelsUpdateSuccess:"{account} 已保存。",channelsRemoveSuccess:"已移除通讯账号“{account}”。",channelsSelectAccountFirst:"请先选择一个已有账号,或者直接新建账号。",channelsSummaryTitle:"通讯平台概况",channelsSummaryAccounts:"账号数",channelsSummaryActive:"正常账号",channelsSummaryPlatforms:"已用平台",channelsWizardTitle:"配置向导",channelsWizardCreateDescription:"先选通讯渠道,再填这个渠道自己的配置,最后把账号绑定到固定的助手引擎。",channelsWizardEditDescription:"当前正在编辑已有账号。平台不在这里切换,改助手引擎只影响新会话,旧会话继续保留原上下文。",channelsWizardStepsTitle:"通讯账号配置步骤",channelsWizardStepPlatform:"选择渠道",channelsWizardStepConfig:"填写渠道配置",channelsWizardStepBinding:"绑定账号",channelsWizardNextToConfig:"继续填写配置",channelsWizardNextToBinding:"继续绑定账号",channelsWizardBackToPlatform:"返回选渠道",channelsWizardBackToConfig:"返回渠道配置",channelsWizardSelectPlatformHint:"先从上面选一个通讯渠道,下面才会出现对应的专用表单。",channelsWizardBindingSummary:"多会话支持",channelsPlatformsTitle:"平台能力清单",channelsPlatformsDescription:"这里按渠道卡片展示第一阶段的 polling 口径、多会话支持情况和当前限制。",channelsPlatformsEmpty:"当前没有可展示的平台能力。",channelsPlatformsEmptyDescription:"等 Host 注册出平台目录后,这里会自动显示。",channelsPlatformSummary:"接入方式:{modes};多会话:{multiSession}",channelsAccountsTitle:"通讯账号",channelsAccountsDescription:"每个账号固定绑定一个助手引擎,并固定走 polling。新会话按账号配置启动,旧会话继续保留原上下文。",channelsAccountsEmpty:"还没有通讯账号。",channelsAccountsEmptyDescription:"先添加一个通讯账号,后面收到消息后这里会开始积累线程和流水。",channelsAccountRowDescription:"{platform} · {provider} · {mode}",channelsCreateAction:"新建账号",channelsSaveAction:"保存账号",channelsResetToCreate:"切到新建",channelsCreateFormTitle:"新建通讯账号",channelsCreateFormDescription:"先把统一字段建出来。平台差异先放进补充配置 JSON,避免第一阶段表单失控。",channelsEditFormTitle:"编辑通讯账号",channelsEditFormDescription:"改 provider 后只会影响新会话,旧会话仍保留原上下文。",channelsFieldDisplayName:"账号显示名",channelsFieldDisplayNamePlaceholder:"例如:飞书值班号",channelsFieldPlatform:"通讯平台",channelsFieldPlatformDescription:"先选平台,再决定接入方式和补充配置。",channelsFieldProvider:"助手引擎",channelsFieldProviderDescription:"第一阶段只允许固定成 Codex 或 Claude Code,不能在同一外部线程里临时切换。",channelsFieldConnectionMode:"接入方式",channelsFieldConnectionModeDescription:"第一阶段六个平台统一按 polling 接入,不在这里切换别的模式。",channelsFieldStatus:"账号状态",channelsFieldStatusDescription:"先用正常、停用、异常降级这三个状态管理账号可用性。",channelsFieldConfig:"平台补充配置(JSON)",channelsFieldConfigDescription:"这里放当前表单里没覆盖到的补充字段。专用表单优先,补充 JSON 只做兜底。",channelsAdvancedConfigTitle:"补充字段(高级)",channelsAdvancedConfigDescription:"只有当前表单没覆盖的字段才放这里,例如回发地址、临时开关或实验参数。",channelsValidationDisplayName:"请先填写账号显示名。",channelsValidationPlatform:"请先选择通讯平台。",channelsValidationConnectionMode:"请先选择接入方式。",channelsValidationConfigJson:"补充配置不是合法 JSON。",channelsValidationConfigObject:"补充配置必须是 JSON 对象。",channelsValidationRequiredField:"请先填写“{field}”。",channelsValidationFeishuCredential:"飞书最少还要补一组凭证:直接填 Tenant Access Token,或者同时填 App ID 和 App Secret。",channelsConfigWechatUnavailableTitle:"个人微信(claw)不需要手填协议参数",channelsConfigWechatUnavailableDescription:"这个通道的扫码、登录态、轮询和回发都交给 Host helper 处理,这一步不用再手填私有协议参数。",channelsDetailTitle:"当前账号概况",channelsDetailDescription:"这里先看当前账号的接入状态、最近收发时间和是否需要人工补查。",channelsDetailPlatform:"平台",channelsDetailProvider:"助手引擎",channelsDetailConnectionMode:"接入方式",channelsDetailStatus:"账号状态",channelsDetailLastInbound:"最近入站",channelsDetailLastOutbound:"最近回发",channelsDetailLastError:"最近错误",channelsProbeAction:"检查连通性",channelsPollAction:"手动轮询",channelsRemoveAction:"移除账号",channelsRemoveConfirmAction:"确认移除",channelsRemoveConfirmDescription:"移除后会同时清理这个账号下的线程映射、入站消息和回发记录。这个操作不能撤回。",channelsWebhookHint:"这个账号是 webhook 模式,不需要手动轮询。",channelsConnectionModeFixedHint:"当前阶段固定按 polling 建模;如果以后换模式,会单独升级账号配置规则。",channelsThreadsTitle:"线程映射",channelsThreadsDescription:"最近 {count} 条线程映射,按 external conversation key 关联到 Butler control session。",channelsThreadsEmpty:"还没有线程映射。",channelsThreadsEmptyDescription:"收到第一条外部消息后,这里会自动出现。",channelsEventsTitle:"入站消息",channelsEventsDescription:"最近 {count} 条入站消息,方便排查消息是否被 Host 接住并成功分发。",channelsEventsEmpty:"还没有入站消息。",channelsEventsEmptyDescription:"等渠道开始真正拉到文本消息后,这里会出现记录。",channelsDeliveriesTitle:"回发记录",channelsDeliveriesDescription:"最近 {count} 条回发记录,用来确认 Butler 首条文本有没有成功送回外部平台。",channelsDeliveriesEmpty:"还没有回发记录。",channelsDeliveriesEmptyDescription:"当 Butler 产出首条文本并触发回发后,这里才会有记录。",channelsConnectionModeWebhook:"Webhook",channelsConnectionModePolling:"Polling",channelsConnectionModeBridge:"Bridge",channelsMultiSessionSupported:"支持多会话",channelsMultiSessionLimited:"有限支持",channelsStatusActive:"正常",channelsStatusDisabled:"已停用",channelsStatusDegraded:"异常降级",channelsThreadStatusActive:"活跃",channelsThreadStatusClosed:"已关闭",channelsThreadStatusFailed:"失败",channelsEventStatusReceived:"已接收",channelsEventStatusDispatched:"已分发",channelsEventStatusReplied:"已回复",channelsEventStatusFailed:"失败",channelsEventStatusIgnored:"已忽略",channelsDeliveryStatusSent:"已发出",channelsDeliveryStatusFailed:"失败",channelsDeliveryStatusSkipped:"已跳过",channelsThreadSummary:"{status} · 会话键:{conversationKey}",channelsEventSummary:"{status} · 会话键:{conversationKey}",channelsDeliverySummary:"{status} · 最近一条回发文本",channelsMetaCreatedAt:"创建时间",channelsMetaUpdatedAt:"更新时间",channelsMetaReceivedAt:"接收时间",channelsMetaExternalUser:"外部用户",channelsMetaEventId:"外部事件",channelsMetaProviderRef:"平台回执",channelsMetaError:"错误",channelsTextFallback:"空文本",channelsTimeUnknown:"暂无",channelsWechatBindingTitle:"微信绑定",channelsWechatBindingDescription:"这个账号会通过 Host 托管的 helper 完成扫码登录、轮询收信和消息回发。",channelsWechatBoundDescription:"微信账号已经绑定成功。现在可以继续做探活、手动轮询和后续会话桥接。",channelsWechatCreateDescription:"先给这个微信账号起个名字。创建完成后,下一步就在详情区生成二维码并扫码绑定。",channelsWechatRuntimeRequiredTitle:"当前还不能直接绑定个人微信",channelsWechatRuntimeRequiredDescription:"当前环境没有启用微信 helper,所以这里只能看到账号基础信息。启用 helper 后,这里会切回真实扫码绑定。",channelsWechatPendingTitle:"这个账号还没完成绑定",channelsWechatPendingDescription:"先完成扫码绑定,绑定成功后才会出现轮询、回发和最近记录。",channelsWechatBeginBindingAction:"开始绑定",channelsWechatContinueBindingAction:"继续绑定",channelsWechatStartLoginAction:"生成二维码",channelsWechatRestartBindingAction:"重新生成二维码",channelsWechatRefreshLoginAction:"刷新绑定状态",channelsWechatLogoutAction:"清除绑定",channelsWechatBindingModalTitle:"扫描二维码绑定微信",channelsWechatBindingModalDescription:"请用微信扫描下面的二维码。扫码后回到这里,点“刷新绑定状态”。",channelsWechatBindingModeValue:"扫码绑定",channelsWechatLoginStatus:"绑定状态",channelsWechatLoginStatusNotLoggedIn:"未绑定",channelsWechatLoginStatusWaitingScan:"等待扫码",channelsWechatLoginStatusScanConfirmed:"已扫码,待确认",channelsWechatLoginStatusActive:"已绑定",channelsWechatLoginStatusExpired:"二维码已过期",channelsWechatQrHint:"扫码成功后,点“刷新绑定状态”同步结果。",channelsWechatQrAlt:"个人微信绑定二维码",channelsWechatOpenQrLinkAction:"打开绑定二维码",channelsWechatQrRawTitle:"查看二维码原始内容",channelsWechatQrRawDescription:"上游返回的原始二维码内容会先保存在这里,方便排查扫码链路。",channelsWechatQrEmpty:"还没有绑定二维码",channelsWechatQrEmptyDescription:"先点上面的“生成二维码”,再用微信扫码完成绑定。",channelsConfigFieldDingtalkAppKey:"钉钉 AppKey",channelsConfigFieldDingtalkAppKeyDescription:"后续接真实拉取接口时,会用这个字段识别钉钉应用。",channelsConfigFieldDingtalkAppKeyPlaceholder:"填写钉钉应用 AppKey",channelsConfigFieldDingtalkAppSecret:"钉钉 AppSecret",channelsConfigFieldDingtalkAppSecretDescription:"建议只填正式值班账号的密钥,避免把测试凭证混进生产轮询账号。",channelsConfigFieldDingtalkAppSecretPlaceholder:"填写钉钉应用 AppSecret",channelsConfigFieldDingtalkRobotCode:"机器人编码",channelsConfigFieldDingtalkRobotCodeDescription:"如果后续消息要回发到固定机器人,可以先把机器人编码记在这里。",channelsConfigFieldDingtalkRobotCodePlaceholder:"例如:dingxxxxxxxx",channelsConfigFieldFeishuAppId:"飞书 App ID",channelsConfigFieldFeishuAppIdDescription:"如果你不打算直接填 Tenant Access Token,这里要和 App Secret 一起填写。",channelsConfigFieldFeishuAppIdPlaceholder:"填写飞书应用 App ID",channelsConfigFieldFeishuAppSecret:"飞书 App Secret",channelsConfigFieldFeishuAppSecretDescription:"如果你不打算直接填 Tenant Access Token,这里要和 App ID 一起填写。",channelsConfigFieldFeishuAppSecretPlaceholder:"填写飞书应用 App Secret",channelsConfigFieldFeishuTenantAccessToken:"Tenant Access Token",channelsConfigFieldFeishuTenantAccessTokenDescription:"如果你已经能稳定拿到 tenant_access_token,直接填这里就行,不用再强制填 App ID 和 App Secret。",channelsConfigFieldFeishuTenantAccessTokenPlaceholder:"填写飞书 tenant_access_token",channelsConfigFieldFeishuChatId:"目标会话 Chat ID",channelsConfigFieldFeishuChatIdDescription:"必填。第一阶段先固定一个群或会话,Host 才知道去哪里拉消息和回发文本。",channelsConfigFieldFeishuChatIdPlaceholder:"例如:oc_xxx 或 chat_xxx",channelsConfigFieldWechatBaseUrl:"claw 服务地址",channelsConfigFieldWechatBaseUrlDescription:"Host 会通过这个地址去拉取消息和发送回复。这里必须能从 Host 所在机器访问到。",channelsConfigFieldWechatBaseUrlPlaceholder:"例如:http://127.0.0.1:8787",channelsConfigFieldWechatBridgeToken:"claw 访问令牌",channelsConfigFieldWechatBridgeTokenDescription:"如果你的 claw transport 有访问令牌,这里填进去做最基本的校验。",channelsConfigFieldWechatBridgeTokenPlaceholder:"填写 claw transport token",channelsConfigFieldWechatPollPath:"拉取路径",channelsConfigFieldWechatPollPathDescription:"默认会用 `/poll`。如果你的 transport 路径不同,可以在这里改。",channelsConfigFieldWechatPollPathPlaceholder:"默认 /poll",channelsConfigFieldWechatSendPath:"发送路径",channelsConfigFieldWechatSendPathDescription:"默认会用 `/send`。如果你的 transport 路径不同,可以在这里改。",channelsConfigFieldWechatSendPathPlaceholder:"默认 /send",channelsConfigFieldTelegramBotToken:"Telegram Bot Token",channelsConfigFieldTelegramBotTokenDescription:"Telegram 真实轮询和回发都要靠这个 token,没填就不能工作。",channelsConfigFieldTelegramBotTokenPlaceholder:"填写 Telegram Bot Token",channelsConfigFieldSlackBotToken:"Slack Bot Token",channelsConfigFieldSlackBotTokenDescription:"必填。Slack 轮询读消息和回发文本都靠这个 token。",channelsConfigFieldSlackBotTokenPlaceholder:"填写 Slack Bot Token",channelsConfigFieldSlackAppToken:"Slack App Token",channelsConfigFieldSlackAppTokenDescription:"当前最少可用配置不强制要它。只有你的 Slack 应用确实额外要求时再填写。",channelsConfigFieldSlackAppTokenPlaceholder:"填写 Slack App Token",channelsConfigFieldSlackChannelId:"频道 ID",channelsConfigFieldSlackChannelIdDescription:"必填。第一阶段先固定一个频道,先把轮询和文本回发链路打通。",channelsConfigFieldSlackChannelIdPlaceholder:"例如:C0123456789",channelsConfigFieldDiscordBotToken:"Discord Bot Token",channelsConfigFieldDiscordBotTokenDescription:"必填。Discord 轮询读消息和回发文本都要靠这个 bot token。",channelsConfigFieldDiscordBotTokenPlaceholder:"填写 Discord Bot Token",channelsConfigFieldDiscordApplicationId:"Application ID",channelsConfigFieldDiscordApplicationIdDescription:"当前最少可用配置不强制要它。只有你的应用权限配置确实依赖它时再填写。",channelsConfigFieldDiscordApplicationIdPlaceholder:"填写 Discord Application ID",channelsConfigFieldDiscordGuildId:"Guild ID",channelsConfigFieldDiscordGuildIdDescription:"必填。先固定一个服务器,后面的 thread 子分支会在这个服务器下工作。",channelsConfigFieldDiscordGuildIdPlaceholder:"填写 Discord Guild ID",channelsConfigFieldDiscordChannelId:"频道 ID",channelsConfigFieldDiscordChannelIdDescription:"必填。先固定一个频道,后面的 thread 子分支会挂在这个频道下面。",channelsConfigFieldDiscordChannelIdPlaceholder:"填写 Discord Channel ID",channelsConfigChecklistTitle:"这一步最少要准备什么",channelsConfigChecklistFeishuSummary:"飞书这一版先按固定会话做 polling,最少要给 Host 一个目标会话和一套可用凭证。",channelsConfigChecklistFeishuItemCredential:"凭证二选一:直接填 Tenant Access Token,或者同时填 App ID 和 App Secret。",channelsConfigChecklistFeishuItemChat:"必须填目标会话 Chat ID,不然 Host 不知道要跟哪一个群或会话对接。",channelsConfigChecklistFeishuItemScope:"先按文本消息打通,不处理图片、文件、语音和卡片。",channelsConfigChecklistSlackSummary:"Slack 这一版先固定一个频道做 polling,先把读消息和回发文本跑通。",channelsConfigChecklistSlackItemToken:"必须填 Bot Token,缺它就没法拉消息也没法发回复。",channelsConfigChecklistSlackItemChannel:"必须填频道 ID,当前账号先固定绑定到一个频道。",channelsConfigChecklistSlackItemScope:"第一阶段只处理文本消息,thread 子分支暂不在 Slack 里实现。",channelsConfigChecklistDiscordSummary:"Discord 这一版最少要固定服务器和频道,后面的 thread 子分支会落在这个范围里。",channelsConfigChecklistDiscordItemToken:"必须填 Bot Token,轮询读消息和回发文本都要靠它。",channelsConfigChecklistDiscordItemGuild:"必须填 Guild ID,先把账号固定到一个服务器。",channelsConfigChecklistDiscordItemChannel:"必须填频道 ID,后面的 thread 子分支会挂在这个频道下面。",modelManagementTitle:"模型快速切换",modelManagementDescription:"这里不新增也不编辑预设,只把 cc-switch 已有预设图形化展示出来,方便你一键切换。",modelManagementRefresh:"刷新模型",modelManagementRefreshSuccess:"模型预设列表已刷新。",modelManagementLoadFailed:"模型预设加载失败。",modelManagementScannedAt:"最近扫描",modelManagementScannedAtUnknown:"暂未扫描",modelManagementCurrentProfile:"当前配置文件",modelManagementCurrentModel:"当前模型",modelManagementCurrentPreset:"当前预设",modelManagementModelUnknown:"未识别",modelManagementPresetMissing:"未设置",modelManagementCurrentTag:"当前",modelManagementOpenSwitcher:"切换配置",modelManagementModalTitle:"供应商配置切换",modelManagementModalDescription:"这里按应用查看 cc-switch 已有配置文件,并切换当前启用项。",modelManagementTabsLabel:"模型应用标签",modelManagementSwitchAction:"切换",modelManagementSwitchSuccess:"{app} 已切换到 {preset}。",modelManagementOptionsEmpty:"当前没有可切换的预设。",modelManagementStatusReady:"可切换",modelManagementStatusUnconfigured:"未配置",modelManagementStatusUnavailable:"未安装 cc-switch-cli",modelManagementStatusError:"读取失败",skills:"Skills",skillsSectionSummary:"读取并同步各个 CLI 自己的本地 skill,不做市场,不接远端仓库。",skillsNavValue:"本地同步",skillManagerTitle:"本地 Skill 管理",skillManagerDescription:"统一读取 Codex、Claude Code、Gemini、OpenCode 的 skill 目录,支持导入未纳管项并重新同步。",skillSummaryManagedSkills:"我的技能",skillSummaryManagedEntries:"已生效",skillSummaryUnmanagedEntries:"未纳管目录",skillSummaryConflictedEntries:"待处理",skillSummaryAssistantRuntimeEntries:"助手专用目录",skillSummaryDiagnostics:"提醒",skillManageAction:"技能配置",skillConfigModalTitle:"技能配置",skillConfigModalDescription:"在这里查看你的技能、系统自带技能和需要处理的项目。",skillCreateAction:"添加技能",skillCreateModalTitle:"添加技能",skillCreateModalDescription:"把新的 SKILL.md 纳管进来。文件上传和粘贴文本都走同一套校验与纳管流程。",skillCreateSourceTabsLabel:"添加方式",skillCreateSourceFile:"选择文件",skillCreateSourcePaste:"粘贴文本",skillCreateSubmitAction:"添加",skillRefresh:"刷新",skillRefreshSuccess:"技能列表已刷新。",skillScannedAt:"最近扫描",skillUploadSectionTitle:"上传 Skill",skillUploadSectionDescription:"选择一个 SKILL.md 文件,先选它属于工作区还是助手运行时,再做基础校验和轻量纠正并纳管。",skillUploadPickAction:"选择 SKILL.md",skillUploadSubmitAction:"上传并纳管",skillUploadEmpty:"当前还没有选择要上传的 SKILL.md 文件。",skillUploadPickedFile:"已选文件",skillUploadScopeLabel:"作用域",skillUploadScopeWorkspace:"工作区 Skill",skillUploadScopeAssistant:"助手专用 Skill",skillUploadDirectoryLabel:"目录名",skillUploadDirectoryPlaceholder:"例如 team-helper",skillUploadDirectoryHint:"用于生成纳管目录和同步目标目录。默认按文件名或标题自动生成,通常不用手动改。",skillUploadDirectoryInvalid:"目录名不合法,只允许字母、数字、点、下划线和短横线。",skillUploadTargetsLabel:"应用 CLI",skillPasteLabel:"粘贴 SKILL 内容",skillPastePlaceholder:"直接粘贴完整的 SKILL.md 内容",skillPasteEmpty:"当前还没有可纳管的 SKILL 内容。",skillUploadDirectoryRequiredNote:"当前文件名推不出合法目录名,请手动补一个。",skillUploadTargetRequired:"至少选择一个目标 CLI。",skillUploadHeadingNote:"当前 markdown 缺少一级标题,纳管时会自动补一个。",skillUploadNormalizedNote:"已按系统规则预处理空白和换行。",skillUploadReadFailed:"读取上传的 SKILL.md 失败。",skillUploadContentEmpty:"上传的 SKILL.md 不能为空。",skillUploadSuccess:"已添加 {name}。",skillManagedListTitle:"我的技能",skillManagedEmpty:"你还没有添加任何技能。",skillManagedItemDescription:"已添加到 {targets}。",skillManagedItemNoTarget:"这项技能还没有应用到任何客户端。",skillUnmanagedListTitle:"待添加技能",skillUnmanagedEmpty:"目前没有新的技能可添加。",skillUnmanagedItemDescription:"已在 {target} 中发现,你可以把它添加到列表。",skillUnmanagedItemDisabledDescription:"已在 {target} 中发现,但这个目标当前已禁用,暂时不能继续添加。",skillAssistantRuntimeListTitle:"助手内置技能",skillAssistantRuntimeListDescription:"这些技能由系统自动提供,只给助手自己使用。",skillAssistantRuntimeEmpty:"当前没有助手内置技能。",skillAssistantRuntimeItemDescription:"这是系统自带技能,你不需要手动处理。",skillAssistantRuntimeUsedBy:"可用于",skillAssistantRuntimeSourcePath:"内置来源路径",skillConflictedListTitle:"待处理",skillConflictedEmpty:"当前没有需要处理的项目。",skillConflictedItemDescription:"{target} 里的这项内容需要处理。",skillConflictedItemDisabledDescription:"{target} 里的这项内容还保留着,但这个目标当前已禁用。",skillDiagnosticsTitle:"提醒",skillDiagnosticsEmpty:"当前没有新的提醒。",skillDiagnosticTargetMissingTitle:"{target} 还没准备好",skillDiagnosticTargetMissingDetail:"当前还没有找到 {target} 的技能目录。",skillDiagnosticReadFailedTitle:"{target} 暂时不可用",skillDiagnosticReadFailedDetail:"暂时无法读取 {target} 的技能信息,请稍后再试。",skillDiagnosticSyncMissingTitle:"{target} 需要重新应用",skillDiagnosticSyncMissingDetail:"有技能还没有在 {target} 中生效。",skillDiagnosticGenericTitle:"{target} 需要留意",skillDiagnosticGenericDetail:"有一项内容暂时没准备好,可以稍后刷新再看。",skillDirectoryName:"目录名",skillSsotPath:"统一存储目录",skillSourceCli:"来源 CLI",skillDirectoryPath:"目录路径",skillImportAction:"添加",skillImportSuccess:"已添加 {name},并应用到 {target}。",skillSyncAction:"重新应用",skillSyncSuccess:"已重新应用 {name}。",skillSyncTargetMissing:"这项技能还没有应用目标,暂时不能重新应用。",skillSyncTargetDisabled:"这项技能当前只剩已禁用目标,先重新启用对应 provider 再继续。",skillLoadFailed:"Skill 概况加载失败。",skillOfficeTemplateCreated:"文档模板已创建。",skillOfficeTemplateUpdated:"文档模板已更新。",skillOpsTargetCreated:"SSH 主机已创建。",skillOpsTargetUpdated:"SSH 主机已更新。",skillOpsApprovalApproved:"运维审批已批准。",skillOpsApprovalRejected:"运维审批已拒绝。",skillTargetCodex:"Codex",skillTargetClaudeCode:"Claude Code",skillTargetGemini:"Gemini",skillTargetOpenCode:"OpenCode",skillBindingPending:"准备中",skillBindingSynced:"可用",skillBindingFailed:"暂不可用",skillBindingConflicted:"需要处理",skillUploadTargetDisabled:"当前可选的 Skill 目标都已经被禁用,先去 provider 设置里重新启用一个。",skillTargetDisabledTag:"已禁用",skillTagAssistantOnly:"仅助手使用",skillTagWorkspaceSessionOnly:"工作区会话使用",securityPrivacy:"安全与隐私",securityPrivacySectionSummary:"会话权限、风险边界与默认授权策略",softwareUpdate:"软件更新",softwareUpdateSectionSummary:"服务端和客户端版本",updateOneClickValue:"一次检查",updateOneClickTitle:"统一更新",updateOneClickDescription:"先检查服务端和桌面端版本,再按顺序安装可用更新。",updateOptions:"更新选项",releaseChannel:"更新通道",releaseChannelDescription:"决定你会收到稳定版还是开发版更新",releaseChannelStable:"稳定版",releaseChannelBeta:"开发版",betaChannelConsentTitle:"切换到开发版",betaChannelConsentDescription:"开发版会比稳定版更早拿到新功能,但可能不够稳定。",betaChannelConsentRisk1:"开发版可能包含尚未完全验证的变更",betaChannelConsentRisk2:"你可能遇到未知 bug、兼容问题或稳定性下降",betaChannelConsentCheckbox:"我已了解开发版可能不稳定,仍要切换到开发版",betaChannelConsentConfirm:"确认切换",updateInstallAll:"安装全部更新",updateCheckFailed:"检查更新失败",updateInstallingSequential:"正在准备安装更新",updateInstallingServerFirst:"正在更新服务端",updateInstallingClientNext:"正在更新桌面端",updateBothReady:"发现服务端和桌面端新版本",updateServerReadyOnly:"发现服务端新版本",updateClientReadyOnly:"发现桌面端新版本",updateAllUpToDate:"当前已是最新版本",updateCheckIncomplete:"部分更新信息暂时无法获取,请稍后重试",updateServerReadyClientCheckFailed:"发现服务端新版本,桌面端信息暂时无法获取",updateClientReadyServiceCheckFailed:"发现桌面端新版本,服务端信息暂时无法获取",serverAddress:"服务器地址",serverDescription:"客户端的登录、接口请求和实时连接都通过这个 Host 入口工作;前端界面资源由应用自身携带。",serverRelayTunnelProfileTitle:"当前 Host 的 CodingNS Connect 入口",serverRelayTunnelProfileDescription:"给当前保存的 Host profile 指定 CodingNS Connect 入口。开启后,客户端会通过 CodingNS Connect 域名和控制站点建立端到端加密连接,而不是直接请求这个地址。",serverRelayTunnelEnabled:"通过 CodingNS Connect 连接",serverRelayTunnelUsageHint:"服务器地址建议填写这台 Host 的公开入口地址,例如 https://demo.codingns.example 。",serverRelayTunnelDomain:"CodingNS Connect 域名",serverRelayTunnelDomainPlaceholder:"例如:demo.codingns.example",serverRelayTunnelControlBaseUrl:"控制站点地址",serverRelayTunnelControlBaseUrlPlaceholder:"例如:https://control.codingns.example",relayTunnelServerAddressDescription:"默认使用官方 CodingNS Connect 地址;如果你明确知道当前控制站地址,也可以在高级设置里手动覆盖。",relayTunnelServerAddressHint:"这里只改 CodingNS Connect 控制站点地址,用来覆盖登录、绑定和流量查询使用的站点,不影响当前 Host 的本地 API 地址。",relayTunnelStatus:"CodingNS Connect 状态",relayTunnelDescription:"通过 CodingNS Connect,让外部设备安全连接到这台 Host。",relayTunnelMasterSwitchLabel:"启用 CodingNS Connect",relayTunnelActivationHint:"开启后才会检查 CodingNS Connect 状态,并允许这台 Host 接入公网访问。",relayTunnelPhase:"当前状态",relayTunnelDomain:"访问地址",relayTunnelUnbound:"还没有绑定",relayTunnelTrafficRemaining:"剩余流量",relayTunnelHostFingerprint:"Host 指纹",relayTunnelTrustBoundaryNotice:"CodingNS Connect 只负责转发加密后的流量,无法看到你和 Host 之间的通信内容。",relayTunnelRecentError:"最近错误:{message}",relayTunnelAccessTitle:"连接设置",relayTunnelAccessDescription:"先登录 CodingNS Connect 账号,再打开开关把这台设备接入公网访问。",relayTunnelLearnService:"了解 CodingNS Connect",relayTunnelWizardTitle:"远程访问向导",relayTunnelWizardDescription:"按下面三步完成账号登录、主机名确认和 CodingNS Connect 启动,收住以后就能稳定从外部访问这台 Host。",relayTunnelStatusErrorTitle:"暂时无法读取远程访问状态",relayTunnelStatusNetworkError:"当前连不上这台 Host({address}),远程访问状态可能不是最新的。请先确认服务器地址、端口和网络连接。",relayTunnelStepPending:"待完成",relayTunnelStepCurrent:"进行中",relayTunnelStepDone:"已完成",relayTunnelStepLocked:"先完成上一步,这一步才会开放。",relayTunnelStepLoginTitle:"登录账号",relayTunnelStepLoginDescription:"先连接你的 CodingNS Connect 账号,后续的主机名检查和流量读取都依赖这个账号。",relayTunnelStepLoginConnected:"账号已经连接,可以继续下一步。",relayTunnelStepHostLabelTitle:"设置主机名",relayTunnelStepHostLabelDescription:"填写你以后要访问的四级域名前缀,并先检查这个名称现在能不能用。",relayTunnelStepStartTitle:"启动 CodingNS Connect",relayTunnelStepStartDescription:"前两步都完成后,再把当前 Host 正式接入 CodingNS Connect。",relayTunnelStepStartReady:"主机名已经确认,可以启动 CodingNS Connect 了。",relayTunnelStartAction:"启动 CodingNS Connect",relayTunnelLoginErrorTitle:"登录 CodingNS Connect 账号失败",relayTunnelAdvancedSettings:"高级设置",relayTunnelAdvancedSettingsHide:"收起高级设置",relayTunnelAdvancedSettingsDescription:"默认使用官方 CodingNS Connect 地址。只有在你明确知道当前控制站地址时,才需要在这里覆盖。",relayTunnelLoginNetworkError:"登录请求没有发出去,因为当前连不上这台 Host({address})。请先确认服务器地址和网络连接,再重新尝试。",relayTunnelReadyTitle:"远程访问已开启",relayTunnelReadyDescription:"当前配置已经收住。这里仅保留访问地址、流量信息和维护动作。",relayTunnelAccessUrlLabel:"远程访问地址",relayTunnelCopyAccessUrl:"复制地址",relayTunnelOpenAccessUrl:"打开页面",relayTunnelAccessUrlCopied:"访问地址已复制。",relayTunnelCopyAccessUrlFailed:"访问地址复制失败。",relayTunnelOpenAccessUrlFailed:"访问地址打开失败。",relayTunnelClientRouteLabel:"当前客户端链路",relayTunnelClientRouteAddressLabel:"当前客户端地址",relayTunnelClientRouteHintRelay:"当前客户端还在通过 CodingNS Connect 连接这台 Host;如果系统确认本地地址可达,会自动切到更省流量的直连链路。",relayTunnelClientRouteHintRelayProbing:"正在检查本地可直连地址。检查完成后,会自动切到更省流量的链路。",relayTunnelClientRouteHintLan:"当前客户端已经切到局域网直连,这条链路更省流量;远程访问地址仍然可以继续给外部设备使用。",relayTunnelClientRouteHintLoopback:"当前客户端直接连到这台设备的本机地址,不经过 CodingNS Connect。",relayTunnelClientRouteHintTailscale:"当前客户端已经切到 Tailscale 地址,不经过 CodingNS Connect。",relayTunnelClientRouteHintDirect:"当前客户端直接请求这个 Host 地址,不经过 CodingNS Connect。",relayTunnelReconnectAction:"重新连接",relayTunnelManageAccountAction:"管理账号",relayTunnelDisconnectDeviceAction:"注销设备",relayTunnelEnableToggleLabel:"启用 CodingNS Connect",relayTunnelConfigTitle:"CodingNS Connect 站点配置",relayTunnelConfigDescription:"这里填写 CodingNS Connect 接入地址和控制面的地址。保存后,下面的登录、绑定和流量操作都会走这里。",relayTunnelConfigErrorTitle:"服务地址保存失败",relayTunnelConfigNetworkError:"新的服务地址还没有保存到这台 Host,因为当前连不上它({address})。请先确认服务器地址和网络连接。",relayTunnelRelayBaseUrl:"CodingNS Connect 接入地址",relayTunnelControlBaseUrl:"控制站点地址",relayTunnelSaveConfig:"保存配置",relayTunnelRefresh:"刷新状态",relayTunnelAccountTitle:"CodingNS Connect 账号登录",relayTunnelAccountDescription:"使用 CodingNS Connect 账号登录后,可以绑定当前 Host 并查看剩余流量。",relayTunnelAccountEmail:"邮箱",relayTunnelAccountEmailPlaceholder:"输入你的邮箱",relayTunnelAccountPassword:"密码",relayTunnelAccountPasswordPlaceholder:"输入你的密码",relayTunnelLoginAccount:"登录",relayTunnelLoggedInAs:"当前已登录:{email}",relayTunnelConnectedBannerTitle:"账号已连接",relayTunnelConnectedBannerDescription:"现在可以打开 CodingNS Connect 开关,让外部设备访问这台 Host。",relayTunnelConnectedBannerActiveTitle:"CodingNS Connect 已开启",relayTunnelConnectedBannerActiveDescription:"这台设备已经可以通过 CodingNS Connect 从外部访问。",relayTunnelConnectedDevice:"当前设备:{name}",relayTunnelBoundDomain:"当前访问地址:{domain}",relayTunnelBindTitle:"绑定当前 Host",relayTunnelBindDescription:"绑定时会先读取当前 Host 的长期公钥,再把这台机器登记到 CodingNS Connect 站点。",relayTunnelHostLabelTitle:"设备名称",relayTunnelHostLabelDescription:"登录成功后,在这里填写你将来要使用的四级域名前缀,并检查这个名称当前能不能使用。",relayTunnelHostLabel:"Host 名称",relayTunnelHostLabelPlaceholder:"填写前缀",relayTunnelHostLabelSuffix:".channel.codingns.com",relayTunnelHostLabelCheck:"检查名称",relayTunnelHostLabelChecking:"正在检查这个名称是否可用。",relayTunnelHostLabelAvailable:"名称可用,公开访问地址将会是 {domain}",relayTunnelHostLabelReserved:"这个名称会命中保留前缀,请换一个名称。",relayTunnelHostLabelOccupied:"这个名称已经被占用,请换一个名称。",relayTunnelHostLabelUnavailable:"暂时无法确认这个名称是否可用,请稍后重试。",relayTunnelHostLabelRequired:"请先填写设备名称。",relayTunnelBindAction:"登录并绑定 Host",relayTunnelActionsTitle:"CodingNS Connect 开关",relayTunnelActionsDescription:"绑定完成后,可以在这里启用、停用或解绑 CodingNS Connect。",relayTunnelEnable:"启用 CodingNS Connect",relayTunnelDisable:"停用 CodingNS Connect",relayTunnelUnbind:"断开此设备",relayTunnelWalletTitle:"流量钱包",relayTunnelWalletDescription:"这里显示控制站点记录的总流量、已用流量和剩余额度。",relayTunnelTrafficGranted:"总流量",relayTunnelTrafficUsed:"已用流量",relayTunnelPackagesTitle:"流量套餐",relayTunnelPackagesDescription:"选择一个套餐后会跳转到官方支付页完成付款,支付成功后自动发放到当前账号钱包。",relayTunnelFeaturedPackage:"推荐",relayTunnelBuyPackage:"购买流量",relayTunnelOrdersTitle:"最近订单",relayTunnelOrdersDescription:"这里只显示最近几笔套餐订单,方便确认支付和到账状态。",relayTunnelOrderPending:"待支付",relayTunnelOrderPaid:"已支付",relayTunnelOrderExpired:"已过期",relayTunnelOrderFailed:"支付失败",relayTunnelControlBaseUrlRequired:"请先填写控制站点地址。",relayTunnelAccountRequired:"请先输入 CodingNS Connect 账号邮箱和密码。",relayTunnelIdentityUnavailable:"当前 Host 身份公钥还没有准备好,请稍后重试。",relayTunnelLoadFailed:"CodingNS Connect 状态读取失败。",relayTunnelPhaseDisabled:"未启用",relayTunnelPhaseBlockedUninitialized:"实例未初始化,已阻断暴露",relayTunnelPhaseUnbound:"还没有绑定",relayTunnelPhaseBinding:"正在绑定",relayTunnelPhaseConnecting:"正在连接",relayTunnelPhaseRunning:"运行中",relayTunnelPhaseQuotaExhausted:"流量耗尽",relayTunnelPhaseError:"状态异常",tailscaleBrand:"Tailscale",tailscaleSectionTitle:"Tailscale 接入",tailscaleSectionDescription:"让这台 Host 通过 Tailscale 在你的设备间可访问。",tailscaleMasterSwitchLabel:"启用 Tailscale",tailscaleActivationHint:"开启后才会检查 Tailscale 状态,并允许继续配置和绑定账号。",tailscaleCurrentState:"当前状态",tailscaleSwitchLabel:"启用开关",tailscaleStatusIndicator:"状态指示器",tailscaleServerAddress:"服务器地址",tailscaleAccountName:"账号名",tailscaleIpAddress:"IP 地址",tailscaleConfigure:"配置",tailscaleConfigModalTitle:"配置 Tailscale",tailscaleConfigModalDescription:"修改接入参数",tailscaleControlServer:"Control Server",tailscaleControlServerDescription:"留空时使用默认 control server。",tailscaleControlServerPlaceholder:"留空表示使用默认 control server",tailscaleHostname:"设备名称",tailscaleHostnameDescription:"可选。",tailscaleHostnamePlaceholder:"例如:codingns-host",tailscaleReachableBaseUrl:"外部访问地址",tailscaleTailnetFqdn:"Tailnet FQDN",tailscaleTailnetIpv4:"Tailnet IPv4",tailscaleTailnetIpv6:"Tailnet IPv6",tailscaleDetailAddresses:"详细地址",tailscaleRefresh:"刷新状态",tailscaleInstallAction:"安装 Tailscale",tailscaleInstallOpenFailed:"打开 Tailscale 安装页面失败。",tailscaleEnable:"启用 Tailscale",tailscaleDisable:"停用 Tailscale",tailscaleLogin:"开始绑定",tailscaleLogout:"解绑账号",tailscaleUnavailable:"暂不可用",tailscaleLoadFailed:"Tailscale 状态读取失败。",tailscalePhaseDisabled:"未启用",tailscalePhaseBlockedUninitialized:"实例未初始化,已阻断暴露",tailscalePhaseStarting:"正在启动",tailscalePhaseNeedsLogin:"等待绑定账号",tailscalePhaseRunning:"运行中",tailscalePhaseStopping:"正在停止",tailscalePhaseError:"状态异常",tailscaleOverviewDisabled:"当前还没有启用远程访问。",tailscaleOverviewBlockedUninitialized:"先完成初始化,再启用远程访问。",tailscaleOverviewStarting:"正在接入 Tailscale,请稍等。",tailscaleOverviewNeedsLogin:"启用完成后,还需要绑定账号。",tailscaleOverviewRunning:"当前实例已经可以通过 Tailscale 访问。",tailscaleOverviewStopping:"正在关闭远程访问。",tailscaleOverviewError:"远程访问状态异常,请先刷新或重新配置。",autoReconnect:"自动重连",autoReconnectDescription:"当 Host 短暂不可达时,自动尝试恢复 HTTP 和 WebSocket 链路。",autoCheckUpdate:"自动检查更新",autoCheckUpdateDescription:"发现客户端新版本时提醒你处理。",autoDownloadUpdate:"自动下载更新包后提示更新",autoDownloadUpdateDescription:"发现客户端新版本后先下载资源,下载完成再提示你安装。",defaultPermissionMode:"默认会话权限",defaultPermissionModeDescription:"控制新建和继续会话时默认使用的工具权限。完整权限会关闭询问,只适合你已经信任当前项目和运行环境时使用。",authDeviceManagement:"登录设备管理",authDeviceManagementDescription:"查看当前设备、其他在线设备和最近 10 条登录记录,并在主设备上按设备逐个退出其他在线设备。",authDeviceEntryHint:"点击“设备管理”后,可在弹窗中查看当前设备、其他在线设备和最近登录记录。",authDeviceOpenManager:"设备管理",authDeviceCurrentTitle:"当前设备",authDeviceOthersTitle:"其他在线设备",authDeviceRecentTitle:"最近登录记录",authDeviceCurrentTag:"当前设备",authDevicePrimaryTag:"主设备",authDeviceLegacyTag:"旧登录态",authDeviceLegacyHiddenHint:"检测到 {count} 条兼容旧登录态记录,默认已隐藏。",authDeviceLegacyReveal:"查看兼容记录",authDeviceLegacyHide:"隐藏兼容记录",authDeviceLegacyDevicesTitle:"兼容旧在线记录",authDeviceLegacyRecentTitle:"兼容旧登录记录",authDeviceLegacyLabel:"未知设备(旧登录态)",authDeviceClientDesktop:"Desktop",authDeviceClientWeb:"Web",authDeviceClientIos:"iOS",authDeviceClientAndroid:"Android",authDeviceClientUnknown:"未知设备",authDeviceCurrentEmpty:"当前登录态还没有可识别的设备信息,请重新登录后重试。",authDeviceOthersEmpty:"当前没有其他在线设备。",authDeviceRecentEmpty:"当前还没有最近登录记录。",authDeviceBrowserValue:"浏览器:{value}",authDeviceOsValue:"系统:{value}",authDeviceLastSeen:"最近在线:{value}",authDeviceLoginAt:"登录时间:{value}",authDeviceSourceAddressValue:"来源地址:{value}",authDeviceSourceAddressUnknown:"来源地址:未知",authDeviceEnablePrimary:"设为主设备",authDeviceDisablePrimary:"取消主设备",authDevicePrimaryUnavailable:"当前登录态缺少稳定设备标识,暂时不能设置主设备。",authDeviceLogoutOthers:"退出其他设备",authDeviceLogoutDevice:"退出设备",authDevicePrimaryEnabled:"当前设备已设为主设备。",authDevicePrimaryDisabled:"当前设备已取消主设备。",authDeviceLogoutOthersSuccess:"已退出其他设备,共处理 {count} 台。",authDeviceLogoutDeviceSuccess:"已退出设备“{device}”,共处理 {count} 个会话。",authDeviceLoadFailed:"登录设备信息加载失败。",authDeviceEnablePrimaryModalTitle:"设为主设备",authDeviceEnablePrimaryModalDescription:"请输入管理员密码,确认把当前设备设为主设备。",authDeviceDisablePrimaryModalTitle:"取消主设备",authDeviceDisablePrimaryModalDescription:"请输入管理员密码,确认取消当前设备的主设备状态。",authDevicePasswordLabel:"管理员密码",userManagementEntryTitle:"用户管理",userManagementEntryDescription:"管理可以登录这台 Host 的用户,并查看每个用户的会话和模型使用情况。",userManagementOpenAction:"用户管理",userManagementTitle:"用户管理",userManagementDescription:"这里管理登录用户。已有业务数据的用户不会被直接删除,避免误删工作区和会话。",userManagementTabsLabel:"用户管理标签页",userManagementUsersTab:"用户列表",userManagementUsageTab:"使用详情",userManagementUsersTitle:"用户列表",userManagementUsersDescription:"新增、编辑、启用或停用登录用户。删除只允许用于还没有产生数据的新用户。",userManagementAddUser:"添加用户",userManagementEditUser:"编辑",userManagementDeleteUser:"删除",userManagementEnableUser:"启用",userManagementDisableUser:"禁用",userManagementStatusActive:"已启用",userManagementStatusDisabled:"已禁用",userManagementUserMeta:"创建时间:{createdAt}",userManagementLoading:"正在读取用户列表。",userManagementUsersEmptyTitle:"还没有用户",userManagementUsersEmptyDescription:"添加第一个用户后,这里会显示可登录账号。",userManagementAddDescription:"输入用户名和密码,新用户创建后可以立即登录。",userManagementEditDescription:"可以修改用户名。密码留空时不会改变原密码。",userManagementUsernameLabel:"用户名",userManagementPasswordLabel:"密码",userManagementPasswordEditHint:"不需要改密码时留空。",userManagementDeleteConfirmTitle:"删除用户",userManagementDeleteConfirmDescription:"确认删除“{username}”?如果该用户已经产生数据,系统会阻止删除。",userManagementCreateSuccess:"用户已添加。",userManagementUpdateSuccess:"用户已更新。",userManagementDeleteSuccess:"用户已删除。",userManagementEnableSuccess:"用户已启用。",userManagementDisableSuccess:"用户已禁用。",userManagementLoadFailed:"用户列表读取失败。",userManagementSaveFailed:"用户保存失败。",userManagementDeleteFailed:"用户删除失败。",userManagementStatusFailed:"用户状态修改失败。",userManagementUsageTitle:"使用详情",userManagementUsageDescription:"按用户查看会话数量、模型、CLI 提供商和模型供应商使用情况。",userManagementUsageLoading:"正在读取使用详情。",userManagementUsageLoadFailed:"使用详情读取失败。",userManagementUsageEmptyTitle:"还没有使用记录",userManagementUsageEmptyDescription:"用户创建会话后,这里会显示使用情况。",userManagementPeriodLabel:"统计周期",userManagementPeriodDay:"按天",userManagementPeriodWeek:"按周",userManagementPeriodMonth:"按月",userManagementSessionCount:"{count} 个会话",userManagementMetricSessions:"会话",userManagementMetricTotalTokens:"总 Token",userManagementMetricInputTokens:"输入 Token",userManagementMetricOutputTokens:"输出 Token",userManagementTokenUnavailable:"当前 Host 还没有落库保存模型 Token 用量,所以 Token 图表会显示为 0;会话、模型和提供商统计来自真实会话记录。",userManagementTokenChartTitle:"模型 Token 用量",userManagementTokenChartEmptyTitle:"暂无 Token 记录",userManagementTokenChartEmptyDescription:"等会话记录里写入 Token 用量后,这里会显示趋势。",userManagementModelUsage:"模型使用情况",userManagementCliProviderUsage:"CLI 提供商使用情况",userManagementModelProviderUsage:"模型供应商使用情况",userManagementUsageGroupEmpty:"暂无记录",permissionModeDefault:"跟随 CLI 默认策略",permissionModeAcceptEdits:"允许编辑工作区,不询问",permissionModeBypassPermissions:"完整权限,不询问",enabled:"已启用",disabled:"已关闭",serverUpdate:"服务端更新",serverUpdateDescription:"",clientUpdate:"客户端更新",clientUpdateDescription:"",serverCurrentVersion:"服务端当前版本",serverTargetVersion:"服务端目标版本",serverPackageName:"npm 包名",serverUpdateCommand:"升级命令",serverCheckNow:"检查服务端",serverOpenPage:"打开 npm",serverLatestUnknown:"暂未获取",serverUpdateReady:"发现新版本",serverUpToDate:"已是最新版本",serverCheckFailed:"检查失败",serverInstallWarning:"安装更新会通过 PM2 自动重启 CodingNS 服务,连接会短暂中断。",serverInstallConfirmTitle:"安装服务端更新",serverInstallConfirmDescription:"继续后会先安装新版本,再由 PM2 自动重启当前 CodingNS 服务。",serverInstallConfirmAction:"继续安装并重启服务",serverRestarting:"更新已安装,正在重启 CodingNS 服务",serverProgressLabel:"服务端更新进度",serverProgressPreparing:"正在准备服务端更新",serverProgressQueued:"已进入更新队列",serverProgressInstalling:"正在更新服务端",serverProgressRestarting:"正在重启服务",serverProgressHint:"服务端更新通常需要几分钟,请保持应用打开。",serverProgressCurrentStage:"当前阶段:{stage}",serverOpenPageFailed:"打开页面失败",updateCheckAll:"检查更新",updateChecking:"正在检查",releaseCurrentVersion:"当前版本",releaseTargetVersion:"目标版本",releaseTargetTag:"目标 Tag",releasePublishedAt:"发布时间",releaseUnknownVersion:"未知",releaseNotes:"更新内容",releaseNotesEmpty:"这个版本暂时没有附带更新说明",releaseNotesView:"查看更新内容",releaseNotesPublishedAt:"发布时间",releaseCheckNow:"检查客户端",releaseInstallNow:"安装更新",releaseDownloading:"正在下载桌面端更新",releaseDownloadedReady:"桌面端更新已准备好,可以安装",releaseDownloadedReadyWithProgress:"桌面端更新已准备好({percent}%),可以安装",releaseDownloadFailed:"下载失败",releaseInstallReadyDialogTitle:"更新包已下载完成",releaseInstallReadyDialogDescription:"新版本 {version} 已准备好,现在可以安装。",releaseInstallReadyWarning:"安装后需要重启应用。",releaseInstallReadyConfirm:"安装并重启",releaseDownloadedNotificationTitle:"客户端更新已下载",releaseDownloadedNotificationBody:"新版本 {version} 已准备好,请到设置里安装。",releaseOpenPage:"打开发布页",releaseRollback:"回退版本",releaseUpdateBadge:"新版本",releaseUpdateReady:"发现新版本",releaseUpToDate:"已是最新版本",releaseCheckFailed:"检查失败",releaseInstallerMissing:"有新版本,暂无安装包",releaseSignatureMissing:"有新版本,缺少校验信息",releaseInstallStarted:"安装已开始",releaseInstallFailed:"安装失败",releaseRestartRequired:"更新已安装,重启应用后生效",releaseRestartDialogTitle:"安装成功",releaseRestartDialogDescription:"新版本 {version} 已安装完成,请重启应用程序后继续使用。",releaseRestartLater:"稍后",releaseRestartConfirm:"是,立即重启",releaseRestartFailed:"重启应用失败",releasePageOpenFailed:"打开页面失败",androidInstallerStarted:"已交给系统安装器,安装完成前你仍可以取消",androidInstallPermissionRequired:"请先允许当前应用安装未知来源应用",androidInstallCancelled:"安装已取消或未完成,可重新触发安装",androidInstallSucceeded:"已检测到新版本完成安装",releaseRollbackStarted:"已开始回退",releaseRollbackFailed:"回退失败",clientUpdateUnsupported:"当前不支持安装更新",logout:"退出登录"},home:{title:"从一条会话继续,而不是从后台表格开始",subtitle:"这里先挑一个工作区和会话,真正的工作区在下一步。",terminalsEntry:"进入终端页",workspaceSection:"工作区",sessionSection:"最近会话",emptyWorkspaces:"还没有导入工作区。先在 Host 侧导入后,这里会出现入口。",emptySessions:"当前工作区还没有可继续的会话。",noActivity:"暂时还没有活动"},shell:{hostSwitcherTitle:"HOST 切换",hostSwitcherAriaLabel:"切换 HOST",hostSwitcherSavedSection:"手动保存",hostSwitcherDiscoveredSection:"自动发现",hostSwitcherCurrentBadge:"当前",hostSwitcherDiscoveredBadge:"发现",hostSwitcherPeerBadge:"Peer",hostSwitcherSwitching:"切换中",hostSwitcherDetailAction:"详情",hostSwitcherDetailAriaLabel:"{name} 详情",hostSwitcherAddAction:"新增 HOST",hostSwitcherAddDirectHostAction:"添加直连 HOST",hostSwitcherAddPeerHostAction:"添加 Peer Host",hostSwitcherNameLabel:"HOST 名称",hostSwitcherNamePlaceholder:"例如:办公室 HOST",hostSwitcherUrlLabel:"HOST 地址",hostSwitcherUrlPlaceholder:"例如:http://10.10.1.8:3002",hostSwitcherSaveAction:"保存 HOST",hostSwitcherDetailTitle:"HOST 详情",hostSwitcherPrimaryHostTitle:"主 HOST",hostSwitcherDirectSectionTitle:"直连 HOST",hostSwitcherDetailStatusLabel:"连接状态",hostSwitcherDetailStatusDirect:"直接连接",hostSwitcherDetailStatusRelay:"中继连接",hostSwitcherDetailRouteLabel:"连接方式",hostSwitcherDetailAddressLabel:"地址",hostSwitcherDetailLatencyLabel:"延迟",hostSwitcherDetailTrafficLabel:"流量",hostSwitcherDetailResourceTitle:"资源占用",hostSwitcherDetailLatencyLoading:"检测中",hostSwitcherDetailUnavailable:"不可用",hostSwitcherDetailCpuLabel:"CPU",hostSwitcherDetailCpuValue:"{usage} · {cores} 核",hostSwitcherDetailMemoryLabel:"内存",hostSwitcherDetailDiskLabel:"磁盘",hostSwitcherAliasLabel:"HOST 别名",hostSwitcherAliasPlaceholder:"4 个英文字母",hostSwitcherAliasRule:"别名只能使用英文字母,最多 4 个。",hostSwitcherAliasInvalid:"别名只能使用英文字母,最多 4 个。",hostSwitcherAliasSaveAction:"保存别名",hostSwitcherAliasSaveSuccess:"HOST 别名已保存。",hostSwitcherPeerTitle:"作为 Peer HOST 使用",hostSwitcherPeerSectionTitle:"Peer HOST",hostSwitcherPeerDescription:"启用前会检查主 HOST 到目标 HOST 的网络、版本和登录状态。全部通过后,工作区才能通过主 HOST 访问它。",hostSwitcherPeerReconnectDescription:"这个 Peer HOST 已经接入。你可以手动重连,重新检查目标 HOST,并使用已保存的登录态恢复代理访问。",hostSwitcherPeerStatusLabel:"Peer 状态",hostSwitcherPeerFailureReasonLabel:"失败原因",hostSwitcherPeerEnableAction:"启用 Peer",hostSwitcherPeerReconnectAction:"手动重连",hostSwitcherPeerDisableAction:"停用 Peer",hostSwitcherPeerChecking:"检查中",hostSwitcherPeerPasswordOneTimeHint:"目标 HOST 密码只用于本次启用检查,不会保存到主 HOST。",hostSwitcherPeerLoginRequired:"请先填写目标 HOST 的用户名和密码。",hostSwitcherPeerEnableSuccess:"Peer HOST 已启用。",hostSwitcherPeerReconnectSuccess:"Peer HOST 已重新连接。",hostSwitcherPeerEnableFailed:"启用 Peer HOST 失败。",hostSwitcherPeerReconnectFailed:"Peer HOST 重连失败。",hostSwitcherPeerDisableSuccess:"Peer HOST 已停用。",hostSwitcherPeerDisableFailed:"停用 Peer HOST 失败。",hostAddInvalidUrl:"HOST 地址不正确。",hostAddDuplicate:"这个 HOST 已经保存过。",hostAddIncompleteCredentials:"用户名和密码需要一起填写。",hostAddSuccess:"{name} 已保存。",hostAddFailed:"保存 HOST 失败。",hostDeleteAction:"删除 HOST",hostDeleteAriaLabel:"删除 HOST {name}",hostDeleteConfirmAction:"确认删除",hostDeleteBusy:"删除中",hostDeleteSuccess:"{name} 已删除。",hostDeleteFailed:"删除 {name} 失败。",hostSwitchFailed:"切换 HOST 失败。",hostSwitchMissing:"找不到这个 HOST。",hostSwitchUnreachable:"{name} 当前不可达。",hostDiscoveryRefreshing:"正在查找局域网 HOST…",hostDiscoveryFailed:"局域网 HOST 查找失败。",manageWorkspaceHostLabel:"使用的 HOST",manageWorkspaceHostSelectLabel:"选择这个项目使用的 HOST",manageWorkspaceHostCurrentOption:"主 HOST · {alias}",manageWorkspaceHostPeerOption:"Peer HOST · {alias}",manageWorkspaceHostHint:"当前项目会通过 {hostName} 打开。",manageWorkspaceHiddenSectionTitle:"已隐藏项目",manageWorkspaceRemotePathTitle:"选择 Peer HOST 上的项目目录",manageWorkspaceRemotePathDescription:"Peer HOST 上没有找到同名项目“{name}”。请选择它在这台 HOST 上对应的目录,保存后会先注册为项目再切换。",manageWorkspaceRemotePathSubmit:"使用这个目录",hostSwitcherPeerWorkspaceDescription:"来自 {hostName} · {path}",hostSwitcherPeerWorkspaceUnavailableDescription:"{hostName} 当前不可用,暂时不能打开这个工作区。",hostSwitcherPeerUnavailableBadge:"不可用",hostSwitcherPeerUnavailable:"{hostName} 当前不可用",hostSwitcherPeerVersionMismatchBadge:"版本不一致",hostSwitcherPeerVersionMismatch:"{hostName} 版本不一致,暂时不能打开",hostSwitcherPeerUnauthorizedBadge:"需要登录",hostSwitcherPeerUnauthorized:"{hostName} 需要先登录后才能打开",hostSwitcherPeerWorkspaceRouteUnsupported:"这个工作区暂时还不能打开",hostSwitcherPeerWorkspaceRouteUnsupportedDescription:"{hostName} 的工作区已经显示出来了,等代理接口接好后就能从这里进入。"},terminal:{title:"终端",heroTitle:"把真实 PTY 留在 Host,把操作入口留在工作台",heroSubtitle:"这里不伪造输出,不把终端和进程搅在一起,只消费 Host 统一托管的真实终端流。",workspaceSection:"工作区与终端",workspaceField:"当前工作区",shellField:"新终端使用的 Shell",runtimeField:"Runtime",runtimeAutoOption:"自动选择",runtimeAutoShortLabel:"auto",runtimeAutoDescription:"按 Host 默认策略选择当前终端 runtime。",runtimePersistentLabel:"持久会话",runtimePersistentShortLabel:"持久",runtimeTmuxDescription:"持久化外部会话,适合需要后台常驻的开发终端。",runtimeWindowsPersistentDescription:"使用基于 ConPTY 的 Windows 持久化会话,让终端在 Host 重启后仍可继续保留。",runtimeEmbeddedDescription:"由当前 Host 直接托管,适合作为轻量回退方案。",runtimeConptyPowerShellLabel:"PowerShell 持久会话",runtimeConptyCmdLabel:"CMD 持久会话",runtimeConptyGitBashLabel:"Git Bash 持久会话",runtimeMissingDialogTitle:"当前系统没有安装 tmux",runtimeMissingDialogDescription:"tmux runtime 无法继续创建持久化终端。你可以先安装 tmux,或者临时切换到 embedded-pty 继续。",runtimeMissingInstallDescription:"建议优先安装 tmux,这样终端才能在 Host 重启后继续保留。",runtimeMissingInstallMacArm:"macOS(Apple Silicon / Homebrew):arch -arm64 brew install tmux",runtimeMissingInstallMacIntel:"macOS(Intel Mac / Homebrew):brew install tmux",runtimeMissingInstallDebian:"Ubuntu / Debian:sudo apt install tmux",runtimeMissingInstallFedora:"Fedora:sudo dnf install tmux",runtimeMissingFallbackDescription:"如果现在先切到 embedded-pty,本次终端可以继续创建,但它不会作为外部持久会话保留。",runtimeMissingKeepAction:"先不切换",runtimeMissingFallbackAction:"切换到 embedded-pty 并继续",runtimeMissingFallbackPending:"正在切换…",shellUnavailable:"当前不可用",workspaceLoadFailed:"工作区或终端列表暂时没有拉回来。",terminalSection:"终端实例",templateSection:"命令模板",stageEmptyTitle:"还没有选中终端",stageEmptySubtitle:"先创建一个终端,或者运行一个命令模板。",emptyTerminals:"当前工作区还没有终端实例。",emptyTemplates:"当前工作区还没有命令模板。",createButton:"新建终端",creating:"正在创建终端…",creationPendingDescription:"Host 正在启动真实 PTY,连上以后这个窗口会立刻接管显示。",defaultTerminalName:"工作终端",created:"终端已经创建并接入 Host。",createFailed:"终端创建失败。",closeButton:"关闭终端",closing:"正在关闭终端…",closed:"终端关闭请求已经提交。",closeCompleted:"终端已关闭。",closePendingDescription:"关闭请求已经发给 Host,前台不会阻塞,系统会继续同步最终结果。",closeSyncDelayed:"Host 还在后台处理关闭,列表会在后续刷新时继续同步。",closeFailed:"终端关闭失败。",inputLabel:"向当前终端发送命令",inputPlaceholder:"例如:pnpm test",sendButton:"发送到终端",inputFailed:"终端输入发送失败。",outputEmpty:"终端已经连上,但暂时还没有输出。",outputTruncated:"断线期间有一段输出超出缓存窗口,当前只补回了仍保留的部分。",connectedHint:"当前输出来自 Host 真实 PTY 流。",moreActions:"终端操作",duplicateAction:"复制标签",duplicateSuccess:"已按当前终端配置新建一个标签。",duplicateFailed:"复制终端标签失败。",disconnectAction:"断开",disconnected:"终端连接已断开。",reconnectAction:"重连",reconnectRequested:"终端重连请求已发出。",deleteAction:"删除",deleting:"正在删除终端…",deleted:"终端记录已删除。",deletePendingDescription:"删除请求已经发给 Host,前台不会阻塞,系统会在后台继续同步列表。",deleteSyncDelayed:"Host 还在后台处理删除,列表会在后续刷新时继续同步。",deleteFailed:"终端记录删除失败。",closePendingBadge:"关闭中",deletePendingBadge:"删除中",pinAction:"固定",unpinAction:"取消固定",zoomLabel:"终端缩放",zoomInAction:"放大终端显示",zoomOutAction:"缩小终端显示",zoomResetAction:"恢复默认缩放",openExternalAction:"独立窗口",openExternalFailed:"打开终端独立窗口失败。",toolbarToggleAction:"展开终端工具菜单",mobileSwipeHint:"左右滑动切换终端",mobileSwipePosition:"{current} / {total}",mobileDrawerAction:"打开快捷终端列表",mobileDrawerTitle:"快捷终端",mobileDrawerDescription:"右滑呼出列表,点一下就切到别的终端。",mobilePinnedSectionTitle:"已固定终端",mobileDrawerEmptyTitle:"当前还没有终端",mobileDrawerEmptyDescription:"先新建一个终端,这里才会出现可切换的列表。",mobileCreateSheetTitle:"新建终端",mobileCreateShellLabel:"终端类型",mobileCreateShellDescription:"先选这次要开的 Shell,别把桌面端那套下拉框搬到手机上。",mobileCreateRuntimeLabel:"会话方式",mobileCreateRuntimeDescription:"再决定它是持久保留,还是只作为当前 runtime 会话。",mobileCreateLoadingShells:"正在读取当前系统可用的终端类型…",mobileCreateConfirm:"创建这个终端",createDialogTitle:"新建终端",createDialogShellDescription:"先选这次要开的 Shell,再创建终端。Windows 下不再偷偷按默认值直接起。",createDialogRuntimeDescription:"再决定它是持久保留,还是只作为当前 runtime 会话。",createDialogConfirm:"创建终端",mobileRuntimePersistentTitle:"持久会话",mobileRuntimePersistentDescription:"适合需要一直挂着的开发终端,创建后会作为可恢复会话保留。",mobileRuntimeSessionTitle:"runtime(当前会话)",mobileRuntimeSessionDescription:"直接由当前 Host 托管,创建更轻,但不会保留成外部持久会话。",mobileWorkspaceSwitcherPlaceholder:"选择项目",mobileEmptyTitle:"这里还没有终端内容",mobileEmptyDescription:"先新建一个终端,或者右滑呼出快捷列表,切到当前工作区已有的终端。",layoutLabel:"分栏布局",layoutSingleAction:"单栏显示",layoutVerticalAction:"左右分栏",layoutHorizontalAction:"上下分栏",saveLogAction:"保存日志",saveLogSuccess:"终端日志已保存。",saveLogFailed:"终端日志保存失败。",logEmpty:"当前终端还没有可保存的日志内容。",bindToPaneAction:"绑定到当前分栏",bindToPrimaryPaneAction:"绑定到主分栏",bindToSecondaryPaneAction:"绑定到副分栏",panePrimary:"主分栏",paneSecondary:"副分栏",splitEmptySubtitle:"先点一个标签,或者新建一个终端,把它绑定到当前分栏。",statusBadge:{creating:"启动中",running:"运行中",closed:"已关闭",error:"异常"},recoveryComplete:"已回到刷新前的终端,缓存内的关键输出已经补回。",recoveryTruncated:"已恢复到上一个终端,但断线期间的部分输出已经超出缓存窗口。",recoveryIdleClosed:"上一个终端已因空闲超时被 Host 自动关闭,你现在看到的是关闭前保留的输出。",reconnect:"手动重连",liveConnected:"实时流已接入",templateName:"模板名称",templateCommand:"主命令",templateArgs:"参数(空格分隔)",templateCreateButton:"保存模板",templateCreated:"命令模板已经保存。",templateCreateFailed:"命令模板保存失败。",templateRunSent:"命令模板已经发送到当前终端。",templateRunCreatedTerminal:"命令模板已在新终端中启动。",templateRunFailed:"命令模板执行失败。",connection:{connected:"已连接",reconnecting:"正在重连",reconnect_failed:"重连失败",closed:"已关闭"}},conversation:{titleFallback:"继续对话",historyLoading:"正在从 Host 拉取消息历史…",historyLoadingOlder:"正在加载更早的消息…",historyLoadFailed:"历史消息暂时没有拉回来,可以稍后再试。",timelineEmpty:"这条会话还没有消息。你发出的第一句话会直接进入 Host 链路。",turnAbortedUser:"上一轮已由你手动停止。",turnAbortedUnexpected:"上一轮意外中断,没有正常结束。",turnAbortedGeneric:"上一轮已中断,没有正常结束。",scrollToBottomAction:"回到底部",rawRefLabel:"来源",copyAction:"复制",copyContentSuccess:"内容已复制。",copyContentFailed:"内容复制失败。",selectionTodoAction:"代办",selectionActionButton:"操作",selectionActionSubmit:"新开操作子会话",selectionActionPromptLabel:"你想让它做什么",selectionActionPromptPlaceholder:"比如:解释这段话、整理成笔记,或调用指定接口处理它",selectionActionIncludeContext:"包含当前上下文",selectionActionContextUnavailable:"当前选区跨了多条消息,没法安全继承上下文,只能按无上下文新建子会话。",selectionActionDefaultPrompt:"请处理这段内容。",selectionActionPreviewLabel:"已选内容",selectionActionTargetLabel:"新会话设置",selectionActionQuotedLabel:"选中文本",selectionActionFailed:"创建操作子会话失败。",actionSessionBadge:"操作",actionInheritedSelectionSummary:"已默认折叠来自“{parentTitle}”的一段选中文本。",forkFromHereAction:"从这里分叉",forkingAction:"正在分叉…",forkMessageSucceeded:"已从这条消息创建新分支。",forkMessageFailed:"从这条消息分叉失败。",forkDraftLabel:"分叉引用",forkDraftEmpty:"这条消息没有可引用的文本内容。",forkDraftClear:"取消这次分叉引用",forkTargetProviderLabel:"目标 CLI",forkTargetModelLabel:"目标模型",forkTargetSummary:"源 CLI:{sourceProvider} · 目标 CLI:{targetProvider}",forkInlineModelLoading:"正在读取模型列表…",forkInlineNativeHint:"保持同一 CLI,继续走原生分叉。",forkInlineCrossHint:"已切到不同 CLI,将按文本历史重建新会话。",forkSwitchConfirmTitle:"切换到其他 CLI?",forkSwitchConfirmDescription:"同一 CLI 会尽量保留原生分叉体验;切到其他 CLI 会改成跨供应商分叉。",forkSwitchConfirmKeepTitle:"会保留",forkSwitchConfirmKeepBody:"分叉点之前的用户消息和助手文本。",forkSwitchConfirmConvertTitle:"会转换",forkSwitchConfirmConvertBody:"可继承文本会重建到新的 CLI 会话里。",forkSwitchConfirmDropTitle:"会丢失",forkSwitchConfirmDropBody:"工具调用、权限交互、附件和运行中状态。",forkSwitchConfirmAction:"确认切换",forkSwitchKeepNative:"保持原生",forkProviderNativeUnsupported:"当前 provider 还不支持原生 fork",forkProviderReconstructedUnsupported:"当前 provider 还不能作为跨 provider 分叉目标",loadMore:"加载更多消息",composerPlaceholder:"把下一步交代清楚,剩下的交给这条会话继续跑。",sendButton:"发送消息",queueTitle:"待发队列",queueDescription:"当前这轮结束后,队列里的消息会按顺序自动继续处理。",queueOrderPrefix:"队列序号",queueStatusQueued:"等待中",queueStatusFailed:"发送失败",queueDelete:"删除",queueDeleting:"删除中",queueImageOnly:"仅图片附件",sendGuidanceButton:"追加引导",queueGuidanceButton:"加入队列",queueSteer:"引导",queueSteering:"引导中",resendButton:"重试发送",quickPhraseTrigger:"快捷短语",quickPhraseModalTitle:"快捷短语",quickPhraseModalDescription:"这里集中管理你常用的会话指令,点一下就能直接填回当前输入框。",quickPhraseCreateLabel:"新增短语",quickPhraseOpenCreateAction:"新增短语",quickPhraseCreateModalTitle:"新增快捷短语",quickPhraseCreateModalDescription:"把常用指令单独存起来,后面在任何设备上都能直接复用。",quickPhraseCreatePlaceholder:"输入一条常用短语,保存后下次可以直接复用。",quickPhraseCreateAction:"添加短语",quickPhraseListLabel:"快捷短语列表",quickPhraseEmpty:"还没有可用的快捷短语,先加一条最常用的。",quickPhraseOrderLabel:"第 {index} 条",quickPhraseMoveUp:"上移短语",quickPhraseMoveDown:"下移短语",quickPhraseDelete:"删除短语",quickPhraseSaveFailed:"快捷短语保存失败,请稍后再试。",sendingState:"发送中",sentState:"已同步",failedState:"发送失败",contextUsageTitle:"当前上下文占用",contextUsageUnavailable:"当前上下文占用暂时不可用",contextUsageEstimated:"上限为估算值",contextUsageCachedTokens:"缓存命中 {count}",contextUsageSourceProviderLog:"上限来自 provider 运行日志",contextUsageSourceProviderRuntime:"上限来自 provider runtime",contextUsageSourceProviderConfig:"上限来自 provider 配置",contextUsageSourceModelMap:"上限来自模型映射",headerWorkspace:"工作区",headerProvider:"Provider",headerCapability:"能力摘要",connectionConnected:"已连接",connectionReconnecting:"正在重连",connectionReconnectFailed:"重连失败",connectionClosed:"连接已关闭",runtimeErrorTitle:"会话运行失败",runtimeErrorFallbackDetail:"CLI 提供商返回了错误,但没有提供更多细节。",runtimeErrorCodeLabel:"错误码",runtimeErrorDetailLabel:"错误详情",reconnectExplain:"实时链路断开了,系统正在补回缺失消息。",reconnectFailedExplain:"自动恢复没有成功。你可以手动重试,或者稍后重新进入会话。",reconnectExplainWithRoute:"实时链路断开了,系统正在补回缺失消息。当前连接方式:{route}。",reconnectFailedExplainWithRoute:"自动恢复没有成功。你可以手动重试,或者稍后重新进入会话。当前连接方式:{route}。",capabilityDenied:"当前会话不支持这个动作",capabilitySendDisabled:"当前 provider 不支持发送新消息",capabilityAttachmentDisabled:"当前会话还不支持附件输入",capabilityInterruptDisabled:"当前会话不支持中断运行",sidebarTitle:"当前会话上下文",sidebarSubtitle:"这里只保留最小能力摘要,不把页面做成后台控制台。",reconnectButton:"手动恢复实时同步",headerResumedAt:"最近续接",headerLastSyncAt:"最近同步",historyPages:"历史分页",syncStatusIdle:"同步空闲",syncStatusSyncing:"同步中",syncStatusError:"同步异常",capabilityResume:"可续接",capabilitySend:"可发送",capabilityInterrupt:"可中断",capabilityTools:"工具调用",attachmentsLabel:"附件",filePanelTitle:"文件管理",filePanelSubtitle:"这里的文件能力只服务当前会话,不把页面拉成重型 IDE。",filePanelNoWorkspace:"当前还没有选中项目,暂时不能浏览或挂载文件。",filePanelRefresh:"刷新",filePanelCopyPath:"复制路径",filePanelCopyAbsolutePath:"复制绝对路径",filePanelCopyRelativePath:"复制相对路径",filePanelCopyAbsolutePathSuccess:"绝对路径已复制。",filePanelCopyRelativePathSuccess:"相对路径已复制。",filePanelCopyPathFailed:"路径复制失败。",filePanelCopy:"复制",filePanelCut:"剪切",filePanelPaste:"粘贴",filePanelCopySelectionSuccess:"已复制 {count} 项,可到目标目录粘贴。",filePanelCutSelectionSuccess:"已剪切 {count} 项,可到目标目录粘贴。",filePanelPasteSuccess:"已粘贴 {count} 项。",filePanelPasteFailed:"粘贴失败,请检查目标目录和重名冲突。",filePanelSelectionCount:"已选 {count} 项",filePanelClipboardCopyReady:"剪贴板中有 {count} 个待复制项目",filePanelClipboardCutReady:"剪贴板中有 {count} 个待移动项目",filePanelOpenFile:"打开文件",filePanelExpandDirectory:"展开文件夹",filePanelCollapseDirectory:"折叠文件夹",filePanelActionsMenu:"文件操作",filePanelSearchPlaceholder:"输入文件名或路径片段",filePanelSearchButton:"搜索",filePanelShowSearch:"打开搜索",filePanelHideSearch:"收起搜索",filePanelSearchEmpty:"没有找到匹配的文件。",filePanelSearchResults:"搜索结果",filePanelSearchFailed:"文件搜索失败,请稍后再试。",filePanelBrowse:"工作区文件",filePanelCollapseCurrent:"折叠当前选中",filePanelCollapseAll:"全部折叠",filePanelBackDirectory:"返回上级",filePanelEmptyDirectory:"这个目录里暂时没有可显示的文件。",filePanelRecentTitle:"最近打开",filePanelEmptyRecent:"最近还没有打开记录。",filePanelContextTitle:"已挂载文件",filePanelEmptyContexts:"当前会话还没有挂载文件管理。",filePanelEditorTitle:"预览与编辑",filePanelEditorPlaceholder:"这里只做轻量文本编辑,不在这里做完整 IDE。",filePanelSelectHint:"先从目录、搜索或最近打开里选一个文件。",filePanelUnsupported:"这个文件当前不能在侧栏里直接编辑。",filePanelAttach:"挂到会话",filePanelAttached:"已挂载",filePanelDetach:"解绑",filePanelSave:"保存",filePanelSaving:"保存中",filePanelLoadFailed:"文件管理面板加载失败。",filePanelOpenFailed:"文件打开失败。",filePanelSaveSuccess:"文件已经保存。",filePanelSaveFailed:"文件保存失败。",fileViewerHint:"当前以 {language} 模式打开,支持预览与编辑保存。",fileViewerModeLabel:"文件查看模式",fileViewerPreview:"预览",fileViewerPresentation:"演示文档",fileViewerCode:"代码",fileViewerEdit:"编辑",fileViewerPlainText:"纯文本",fileViewerHtml:"HTML",fileViewerImage:"图片",fileViewerPdf:"PDF",fileViewerRefreshPreview:"刷新",fileViewerRefreshFailed:"文件预览刷新失败。",fileViewerExportPdf:"导出 PDF",fileViewerExportPdfRunning:"导出中",fileViewerExportPdfSuccess:"PDF 已导出到 {path}",fileViewerExportPdfFailed:"PDF 导出失败。",fileViewerExportPdfTimeout:"PDF 导出超时,请稍后重试。",fileViewerExportPdfMissingHtml:"当前没有可导出的 HTML 内容。",fileViewerExportPptx:"导出 PPTX",fileViewerExportPptxRunning:"导出中",fileViewerExportPptxSuccess:"PPTX 已导出到 {path}",fileViewerExportPptxFailed:"PPTX 导出失败。",fileViewerExportPptxMissingHtml:"当前没有可导出的 HTML 内容。",fileViewerExportTaskTimeout:"导出超时,请稍后重试。",fileViewerOpenExternal:"外部打开",fileViewerOpenExternalFailed:"外部打开失败。",fileViewerOpenInWindow:"独立窗口",fileViewerOpenInWindowFailed:"独立窗口打开失败。",fileViewerWindowTitle:"文件预览",fileViewerCollapse:"收起预览",fileViewerExpand:"展开预览",fileViewerZoomIn:"放大",fileViewerZoomOut:"缩小",fileViewerFit:"适配",fileViewerActualSize:"原始大小",fileViewerFitWidth:"适宽",fileViewerPreviousPage:"上一页",fileViewerNextPage:"下一页",fileViewerPageIndicator:"第 {page} 页",fileViewerSizeLabel:"查看器尺寸",fileViewerSizeDefault:"默认",fileViewerSizeWide:"加宽",fileViewerSizeFull:"铺满",fileViewerDiffModified:"已修改",fileViewerDiffAdded:"新增内容",fileViewerImageUnavailable:"当前无法显示图片预览,请尝试刷新或外部打开。",fileViewerPdfUnavailable:"当前无法显示 PDF 预览,请尝试刷新或外部打开。",fileViewerOfficeLoading:"正在加载 ONLYOFFICE 预览…",fileViewerOfficeUnavailable:"当前无法显示 Office 预览,请先检查 ONLYOFFICE 配置和服务状态。",fileViewerOfficeScriptUnavailable:"ONLYOFFICE 编辑器脚本加载失败,请检查服务地址是否可访问。",fileViewerEnterFullscreen:"全屏",fileViewerExitFullscreen:"退出",fileViewerOpenInBrowser:"在浏览器中打开",fileViewerOpenInBrowserFailed:"打开浏览器预览失败。",fileViewerHtmlPreviewLoading:"正在加载 HTML 预览...",fileViewerHtmlPreviewUnavailable:"当前无法显示 HTML 预览,请先切到代码模式查看。",fileViewerHtmlPreviewFailed:"HTML 预览链接生成失败。",fileViewerPresentationBadge:"静态 HTML",fileViewerPresentationSummary:"已识别 {count} 页,画布基准 {size}",fileViewerPresentationWarningCount:"当前有 {count} 条导入提醒。",fileViewerPresentationCurrentPage:"当前页面",fileViewerPresentationUntitled:"未命名页面",fileViewerPresentationReadOnlyHint:"请选择要编辑的组件以查看文本和布局编辑工具",fileViewerPresentationEditHint:"这一版已经支持选中组件、修改文字和基础样式,复杂结构继续保持只读。",fileViewerPresentationCanvasSelectHint:"可以直接点击画布里的组件进入顶部编辑栏,也可以在右侧组件列表里切换。",fileViewerPresentationUnsupported:"这份 HTML 还不适合进入演示文档视图。",fileViewerPresentationUnsupportedReason:"原因:{reason}",fileViewerPresentationSelectNode:"先在右侧组件列表里选一个可编辑节点。",fileViewerPresentationAddPage:"新增页面",fileViewerPresentationDuplicatePage:"复制页面",fileViewerPresentationDeletePage:"删除页面",fileViewerPresentationMovePageUp:"上移页面",fileViewerPresentationMovePageDown:"下移页面",fileViewerPresentationPageActions:"页面操作",fileViewerPresentationDragToSort:"拖拽排序",fileViewerPresentationUndoAction:"撤销上一步",fileViewerPresentationInspector:"组件属性",fileViewerPresentationComponentList:"组件列表",fileViewerPresentationEditable:"可编辑",fileViewerPresentationReadOnly:"只读",fileViewerPresentationTextLabel:"文字内容",fileViewerPresentationTextDescription:"这里直接改组件文案,中间画布会实时刷新。",fileViewerPresentationTextToolbar:"文字工具栏",fileViewerPresentationFontFamilyLabel:"字体",fileViewerPresentationFontPresetTitle:"等线 Light(标题)",fileViewerPresentationFontPresetSans:"思源黑体",fileViewerPresentationFontPresetSerif:"衬线正文",fileViewerPresentationFontPresetMono:"等宽字体",fileViewerPresentationBoldAction:"加粗",fileViewerPresentationItalicAction:"倾斜",fileViewerPresentationUnderlineAction:"下划线",fileViewerPresentationFontSizeIncreaseAction:"字体放大",fileViewerPresentationFontSizeDecreaseAction:"字体缩小",fileViewerPresentationLineHeightAuto:"默认行距",fileViewerPresentationFontSizeLabel:"字号",fileViewerPresentationFontWeightLabel:"字重",fileViewerPresentationTextColorLabel:"文字颜色",fileViewerPresentationBackgroundColorLabel:"背景颜色",fileViewerPresentationTextAlignLabel:"对齐",fileViewerPresentationLineHeightLabel:"行高",fileViewerPresentationPaddingLabel:"内边距",fileViewerPresentationRadiusLabel:"圆角",fileViewerPresentationPositionXLabel:"水平位置",fileViewerPresentationPositionYLabel:"垂直位置",fileViewerPresentationWidthLabel:"组件宽度",fileViewerPresentationHeightLabel:"组件高度",fileViewerPresentationDuplicateAction:"复制当前组件",fileViewerPresentationKeepOriginal:"保持原样",fileViewerPresentationAlignLeft:"左对齐",fileViewerPresentationAlignCenter:"居中",fileViewerPresentationAlignRight:"右对齐",fileViewerPresentationTextMode:"文本",fileViewerPresentationLayoutMode:"布局",fileViewerPresentationLayoutHint:"这里改的是组件位置和尺寸,画布拖拽与保存会一起生效。",fileViewerPresentationLayoutSelectNode:"先选一个支持布局编辑的组件。",fileViewerPresentationLayoutEditable:"可做布局编辑",fileViewerPresentationLayoutLocked:"当前不能做布局编辑",fileViewerPresentationLayoutUnsupported:"这个组件当前还不能安全做布局编辑。",fileViewerPresentationLayoutStrictLocked:"该组件处在流式布局里,不能直接自由拖动。先把它所在容器转换成自由布局。",fileViewerPresentationLayoutFreezeContainer:"转换当前容器为自由布局",fileViewerPresentationLayoutRootLocked:"页面根容器这轮不允许直接改布局。",fileViewerPresentationLayoutSelectionCount:"已选中 {count} 个组件",fileViewerPresentationLayoutAlignLeft:"左边对齐",fileViewerPresentationLayoutAlignRight:"右边对齐",fileViewerPresentationLayoutAlignTop:"顶部对齐",fileViewerPresentationLayoutAlignBottom:"底部对齐",fileViewerPresentationResizeHandle:"调整组件大小",filePanelAttachSuccess:"文件已经挂到当前会话。",filePanelAttachFailed:"文件挂载失败。",filePanelDetachSuccess:"文件已经从当前会话解绑。",filePanelDetachFailed:"文件解绑失败。",filePanelNewFile:"新建文件",filePanelNewDirectory:"新建目录",filePanelUpload:"上传文件",filePanelDownload:"下载文件",filePanelUploadSuccess:"已上传 {name}。",filePanelUploadFailed:"文件上传失败。",filePanelDownloadSuccess:"已开始下载 {name}。",filePanelDownloadFailed:"文件下载失败。",filePanelDelete:"删除",filePanelDeleting:"删除中...",filePanelDeleteSuccess:"已删除 {name}。",filePanelDeleteConfirmTitle:"确认删除",filePanelDeleteConfirmDescription:"删除后会立即从当前项目移除,这一步不能撤销。",filePanelDeleteSelectionConfirm:"确认删除选中的 {count} 项吗?",filePanelDeleteSelectionSuccess:"已删除 {count} 项。",filePanelRenameMove:"重命名/移动",filePanelRenameSuccess:"已重命名为 {name}。",filePanelMutateFailed:"文件操作失败,请检查路径和当前状态。",filePanelCreateFilePrompt:"输入要创建的相对文件路径",filePanelCreateDirectoryPrompt:"输入要创建的相对目录路径",filePanelCreateFileDescription:"输入工作区内的相对路径,文件会立刻创建出来。",filePanelCreateDirectoryDescription:"输入工作区内的相对路径,文件夹会立刻创建出来。",filePanelPathFieldLabel:"相对路径",filePanelPathFieldPlaceholder:"例如 src/features/files/index.ts",filePanelCreateFileSubmit:"创建文件",filePanelCreateDirectorySubmit:"创建文件夹",filePanelCreatingFile:"创建文件中...",filePanelCreatingDirectory:"创建文件夹中...",exportAction:"导出会话",exportDialogTitle:"导出当前会话",exportDialogDescription:"可以导出成 Markdown 文件,或者按当前消息样式打印并保存为 PDF。",exportMarkdownAction:"导出 Markdown",exportMarkdownHint:"导出完整消息内容,适合继续编辑、归档和提交。",exportPdfAction:"导出 PDF",exportPdfHint:"会直接下载 PDF 文件,保留当前会话内容排版。",exportHtmlAction:"导出 HTML",exportPreparing:"正在准备导出内容...",exportMarkdownSuccess:"Markdown 已开始导出。",exportPdfPreparing:"PDF 已开始下载。",exportHtmlSuccess:"HTML 已开始导出。",exportLoadFailed:"导出失败,当前会话内容没有完整拉取下来。",exportDownloadFailed:"导出文件失败。",exportPrintFailed:"打开打印窗口失败。",exportPrintContainerTitle:"会话导出",exportMarkdownSessionIdLabel:"会话 ID",exportMarkdownProviderLabel:"Provider",exportMarkdownWorkspaceLabel:"工作区 ID",exportMarkdownCreatedAtLabel:"创建时间",exportMarkdownExportedAtLabel:"导出时间",exportMarkdownTimeLabel:"时间",exportMarkdownTypeLabel:"类型",exportMarkdownAttachmentsLabel:"附件数量",exportMarkdownAttachmentsSectionTitle:"附件",exportMarkdownToolSectionTitle:"工具调用",exportMarkdownToolNameLabel:"工具名",exportMarkdownToolStatusLabel:"状态",exportMarkdownToolInputLabel:"输入",exportMarkdownToolOutputLabel:"输出",exportMarkdownToolErrorLabel:"错误",exportMarkdownToolCallType:"工具调用",exportMarkdownToolResultType:"工具结果",exportMarkdownTextType:"正文",exportMarkdownUnknownSize:"大小未知",filePanelFilterChanges:"仅显示变更",filePanelShowAll:"显示全部",filePanelNoChanges:"当前没有变更文件。",filePanelBinaryPreview:"二进制文件不支持预览。",filePanelDeleteFileConfirm:"确认删除这个文件吗?{path}",filePanelDeleteDirectoryConfirm:"确认删除这个文件夹吗?{path}",filePanelRenameMovePrompt:"输入新的相对路径",filePanelRenameDescription:"只改路径,不改文件内容。填新路径就会同时支持移动目录层级。",filePanelRenameSubmit:"确认重命名",filePanelRenaming:"重命名中...",unavailableAction:"当前不可用",roleUser:"你",roleAssistant:"助手",roleTool:"工具",toolViewImageActiveLabel:"AI正在查看图片",assistantCapabilityBadgeSubAgent:"子会话",codexAgentToolCreateTitle:"创建子会话",codexAgentToolReadTitle:"查看子会话",codexAgentToolUpdateTitle:"更新子会话",codexAgentToolReplyTitle:"回复子会话",codexAgentToolCloseTitle:"关闭子会话",codexAgentToolCreateSummary:"已把一段独立任务交给子 agent 处理。",codexAgentToolReadSummary:"正在读取子 agent 的最新状态和回复。",codexAgentToolUpdateSummary:"已向子 agent 改派或更新当前任务。",codexAgentToolReplySummary:"已把补充消息发给子 agent。",codexAgentToolCloseSummary:"已关闭这个子 agent 会话。",codexAgentToolLabelAgent:"Agent",codexAgentToolLabelNickname:"昵称",codexAgentToolLabelRole:"类型",codexAgentToolLabelModel:"模型",codexAgentToolLabelTargets:"目标",codexAgentToolLabelTimeout:"等待",codexAgentToolLabelMessage:"消息",codexAgentToolLabelReason:"结果",subagentNotificationTitle:"子 agent 汇报",subagentNotificationSummary:"子 agent 已返回本次任务结果。",subagentNotificationLabelSummary:"摘要",subagentNotificationStatusCancelled:"已取消",roleSystem:"系统"},git:{title:"Git 上下文",subtitle:"这里是会话侧边的辅助区,只处理当前工作区里的 Git 事实。",loading:"正在读取当前工作区的 Git 上下文。",refresh:"刷新",panelLoadFailed:"Git 上下文暂时没有加载出来。",uninitializedTitle:"当前目录还没有启用 Git",uninitializedDescription:"先初始化这个目录的 Git 工作区,后面才能查看改动、写提交和追踪历史。",initRepository:"初始化 Git 工作区",initInProgress:"正在初始化…",initSuccess:"Git 工作区已初始化。",initFailed:"初始化 Git 工作区失败。",ahead:"领先",behind:"落后",dirty:"有改动",clean:"已干净",changeCount:"当前有 {count} 个变更文件",noChanges:"当前没有待处理改动。",changesTitle:"当前变更",rulesFirstHint:"规则先于生成,草稿不能绕过校验。",stage:"暂存",unstage:"取消暂存",preview:"预览",stageFailed:"暂存操作失败。",diffTitle:"差异预览",diffLoadFailed:"差异内容暂时没有拉回来。",binaryDiff:"这个文件是二进制改动,侧栏不直接展示内容。",stagedDiff:"暂存区 diff",worktreeDiff:"工作区 diff",emptyDiff:"当前没有可展示的文本差异。",diffTruncated:"差异内容过长,已经做了截断保护。",commitTitle:"提交草稿",defaultRuleName:"默认提交规则",language:"语言",maxLength:"长度",bodyRequired:"正文必填",bodyOptional:"正文可选",issueRequired:"Issue 必填",issueOptional:"Issue 可选",commitSubject:"提交标题",commitSubjectPlaceholder:"在这里输入提交信息",commitBody:"提交正文",commitBodyPlaceholder:"把这次改动说清楚,别写空话。",commitFooter:"提交脚注",commitFooterPlaceholder:"例如:Refs: #123",generateDraft:"AI 起草",validate:"校验草稿",commit:"执行提交",draftFailed:"提交草稿生成失败。",validateFailed:"提交规则校验失败。",commitFailed:"提交失败。",commitSuccess:"提交已经写入当前仓库。",validationPassed:"规则校验通过,可以继续提交。",validationFailed:"规则校验没有通过,先把下面的问题修掉。",branchTitle:"分支",branchPlaceholder:"输入要切换或创建的分支名",switchBranch:"切换",createBranch:"新建",branchFailed:"分支操作失败。",historyTitle:"最近历史",historyHint:"只放最近几条,不做图形历史树。",noHistory:"当前没有可展示的提交历史。",viewAllVersions:"查看所有版本",viewAllVersionsDescription:"这里展示当前仓库已加载的版本历史,共 {count} 条。",viewCommitChanges:"查看更改文件与 DIFF",copyCommitMessage:"复制提交信息",copyCommitMessageSuccess:"提交信息已复制。",copyCommitVersion:"复制 Git 版本号",copyCommitVersionSuccess:"Git 版本号已复制。",commitDetailTitle:"版本详情",commitDetailDescription:"当前查看提交 {hash} 的完整改动。",commitDetailLoading:"正在读取提交详情…",commitDetailEmpty:"当前没有可展示的提交详情。",commitDetailLoadFailed:"提交详情暂时没有拉回来。",commitVersionLabel:"Git 版本号",commitHashLabel:"提交 Hash",commitAuthorLabel:"作者",commitTimeLabel:"提交时间",commitMessageLabel:"提交信息",changedFilesTitle:"变更文件",commitDiffLabel:"提交 DIFF",renamedFromLabel:"从 {path} 重命名",explainCommitTitle:"解释版本更改",explainCommitDescription:"先选择一个 CLI 供应商,再新建会话分析这个提交。",explainCommitAction:"解释更改",startExplainCommit:"开始解释",explainCommitStarted:"解释会话已经创建。",explainCommitFailed:"解释更改失败。",remoteTitle:"远程同步",remoteReady:"当前仓库已配置远程。",remoteMissing:"当前仓库还没有远程。",fetch:"Fetch",pull:"Pull",push:"Push",pushNow:"立即推送",publish:"Publish",remoteFailed:"远程同步失败。",remoteAuthAction:"远程认证",remoteAuthTitle:"设置远程仓库认证",remoteAuthDescription:"需要认证的远程仓库,在这里填写本次页面会话使用的用户名、密码或 token。",remoteAuthDescriptionGithub:"检测到当前远程仓库来自 GitHub。GitHub 的 HTTPS Git 操作请使用 Personal Access Token (PAT),不要填写 GitHub 登录密码。",remoteAuthStatusLabel:"认证状态",remoteAuthManageHint:"按仓库分别查看和配置",remoteAuthManageTitle:"管理远程仓库认证",remoteAuthManageDescription:"每个远程仓库单独显示自己的凭据状态,也在这里分别配置。",remoteAuthConfigured:"已配置",remoteAuthConfiguredInSession:"当前页面已配置",remoteAuthConfiguredOnHost:"Host 已配置",remoteAuthNotConfigured:"未配置",remoteAuthGithubPatLabel:"Personal Access Token (PAT)",remoteAuthGithubPatPlaceholder:"输入 GitHub PAT",remoteAuthGithubUsernamePlaceholder:"输入 GitHub 用户名",remoteAuthGithubPatHint:"GitHub 不支持用账号密码做 Git HTTPS 认证。basic 模式请填写 GitHub 用户名 + PAT;token 模式可以直接填写 PAT。",remoteAuthRemember:"记住账号密码到 Host",remoteAuthSessionHint:"默认只在当前页面会话里生效;勾选“记住账号密码到 Host”后,远程同步成功时会写到 Host,后续自动复用。",remoteAuthRememberHint:"勾选记住后,本次远程同步成功时会把认证写到 Host。",remoteAuthSave:"保存认证",remoteAuthSaved:"远程仓库认证已保存,请重新执行同步。",remoteAuthCleared:"已清除当前页面会话里的远程认证设置。",selectRemoteTitle:"选择推送仓库",selectRemoteDesc:"勾选要推送到的远程仓库,支持多选。",noRemotes:"当前仓库没有配置任何远程仓库。",pushSelected:"推送 ({count})",pushing:"推送中…",pushAllSuccess:"已成功推送到 {count} 个远程仓库。",errors:{unauthorized:"当前登录态已经失效,请重新登录后再试。",workspaceNotFound:"当前会话绑定的工作区不存在,先确认工作区是否还可用。",invalidWorkspace:"当前工作区配置无效,Git 侧栏不能脱离仓库根目录执行。",notGitRepository:"当前工作区不是 Git 仓库,Git 侧栏不会伪造状态。",repoNotFound:"当前工作区找不到可用的 Git 仓库根目录。",pathOutOfWorkspace:"Git 目标超出了当前工作区仓库边界,操作已被拦截。",invalidTarget:"Git 目标路径无效,请先刷新侧栏后重试。",notStaged:"目标文件还不在暂存区里,先确认当前变更状态。",emptyStagedChanges:"暂存区为空,先把要提交的改动放进暂存区。",branchConflict:"当前分支存在冲突或不是快进更新,先同步并处理差异。",branchNotFound:"目标分支不存在,先确认分支名是否正确。",remoteNotFound:"当前仓库还没有可用的 origin 远程,先配置远程再同步。",remoteAuthFailed:"远程仓库认证失败,请先确认当前仓库凭据可用。",pushFailed:"推送失败,请先检查远程状态和本地提交。",pullFailed:"拉取失败,请先确认远程分支状态。",remoteFailed:"远程同步失败,请检查 Git 输出和网络状态。",initFailed:"Git 工作区初始化失败,请确认当前目录可写且 Git 可用。",commitValidationFailed:"提交草稿还没通过规则校验,先把校验问题修掉。",commandTimeout:"Git 操作超时了,先确认仓库状态和网络环境。"}}},Ys="default-host";function zd(i){return!!(i&&"discoveryKey"in i&&typeof i.discoveryKey=="string")}function hm(i,r){var o;return r?i.hosts.find(c=>c.id===r)??((o=i.discoveredHosts)==null?void 0:o.find(c=>c.id===r))??null:null}function mm(i,r){var o;return r?i.hosts.find(c=>c.baseUrl===r)??((o=i.discoveredHosts)==null?void 0:o.find(c=>c.baseUrl===r))??null:null}function Tn(i){var r,o,c,u;return i.activeDiscoveredHostId&&((r=i.discoveredHosts)!=null&&r.some(p=>p.id===i.activeDiscoveredHostId))?i.activeDiscoveredHostId:i.activeHostId&&i.hosts.some(p=>p.id===i.activeHostId)?i.activeHostId:((o=i.hosts[0])==null?void 0:o.id)??((u=(c=i.discoveredHosts)==null?void 0:c[0])==null?void 0:u.id)??null}function Da(i){return hm(i,Tn(i))}function gm(i){var r;return((r=Da(i))==null?void 0:r.baseUrl)??null}function bm(i){return i==="http:"||i==="https:"}function Ue(i){const r=i.trim();if(!r)throw new Error("EMPTY_SERVER_URL");const o=/^[a-zA-Z][a-zA-Z\d+.-]*:\/\//.test(r)?r:`http://${r}`,c=new URL(o);if(!bm(c.protocol))throw new Error("INVALID_SERVER_PROTOCOL");c.hash="",c.search="";const u=c.pathname.replace(/\/+$/,"");return`${c.origin}${u==="/"?"":u}`}const Tt="codingns.auth.remembered-login";function Ji(){return typeof window<"u"&&typeof window.localStorage<"u"}function Zy(i){return i.isNativeMobile?!0:i.isDesktop?i.ui.osFamily==="windows"||i.ui.osFamily==="macos":!1}function ym(i){const r={credentials:null,legacyServerBaseUrl:null};if(!Ji())return r;const o=window.localStorage.getItem(Tt);if(!o)return r;try{const c=JSON.parse(o);if($s(c))return{credentials:i?c[i]??null:null,legacyServerBaseUrl:null};const u=qd(c);if(!u||!i)return{credentials:null,legacyServerBaseUrl:(u==null?void 0:u.serverBaseUrl)??null};const p={hostId:i,username:u.username,password:u.password,savedAt:Date.now()},y={[i]:p};return window.localStorage.setItem(Tt,JSON.stringify(y)),{credentials:p,legacyServerBaseUrl:u.serverBaseUrl}}catch{return window.localStorage.removeItem(Tt),r}}function eS(i){return ym(i).credentials}function tS(i){if(!Ji())return;const r=jd(),o={hostId:i.hostId,username:i.username.trim(),password:i.password,savedAt:Date.now()};!o.hostId||!o.username||!o.password||window.localStorage.setItem(Tt,JSON.stringify({...r,[o.hostId]:o}))}function Sm(i){if(!Ji())return;const r=window.localStorage.getItem(Tt);if(r)try{const o=JSON.parse(r);if($s(o))return;const c=qd(o);if(!c){window.localStorage.removeItem(Tt);return}window.localStorage.setItem(Tt,JSON.stringify({...c,serverBaseUrl:Ue(i)}))}catch{window.localStorage.removeItem(Tt)}}function aS(i){if(!Ji()||!i)return;const r=jd();if(!r[i])return;const o={...r};if(delete o[i],Object.keys(o).length===0){window.localStorage.removeItem(Tt);return}window.localStorage.setItem(Tt,JSON.stringify(o))}function jd(){if(!Ji())return{};const i=window.localStorage.getItem(Tt);if(!i)return{};try{const r=JSON.parse(i);return $s(r)?r:{}}catch{return{}}}function $s(i){return typeof i!="object"||i===null||Array.isArray(i)?!1:Object.values(i).every(r=>Tm(r))}function Tm(i){if(typeof i!="object"||i===null)return!1;const r=i;return typeof r.hostId=="string"&&typeof r.username=="string"&&typeof r.password=="string"&&typeof r.savedAt=="number"&&r.username.trim().length>0&&r.password.length>0}function qd(i){if(typeof i!="object"||i===null)return null;const r=i;if(typeof r.username!="string"||typeof r.password!="string"||typeof r.serverBaseUrl!="string")return null;const o=r.username.trim(),c=r.password,u=Ue(r.serverBaseUrl);return!o||!c?null:{username:o,password:c,serverBaseUrl:u}}function km(i){return{filePath:(i==null?void 0:i.filePath)??null,routePath:(i==null?void 0:i.routePath)??null}}function Gd(i={}){return{x:i.x??null,y:i.y??null,width:i.width??1200,height:i.height??780,minWidth:i.minWidth??720,minHeight:i.minHeight??480}}function iS(i){return{windowId:i.windowId,kind:i.kind,workspaceId:i.workspaceId??null,workspaceName:i.workspaceName??null,sessionId:i.sessionId??null,mode:i.mode??"docked",bounds:Gd(i.bounds),focusOwner:i.focusOwner??null,payload:km(i.payload)}}function ti(i){return{...i,bounds:{...i.bounds},payload:{...i.payload}}}function wm(i){return{descriptors:Object.fromEntries(Object.entries(i.descriptors).map(([o,c])=>[o,ti(c)])),openWindowIds:[...i.openWindowIds],lastActiveWindowId:i.lastActiveWindowId}}function ud(){return{descriptors:{},openWindowIds:[],lastActiveWindowId:null}}function vm(i,r){return{...i,...r,windowId:i.windowId,bounds:Gd({...i.bounds,...r.bounds}),payload:{...i.payload,...r.payload}}}class Cm{constructor(){L(this,"state",ud());L(this,"listeners",new Set);L(this,"subscribe",r=>(this.listeners.add(r),()=>{this.listeners.delete(r)}));L(this,"getState",()=>wm(this.state))}registerDescriptor(r){const o=ti(r),c=this.state.openWindowIds.includes(o.windowId);return this.state={...this.state,descriptors:{...this.state.descriptors,[o.windowId]:o},lastActiveWindowId:c?o.windowId:this.state.lastActiveWindowId},this.emit(),ti(o)}updateDescriptor(r,o){const c=this.state.descriptors[r];if(!c)return null;const u=vm(c,o);return this.state={...this.state,descriptors:{...this.state.descriptors,[r]:u}},this.emit(),ti(u)}getDescriptor(r){const o=this.state.descriptors[r];return o?ti(o):null}getWindows(){return Object.values(this.state.descriptors).map(r=>({descriptor:ti(r),isOpen:this.state.openWindowIds.includes(r.windowId)}))}markWindowOpen(r){if(!this.state.descriptors[r])return!1;const o=this.state.openWindowIds.filter(c=>c!==r);return this.state={...this.state,openWindowIds:[...o,r],lastActiveWindowId:r},this.emit(),!0}markWindowClosed(r){if(!this.state.openWindowIds.includes(r))return!1;const o=this.state.openWindowIds.filter(c=>c!==r);return this.state={...this.state,openWindowIds:o,lastActiveWindowId:this.state.lastActiveWindowId===r?o.at(-1)??null:this.state.lastActiveWindowId},this.emit(),!0}isWindowOpen(r){return this.state.openWindowIds.includes(r)}removeWindow(r){if(!this.state.descriptors[r])return!1;const o={...this.state.descriptors};delete o[r];const c=this.state.openWindowIds.filter(u=>u!==r);return this.state={descriptors:o,openWindowIds:c,lastActiveWindowId:this.state.lastActiveWindowId===r?c.at(-1)??null:this.state.lastActiveWindowId},this.emit(),!0}clear(){const r=this.state.openWindowIds.length>0||this.state.lastActiveWindowId!==null||Object.keys(this.state.descriptors).length>0;this.state=ud(),r&&this.emit()}emit(){for(const r of this.listeners)r()}}function Dm(){return new Cm}const Bs=Dm();function Pm(){return Bs}function rS(i){return He.useSyncExternalStore(Bs.subscribe,()=>i(Bs.getState()))}const Am=Pm();function Kd(){return typeof window<"u"&&typeof window.__TAURI_INTERNALS__<"u"}function Qd(){var p,y;if(typeof navigator>"u")return"unknown";const i=navigator.userAgent.toLowerCase(),r=navigator.userAgentData,o=((p=r==null?void 0:r.platform)==null?void 0:p.toLowerCase())??((y=navigator.platform)==null?void 0:y.toLowerCase())??"",c=`${o} ${i}`,u=o.includes("mac")&&navigator.maxTouchPoints>1;return c.includes("android")?"android":c.includes("iphone")||c.includes("ipad")||c.includes("ipod")||u?"ios":c.includes("mac")?"macos":c.includes("win")?"windows":c.includes("linux")?"linux":"unknown"}function Lm(i){var r;return typeof i=="number"&&Number.isFinite(i)&&i>0?i:typeof window<"u"&&Number.isFinite(window.innerWidth)&&window.innerWidth>0?window.innerWidth:typeof document<"u"&&Number.isFinite((r=document.documentElement)==null?void 0:r.clientWidth)&&document.documentElement.clientWidth>0?document.documentElement.clientWidth:1280}function Rm(i){const r=Lm(i);return r<768?"compact":r<1024?"medium":"expanded"}function Fm(i){const r=Qd();return i==="desktop"?{osFamily:r,windowControlsStyle:r==="macos"?"traffic-lights":r==="windows"?"windows":"none",prefersDesktopChrome:!0,prefersOverlayTitlebar:r==="macos",prefersSystemFontStack:!0}:{osFamily:r,windowControlsStyle:"none",prefersDesktopChrome:!1,prefersOverlayTitlebar:!1,prefersSystemFontStack:!0}}function _(i){return{ok:!1,errorCode:"PLATFORM_NOT_SUPPORTED",detail:i}}function Em(i){const r=i instanceof Error?i.message:"桌面壳调用失败。",o=r.match(/^([A-Z0-9_]+):\s*(.+)$/);return o?{errorCode:o[1],detail:o[2]}:{errorCode:"SHELL_BRIDGE_ERROR",detail:r}}async function oe(i,r){return Qi(i,r)}async function Qi(i,r){if(!Kd())return _("当前运行环境不支持桌面壳能力。");try{return{ok:!0,value:await window.__TAURI_INTERNALS__.invoke(i,r)}}catch(o){return{ok:!1,...Em(o)}}}function Mm(i){switch(i){case"selection":return 10;case"action":return[12];case"gesture":return[10,18,10];case"success":return[16,30,20];case"warning":return[20,36,18];case"error":return[24,40,24,40,20];default:return 10}}function Yd(){return typeof navigator<"u"&&typeof navigator.vibrate=="function"}async function $d(i){if(Yd())try{navigator.vibrate(Mm(i))}catch{return}}async function Js(i,r){if(typeof window>"u"||typeof Notification>"u")return _("当前环境不支持系统通知。");try{if(Notification.permission==="default"&&await Notification.requestPermission()!=="granted"||Notification.permission!=="granted")return _("系统通知权限未授予。");const o=new Notification(i,{body:r});return o.onerror=()=>{},{ok:!0}}catch(o){return{ok:!1,errorCode:"NOTIFICATION_FAILED",detail:o instanceof Error?o.message:"系统通知发送失败。"}}}class Im{constructor(){L(this,"supported",!1)}openExternal(r){return typeof window>"u"?Promise.resolve(_("当前环境无法打开外部链接。")):(window.open(r,"_blank","noopener,noreferrer"),Promise.resolve({ok:!0}))}openLocalFile(){return Promise.resolve(_("当前不是桌面端运行环境。"))}revealInFileManager(){return Promise.resolve(_("当前不是桌面端运行环境。"))}getPlatformInfo(){return Promise.resolve(_("当前不是桌面端运行环境。"))}showNotification(r,o){return Js(r,o)}writeClipboardText(){return Promise.resolve(_("当前不是桌面端运行环境。"))}setWindowState(){return Promise.resolve(_("当前不是桌面端运行环境。"))}readDesktopConfig(){return Promise.resolve(_("当前不是桌面端运行环境。"))}writeDesktopConfig(){return Promise.resolve(_("当前不是桌面端运行环境。"))}scanLocalHosts(){return Promise.resolve(_("当前不是桌面端运行环境。"))}getRuntimeInfo(){return Promise.resolve(_("当前不是桌面端运行环境。"))}checkForUpdate(){return Promise.resolve(_("当前不是桌面端运行环境。"))}downloadUpdate(){return Promise.resolve({ok:!1,errorCode:"PLATFORM_NOT_SUPPORTED",detail:"当前不是桌面端运行环境。"})}installUpdate(){return Promise.resolve({ok:!1,errorCode:"PLATFORM_NOT_SUPPORTED",detail:"当前不是桌面端运行环境。"})}getAndroidRuntimeInfo(){return Promise.resolve(_("当前不是 Android 原生运行环境。"))}installAndroidUpdate(){return Promise.resolve({ok:!1,status:"failed",detail:"当前不是 Android 原生运行环境。"})}rollbackToPreviousVersion(){return Promise.resolve(_("当前不是桌面端运行环境。"))}pickDirectory(){return Promise.resolve(_("当前不是桌面端运行环境。"))}createWindow(){return Promise.resolve(_("当前不是桌面端运行环境。"))}closeWindow(){return Promise.resolve(_("当前不是桌面端运行环境。"))}focusWindow(){return Promise.resolve(_("当前不是桌面端运行环境。"))}listWindows(){return Promise.resolve(_("当前不是桌面端运行环境。"))}isWindowOpen(){return Promise.resolve(_("当前不是桌面端运行环境。"))}getWindowDescriptor(){return Promise.resolve(_("当前不是桌面端运行环境。"))}syncWindowDescriptor(){return Promise.resolve(_("当前不是桌面端运行环境。"))}updateWindowBounds(){return Promise.resolve(_("当前不是桌面端运行环境。"))}syncNativeSidebarLayout(){return Promise.resolve(_("当前不是桌面端运行环境。"))}}class xm{constructor(){L(this,"supported",Yd())}trigger(r){return $d(r)}}class Om{constructor(){L(this,"supported",!0)}openExternal(r){return oe("open_external",{url:r})}openLocalFile(r){return oe("open_local_file",{path:r})}revealInFileManager(r){return oe("reveal_in_file_manager",{path:r})}getPlatformInfo(){return oe("get_platform_info")}async showNotification(r,o){const c=await Js(r,o);return c.ok?c:oe("show_notification",{title:r,body:o})}writeClipboardText(r){return oe("copy_text",{text:r})}setWindowState(r){return oe("set_window_state",{state:r})}readDesktopConfig(){return oe("read_desktop_config")}writeDesktopConfig(r){return oe("write_desktop_config",{patch:r})}scanLocalHosts(){return oe("scan_local_hosts")}getRuntimeInfo(){return oe("get_runtime_info")}checkForUpdate(r){return oe("check_for_update",{channel:r})}async downloadUpdate(r){const o=await oe("download_update",{channel:r});return o.ok?o.value??{ok:!0}:{ok:!1,errorCode:o.errorCode,detail:o.detail}}async installUpdate(r){const o=await oe("install_update",{channel:r});return o.ok?o.value??{ok:!0}:{ok:!1,errorCode:o.errorCode,detail:o.detail}}getAndroidRuntimeInfo(){return Promise.resolve(_("当前不是 Android 原生运行环境。"))}installAndroidUpdate(){return Promise.resolve({ok:!1,status:"failed",detail:"当前不是 Android 原生运行环境。"})}rollbackToPreviousVersion(){return oe("rollback_to_previous_version")}pickDirectory(){return oe("pick_directory")}createWindow(r){return oe("create_window",{descriptor:r})}closeWindow(r){return oe("close_window",{windowId:r})}focusWindow(r){return oe("focus_window",{windowId:r})}listWindows(){return oe("list_windows")}isWindowOpen(r){return oe("is_window_open",{windowId:r})}getWindowDescriptor(r){return typeof r=="string"?oe("get_window_descriptor",{windowId:r}):oe("get_window_descriptor")}syncWindowDescriptor(r){return oe("sync_window_descriptor",{descriptor:r})}updateWindowBounds(r,o){return oe("update_window_bounds",{windowId:r,bounds:o})}syncNativeSidebarLayout(r){return oe("sync_native_sidebar_layout",{layout:r})}}class Hm{constructor(){L(this,"supported",!0)}async trigger(r){(await Qi("perform_haptic_feedback",{kind:r})).ok||await $d(r)}}class Nm{constructor(r){L(this,"supported",!0);this.platform=r}openExternal(r){return typeof window>"u"?Promise.resolve(_("当前环境无法打开外部链接。")):(window.open(r,"_blank","noopener,noreferrer"),Promise.resolve({ok:!0}))}openLocalFile(){return Promise.resolve(_("当前不是桌面端运行环境。"))}revealInFileManager(){return Promise.resolve(_("当前不是桌面端运行环境。"))}getPlatformInfo(){return Promise.resolve(_("当前不是桌面端运行环境。"))}showNotification(r,o){return Js(r,o)}writeClipboardText(r){return Qi("copy_text",{text:r})}setWindowState(){return Promise.resolve(_("当前平台不支持窗口控制。"))}readDesktopConfig(){return Promise.resolve(_("当前不是桌面端运行环境。"))}writeDesktopConfig(){return Promise.resolve(_("当前不是桌面端运行环境。"))}scanLocalHosts(){return Promise.resolve(_("当前不是桌面端运行环境。"))}getRuntimeInfo(){return Promise.resolve(_("当前不是桌面端运行环境。"))}checkForUpdate(){return Promise.resolve(_("当前不是桌面端运行环境。"))}downloadUpdate(){return Promise.resolve({ok:!1,errorCode:"PLATFORM_NOT_SUPPORTED",detail:"当前不是桌面端运行环境。"})}installUpdate(){return Promise.resolve({ok:!1,errorCode:"PLATFORM_NOT_SUPPORTED",detail:"当前不是桌面端运行环境。"})}getAndroidRuntimeInfo(){return this.platform!=="android"?Promise.resolve(_("当前不是 Android 原生运行环境。")):Qi("get_android_runtime_info")}async installAndroidUpdate(r){if(this.platform!=="android")return{ok:!1,status:"failed",detail:"当前不是 Android 原生运行环境。"};const o=await Qi("install_android_update",{manifest:r});return o.ok?o.value??{ok:!1,status:"failed",detail:"Android 更新结果为空。"}:{ok:!1,status:"failed",detail:o.detail}}rollbackToPreviousVersion(){return Promise.resolve(_("当前不是桌面端运行环境。"))}pickDirectory(){return Promise.resolve(_("当前不是桌面端运行环境。"))}createWindow(){return Promise.resolve(_("当前不是桌面端运行环境。"))}closeWindow(){return Promise.resolve(_("当前不是桌面端运行环境。"))}focusWindow(){return Promise.resolve(_("当前不是桌面端运行环境。"))}listWindows(){return Promise.resolve(_("当前不是桌面端运行环境。"))}isWindowOpen(){return Promise.resolve(_("当前不是桌面端运行环境。"))}getWindowDescriptor(){return Promise.resolve(_("当前不是桌面端运行环境。"))}syncWindowDescriptor(){return Promise.resolve(_("当前不是桌面端运行环境。"))}updateWindowBounds(){return Promise.resolve(_("当前不是桌面端运行环境。"))}syncNativeSidebarLayout(){return Promise.resolve(_("当前不是桌面端运行环境。"))}}function Xs(){if(!Kd())return"web";const i=Qd();return i==="ios"?"ios":i==="android"?"android":"desktop"}function Rn(i={}){const r=Xs(),o=Rm(i.viewportWidth),c=r==="ios"||r==="android";return{platform:r,isDesktop:r==="desktop",isWeb:r==="web",isMobile:o!=="expanded",isNativeMobile:c,viewportClass:o,ui:Fm(r),bridge:r==="desktop"?new Om:c?new Nm(r):new Im,windows:Am,haptics:c?new Hm:new xm}}const Us="codingns.client.runtime-config",Bm=4,Is="HOST";function Um(i){return i==="desktop"||i==="ios"||i==="android"}function Ws(i){return i==="en"||i==="en-US"?"en-US":"zh-CN"}function Wm(){return typeof navigator>"u"?"zh-CN":Ws(navigator.language)}function dd(i){return i==="acceptEdits"||i==="bypassPermissions"?i:"default"}function Jd(){return typeof window<"u"&&typeof window.localStorage<"u"}function _m(){if(!Jd())return null;const i=window.localStorage.getItem(Us);if(!i)return null;try{return JSON.parse(i)}catch{return window.localStorage.removeItem(Us),null}}function Xd(i){Jd()&&window.localStorage.setItem(Us,JSON.stringify(ip(i)))}function Vm(){var i;return typeof window>"u"||!((i=window.location)!=null&&i.origin)?null:window.location.origin}function zm(i){if(!i)return null;try{return Ue(i)}catch{return null}}function Zd(i){if(i==="web"){const r=zm(Vm());if(r)return r}return Ue("http://127.0.0.1:3002")}function ep(){return new Date().toISOString()}function jm(){return{status:"idle",lastScannedAt:null,cooldownUntil:null,errorCode:null,errorDetail:null}}function ke(i){return typeof i=="string"&&i.trim()?i.trim():null}function pd(i,r){return ke(i)??r}function tp(i){try{const r=new URL(i).hostname.toLowerCase();return r==="localhost"||r==="127.0.0.1"||r==="::1"||r==="[::1]"?"local":/^10\./.test(r)||/^192\.168\./.test(r)||/^172\.(1[6-9]|2\d|3[0-1])\./.test(r)?"lan":"remote"}catch{return"custom"}}function ap(i){try{const r=new URL(i),o=r.pathname==="/"?"":r.pathname.replace(/\/+$/,"");return`${r.host}${o}`}catch{return i}}function _s(i){var o;const r=typeof i=="string"?(o=i.match(/[A-Za-z]/g))==null?void 0:o.join("").toUpperCase().slice(0,Bm):null;return r||null}function qm(i){try{const r=new URL(i),c=r.hostname.replace(/^\[|\]$/g,"").split(".").filter(Boolean),u=c.length>0?c[c.length-1]==="localhost"?Is:c[c.length-1]:r.host;return _s(u)??Is}catch{return _s(i)??Is}}function kn(i,r,o={}){const c=Ue(i),u=Object.prototype.hasOwnProperty.call(o,"alias");return{id:ke(o.id)??Ys,name:ke(o.name)??ap(c),alias:u?_s(o.alias):qm(c),baseUrl:c,kind:o.kind??tp(c),peerEnabled:o.peerEnabled===!0,peerHostId:ke(o.peerHostId)??null,createdAt:pd(o.createdAt,r),updatedAt:pd(o.updatedAt,r),lastConnectedAt:ke(o.lastConnectedAt)??null,lastUserId:ke(o.lastUserId)??null,lastUsername:ke(o.lastUsername)??null,relayTunnel:Qm(o.relayTunnel)}}function Gm(i){return typeof i=="object"&&i!==null}function fd(i,r){if(!Array.isArray(i))return[];const o=new Set,c=[];for(let u=0;u<i.length;u+=1){const p=i[u];if(!Gm(p))continue;const y=ke(p.baseUrl);if(y)try{const S=u===0?Ys:`host-${u+1}`,A=kn(y,r,{...p,id:ke(p.id)??S});if(o.has(A.id))continue;o.add(A.id),c.push(A)}catch{continue}}return c}function Km(i){return typeof i=="object"&&i!==null}function Qm(i){if(typeof i!="object"||i===null||Array.isArray(i))return null;const r=ke(i.provider),o=i.enabled,c=ke(i.tunnelDomain),u=ke(i.controlBaseUrl),p=ke(i.bindingId),y=ke(i.hostFingerprint),S=Ym(i.candidateEndpoints);if(r!=="codingns_relay"||typeof o!="boolean"||!c||!u)return null;try{const A=Ue(u);return/^[a-z0-9-]+(\.[a-z0-9-]+)+$/i.test(c)?{provider:r,enabled:o,tunnelDomain:c.trim().toLowerCase(),controlBaseUrl:A,bindingId:p,hostFingerprint:y,candidateEndpoints:S}:null}catch{return null}}function Ym(i){if(!Array.isArray(i))return[];const r=[],o=new Set;for(const c of i){if(typeof c!="object"||c===null||Array.isArray(c))continue;const u=ke(c.endpointId),p=ke(c.kind),y=ke(c.url),S=c.priority,A=ke(c.expiresAt),O=ke(c.source);if(!(!u||!y||typeof S!="number"||!Number.isFinite(S)||p!=="relay"&&p!=="lan"&&p!=="loopback"&&p!=="tailscale"&&p!=="custom"||O!=="host_reported"&&O!=="desktop_scan"&&O!=="user_saved"))try{const E=Ue(y);if(o.has(E))continue;r.push({endpointId:u,kind:p,url:E,priority:S,expiresAt:A,source:O}),o.add(E)}catch{continue}}return r.sort((c,u)=>c.priority!==u.priority?c.priority-u.priority:c.url.localeCompare(u.url))}function hd(i,r,o){const c=Ue(r),u=Da(i);return u?i.hosts.map(p=>p.id===u.id?kn(c,o,{...p,name:ap(c),kind:tp(c),createdAt:p.createdAt,updatedAt:o}):p):[kn(c,o)]}function Zs(i){const r=ep();return{platform:i,activeHostId:Ys,hosts:[kn(Zd(i),r)],discoveredHosts:[],activeDiscoveredHostId:null,localHostDiscovery:jm(),releaseChannel:"stable",betaChannelConsentAcceptedAt:null,autoReconnect:!0,autoCheckUpdate:i==="desktop",autoDownloadUpdate:!1,language:Wm(),defaultPermissionMode:"default"}}function wn(i,r){var A,O;if(!r||!Km(r))return i;const o=r.platform??i.platform,c=Zs(o),u=ep();if(!Um(o)){let E=r.hosts!==void 0?fd(r.hosts,u):c.hosts;r.hostBaseUrl&&(E=hd(i,r.hostBaseUrl,u)),E.length===0&&(E=c.hosts);const W=r.activeHostId??i.activeHostId??c.activeHostId,j=E.some(ye=>ye.id===W)?W:((A=E[0])==null?void 0:A.id)??null;return{platform:o,activeHostId:j,hosts:E,discoveredHosts:i.discoveredHosts,activeDiscoveredHostId:null,localHostDiscovery:i.localHostDiscovery,releaseChannel:r.releaseChannel??i.releaseChannel,betaChannelConsentAcceptedAt:Object.prototype.hasOwnProperty.call(r,"betaChannelConsentAcceptedAt")?r.betaChannelConsentAcceptedAt:i.betaChannelConsentAcceptedAt,autoReconnect:r.autoReconnect??i.autoReconnect,autoCheckUpdate:r.autoCheckUpdate??i.autoCheckUpdate,autoDownloadUpdate:r.autoDownloadUpdate??i.autoDownloadUpdate,language:Ws(r.language??i.language),defaultPermissionMode:dd(r.defaultPermissionMode??i.defaultPermissionMode)}}let p=r.hosts!==void 0?fd(r.hosts,u):i.hosts;r.hostBaseUrl&&(p=hd(i,r.hostBaseUrl,u)),p.length===0&&(p=c.hosts);const y=r.activeHostId??i.activeHostId,S=p.some(E=>E.id===y)?y:((O=p[0])==null?void 0:O.id)??null;return{platform:o,activeHostId:S,hosts:p,discoveredHosts:i.discoveredHosts,activeDiscoveredHostId:i.activeDiscoveredHostId&&i.discoveredHosts.some(E=>E.id===i.activeDiscoveredHostId)?i.activeDiscoveredHostId:null,localHostDiscovery:i.localHostDiscovery,releaseChannel:r.releaseChannel??i.releaseChannel,betaChannelConsentAcceptedAt:r.betaChannelConsentAcceptedAt??i.betaChannelConsentAcceptedAt,autoReconnect:r.autoReconnect??i.autoReconnect,autoCheckUpdate:r.autoCheckUpdate??i.autoCheckUpdate,autoDownloadUpdate:r.autoDownloadUpdate??i.autoDownloadUpdate,language:Ws(r.language??i.language),defaultPermissionMode:dd(r.defaultPermissionMode??i.defaultPermissionMode)}}function ip(i){return{platform:i.platform,activeHostId:i.activeHostId,hosts:i.hosts,releaseChannel:i.releaseChannel,betaChannelConsentAcceptedAt:i.betaChannelConsentAcceptedAt,autoReconnect:i.autoReconnect,autoCheckUpdate:i.autoCheckUpdate,autoDownloadUpdate:i.autoDownloadUpdate,language:i.language,defaultPermissionMode:i.defaultPermissionMode}}function rp(i,r){return wn(Zs(r),i)}async function $m(){const i=Rn(),r=Zs(i.platform),o=_m();let c=null;if(i.isDesktop){const p=await i.bridge.readDesktopConfig();p.ok&&p.value&&(c=p.value)}const u=wn(wn(r,o),c);return Xd(u),u}async function Jm(i,r){var p;const o=wn(i,r);Xd(o);const c=(p=Da(o))==null?void 0:p.baseUrl;c&&Sm(c);const u=Rn();return u.isDesktop&&await u.bridge.writeDesktopConfig(ip(o)),o}function Xm(){return rp(null,Xs())}class Zm{constructor(){L(this,"state",Xm());L(this,"initialized",!1);L(this,"listeners",new Set);L(this,"subscribe",r=>(this.listeners.add(r),()=>{this.listeners.delete(r)}));L(this,"getState",()=>this.state);L(this,"isInitialized",()=>this.initialized)}hydrate(r){this.state=rp(r,this.state.platform),this.initialized=!0,this.emit()}updateRuntime(r){const o=r.discoveredHosts??this.state.discoveredHosts,c=r.activeDiscoveredHostId!==void 0?r.activeDiscoveredHostId:this.state.activeDiscoveredHostId,u=c&&o.some(y=>y.id===c)?c:null,p=r.localHostDiscovery??this.state.localHostDiscovery;o===this.state.discoveredHosts&&u===this.state.activeDiscoveredHostId&&p===this.state.localHostDiscovery||(this.state={...this.state,discoveredHosts:o,activeDiscoveredHostId:u,localHostDiscovery:p},this.emit())}async initialize(){const r=await $m();return this.hydrate(r),r}async update(r){const o=await Jm(this.state,r);return this.hydrate(o),o}emit(){for(const r of this.listeners)r()}}const Z=new Zm;function nS(i){return He.useSyncExternalStore(Z.subscribe,()=>i(Z.getState()))}function eg(i){return i.endsWith("/")?i:`${i}/`}function tg(i){return i.replace(/^\/+/,"")}function vn(){const i=Z.getState();return gm(i)??Zd(i.platform)}function Fn(i,r=vn()){return new URL(tg(i),eg(r)).toString()}function oS(i,r=vn()){const o=new URL(Fn(i,r));return o.protocol=o.protocol==="https:"?"wss:":"ws:",o.toString()}const ag=3e4;class ig{constructor(){L(this,"hints",new Map);L(this,"listeners",new Set);L(this,"subscribe",r=>(this.listeners.add(r),()=>{this.listeners.delete(r)}))}remember(r,o){const c=r.trim(),u=o.trim();!c||!u||(this.hints.set(c,{hostId:c,baseUrl:u,savedAt:Date.now()}),this.emit())}forget(r){const o=r==null?void 0:r.trim();!o||!this.hints.delete(o)||this.emit()}clear(){this.hints.size!==0&&(this.hints.clear(),this.emit())}get(r){const o=r==null?void 0:r.trim();if(!o)return null;const c=this.hints.get(o);return c?Date.now()-c.savedAt>ag?(this.hints.delete(o),this.emit(),null):c:null}emit(){for(const r of this.listeners)r()}}const Ca=new ig;let el=!1,md=!1;function gd(){return rg(),el}function rg(){md||typeof window>"u"||(md=!0,window.addEventListener("beforeunload",bd,{capture:!0}),window.addEventListener("pagehide",bd,{capture:!0}),window.addEventListener("pageshow",ng,{capture:!0}))}function bd(){el=!0}function ng(){el=!1}class et extends Error{constructor(o,c){super(c.detail);L(this,"status");L(this,"errorCode");L(this,"field");L(this,"data");this.name="ApiError",this.status=o,this.errorCode=c.error_code,this.field=c.field,this.data=c.data}}function sS(i){return i instanceof et&&i.errorCode==="NETWORK_ERROR"}function lS(i){return i instanceof et&&i.errorCode==="INVALID_RESPONSE"}const yd="codingns.auth.client-instance-id",og="x-codingns-client-type",sg="x-codingns-client-instance-id";let sa=null;function np(){return{[og]:lg(),[sg]:cg()}}function lg(){const i=Xs();switch(i){case"desktop":case"ios":case"android":return i;default:return"web"}}function cg(){var o;if(sa)return sa;if(!ug())return sa=Sd(),sa;const i=(o=window.localStorage.getItem(yd))==null?void 0:o.trim();if(i)return sa=i,sa;const r=Sd();return window.localStorage.setItem(yd,r),sa=r,sa}function Sd(){var i;return typeof((i=globalThis.crypto)==null?void 0:i.randomUUID)=="function"?globalThis.crypto.randomUUID():`client-${Math.random().toString(36).slice(2)}-${Date.now().toString(36)}`}function ug(){return typeof window<"u"&&typeof window.localStorage<"u"}const dn="codingns.auth.session",Td=3e3,dg=15e3;class pg{constructor(){L(this,"state",{status:"anonymous",session:null,sessionReady:!0});L(this,"listeners",new Set);L(this,"sessionMap",{});L(this,"lastRuntimeConfigSyncKey",null);L(this,"lastStoredSessionValidationKey",null);L(this,"refreshInFlight",null);L(this,"subscribe",r=>(this.listeners.add(r),()=>{this.listeners.delete(r)}));L(this,"getState",()=>this.state);this.syncCurrentHostSession(),Z.subscribe(()=>{this.syncCurrentHostSession()})}async login(r,o){const c=this.getCurrentHost();if(!c){const{loginRequest:p}=await Wt(async()=>{const{loginRequest:S}=await Promise.resolve().then(()=>Ns);return{loginRequest:S}},void 0),y=await p(r,o);return this.updateState({status:"authenticated",session:y,sessionReady:!0}),y}const u=await this.loginForHost(c,r,o);return this.updateState({status:"authenticated",session:u,sessionReady:!0}),u}async loginForHost(r,o,c){var O;const{loginRequest:u}=await Wt(async()=>{const{loginRequest:E}=await Promise.resolve().then(()=>Ns);return{loginRequest:E}},void 0),{resolveLoginBaseUrlWithDirectCandidates:p}=await Wt(async()=>{const{resolveLoginBaseUrlWithDirectCandidates:E}=await import("./login-direct-candidate-resolver-DL8DS-Si.js");return{resolveLoginBaseUrlWithDirectCandidates:E}},[]),y=c??r.baseUrl,S=await p({host:r,requestedBaseUrl:y,platform:Z.getState().platform}),A=await u(o,S);return S!==r.baseUrl?Ca.remember(r.id,S):Ca.forget(r.id),this.persistSession(r,A),((O=this.getCurrentHost())==null?void 0:O.id)===r.id&&(this.updateState({status:"authenticated",session:A,sessionReady:!0}),this.scheduleRuntimeConfigSync(r,A)),A}async bootstrap(r,o,c){const{setupRequest:u}=await Wt(async()=>{const{setupRequest:p}=await Promise.resolve().then(()=>Ns);return{setupRequest:p}},void 0);await u({username:r,password:o},c)}hydrate(r){if(!r){this.clear();return}this.setSession(r)}async refresh(){if(this.refreshInFlight)return await this.refreshInFlight;const r=this.runRefresh();this.refreshInFlight=r;try{return await r}finally{this.refreshInFlight===r&&(this.refreshInFlight=null)}}shouldRefreshCurrentSession(r=Date.now()){return Tg(this.getCurrentSessionEnvelope(),r)}async runRefresh(){const r=this.state.session,o=r==null?void 0:r.refreshToken,c=this.getCurrentHost();if(!o)return this.clear(),{status:"invalid",session:null};this.state={...this.state,status:"refreshing"},this.emit();try{const u=await vd(o,c==null?void 0:c.baseUrl);return this.setSession(u,c),this.scheduleRuntimeConfigSync(c,u),{status:"refreshed",session:u}}catch(u){return wd(u)?(this.clear(),{status:"invalid",session:null}):(this.state={status:r?"authenticated":"anonymous",session:r,sessionReady:this.state.sessionReady},this.emit(),{status:"deferred",session:r,error:u})}}clear(){const r=this.getCurrentHost();if(this.lastRuntimeConfigSyncKey=null,this.lastStoredSessionValidationKey=null,!r){Ca.clear(),this.sessionMap={},this.persistSessionMap(),this.updateState({status:"anonymous",session:null,sessionReady:!0});return}if(Ca.forget(r.id),this.sessionMap[r.id]){const o={...this.sessionMap};delete o[r.id],this.sessionMap=o,this.persistSessionMap()}this.updateState({status:"anonymous",session:null,sessionReady:!0})}clearHostSession(r){var c;if(!r||(Ca.forget(r),!this.sessionMap[r]))return;const o={...this.sessionMap};delete o[r],this.sessionMap=o,this.persistSessionMap(),((c=this.getCurrentHost())==null?void 0:c.id)===r&&(this.lastRuntimeConfigSyncKey=null,this.lastStoredSessionValidationKey=null,this.updateState({status:"anonymous",session:null,sessionReady:!0}))}setSession(r,o=this.getCurrentHost(),c={}){o&&(this.persistSession(o,r),this.lastStoredSessionValidationKey=pn(o,r),this.updateState({status:"authenticated",session:r,sessionReady:c.sessionReady??!0}))}persistSession(r,o){this.lastStoredSessionValidationKey=pn(r,o),this.sessionMap={...this.sessionMap,[r.id]:{hostId:r.id,session:o,savedAt:Date.now()}},this.persistSessionMap();const c=new Date().toISOString();if(zd(r)){Z.updateRuntime({discoveredHosts:Z.getState().discoveredHosts.map(u=>u.id===r.id?{...u,lastConnectedAt:c,lastUserId:o.user.userId,lastUsername:o.user.username,updatedAt:c}:u)});return}Z.update({hosts:Z.getState().hosts.map(u=>u.id===r.id?{...u,lastConnectedAt:c,lastUserId:o.user.userId,lastUsername:o.user.username,updatedAt:c}:u)}).catch(()=>{})}syncCurrentHostSession(){var S;if(!Z.isInitialized())return;const r=this.getCurrentHost(),{sessionMap:o,migrated:c}=this.readSessionMapFromStorage(r),u=yg(o);this.sessionMap=u,(c||Object.keys(u).length!==Object.keys(o).length)&&this.persistSessionMap();const p=r?((S=u[r.id])==null?void 0:S.session)??null:null;if(!r||!p){this.lastStoredSessionValidationKey=null,this.updateState({status:"anonymous",session:null,sessionReady:!0}),this.lastRuntimeConfigSyncKey=null;return}const y=pn(r,p);if(this.lastStoredSessionValidationKey===y){this.updateState({status:"authenticated",session:p,sessionReady:!0});return}this.updateState({status:"authenticated",session:p,sessionReady:!1}),this.scheduleStoredSessionValidation(r,p)}getCurrentHost(){return Da(Z.getState())}getCurrentSessionEnvelope(){const r=this.getCurrentHost();return r?this.sessionMap[r.id]??null:null}readSessionMapFromStorage(r){if(typeof window>"u"||typeof window.localStorage>"u")return{sessionMap:{},migrated:!1};const o=window.localStorage.getItem(dn);if(!o)return{sessionMap:{},migrated:!1};try{const c=JSON.parse(o);if(hg(c))return{sessionMap:c,migrated:!1};const u=gg(c,r);if(u)return{sessionMap:u,migrated:!0}}catch{}return window.localStorage.removeItem(dn),{sessionMap:{},migrated:!1}}persistSessionMap(){if(!(typeof window>"u"||typeof window.localStorage>"u")){if(Object.keys(this.sessionMap).length===0){window.localStorage.removeItem(dn);return}window.localStorage.setItem(dn,JSON.stringify(this.sessionMap))}}updateState(r){this.state.status===r.status&&this.state.session===r.session&&this.state.sessionReady===r.sessionReady||(this.state=r,this.emit())}async ensureRuntimeConfigSynced(r,o){var u;if(!r||!o||gd()){this.lastRuntimeConfigSyncKey=null;return}if(((u=this.getCurrentHost())==null?void 0:u.id)!==r.id)return;const c=`${r.id}:${o.accessToken}`;if(this.lastRuntimeConfigSyncKey!==c){this.lastRuntimeConfigSyncKey=c;try{const{syncActiveHostAuthenticatedRuntimeConfig:p}=await Wt(async()=>{const{syncActiveHostAuthenticatedRuntimeConfig:S}=await import("./client-runtime-manager-BFXU9DmS.js");return{syncActiveHostAuthenticatedRuntimeConfig:S}},[]);await kd(p(),Td,"runtime_config_sync_timeout");const{syncPeerHostsIntoClientConfig:y}=await Wt(async()=>{const{syncPeerHostsIntoClientConfig:S}=await import("./peer-host-config-sync-d2ZcPC5P.js");return{syncPeerHostsIntoClientConfig:S}},__vite__mapDeps([0,1]));await kd(y(),Td,"peer_host_config_sync_timeout")}catch{this.lastRuntimeConfigSyncKey===c&&(this.lastRuntimeConfigSyncKey=null)}}}scheduleRuntimeConfigSync(r,o){this.ensureRuntimeConfigSynced(r,o)}scheduleStoredSessionValidation(r,o){this.ensureStoredSessionValidated(r,o)}async ensureStoredSessionValidated(r,o){var u,p,y,S,A,O;if(gd()||((u=this.getCurrentHost())==null?void 0:u.id)!==r.id||((p=this.state.session)==null?void 0:p.refreshToken)!==o.refreshToken)return;const c=pn(r,o);try{const E=await vd(o.refreshToken,r.baseUrl);if(((y=this.getCurrentHost())==null?void 0:y.id)!==r.id||((S=this.state.session)==null?void 0:S.refreshToken)!==o.refreshToken)return;this.lastStoredSessionValidationKey=c,this.setSession(E,r,{sessionReady:!0}),this.scheduleRuntimeConfigSync(r,E)}catch(E){if(((A=this.getCurrentHost())==null?void 0:A.id)!==r.id||((O=this.state.session)==null?void 0:O.refreshToken)!==o.refreshToken)return;if(wd(E)){this.clear();return}this.lastStoredSessionValidationKey=c,this.updateState({status:"authenticated",session:o,sessionReady:!0})}}emit(){for(const r of this.listeners)r()}}const Me=new pg;function cS(i){return He.useSyncExternalStore(Me.subscribe,()=>i(Me.getState()))}function fg(i){if(typeof i!="object"||i===null)return!1;const r=i;return typeof r.hostId=="string"&&typeof r.savedAt=="number"&&En(r.session)}function kd(i,r,o){return new Promise((c,u)=>{const p=globalThis.setTimeout(()=>{u(new Error(o))},r);i.then(y=>{globalThis.clearTimeout(p),c(y)},y=>{globalThis.clearTimeout(p),u(y)})})}function hg(i){return typeof i!="object"||i===null||Array.isArray(i)?!1:Object.values(i).every(r=>fg(r))}function mg(i){return typeof i!="object"||i===null?!1:"session"in i&&En(i.session)}function En(i){if(typeof i!="object"||i===null)return!1;const r=i;return typeof r.accessToken=="string"&&typeof r.refreshToken=="string"&&typeof r.expiresIn=="number"&&typeof r.user=="object"&&r.user!==null}function gg(i,r){const o=(r==null?void 0:r.id)??null;if(!o)return null;if(mg(i)){const c=bg(i.serverBaseUrl,r)??o;return{[c]:{hostId:c,session:i.session,savedAt:Date.now()}}}return En(i)?{[o]:{hostId:o,session:i,savedAt:Date.now()}}:null}function bg(i,r){if(!i)return(r==null?void 0:r.id)??null;const c=Z.getState().hosts.find(u=>u.baseUrl===i);return(c==null?void 0:c.id)??(r==null?void 0:r.id)??null}function wd(i){return i instanceof et?i.status===401?!0:i.status===403&&i.errorCode==="BOOTSTRAP_REQUIRED":!1}function yg(i){const r=Object.entries(i).filter(([,o])=>!Sg(o));return Object.fromEntries(r)}function Sg(i){var o;const r=(o=i.session)==null?void 0:o.expiresIn;return typeof r!="number"||!Number.isFinite(r)||r<=0?!0:i.savedAt+r*1e3<=Date.now()}function Tg(i,r){var c;const o=(c=i==null?void 0:i.session)==null?void 0:c.expiresIn;return!(i!=null&&i.session)||typeof o!="number"||!Number.isFinite(o)||o<=0?!1:i.savedAt+o*1e3<=r+dg}function pn(i,r){return`${i.id}:${r.refreshToken}`}async function vd(i,r){const o=await fetch(Fn("/api/auth/refresh",r),{method:"POST",headers:{...np(),"Content-Type":"application/json"},body:JSON.stringify({refreshToken:i})}),c=await o.text(),u=c?kg(c):null;if(!o.ok)throw new et(o.status,{detail:(u==null?void 0:u.detail)??`请求失败(HTTP ${o.status})`,error_code:(u==null?void 0:u.error_code)??(o.status===401?"UNAUTHORIZED":"HTTP_ERROR"),field:u==null?void 0:u.field,data:u==null?void 0:u.data,timestamp:u==null?void 0:u.timestamp});if(!u||!En(u))throw new et(o.status,{detail:"刷新登录态返回了无效响应",error_code:"HTTP_ERROR"});return u}function kg(i){try{return JSON.parse(i)}catch{return null}}const ai=new Map,op=48;function Pa(){return typeof window<"u"&&typeof window.sessionStorage<"u"}function Cd(i,r){return!Number.isFinite(i)||Date.now()-i>r}function wg(i){return!i||typeof i!="object"||!("savedAt"in i)||!("value"in i)?!1:Number.isFinite(i.savedAt)}function sp(i){try{const r=JSON.parse(i);return wg(r)?r:null}catch{return null}}function vg(){if(!Pa())return[];try{return Array.from({length:window.sessionStorage.length},(i,r)=>window.sessionStorage.key(r)).filter(i=>typeof i=="string"&&i.length>0)}catch{return[]}}function lp(){if(!Pa())return[];const i=[];for(const r of vg()){let o=null;try{o=window.sessionStorage.getItem(r)}catch{continue}if(!o)continue;const c=sp(o);c&&i.push({key:r,savedAt:c.savedAt})}return i.sort((r,o)=>r.savedAt-o.savedAt)}function Yi(i){if(Pa())try{window.sessionStorage.removeItem(i)}catch{}}function fn(i){const r=new Set((i==null?void 0:i.preserveKeys)??[]),o=(i==null?void 0:i.maxCount)??op,c=lp().filter(p=>!r.has(p.key)),u=Math.max(0,r.size+c.length-o);for(let p=0;p<u;p+=1){const y=c[p];if(!y)break;Yi(y.key)}}function Cg(i){return i instanceof DOMException&&(i.name==="QuotaExceededError"||i.name==="NS_ERROR_DOM_QUOTA_REACHED"||i.code===22||i.code===1014)}function xs(i,r){if(!Pa())return"failed";try{return window.sessionStorage.setItem(i,r),"success"}catch(o){return Cg(o)?"quota_exceeded":"failed"}}function Dg(i,r){const o=xs(i,r);if(o==="success"){fn({preserveKeys:[i]});return}if(o==="quota_exceeded"){if(Yi(i),fn({maxCount:Math.max(0,op-1)}),xs(i,r)==="success"){fn({preserveKeys:[i]});return}for(const c of lp())if(c.key!==i&&(Yi(c.key),xs(i,r)==="success")){fn({preserveKeys:[i]});return}}}function Pg(i,r){const o=ai.get(i);if(o){if(!Cd(o.savedAt,r))return o.value;ai.delete(i)}if(!Pa())return null;let c=null;try{c=window.sessionStorage.getItem(i)}catch{return null}if(!c)return null;const u=sp(c);return!u||Cd(u.savedAt,r)?(Yi(i),ai.delete(i),null):(ai.set(i,u),u.value)}function Ag(i,r){const o={savedAt:Date.now(),value:r};if(ai.set(i,o),!!Pa())try{Dg(i,JSON.stringify(o))}catch{}}function uS(i){ai.delete(i),Pa()&&Yi(i)}const Lg="workbench.affairs.dashboard.",cp=7,Rg=365*24*60*60*1e3,Fg=/\.(html?|HTML?)$/,dS="affairs-global",Eg="codingns:affairs-dashboard-state-updated";function up(i){return`${Lg}${i}`}function Aa(i){var r;return typeof((r=globalThis.crypto)==null?void 0:r.randomUUID)=="function"?`${i}-${globalThis.crypto.randomUUID()}`:`${i}-${Date.now()}-${Math.random().toString(16).slice(2)}`}function Rt(i){return!!i&&typeof i=="object"&&!Array.isArray(i)}function hn(i){return Number.isInteger(i)&&Number(i)>0}function Dd(i){return Number.isInteger(i)&&Number(i)>=0}function tl(i){const r=i.trim().replace(/\\/g,"/"),o=r.split("/").filter(Boolean);return o[o.length-1]??r}function pS(i){const r=(i==null?void 0:i.trim())??"";return r.length>0&&Fg.test(r)}function dp(i,r,o="embed"){return i==="todo"?tt("shell.affairsTodoAllFilter"):i==="automation"?tt("shell.affairsAutomationStageTitle"):i==="teable"?tt("shell.teableRuntimeDefaultBlockTitle"):r!=null&&r.trim()?tl(r):Mg(o)}function Mg(i){return tt(i==="app"?"shell.affairsWorkbenchHtmlAppDefaultTitle":i==="stat"?"shell.affairsWorkbenchHtmlStatDefaultTitle":"shell.affairsWorkbenchHtmlEmbedDefaultTitle")}function pp(i,r=new Date().toISOString()){var c,u,p;const o=i.type==="html"?Vs(i.variant)??"embed":void 0;return{id:Aa("dashboard-widget"),type:i.type,variant:o,title:((c=i.title)==null?void 0:c.trim())||dp(i.type,(u=i.sourceRef)==null?void 0:u.sourceId,o),sourceRef:i.sourceRef?{...i.sourceRef,workspaceId:((p=i.sourceRef.workspaceId)==null?void 0:p.trim())||void 0}:void 0,config:Rt(i.config)?i.config:{},createdAt:r,updatedAt:r}}function Ig(i){return pp({type:"todo",title:tt("shell.affairsTodoAllFilter"),config:{filter:"all",view:"compact"}},i)}function xg(i){return pp({type:"automation",title:tt("shell.affairsAutomationStageTitle"),config:{scope:"all",view:"list"}},i)}function fp(i){return i.map((r,o)=>({widgetId:r.id,x:o===0?0:6,y:0,w:6,h:5,minW:4,minH:3}))}function fS(i,r=new Date().toISOString()){return{id:Aa("dashboard-tab"),title:i.trim()||tt("shell.affairsWorkbenchDefaultTabTitle"),widgets:[],layout:[],createdAt:r,updatedAt:r}}function Og(i=new Date().toISOString()){const r=[Ig(i),xg(i)];return{id:Aa("dashboard-tab"),title:tt("shell.affairsWorkbenchDefaultTabTitle"),widgets:r,layout:fp(r),createdAt:i,updatedAt:i}}function hS(i,r=new Date().toISOString()){var y,S;const o=i.entryPath.trim(),c=i.workspaceId.trim(),u=((y=i.sourceId)==null?void 0:y.trim())||o,p=i.sourceKind==="affairs_library"?"affairs_library":"workspace";return{id:Aa("shortcut-app"),title:((S=i.title)==null?void 0:S.trim())||tl(o),sourceKind:p,workspaceId:c,sourceId:u,entryPath:o,createdAt:r,updatedAt:r}}function Hg(i,r=new Date().toISOString()){const o=Og(r);return{workspaceId:i,version:cp,layoutLocked:!0,activeTabId:o.id,tabs:[o],shortcutApps:[],updatedAt:r}}function Ng(i,r){if(!Rt(i))return null;const o=Vg(i.type,Rt(i.config)?i.config.variant:void 0,i.variant);if(!o)return null;const c=Rt(i.sourceRef)?{kind:i.sourceRef.kind==="html_shortcut"?"html_shortcut":i.sourceRef.kind==="affairs_library_html"?"affairs_library_html":"plugin_runtime",workspaceId:typeof i.sourceRef.workspaceId=="string"&&i.sourceRef.workspaceId.trim()?i.sourceRef.workspaceId.trim():void 0,sourceId:typeof i.sourceRef.sourceId=="string"?i.sourceRef.sourceId.trim():"",entryId:typeof i.sourceRef.entryId=="string"&&i.sourceRef.entryId.trim()?i.sourceRef.entryId.trim():void 0}:void 0;return o.type==="html"&&!(c!=null&&c.sourceId)||o.type==="teable"&&!Rt(i.config)?null:{id:typeof i.id=="string"&&i.id.trim()?i.id.trim():Aa("dashboard-widget"),type:o.type,variant:o.variant,title:typeof i.title=="string"&&i.title.trim()?i.title.trim():dp(o.type,c==null?void 0:c.sourceId,o.variant??"embed"),sourceRef:c,config:zg(Rt(i.config)?i.config:{}),createdAt:typeof i.createdAt=="string"&&i.createdAt.trim()?i.createdAt:r,updatedAt:typeof i.updatedAt=="string"&&i.updatedAt.trim()?i.updatedAt:r}}function Bg(i){return!Rt(i)||typeof i.widgetId!="string"||!i.widgetId.trim()||!Dd(i.x)||!Dd(i.y)||!hn(i.w)||!hn(i.h)?null:{widgetId:i.widgetId.trim(),x:i.x,y:i.y,w:i.w,h:i.h,minW:hn(i.minW)?i.minW:void 0,minH:hn(i.minH)?i.minH:void 0}}function Ug(i,r){if(!Rt(i))return null;const o=i.sourceKind==="affairs_library"?"affairs_library":"workspace",c=typeof i.workspaceId=="string"?i.workspaceId.trim():"",u=typeof i.entryPath=="string"?i.entryPath.trim():"";if(!c||!u)return null;const p=typeof i.sourceId=="string"&&i.sourceId.trim()?i.sourceId.trim():u;return{id:typeof i.id=="string"&&i.id.trim()?i.id.trim():Aa("shortcut-app"),title:typeof i.title=="string"&&i.title.trim()?i.title.trim():tl(u),sourceKind:o,workspaceId:c,sourceId:p,entryPath:u,createdAt:typeof i.createdAt=="string"&&i.createdAt.trim()?i.createdAt:r,updatedAt:typeof i.updatedAt=="string"&&i.updatedAt.trim()?i.updatedAt:r}}function Wg(i,r){if(!Rt(i))return null;const o=(Array.isArray(i.widgets)?i.widgets:[]).map(p=>Ng(p,r)).filter(p=>p!==null),c=new Map((Array.isArray(i.layout)?i.layout:[]).map(p=>Bg(p)).filter(p=>p!==null).map(p=>[p.widgetId,p])),u=fp(o);return{id:typeof i.id=="string"&&i.id.trim()?i.id.trim():Aa("dashboard-tab"),title:typeof i.title=="string"&&i.title.trim()?i.title.trim():tt("shell.affairsWorkbenchDefaultTabTitle"),widgets:o,layout:o.map((p,y)=>c.get(p.id)??u[y]),createdAt:typeof i.createdAt=="string"&&i.createdAt.trim()?i.createdAt:r,updatedAt:typeof i.updatedAt=="string"&&i.updatedAt.trim()?i.updatedAt:r}}function hp(i,r){if(!Rt(r))return null;const o=new Date().toISOString(),c=(Array.isArray(r.tabs)?r.tabs:[]).map(S=>Wg(S,o)).filter(S=>S!==null),u=(Array.isArray(r.shortcutApps)?r.shortcutApps:[]).map(S=>Ug(S,o)).filter(S=>S!==null);if(c.length===0)return{...Hg(i,o),shortcutApps:u};const p=typeof r.activeTabId=="string"?r.activeTabId.trim():"",y=c.some(S=>S.id===p)?p:c[0].id;return{workspaceId:i,version:cp,layoutLocked:typeof r.layoutLocked=="boolean"?r.layoutLocked:!0,activeTabId:y,tabs:c,shortcutApps:u,updatedAt:typeof r.updatedAt=="string"&&r.updatedAt.trim()?r.updatedAt:o}}function Vs(i){return i==="app"||i==="stat"||i==="embed"?i:null}function _g(i){return i==="html_app"?"app":i==="html_stat"?"stat":i==="html_embed"?"embed":null}function Vg(i,r,o){if(i==="todo"||i==="automation"||i==="teable")return{type:i};if(i==="html")return{type:"html",variant:Vs(o)??Vs(r)??"embed"};const c=_g(i);return c?{type:"html",variant:c}:null}function zg(i){if(!("variant"in i))return i;const{variant:r,...o}=i;return o}function mS(i){const r=i==null?void 0:i.trim();if(!r)return null;const o=Pg(up(r),Rg);return o?hp(r,o):null}function gS(i){Ag(up(i.workspaceId),i),typeof window<"u"&&window.dispatchEvent(new CustomEvent(Eg,{detail:{workspaceId:i.workspaceId}}))}const Mn=["claude-code","codex","opencode","gemini","kimi"],mp="codingns.account.preferences.shadow",jg="codingns.client.runtime-config",qg="codingns-theme",Gg="composer-selected-model:",Kg="composer-reasoning-level:",al={start:43e3,end:47999};function Xi(){return typeof window<"u"&&typeof window.localStorage<"u"}function il(i){return i==="en-US"||i==="en"?"en-US":i==="zh-CN"?"zh-CN":null}function Qg(){return typeof navigator>"u"?"zh-CN":il(navigator.language)??"zh-CN"}function gp(i){return i==="light"||i==="dark"||i==="sky-blue"||i==="eye-green"?i:null}function Yg(){return typeof window>"u"||typeof window.matchMedia!="function"?"light":window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light"}function $g(i){return typeof i=="boolean"?i:null}function bp(i){return i==="acceptEdits"||i==="bypassPermissions"||i==="default"?i:null}function yp(i){return i==="low"||i==="medium"||i==="high"||i==="xhigh"?i:null}function Sp(){return{"claude-code":{defaultModel:null,defaultReasoningLevel:null},codex:{defaultModel:null,defaultReasoningLevel:null},opencode:{defaultModel:null,defaultReasoningLevel:null},gemini:{defaultModel:null,defaultReasoningLevel:null},kimi:{defaultModel:null,defaultReasoningLevel:null}}}function Tp(){return{initialized:!0,profile:{language:Qg(),theme:Yg(),autoTheme:!1,defaultPermissionMode:"default",debugPortPools:Pn(al)},providers:Sp(),affairsDashboardStatesByWorkspace:{},updatedAt:null,source:"default"}}function Jg(){const i=Z.getState(),r={language:i.language,defaultPermissionMode:i.defaultPermissionMode};if(!Xi())return r;const o=window.localStorage.getItem(jg);if(!o)return r;try{const c=JSON.parse(o);return{language:il(c.language)??r.language,defaultPermissionMode:bp(c.defaultPermissionMode)??r.defaultPermissionMode}}catch{return r}}function Xg(){return Xi()?gp(window.localStorage.getItem(qg)):null}function Zg(){var r;if(!Xi())return;const i={};for(const o of Mn){const c=((r=window.localStorage.getItem(`${Gg}${o}`))==null?void 0:r.trim())||null,u=yp(window.localStorage.getItem(`${Kg}${o}`));c===null&&u===null||(i[o]={defaultModel:c,defaultReasoningLevel:u})}return Object.keys(i).length>0?i:void 0}function kp(){const i=Jg(),r=Xg(),o=Zg(),c={};return i.language&&(c.language=i.language),r&&(c.theme=r),i.defaultPermissionMode&&(c.defaultPermissionMode=i.defaultPermissionMode),o&&(c.providers=o),wp(c)?c:null}function wp(i){return i?i.language!==void 0||i.theme!==void 0||i.autoTheme!==void 0||i.defaultPermissionMode!==void 0||i.debugPortPools!==void 0||i.affairsDashboardStatesByWorkspace!==void 0||i.providers!==void 0&&Object.keys(i.providers).length>0:!1}function Cn(i){var c;const r=Tp(),o=Sp();for(const u of Mn){const p=(c=i==null?void 0:i.providers)==null?void 0:c[u];o[u]={defaultModel:typeof(p==null?void 0:p.defaultModel)=="string"&&p.defaultModel.trim()||null,defaultReasoningLevel:yp(p==null?void 0:p.defaultReasoningLevel)??null}}return{language:il(i==null?void 0:i.language)??r.profile.language,theme:gp(i==null?void 0:i.theme)??r.profile.theme,autoTheme:$g(i==null?void 0:i.autoTheme)??r.profile.autoTheme,defaultPermissionMode:bp(i==null?void 0:i.defaultPermissionMode)??r.profile.defaultPermissionMode,debugPortPools:tb(i==null?void 0:i.debugPortPools)??r.profile.debugPortPools,providers:o,affairsDashboardStatesByWorkspace:Cp(i==null?void 0:i.affairsDashboardStatesByWorkspace),updatedAt:typeof(i==null?void 0:i.updatedAt)=="string"?i.updatedAt:null}}function eb(){var r,o,c,u,p;if(!Xi())return null;const i=window.localStorage.getItem(mp);if(!i)return null;try{const y=JSON.parse(i),S=Cn({language:(r=y.profile)==null?void 0:r.language,theme:(o=y.profile)==null?void 0:o.theme,autoTheme:(c=y.profile)==null?void 0:c.autoTheme,defaultPermissionMode:(u=y.profile)==null?void 0:u.defaultPermissionMode,debugPortPools:(p=y.profile)==null?void 0:p.debugPortPools,providers:y.providers,affairsDashboardStatesByWorkspace:y.affairsDashboardStatesByWorkspace,updatedAt:y.updatedAt});return{profile:{language:S.language,theme:S.theme,autoTheme:S.autoTheme,defaultPermissionMode:S.defaultPermissionMode,debugPortPools:S.debugPortPools},providers:S.providers,affairsDashboardStatesByWorkspace:S.affairsDashboardStatesByWorkspace,updatedAt:S.updatedAt}}catch{return null}}function Dn(i){if(!Xi())return;const r={profile:i.profile,providers:i.providers,affairsDashboardStatesByWorkspace:i.affairsDashboardStatesByWorkspace,updatedAt:i.updatedAt};window.localStorage.setItem(mp,JSON.stringify(r))}function ei(){const i=Tp(),r=kp(),o=r?vp(i,r,"default"):i,c=eb();return c?{initialized:!0,profile:c.profile,providers:c.providers,affairsDashboardStatesByWorkspace:c.affairsDashboardStatesByWorkspace,updatedAt:c.updatedAt,source:"shadow"}:o}function zs(i,r){return{initialized:!0,profile:{language:i.language,theme:i.theme,autoTheme:i.autoTheme,defaultPermissionMode:i.defaultPermissionMode,debugPortPools:Pn(i.debugPortPools??al)},providers:i.providers,affairsDashboardStatesByWorkspace:i.affairsDashboardStatesByWorkspace??{},updatedAt:i.updatedAt,source:r}}function vp(i,r,o){const c={...i.providers};if(r.providers)for(const u of Mn){const p=r.providers[u];p&&(c[u]={defaultModel:p.defaultModel!==void 0?p.defaultModel??null:i.providers[u].defaultModel,defaultReasoningLevel:p.defaultReasoningLevel!==void 0?p.defaultReasoningLevel??null:i.providers[u].defaultReasoningLevel})}return{initialized:!0,profile:{language:r.language??i.profile.language,theme:r.theme??i.profile.theme,autoTheme:r.autoTheme??i.profile.autoTheme,defaultPermissionMode:r.defaultPermissionMode??i.profile.defaultPermissionMode,debugPortPools:r.debugPortPools?Pn(r.debugPortPools):i.profile.debugPortPools??Pn(al)},providers:c,affairsDashboardStatesByWorkspace:r.affairsDashboardStatesByWorkspace!==void 0?Cp(r.affairsDashboardStatesByWorkspace):i.affairsDashboardStatesByWorkspace??{},updatedAt:i.updatedAt,source:o}}function Cp(i){if(!i||typeof i!="object"||Array.isArray(i))return{};const r={};for(const[o,c]of Object.entries(i)){const u=o.trim();if(!u)continue;const p=hp(u,c);p&&(r[u]=p)}return r}function tb(i){if(!i||typeof i!="object"||Array.isArray(i))return null;const r=Dp(i);return r||ab(i)}function Pd(i){if(!Number.isInteger(i))return null;const r=Number(i);return r>=1024&&r<=65535?r:null}function Dp(i){if(!i||typeof i!="object"||Array.isArray(i))return null;const r=i;if(!Object.prototype.hasOwnProperty.call(r,"start")||!Object.prototype.hasOwnProperty.call(r,"end"))return null;const o=Pd(r.start),c=Pd(r.end);return o===null||c===null||o>=c?null:{start:o,end:c}}function ab(i){if(!i||typeof i!="object"||Array.isArray(i))return null;const r=["frontend","backend","worker","mock","custom"];let o=Number.POSITIVE_INFINITY,c=Number.NEGATIVE_INFINITY;for(const u of r){const p=Dp(i[u]);if(!p)return null;o=Math.min(o,p.start),c=Math.max(c,p.end)}return Number.isFinite(o)&&Number.isFinite(c)&&o<c?{start:o,end:c}:null}function Pn(i){return{...i}}async function ib(){const{fetchPreferencesProfile:i,updatePreferencesProfile:r}=await Wt(async()=>{const{fetchPreferencesProfile:u,updatePreferencesProfile:p}=await import("./preferences-service-CEWNV1w9.js");return{fetchPreferencesProfile:u,updatePreferencesProfile:p}},[]),o=Cn(await i());if(o.updatedAt===null){const u=kp();if(wp(u)){const p=Cn(await r(u)),y=zs(p,"remote");return Dn(y),y}}const c=zs(o,"remote");return Dn(c),c}class rb{constructor(){L(this,"state",ei());L(this,"listeners",new Set);L(this,"subscribe",r=>(this.listeners.add(r),()=>{this.listeners.delete(r)}));L(this,"getState",()=>this.state);Z.subscribe(()=>{Me.getState().session||this.state.source==="remote"||this.hydrate(ei())})}hydrate(r){this.state=r,this.emit()}resetToLocalFallback(){this.hydrate(ei())}async initialize(){if(!Me.getState().session){const r=ei();return this.hydrate(r),r}return this.refreshForAuthenticatedUser()}async refreshForAuthenticatedUser(){if(!Me.getState().session){const r=ei();return this.hydrate(r),r}try{const r=await ib();return this.hydrate(r),r}catch{const r=ei();return this.hydrate(r),r}}async updateProfile(r){const o=this.state,c=vp(o,r,o.source);if(this.hydrate(c),!Me.getState().session)return Dn(c),c;try{const{updatePreferencesProfile:u}=await Wt(async()=>{const{updatePreferencesProfile:S}=await import("./preferences-service-CEWNV1w9.js");return{updatePreferencesProfile:S}},[]),p=Cn(await u(r)),y=zs(p,"remote");return Dn(y),this.hydrate(y),y}catch(u){throw this.hydrate(o),u}}async updateProviderPreference(r,o){return this.updateProfile({providers:{[r]:o}})}emit(){for(const r of this.listeners)r()}}const ri=new rb;function Pp(i){return He.useSyncExternalStore(ri.subscribe,()=>i(ri.getState()))}function nb(i){return Mn.includes(i)}const bS=Object.freeze(Object.defineProperty({__proto__:null,isPreferenceProviderId:nb,useUserPreferenceSelector:Pp,userPreferenceStore:ri},Symbol.toStringTag,{value:"Module"}));function ob(){return ri.initialize()}function yS(i){return ri.updateProfile(i)}function sb(i){return Pp(r=>i({profile:{...r.profile,providers:r.providers,affairsDashboardStatesByWorkspace:r.affairsDashboardStatesByWorkspace??{},updatedAt:r.updatedAt},isFetching:!1,error:null}))}const lb={common:{close:"关闭",cancel:"取消",copy:"复制",copyFailed:"复制失败",enabled:"已启用",disabled:"已关闭",logout:"退出登录",language:"语言",none:"无"},locale:{zhCN:"简体中文",enUS:"English"},settings:{title:"设置",appearance:"外观",language:"语言",languageDescription:"选择界面显示语言,切换后立即应用到当前页面。",theme:"主题",themeDescription:"选择适合你的界面配色方案",connection:"连接与更新",serverAddress:"服务地址",serverDescription:"桌面端和 H5 都通过这个 Host 入口工作。",autoReconnect:"自动重连",autoReconnectDescription:"当 Host 短暂不可达时,自动尝试恢复 HTTP 和 WebSocket 链路。",autoCheckUpdate:"自动检查更新",autoCheckUpdateDescription:"发现客户端新版本时提醒你处理。",autoDownloadUpdate:"自动下载更新包后提示更新",autoDownloadUpdateDescription:"发现客户端新版本后先下载资源,下载完成再提示你安装。",notificationSettings:"通知",notificationSettingsDescription:"单独控制会话相关的系统通知提醒。",notifyOnPermissionRequest:"会话等待审批时通知",notifyOnPermissionRequestDescription:"后台会话出现新的权限申请时推送通知。",notifyOnSessionCompleted:"会话完成时通知",notifyOnSessionCompletedDescription:"后台会话变为已完成时推送通知。",notifyOnSessionFailed:"会话异常时通知",notifyOnSessionFailedDescription:"后台会话运行失败时推送通知。",enabled:"已启用",disabled:"已关闭",serverUpdate:"服务端更新",serverUpdateDescription:"",clientUpdate:"客户端更新",clientUpdateDescription:"",serverCurrentVersion:"服务端当前版本",serverTargetVersion:"服务端目标版本",serverPackageName:"npm 包名",serverUpdateCommand:"升级命令",serverCheckNow:"检查服务端",serverInstallNow:"安装更新",serverOpenPage:"打开 npm",serverLatestUnknown:"暂未获取",serverUpdateReady:"发现新版本",serverUpToDate:"已是最新版本",serverCheckFailed:"检查失败",serverInstallWarning:"安装更新会通过 PM2 自动重启 CodingNS 服务,连接会短暂中断。",serverInstallConfirmTitle:"安装服务端更新",serverInstallConfirmDescription:"继续后会先安装新版本,再由 PM2 自动重启当前 CodingNS 服务。",serverInstallConfirmAction:"继续安装并重启服务",serverRestarting:"更新已安装,正在重启 CodingNS 服务",serverProgressLabel:"服务端更新进度",serverProgressPreparing:"正在准备服务端更新",serverProgressQueued:"已加入更新队列",serverProgressInstalling:"正在安装服务端更新",serverProgressRestarting:"正在重启服务",serverProgressHint:"服务端升级由 npm 和 PM2 执行,当前只能显示阶段,不能显示准确百分比。",serverProgressCurrentStage:"当前阶段:{stage}",updateCheckAll:"检查更新",updateChecking:"正在检查",serverInstallQueued:"已加入更新队列",serverInstalling:"正在安装更新",serverInstallSucceeded:"更新已完成",serverInstallFailed:"安装失败",serverInstallCancelled:"安装已取消",serverInstallTimeout:"安装超时",serverRestartRequired:"新版本已安装,重启 Host 后生效",serverOpenPageFailed:"打开页面失败",runtimePlatform:"当前运行平台",runtimePlatformDescription:"用来确认现在是 Web/H5、Desktop、iOS 还是 Android 运行环境。",platformDesktop:"Desktop",platformWeb:"Web",platformIos:"iOS",platformAndroid:"Android",releaseDesktopOnly:"当前是 Web/H5 运行环境,不支持桌面更新。",releaseCurrentVersion:"当前版本",releaseTargetVersion:"目标版本",releaseUnknownVersion:"未知",releaseNotes:"更新内容",releaseNotesEmpty:"暂无更新内容",releaseCheckNow:"检查客户端",releaseInstallNow:"安装更新",releaseDownloading:"正在下载更新包",releaseDownloadedReady:"更新包已下载完成,可以安装",releaseDownloadedReadyWithProgress:"更新包已下载完成({percent}%),可以安装",releaseDownloadFailed:"下载失败",releaseInstallReadyDialogTitle:"更新包已下载完成",releaseInstallReadyDialogDescription:"新版本 {version} 已准备好,现在可以安装。",releaseInstallReadyWarning:"安装完成后需要重启应用才能切到新版本。",releaseInstallReadyConfirm:"安装并重启",releaseDownloadedNotificationTitle:"客户端更新已下载",releaseDownloadedNotificationBody:"新版本 {version} 已下载完成,请到设置里安装。",releaseOpenPage:"打开发布页",releaseManualOnly:"当前版本只能手动安装",releaseUpdateBadge:"新版本",releaseUpdateReady:"发现新版本",releaseUpToDate:"已是最新版本",releaseCheckFailed:"检查失败",releaseInstallStarted:"安装已开始",releaseInstallFailed:"安装失败",releasePageOpenFailed:"打开发布页失败",androidInstallerStarted:"已交给系统安装器,安装完成前你仍可以取消",androidInstallPermissionRequired:"请先允许当前应用安装未知来源应用",androidInstallCancelled:"安装已取消或未完成,可重新触发安装",androidInstallSucceeded:"已检测到新版本完成安装",clientUpdateUnsupported:"当前不支持安装更新",account:"账号",logout:"退出登录",logoutDescription:"退出当前账号并返回登录页面",advancedSettings:"高级设置",parallelTaskDebug:"并行任务调试",parallelTaskDebugDescription:"打开后才会启用运行时采样,用来实时看后台任务、调度器和主线程压力指标。",debugPortPool:"调试端口池",debugPortPoolDescription:"给子工作区的已登记启动项分配可用端口。所有调试服务统一从这个范围里拿空闲端口,不再分前后端和 Worker。",debugPortPoolRangeLabel:"端口范围",debugPortPoolRangeHint:"子工作区里的前端、后端、Worker、Mock 和自定义服务统一从这里取可用端口",debugPortPoolStart:"起始",debugPortPoolEnd:"结束",debugPortPoolRangeSeparator:"到",debugPortPoolSaveAction:"保存端口池",debugPortPoolSaved:"端口池已保存",debugPortPoolSaveFailed:"端口池保存失败",debugPortPoolValidationInteger:"端口池的起止值必须是整数",debugPortPoolValidationRange:"端口池必须在 1024 到 65535 之间,且起始值必须小于结束值",debugPortPoolValidationOverlap:"各角色的端口池不能重叠",debugPortPoolRoleFrontend:"前端",debugPortPoolRoleBackend:"后端",debugPortPoolRoleWorker:"Worker",debugPortPoolRoleMock:"Mock",debugPortPoolRoleCustom:"自定义",debugPortPoolRoleHint:"{role} 统一从这个范围里拿可用端口",parallelTaskDebugAction:"打开调试面板",parallelTaskDebugModalTitle:"并行任务调试",parallelTaskDebugModalDescription:"这个窗口打开时才会继续采集任务活动和 event loop 指标,关掉后立即停止。",parallelTaskDebugClose:"关闭并行任务调试",parallelTaskDebugLoading:"正在建立观测会话并拉取快照…",parallelTaskDebugLoadFailed:"加载并行任务调试信息失败",parallelTaskDebugEmpty:"当前没有可展示的执行记录。",parallelTaskDebugStatusActive:"采集中",parallelTaskDebugStatusError:"采集异常",parallelTaskDebugObservedAt:"最后更新",parallelTaskDebugSessionExpireAt:"会话到期时间",parallelTaskDebugSessionTtl:"会话 TTL",parallelTaskDebugCollectorState:"采集器状态",parallelTaskDebugCollectorEnabled:"已启用",parallelTaskDebugCollectorDisabled:"未启用",parallelTaskDebugAutoRefresh:"每秒自动刷新",parallelTaskDebugCountersTitle:"总指标",parallelTaskDebugRegisteredTasksTitle:"已注册任务列表",parallelTaskDebugRegisteredTasksEmpty:"当前没有可展示的已注册任务。",parallelTaskDebugTaskMetricsTitle:"最近活跃任务指标",parallelTaskDebugActiveTaskMetricsEmpty:"当前观测窗口内还没有活跃任务指标。",parallelTaskDebugSchedulerTitle:"调度器指标",parallelTaskDebugEventLoopTitle:"Event Loop",parallelTaskDebugRecentActivitiesTitle:"最近执行记录",parallelTaskDebugWaitAvg:"平均等待",parallelTaskDebugRunAvg:"平均执行",parallelTaskDebugRunMax:"最长执行",parallelTaskDebugStartedCount:"启动次数",parallelTaskDebugFinishedCount:"完成次数",parallelTaskDebugFailedCount:"失败次数",parallelTaskDebugCacheHitCount:"缓存命中",parallelTaskDebugIdle:"空转",parallelTaskDebugBusy:"已命中任务",parallelTaskDebugTickTotal:"tick 总数",parallelTaskDebugIdleTickTotal:"空转 tick",parallelTaskDebugTaskCountTotal:"命中任务",parallelTaskDebugSchedulerErrorTotal:"异常次数",parallelTaskDebugLastDuration:"上次耗时",parallelTaskDebugNextDelay:"下次延迟",parallelTaskDebugEventLoopResolution:"采样粒度",parallelTaskDebugEventLoopMean:"平均延迟",parallelTaskDebugEventLoopP95:"P95 延迟",parallelTaskDebugEventLoopP99:"P99 延迟",parallelTaskDebugEventLoopMax:"最大延迟",parallelTaskDebugTaskTimeout:"超时设置",parallelTaskDebugTaskConcurrency:"并发限制",parallelTaskDebugTaskRetry:"重试次数",parallelTaskDebugTaskCategory:"任务类型",parallelTaskDebugTaskCategoryBuiltinIndexer:"内置索引器",parallelTaskDebugTaskCategoryGeneric:"常规后台任务",parallelTaskDebugTaskRuntime:"运行方式",parallelTaskDebugTaskRuntimeBuiltinHelper:"Host 内置 Helper",parallelTaskDebugTaskRuntimeHelperProcess:"通用 Helper 进程",parallelTaskDebugTaskRuntimeHostBackground:"Host 后台内执行",parallelTaskDebugTaskRuntimeExternalProcess:"外部进程",parallelTaskDebugTaskRuntimeMainThread:"请求主线程",parallelTaskDebugTaskHelper:"Helper 处理器",parallelTaskDebugTaskKey:"任务 Key",parallelTaskDebugStatus:"状态",parallelTaskDebugAttempt:"尝试",parallelTaskDebugWaitMs:"等待",parallelTaskDebugRunMs:"执行",parallelTaskDebugSource:"来源",parallelTaskDebugError:"错误",parallelTaskDebugMetricEnqueue:"入队",parallelTaskDebugMetricDedupe:"去重",parallelTaskDebugMetricStarted:"已启动",parallelTaskDebugMetricFinished:"已完成",parallelTaskDebugMetricFailed:"失败",parallelTaskDebugMetricCancelled:"已取消",parallelTaskDebugMetricTimeout:"超时",parallelTaskDebugMetricCacheHit:"缓存命中",parallelTaskDebugLaneRequestMainThread:"请求主线程",parallelTaskDebugLaneHostBackground:"Host 后台",parallelTaskDebugLaneHelperProcess:"Helper 进程",parallelTaskDebugLaneExternalProcess:"外部进程",parallelTaskDebugEventEnqueued:"入队",parallelTaskDebugEventDeduped:"去重复用",parallelTaskDebugEventStarted:"开始",parallelTaskDebugEventFinished:"完成",parallelTaskDebugEventFailed:"失败",parallelTaskDebugEventCancelled:"取消",parallelTaskDebugEventTimeout:"超时",parallelTaskDebugEventCacheHit:"命中缓存",parallelTaskDebugTaskStatusQueued:"排队中",parallelTaskDebugTaskStatusRunning:"运行中",parallelTaskDebugTaskStatusSucceeded:"已成功",parallelTaskDebugTaskStatusFailed:"已失败",parallelTaskDebugTaskStatusCancelled:"已取消",parallelTaskDebugTaskStatusTimeout:"已超时",opencliSectionTitle:"OpenCLI 接入",opencliSectionDescription:"这里管理 CodingNS 会话里可见的 OpenCLI CLI技能,不改你机器上的全局安装。",opencliEnableAction:"启用",opencliRefreshAction:"刷新",opencliSaveAction:"保存",opencliLoading:"正在读取 OpenCLI 状态…",opencliLoadFailed:"读取 OpenCLI 状态失败",opencliSummaryInstallState:"安装状态",opencliSummaryCatalogCount:"目录总数",opencliSummaryEnabledCount:"当前启用",opencliSummaryBrowserCount:"依赖浏览器",opencliProviderToggleLabel:"在新会话里启用 OpenCLI",opencliProviderHint:"这里控制的是 CodingNS 托管会话里能不能用,不会改你自己终端里的全局 opencli。",opencliVersionLabel:"版本",opencliCatalogSourceLabel:"目录来源",opencliLastCheckedLabel:"最近检查",opencliCatalogRefreshedLabel:"最近刷新",opencliInstallPathLabel:"安装目录",opencliInstallInstalled:"已安装",opencliInstallBroken:"安装损坏",opencliInstallMissing:"未安装",opencliHealthReady:"可运行",opencliHealthBridgeMissing:"浏览器桥缺失",opencliHealthBinaryReady:"命令可用",opencliHealthRuntimeBuildFailed:"运行时构建失败",opencliHealthUnknown:"未检查",opencliCatalogSourceManifest:"安装目录 manifest",opencliCatalogSourceCliList:"opencli list",opencliCatalogSourceLocalManifest:"本地 manifest",opencliCatalogSourceCache:"最近一次缓存",opencliRuntimeReady:"裁剪运行时已就绪",opencliRuntimeFailed:"裁剪运行时失败",opencliRuntimePending:"裁剪运行时构建中",opencliRuntimeStale:"裁剪运行时已过期",opencliRuntimeIdle:"还没生成运行时",opencliRefreshDone:"OpenCLI 状态已刷新",opencliRefreshReady:"OpenCLI 状态已刷新,新会话可使用当前运行时",opencliRefreshCacheRetained:"刷新失败,已保留最近一次成功目录缓存",opencliRefreshUnavailable:"当前无法读取 OpenCLI 目录",opencliSaveReady:"OpenCLI 设置已保存,新会话会使用新的裁剪运行时",opencliSaveEnabled:"OpenCLI 设置已保存,但当前运行时还不可用",opencliSaveDisabled:"OpenCLI 已从新会话里关闭",opencliEmpty:"当前没有可展示的 OpenCLI 命令目录。",opencliEmptyNotInstalled:"当前机器还没发现 OpenCLI 安装,先装好后再回来刷新。",opencliCatalogGridTitle:"CLI技能目录",opencliCatalogGridDescription:"先用标签缩小范围,再按站点卡片查看和切换具体命令。",opencliDetailAction:"详情",opencliDetailTitle:"OpenCLI 详情",opencliDetailStatusHeading:"当前状态",opencliDetailRuntimeIdLabel:"运行时 ID",opencliDetailRuntimeRootLabel:"运行时目录",opencliDetailErrorHeading:"最近错误",opencliEnabledStateLabel:"新会话启用",opencliEnabledStateOn:"已启用",opencliEnabledStateOff:"已关闭",opencliFilterTabsLabel:"OpenCLI CLI技能筛选",opencliFilterAll:"全部",opencliFilterEnabled:"已启用",opencliFilterBrowser:"依赖浏览器",opencliFilterDirect:"可直接运行",opencliFilterStrategy:"策略 {strategy}",opencliFilteredEmpty:"当前筛选条件下没有可展示的 CLI技能。",opencliSiteToggleLabel:"切换站点 {site}",opencliSiteSummary:"已启用 {enabled}/{total},其中 {browser} 条依赖浏览器桥。",opencliSiteSummaryCompact:"{enabled}/{total} 已启用",opencliSiteBrowserCompact:"{count} 条依赖浏览器",opencliSiteDirectCompact:"无需浏览器桥",opencliSiteCommandCount:"{count} 条命令",opencliSiteDescriptionEmpty:"这个站点暂时没有补充说明,你可以展开下面的命令明细继续筛选。",opencliSiteViewAction:"查看",opencliSiteSelectedAction:"正在查看",opencliSiteEnableAction:"启用",opencliSiteDetailTitle:"{site} 命令",opencliSiteDetailDescription:"当前筛选命中 {count} 条,可在这里逐条控制;这个站点总共 {total} 条。",opencliSiteDescriptionHeading:"站点说明",opencliCommandModalFallbackTitle:"命令列表",opencliCommandModalEmpty:"当前筛选条件下,这个 CLI技能站点没有可展示的命令。",opencliCommandSearchLabel:"搜索命令",opencliCommandSearchPlaceholder:"按命令名、说明或策略筛选",opencliCommandSortLabel:"排序方式",opencliCommandSortStatus:"按状态",opencliCommandSortBrowser:"浏览器优先",opencliCommandSortName:"按名称",opencliCommandResultCount:"当前显示 {count} 条",opencliCommandToggleLabel:"切换命令 {commandId}",opencliBrowserTag:"浏览器桥",opencliHttpTag:"HTTP",opencliCommandDescriptionEmpty:"这条目录项没有提供额外说明。",opencliStrategyUnknown:"策略未知",opencliStrategyLabel:"类型:{strategy}",opencliStrategyShortLabel:"{strategy}",opencliStrategyCookie:"Cookie",opencliStrategyHeader:"请求头",opencliStrategyIntercept:"拦截",opencliStrategyLocal:"本地",opencliStrategyPublic:"公开",opencliStrategyUi:"界面",skillConfigTabsLabel:"技能管理标签页",skillConfigTabSkills:"SKILL",skillConfigTabOffice:"办公",skillConfigTabOps:"运维",skillConfigTabOpenCli:"OpenCLI",skillOfficeTemplateCount:"模板数量",skillOfficeBrowserProfileCount:"浏览器配置",skillOfficeBrowserTaskCount:"浏览器任务",skillOnlyOfficeStatusLabel:"Office 集成",skillOnlyOfficeSectionTitle:"ONLYOFFICE 集成",skillOnlyOfficeSectionDescription:"这里配置外部 ONLYOFFICE 服务地址,不开启不影响正常使用。",skillOnlyOfficeSectionEmpty:"当前还没有 ONLYOFFICE 配置。",skillOnlyOfficeEnabledLabel:"启用 ONLYOFFICE 文档预览与编辑",skillOnlyOfficeServerUrlLabel:"ONLYOFFICE 服务地址",skillOnlyOfficeServerUrlPlaceholder:"例如:http://127.0.0.1:8088",skillOnlyOfficePublicBaseUrlLabel:"CodingNS 对外地址",skillOnlyOfficePublicBaseUrlPlaceholder:"例如:http://host.docker.internal:3002",skillOnlyOfficeCallbackBaseUrlLabel:"回调地址(可选)",skillOnlyOfficeCallbackBaseUrlPlaceholder:"留空时默认复用 CodingNS 对外地址",skillOnlyOfficeUserDisplayNameLabel:"ONLYOFFICE 显示名称(可选)",skillOnlyOfficeUserDisplayNameDescription:"留空时默认使用当前登录用户名:{username}",skillOnlyOfficeUserDisplayNamePlaceholder:"留空时自动带入当前登录用户名",skillOnlyOfficeUserAvatarUrlLabel:"ONLYOFFICE 头像地址(可选)",skillOnlyOfficeUserAvatarUrlDescription:"留空时不传头像,填写后会显示在协作用户信息里。",skillOnlyOfficeUserAvatarUrlPlaceholder:"例如:https://example.com/avatar.png",skillOnlyOfficeJwtSecretLabel:"JWT 密钥(可选)",skillOnlyOfficeJwtSecretPlaceholder:"如果 ONLYOFFICE 开了 JWT,这里填同一份密钥",skillOnlyOfficeJwtSecretKeepPlaceholder:"当前已保存 JWT 密钥;留空表示保持不变",skillOnlyOfficeClearJwtSecretLabel:"清空当前 JWT 密钥",skillOnlyOfficeOpenSettingsAction:"设置",skillOnlyOfficeModalTitle:"配置 ONLYOFFICE",skillOnlyOfficeModalDescription:"在这里填写 ONLYOFFICE 服务地址、CodingNS 对外地址和回调地址。保存后会影响 docx、xlsx、pptx 的预览和回写。",skillOnlyOfficeSaveAction:"保存配置",skillOnlyOfficeCheckAction:"重新检测",skillOnlyOfficeSaveSuccess:"ONLYOFFICE 配置已保存。",skillOnlyOfficeCheckSuccess:"ONLYOFFICE 状态已刷新。",skillOnlyOfficeStatusReady:"可用",skillOnlyOfficeStatusWarning:"有风险",skillOnlyOfficeStatusError:"不可用",skillOnlyOfficeStatusMisconfigured:"未配好",skillOnlyOfficeStatusDisabled:"未启用",skillOnlyOfficeStatusUnknown:"状态未知",skillOnlyOfficeCheckPass:"通过",skillOnlyOfficeCheckWarn:"警告",skillOnlyOfficeCheckFail:"失败",skillOnlyOfficeCheckSkip:"跳过",skillOfficeBrowserBridgeSummaryLabel:"真实浏览器调试",skillOfficeWorkspaceScope:"当前范围",skillOfficeScoped:"当前工作区",skillOfficeGlobal:"全局",skillOfficeTemplateFormTitle:"文档模板配置",skillOfficeTemplateFormDescription:"在这里登记或更新当前可用的文档模板。模板 key 已存在时会按同 key 更新当前模板配置。",skillOfficeTemplateKeyLabel:"模板 Key",skillOfficeTemplateNameLabel:"模板名称",skillOfficeTemplateVersionLabel:"模板版本",skillOfficeTemplateFormatsLabel:"输出格式",skillOfficeTemplatePathLabel:"模板来源路径",skillOfficeTemplateSchemaLabel:"模板 Schema JSON",skillOfficeTemplateMappingLabel:"模板 Mapping JSON",skillOfficeTemplateSaveAction:"保存模板",skillOfficeTemplateCreated:"文档模板已创建。",skillOfficeTemplateUpdated:"文档模板已更新。",skillOfficeTemplateImported:"文档模板已导入。",skillOfficeTemplateListTitle:"可用模板",skillOfficeTemplateListDescription:"这里展示当前 Host 已登记的文档模板。",skillOfficeTemplateEmpty:"当前还没有可用的文档模板。",skillOfficeTemplateListMeta:"Key:{key} · 版本:{version}",skillOfficeTemplateEditAction:"模板文件",skillOfficeTemplateOpenCreateAction:"添加模板",skillOfficeTemplateModalTitle:"添加文档模板",skillOfficeTemplateModalDescription:"直接上传 .domt 或 .doct 模板文件,Host 会自动保存并识别模板信息。",skillOfficeTemplateUploadLabel:"模板文件",skillOfficeTemplateUploadDescription:"当前先支持 doct 模板文件导入,会自动生成模板 key、版本和默认映射。",skillOfficeTemplatePickAction:"选择模板文件",skillOfficeTemplateAutoDetectHint:"导入后会按文件名自动生成模板 key,并写入 Host 的模板目录。",skillOfficeBrowserProfileListTitle:"浏览器配置文件",skillOfficeBrowserProfileListDescription:"这里管理办公能力复用的真实浏览器配置,登录态、用户目录和接管方式都在这里看。",skillOfficeBrowserBridgeSummaryDetail:"{provider} 桥接状态:{status}。{detail}",skillOfficeBrowserBridgeDetailReady:"当前可以直接走真实浏览器调试。",skillOfficeBrowserBridgeAvailabilityUnknown:"状态未知",skillOfficeBrowserBridgeAvailabilityReady:"可用",skillOfficeBrowserBridgeAvailabilityDaemonMissing:"Daemon 未就绪",skillOfficeBrowserBridgeAvailabilityExtensionMissing:"扩展未连接",skillOfficeBrowserBridgeAvailabilityUnavailable:"不可用",skillOfficeBrowserProfileEmpty:"当前还没有可用的浏览器配置文件。",skillOfficeBrowserProfileOnlyCurrentWorkspace:"仅显示当前工作区记录",skillOfficeBrowserProfileListMeta:"{engine} · {mode} · {scope}",skillOfficeBrowserProfileOpenCreateAction:"添加浏览器配置",skillOfficeBrowserProfileModalTitle:"添加浏览器配置",skillOfficeBrowserProfileModalDescription:"创建独立浏览器配置,或接管已经开启远程调试端口的浏览器实例。",skillOfficeBrowserProfileFormTitle:"浏览器配置",skillOfficeBrowserProfileNameLabel:"配置名称",skillOfficeBrowserProfileEngineLabel:"浏览器",skillOfficeBrowserProfileModeLabel:"接入方式",skillOfficeBrowserProfileScopeLabel:"归属范围",skillOfficeBrowserProfileCdpEndpointLabel:"CDP 地址",skillOfficeBrowserProfileCdpEndpointDescription:"只有接管现有浏览器时才需要填写,例如 http://127.0.0.1:9222。",skillOfficeBrowserProfileSaveAction:"保存配置",skillOfficeBrowserProfileCreated:"浏览器配置已创建。",skillOfficeBrowserProfileEngineChrome:"Chrome",skillOfficeBrowserProfileEngineEdge:"Edge",skillOfficeBrowserProfileModePersistent:"独立配置",skillOfficeBrowserProfileModeCdpAttached:"接管现有浏览器",skillOfficeBrowserProfileScopeUser:"仅自己可用",skillOfficeBrowserProfileScopeWorkspace:"当前工作区可复用",skillOfficeBrowserProfileScopeTarget:"绑定到目标",skillOfficeBrowserProfileStatusActive:"可用",skillOfficeBrowserProfileStatusLocked:"占用中",skillOfficeBrowserProfileStatusArchived:"已归档",skillOfficeBrowserProfileStatusError:"异常",skillOfficeBrowserProfileUserDataDirLabel:"用户目录",skillOfficeBrowserProfileWorkspaceTag:"工作区:{workspaceName}",skillOfficeBrowserProfileWorkspaceUnbound:"未绑定工作区",skillOfficeBrowserProfileWorkspaceUnknown:"未知工作区",skillOfficeBrowserProfileCrossWorkspaceTag:"跨工作区可用",skillOfficeBrowserProfileOptionAction:"选项",skillOfficeBrowserProfileAllowCrossWorkspaceAction:"允许跨工作区使用",skillOfficeBrowserProfileSetWorkspaceOnlyAction:"设为仅当前工作区可用",skillOfficeBrowserProfileCrossWorkspaceEnabled:"浏览器配置已允许跨工作区使用。",skillOfficeBrowserProfileWorkspaceOnlyEnabled:"浏览器配置已改为仅当前工作区可用。",skillOfficeBrowserProfileWorkspaceRequired:"这个浏览器配置没有绑定工作区,不能切回仅当前工作区可用。",skillOfficeBrowserProfileOptionsModalTitle:"{profileName} 的选项",skillOfficeBrowserProfileOptionsModalDescription:"在这里调整这个浏览器配置的使用范围。",skillOfficeBrowserProfileOptionsSectionTitle:"使用范围",skillOfficeBrowserProfileCrossWorkspaceFieldLabel:"跨工作区使用",skillOfficeBrowserProfileCrossWorkspaceFieldDescription:"开启后,这个浏览器配置可以在其他工作区复用;关闭后,只允许当前工作区使用。",skillOfficeBrowserProfileTaskAction:"查看任务",skillOfficeBrowserProfileDeleteAction:"删除配置",skillOfficeBrowserProfileDeleted:"浏览器配置已删除。",skillOfficeBrowserProfileDeleteModalTitle:"确认删除浏览器配置",skillOfficeBrowserProfileDeleteModalDescription:"删除前会再确认一次,避免误删当前正在使用的配置。",skillOfficeBrowserProfileDeleteModalWarning:"删除后,这个浏览器配置会从办公能力里移除;未开始的关联任务会自动取消。",skillOfficeBrowserProfileDeleteConfirmAction:"确认删除",skillOfficeBrowserProfileCdpEndpointTag:"已接管",skillOfficeBrowserProfileTaskModalTitle:"{profileName} 的任务记录",skillOfficeBrowserProfileTaskModalDescription:"这里集中查看这个浏览器配置对应的任务记录和执行状态。",skillOfficeBrowserProfileTaskListTitle:"任务记录",skillOfficeBrowserProfileTaskListDescription:"所属工作区:{workspaceName}",skillOfficeBrowserProfileTaskEmpty:"这个浏览器配置还没有任务记录。",skillOfficeBrowserInstanceListTitle:"浏览器实例",skillOfficeBrowserInstanceListDescription:"实例本质上就是浏览器任务。这里可以新建、执行、查看当前运行状态,也能直接取消运行中的实例。",skillOfficeBrowserInstanceEmpty:"当前还没有浏览器实例。",skillOfficeBrowserInstanceListMeta:"{profileName} · {status} · 风险 {risk}",skillOfficeBrowserInstanceExecutionIdle:"未启动",skillOfficeBrowserInstanceExecutionQueued:"排队中",skillOfficeBrowserInstanceExecutionRunning:"运行中",skillOfficeBrowserInstanceExecutionSucceeded:"已完成",skillOfficeBrowserInstanceExecutionFailed:"执行失败",skillOfficeBrowserInstanceExecutionCancelled:"已取消",skillOfficeBrowserInstanceExecutionTimeout:"已超时",skillOfficeBrowserExecutionBackendPlaywright:"无头浏览器",skillOfficeBrowserExecutionBackendOpenCliBridge:"真实浏览器调试",skillOfficeBrowserInstanceDetailAction:"查看详情",skillOfficeBrowserInstanceExecuteAction:"启动实例",skillOfficeBrowserInstanceCancelAction:"取消实例",skillOfficeBrowserInstanceStarted:"浏览器实例已开始执行。",skillOfficeBrowserInstanceCancelled:"浏览器实例已取消。",skillOfficeBrowserInstanceSnapshotPending:"还没有执行快照",skillOfficeBrowserInstanceSnapshotMeta:"状态:{status} · 尝试次数:{attempt} · 开始:{startedAt} · 结束:{finishedAt}",skillOpsTaskCount:"当前任务",skillOpsTargetCount:"SSH 主机",skillOpsWorkspaceScope:"当前范围",skillOpsTaskListTitle:"运维任务",skillOpsTaskListDescription:"这里只看运维类型任务,方便快速检查当前工作区的执行状态和审批状态。",skillOpsTaskEmpty:"当前还没有运维任务。",skillOpsTaskListMeta:"状态:{status} · 风险:{risk}",skillOpsTaskDetailAction:"查看详情",skillOpsApprovalApproveAction:"批准",skillOpsApprovalApproveNote:"已在技能面板中批准执行。",skillOpsApprovalRejectNote:"已在技能面板中拒绝执行。",skillOpsApprovalApproved:"运维审批已批准。",skillOpsApprovalRejected:"运维审批已拒绝。",skillOpsTargetFormTitle:"SSH 主机配置",skillOpsTargetFormDescription:"这里先接当前已经真正支持的 SSH 主机字段:主机、用户名、端口、密钥路径和凭据引用。",skillOpsPasswordNotice:"当前正式能力只保证密钥路径和凭据引用链路可用,密码认证链路还没有完整接通。",skillOpsTargetNameLabel:"主机名称",skillOpsTargetEnvironmentLabel:"环境",skillOpsTargetHostLabel:"主机地址",skillOpsTargetPortLabel:"端口",skillOpsTargetUsernameLabel:"登录用户",skillOpsTargetPrivateKeyPathLabel:"私钥路径",skillOpsTargetKnownHostsPathLabel:"known_hosts 路径",skillOpsTargetJumpHostLabel:"跳板机",skillOpsTargetWorkspacePathLabel:"默认工作目录",skillOpsTargetCredentialRefLabel:"凭据引用",skillOpsTargetHostKeyPolicyLabel:"主机校验策略",skillOpsTargetSaveAction:"保存主机",skillOpsTargetResetAction:"清空表单",skillOpsTargetCreated:"SSH 主机已创建。",skillOpsTargetUpdated:"SSH 主机已更新。",skillOpsTargetListTitle:"已保存主机",skillOpsTargetListDescription:"这里展示当前范围内已保存的 SSH 主机配置。",skillOpsTargetEmpty:"当前还没有已保存的 SSH 主机。",skillOpsTargetEditAction:"载入编辑",skillOpsTargetOpenCreateAction:"添加主机",skillOpsTargetModalTitle:"添加 SSH 主机",skillOpsTargetModalDescription:"在这个窗口里登记当前工作区可用的 SSH 主机配置。",skillWorkspaceSessionMcpStatusAction:"查看 MCP 状态",skillWorkspaceSessionMcpModalTitle:"工作区会话 MCP 状态",skillWorkspaceSessionMcpModalDescription:"这里同时检查当前工作区会话 runtime、全局 CLI 安装状态,以及各个 CLI 是否已经具备调用 office MCP 的条件。",skillWorkspaceSessionMcpLoading:"正在读取 MCP 状态…",skillWorkspaceSessionMcpRuntimeTitle:"当前会话 runtime",skillWorkspaceSessionMcpRuntimeDescription:"先看当前工作区会话在全局 CodingNS 目录下的专用 runtime 是否真的落出了 scoped 认证、说明文件和专用 skill;Codex 的 office MCP 依赖这些运行时资产做启动时注入,不再要求写入全局 home。",skillWorkspaceSessionMcpReadyCliCount:"可直接调用",skillWorkspaceSessionMcpConfiguredCliCount:"已写配置/已注入",skillWorkspaceSessionMcpTotalCliCount:"CLI 数量",skillWorkspaceSessionMcpOverallLabel:"总体状态",skillWorkspaceSessionMcpCurrentSessionLabel:"当前会话",skillWorkspaceSessionMcpCodexLabel:"Codex",skillWorkspaceSessionMcpRuntimeHomeLabel:"runtime 目录",skillWorkspaceSessionMcpAuthFileLabel:"scoped 认证文件",skillWorkspaceSessionMcpInstructionFileLabel:"组合说明文件",skillWorkspaceSessionMcpSkillDirLabel:"工作区会话 skill 目录",skillWorkspaceSessionMcpCommandTitle:"CLI 命令状态",skillWorkspaceSessionMcpCommandDescription:"这里区分仓库里的实现是否已具备,和你机器当前全局安装的 CLI 是否已经升级到可用版本。",skillWorkspaceSessionMcpGlobalCodingnsLabel:"全局 codingns",skillWorkspaceSessionMcpGlobalStandaloneLabel:"全局 codingns-workspace-office-mcp",skillWorkspaceSessionMcpGlobalStandaloneMissing:"当前机器还没有这个独立命令入口。",skillWorkspaceSessionMcpRepoCodingnsLabel:"仓库内 codingns.mjs",skillWorkspaceSessionMcpCliTitle:"各 CLI 调用状态",skillWorkspaceSessionMcpCliDescription:"这里按各 CLI 的真实接入方式判断是否可用:Codex 看运行时注入链路,Claude Code / OpenCode 继续看 runtime 配置是否落地。",skillWorkspaceSessionMcpRefreshAction:"刷新 MCP 状态",skillWorkspaceSessionMcpStateReady:"已就绪",skillWorkspaceSessionMcpStatePartial:"部分就绪",skillWorkspaceSessionMcpStateMissing:"未就绪",skillWorkspaceSessionMcpBrowserBridgeLabel:"真实浏览器调试",skillWorkspaceSessionMcpBrowserBridgeDetail:"这里指的是 browser.opencli_bridge。它不是 profile 型任务,不需要先查或先建浏览器 Profile。",skillWorkspaceSessionMcpRecommendedPathLabel:"推荐调用链路",skillWorkspaceSessionMcpValueMissing:"当前没有可用路径",skillWorkspaceSessionMcpEmptyTitle:"还没有拿到 MCP 状态",skillWorkspaceSessionMcpEmptyDescription:"请先确认当前已经进入工作区普通会话,并且这个会话已经在全局 CodingNS 目录下生成专用 runtime。"},shell:{title:"工作台",subtitle:"管理代码项目里的 AI 会话",mobileWorkspacesEntry:"工作区",mobileTerminalsEntry:"终端",mobileSessionsEntry:"对话",mobileToolsEntry:"工具",mobileSettingsEntry:"设置",mobileNavigationAction:"打开工作台菜单",mobileSearchAction:"打开搜索",mobileAuxiliaryAction:"打开工具面板",mobileRevealNavigationAction:"显示主导航",mobileHideNavigationAction:"收起主导航",mobileConversationPreviewTitle:"快速预览",mobileConversationCurrentWorkspaceSection:"当前工作区",mobileConversationCollapsePreviewAction:"收起预览",mobileConversationRestorePreviewAction:"恢复会话预览",iosMoreAction:"更多操作",androidMoreAction:"更多操作",conversationEntry:"对话",terminalsEntry:"终端",butlerEntry:"助手",skillsEntry:"技能",codeShortcutRailTitle:"快捷应用",codeShortcutSystemBadge:"系统应用",codeShortcutTerminalTitle:"终端",codeShortcutTerminalAction:"打开终端面板",codeShortcutSkillsTitle:"技能",codeTerminalDockTitle:"终端",codeTerminalDockWorkspaceFallback:"当前工作区",codeTerminalDockCloseAction:"关闭终端面板",codeTerminalDockLayoutLabel:"终端布局",codeTerminalDockLayoutVertical:"上下布局",codeTerminalDockLayoutHorizontal:"左右布局",codeTerminalDockSwitchToVerticalAction:"切换到上下布局",codeTerminalDockSwitchToHorizontalAction:"切换到左右布局",codeTerminalDockResizeLabel:"调整对话区和终端区比例",globalNotificationsAction:"通知",globalNotificationsUnreadAria:"未读通知 {count}",globalNotificationsPanelTitle:"通知中心",globalNotificationsPanelDescription:"这里集中看需要你拍板、代办分析结果、跟进状态和验证失败的提醒。",globalNotificationsEmpty:"当前没有新的全局通知。",globalNotificationsShowArchived:"显示已归档通知",globalNotificationsArchiveAction:"归档",globalNotificationsRemoveArchiveAction:"移除归档",globalNotificationsArchiveFailed:"通知归档更新失败",globalNotificationKindWaitingUser:"等待你决定",globalNotificationKindTodoAnalyzed:"代办分析完成",globalNotificationKindTodoAnalyzeFailed:"代办分析失败",globalNotificationKindFollowUpFailed:"跟进失败",globalNotificationKindFollowUpCompleted:"跟进完成",globalNotificationKindVerificationFailed:"验证失败",globalNotificationTodoAnalyzedTitle:"代办分析完成:{title}",globalNotificationTodoAnalyzeFailedTitle:"代办分析失败:{title}",globalNotificationFollowUpWaitingTitle:"需要你决定:{title}",globalNotificationFollowUpFailedTitle:"跟进失败:{title}",globalNotificationFollowUpCompletedTitle:"跟进完成:{title}",globalNotificationVerificationFailedTitle:"验证失败:{title}",globalNotificationVerificationFailedFallback:"最近一次验证没有通过,请尽快查看。",searchEntry:"搜索",workbenchModeTabsLabel:"工作台模式",workbenchModeCode:"代码",workbenchModeAffairs:"事务",affairsInitPill:"文档与工作台",workbenchModeCodeOpenInNewWindow:"在新窗口打开代码",affairsSectionGroupPrimary:"分区入口",affairsSectionGroupFavorites:"收藏",affairsSectionGroupRecent:"最近打开",affairsNavigationDescription:"这里先收口事务分区、收藏和最近对象,别再把对象入口散在各个角落。",affairsLibraryNav:"文档",affairsLibraryNavSummary:"当前先把文档对象和相关操作接进来。",affairsLibrarySummary:"文档对象先落在中间主舞台,右侧再给详情和事务助手。",affairsWorkbenchNav:"工作台",affairsWorkbenchSummary:"把代办、自动化和 HTML 工具都收进统一工作台。",affairsWorkbenchSidebarTitle:"工作台",affairsWorkbenchSidebarDescription:"先把代办和自动化收在一起,再把右侧整块区域交给画布。当前共 {todoCount} 条代办、{automationCount} 个自动化。",affairsWorkbenchSidebarGroupOverview:"总览",affairsWorkbenchStageTitle:"工作台",affairsWorkbenchStageDescription:"这里会逐步长成整块画布式工作台。当前先保留总览、代办和自动化入口,共 {count} 项。",affairsWorkbenchEmpty:"当前还没有可展示的工作台内容。",affairsWorkbenchEmptyBody:"这一块后面会变成可摆放代办、自动化和 HTML 插件的画布。现在先用它收口旧入口,避免继续分散。",affairsWorkbenchEyebrow:"工作台预览",affairsWorkbenchDefaultTabTitle:"默认工作台",affairsWorkbenchDefaultTabShortTitle:"默认",affairsWorkbenchNewTabTitle:"工作台 {count}",affairsWorkbenchAddTabAction:"新建标签页",affairsWorkbenchRenameTabAction:"重命名标签页",affairsWorkbenchDeleteTabAction:"删除标签页",affairsWorkbenchCanvasTitle:"工作台画布",affairsWorkbenchCanvasDescription:"这块区域现在就是完整工作台画布。顶部切标签页,下面的块可以直接拖动位置,也可以直接拖拽调整大小。",affairsWorkbenchCanvasEmptyTitle:"这个标签页还没有块",affairsWorkbenchCanvasEmptyBody:"先在这里添加第一块,后面这里会变成可调整布局的正式画布。",affairsWorkbenchWidgetHtmlAppHint:"把工作区里的静态 HTML 页面直接钉进画布,适合常用工具或小应用。",affairsWorkbenchWidgetHtmlStatHint:"把 HTML 统计页面作为指标块固定在画布里,适合盯数据。",affairsWorkbenchWidgetHtmlEmbedHint:"把受控 HTML 页面嵌进工作台,适合展示页面块或只读页面。",affairsWorkbenchWidgetOpenTodoAction:"打开代办列表",affairsWorkbenchWidgetOpenAutomationAction:"打开自动化列表",affairsWorkbenchWidgetCountValue:"共 {count} 项",affairsWorkbenchWidgetTeableBadge:"Teable",affairsWorkbenchHtmlWidgetBadge:"HTML",affairsWorkbenchHtmlAppDefaultTitle:"HTML 应用",affairsWorkbenchHtmlStatDefaultTitle:"HTML 统计",affairsWorkbenchHtmlEmbedDefaultTitle:"HTML 页面",affairsWorkbenchCancelAction:"取消",affairsWorkbenchAddWidgetAction:"添加块",affairsWorkbenchResetLayoutAction:"恢复默认布局",affairsWorkbenchLockLayoutAction:"锁定布局",affairsWorkbenchUnlockLayoutAction:"解锁布局",affairsWorkbenchWidgetTypeTodo:"代办块",affairsWorkbenchWidgetTypeAutomation:"自动化块",affairsWorkbenchWidgetTypeTeable:"Teable 块",affairsWorkbenchWidgetTypeHtml:"HTML 块",affairsWorkbenchWidgetTypeHtmlApp:"HTML 应用块",affairsWorkbenchWidgetTypeHtmlStat:"HTML 统计块",affairsWorkbenchWidgetTypeHtmlEmbed:"HTML 页面块",affairsWorkbenchHtmlVariantField:"用途预设",affairsWorkbenchHtmlVariantHelper:"这里只是创建时的默认用途预设,主要影响默认标题、推荐尺寸和后续呈现语义。",affairsWorkbenchHtmlVariantApp:"应用",affairsWorkbenchHtmlVariantStat:"统计",affairsWorkbenchHtmlVariantEmbed:"页面",affairsWorkbenchWidgetTitleField:"块标题",affairsWorkbenchWidgetTitlePlaceholder:"不填就用默认标题",affairsWorkbenchHtmlSourceWorkspaceField:"来源工作区",affairsWorkbenchHtmlSourceWorkspaceHelper:"先选择代码工作区,再从这个工作区里选 HTML 文件。HTML 预览和权限会沿用该工作区。",affairsWorkbenchHtmlSourceWorkspaceCurrentLibraryOption:"当前文档库",affairsWorkbenchHtmlSourceWorkspaceCurrentLibraryHelper:"当前文档库路径:{path}。下面的文件列表直接来自这份全局文档库配置。",affairsWorkbenchHtmlSourceField:"HTML 文件路径",affairsWorkbenchHtmlSourcePlaceholder:"例如:tools/report/index.html",affairsWorkbenchHtmlSourceSelectField:"HTML 文件",affairsWorkbenchHtmlSourceSelectPlaceholder:"请选择一个 HTML 文件",affairsWorkbenchHtmlSourceHelper:"先选来源工作区,再从下面的文件列表里选 HTML 文件。",affairsWorkbenchHtmlSourceListFailed:"读取工作区 HTML 文件列表失败",affairsWorkbenchHtmlSourceInvalid:"只允许添加 .html 或 .htm 文件。",affairsWorkbenchHtmlSourceUnsupported:"这个文件当前不能作为工作台 HTML 来源。",affairsWorkbenchHtmlSourceMissing:"当前块还没有可用的 HTML 来源。",affairsWorkbenchHtmlSourceLoadFailed:"加载 HTML 页面失败",affairsWorkbenchConfirmAddWidgetAction:"确认添加",affairsWorkbenchAddWidgetFailed:"添加工作台块失败",affairsWorkbenchWidgetSizeGroup:"块尺寸",affairsWorkbenchWidgetSizeSmall:"小",affairsWorkbenchWidgetSizeMedium:"中",affairsWorkbenchWidgetSizeLarge:"大",affairsWorkbenchMoveWidgetBackwardAction:"向前移动",affairsWorkbenchMoveWidgetForwardAction:"向后移动",affairsWorkbenchDragWidgetAction:"拖动块",affairsWorkbenchResizeWidgetAction:"调整块大小",affairsWorkbenchRemoveWidgetAction:"删除块",affairsWorkbenchWidgetErrorTitle:"这个块加载失败了",affairsWorkbenchWidgetErrorBody:"先保留其他块继续用,再检查这个块的配置或来源。",affairsWorkbenchWidgetTodoViewLabel:"代办块视图",affairsWorkbenchWidgetCompactView:"紧凑",affairsWorkbenchWidgetDetailView:"明细",affairsWorkbenchWidgetAutomationViewLabel:"自动化块视图",affairsWorkbenchWidgetAutomationListView:"任务",affairsWorkbenchWidgetAutomationRecentView:"最近运行",affairsWorkbenchWidgetAutomationRunFallbackTitle:"自动化运行",affairsWorkbenchOpenHtmlAction:"新窗口打开",teableRuntimeDefaultBlockTitle:"Teable 数据",teableRuntimeTableField:"Teable 表",teableRuntimeViewField:"Teable 视图",teableRuntimeCreateFormViewField:"新建记录表单视图",teableRuntimeEditFormViewField:"编辑记录表单视图",teableRuntimeViewGrid:"表格",teableRuntimeViewForm:"表单",teableRuntimeViewCalendar:"日历",teableRuntimeViewKanban:"看板",teableRuntimeTablesLoadFailed:"读取 Teable 表失败",teableRuntimeViewsLoadFailed:"读取 Teable 视图失败",teableRuntimeTablesEmpty:"当前 Base 里还没有可选表。请先到 Teable 创建表,或检查连接设置。",teableRuntimeViewsEmpty:"这张表没有可用的表格、表单、日历或看板视图。",teableRuntimeFormViewsEmpty:"这张表没有可用的表单视图。请先在 Teable 里创建表单视图,再添加这个块。",teableRuntimeSelectionRequired:"请先选择 Teable 表和视图。",teableRuntimeBlockLoadFailed:"加载 Teable 数据失败",teableRuntimeConfigMissing:"这个 Teable 块缺少表配置。",teableRuntimeRefreshAction:"刷新记录",teableRuntimeRecordsEmpty:"当前视图还没有记录。",teableRuntimeEmptyValue:"空",teableRuntimePrimaryFieldMissing:"这张表没有可用的主字段。",teableRuntimeRecordDrawerTitle:"编辑记录",teableRuntimeRecordDrawerDescription:"普通字段可以编辑;公式、查找和汇总字段只读,由 Teable 计算。",teableRuntimeRecordFieldsTitle:"记录字段",teableRuntimeReadonlyHint:"保存后会重新读取记录,显示 Teable 计算后的最新值。",teableRuntimeSaveRecordAction:"保存记录",teableRuntimeDeleteRecordAction:"删除记录",teableRuntimeDeleteConfirm:"确定删除这条 Teable 记录吗?",teableRuntimeSaveFailed:"保存记录失败",teableRuntimeDeleteFailed:"删除记录失败",teableRuntimeCreateFailed:"新建记录失败",teableRuntimeCreateRecordAction:"新建记录",teableRuntimeCreateRecordModalTitle:"新建 Teable 记录",teableRuntimeCreateRecordModalDescription:"正在向「{table}」添加一条新记录。",teableRuntimeCreateRecordFieldsTitle:"填写记录内容",teableRuntimeCreateRecordFieldsDescription:"这里按 Teable 表单视图能读取到的字段顺序、可见字段和必填规则展示。",teableRuntimeNoWritableFields:"这张表没有可填写的字段。",teableRuntimeRequiredMark:" *",teableRuntimeRequiredFieldMissing:"请填写「{field}」。",teableRuntimeUnsupportedEditor:"暂不支持编辑,当前值:{value}",teableRuntimeLinkOptionsLoadFailed:"读取关联记录失败",teableRuntimeLinkFieldMissing:"这个关联字段缺少关联表配置。",teableRuntimeLinkEmptyOption:"不选择",teableRuntimeCalendarDateMissing:"日历视图需要一个日期字段。请在 Teable 视图或块设置里选择日期字段。",teableRuntimeKanbanGroupMissing:"看板视图需要一个单选字段。请在 Teable 视图或块设置里选择分组字段。",affairsShortcutRailTitle:"快捷应用",affairsShortcutRailDescription:"暂无",affairsShortcutRailEmpty:"暂无",affairsShortcutRailEditAction:"编辑",affairsShortcutRailDoneAction:"完成",affairsShortcutRailAddAction:"添加应用",affairsShortcutRailTitleField:"应用名称",affairsShortcutRailTitlePlaceholder:"不填就用文件名",affairsShortcutRailSourceSelectField:"文件",affairsShortcutRailSourceSelectPlaceholder:"请选择一个文件",affairsShortcutRailSourceHelper:"先选来源工作区,再从下面的文件列表里选一个文件。打开时会复用该工作区的预览和权限。",affairsShortcutRailSourceListFailed:"读取工作区文件列表失败",affairsShortcutRailSourceInvalid:"请选择一个文件。",affairsShortcutRailSourceUnsupported:"这个文件当前不能作为快捷应用打开。",affairsShortcutRailSourcePickerTitle:"选择文件",affairsShortcutRailSourcePickerDescription:"从工作区目录里选一个文件,保存后会作为快捷应用打开。",affairsShortcutRailSourcePickerCurrentField:"当前文件",affairsShortcutRailSourcePickerCurrentEmpty:"还没选文件",affairsShortcutRailSourcePickerTreeTitle:"工作区文件",affairsShortcutRailSourcePickerTreeEmpty:"当前没有可选文件",affairsShortcutRailSourcePickerTreeEmptyDescription:"先展开目录,再选一个能预览的文件。",affairsShortcutRailSourcePickerRetryAction:"重新加载",affairsShortcutRailSourcePickerConfirmAction:"使用这个文件",affairsShortcutRailConfirmAddAction:"添加到快捷应用",affairsShortcutRailConfirmEditAction:"保存快捷应用",affairsShortcutRailAddedTitle:"快捷应用已添加",affairsShortcutRailUpdatedTitle:"快捷应用已更新",affairsShortcutRailAddFailed:"添加快捷应用失败",affairsShortcutRailUpdateFailed:"更新快捷应用失败",affairsShortcutRailOpenAction:"打开",affairsShortcutRailOpenFailed:"打开快捷应用失败",affairsShortcutRailRemoveAction:"移除",affairsShortcutRailExpandAction:"展开",affairsShortcutRailCollapseAction:"收起",affairsShortcutRailMoveLeftAction:"移到左侧",affairsShortcutRailMoveRightAction:"移到右侧",affairsShortcutRailLaunchAction:"打开快捷应用:{title}",affairsShortcutRailEditEntryAction:"编辑快捷应用:{title}",affairsShortcutRailPreviewEditDisabled:"快捷应用当前只支持预览,不支持直接编辑。",codeShortcutRailStateSaveFailed:"快捷应用栏状态保存失败",affairsWorkbenchDetailTitle:"工作台总览",affairsWorkbenchDetailDescription:"这里先展示工作台的标签页和画布方向,等块系统接完后,再把更多细节放进来。",affairsWorkbenchOverviewLabel:"总览",affairsWorkbenchOverviewSummary:"先收口 {todoCount} 条代办和 {automationCount} 个自动化,后面再接画布块。",affairsWorkbenchAssistantContextTitle:"当前工作台代办",affairsWorkbenchAssistantContextSummary:"当前筛选是 {scopeLabel},共 {count} 条代办。优先关注:{titles}",affairsWorkbenchAssistantContextSummaryCompact:"当前筛选是 {scopeLabel},共 {count} 条代办。",affairsWorkbenchAssistantContextEmpty:"当前筛选下还没有代办,先帮我判断下一步该补什么。",affairsWorkbenchStepTodoTitle:"先看代办",affairsWorkbenchStepTodoDescription:"代办先按来源收进工作台,后面会变成可拖拽的块。",affairsWorkbenchStepAutomationTitle:"再看自动化",affairsWorkbenchStepAutomationDescription:"自动化任务先保留现有列表,后面再接进画布。",affairsWorkbenchStepHtmlTitle:"最后接 HTML 块",affairsWorkbenchStepHtmlDescription:"静态 HTML 快捷应用和统计插件后面统一按工作台块接入。",affairsConversationNav:"纯对话",affairsConversationSummary:"这里放纯对话历史和快速问答入口,不去碰当前项目文件。",affairsConversationSidebarTitle:"纯对话",affairsConversationSidebarListTitle:"会话列表",affairsConversationSidebarGroupModes:"创建入口",affairsConversationStageTitle:"纯对话",affairsConversationStageDescription:"先把事务对话入口和创建方式收口,后面再一条条接真实运行时。",affairsConversationEmpty:"当前还没有纯对话,先新建一条。",affairsConversationEmptyEyebrow:"开始",affairsConversationEmptyBody:"从这里新建一条纯对话,用来快速提问、联网搜索和轻量分析。",affairsConversationEmptyCreateTitle:"新建",affairsConversationEmptyCreateBody:"点击“新建对话”后,选择纯对话使用的模型再开始。",affairsConversationEmptyModeTitle:"先选会话模式",affairsConversationEmptyModeBody:"纯对话适合快速问答、联网搜索和轻量分析,不会读取本地项目文件。",affairsConversationEmptySelectedTitle:"当前准备创建的会话",affairsConversationEmptyCompanionTitle:"右侧配合使用",affairsConversationEmptyCompanionBody:"如果要继续处理代码,请回到上方项目对话。",affairsConversationEmptyTip:"这里的纯对话只负责快速问答和轻量分析。",affairsConversationEmptyDescription:"这里复用正式聊天页样式,但先把创建入口、模式分组和 provider 选择钉住,避免后面越做越乱。",affairsConversationEntryBadge:"正式入口",affairsConversationCreateAction:"新建对话",affairsConversationCreateHint:"新建纯对话",affairsConversationSidebarLoadingAll:"正在补全会话列表…",affairsConversationSidebarLoadingLightweight:"正在加载纯对话历史…",affairsConversationSidebarLoadingAgent:"正在补全助手会话…",affairsConversationAgentSessionHint:"当前工作区还没有可复用的助手会话。",affairsConversationLightweightCapabilityHint:"纯对话只支持快速问答、联网搜索和轻量分析,不会调用本地项目工具。",affairsConversationLightweightLoadFailed:"读取纯对话历史失败",affairsConversationAgentLoadFailed:"读取助手会话列表失败",affairsConversationCreateModalDescription:"先选模式,再选 provider。纯对话模式只放适合快速问答和轻量分析的 provider。",affairsConversationCreateModalDescriptionWithWorkspace:"当前文档库:{workspace}。先选会话模式,再选 provider。",affairsConversationLightweightTitle:"纯对话模式",affairsConversationLightweightDescription:"适合快速提问、联网搜索和轻量分析,不会读取或修改当前项目文件。",affairsConversationAssistantTitle:"助手模式",affairsConversationAssistantDescription:"这里复用完整助手链路和 AGENTS.md 注入,适合继续做 Agent 任务。",affairsConversationModePickerTitle:"先选会话模式,再选 provider",affairsConversationModePickerDescription:"轻量和 Agent 说的是能力级别,Codex 和 Claude Code 说的是底层 provider,这两件事不能混。",affairsConversationBoundaryTitle:"这一页当前先定什么",affairsConversationBoundaryDescription:"这一步先把入口、壳层和边界钉住,不急着把所有运行时一次接完。",affairsConversationBoundaryLightweight:"纯对话只做快速问答、联网搜索和轻量分析,不带完整本地工具。",affairsConversationBoundaryAgent:"Agent 会话后面复用完整助手链路,围绕当前文档库和事务对象继续工作。",affairsConversationBoundaryProvider:"轻量模式和助手模式是两类会话,不是 provider 别名;provider 只负责底层模型来源。",affairsInitSubmit:"完成助手初始化",affairsInitSuccess:"助手初始化已完成",affairsInitFailed:"助手初始化失败",affairsInitPreviewRuleLabel:"文档和工作台助手",affairsInitLibraryTitle:"文档库设置",affairsInitLibraryDescription:"这里决定第一次进入文档和工作台时,要不要直接把文档库接上。",affairsInitLibraryEnabledLabel:"是否启用文档库",affairsInitLibraryEnabledHint:"启用后会在初始化完成后直接绑定文档库,并开始可用。",affairsInitLibraryPathHint:"这里填事务文档库根目录,后面还能在文档库设置里再改。",affairsInitLibraryPathRequired:"启用文档库时,必须先选择文档库路径",affairsInitRouteGuardHint:"文档和工作台需要先完成助手初始化,完成后会回到你刚才要打开的位置。",affairsInitRouteGuardSidebarEmpty:"先完成初始化,左侧分区内容才会出现。",affairsInitRouteGuardAuxiliaryEmpty:"先完成初始化,右侧详情区才会展示对象内容。",affairsConnectionCheckingTitle:"正在检查助手服务",affairsConnectionCheckingDescription:"先确认 Host 是否可用,再加载文档、工作台和助手能力。",affairsConnectionCheckingSidebarEmpty:"正在检查连接状态,纯对话历史稍后再加载。",affairsConnectionCheckingAuxiliaryEmpty:"正在检查连接状态,纯对话详情稍后再加载。",affairsHostUnavailableTitle:"暂时连不上助手服务",affairsHostUnavailableDescription:"现在不是初始化问题,而是前端还连不上 Host。先把连接恢复,再回来继续。",affairsHostUnavailableRetryAction:"重新连接",affairsHostUnavailableRetryHint:"重试不会改你的初始化状态,只会重新检查 Host 是否恢复可用。",affairsHostUnavailableErrorTitle:"连接报错",affairsHostUnavailableSidebarEmpty:"连接恢复前,左侧分区内容暂时加载不出来。",affairsHostUnavailableAuxiliaryEmpty:"连接恢复前,右侧详情区暂时拿不到对象内容。",affairsConversationKindLightweight:"纯对话",affairsConversationKindAgent:"Agent 会话",affairsConversationOptionLabel:"{kind} · {provider}",affairsConversationOptionSummaryLightweight:"用 {provider} 开一条轻量对话,优先做快速问答、联网搜索和轻分析。",affairsConversationOptionSummaryAgent:"用 {provider} 开一条助手对话,后面复用完整助手链路和当前事务上下文。",affairsTodoNav:"待办",affairsTodoSummary:"这里后面承接待办拆解、优先级和执行跟踪。",affairsAutomationNav:"自动化",affairsAutomationSummary:"这里后面承接自动化流程、浏览器任务和运维结果。",affairsPluginsNav:"插件",affairsPluginsSummary:"这里后面承接事务插件和对象级扩展入口。",affairsComingSoon:"这块先占位,后面按 spec 继续接。",affairsLibraryTitle:"文档库",affairsToolbarCount:"{count} 项",affairsToolbarSummary:"当前工作区:{workspaceName} · 共 {count} 个对象",affairsToolbarExpand:"展开工具区",affairsToolbarCollapse:"收起工具区",affairsToolbarPlaceholderNew:"新建",affairsToolbarPlaceholderSearch:"搜索",affairsToolbarPlaceholderFilter:"筛选",affairsLibraryResultTitle:"对象结果",affairsLibraryEmpty:"当前还没有可用对象,先从左侧切分区或回到代码视图沉淀内容。",affairsSectionPlaceholderBadge:"规划中",affairsTodoPlaceholderTitle:"待办区稍后接入",affairsTodoPlaceholderDescription:"这块先保留正式入口,后面把待办拆解、标签整理和执行跟踪接进来。",affairsAutomationPlaceholderTitle:"自动化区稍后接入",affairsAutomationPlaceholderDescription:"这块先保留正式入口,后面把浏览器任务、自动化流程和运维动作接进来。",affairsPluginsPlaceholderTitle:"插件区稍后接入",affairsPluginsPlaceholderDescription:"这块先保留正式入口,后面把事务插件和对象级扩展入口接进来。",affairsDetailTitle:"对象详情",affairsDetailEmpty:"先从中间选一个对象,右侧再给你详情和助手。",affairsObjectTypeDocument:"文档",affairsAssistantTitle:"事务助手",affairsAssistantDescription:"这里的助手先围绕当前对象工作,不再把代码会话当默认语境。",affairsAssistantPlaceholder:"围绕《{title}》继续处理文档、标签、待办或浏览器任务",affairsAssistantPlaceholderEmpty:"先选一个对象,再让助手围着它做事。",affairsAssistantContextFallback:"当前对象还没有更多摘要。",affairsAssistantPromptPreamble:`当前事务对象:{title}
42
42
  对象摘要:{summary}
43
43
  来源:{sourceRef}
44
44
  请围绕这个对象处理文档整理、标签、待办拆解、浏览器任务和导出建议。`,affairsAssistantPromptPreambleEmpty:"当前还没有选中事务对象,请先帮我判断应该先看什么,再给下一步建议。",affairsDocumentSummaryTemplate:"来自会话《{sessionTitle}》的文档对象占位,后面这里会接正式文档索引结果。",affairsSidebarMenuLabel:"事务视图分区菜单",affairsLibrarySidebarTitle:"收藏与标签",affairsLibrarySidebarDescription:"当前工作区共 {count} 份文档对象,已收口 {favorites} 个收藏、{tags} 个标签。",affairsLibraryAllFilter:"全部文档",affairsLibraryAllFilterSummary:"按当前工作区查看全部文档对象。",affairsLibraryFavoritesSummary:"优先看你已经标过星的内容。",affairsLibraryFavoritesEntry:"全部收藏",affairsLibraryTagSummary:"按标签筛当前文档结果。",affairsLibraryFoldersEntry:"目录",affairsLibraryFoldersSummary:"按目录浏览当前文档库。",affairsLibraryTagsEntry:"标签",affairsLibraryTagsSummary:"按标签浏览当前文档库。",affairsLibraryFolderNodeSummary:"按目录筛当前文档结果。",affairsLibraryTagNodeSummary:"按标签筛当前文档结果。",affairsLibraryRefreshAction:"刷新文档库",affairsLibraryRefreshQueued:"已开始刷新文档库",affairsLibraryRefreshQueuedDescription:"系统会在后台重新扫描文档并更新目录、标签和列表结果。",affairsLibraryRefreshFailed:"刷新文档库失败",affairsLibraryBindingTitle:"先绑定文档库路径",affairsLibraryBindingDescription:"给当前事务视图指定一个文档库根目录,后面左侧目录、收藏、标签和中间文档列表都基于这里显示。",affairsLibraryBindingFieldLabel:"文档库路径",affairsLibraryBindingFieldPlaceholder:"/Users/you/Documents/Knowledge",affairsLibraryBindingSubmitAction:"保存路径",affairsLibraryBindingBrowseAction:"选择目录",affairsLibraryBindingPickerTitle:"选择文档库目录",affairsLibraryBindingPickerDescription:"从真实目录里挑一个文档库根路径,事务视图会基于这里显示目录、收藏、标签和文档。",affairsLibraryBindingUseThisDirectory:"使用这个目录",affairsLibraryEnableLabel:"启用文档库",affairsLibraryEnableHint:"关闭后会停掉当前工作区的内置索引服务,重新开启后才会继续刷新索引。",affairsLibraryEnableAction:"启用",affairsLibraryDisableAction:"停用",affairsLibraryEnabledState:"已启用",affairsLibraryDisabledState:"未启用",affairsLibraryEnableSaveFailed:"更新文档库开关失败",affairsLibraryDisabledSummary:"文档库功能当前已关闭。重新启用后,内置索引服务才会继续工作。",affairsLibraryConfigTitle:"文档库设置",affairsLibraryConfigDescription:"这里补本地镜像路径、允许索引的文件类型,以及确实需要放行的隐藏路径。",affairsLibraryMirrorRootLabel:"本地镜像路径",affairsLibraryMirrorRootPlaceholder:"/Users/you/SynologyDrive",affairsLibraryMirrorRootBrowseAction:"选择本地目录",affairsLibraryMirrorRootDesktopOnlyHint:"选择目录只在桌面应用里生效,H5 端请直接手动填写路径。",affairsLibraryIncludedHiddenPathsLabel:"额外纳入的隐藏路径",affairsLibraryIncludedHiddenPathsHint:"默认会忽略 . 开头的文件和文件夹。只有你明确需要时,才在这里逐条填相对路径,例如 .obsidian 或 notes/.draft.md。",affairsLibraryIncludedHiddenPathsPlaceholder:`.obsidian
@@ -47,4 +47,4 @@ Summary: {summary}
47
47
  Source: {sourceRef}
48
48
  Work around this object for document cleanup, tags, todos, browser tasks, and export suggestions.`,affairsAssistantPromptPreambleEmpty:"There is no selected affairs object yet. Help decide what to inspect first and suggest the next step.",affairsDocumentSummaryTemplate:"Placeholder document object derived from session {sessionTitle}. This will be replaced by the formal document index later.",affairsSidebarMenuLabel:"Affairs sections",affairsLibrarySidebarTitle:"Favorites and tags",affairsLibrarySidebarDescription:"This workspace currently shows {count} document objects, with {favorites} favorites and {tags} tags collected here.",affairsLibraryAllFilter:"All documents",affairsLibraryAllFilterSummary:"Browse every document object in this workspace.",affairsLibraryFavoritesSummary:"Start from the documents you already starred.",affairsLibraryFavoritesEntry:"All pinned",affairsLibraryTagSummary:"Filter the current document list by tag.",affairsLibraryFoldersEntry:"Folders",affairsLibraryFoldersSummary:"Browse the current library by folder.",affairsLibraryTagsEntry:"Tags",affairsLibraryTagsSummary:"Browse the current library by tag.",affairsLibraryFolderNodeSummary:"Filter the current document list by folder.",affairsLibraryTagNodeSummary:"Filter the current document list by tag.",affairsLibraryRefreshAction:"Refresh library",affairsLibraryRefreshQueued:"Library refresh started",affairsLibraryRefreshQueuedDescription:"The app is rescanning documents in the background and will update folders, tags, and list results.",affairsLibraryRefreshFailed:"Failed to refresh the library",affairsLibraryBindingTitle:"Bind a document library first",affairsLibraryBindingDescription:"Pick a root directory for this affairs view. The left sidebar, favorites, tags, and the middle document list will all come from it.",affairsLibraryBindingFieldLabel:"Library path",affairsLibraryBindingFieldPlaceholder:"/Users/you/Documents/Knowledge",affairsLibraryBindingSubmitAction:"Save path",affairsLibraryBindingBrowseAction:"Choose folder",affairsLibraryBindingPickerTitle:"Choose a document library folder",affairsLibraryBindingPickerDescription:"Pick a real directory as the library root. The affairs view will show folders, favorites, tags, and documents from it.",affairsLibraryBindingUseThisDirectory:"Use this folder",affairsLibraryEnableLabel:"Enable library",affairsLibraryEnableHint:"When disabled, the built-in indexer for this workspace stops running until you turn it back on.",affairsLibraryEnableAction:"Enable",affairsLibraryDisableAction:"Disable",affairsLibraryEnabledState:"Enabled",affairsLibraryDisabledState:"Disabled",affairsLibraryEnableSaveFailed:"Failed to update the library switch",affairsLibraryDisabledSummary:"The library is currently disabled. Turn it back on before the built-in indexer can resume.",affairsLibraryConfigTitle:"Library settings",affairsLibraryConfigDescription:"Set the local mirror path, allowed file types, and any hidden paths that really need to be included.",affairsLibraryMirrorRootLabel:"Local mirror path",affairsLibraryMirrorRootPlaceholder:"/Users/you/SynologyDrive",affairsLibraryMirrorRootBrowseAction:"Choose local folder",affairsLibraryMirrorRootDesktopOnlyHint:"Directory picker only works in the desktop app. On the web, enter the path manually.",affairsLibraryIncludedHiddenPathsLabel:"Extra hidden paths to include",affairsLibraryIncludedHiddenPathsHint:"Dot-prefixed files and folders are ignored by default. Add relative paths here only when you really want them indexed, for example .obsidian or notes/.draft.md.",affairsLibraryIncludedHiddenPathsPlaceholder:`.obsidian
49
49
  notes/.draft.md`,affairsLibraryAllowedExtensionsLabel:"Indexed file types",affairsLibraryAllowedExtensionsPlaceholder:".md, .pdf, .docx",affairsLibraryAllowedExtensionsHint:"Separate multiple suffixes with commas or spaces. This is only a whitelist. The indexer still decides what it can really parse.",affairsLibraryAllowedExtensionsCustomPlaceholder:"Add a custom suffix, for example .pages or .epub",affairsLibraryAllowedExtensionsCustomAddAction:"Add suffix",affairsLibraryAllowedExtensionsCustomInvalid:"Enter a valid suffix such as .pages.",affairsLibraryCustomExtensionBadge:"Custom",affairsLibrarySettingsAction:"Open library settings",affairsLibraryConfigSaveAction:"Save settings",affairsLibraryFolderOpenBehaviorLabel:"Folder open behavior",affairsLibraryFolderOpenBehaviorHint:"Folders open on double click by default. Switch to single click if you want faster navigation.",affairsLibraryFolderOpenBehaviorSwitchLabel:"Open folders on single click",affairsLibraryFolderOpenBehaviorSingle:"Open on single click",affairsLibraryFolderOpenBehaviorDouble:"Open on double click",affairsLibraryConfigSaveFailed:"Failed to save the library settings",affairsLibraryConfigSaved:"Library settings saved",affairsLibraryConfigAppliedSuccess:"The new mirror path and whitelist have been applied to the indexer.",affairsLibraryConfigAppliedRunning:"Settings saved. The indexer is applying the new configuration.",affairsLibraryConfigAppliedFailed:"Settings saved, but the indexer failed to apply the new configuration.",affairsLibraryOpenLocalFileAction:"Open local file",affairsLibraryOpenWithLocalAppAction:"Open with local application",affairsLibraryOpenLocalFileFailed:"Failed to open the local file",affairsLibraryRevealLocalFileAction:"Reveal in Finder",affairsLibraryRevealLocalFileFailed:"Failed to reveal the file in Finder",affairsLibraryLocateFolderAction:"Go to folder",affairsLibraryContextLocate:"Locate",affairsLibraryMirrorRootEmpty:"No local mirror path is configured yet",affairsLibraryContextMenuLabel:"Document library action menu",affairsLibraryContextPreview:"Preview",affairsLibraryContextOpen:"Open",affairsLibraryContextDownload:"Download",affairsLibraryContextNew:"New",affairsLibraryContextNewDirectory:"Folder",affairsLibraryContextNewMarkdown:"Markdown file",affairsLibraryContextNewText:"Text file",affairsLibraryContextNewCustomFile:"Custom file",affairsLibraryContextRefresh:"Refresh",affairsLibraryContextCopy:"Copy",affairsLibraryContextCopyFile:"File",affairsLibraryContextCopyFileName:"File name",affairsLibraryContextCopyAbsolutePath:"Absolute path",affairsLibraryContextCopyRelativePath:"Relative path",affairsLibraryContextCut:"Cut",affairsLibraryContextPaste:"Paste",affairsLibraryContextDelete:"Delete",affairsLibraryContextTags:"Tags",affairsLibraryContextProperties:"Properties",affairsLibraryRecentTagsEmpty:"No recent tags available",affairsLibraryActionFailed:"Document action failed",affairsLibraryDownloadSuccess:"Downloaded {name}",affairsLibraryDownloadFailed:"Download failed",affairsLibraryCopyFileSuccess:"File path copied",affairsLibraryCopyFileNameSuccess:"File name copied",affairsLibraryCopyAbsolutePathSuccess:"Absolute path copied",affairsLibraryCopyRelativePathSuccess:"Relative path copied",affairsLibraryCopyFailed:"Copy failed",affairsLibraryCutSuccess:"Cut {name}",affairsLibraryPasteSuccess:"Pasted {name}",affairsLibraryDeleteSuccess:"Deleted {name}",affairsLibraryDeleteConfirmTitle:"Confirm deletion",affairsLibraryDeleteConfirmDescription:"Deletion happens immediately and cannot be undone here.",affairsLibraryDeleteDocumentConfirm:'Are you sure you want to delete the file "{path}"?',affairsLibraryDeleteFolderConfirm:'Are you sure you want to delete the folder "{path}"? Everything inside it will be removed too.',affairsLibraryDeleteConfirmAction:"Delete",affairsLibraryDeleteSubmitting:"Deleting...",affairsLibraryCreateModalTitle:"Create item",affairsLibraryCreateModalDescription:"This will be created in {path}. Give it a clear name first.",affairsLibraryCreateNameLabel:"Name",affairsLibraryCreateNamePlaceholder:"Enter a name",affairsLibraryCreateTypeHint:"You are about to create: {type}",affairsLibraryCreateConfirmAction:"Create",affairsLibraryCreateFailed:"Failed to create the item",affairsLibraryCreateSuccess:"Created {name}",affairsLibraryCreateNameRequired:"Enter a name first",affairsLibraryCreateDirectoryDefaultName:"New Folder",affairsLibraryCreateMarkdownDefaultName:"Untitled.md",affairsLibraryCreateTextDefaultName:"Untitled.txt",affairsLibraryCreateCustomDefaultName:"Untitled file",affairsLibraryCreateMarkdownHeading:"Untitled",affairsLibraryAbsolutePathMissing:"This library item has no local path to open",affairsLibraryUntitledFileName:"Untitled file",affairsFavoriteAddAction:"Add to favorites",affairsFavoriteRemoveAction:"Remove from favorites",affairsFavoriteAdded:"Added to favorites",affairsFavoriteRemoved:"Removed from favorites",affairsFavoriteContextMenuLabel:"Favorite actions",affairsFavoriteMoveUpAction:"Move up",affairsFavoriteMoveDownAction:"Move down",affairsTagFilterFavoriteAction:"Favorite current tag filter",affairsTagFilterFavoriteModalTitle:"Favorite tag filter",affairsTagFilterFavoriteModalDescription:"{count} tags are selected. Save this view so you can reopen it from favorites.",affairsTagFilterFavoriteSelectedCount:"{count} tags selected",affairsTagFilterFavoriteNameLabel:"Favorite name",affairsTagFilterFavoriteNamePlaceholder:"Name this filter",affairsTagFilterFavoriteSingleNameHint:"A single tag uses the tag name by default.",affairsTagFilterFavoriteMultiNameHint:"Multiple tags need a clear name so this favorite is readable later.",affairsTagFilterFavoriteNameRequired:"Enter a favorite name first",affairsTagFilterFavoriteConfirmAction:"Save favorite",affairsTagFilterFavoriteSaving:"Saving...",affairsLibraryBrowseModeLabel:"Library browse mode",affairsLibraryBrowseModeFolder:"Folders",affairsLibraryBrowseModeTag:"Tags",affairsLibrarySortLabel:"Sort order",affairsLibrarySortRecent:"Recent",affairsLibrarySortName:"Name",affairsLibrarySortType:"Type",affairsLibrarySortSize:"Size",affairsLibrarySortCreatedAt:"Date Added",affairsLibraryViewModeLabel:"Library view mode",affairsLibraryViewModeGrid:"Grid",affairsLibraryViewModeList:"List",affairsLibraryTagResultStructureLabel:"Tag result view",affairsLibraryTagResultFileMode:"Files",affairsLibraryTagResultDirectoryMode:"Folders",affairsLibraryTagDirectoryFileCount:"{count} files",affairsLibraryTagTreeTitle:"Tag Tree",affairsLibraryTagTreeShowMore:"Show More Tags",affairsLibraryTagTreeShowLess:"Show Fewer Tags",affairsLibraryTagTreeReset:"Reset Filters",affairsLibraryTagSearchAction:"Find tag",affairsLibraryTagSearchInputLabel:"Find tag",affairsLibraryTagSearchPlaceholder:"Enter keyword or pinyin",affairsLibraryTagSearchResultsLabel:"Tag search results",affairsLibraryTagSearchEmpty:"No matching tags",affairsDocumentTagsSectionTitle:"Document tags",affairsFolderTagsSectionTitle:"Folder tags",affairsDocumentTagSourcesTitle:"Tag sources",affairsDocumentTagSourcesEmpty:"This file has no explainable tag source yet.",affairsTagSourceManualDocument:"Manual",affairsTagSourceFolderBinding:"Folder",affairsTagSourceRuleMatch:"Smart match",affairsTagSourceSystemDerived:"System",affairsTagDetailsLoading:"Loading tag details…",affairsDocumentTagAddLabel:"Add document tag",affairsDocumentTagSearchPlaceholder:"Type a tag name or path",affairsDocumentTagSuggestionsLabel:"Document tags you can add",affairsDocumentTagNoMatch:"No matching tag can be added",affairsDocumentTagsEmpty:"No manual tags yet.",affairsDocumentTagRemoveAction:"Remove tag {tag}",affairsFolderTagAddLabel:"Add folder tag",affairsFolderTagSuggestionsLabel:"Tags you can assign to this folder",affairsFolderTagsEmpty:"This folder has no manual tags yet.",affairsTagQuickSearchPlaceholder:"Type a tag name or path, then press Enter to assign",affairsTagQuickCreateAction:"Create and assign “{tag}”",affairsTagQuickCreateHint:"If this tag does not exist yet, it will be created immediately.",affairsTagQuickAlreadyAssigned:"This tag is already assigned.",affairsTagQuickAssignSubmitting:"Adding tag…",affairsTagQuickCreateSubmitting:"Creating and adding tag…",affairsTagQuickRemoveSubmitting:"Removing tag…",affairsTagQuickAssignModalTitle:"Assign tags",affairsTagQuickAssignDocumentDescription:"Assign tags to “{name}”. Existing tags match immediately. Missing tags are created on the spot.",affairsTagQuickAssignFolderDescription:"Assign tags to “{name}”. The tag will apply to this folder and future files added under it.",affairsTagRecommendationsLabel:"Recommended tags",affairsTagRecommendationsAction:"Tag recommendations",affairsTagRecommendationsCount:"{count} recommended tags",affairsTagRecommendationsEmpty:"No tag recommendation now",affairsTagRecommendationAssignAction:"Assign recommended tag “{tag}”",affairsTagRecommendationReasonName:"Name match",affairsTagRecommendationReasonFolder:"Folder related",affairsTagRecommendationReasonRule:"Smart rule",affairsTagRecommendationReasonTime:"Recent use",affairsFolderTagTaskShortTitle:"{operation} tags",affairsFolderTagTaskTitle:"{operation} tag progress",affairsFolderTagTaskButtonLabel:"{operation} tags for {folder}: {status}, {percent}% complete",affairsFolderTagTaskFolderLabel:"Current folder",affairsFolderTagTaskPhaseLabel:"Current stage",affairsFolderTagTaskProgressLabel:"Processed documents",affairsFolderTagTaskProgressCount:"{current} / {total}",affairsFolderTagTaskPreparing:"Preparing",affairsFolderTagTaskSubmitting:"Submitting {operation} tag request",affairsFolderTagTaskSubmittingDetail:"The request has been sent. Waiting for the task to start.",affairsFolderTagTaskOperationAttach:"Add",affairsFolderTagTaskOperationRemove:"Remove",affairsFolderTagTaskOperationUpdate:"Update",affairsFolderTagTaskStatusQueued:"Queued",affairsFolderTagTaskStatusRunning:"Running",affairsFolderTagTaskStatusSucceeded:"Completed",affairsFolderTagTaskStatusFailed:"Failed",affairsFolderTagTaskStatusCancelled:"Cancelled",affairsFolderTagTaskStatusTimeout:"Timed out",affairsFolderTagTaskPhasePrepare:"Preparing task",affairsFolderTagTaskPhaseRecompute:"Applying tags",affairsFolderTagTaskPhaseWrite:"Writing results",affairsFolderTagTaskPhaseExport:"Refreshing results",affairsFolderTagTaskPhaseFinished:"Finished",affairsTagTaskHistoryTitle:"Recent tag tasks",affairsTagTaskHistoryShortTitle:"Tag tasks",affairsTagTaskHistoryButtonLabel:"Recent {count} tag tasks. Current: {operation} tags for {target}: {status}, {percent}% complete",affairsTagTaskHistoryCount:"Recent {count}",affairsTagTaskHistoryRunningCount:"{count} active",affairsTagTaskDocumentLabel:"Current document",affairsTagManagerAction:"Manage tags",affairsTagManagerTitle:"Tag management",affairsTagManagerDescription:"Use this panel to organize the tag tree. Pick a tag on the left, edit it on the right, and add rules for tags that should match automatically.",affairsTagManagerSectionTitle:"Tag tree and rules",affairsTagManagerSectionDescription:"Pick a tag on the left, then create, edit, or delete it on the right.",affairsTagBatchSectionTitle:"Bulk edit and bulk delete",affairsTagBatchSectionDescription:"Select the tags you want to handle together, then move, enable, disable, or delete them in one pass.",affairsTagBatchEmpty:"No tags selected yet",affairsTagBatchEmptyDescription:"Check two or more tags on the left to manage them together here.",affairsTagBatchSelectionSummary:"{count} tags selected",affairsTagBatchCheckboxLabel:"Select tag {tag}",affairsTagBatchSelectAllAction:"Select all",affairsTagBatchClearSelectionAction:"Clear selection",affairsTagBatchParentLabel:"Move all to parent tag",affairsTagBatchParentKeepOption:"Keep current parents",affairsTagBatchStatusLabel:"Unified status",affairsTagBatchStatusKeepOption:"Keep current status",affairsTagBatchStatusActiveOption:"Enable all",affairsTagBatchStatusDisabledOption:"Disable all",affairsTagBatchUpdateAction:"Save bulk changes",affairsTagBatchDeleteAction:"Delete selected",affairsTagBatchHint:"Bulk edits move all selected tags under the same parent and unify their status. Their original parent-child structure is not preserved automatically.",affairsTagRecoverySectionTitle:"Rewrite document tag results",affairsTagRecoverySectionDescription:"Only rerun this when document tag results have not caught up with the latest tag tree, folder tags, or smart rules.",affairsTagRecoveryStatusLabel:"Current status",affairsTagRecoveryStatusIdle:"Not started",affairsTagRecoveryPhaseIdle:"Waiting to start",affairsTagRecoveryProgressIdle:"Nothing has been processed yet",affairsTagRecoveryAction:"Recover document tag results",affairsTagRecoveryRunningAction:"Recovering document tag results…",affairsTagRecoveryHint:"This reruns manual tags, folder tags, smart tags, and system tags to write tag results back to documents.",affairsTagRecoveryRunningHint:"The recovery task is running. Document tag links will recover automatically when it finishes.",affairsTagRecoveryStartedDescription:"The recovery task has started. Document tag results will recover as it finishes.",affairsTagRecoveryQueuedDescription:"A recovery task is already queued or running. Wait for that one to finish.",affairsTagRecoveryFailed:"Failed to start document tag recovery. Please try again later.",affairsTagRecoveryIdentityBindingLabel:"Identity bindings",affairsTagRecoveryLegacyBindingLabel:"Legacy path data",affairsTagRecoveryLegacyFallbackLabel:"Still on compatibility layer",affairsTagRecoveryCompatibilityHint:"The primary path now reads identity bindings first. There are still {count} legacy path bindings left only in the compatibility layer across {documents} documents, and they will be phased out gradually.",affairsTagRecoveryCleanHint:"There is no compatibility-only legacy data right now. Rerun this only when document tag results look wrong.",affairsTagRecoveryPendingHint:"{documents} documents are still using compatibility-only legacy data. Use the button below when you want to rewrite all document tag results together.",affairsTagBatchUpdateNoop:"Choose at least one batch change first. Otherwise nothing will change.",affairsTagBatchUpdateSuccess:"Bulk update completed",affairsTagBatchUpdateSuccessDescription:"Updated {count} tags.",affairsTagBatchUpdateFailed:"Bulk update failed",affairsTagBatchDeleteConfirm:"Delete these {count} tags? If a parent tag is included, its child tags will be removed too.",affairsTagBatchDeleteSuccess:"Bulk delete completed",affairsTagBatchDeleteSuccessDescription:"Deleted {count} tags.",affairsTagBatchDeleteFailed:"Bulk delete failed",affairsTagCreateAction:"New tag",affairsTagTreeSectionTitle:"Tag tree",affairsTagTreeSectionDescription:"Only manually managed business tags are shown here.",affairsTagTreeEmpty:"No business tags yet",affairsTagTreeEmptyDescription:"Start with one root tag, then split it into child tags later.",affairsTagTreeDocumentCount:"{count} documents",affairsTagCreateRootAction:"New root tag",affairsTagCreateChildAction:"New child tag",affairsTagEditorCreateRootTitle:"Create root tag",affairsTagEditorCreateRootDescription:"Create the top-level category first, then refine it layer by layer.",affairsTagEditorCreateChildTitle:"Create child tag",affairsTagEditorCreateChildDescription:"This new tag will be created under “{tag}”.",affairsTagEditorEditTitle:"Edit tag",affairsTagEditorEditDescription:"Update the current tag's name and place in the tree here. The document count also lives here, and smart rules are edited in the next section.",affairsTagEditorPathLabel:"Tag path",affairsTagEditorDocumentCountLabel:"Matched documents",affairsTagSmartRulesSectionTitle:"Smart tag rules",affairsTagSmartRulesSectionDescription:"Rules live on the current tag. When a file matches them, the tag is assigned automatically.",affairsTagSmartRulesEmpty:"No smart rules yet",affairsTagSmartRulesEmptyDescription:"Add rules here if this tag should be assigned automatically.",affairsTagSmartRuleAddAction:"Add rule",affairsTagSmartRuleRelationLabel:"Relation",affairsTagSmartRuleRelationAnd:"AND",affairsTagSmartRuleRelationOr:"OR",affairsTagSmartRuleRelationNot:"NOT",affairsTagSmartRuleTypeLabel:"Rule type",affairsTagSmartRuleTypeFileNameContains:"File name contains text",affairsTagSmartRuleTypeFileContentContains:"File content contains text",affairsTagSmartRuleTypeFileExtensionIn:"File type matches",affairsTagSmartRuleTypeModifiedTimeBetween:"Modified time range",affairsTagSmartRuleTypeDocumentPathInFolder:"Inside a folder and its subfolders",affairsTagSmartRuleKeywordLabel:"Keyword",affairsTagSmartRuleKeywordPlaceholder:"For example: contract, quote, payment",affairsTagSmartRuleExtensionsLabel:"File types",affairsTagSmartRuleExtensionsPlaceholder:"For example: pdf, docx, xlsx",affairsTagSmartRuleModifiedStartLabel:"Start time",affairsTagSmartRuleModifiedEndLabel:"End time",affairsTagSmartRuleFolderPathLabel:"Folder path",affairsTagSmartRuleFolderPathPlaceholder:"For example: presales/proposals, or . for root",affairsTagSmartRuleEnabledLabel:"Enable this rule",affairsTagSmartRuleRemoveAction:"Remove rule",affairsTagSmartRuleOrderHint:"Rule {index}",affairsTagNameLabel:"Tag name",affairsTagNamePlaceholder:"For example: Customer contracts",affairsTagParentLabel:"Parent tag",affairsTagParentRootOption:"Place at the tag tree root",affairsTagSaveAction:"Save tag",affairsTagSaveFailed:"Failed to save the tag",affairsTagSaveSuccess:"Tag saved",affairsTagSaveSuccessDescription:"The tag tree was updated.",affairsTagCreateSubmitAction:"Create tag",affairsTagUpdateSubmitAction:"Save changes",affairsTagResetFormAction:"Reset form",affairsTagRevertAction:"Revert",affairsTagCloseAction:"Close",affairsTagDangerZoneTitle:"Delete tag",affairsTagDangerZoneDescription:"Deleting this tag will also remove all of its child tags.",affairsTagDeleteAction:"Delete this tag",affairsTagDeleteConfirm:"Delete “{tag}”? All child tags under it will also be removed.",affairsTagDeleteFailed:"Failed to delete the tag",affairsTagDeleteSuccess:"Tag deleted",affairsTagDeleteSuccessDescription:"The tag tree was updated and document tag results will refresh.",affairsFinderColumnName:"Name",affairsFinderColumnSize:"Size",affairsFinderColumnUpdatedAt:"Date Modified",affairsFinderColumnType:"Kind",affairsFinderColumnCreatedAt:"Date Added",affairsFinderSortAction:"Sort by {column}",affairsFinderSortCurrent:"{column}, currently sorted {direction}",affairsFinderSortDirectionAsc:"ascending",affairsFinderSortDirectionDesc:"descending",affairsFinderResizeColumn:"Resize {column} column",affairsFinderDateToday:"Today",affairsFinderDateYesterday:"Yesterday",affairsFinderKindFolder:"Folder",affairsFinderKindFile:"File",affairsFinderKindMarkdown:"Markdown document",affairsFinderKindText:"Text document",affairsFinderKindHtml:"HTML document",affairsFinderKindJson:"JSON data",affairsFinderKindXml:"XML document",affairsFinderKindYaml:"YAML config",affairsFinderKindImage:"Image",affairsFinderKindPdf:"PDF document",affairsFinderKindWord:"Word document",affairsFinderKindExcel:"Excel spreadsheet",affairsFinderKindPowerPoint:"PowerPoint presentation",affairsFinderKindArchive:"Archive",affairsFinderKindCode:"Code file",affairsFinderKindSql:"SQL script",affairsFinderKindDatabase:"Database file",affairsFinderKindAudio:"Audio file",affairsFinderKindVideo:"Video file",affairsFinderKindDesign:"Design file",affairsFinderKindFont:"Font file",affairsFinderKindEbook:"E-book",affairsFinderKindData:"Data file",affairsLibraryTagMultiTitle:"Combined Filters",affairsLibraryTagMultiRootType:"Multiple tags",affairsLibraryBindingSaveFailed:"Failed to save the document library path",affairsLibraryStatusIdle:"Not ready",affairsLibraryStatusFresh:"Ready",affairsLibraryStatusStale:"Needs refresh",affairsLibraryStatusQueued:"Queued",affairsLibraryStatusRunning:"Refreshing",affairsLibraryStatusQueueTimeout:"Queue timeout",affairsLibraryStatusCooldown:"Just refreshed",affairsLibraryStatusFailed:"Refresh failed",affairsLibraryStatusIndicatorAction:"Document library index status: {status}",affairsLibraryStatusIndicatorProgress:"Scanned {scanned}",affairsLibraryStatusPopoverTitle:"Document library indexer status",affairsLibraryStatusSummaryTotalLabel:"Indexed total",affairsLibraryStatusSummaryScannedLabel:"Current count",affairsLibraryStatusSummaryUpdatedLabel:"Updated",affairsLibraryStatusSummaryIssueLabel:"Issues",affairsLibraryStatusPrimaryTitle:"Current overview",affairsLibraryStatusTechnicalToggle:"Technical details",affairsLibraryStatusSectionOverviewTitle:"Run details",affairsLibraryStatusSectionTimelineTitle:"Timeline",affairsLibraryStatusSectionProgressTitle:"Scan details",affairsLibraryStatusSectionDirectoryTitle:"Directory result",affairsLibraryStatusSectionWorkerTitle:"Background worker",affairsLibraryStatusCurrentLabel:"Current status",affairsLibraryStatusLastRequestedAtLabel:"Last requested",affairsLibraryStatusLastStartedAtLabel:"Last started",affairsLibraryStatusLastCompletedAtLabel:"Last completed",affairsLibraryStatusLastFailedAtLabel:"Last failed",affairsLibraryStatusNextAllowedAtLabel:"Next allowed refresh",affairsLibraryStatusRunningTaskIdLabel:"Running task",affairsLibraryStatusRunningStageLabel:"Current stage",affairsLibraryStatusProgressScannedLabel:"Files scanned",affairsLibraryStatusProgressIndexedLabel:"Updated this run",affairsLibraryStatusProgressUnchangedLabel:"Unchanged skipped",affairsLibraryStatusProgressSkippedLabel:"Parser skipped",affairsLibraryStatusProgressFailedLabel:"Failed",affairsLibraryStatusProgressTotalLabel:"Estimated total",affairsLibraryStatusDirtyReasonsLabel:"Pending reasons",affairsLibraryStatusErrorSummaryLabel:"Failure summary",affairsLibraryStatusStageQueued:"Queued",affairsLibraryStatusStageInit:"Preparing index environment",affairsLibraryStatusStageApplyConfig:"Applying config",affairsLibraryStatusStageIndex:"Updating index",affairsLibraryStatusStageIncrementalIndex:"Incremental index",affairsLibraryStatusStageRecomputeTags:"Recomputing tags",affairsLibraryStatusStageExport:"Exporting results",affairsLibraryStatusStageExportMetaDetail:"Exporting folders and documents",affairsLibraryStatusStageExportTag:"Exporting tag results",affairsLibraryStatusStageExportRelation:"Exporting document relations",affairsLibraryStatusStageExportSearch:"Building search index",affairsLibraryStatusStageSqlite:"Writing SQLite metadata",affairsLibraryDirectoryStatusPathLabel:"Current directory",affairsLibraryDirectoryStatusRootPath:"Root directory",affairsLibraryDirectoryStatusStateLabel:"Directory refresh status",affairsLibraryDirectoryStatusSourceLabel:"Directory result source",affairsLibraryDirectoryStatusLastRequestedAtLabel:"Directory last requested",affairsLibraryDirectoryStatusLastCompletedAtLabel:"Directory last completed",affairsLibraryDirectoryStatusLastFailedAtLabel:"Directory last failed",affairsLibraryDirectoryStatusRunningTaskIdLabel:"Directory task",affairsLibraryDirectoryStatusErrorSummaryLabel:"Directory failure summary",affairsLibraryDirectoryStatusGeneratedAtLabel:"Result generated",affairsLibraryDirectoryStatusFilesystemObservedAtLabel:"Filesystem observed",affairsLibraryDirectoryStatusStaleReasonLabel:"Fallback reason",affairsLibraryDirectoryStatusIdle:"Idle",affairsLibraryDirectoryStatusQueued:"Queued",affairsLibraryDirectoryStatusRunning:"Refreshing",affairsLibraryDirectoryStatusQueueTimeout:"Queue timeout",affairsLibraryDirectoryStatusFresh:"Updated",affairsLibraryDirectoryStatusFailed:"Refresh failed",affairsLibraryDirectoryStatusSourceLive:"Live directory",affairsLibraryDirectoryStatusSourceSnapshot:"Export snapshot",affairsLibraryDirectoryStatusSourceMixed:"Live + snapshot",affairsLibraryDirectoryStatusSourceStaleFallback:"Stale fallback",affairsLibraryWorkerHealthStateLabel:"Worker state",affairsLibraryWorkerHealthPidLabel:"Worker PID",affairsLibraryWorkerHealthLocalInflightLabel:"Local inflight",affairsLibraryWorkerHealthRemoteInflightLabel:"Remote inflight",affairsLibraryWorkerHealthStartedAtLabel:"Worker started",affairsLibraryWorkerHealthHeartbeatLabel:"Last heartbeat",affairsLibraryWorkerHealthLastStartedAtLabel:"Last task started",affairsLibraryWorkerHealthLastCompletedAtLabel:"Last task completed",affairsLibraryWorkerHealthLastFailedAtLabel:"Last task failed",affairsLibraryWorkerHealthSoftCancelAtLabel:"Last soft cancel",affairsLibraryWorkerHealthHardKillAtLabel:"Last hard kill",affairsLibraryWorkerHealthLastExitAtLabel:"Last exit",affairsLibraryWorkerHealthTerminationReasonLabel:"Last termination reason",affairsLibraryWorkerHealthStateIdle:"Idle",affairsLibraryWorkerHealthStateRunning:"Running",affairsLibraryWorkerHealthStateTerminating:"Terminating",affairsLibraryWorkerHealthStateRecycled:"Recycled",affairsLibraryEmptyRunning:"The document library is refreshing. Check back in a moment.",affairsAssistantWaitingDocument:"The library is bound, but there is no selectable document yet. Refresh it or choose another directory.",affairsSidebarGroupOverview:"Overview",affairsSidebarGroupTags:"Tags",affairsFavoriteBadge:"Pinned",affairsLibraryStageDescription:"The document list is currently driven by {count} favorite/tag entries.",affairsTodoSidebarTitle:"Todo sources",affairsTodoSidebarDescription:"This area merges manual todos, inbox items, and follow-up tasks. {count} items in total.",affairsTodoAllFilter:"All todos",affairsTodoAllFilterSummary:"See every unfinished item in the current workspace together.",affairsTodoInboxFilter:"Inbox items",affairsTodoInboxSummary:"Items from the assistant inbox that still need to be processed.",affairsTodoFollowUpFilter:"Session follow-up",affairsTodoFollowUpSummary:"Unfinished follow-up tasks recognized from coding sessions.",affairsTodoSidebarGroupSources:"Source groups",affairsTodoStageTitle:"Todo list",affairsTodoStageDescription:"The main list is currently driven by {count} todo sources.",affairsTodoEmpty:"There are no pending todos or follow-up tasks right now.",affairsTodoStatusPending:"Pending",affairsTodoStatusInProgress:"In progress",affairsTodoStatusClosed:"Closed",affairsTodoStatusWaitingUser:"Waiting for you",affairsTodoStatusCompleted:"Completed",affairsTodoStatusFailed:"Failed",affairsTodoStatusCancelled:"Cancelled",affairsTodoStatusActive:"Active",affairsTodoDetailStatus:"Status",affairsTodoDetailSource:"Source session",affairsTodoDetailNotes:"Notes",affairsTodoDetailTotal:"Current result",affairsTodoDetailTotalValue:"{count} items",affairsAutomationSidebarTitle:"Automation tasks",affairsAutomationSidebarDescription:"This area directly reuses assistant automation tasks. {count} items total.",affairsAutomationStageTitle:"Automation tasks",affairsAutomationStageDescription:"There are currently {count} automation tasks available here.",affairsAutomationEmpty:"There are no automation tasks to show right now.",affairsAutomationUntitled:"Untitled automation",affairsAutomationPromptFallback:"This automation does not have a readable summary yet.",affairsAutomationStatusActive:"Running",affairsAutomationStatusPaused:"Paused",affairsAutomationStatusCompleted:"Completed",affairsAutomationStatusCancelled:"Cancelled",affairsAutomationStatusFailed:"Failed",affairsAutomationTriggerOnce:"Run once",affairsAutomationTriggerInterval:"Interval",affairsAutomationTriggerCron:"Schedule",affairsAutomationTriggerCondition:"Condition",affairsAutomationTargetFallback:"No target session is bound yet",affairsAutomationDetailTrigger:"Trigger",affairsAutomationDetailTarget:"Target session",affairsAutomationDetailStatus:"Status",affairsAutomationRunsTitle:"Recent runs",affairsAutomationRunsDescription:"Review how this automation has been running recently.",affairsAutomationRunsEmpty:"There are no recent runs yet.",affairsAutomationRunsFallback:"This run did not produce a readable summary.",affairsAutomationLastRunSummary:"Last run: {summary}",affairsAutomationSidebarGroupTasks:"Task list",affairsAutomationRunsStatusQueued:"Queued",affairsAutomationRunsStatusRunning:"Running",affairsAutomationRunsStatusFinished:"Finished",affairsAutomationRunsStatusFailed:"Failed",affairsAutomationRunsStatusCancelled:"Cancelled",affairsAutomationRunsStatusSkipped:"Skipped",affairsAuxiliaryTabsLabel:"Affairs auxiliary tabs",affairsDetailMetaPath:"Document path",affairsDetailMetaTags:"Tags",butlerInitTitle:"Initialize Assistant",butlerInitDescription:"Set the Butler name, provider, and work style first. The dedicated workspace and first AGENTS.md will be created automatically.",butlerInitPreviewTitle:"Live Preview",butlerInitPreviewDescription:"These choices directly shape the first rule set, so show the result instead of dumping a plain form.",butlerInitBasicsTitle:"Basics",butlerInitBasicsDescription:"Lock in the name, provider, and rule storage first so initialization does not become config soup.",butlerInitPersonaTitle:"Expression Style",butlerInitPersonaDescription:"Tone, language, and summary style decide how Butler speaks, not whether it gets to be sloppy.",butlerInitPreferenceTitle:"Default Priorities",butlerInitPreferenceDescription:"This decides which risks Butler watches first and what it surfaces first in reports.",butlerInitRuleLabel:"Rule Format",butlerInitTipAutoWorkspace:"The system creates the Butler workspace and first AGENTS.md automatically, so you only set the defaults here.",butlerInitTipProviderSwitch:"You can switch provider later, so do not overthink the first initialization pass.",butlerInitTipReportPriority:"Report priority changes whether Butler leads with risk, blockers, or verification results.",butlerDisplayNameLabel:"Butler Name",butlerDisplayNamePlaceholder:"Example: Arvin, Butler",butlerDisplayNameHint:"This is the Butler's self-name. The system writes it into the first generated AGENTS.md.",butlerProviderLabel:"Provider",butlerWorkspacePathLabel:"Butler Workspace Path",butlerWorkspacePathPlaceholder:"Example: /Users/you/WorkFile/butler-home",butlerAgentsModeLabel:"AGENTS Mode",butlerAgentsModeInline:"Inline",butlerAgentsModeFile:"File",butlerAgentsModeInlineDescription:"Inline: the system generates rules from your initialization choices and manages them for you.",butlerAgentsModeFileDescription:"File: the system writes AGENTS.md into the Butler workspace so you can edit the file directly later.",butlerAgentsFilePathLabel:"AGENTS.md File Path",butlerAgentsFilePathPlaceholder:"Example: /Users/you/WorkFile/butler-home/AGENTS.md",butlerAgentsContentLabel:"AGENTS Instructions",butlerAgentsContentPlaceholder:"Describe the Butler's work rules and response style",butlerAgentsContentHint:"Maintain Butler's formal rules here. Saving will write back to the dedicated AGENTS.md or inline instructions.",butlerPersonaToneLabel:"Tone",butlerPersonaLanguageLabel:"Language",butlerPersonaSummaryStyleLabel:"Summary Style",butlerFocusRiskPreferenceLabel:"Risk Preference",butlerFocusReportPriorityLabel:"Report Priorities (comma-separated)",butlerFocusReportPriorityPlaceholder:"Example: risk,blocker,verification",butlerToneDirect:"Direct and Clear",butlerToneSteady:"Steady and Controlled",butlerToneFriendly:"Friendly and Patient",butlerLanguageZhCn:"Chinese First",butlerLanguageEnUs:"English First",butlerLanguageBilingual:"Bilingual",butlerSummaryBrief:"Brief",butlerSummaryStructured:"Structured",butlerSummaryThorough:"Thorough",butlerRiskConservative:"Conservative",butlerRiskBalanced:"Balanced",butlerRiskProactive:"Proactive",butlerReportPriorityPresetLabel:"Report Priority",butlerReportRiskFirst:"Risk First",butlerReportBlockerFirst:"Blockers First",butlerReportVerificationFirst:"Verification First",butlerReportProgressFirst:"Progress First",butlerSummaryDebounceLabel:"Session Summary Debounce",butlerSummaryDebounceOption1Minute:"1 minute",butlerSummaryDebounceOption3Minutes:"3 minutes",butlerSummaryDebounceOption5Minutes:"5 minutes (default)",butlerSummaryDebounceOption10Minutes:"10 minutes",butlerSummaryDebounceOption15Minutes:"15 minutes",butlerSummaryDebounceOption30Minutes:"30 minutes",butlerSettingsTitle:"Butler Settings",butlerSettingsSaveAction:"Save Settings",butlerSettingsSaving:"Saving...",butlerSettingsSaved:"Butler settings saved",butlerSettingsSaveFailed:"Failed to save Butler settings",butlerInitSubmitting:"Initializing...",butlerInitSubmit:"Initialize Butler",butlerInitSuccess:"Assistant initialized",butlerInitFailed:"Failed to initialize Assistant",butlerInitNameRequired:"Assistant name is required",butlerInitWorkspaceRequired:"Assistant workspace path is required",butlerInitAgentsFileRequired:"AGENTS.md path is required in file mode",butlerWorkbenchTitle:"Assistant Workbench",butlerWorkbenchSubtitle:"Chat with Butler here and review aggregated context with action events.",butlerWorkspaceHint:"Butler workspace: {workspacePath}",butlerDisplayNameActiveHint:"Current Butler name: {displayName}",butlerNewSessionAction:"New Session",butlerNewSessionStarted:"Started a fresh Butler session",butlerNewSessionFailed:"Failed to start a fresh Butler session",butlerRefreshAction:"Refresh",butlerHistoryAction:"Recent Sessions",butlerHistoryTitle:"Recent Sessions",butlerHistoryDescription:"All assistant sessions are kept here, including todo analysis runs and regular chats.",butlerHistoryEmpty:"There is no assistant history yet.",butlerHistorySearchLabel:"Search sessions",butlerHistorySearchPlaceholder:"Search by title or preview",butlerHistorySearchEmpty:"No matching sessions found.",butlerHistoryActiveSection:"Active",butlerHistoryInactiveSection:"Earlier",butlerHistoryOpenAction:"Open Session",butlerHistoryDeleteAction:"Delete Session",butlerCurrentSessionBadge:"Current",butlerControlSessionKindChat:"Chat",butlerControlSessionKindTodoAnalysis:"Todo Analysis",butlerLoadingTitle:"Loading Butler",butlerLoadingDescription:"Pulling the current assistant session, summaries, and control state. Please wait a moment.",butlerSidebarInfoTab:"Info",butlerSidebarAutomationTab:"Automation",butlerSidebarSettingsTab:"Settings",butlerSidebarTabsLabel:"Butler sidebar tabs",butlerSidebarLoadFailed:"Failed to load Butler sidebar",butlerInfoContextTitle:"Current Context",butlerInfoContextDescription:"Show only what the Butler is using in this round, without flooding the panel with unrelated details.",butlerInfoCurrentScopeLabel:"Current Scope",butlerInfoCurrentScopeProject:"Project: {projectName}",butlerInfoCurrentScopeGlobal:"Global Overview",butlerInfoManagedProjectsLabel:"Tracked Projects",butlerInfoManagedProjectsValue:"Active {activeCount} / Total {totalCount}",butlerInfoCurrentContextProjectHint:"{projectName} is selected, so follow-up lookups will stay centered on this project first.",butlerInfoCurrentContextGlobalHint:"The Butler is still in global view. It only drills down when you pick a project or ask for details.",butlerInfoProjectSelectedAction:"Currently Selected",butlerInfoProjectViewAction:"View Project",butlerInfoProjectBlockedBadge:"Blocked",butlerInfoProjectRiskBadge:"Risk: {riskLevel}",butlerInfoProjectRiskShortBadge:"Risk {riskLevel}",butlerInfoProjectLastActivityBadge:"Active: {updatedAt}",butlerInfoLatestSessionAction:"Open Latest Session",butlerInfoProgressTitle:"Current Progress",butlerInfoAttentionTitle:"Watch For",butlerInfoNextStepTitle:"Next Step",butlerInfoFollowUpRecordsTitle:"Follow-up Records",butlerInfoFollowUpRecordsDescription:"Only the latest 5 follow-up states are shown here; open the full history for more.",butlerInfoFollowUpRecordsEmpty:"No follow-up records yet.",butlerInfoFollowUpUntitled:"Untitled Session",butlerInfoFollowUpFallback:"Last updated: {updatedAt}",butlerFollowUpHistoryAction:"View History",butlerFollowUpHistoryTitle:"Follow-up History",butlerFollowUpHistoryDescription:"Review the complete follow-up status history and continue drilling into round details.",butlerInfoVerificationRecordsTitle:"Verification Records",butlerInfoVerificationRecordsDescription:"A global view of feature verification records.",butlerInfoVerificationRecordsEmpty:"No verification records yet.",butlerInfoVerificationFallback:"Current status: {status}",butlerVerificationHistoryTitle:"Verification History",butlerVerificationHistoryDescription:"Only non-active verification records are collected here. Active verifications stay in the main info list.",butlerVerificationHistoryEmpty:"There are no historical verification records yet.",butlerInfoTodoRecordsTitle:"Todo Progress",butlerInfoTodoRecordsDescription:"A global view of current todo progress.",butlerInfoTodoRecordsEmpty:"No todo progress records yet.",butlerInfoShowCompletedAction:"Show completed",butlerInfoTodoItemTitle:"Todo {index}",butlerInfoTodoPending:"Pending",butlerInfoTodoInProgress:"In Progress",butlerInfoTodoClosed:"Closed",butlerTodoLifecyclePending:"Pending analysis",butlerTodoLifecycleAnalyzing:"Analyzing",butlerTodoLifecycleAnalyzed:"Prompt ready",butlerTodoLifecycleSessionCreated:"Session created",butlerTodoLifecycleFollowUpActive:"Assistant working",butlerTodoLifecycleCompleted:"Completed",butlerTodoLifecycleFailed:"Failed",butlerTodoLifecycleEmpty:"No analysis summary has been generated for this todo yet.",butlerTodoPromptPreviewAction:"View prompt",butlerTodoAnalyzeAction:"Analyze repo",butlerTodoReanalyzeAction:"Analyze again",butlerTodoAnalyzeRunning:"Analyzing...",butlerTodoAnalyzeQueued:"Queued for background analysis",butlerTodoAnalyzeSucceeded:"Development prompt generated",butlerTodoAnalyzeFailed:"Failed to analyze the todo repository context",butlerTodoAnalyzeFirstAction:"Analyze first",butlerTodoWaitForPromptAction:"Waiting for prompt",butlerTodoStartSessionAction:"Create session",butlerTodoStartSessionRunning:"Creating...",butlerTodoCopyPromptAction:"Copy prompt",butlerTodoOpenSessionAction:"Open session",butlerTodoCopyPromptSucceeded:"Prompt copied",butlerTodoStartSessionSucceeded:"Created a development session for the todo",butlerTodoStartSessionFailed:"Failed to create a development session for the todo",butlerAutomationTasksTitle:"Automation Tasks",butlerAutomationTasksDescription:"Only automation tasks live here: what exists, what state it is in, and when it runs next.",butlerAutomationTasksEmpty:"No automation tasks yet.",butlerAutomationMobileOverviewDescription:"The main list only keeps the signals worth scanning. Open a card to view and edit the full configuration.",butlerAutomationRunsTitle:"Recent Automation Runs",butlerAutomationRunsDescription:"This view only shows recent automation executions and their outcomes.",butlerAutomationRunsEmpty:"No automation run records yet.",butlerAutomationHistoryTitle:"Automation History",butlerAutomationHistoryDescription:"Only non-active automation tasks and completed run records are collected here. Active automation stays in the main list.",butlerAutomationHistoryEmpty:"There are no automation history records yet.",butlerAutomationStatusActive:"Running",butlerAutomationStatusWaitingUser:"Waiting for You",butlerAutomationStatusCompleted:"Completed",butlerAutomationStatusFailed:"Failed",butlerAutomationStatusCancelled:"Cancelled",butlerAutomationTaskTypeLabel:"Task type",butlerAutomationTaskTypeManual:"Manual plan task",butlerAutomationTaskTypeInterval:"Scheduled plan task",butlerAutomationTaskTypeCron:"Cron plan task",butlerAutomationTaskTypeFollowUp:"Conditional follow-up task",butlerAutomationTaskTypeControlTimer:"Assistant timer",butlerAutomationTaskEnabled:"Enabled",butlerAutomationTaskDisabled:"Disabled",butlerAutomationStatusLabel:"Status",butlerAutomationTaskLastRunLabel:"Last run",butlerAutomationTaskNextRunLabel:"Next run",butlerAutomationOpenDetailsAction:"Open Details",butlerAutomationCollapseDetailsAction:"Hide Details",butlerAutomationDetailTitle:"Automation Config",butlerAutomationDetailDescription:"Edit the trigger rules and action content here. Changes apply immediately after saving.",butlerAutomationSaveAction:"Save Changes",butlerAutomationSaving:"Saving...",butlerAutomationSaveSucceeded:"Automation config saved",butlerAutomationSaveFailed:"Failed to save automation config",butlerAutomationTitleLabel:"Automation name",butlerAutomationPromptLabel:"Action content",butlerAutomationPromptRequired:"Action content is required.",butlerAutomationIncludeTriggerContextLabel:"Include trigger context in the assistant message",butlerAutomationTargetSessionLabel:"Target session",butlerAutomationDueAtLabel:"Run at",butlerAutomationEverySecondsLabel:"Every seconds",butlerAutomationEveryMinutesLabel:"Every minutes",butlerAutomationEveryHoursLabel:"Every hours",butlerAutomationStopAtLabel:"Stop at",butlerAutomationCronMinuteLabel:"Cron minute",butlerAutomationCronHourLabel:"Cron hour",butlerAutomationCronDaysOfWeekLabel:"Days of week",butlerAutomationPollIntervalLabel:"Poll interval (seconds)",butlerAutomationExpiresAtLabel:"Expires at",butlerAutomationMaxChecksLabel:"Max checks",butlerAutomationInvalidDateSuffix:" has an invalid datetime value.",butlerAutomationRequiredSuffix:" is required.",butlerAutomationInvalidNumberSuffix:" must be an integer.",butlerAutomationInvalidPositiveNumberSuffix:" must be greater than 0.",butlerAutomationCronDaysValidation:"Days of week must be comma-separated integers from 0 to 6.",butlerAutomationRunSourceLabel:"Source",butlerAutomationRunSourcePatrol:"Plan task run",butlerAutomationRunSourceFollowUp:"Conditional follow-up run",butlerAutomationRunSourceControlTimer:"Assistant timed resume",butlerAutomationRunSummaryLabel:"Outcome",butlerAutomationRunProcessedAtLabel:"Processed at",butlerAutomationRunEmptySummary:"No summary was returned for this run.",butlerAutomationPatrolRunTitle:"Patrol Task Run",butlerControlTimerBannerTitle:"Next timed step",butlerControlTimerCountdownActive:"The assistant will continue in {duration}",butlerControlTimerCountdownDueNow:"The assistant is about to continue",butlerControlTimerCountdownLead:"The assistant will",butlerControlTimerCountdownTail:"before continuing",butlerControlTimerCountdownDueLead:"The assistant is about to",butlerControlTimerCountdownDueTail:"continue",butlerControlTimerDueAtLabel:"Scheduled for: {time}",butlerControlTimerTypeOnce:"One-time",butlerControlTimerTypeRepeat:"Repeating",butlerControlTimerTypeConditional:"Conditional",butlerControlTimerTypeOther:"Other",butlerControlTimerWorkspaceLabel:"Target workspace",butlerControlTimerSessionLabel:"Target session",butlerControlTimerTargetSessionLabel:"Target session: {sessionId}",butlerControlTimerDetailAction:"View prompt details",butlerControlTimerPromptTitle:"Resume prompt",butlerControlTimerUnknownWorkspace:"No workspace linked",butlerControlTimerUnknownSession:"No session linked",butlerControlTimerStopAction:"Stop action",butlerControlTimerCancelOperationAction:"Cancel action",butlerControlTimerExecuteNowAction:"Stop timer",butlerControlTimerExecutingNow:"Executing now...",butlerControlTimerExecuteNowSucceeded:"The wait ended and the next action started immediately",butlerControlTimerExecuteNowFailed:"Failed to end the wait and execute immediately",butlerControlTimerActionNote:"Stop action cancels this timed continuation. Stop timer ends the wait and runs it now.",butlerControlTimerCancelAction:"Cancel timer",butlerControlTimerCancelling:"Cancelling...",butlerControlTimerCancelSucceeded:"The assistant timer was cancelled",butlerControlTimerCancelFailed:"Failed to cancel the assistant timer",butlerControlTimerRunCompletedSummary:"The timer fired and the assistant continued the next step.",butlerControlTimerRunCancelledSummary:"This timer was cancelled manually.",butlerControlTimerRunFailedSummary:"The timer failed to resume the assistant.",butlerControlTimerNoProject:"No linked project",butlerAutomationViewRoundsAction:"View Round Details",butlerAutomationRoundDetailsTitle:"Follow-up Round Details",butlerAutomationRoundDetailsDescription:"Review each Butler follow-up round for this task.",butlerAutomationRoundLoading:"Loading follow-up round details...",butlerAutomationRoundLoadFailed:"Failed to load follow-up round details",butlerAutomationRoundEmpty:"There are no follow-up round details yet.",butlerAutomationRoundLabel:"Round {round}",butlerAutomationRoundProcessedAtLabel:"Processed at",butlerAutomationRoundStatusLabel:"Task status",butlerAutomationRoundObservedStateLabel:"Session runtime state",butlerAutomationRoundSummaryLabel:"Round decision",butlerAutomationRoundWaitingReasonLabel:"Waiting reason",butlerAutomationRoundPromptLabel:"Proxy-sent content",butlerAutomationRoundKindStarted:"Follow-up started",butlerAutomationRoundKindContinue:"Resumed immediately",butlerAutomationRoundKindQueued:"Queued for send",butlerAutomationRoundKindWaitingUser:"Waiting for user",butlerAutomationRoundKindCompleted:"Marked completed",butlerAutomationRoundKindFailed:"Follow-up failed",butlerAutomationRoundKindCancelled:"Stopped manually",butlerAutomationRoundKindLimitReached:"Round limit reached",butlerInboxAction:"Inbox",butlerInboxModalTitle:"Inbox",butlerInboxModalDescription:"Track project todos here and keep their current progress tied to real projects.",butlerInboxLoading:"Loading inbox...",butlerInboxLoadFailed:"Failed to load inbox",butlerInboxProjectsEmpty:"No managed project is available to bind yet.",butlerInboxEmpty:"No inbox records yet.",butlerInboxCreateTitle:"Add Todo",butlerInboxEditingTitle:"Edit Todo",butlerInboxFormDescription:"Every todo must be bound to a project so the assistant can keep following it later.",butlerInboxListTitle:"Current Todos",butlerInboxListDescription:"This list shows todos across your managed projects so you can handle them in one place.",butlerInboxShowClosedAction:"Show closed",butlerInboxQuickStatusLabel:"Quick status update",butlerInboxProjectLabel:"Project",butlerInboxTypeLabel:"Type",butlerInboxTitleLabel:"Title",butlerInboxTitlePlaceholder:"For example: Finish login captcha flow",butlerInboxContentLabel:"Details",butlerInboxContentPlaceholder:"Describe the current issue, target, or what you want the assistant to keep pushing forward.",butlerInboxStatusLabel:"Progress",butlerInboxTypeTask:"Task",butlerInboxTypeBug:"Bug",butlerInboxTypeFeature:"Feature",butlerInboxTypeChange:"Change",butlerInboxStatusPending:"Pending",butlerInboxStatusInProgress:"In Progress",butlerInboxStatusClosed:"Closed",butlerInboxCreateAction:"Add Todo",butlerInboxUpdateAction:"Save Changes",butlerInboxCancelEditAction:"Cancel Edit",butlerInboxEditAction:"Edit",butlerInboxDeleteAction:"Delete",butlerInboxCreated:"Todo created",butlerInboxUpdated:"Todo updated",butlerInboxDeleted:"Todo deleted",butlerInboxSaveFailed:"Failed to save todo",butlerInboxDeleteFailed:"Failed to delete todo",butlerProviderSwitched:"Provider switched",butlerProviderSwitchedDescription:"Switched to {provider}. The current view was reset and reloaded.",butlerProviderSwitchFailed:"Failed to switch provider",butlerAttachmentUnsupported:"Attachments are not supported in Butler chat yet",butlerOverviewTitle:"Overview",butlerOverviewDescription:"This area pulls together the most important things to pay attention to right now.",butlerMetricProjectCount:"Projects",butlerMetricBlockedCount:"Blocked",butlerMetricHighRiskCount:"High Risk",butlerTopRisksTitle:"Top Risks",butlerNextActionsTitle:"Next Actions",butlerOverviewEmpty:"No data",butlerOverviewLoading:"Loading Butler context summary...",butlerEventsTitle:"Recent Actions",butlerEventsDescription:"Anything Butler just helped you do is listed here.",butlerEventsEmpty:"No action events yet",butlerLoadFailed:"Failed to load Butler workbench",butlerContextStrategyTitle:"Context On Demand",butlerContextStrategyDescription:"Butler only receives the global summary by default. Project sessions, memories, patrols, and verifications are fetched from the backend only after you drill into a specific project.",butlerConversationTitle:"Talk to Assistant",butlerConversationDescription:"This conversation belongs to {displayName} only. When details are needed, {displayName} answers from the aggregated summary first, then pulls the relevant project, session, patrol, or verification data from the backend on demand.",butlerComposerPlaceholder:"Tell {displayName} what you want to inspect or decide next",butlerProjectsTitle:"Projects",butlerProjectsDescription:"Pick a project here and Butler will continue with its latest progress and records.",butlerProjectsEmpty:"No projects available for drilldown",butlerProjectWorkspaceLabel:"Workspace: {workspaceId}",butlerProjectSummaryEmpty:"No summary available yet",butlerProjectOpenDetailAction:"Open Details",butlerProjectSyncAction:"Sync to Timeline",butlerProjectSyncSucceeded:"Project {projectName} was synced into Butler's timeline",butlerProjectActionRequiresSession:"Send Butler a message first, then ask it to continue working on a project.",butlerProjectContextTitle:"Current Project",butlerProjectContextDescription:"This area shows the sessions, records, and results tied to the project you selected.",butlerProjectContextEmpty:"Pick a project from the list or action events first.",butlerProjectContextLoading:"Loading project-related context...",butlerProjectContextMeta:"Project status: {status} · Risk level: {riskLevel}",butlerProjectActionSucceeded:"Butler action completed",butlerProjectActionFailed:"Butler action failed",butlerProjectActionPending:"Processing...",butlerProjectSessionsTitle:"Project Sessions",butlerProjectMemoriesTitle:"Project Memories",butlerProjectPatrolsTitle:"Patrol Runs",butlerProjectVerificationsTitle:"Verification Runs",butlerProjectOpenConversationAction:"Open Real Session",butlerProjectResumeAction:"Resume Session",butlerProjectResumeSucceeded:"Session resumed: {sessionTitle}",butlerProjectStartPatrolAction:"Start Patrol",butlerProjectPatrolSucceeded:"Started a patrol for {projectName}",butlerProjectStartVerificationAction:"Start Verification",butlerProjectVerificationSucceeded:"Started a verification for {projectName}",butlerProjectMemoryMeta:"Type: {memoryType} · Status: {status}",butlerProjectSessionMeta:"Role: {role} · Status: {status}",butlerProjectPatrolMeta:"Status: {status} · Risk: {riskLevel}",butlerProjectVerificationMeta:"Type: {verificationType} · Status: {status}",butlerProjectRunSummaryEmpty:"No summary yet",butlerProjectFocusAction:"Focus This Record",butlerProjectUpdatedAtLabel:"Updated: {updatedAt}",butlerFocusedBadge:"Focused",searchModalTitle:"Search",searchModalDescription:"Enter a keyword, then choose whether to search code, affairs, or everything.",searchPlaceholder:"Search sessions, code, documents, tags, or todos",searchHint:"Type a keyword first, then choose code, affairs, or all.",searchChooseActionHint:"Choose a search scope below.",searchActionLabel:"Search scope",searchActionCode:"Search Code",searchActionAffairs:"Search Affairs",searchActionAll:"Search All",searchClearAction:"Clear",searchLoading:"Searching...",searchEmpty:"No matching results found.",searchSessionsGroup:"Sessions",searchCodeGroup:"Code",searchModeLabel:"Search mode",searchModeSessions:"Sessions",searchModeCode:"Code",searchModeAffairs:"Affairs",searchKeywordLabel:"Keyword",searchWorkspaceLabel:"Workspace",searchSessionPlaceholder:"Search by session title, workspace, or provider",searchCodePlaceholder:"Search by file name or path fragment",searchAffairsPlaceholder:"Search by document, tag, todo, or conversation keyword",searchSessionHint:"Type a keyword to instantly filter matching sessions.",searchCodeHint:"Pick a workspace, then search by file name or path.",searchAffairsHint:"Type a keyword to search documents, tags, todos, and conversations across all affairs workspaces.",searchAffairsLoading:"Searching affairs content...",searchSessionEmpty:"No matching sessions found.",searchCodeEmpty:"No matching files found.",searchAffairsEmpty:"No matching affairs content found.",searchCodeFailed:"Code search failed. Please try again later.",searchAffairsFailed:"Affairs search failed. Please try again later.",searchAffairsWorkspaceMissing:"No affairs workspace is available right now.",searchAffairsDocumentsGroup:"Documents",searchAffairsTagsGroup:"Tags",searchAffairsConversationsGroup:"Conversations",searchAffairsTodosGroup:"Todos",searchSortLabel:"Sort by",searchSortRelevance:"Relevance first",searchSortUpdated:"Recently updated first",searchSortTitle:"Title or name first",searchResultTypeSession:"Session",searchResultTypeCode:"Code",searchResultTypeDocument:"Document",searchResultTypeAffairsTag:"Library tag",searchResultTypeTodo:"Todo",searchResultLocateDocument:"Locate",searchResultLocateDocumentTitle:"Locate this file in the document library",searchSubmit:"Search",filesEntry:"Files",gitEntry:"GIT",terminalManagerEntry:"Debug",workspaceSectionTitle:"Workspaces",goBack:"Back",goForward:"Forward",workspaceCount:"Projects",sessionCount:"Sessions",manageWorkspaceAction:"Manage Projects",manageWorkspaceTitle:"Manage Projects",manageWorkspaceDescription:"The list starts with the currently loaded projects. Expand one to inspect its path, Git summary, and code composition, or remove it from the current workbench list.",manageWorkspaceImportAction:"Import Project",manageWorkspaceCloneAction:"Clone Project",manageWorkspaceEmpty:"There are no projects to manage right now.",manageWorkspaceLoading:"Loading project details...",manageWorkspaceLoadFailed:"Failed to load project details.",manageWorkspacePathLabel:"Path",manageWorkspaceGitCommitCount:"Git Commit Count",manageWorkspaceGitInfoLabel:"Git Repository Info",manageWorkspaceRepoRoot:"Repository Root",manageWorkspaceCurrentBranch:"Current Branch",manageWorkspaceRemoteLabel:"Remote",manageWorkspaceNoRemote:"No remote configured",manageWorkspaceNotGit:"This project is not a Git repository.",manageWorkspaceCodeCompositionLabel:"Code Composition",manageWorkspaceCodeCompositionFiles:"files",manageWorkspaceCodeCompositionOther:"Other",manageWorkspaceNoCodeComposition:"No recognizable code files were found for composition stats.",manageWorkspaceCodeTruncated:"The project is large, so only the first {count} recognizable files were counted.",manageWorkspaceColorLabel:"Background Color",manageWorkspaceColorSelectSwatch:"Use color {color}",manageWorkspaceColorClearAction:"Clear Color",manageWorkspaceColorUnset:"Not set. The default worktree color is in use.",manageWorkspaceColorSaveFailed:"Failed to save the workspace color.",manageWorkspaceHiddenSectionTitle:"Hidden Projects",manageWorkspaceRemoveAction:"Remove Project",manageWorkspaceRemoving:"Removing...",manageWorkspaceRemoveSuccess:"Project removed from the current workbench list",manageWorkspaceRemoveFailed:"Failed to remove the project",manageWorkspaceRemoveConfirmTitle:"Confirm Project Removal",manageWorkspaceRemoveConfirmDescription:"This only removes the project from the current workbench list. It does not delete any files on disk or historical records. If you load the same path again later, the old records will appear again.",manageWorkspaceRemoveConfirmTarget:'Remove "{name}" from the current workbench?',manageWorkspaceRemoveConfirmAction:"Remove Project",importWorkspaceTitle:"Add Project",importWorkspaceHint:"Import a local code directory",importExpand:"Expand",importCollapse:"Collapse",importPathLabel:"Project Path",importPathPlaceholder:"Enter the project folder path",importNameLabel:"Project Name",importNamePlaceholder:"Optional",importSubmit:"Add Project",importSubmitting:"Adding...",importChooseFolder:"Choose Folder",importPickFolderFailed:"Failed to open the folder picker",importDesktopDropHint:"You can drag a local project folder directly into this area",importHint:"Enter a local code directory and start working",importServerDirectoryHint:"Browse and select the project directory on the server",importBrowserTitle:"Select Server Directory",importBrowserDescription:"You are browsing directories on the server, not on the current device.",importBrowserCurrentPath:"Current Path",importBrowserRoots:"Root Directories",importBrowserOpenParent:"Go Up",importBrowserOpenPath:"Open Path",importBrowserCreateDirectory:"New Folder",importBrowserCreateDirectoryTitle:"New Folder",importBrowserCreateDirectoryDescription:"Create a single child folder in the current server path. Path separators are not accepted.",importBrowserCreateDirectoryLabel:"Folder Name",importBrowserCreateDirectoryPlaceholder:"Enter the new folder name",importBrowserCreateDirectorySuccess:"Folder created",importBrowserCreateDirectoryFailed:"Failed to create folder",importBrowserCreateDirectorySubmit:"Create Folder",importBrowserCreatingDirectory:"Creating...",importBrowserEmpty:"No subdirectory is available in the current path",importBrowserBrowseFailed:"Failed to load server directories",importBrowserSubmit:"Import Current Directory",importPathRequired:"Enter the project path",importSuccess:"Project added",importFailed:"Failed to add project",cloneWorkspaceTitle:"Clone Project",cloneWorkspaceHint:"Clone a Git repository into a server directory and add it to the project list.",cloneSubmit:"Clone Project",cloneSubmitting:"Cloning...",cloneRepositoryLabel:"Git Repository URL",cloneRepositoryPlaceholder:"For example: https://github.com/org/repo.git",cloneParentPathLabel:"Target Parent Directory",cloneParentPathPlaceholder:"Choose an existing directory on the backend server",cloneDirectoryNameLabel:"New Project Directory Name",cloneDirectoryNamePlaceholder:"Defaults to the repository name when left empty",clonePickDirectory:"Choose Directory",cloneAuthModeLabel:"Authentication",cloneAuthModeNone:"No Authentication",cloneAuthModeBasic:"Username + Password",cloneAuthModeToken:"Token",cloneUsernameLabel:"Username",cloneUsernamePlaceholder:"Enter Git username",clonePasswordLabel:"Password",clonePasswordPlaceholder:"Enter Git password",cloneTokenLabel:"Token",cloneTokenPlaceholder:"Enter access token",cloneTokenUsernamePlaceholder:"Optional, defaults to git when left empty",cloneRepoRequired:"Enter the Git repository URL",clonePathRequired:"Select the target parent directory",cloneSuccess:"Project cloned successfully",cloneFailed:"Clone failed",cloneHint:"The target parent directory must already exist. Clone creates a new repository folder under it.",cloneBrowserTitle:"Select Clone Parent Directory",cloneBrowserDescription:"Choose an existing server-side parent directory. Clone will create a new project folder under it.",cloneBrowserSubmit:"Use Current Directory",refreshNavigation:"Refresh",desktopChromeLabel:"Desktop Workbench",windowMinimize:"Minimize Window",windowMaximize:"Maximize or Restore Window",windowClose:"Close Window",contextOpenSession:"Open Session",navigationLoadFailed:"Load failed. Retry.",emptyNavigationTitle:"No project yet",emptyNavigationBody:"Add a local code directory to start working",emptyWorkspaceSessions:"No sessions",favoriteSectionTitle:"Pinned Sessions",favoriteSectionEmpty:"Pinned sessions stay here for quick access.",chatSectionTitle:"Chats",chatSectionEmpty:"No chats yet",chatNewAction:"New chat",worktreeSectionTitle:"Child Worktrees",worktreeSectionExpand:"Expand Child Worktrees",worktreeSectionCollapse:"Collapse Child Worktrees",worktreeMergePanelLabel:"Worktree Merge",worktreeMergePanelTitle:"Merge Into Direct Parent",worktreeMergePreviewAction:"Preview",worktreeMergePreviewRefresh:"Preview",worktreeMergePreviewIdle:"Preview not loaded",worktreeMergePreviewLoading:"Checking...",worktreeMergeReady:"Ready to merge",worktreeMergeBlocked:"Merge blocked",worktreeMergeApplying:"Merging...",worktreeMergeApplyAction:"Merge",worktreeMergeApplySuccess:"The worktree has been merged into its direct parent",worktreeMergeApplyFailed:"Failed to merge worktree",worktreeMergePreviewFailed:"Failed to load merge preview",worktreeMergeAlreadyMerged:"Already merged into parent",worktreeMergeMergedHint:"The code is already back in the parent. Cleanup can be done next.",worktreeMergeMergedDirtyHint:"Committed history is already in the parent, but this worktree still has pending work and cannot be cleaned up yet.",worktreeMergeChecklistTitle:"Merge Checklist",worktreeMergeChecklistSourceState:"Worktree state is valid",worktreeMergeChecklistSourceStateBlocked:"The worktree state is inconsistent. The system is not treating it as an active worktree yet.",worktreeMergeChecklistSourceClean:"Source worktree is clean",worktreeMergeChecklistSourceCleanBlocked:"The source worktree still has uncommitted changes. Commit them first.",worktreeMergeChecklistTargetClean:"Parent workspace is clean",worktreeMergeChecklistTargetCleanBlocked:"The direct parent workspace has uncommitted changes and cannot receive the merge.",worktreeMergeChecklistChildren:"No active child worktrees",worktreeMergeChecklistChildrenBlocked:"There are still active child worktrees under this node. Clean leaf nodes first.",worktreeMergeChecklistCommits:"There are commits to merge",worktreeMergeChecklistCommitsBlocked:"This worktree has no commits ahead of the parent workspace.",worktreeMergeChecklistConflicts:"No merge conflicts detected",worktreeMergeChecklistConflictsBlocked:"Merge conflicts were detected. Resolve them before continuing.",worktreeMergeChecklistResultPending:"Waiting for preview",worktreeMergeChecklistResultReady:"Merge can proceed",worktreeMergeChecklistResultReadyDetail:"All checks passed. You can start the merge now.",worktreeMergeChecklistResultBlocked:"Merge cannot proceed yet",worktreeMergeChecklistResultBlockedDetail:"Resolve the blockers above before continuing.",worktreeMergeChecklistResultMerged:"Merged. Cleanup can continue",worktreeMergeCompactPending:"Pending",worktreeMergeCompactChecking:"Checking",worktreeMergeCompactReady:"Ready",worktreeMergeCompactBlocked:"Blocked",worktreeMergeCompactMerged:"Merged",worktreeMergeCompactMerging:"Merging",worktreeMergeCompactCleaning:"Cleaning",worktreeMergeCompactInactive:"State Error",worktreeMergeCompactDirty:"Dirty",worktreeMergeCompactTargetDirty:"Parent Dirty",worktreeMergeCompactConflict:"Conflict",worktreeMergeCompactChildren:"Has Children",worktreeMergeCompactNoCommits:"No Commits",worktreeCleanupAction:"Cleanup",worktreeCleanupRunning:"Cleaning...",worktreeCleanupSuccess:"The worktree has been cleaned up",worktreeCleanupFailed:"Failed to clean up worktree",worktreeCleanupModalTitle:"Confirm Worktree Cleanup",worktreeCleanupModalDescription:"Cleanup removes the worktree directory and app metadata by default. Deleting the branch is only available after it has been merged into the parent branch.",worktreeCleanupConfirm:"Clean up {name}? The git branch will be kept by default.",worktreeCleanupDeleteBranchLabel:"Also delete branch {branch}",worktreeCleanupDeleteBranchHint:"Branch deletion is only available after the branch has been merged into the parent branch.",worktreeCleanupDeleteBranchAction:"Cleanup and Delete Branch",worktreeCleanupDeleteBranchSuccess:"The worktree and branch {branch} have been cleaned up",worktreeCleanupDeleteBranchPartialFailed:"The worktree was cleaned up, but branch {branch} could not be deleted",worktreeMergeCurrentBranch:"Current branch: {branch}",worktreeMergeParentBranch:"Parent branch: {branch}",worktreeMergeTargetWorkspace:"Target parent: {name}",worktreeMergeAheadBehind:"Commit delta: ahead {ahead} / behind {behind}",worktreeMergeBaseCommit:"merge base: {commit}",worktreeMergeConflictLabel:"Conflicting files",favoriteAction:"Pin Session",unfavoriteAction:"Unpin",favoriteAdded:"Session pinned",favoriteRemoved:"Session unpinned",favoriteToggleFailed:"Failed to update pinned state",sessionMoreAction:"More Actions",deleteSessionAction:"Delete Session",deleteSessionConfirmTitle:"Delete This Session",deleteSessionConfirmDescription:"Deleting a session removes it from assistant history and workspace lists, and also clears the real session record. This cannot be undone.",deleteSessionSuccess:"Session deleted",deleteSessionFailed:"Failed to delete session",sessionStateInferred:"Inferred",renameAction:"Rename",renameSuccess:"Session name updated",renameFailed:"Failed to rename session",renameModalTitle:"Rename Session",renameModalDescription:"Use a name you can recognize at a glance. This changes only the title, not the content.",renameInputLabel:"Session Name",renameInputPlaceholder:"Enter a new session name",renamingSession:"Saving...",archiveFolderLabel:"Archived Sessions",archiveFolderAction:"Open Archive Folder",archiveAction:"Archive Session",archiveCurrentSessionAction:"Archive Current Session",archiveAdded:"Session archived",archiveConfirmTitle:"Archive This Session",archiveConfirmDescription:"After archiving, this session will be hidden from the main list for the current workspace, and you can still restore it from archive.",unarchiveAction:"Restore from Archive",archiveRestored:"Session restored to the main list",archiveModalTitle:"Archived Sessions",archiveModalDescription:"This list shows sessions temporarily hidden in the current project. Restore them when needed.",archiveEmpty:"There are no archived sessions in this project yet.",archiveSearchAction:"Search",archiveSearchLabel:"Search Archived Sessions",archiveSearchPlaceholder:"Search by session name or summary",archiveSearchEmpty:"No archived sessions match your search.",archiveSearchSummaryLoading:"Loading archived session summaries...",archiveSearchSummaryFailed:"Some archived summaries could not be loaded yet, so search currently falls back to titles.",archiveViewAction:"View Archived Sessions",parallelCreateAction:"Create Parallel Session",parallelCreateModalTitle:"Create Parallel Sessions",parallelCreateModalDescription:"Set the goal for this parallel run first, then adjust each session separately.",parallelCreateSharedPromptLabel:"The goal for this parallel run is",parallelCreateSharedPromptPlaceholder:"For example: explore multiple implementation paths, compare technical directions, or split the same debugging task into parallel angles.",parallelCreateCountLabel:"Parallel Count",parallelCreateMembersTitle:"Configure Each Session",parallelCreateMembersDescription:"Each pane is a real session member, with its own provider, model, and temporary workspace choice.",parallelCreateMemberTitle:"Member {index}",parallelCreateModelLabel:"Model",parallelCreateMemberPromptLabel:"Any special requirement?",parallelCreateMemberPromptPlaceholder:"For example: be more conservative, focus on refactoring, prioritize performance investigation, or constrain the stack and output style.",parallelCreateIsolationLabel:"Use Temporary Isolated Workspace",parallelCreateIsolationHint:"Only enable this for members that need an independent code directory. It stays out of formal worktrees until promotion succeeds.",parallelCreateProvidersLoading:"Loading installed providers...",parallelCreateNoAvailableProviders:"No available model provider is installed for this workspace yet.",parallelCreateNoModelsAvailable:"No models are available for this provider",parallelCreatePromptRequired:"The shared prompt cannot be empty",parallelCreatePartialFailure:"{successCount} members were created, and {failureCount} members failed to start.",parallelCreateAllFailed:"All {failureCount} members failed to start. Adjust the failed member settings and try again.",parallelCreateContinuePartial:"Open Created Split View",parallelCreateMemberSucceeded:"Created",parallelCreateMemberFailed:"Failed",parallelCreateMemberErrorTitle:"This member was not created",parallelCreateSubmit:"Create Parallel Sessions",parallelCreateSubmitting:"Creating parallel sessions...",parallelCreateSucceeded:"Parallel sessions created",parallelAppendAction:"Add Parallel Session",parallelAppendModalTitle:"Add Parallel Sessions",parallelAppendModalDescription:"Reuse the original user prompt for this group and only configure the newly added members.",parallelAppendSharedPromptLabel:"Original User Prompt",parallelAppendSharedPromptDescription:"This comes from the first user message in the current parallel group and cannot be edited here.",parallelAppendCountLabel:"Add Count",parallelAppendSubmit:"Add Parallel Sessions",parallelAppendSubmitting:"Adding parallel sessions...",parallelAppendSucceeded:"Parallel sessions added",parallelAppendNoRemainingSlots:"This parallel group already has 4 members and cannot accept more.",parallelGroupBadge:"Parallel",parallelGroupAnchorBadge:"Anchor",parallelGroupMemberBadge:"Member",parallelWorkspacePromotedBadge:"Promoted Workspace",parallelGroupLoadFailed:"Failed to load the parallel session group",parallelGroupEmpty:"No parallel members are available yet.",parallelPaneOpenAction:"Open Session",parallelPaneToolsAction:"Tools",parallelPanePinAction:"Pin Panel",parallelPaneDetachAction:"Open in Window",parallelPaneResizeAction:"Resize Panel",parallelPaneMoreAction:"More Options",parallelPaneInfoAction:"View Info",parallelPaneProcessesEntry:"Processes",parallelPaneTerminalEntryDescription:"Terminal work is input-heavy and scroll-heavy, so it stays as a dedicated entry instead of being forced into this floating panel.",parallelPaneTerminalOpenAction:"Open Terminal",parallelPaneInfoTitle:"Session Info",parallelPaneModelFallback:"Default Model",parallelPaneIsolatedWorkspaceTitle:"Temporary Isolated Workspace",parallelPanePromptFallback:"No special requirement",parallelPaneColorPaletteLabel:"Palette",parallelPaneColorPaletteDescription:"Adjust this pane color so it is easier to tell branches apart at a glance.",parallelPaneColorPaletteReset:"Use Default Split Colors",parallelPaneRemoveAction:"Remove Parallel Session",parallelPaneRemoveDescription:"Removing this session takes it out of the current parallel group. If it is still using a temporary isolated workspace, the workspace and branch are cleaned up too.",parallelPaneRemovePromotedDescription:"Removing this session takes it out of the current parallel group. Promoted child worktrees and branches are kept.",parallelPanePromoteAction:"Promote to Formal Worktree",parallelPanePromoteDescription:"Only promote this temporary workspace after you are sure it should be kept as a formal child worktree.",parallelPanePromoting:"Promoting...",parallelPaneRemoving:"Removing...",subagentBadge:"Sub-agent",sessionChildBadge:"Child Session",sessionForkSession:"Session Fork",sessionForkMessage:"Message Fork",sessionForkReconstructed:"Reconstructed Fork",subagentExpand:"Expand Sub-agent List",subagentCollapse:"Collapse Sub-agent List",subagentExpandMore:"Show More Sub-agents",closedSubagentToggle:"Closed Sub-agents",favoriteExpandMore:"Show More Pinned",sessionExpandMore:"Show More Sessions",archiveExpandMore:"Show More Archived Sessions",worktreeCollapse:"Collapse Worktree",worktreeExpand:"Expand Worktree",workspaceCollapse:"Collapse Project",workspaceExpand:"Expand Project",reorderWorkspace:"Drag to Reorder Projects",switchWorkspace:"Switch to Project",workspacePinToTopAction:"Pin to Top",workspaceSwitchHostAction:"Switch",workspaceHideAction:"Hide",workspaceHideSuccess:"Project hidden from the current list",workspaceHideFailed:"Failed to hide the project",workspaceUnhideAction:"Unhide",workspaceUnhideSuccess:"Project is visible again",workspaceUnhideFailed:"Failed to unhide the project",workspaceProcessEntry:"Processes",workspaceReorderFailed:"Failed to save project order.",workspaceCollapseStateSaveFailed:"Failed to save project collapse state.",workspaceHomeSwitcherLabel:"Switch Workspace",workspaceHomeSwitcherTitle:"Workspace",hostWorkspaceSwitcherTitle:"Hosts and Workspaces",hostSwitcherAriaLabel:"Switch Host",hostSwitcherTitle:"Hosts",hostSwitcherSavedSection:"Saved",hostSwitcherDiscoveredSection:"Discovered",hostSwitcherCurrentBadge:"Current",hostSwitcherDiscoveredBadge:"Auto",hostSwitcherPeerBadge:"Peer",hostSwitcherNodeBadge:"HOST",hostSwitcherPrimaryHostTitle:"Primary HOST",hostSwitcherAliasLabel:"HOST alias",hostSwitcherAliasPlaceholder:"4 English letters",hostSwitcherAliasRule:"Aliases can only use English letters, up to 4.",hostSwitcherAliasInvalid:"Aliases can only use English letters, up to 4.",hostSwitcherAliasSaveAction:"Save alias",hostSwitcherAliasSaveSuccess:"HOST alias saved",hostSwitcherPeerTitle:"Use as Peer HOST",hostSwitcherPeerSectionTitle:"Peer HOST",hostSwitcherPeerDescription:"Before enabling, the primary HOST checks network reachability, version compatibility, and account sign-in. It will not enable if any check fails.",hostSwitcherPeerStatusLabel:"Peer status",hostSwitcherPeerPasswordOneTimeHint:"The target HOST password is only used for this enable check and is not saved to the primary HOST.",hostSwitcherPeerLoginRequired:"Enter the target HOST username and password before enabling Peer HOST.",hostSwitcherPeerChecking:"Checking",hostSwitcherPeerEnableAction:"Enable Peer",hostSwitcherPeerReconnectAction:"Reconnect",hostSwitcherPeerDisableAction:"Disable Peer",hostSwitcherPeerEnableSuccess:"Peer HOST enabled",hostSwitcherPeerReconnectSuccess:"Peer HOST reconnected",hostSwitcherPeerEnableFailed:"Failed to enable Peer HOST",hostSwitcherPeerReconnectFailed:"Failed to reconnect Peer HOST",hostSwitcherPeerDisableSuccess:"Peer HOST disabled",hostSwitcherPeerDisableFailed:"Failed to disable Peer HOST",hostSwitcherPeerCheckFailed:"{name} did not pass the check",hostSwitcherAddAction:"Add Host",hostSwitcherAddPeerHostAction:"Add Peer Host",hostSwitcherNameLabel:"Host Name",hostSwitcherNamePlaceholder:"For example: Office Host",hostSwitcherUrlLabel:"Host URL",hostSwitcherUrlPlaceholder:"For example: http://192.168.1.20:3002",hostSwitcherSaveAction:"Save Host",hostSwitcherSwitching:"Switching",hostSwitcherDetailAction:"Details",hostSwitcherDetailAriaLabel:"View connection details for host {name}",hostSwitcherDetailTitle:"Connection Details",hostSwitcherDetailStatusLabel:"Connection Status",hostSwitcherDetailStatusRelay:"CodingNS Connect",hostSwitcherDetailStatusDirect:"Direct",hostSwitcherDetailRouteLabel:"Current Route",hostSwitcherDetailAddressLabel:"Current Address",hostSwitcherDetailLatencyLabel:"CodingNS Connect Latency",hostSwitcherDetailLatencyLoading:"Checking...",hostSwitcherDetailTrafficLabel:"Session Traffic",hostSwitcherDetailResourceTitle:"Host Resources",hostSwitcherDetailCpuLabel:"CPU",hostSwitcherDetailCpuValue:"{usage} · {cores} cores",hostSwitcherDetailMemoryLabel:"Memory",hostSwitcherDetailDiskLabel:"Disk",hostSwitcherDetailUnavailable:"Unavailable",hostSwitcherWorkspaceCount:"{count} workspaces",hostSwitcherWorkspaceCountWithUser:"{username} · {count} workspaces",hostSwitchFailed:"Failed to switch host.",hostSwitchUnreachable:"{name} is unreachable right now.",hostSwitchMissing:"The target host no longer exists.",hostDeleteAction:"Delete Host",hostDeleteAriaLabel:"Delete host {name}",hostDeleteBusy:"Removing",hostDeleteConfirmAction:"Confirm",hostDeleteConfirm:'Delete host "{name}"? Saved sign-in info will also be cleared.',hostDeleteSuccess:"Removed host: {name}",hostDeleteFailed:"Failed to remove host: {name}",hostAddIncompleteCredentials:"Fill in both the username and password, or leave both blank.",hostAddInvalidUrl:"The host URL is invalid.",hostAddDuplicate:"This host already exists.",hostAddFailed:"Failed to add the host.",hostAddSuccess:"Added host: {name}",hostDiscoveryRefreshing:"Scanning local hosts...",hostDiscoveryFailed:"Failed to scan local hosts.",mobileWorktreeBadge:"Worktree",workspaceHomeStatusSectionTitle:"Current Workspace",workspaceHomeViewAllAction:"View All Sessions",workspaceHomeMetricActive:"Active",workspaceHomeMetricUnread:"Notifications",workspaceHomeMetricTerminal:"Terminals",workspaceHomeMetricChanges:"Changes",workspaceHomeActiveSessionsSectionTitle:"Active Sessions",workspaceHomeQuickLaunchStatusLabel:"Quick Debug",workspaceHomeQuickLaunchRunning:"Running",workspaceHomeQuickLaunchStopped:"Stopped",workspaceHomeWaitingInputLabel:"Waiting Input",workspaceHomeButlerLabel:"Assistant",mobileButlerEntry:"Assistant",mobileConversationToolCloseAction:"Back to Conversation",mobileConversationToolTabsLabel:"Files, Git, and Debug Tabs",mobileConversationToolProcessesTab:"Debug",mobileButlerEmptyTitle:"Assistant is not ready yet",mobileButlerEmptyBody:"The first assistant setup has not been completed yet. Finish the initial setup on desktop, then come back on mobile to review follow-ups and automations.",butlerProjectSyncEmptyState:"Give the assistant a concrete goal and it will continue the work here.",mobileButlerSummaryTitle:"Workspace Summary",mobileButlerSummaryProjects:"Projects",mobileButlerSummaryFollowUps:"Active Tasks",mobileButlerSummaryWaitingUser:"Waiting on You",mobileButlerSummaryInbox:"Open Todos",mobileButlerAssistantWorkspaceLabel:"Butler Workspace",mobileButlerAssistantToneLabel:"Tone",mobileButlerAssistantLanguageLabel:"Language",mobileButlerAssistantUpdatedAtLabel:"Updated",workspaceOverviewTitle:"Put project entry points where you can actually see them",workspaceOverviewBody:"Choose a project first, then decide whether to continue or start a new session.",workspaceListBody:"Keep every loaded project here and surface the frequent actions on the page.",workspaceDetailTitle:"Project Details",workspaceDetailSummaryTitle:"Project Overview",workspaceDetailSummaryBody:"See the path, Git summary, and code footprint first, then jump into the right tool.",workspaceDetailMissingTitle:"Project not found",workspaceDetailMissingBody:"This project may have been removed, or the current snapshot has not loaded it yet.",workspaceDetailDebugTitle:"Service Status",manageWorkspaceDebugDescription:"Review detected services, recent start status, and support guidance for the current project.",workspaceDetailDebugAnalyzeFailed:"Failed to load service status",workspaceDetailDebugFrameworkLabel:"Detected Type",workspaceDetailDebugConfidenceLabel:"Confidence",workspaceDetailDebugCompatibilityLabel:"Readiness",workspaceDetailDebugInjectionLabel:"Recommended Handling",workspaceDetailDebugRuntimeStatusLabel:"Current Status",workspaceDetailDebugFailureStageLabel:"Blocked At",workspaceDetailDebugServiceDiscoveryLabel:"Service Address Handling",workspaceDetailDebugHmrLabel:"Hot Reload Handling",workspaceDetailDebugCallbackLabel:"Callback Handling",workspaceDetailDebugAiFallbackLabel:"Manual Handling Policy",workspaceDetailDebugFrameworkNoteLabel:"Notes",workspaceDetailDebugReasonsLabel:"Summary",workspaceDetailDebugFilesLabel:"Reference Files",workspaceDetailDebugFailureStageEmpty:"None",workspaceDetailDebugRuntimeEmpty:"No runtime record yet.",workspaceDetailDebugFrameworkNoteEmpty:"No extra compatibility note.",workspaceDetailDebugEmptyReasons:"None",workspaceDetailDebugEmptyFiles:"None",workspaceDetailDebugConfidenceHigh:"High",workspaceDetailDebugConfidenceMedium:"Medium",workspaceDetailDebugConfidenceLow:"Low",workspaceDetailDebugCompatibilitySupported:"Ready to Use",workspaceDetailDebugCompatibilityConditional:"Needs More Setup",workspaceDetailDebugCompatibilityUnsupported:"Not Recommended Yet",workspaceDetailDebugCompatibilityUnknown:"Unknown",workspaceDetailDebugInjectionCli:"Startup Args",workspaceDetailDebugInjectionEnv:"Environment",workspaceDetailDebugInjectionOverride:"Adjust Command",workspaceDetailDebugInjectionAiFallback:"Needs Manual Help",workspaceDetailDebugInjectionNone:"Do Not Auto Handle Yet",workspaceDetailDebugRuntimePreparing:"Preparing",workspaceDetailDebugRuntimeRunning:"Running",workspaceDetailDebugRuntimeFailed:"Start Failed",workspaceDetailDebugRuntimeStopped:"Stopped",workspaceDetailDebugRuntimeNotStarted:"Not Started",workspaceDetailDebugRequirementRequired:"Needs Extra Setup",workspaceDetailDebugRequirementNotRequired:"No Extra Setup",workspaceDetailDebugAiPolicyNever:"Do Not Auto Handle",workspaceDetailDebugAiPolicyConditional:"Case by Case",workspaceDetailDebugAiPolicyAllowed:"Allowed",workspaceDetailDebugRuntimeServicesTitle:"Most Recent Start",workspaceDetailDebugRuntimeHistoryTitle:"Recent Starts",workspaceDetailDebugRuntimeHistoryTimeLabel:"Started At",workspaceDetailDebugRuntimeHistoryServiceLabel:"Services",workspaceDetailDebugRuntimeHistoryResultLabel:"Result",workspaceDetailDebugRuntimeHistoryTitleWithIndex:"Run #{id}",workspaceDetailDebugRuntimeHistoryFailedSummary:"{services} did not start correctly in this run.",workspaceDetailDebugRuntimeHistoryGenericSummary:"Recent start records are kept here so repeated failures are easier to spot.",workspaceDetailDebugRuntimeHistoryNoServices:"None",workspaceDetailDebugRuntimeHistoryResultRunning:"Still Running",workspaceDetailDebugRuntimeHistoryResultFailed:"Start Failed",workspaceDetailDebugRuntimeHistoryResultStopped:"Stopped",workspaceDetailDebugRuntimeHistoryResultPreparing:"Preparing",workspaceDetailDebugRuntimeServicePortLabel:"Assigned Port",workspaceDetailDebugRuntimeServiceBindingLabel:"Port State",workspaceDetailDebugRuntimeServiceProcessLabel:"Process",workspaceDetailDebugRuntimeServiceFailureLabel:"Issue Stage",workspaceDetailDebugRuntimeServiceAiLabel:"Manual Handling Record",workspaceDetailDebugDetectedServicesTitle:"Detected Services",workspaceDetailDebugServicePathLabel:"Location",workspaceDetailDebugServiceFrameworkLabel:"Detected As",workspaceDetailDebugServiceCommandLabel:"Start Command",workspaceDetailDebugServiceRequirementsLabel:"Extra Setup Needed",workspaceDetailDebugServiceActionLabel:"Recommended Action",workspaceDetailDebugOpenPageAction:"Services",workspaceDetailDebugPageTitle:"Services",workspaceDetailDebugPageDescription:"View launchers and current status.",workspaceDetailRegisteredDebugPageHeroEyebrow:"Registered Launchers",workspaceDetailRegisteredDebugPageDescription:"Shows registered launchers and status only.",workspaceDetailRegisteredDebugLoadFailed:"Failed to load registered launchers",workspaceDetailRegisteredDebugOverallStatusReady:"Ready",workspaceDetailRegisteredDebugOverallStatusPartial:"Needs Attention",workspaceDetailRegisteredDebugOverallStatusEmpty:"Not Set",workspaceDetailRegisteredDebugOverallSummary:"{runnable} ready · {orchestrated} adjust · {blocked} blocked",workspaceDetailRegisteredDebugSummaryRegisteredCountLabel:"Launchers",workspaceDetailRegisteredDebugSummaryConfiguredPortLabel:"Port Configured",workspaceDetailRegisteredDebugSummaryRunnableCountLabel:"Runnable Now",workspaceDetailRegisteredDebugSummaryOrchestratedCountLabel:"Needs Adjust",workspaceDetailRegisteredDebugSummaryBlockedCountLabel:"Blocked",workspaceDetailRegisteredDebugSummaryLastRefreshLabel:"Updated",workspaceDetailRegisteredDebugChipRegisteredOnly:"Only Debug entries",workspaceDetailRegisteredDebugChipNoGuessing:"No framework guessing",workspaceDetailRegisteredDebugChipPortDriven:"Runtime is port-driven only",workspaceDetailRegisteredDebugAnalysisTitle:"Project Info",workspaceDetailRegisteredDebugAnalysisDescription:"Shows project info.",workspaceDetailRegisteredDebugAnalysisReadonlyNote:"View only",workspaceDetailRegisteredDebugAnalysisDisplayOnlyHint:"View only",workspaceDetailRegisteredDebugAnalysisRoleLabel:"Type",workspaceDetailRegisteredDebugAnalysisNoService:"No result yet.",workspaceDetailRegisteredDebugAnalysisSourceSummary:"Analysis Source: {sourceType}",workspaceDetailRegisteredDebugTemplatesTitle:"Launchers",workspaceDetailRegisteredDebugTemplatesDescription:"Shows registered launchers only.",workspaceDetailRegisteredDebugTemplatesEmpty:"No launcher yet. Add one in Debug.",workspaceDetailRegisteredDebugOpenProcessManagerAction:"Open Debug",workspaceDetailRegisteredDebugActionSyncTemplates:"Refresh",workspaceDetailRegisteredDebugActionSyncingTemplates:"Refreshing…",workspaceDetailRegisteredDebugActionSyncTemplatesSuccess:"Registered launchers were synced from Debug",workspaceDetailRegisteredDebugActionSyncTemplatesFailed:"Failed to refresh registered launchers",workspaceDetailRegisteredDebugActionRunRegistered:"Start",workspaceDetailRegisteredDebugActionRunningRegistered:"Starting…",workspaceDetailRegisteredDebugActionRunRegisteredSuccess:"Runnable items were dispatched",workspaceDetailRegisteredDebugActionRunRegisteredFailed:"Failed to start registered items",workspaceDetailRegisteredDebugActionRunRegisteredSkipped:"Nothing is ready yet. Clear blockers first.",workspaceDetailRegisteredDebugActionPlanHint:"Check plan first",workspaceDetailDebugPageHeroEyebrow:"Service Overview",workspaceDetailDebugOverallStatusLabel:"Overall Status",workspaceDetailDebugOverallSummaryLabel:"Summary",workspaceDetailDebugOverallStatusSupported:"Ready to Start",workspaceDetailDebugOverallStatusConditional:"Some Services Need More Setup",workspaceDetailDebugOverallStatusBlocked:"Do Not Start Everything Yet",workspaceDetailDebugOverallSummaryEmpty:"No usable service check result is available yet.",workspaceDetailDebugOverallSummaryMixed:"Detected {webCount} web services and {desktopCount} desktop-shell services. Desktop shells are shown separately and excluded from web auto handling.",workspaceDetailDebugOverallSummaryDesktopOnly:"Detected {count} desktop-shell services and no clear web service yet.",workspaceDetailDebugOverallSummaryWebOnly:"Detected {count} web services that can join the web debug flow.",workspaceDetailDebugSummaryServiceCountLabel:"Analysis Items",workspaceDetailDebugSummaryWebCountLabel:"Web Services",workspaceDetailDebugSummaryDesktopShellCountLabel:"Desktop Shells",workspaceDetailDebugSummaryWebServicesChip:"{count} web services",workspaceDetailDebugSummaryDesktopShellChip:"{count} desktop shells",workspaceDetailDebugSummaryUnsupportedChip:"{count} blocking items",workspaceDetailDebugAutoInjectionEligible:"Current web services are ready for automatic handling",workspaceDetailDebugAutoInjectionBlocked:"Do not treat this whole project as auto-ready yet",workspaceDetailDebugDesktopShellSummaryHint:"Desktop shell services are shown separately from web service handling",workspaceDetailDebugCompatibilityBreakdown:"Ready {supported} / Needs setup {conditional} / Not recommended {unsupported}",workspaceDetailDebugLastAnalyzedAtLabel:"Last Check",workspaceDetailDebugTargetSourceRepo:"Scope: Repository Root",workspaceDetailDebugTargetSourceWorktree:"Scope: Current Worktree",workspaceDetailDebugRequirementsNone:"No extra setup required",workspaceDetailDebugServiceSectionDescription:"View the project one service at a time so you can tell what is ready and what still needs setup.",workspaceDetailDebugRuntimeSectionDescription:"This only shows the most recent start result so you can quickly see which service failed to come up.",workspaceDetailDebugMatrixSectionDescription:"This section explains the default support level for each detected service type.",workspaceDetailDebugMatrixTitle:"Support Guidance",workspaceDetailDebugMatrixOpenAction:"Open Support Matrix",workspaceDetailDebugMatrixModalDescription:"Use a real matrix table so people can scan support rules without reading a wall of cards.",workspaceDetailDebugMatrixFrameworkHeader:"Framework",workspaceDetailDebugMatrixCompatibilityHeader:"Support",workspaceDetailDebugMatrixInjectionHeader:"Mode",workspaceDetailDebugMatrixDiscoveryHeader:"Discovery",workspaceDetailDebugMatrixHmrHeader:"HMR",workspaceDetailDebugMatrixCallbackHeader:"Callback",workspaceDetailDebugMatrixAiHeader:"Manual",workspaceDetailDebugMatrixNotesHeader:"Notes",workspaceDetailDebugMatrixCompatibilitySupportedShort:"Ready",workspaceDetailDebugMatrixCompatibilityConditionalShort:"Needs Setup",workspaceDetailDebugMatrixCompatibilityUnsupportedShort:"Avoid",workspaceDetailDebugMatrixCompatibilityUnknownShort:"Unknown",workspaceDetailDebugMatrixInjectionCliShort:"CLI",workspaceDetailDebugMatrixInjectionEnvShort:"ENV",workspaceDetailDebugMatrixInjectionOverrideShort:"CMD",workspaceDetailDebugMatrixInjectionAiFallbackShort:"Manual",workspaceDetailDebugMatrixInjectionNoneShort:"None",workspaceDetailDebugMatrixRequirementRequiredShort:"Needs Work",workspaceDetailDebugMatrixRequirementNotRequiredShort:"Not Needed",workspaceDetailDebugMatrixAiNeverShort:"Do Not Use",workspaceDetailDebugMatrixAiConditionalShort:"Conditional",workspaceDetailDebugMatrixAiAllowedShort:"Allowed",workspaceDetailDebugMatrixLegendSummary:"Icon meanings: check means the default path is clear, warning means you still need setup, and cross means this path is not recommended for automatic handling yet.",workspaceDetailDebugMatrixDiscoveryNote:"Service address handling such as proxy, rewrites, and discovery.",workspaceDetailDebugMatrixHmrNote:"Hot reload and other long-lived frontend dev connections.",workspaceDetailDebugMatrixCallbackNote:"Callback-style entries such as OAuth, login callback, or webhook.",workspaceDetailDebugMatrixAiNote:"Whether edge cases are allowed to fall back to manual help.",workspaceDetailDebugActionAnalyze:"Reanalyze",workspaceDetailDebugActionPlan:"Create Plan",workspaceDetailDebugActionRun:"Start Services",workspaceDetailDebugActionRefresh:"Refresh Status",workspaceDetailDebugActionAnalyzing:"Analyzing…",workspaceDetailDebugActionPlanning:"Creating…",workspaceDetailDebugActionRunning:"Starting…",workspaceDetailDebugActionRefreshing:"Refreshing…",workspaceDetailDebugActionAnalyzeSuccess:"Service analysis has been refreshed",workspaceDetailDebugActionPlanSuccess:"Launch plan created",workspaceDetailDebugActionRunSuccess:"Start command was dispatched and the latest runtime is being refreshed",workspaceDetailDebugActionRefreshSuccess:"Status refreshed",workspaceDetailDebugActionWorkspaceMissing:"The current workspace information is incomplete, so this action cannot run yet.",workspaceDetailDebugActionTargetMissing:"No usable debug target is available yet. Finish analysis first.",workspaceDetailDebugActionAnalyzeFailed:"Failed to refresh analysis",workspaceDetailDebugActionPlanFailed:"Failed to create the launch plan",workspaceDetailDebugActionRunFailed:"Failed to start services",workspaceDetailDebugActionRefreshFailed:"Failed to refresh runtime",workspaceDetailDebugLaunchPlanTitle:"Launch Plan",workspaceDetailDebugLaunchPlanDescription:"View the current plan.",workspaceDetailRegisteredDebugLaunchPlanDescription:"Shows the latest plan.",workspaceDetailRegisteredDebugLaunchPlanGeneratedAtLabel:"Time",workspaceDetailRegisteredDebugLaunchPlanRunnableLabel:"Ready",workspaceDetailRegisteredDebugLaunchPlanOrchestratedLabel:"Adjust",workspaceDetailRegisteredDebugLaunchPlanBlockedLabel:"Blocked",workspaceDetailRegisteredDebugLaunchPlanNote:"Built from current settings.",workspaceDetailDebugLaunchPlanRuntimeIdLabel:"Preparation Record",workspaceDetailDebugLaunchPlanAutoStartLabel:"Result",workspaceDetailDebugLaunchPlanAutoStartAllowed:"Ready to run",workspaceDetailDebugLaunchPlanAutoStartBlocked:"Needs attention",workspaceDetailDebugLaunchPlanSideEffectNote:"Note: “Check Launch Plan” is not a pure preview right now. The backend will create a preparation record.",workspaceDetailDebugLaunchPlanServicePortLabel:"Planned Port",workspaceDetailDebugLaunchPlanServiceAdapterLabel:"Handling Mode",workspaceDetailDebugLaunchPlanServiceFailureLabel:"Blocked At",workspaceDetailDebugLaunchPlanServiceRequirementsLabel:"Missing Requirements",workspaceDetailDebugLaunchPlanServiceAttemptsLabel:"Resolution Chain",workspaceDetailDebugLaunchPlanServiceAiLabel:"Manual Fallback",workspaceDetailDebugLaunchPlanServiceAllowedFilesLabel:"Allowed Files",workspaceDetailDebugLaunchPlanServiceNoRequirements:"No extra blocking requirement right now",workspaceDetailDebugLaunchPlanServiceNoEnvPatch:"No additional environment patch",workspaceDetailDebugLaunchPlanServiceEnvPatchLabel:"Environment Patch",workspaceDetailDebugLaunchPlanDismissAction:"Clear Plan",workspaceDetailDebugFailureStageServiceDiscovery:"Still needs service address handling",workspaceDetailDebugFailureStageHmr:"Still needs hot reload handling",workspaceDetailDebugFailureStageCallback:"Still needs callback handling",workspaceDetailDebugFailureStageAiFallbackRequired:"Needs manual review",workspaceDetailDebugFailureStageAdapterSelection:"No suitable start method was found",workspaceDetailDebugFailureStageLaunchRequirements:"Some launch requirements are still missing",workspaceDetailDebugFailureStageCommandExecution:"The start command did not run correctly",workspaceDetailDebugFailureStageProcessExit:"The service exited right after start",workspaceDetailDebugFailureStageProcessRuntimeError:"The service hit a runtime error",workspaceDetailDebugFailureStageStaleRuntimeBinding:"This start record is no longer valid",workspaceDetailDebugFailureStageUnknown:"Unknown stage ({code})",workspaceDetailDebugBindingAllocated:"Assigned",workspaceDetailDebugBindingListening:"Reachable",workspaceDetailDebugBindingFailed:"Not Ready",workspaceDetailDebugBindingReleased:"Released",workspaceDetailDebugBindingUnknown:"Unknown",workspaceDetailDebugProcessCreating:"Starting",workspaceDetailDebugProcessRunning:"Running",workspaceDetailDebugProcessClosed:"Stopped",workspaceDetailDebugProcessError:"Error",workspaceDetailDebugProcessUnknown:"Unknown",workspaceDetailDebugPortEmpty:"None",workspaceDetailRegisteredDebugTemplatePortMissing:"Not Set",workspaceDetailRegisteredDebugTemplatePathLabel:"Registered Path",workspaceDetailRegisteredDebugTemplatePortLabel:"Port",workspaceDetailRegisteredDebugTemplateRuntimeTypeLabel:"Runtime",workspaceDetailRegisteredDebugTemplateSourceLabel:"Source",workspaceDetailRegisteredDebugTemplateSourceManual:"Manual",workspaceDetailRegisteredDebugTemplateSourceDebugService:"Auto",workspaceDetailRegisteredDebugTemplateSourceManaged:"Generated by System",workspaceDetailRegisteredDebugTemplateProxyLabel:"Proxy",workspaceDetailRegisteredDebugTemplateProxyEnabled:"Enabled",workspaceDetailRegisteredDebugTemplateProxyDisabled:"Disabled",workspaceDetailRegisteredDebugTemplateInjectionModeLabel:"Port Injection",workspaceDetailRegisteredDebugTemplateInjectionModeUnknown:"Not Marked",workspaceDetailRegisteredDebugTemplateServiceDiscoveryLabel:"Service Address Sync",workspaceDetailRegisteredDebugTemplateServiceDiscoverySameOrigin:"Same Origin",workspaceDetailRegisteredDebugTemplateServiceDiscoveryApiBaseUrl:"Inject API_BASE_URL",workspaceDetailRegisteredDebugTemplateServiceDiscoveryNone:"No Extra Handling",workspaceDetailRegisteredDebugTemplateServiceDiscoveryUnknown:"Not Marked",workspaceDetailRegisteredDebugTemplateStatusOccupied:"Busy",workspaceDetailRegisteredDebugTemplateStatusIdle:"Idle",workspaceDetailRegisteredDebugTemplateStatusUntracked:"Unknown",workspaceDetailRegisteredDebugPlanItemCommandLabel:"Command",workspaceDetailRegisteredDebugPlanItemRuntimeLabel:"Runtime",workspaceDetailRegisteredDebugPlanItemActionLabel:"Status",workspaceDetailRegisteredDebugPlanItemReasonLabel:"Reason",workspaceDetailRegisteredDebugPlanActionStart:"Start Directly",workspaceDetailRegisteredDebugPlanActionOrchestrated:"Start After Adjust",workspaceDetailRegisteredDebugPlanActionBlocked:"Cannot Start",workspaceDetailRegisteredDebugPlanReasonPortMissing:"Port is not set",workspaceDetailRegisteredDebugPlanReasonDuplicatePort:"Multiple launchers are registered with the same port, so auto-start is blocked.",workspaceDetailRegisteredDebugPlanReasonDuplicatePortWillOrchestrate:"Port conflict, a new port will be assigned",workspaceDetailRegisteredDebugPlanReasonPortOccupied:"Port is occupied",workspaceDetailRegisteredDebugPlanReasonPortOccupiedWillOrchestrate:"Port is occupied, a new port will be assigned",workspaceDetailRegisteredDebugPlanReasonPortOrchestrated:"Will switch to port {port}",workspaceDetailRegisteredDebugPlanReasonServiceDiscoveryInjected:"Address sync is ready",workspaceDetailRegisteredDebugPlanReasonAnalysisMissing:"Project analysis is missing. Refresh launchers and create the plan again.",workspaceDetailRegisteredDebugPlanReasonServiceDiscoveryMissing:"A backend launcher is required for address sync. Register it in Debug. Ports will be injected automatically.",workspaceDetailRegisteredDebugPlanReasonCallbackMissing:"This callback flow is not handled automatically yet. Confirm the startup flow manually.",workspaceDetailRegisteredDebugPlanReasonRunnable:"Ready to start",workspaceDetailRegisteredDebugLaunchPlanServiceDiscoveryHelp:"If address sync is missing, register the backend launcher in Debug. Ports are adjusted automatically at start time.",workspaceDetailRegisteredDebugRuntimeScopeNote:"Items without a port are skipped.",workspaceDetailRegisteredDebugRuntimeIdle:"Idle",workspaceDetailRegisteredDebugRuntimeUnknown:"No status",workspaceDetailRegisteredDebugRuntimeProcessLabel:"Process",workspaceDetailRegisteredDebugRuntimeCommandLabel:"Process Command Line",workspaceDetailDebugRoleFrontend:"Web Service",workspaceDetailDebugRoleBackend:"Backend Service",workspaceDetailDebugRoleWorker:"Background Worker",workspaceDetailDebugRoleMock:"Mock Service",workspaceDetailDebugRoleDesktopShell:"Desktop Shell",workspaceDetailDebugRoleCustom:"Custom",workspaceDetailDebugServiceOverviewSupported:"This service is clearly identified and is usually ready to start once you follow the recommended handling.",workspaceDetailDebugServiceOverviewConditional:"This service is identified, but still needs a few extra setup steps before it can start cleanly.",workspaceDetailDebugServiceOverviewUnsupported:"This service is not recommended for direct automatic handling yet. Confirm the start flow manually first.",workspaceDetailDebugServiceOverviewUnknown:"This service has not been identified clearly yet. The current result is kept for later review.",workspaceDetailDebugServiceOverviewDesktopShell:"This is a desktop shell service. It is shown separately and does not participate in automatic web-port handling.",workspaceDetailDebugServiceActionSupported:"Start Directly",workspaceDetailDebugServiceActionConditional:"Complete Setup First",workspaceDetailDebugServiceActionUnsupported:"Handle Manually",workspaceDetailDebugServiceActionUnknown:"Confirm Service Type First",workspaceDetailDebugServiceActionDesktopShell:"Handle as Desktop Shell",workspaceDetailDebugAiEditEmpty:"None",workspaceDetailDebugAiEditPending:"Pending",workspaceDetailDebugAiEditApplied:"Applied",workspaceDetailDebugAiEditRolledBack:"Rolled Back",workspaceDetailDebugAiEditRejected:"Rejected",workspaceSessionListBody:"Project sessions, favorites, and archive actions live here instead of hiding in a sidebar.",recentSessionsSectionTitle:"Recent Sessions",recentSessionsSectionBody:"Jump back into the work you touched most recently.",currentWorkspaceSectionTitle:"Current Project Sessions",currentWorkspaceSectionBody:"Keep the sessions for the current project together so the context stays obvious.",sessionIndexTitle:"Sessions deserve their own page",sessionIndexBody:"Recent, favorites, and current-project sessions are split into clear sections for mobile.",toolsMoreAction:"More",toolsSwipeHint:"Swipe left or right to switch between files and Git",toolsSwipePosition:"{current} / {total}",toolFilesBody:"Browse project files, changed files, and code context without relying on a desktop sidebar.",toolGitBody:"Open a clear Git entry for status, commits, and branches in the current project.",toolTerminalsBody:"Open the full terminal page for input-heavy and scroll-heavy tasks.",toolProcessesBody:"Review terminal templates, runtime status, and debug entry points for the current project.",toolsWorkspaceRequiredBody:"Pick a project before opening this tool page.",createSession:"New Session",createSessionModalTitle:"Choose Session Type",createSessionModalDescription:"Pick the session type first, then start the actual session process.",createSessionWorkspaceLabel:"Choose Workspace",createSessionProviderLabel:"Choose Provider",createSessionTarget:"Current Project",createWorktreeSectionTitle:"Child Workspace",createWorktreeSectionDescription:"Create a child workspace from the current project first, then choose the provider for the new session.",createWorktreeAction:"Add Child Workspace",createWorktreeCollapseAction:"Hide Child Workspace Form",createWorktreeBranchLabel:"Branch Name",createWorktreeBranchPlaceholder:"For example: feat/login-codex",createWorktreeBranchRequired:"Enter the child workspace branch name first.",createWorktreeBranchInvalid:"Branch names may only contain letters, numbers, -, _, and /. They cannot start or end with / or contain //.",createWorktreeDisplayNameLabel:"Display Name (Optional)",createWorktreeDisplayNamePlaceholder:"Defaults to the branch name",createWorktreeBaseRefLabel:"Create From Branch/Commit (Optional)",createWorktreeBaseRefPlaceholder:"Defaults to the current branch",createWorktreeBaseRefHint:"You can choose from {localCount} local branches, {remoteCount} remote branches, and {tagCount} tags, or enter a commit hash manually.",createWorktreeBaseRefLoading:"Loading branches and tags from the current repository...",createWorktreeBaseRefLoadFailed:"Failed to load branches and tags. You can still enter a branch, tag, or commit hash manually.",createWorktreeBaseRefLocalGroup:"Local Branches",createWorktreeBaseRefRemoteGroup:"Remote Branches",createWorktreeBaseRefTagGroup:"Tags",createWorktreeBaseRefCurrentBadge:"Current",createWorktreeBaseRefRecommendedBadge:"Recommended",createWorktreeBaseRefEmpty:"No matches found. You can still enter a branch, tag, or commit hash manually.",createWorktreeBaseRefToggle:"Show available branches and tags",createWorktreeHelpAction:"How to Fill This",createWorktreeHelpTitle:"What These Fields Mean",createWorktreeHelpBranchTitle:"Branch Name",createWorktreeHelpBranchBody:"This is the name of the new child workspace. It is also what you will see in the list later. A short name like feat/login is usually enough.",createWorktreeHelpDisplayNameTitle:"Display Name",createWorktreeHelpDisplayNameBody:"Use this if you want a clearer name in the list. If you leave it empty, the branch name will be used automatically.",createWorktreeHelpBaseRefTitle:"Create From Branch/Commit",createWorktreeHelpBaseRefBody:"This decides where the new child workspace starts from. Most of the time, you can keep the default. Only change it if you want to start from another branch, tag, or specific commit.",createWorktreeSubmit:"Create Child Workspace",createWorktreeSubmitting:"Creating...",createWorktreeSucceeded:"Child workspace created: {name}",createWorktreeFailed:"Failed to create child workspace",providerClaudeCode:"Claude Code",providerLegnaCode:"Legna Code",providerCodexDescription:"Create a Codex session for the current default workflow.",providerClaudeDescription:"Create a Claude Code session when you want to switch to another conversation chain.",providerLegnaDescription:"Create a Legna Code session that reuses the Claude-compatible runtime with an independent session store.",providerOpenCodeDescription:"Create an OpenCode session to continue context via the OpenCode service.",providerGeminiDescription:"Create a Gemini session for the native Gemini CLI workflow.",providerKimiDescription:"Create a Kimi session for the native Kimi CLI workflow.",createSessionPresetLabel:"Session Config",createSessionPresetHint:"The default follows the current global preset. Session-level presets are only available for Codex, Claude Code, and Gemini.",createSessionPresetDefault:"Use current default preset",createSessionPresetLoading:"Loading cc-switch presets...",createSessionPresetUnavailable:"cc-switch presets are unavailable right now. You can still start with the default config.",createSessionStartAction:"Open Draft Session",providerChecking:"Checking...",startClaude:"Claude",startCodex:"Codex",startingSession:"Creating...",startClaudeSuccess:"Claude session created",startCodexSuccess:"Codex session created",startSessionFailed:"Failed to create session",auxiliaryTitle:"Info",auxiliarySubtitle:"Files and Git status",expandAuxiliary:"Expand",collapseAuxiliary:"Collapse",auxiliaryEmptyTitle:"Select a session",auxiliaryEmptyBody:"Session files and Git info will appear here",batchSelectSessions:"Select Sessions in Bulk",batchSelectionMode:"Batch Selection",selectAllSessions:"Select All",clearSelectedSessions:"Clear Selection",batchArchiveAction:"Archive Selected",batchArchiving:"Archiving...",batchArchiveSuccess:"Selected sessions archived",batchArchivePartialFailed:"Some sessions failed to archive. Retry.",batchArchiveFailed:"Batch archive failed",batchDeleteAction:"Delete Selected",batchDeleting:"Deleting...",batchDeleteSuccess:"Selected sessions deleted",batchDeletePartialFailed:"Some sessions failed to delete. Retry.",batchDeleteFailed:"Batch delete failed",batchDeleteConfirmTitle:"Delete Selected Sessions",batchDeleteConfirmDescription:"The selected {count} sessions will be removed from the assistant history and workspace list, and the underlying records will be deleted permanently.",batchDeleteSelectionSummary:"{count} sessions selected",hideSessionSidebar:"Hide Session List",showSessionSidebar:"Show Session List",hideInfoSidebar:"Hide Info Sidebar",showInfoSidebar:"Show Info Sidebar",centerTabsLabel:"Center Area Tabs",infoTabsLabel:"Info Sidebar Tabs",leftResizerLabel:"Resize Left Sidebar",rightResizerLabel:"Resize Right Sidebar",filesPanelEmpty:"Import or select a workspace first to use file management.",gitPanelEmpty:"Import or select a workspace first to view Git info.",infoPanelDeferred:"The left session list loads first. The right auxiliary panel mounts slightly later."},workbench:{emptyEyebrow:"Start",emptyTitle:"Choose a session first",emptyBody:"Continue from the left, or create a new session.",emptyResumeTitle:"Continue",emptyResumeBody:"Go back to where you stopped.",emptyNewTitle:"New session",emptyNewBody:"Put a new question into a clean session.",emptyCompanionTitle:"Side details",emptyCompanionBody:"Open files, Git, or terminal on the right when needed.",emptyTip:"When you are ready, pick a session from the left."},conversation:{resendButton:"Resend",historyLoading:"Loading...",historyLoadingOlder:"Loading older messages...",historyLoadFailed:"Load failed",inheritedContextLoading:"Preparing inherited context from the parent session...",inheritedContextMessageLabel:"Inherited context before the forked message",inheritedContextSessionLabel:"Inherited context from the parent session",inheritedContextSummary:'Collapsed {count} inherited messages from "{parentTitle}" by default.',actionInheritedSelectionSummary:'Collapsed the selected text from "{parentTitle}" by default.',inheritedContextExpand:"Show inherited context",inheritedContextCollapse:"Hide inherited context",inheritedContextParentFallback:"Parent session",timelineEmpty:"Start Conversation",composerPlaceholder:"State the next step clearly. Let the session continue from there.",sendButton:"Send Message",attachFiles:"Attach File",attachmentSourceSheetTitle:"Add Files",attachmentSourceSheetDescription:"Choose one or more files from the system picker, or capture a photo.",attachmentTakePhoto:"Take Photo",attachmentTakePhotoHint:"Open the camera and attach a new photo",attachmentChooseFromLibrary:"Choose Files",attachmentChooseFromLibraryHint:"Open the system file picker and add one or more files",pasteImagesHint:"Supports pasting files directly",attachmentImageOnly:"Only image attachments are supported right now",attachmentReadFailed:"Failed to read attachment. Retry.",attachmentPreviewAlt:"Selected image preview",attachmentPreviewOpen:"Open attachment",attachmentPreviewClose:"Close preview",attachmentPreviewLoading:"Loading attachment...",attachmentPreviewUnavailable:"Attachment unavailable",attachmentDownload:"Download attachment",toolWebSearch:"Web search",toolWebSearchQueryLabel:"Query",toolWebSearchSourcesLabel:"Sources",toolWebSearchUntitledSource:"Untitled source",attachmentDropHint:"Drop files here to attach them",imageAttachmentLabel:"Image Attachment",fileAttachmentLabel:"File Attachment",imagePreviewTitle:"Image Preview",imagePreviewHint:"Click the backdrop or press Esc to close the preview",removeAttachment:"Remove Attachment",selectionTodoAction:"Todo",selectionActionButton:"Action",selectionActionSubmit:"Open action child session",selectionActionPromptLabel:"What should it do",selectionActionPromptPlaceholder:"For example: explain this, turn it into notes, or send it to a specific API",selectionActionIncludeContext:"Include current context",selectionActionContextUnavailable:"This selection spans multiple messages, so context inheritance is disabled for safety.",selectionActionDefaultPrompt:"Please process this content.",selectionActionPreviewLabel:"Selected content",selectionActionTargetLabel:"New session settings",selectionActionQuotedLabel:"Selected text",selectionActionFailed:"Failed to create the action child session.",actionSessionBadge:"Action",modelSelectorLabel:"Model",modelUseCliDefault:"Default",deploymentDefaultPreset:"Default",deploymentConfigColumn:"Config",deploymentModelColumn:"Model",deploymentLoading:"Loading deployments...",deploymentModelLoading:"Loading models...",deploymentModelEmpty:"No models are available for this config yet.",modelUseCodexConfig:"Follow current Codex config",modelUseOpenCodeConfig:"Follow current OpenCode config",reasoningSelectorLabel:"Reasoning Effort",reasoningLow:"Low",reasoningMedium:"Medium",reasoningHigh:"High",reasoningMaximum:"Maximum",slashMenu:"Commands",slashMenuTitle:"Quick Commands",slashCommandPlan:"Ask for an execution plan first",slashCommandReview:"Switch directly to code review mode",slashCommandExplain:"Ask for a clearer explanation",toolInputLabel:"Input",toolResultLabel:"Result",toolResultEmpty:"No output yet",toolPreviewCommand:"Command",toolPreviewTerminal:"Terminal",toolViewImageActiveLabel:"AI is viewing an image",toolStatusRunning:"Running",toolStatusFailed:"Failed",toolStatusCompleted:"Completed",runtimeThinkingPlaceholder:"{provider} is thinking...",applyPatchEditedLabel:"Edited",applyPatchAddedLabel:"Added",applyPatchDeletedLabel:"Deleted",applyPatchDialogTitle:"Patch Change Preview",applyPatchDialogDescription:"This shows the file-level changes that apply_patch is about to perform.",applyPatchOpenDiff:"View Diff",applyPatchEditedStat:"Edited",applyPatchAddedStat:"Added",applyPatchRemovedStat:"Removed",applyPatchEmpty:"This patch does not contain any file change that can be displayed right now.",titleFallback:"Continue Conversation",draftTitleCodex:"New Codex session",draftTitleClaude:"New Claude Code session",draftTitleLegna:"New LegnaCode session",draftTitleOpenCode:"New OpenCode session",draftTitleGemini:"New Gemini session",draftTitleKimi:"New Kimi session",headerWorkspace:"Workspace",headerWorkspaceUnknown:"Unknown Workspace",headerProvider:"Provider",headerConnection:"Connection",headerRuntime:"Runtime",providerCodex:"Codex",branchTreeAction:"Branch Tree",branchTreeTitle:"Branch Tree",branchTreeDescription:"This panel only shows the parent-child chain around the current session.",branchTreeUpstreamLabel:"Upstream Chain",branchTreeCurrentLabel:"Current Session",branchTreeChildrenLabel:"Child Branches",branchTreeCurrentBadge:"Current",branchTreeArchivedBadge:"Archived",branchTreeEmpty:"This session does not have any child branches yet.",branchTreeMapTitle:"Branch Map",branchTreeMapDescription:"This view expands the full branch family around the current session.",branchTreePreviewTitle:"Session Preview",branchTreePreviewDescription:"Click a node to float its latest messages before switching.",branchTreePreviewLoading:"Loading recent messages for this session...",branchTreePreviewFailed:"Failed to load the session preview.",branchTreePreviewEmpty:"There are no recent messages to preview for this session.",branchTreeResizeHandle:"Resize branch tree width",branchTreeZoomInAction:"Zoom in branch map",branchTreeZoomOutAction:"Zoom out branch map",branchTreeZoomResetAction:"Reset branch map zoom",branchTreeSwitchAction:"Switch to This Session",branchTreeCurrentAction:"Already Current",branchTreeToolMessageFallback:"tool message",branchTreeMessageEmpty:"This message does not have visible text.",moreSessionActions:"More session actions",branchAction:"Branch",moreSessionActionsTitle:"More Session Actions",moreSessionActionsDescription:"Branch navigation and assistant actions live here so the mobile header stays clean.",branchTreeTab:"Branch Tree",aiAssistantTab:"Assistant",aiAssistantTabDescription:"Use the assistant entry here when you want to continue follow-up or start verification for this session.",providerClaude:"Claude",providerLegna:"Legna",providerOpenCode:"OpenCode",providerGemini:"Gemini",providerKimi:"Kimi",capabilitySend:"Send Enabled",queueTitle:"Queued Messages",queueDescription:"After the current run finishes, these messages will be processed automatically in order.",queueOrderPrefix:"Queue Position",queueStatusQueued:"Queued",queueStatusFailed:"Dispatch Failed",queueDelete:"Delete",queueDeleting:"Deleting",permissionRequestSectionTitle:"Pending approvals",permissionRequestSectionDescription:"Provider-side approvals are unified here so you do not need to learn three different dialogs.",permissionRequestToastTitle:"Approval needed",backgroundPermissionToastDescription:"{title} · {requestTitle}",backgroundCompletionToastTitle:"Session completed",backgroundCompletionToastDescription:"{title}",backgroundFailureToastTitle:"Session failed",backgroundFailureToastDescription:"{title} · {detail}",permissionRequestReplyFailed:"Failed to reply to the approval request.",permissionRequestSubmitting:"Submitting...",permissionRequestReasonLabel:"Reason",permissionRequestCommandLabel:"Command",permissionRequestToolLabel:"Tool",permissionRequestCwdLabel:"Working directory",permissionRequestPathsLabel:"Related paths",permissionRequestPermissionsLabel:"Requested permissions",permissionRequestReadLabel:"Read",permissionRequestWriteLabel:"Write",permissionRequestNetworkLabel:"Network",permissionRequestQuestionsLabel:"Questions",permissionRequestDetailLabel:"Details",permissionRequestEmpty:"None",permissionRequestUnknown:"Unknown",permissionRequestKindCommand:"Command",permissionRequestKindFileChange:"File Change",permissionRequestKindPermissions:"Permissions",permissionRequestKindUserInput:"User Input",permissionRequestKindToolCall:"Tool Call",queueImageOnly:"Image attachments only",sendGuidanceButton:"Add Guidance",queueGuidanceButton:"Queue Guidance",capabilityDenied:"Restricted",capabilitySendDisabled:"Sending disabled",connectionConnected:"Realtime connected",connectionReconnecting:"Reconnecting",connectionReconnectFailed:"Reconnect failed",connectionClosed:"Connection closed",runtimeIdle:"Idle",runtimeStarting:"Starting",runtimeRunning:"Running",runtimeReconnecting:"Recovering",runtimeStale:"Awaiting confirmation",runtimeUnknown:"Status pending",runtimeCompleted:"Completed",runtimeInterrupted:"Interrupted",runtimeFailed:"Failed",rulesMessageTitle:"Rules",rulesMessageHint:"This is the startup rule block for the session. It is collapsed by default and can be expanded when needed.",rulesMessageExpand:"Expand Rules",rulesMessageCollapse:"Collapse Rules",skillContextTitle:"Assistant Skill",skillContextHint:"This is the Skill context injected at Claude Code session startup. It is collapsed by default and can be expanded when needed.",skillContextExpand:"Expand Skill",skillContextCollapse:"Collapse Skill",systemPromptTitle:"System Prompt",systemPromptHint:"This is the Kimi startup system prompt for the session. It is collapsed by default and can be expanded when needed.",systemPromptExpand:"Expand Prompt",systemPromptCollapse:"Collapse Prompt",taskProgressButton:"Task Progress ({count})",taskProgressModalTitle:"Task Progress",taskProgressModalDescription:"This session has recorded {count} tasks. Check the latest progress here.",taskProgressExplanationTitle:"Latest Update Note",taskProgressSummaryTotal:"Total",taskProgressStatusPending:"Pending",taskProgressStatusInProgress:"In Progress",taskProgressStatusCompleted:"Completed",taskProgressStatusFailed:"Failed",taskProgressStatusCancelled:"Cancelled",taskCardPlanTitle:"Plan Update",taskCardTodoTitle:"Task Update",taskCardPlanUpdated:"Latest Plan",taskCardTodoUpdated:"Latest Task List",taskCardRawExpand:"Show Raw Call",taskCardRawCollapse:"Hide Raw Call",taskCardSummaryTotal:"{count} total",taskCardSummaryInProgress:"{count} in progress",taskCardSummaryPending:"{count} pending",taskCardSummaryCompleted:"{count} completed",taskCardSummaryFailed:"{count} failed",butlerActionButton:"Assistant",butlerActionModalTitle:"Butler Actions",butlerActionModalDescription:"Ask Butler to continue this development session or start a development verification run.",butlerActionLoading:"Loading Butler action context...",butlerActionLoadFailed:"Failed to load Butler action context",butlerActionProjectLabel:"Project",butlerActionSessionLabel:"Session",butlerFollowUpAction:"Continue Follow-up",butlerFollowUpActionDescription:"Let Butler keep watching this session and continue pushing it after each stop or blocker.",butlerFollowUpProviderLabel:"Follow-up Assistant",butlerFollowUpProviderHint:"Choose which CLI-backed assistant should own this follow-up session. Later rounds reuse the same visible assistant session.",butlerFollowUpObjectiveLabel:"Follow-up Goal",butlerFollowUpObjectivePlaceholder:"Example: finish this feature for me; if the spec still has unfinished work, keep going.",butlerFollowUpCompletionCriteriaLabel:"Finish Conditions",butlerFollowUpCompletionCriteriaPlaceholder:"Example: only stop once the current feature is finished against the agreed requirements.",butlerFollowUpCompletionCriteriaRequired:"Choose or write an explicit stop condition first so Butler knows exactly when to stop",butlerCompletionTemplateSectionLabel:"Stop Templates",butlerCompletionTemplateSectionHint:"Pick one explicit template. It replaces the stop condition and must still stop when the round limit is reached.",butlerCompletionTemplateRecommendedLabel:"Standard Finish",butlerCompletionTemplateRecommendedDescription:"Stop after the feature is done and verified",butlerCompletionTemplateRecommendedValue:"Stop only when the current feature is complete for this request, one development verification or manual confirmation has finished, and there is no blocking item that must still be pushed forward; if the next step recommended by AI is not required for the core goal, it must also stop; once the auto-continue round limit is reached, it must also stop and must not keep extending the session.",butlerCompletionTemplateSpecLabel:"Spec Wrap-up",butlerCompletionTemplateSpecDescription:"Finish the must-do items in the current spec",butlerCompletionTemplateSpecValue:"Stop only when the must-do tasks in the current spec are complete, the related code, docs, and required verification are all in place, and there is no blocking item that still must be pushed forward; if the next step recommended by AI is not required for the core goal, it must also stop; do not expand into new scope; once the auto-continue round limit is reached, it must also stop.",butlerCompletionTemplateBugfixLabel:"Bug Fix",butlerCompletionTemplateBugfixDescription:"Fix the issue and confirm there is no high-priority regression",butlerCompletionTemplateBugfixValue:"Stop only when this issue has been diagnosed and fixed, the related verification has passed, and there is no new high-priority regression that needs immediate work; if the next step recommended by AI is not required for the core goal, it must also stop; follow-up ideas and optimizations are not valid reasons to keep pushing; once the auto-continue round limit is reached, it must also stop.",butlerFollowUpRoundLimitLabel:"Max Auto Follow-up Rounds",butlerFollowUpRoundLimitHint:"Once the limit is reached, Butler stops auto-resuming so the session does not expand forever.",butlerCurrentFollowUpLabel:"Current Follow-up",butlerCurrentFollowUpProgress:"Auto-continued {current} / {max} rounds",butlerFollowUpStopping:"Stopping follow-up...",butlerStopFollowUpAction:"Stop Current Follow-up",butlerFollowUpObjectiveRequired:"Please describe the goal you want Butler to keep pushing",butlerCurrentVerificationLabel:"Current Verification",butlerStopVerificationAction:"Stop Current Verification",butlerVerificationAction:"Start Verification",butlerVerificationActionDescription:"Let Butler start a user-facing verification run for the feature behind this session.",butlerFollowUpStarted:"Butler follow-up started",butlerFollowUpStartedDescription:"Butler will continue following the current development session for {projectName}.",butlerFollowUpFailed:"Failed to start Butler follow-up",butlerFollowUpStopped:"Current Butler follow-up stopped",butlerFollowUpStoppedDescription:"Automatic follow-up for the current session has been stopped and will not auto-resume.",butlerFollowUpStopFailed:"Failed to stop Butler follow-up",butlerVerificationStarted:"Development verification started",butlerVerificationStartedDescription:"Butler will start a development verification run for {projectName}.",butlerVerificationFailed:"Failed to start development verification",butlerVerificationStopping:"Stopping verification...",butlerVerificationStopped:"Current development verification stopped",butlerVerificationStoppedDescription:"The current verification has been stopped, and the linked automation has been ended as well.",butlerVerificationStopFailed:"Failed to stop development verification",butlerAnalysisTitle:"Butler Analysis",butlerAnalysisLoadFailed:"Failed to load Butler analysis",butlerAnalysisObjectiveLabel:"Objective",butlerAnalysisStatusLabel:"Decision",butlerAnalysisSummaryLabel:"Latest analysis",butlerAnalysisWaitingReasonLabel:"Waiting reason",butlerAnalysisEmpty:"There is no Butler analysis record yet.",butlerProxyMessageBadge:"Sent by Butler",butlerOriginDetailTitle:"Related Butler Follow-up",butlerOriginDetailLoading:"Loading the related Butler follow-up...",butlerOriginDetailLoadFailed:"Failed to load the related Butler follow-up",butlerOriginDetailObjectiveLabel:"Objective",butlerOriginDetailStatusLabel:"Status",butlerOriginDetailSummaryLabel:"Latest analysis",butlerOriginDetailWaitingReasonLabel:"Waiting reason",assistantCapabilityBadgeSession:"Assistant Session",assistantCapabilityBadgeAutomation:"Assistant Automation",assistantCapabilityBadgeTerminal:"Assistant Terminal",assistantCapabilityBadgeWorkspace:"Assistant Workspace",assistantCapabilityBadgeDebug:"Assistant Debug",assistantCapabilityBadgeQuery:"Assistant Query",assistantCapabilityBadgeSubAgent:"Sub-agent",assistantCapabilityProjectSessionStartTitle:"Create Session",assistantCapabilitySessionSendTitle:"Send Message",assistantCapabilitySessionForkTitle:"Fork Session",assistantCapabilityTimerCreateTitle:"Create Automation",assistantCapabilityTimerCancelTitle:"Cancel Automation",assistantCapabilityTerminalInputTitle:"Send Terminal Input",assistantCapabilityTerminalCloseTitle:"Close Terminal",assistantCapabilityWorkspaceDirectoryCreateTitle:"Create Directory",assistantCapabilityWorkspaceImportTitle:"Import Workspace",assistantCapabilityWorkspaceCloneTitle:"Clone Workspace",assistantCapabilityWorkspaceNavigationUpdateTitle:"Update Workspace View",assistantCapabilityWorkspaceRemoveTitle:"Remove Workspace",assistantCapabilityWorktreeCreateTitle:"Create Worktree",assistantCapabilityWorktreeMergeTitle:"Merge Worktree",assistantCapabilityWorktreeCleanupTitle:"Clean Up Worktree",assistantCapabilityDebugRunTitle:"Start Debug Run",assistantCapabilitySessionReadTitle:"Read Session Info",assistantCapabilityAutomationReadTitle:"Read Automation Info",assistantCapabilityTerminalReadTitle:"Read Terminal Info",assistantCapabilityWorkspaceReadTitle:"Read Workspace Info",assistantCapabilityDebugReadTitle:"Read Debug Info",assistantCapabilityQueryTitle:"Assistant Action",codexAgentToolCreateTitle:"Create Sub-agent",codexAgentToolReadTitle:"Read Sub-agent",codexAgentToolUpdateTitle:"Update Sub-agent",codexAgentToolReplyTitle:"Reply to Sub-agent",codexAgentToolCloseTitle:"Close Sub-agent",assistantCapabilitySummarySessionStart:"A real session was created with the current assistant settings.",assistantCapabilitySummarySessionSend:"The message was submitted to the target real session.",assistantCapabilitySummarySessionFork:"A new session was forked from the current context.",assistantCapabilitySummaryTimerCreate:"A follow-up automation was created.",assistantCapabilitySummaryTimerCancel:"The pending follow-up automation was cancelled.",assistantCapabilitySummaryTerminalInput:"Input was sent to the target terminal.",assistantCapabilitySummaryTerminalClose:"The target terminal was closed.",assistantCapabilitySummaryWorkspace:"The workspace action has been executed.",assistantCapabilitySummaryWorktree:"The worktree action has been executed.",assistantCapabilitySummaryDebug:"The debug action has been triggered.",assistantCapabilitySummaryRead:"The assistant finished this read operation.",codexAgentToolCreateSummary:"A separate task was delegated to a sub-agent.",codexAgentToolReadSummary:"Reading the latest sub-agent status and response.",codexAgentToolUpdateSummary:"The sub-agent task was redirected or updated.",codexAgentToolReplySummary:"A follow-up message was sent to the sub-agent.",codexAgentToolCloseSummary:"This sub-agent session was closed.",assistantCliSummaryHelp:"The matching assistant help command has been queried.",assistantCliSummaryCommand:"The assistant command has been issued.",assistantCliHelpRootTitle:"View Assistant Help",assistantCliHelpSessionsTitle:"View Session Help",assistantCliHelpSessionActionTitle:"View Session Action Help: {action}",assistantCliHelpTimersTitle:"View Automation Help",assistantCliHelpTerminalsTitle:"View Terminal Help",assistantCliHelpWorkspacesTitle:"View Workspace Help",assistantCliHelpGenericTitle:"View {group} Help",assistantCapabilityRawExpand:"View Raw",assistantCapabilityRawCollapse:"Hide Raw",assistantCapabilityLabelWorkspace:"Workspace",assistantCapabilityLabelSession:"Session",assistantCapabilityLabelTerminal:"Terminal",assistantCapabilityLabelTimer:"Automation",assistantCapabilityLabelProvider:"Provider",assistantCapabilityLabelDueAt:"Time",assistantCapabilityLabelStatus:"Status",assistantCapabilityLabelPath:"Path",assistantCapabilityLabelBranch:"Branch",assistantCapabilityLabelRuntime:"Runtime",assistantCapabilityLabelCount:"Count",assistantCapabilityLabelDebugTarget:"Debug Target",codexAgentToolLabelAgent:"Agent",codexAgentToolLabelNickname:"Nickname",codexAgentToolLabelRole:"Type",codexAgentToolLabelModel:"Model",codexAgentToolLabelTargets:"Targets",codexAgentToolLabelTimeout:"Wait",codexAgentToolLabelMessage:"Message",codexAgentToolLabelReason:"Result",subagentNotificationTitle:"Sub-agent Report",subagentNotificationSummary:"The sub-agent returned the task result.",subagentNotificationLabelSummary:"Summary",subagentNotificationStatusCancelled:"Cancelled",assistantCliLabelScope:"Scope",assistantCliLabelAction:"Action",assistantCliLabelProject:"Project",assistantCliLabelMessage:"Message",assistantCliLabelInput:"Input",assistantCliLabelDelay:"Delay",assistantCliScopeRoot:"Root Command",assistantCapabilityNavigationCollapsed:"Collapsed",assistantCapabilityNavigationExpanded:"Expanded",assistantCapabilityStatusActive:"Active",assistantCapabilityStatusCompleted:"Completed",assistantCapabilityStatusCancelled:"Cancelled",assistantCapabilityStatusFailed:"Failed",thinkingLabel:"Thinking",filePanelWorkspaceTab:"Workspace",filePanelSessionTab:"Session",filePanelSessionViewLabel:"Session File View",filePanelSessionTreeView:"Tree",filePanelSessionListView:"List",filePanelSessionLoading:"Collecting files changed in this session...",filePanelSessionEmpty:"No cacheable changed files have been detected in this session yet.",filePanelSessionNoSession:"Only the workspace is selected right now. Pick a session before viewing session-scoped files.",filePanelSessionStageAll:"Stage All",filePanelSessionStageSuccess:"Changes from this session have been added to the staging area.",filePanelSessionLoadFailed:"Failed to load changed files for this session.",filePanelSessionSummary:"Detected Files",filePanelSessionUnstagedSummary:"Unstaged",filePanelSessionDeleted:"Deleted",filePanelOpenExternalWindow:"Open in New Window",filePanelOpenExternalFailed:"Failed to open the file window externally."},desktopWindow:{invalidWindowId:"The external window is missing a window id.",loadDescriptorFailed:"Failed to load the window descriptor.",unsupportedKind:"Rendering the {kind} window is not supported yet.",invalidFilePreviewTarget:"The file preview window is missing its file target.",invalidAffairsTarget:"The affairs window is missing its workspace target.",invalidCodeTarget:"The code window is missing its route target."},git:{recentVersionsTitle:"Recent Versions",stagedChangesTitle:"Staged Changes",expandRecentVersions:"Expand Recent Versions",collapseRecentVersions:"Collapse Recent Versions",stagedLabel:"Staged",workingTreeLabel:"Working Tree",changeTreeHint:"Show current changes by directory hierarchy",discard:"Discard Changes",discardFailed:"Failed to discard changes",operationMenu:"Actions",currentBranch:"Current Branch",resizePanels:"Resize file and recent-version panels",switchBranchTo:"Switch To",undoLastCommit:"Undo Last Commit",undoLastCommitFailed:"Failed to undo last commit",undoLastCommitSuccess:"Last commit undone",historyKindLocal:"Local",historyKindRemote:"Remote",historyKindShared:"Synced",pushNow:"Push",commitNow:"Commit",refreshNow:"Refresh",openExternalWindow:"Open Git in New Window",openExternalFailed:"Failed to open the Git window externally.",stageAll:"Stage All",unstageAll:"Unstage All",discardAll:"Discard All Changes",selectedFiles:"Selected Files",clearSelection:"Clear Selection",selectFile:"Select File",discardConfirm:"Discard these changes? {path}",historyItemMenu:"Commit Actions",copyCommitHash:"Copy Commit Hash",copyCommitHashSuccess:"Commit hash copied.",copyCommitSubject:"Copy Commit Title",copyCommitSubjectSuccess:"Commit title copied."},terminalManager:{workspaceField:"Current Workspace",refresh:"Refresh List",loadFailed:"Failed to load the terminal management panel",shellLoadFailed:"Failed to load the terminal shell list",emptyWorkspaceBody:"There is no available workspace yet.",noCurrentWorkspaceBody:"Select a session first so process management can bind to its workspace.",emptyTerminalBody:"There is no terminal instance in the current workspace yet.",emptyTemplateBody:"There is no quick launch item yet. Save a command or script first.",shellField:"Shell for New Terminal",shellUnavailable:"Unavailable",cwdField:"Startup Directory",cwdLabel:"Directory",cwdPlaceholder:"Defaults to the workspace root when left empty",modeField:"Launch Mode",commandMode:"Command",scriptMode:"Script",quickLaunchDescription:"Save a launch preset here so you can start it in a new terminal with one click later.",desktopPanelDescription:"Keep the default view focused on launch decisions, while paths and command lines stay inside the details layer.",openExternalWindow:"Open in New Window",openExternalFailed:"Failed to open the process management window externally.",runningCountLabel:"Running",portWatchCountLabel:"Watched Ports",terminalCountLabel:"Terminals",templateSectionTitle:"Launch Items",templateSectionDescription:"The right side prioritizes the port status of launch items so you can see whether a service is already in use.",openWorkspaceDebugAction:"Debug Services",openCreateModalAction:"Add Quick Launch Item",createModalTitle:"Add Quick Launch Item",createModalDescription:"Save a command or script here. You can attach a port and then start it with one click while checking whether it is already running.",editAction:"Edit Launch Item",editModalTitle:"Edit Quick Launch Item",editModalDescription:"Update the name, command, directory, and port for this quick launch item.",saveTemplateChangesAction:"Save Changes",templateUpdating:"Saving changes...",templateUpdateSuccess:"Quick launch item updated.",templateUpdateFailed:"Failed to update quick launch item",removeAction:"Remove Launch Item",templateRemoving:"Removing...",removeConfirmTitle:"Remove Quick Launch Item",removeConfirmAction:"Remove Item",removeConfirmTarget:'Remove "{name}"? It will disappear from the quick launch list after removal.',removeRunningConfirmTarget:'"{name}" is still running. Removing it only deletes the launch item configuration and will not stop the active process. Continue?',templateDeleteSuccess:"Quick launch item removed.",templateDeleteFailed:"Failed to remove quick launch item",terminalSectionTitle:"Terminal Instances",terminalSectionDescription:"This area shows terminals currently managed by CodingNS for the workspace.",closeAction:"Close Terminal",closing:"Closing...",closeSuccess:"Terminal close request submitted.",closeFailed:"Failed to close terminal",createTerminalAction:"New Empty Terminal",creatingTerminal:"Creating...",createTerminalSuccess:"New terminal created.",createTerminalFailed:"Failed to create a new terminal",defaultTerminalName:"Workspace Terminal",templateNameField:"Name",templateNamePlaceholder:"Generated automatically when left empty",commandField:"Launch Command",commandPlaceholder:"For example: npm",scriptPathField:"Script Path",scriptPathPlaceholder:"For example: scripts/dev.ps1 or scripts/dev.sh",argsField:"Arguments",argsPlaceholder:"For example: run dev or --watch",portField:"Listening Port",portLabel:"Port",portPlaceholder:"For example: 3000",proxyField:"Reverse Proxy",proxyToggleLabel:"Enable Reverse Proxy",proxyEnabled:"Proxy Enabled",proxyEnabledDescription:"When enabled, the system generates a random URL code and exposes your dev service under /proxy/.",proxyDisabledDescription:"Reverse proxy is disabled",proxyPortRequired:"A listening port is required when reverse proxy is enabled",openProxyUrlAction:"Open Proxy URL",openProxyUrlFailed:"Failed to open proxy URL",invalidPort:"Port must be an integer between 1 and 65535",saveLaunchAction:"Save as Quick Launch",templateSaving:"Saving...",templateSaveSuccess:"Quick launch item saved.",templateSaveFailed:"Failed to save quick launch item",runTemplateAction:"Run in New Terminal",runningTemplate:"Starting...",templateRunSuccess:"Quick launch item sent to a new terminal.",templateRunFailed:"Failed to run quick launch item",showDetailsAction:"Show details",hideDetailsAction:"Hide details",detailsSectionTitle:"Launch item details",commandPreviewLabel:"Launch Command",processIdLabel:"Listener PID",processGroupIdLabel:"Process Group PGID",processCommandLabel:"Listener Command Line",parentProcessIdLabel:"Parent PID",parentProcessCommandLabel:"Parent Command Line",terminationScopeLabel:"Stop Scope",terminationScopeProcess:"Listener only",terminationScopeProcessGroup:"Whole process group",stopProcessAction:"Stop Process",stoppingProcess:"Stopping...",stopProcessSuccess:"The listening process or its process group has been stopped.",stopProcessFailed:"Failed to stop the listening process or process group",defaultCommandName:"New Launch Command",defaultScriptName:"New Launch Script",lastActiveAt:"Last Active",updatedAt:"Updated At",processCommandFallback:"This process did not expose its command line",portUnset:"Port Not Configured",portUnsetDescription:"Without a port, the item can only be started. The system cannot determine automatically whether the service is running.",portOccupied:"Process Started",portAvailable:"Port Available",portAvailableDescription:"There is currently no listening process on the port used by this launch item.",statusRunning:"Running",statusStopped:"Stopped",exitCode:"Exit Code",runningValue:"Running"},theme:{light:"浅色",dark:"深色",skyBlue:"赛博",eyeGreen:"护眼",switchLabel:"Theme"}},Ap={"zh-CN":fm,"en-US":pm},ub={butlerInitTitle:"设置助手",butlerInitDescription:"先完成几个基本设置。",butlerInitPreviewTitle:"当前效果",butlerInitPreviewDescription:"",butlerInitBasicsTitle:"基本信息",butlerInitBasicsDescription:"",butlerInitPersonaTitle:"说话方式",butlerInitPersonaDescription:"",butlerInitPreferenceTitle:"默认偏好",butlerInitPreferenceDescription:"",butlerInitRuleLabel:"规则方式",butlerInitPreviewRuleLabel:"管理方式",butlerInitTipAutoWorkspace:"",butlerInitTipProviderSwitch:"",butlerInitTipReportPriority:"",butlerDisplayNameLabel:"助手称呼",butlerDisplayNamePlaceholder:"例如:小助手",butlerDisplayNameHint:"这个名字会显示在助手页面里。",butlerProviderLabel:"助手引擎",butlerAgentsModeLabel:"规则方式",butlerAgentsModeInline:"自动管理",butlerAgentsModeFile:"手动编辑",butlerAgentsModeInlineDescription:"规则由系统自动管理。",butlerAgentsModeFileDescription:"会生成一份可编辑的规则文件。",butlerPersonaToneLabel:"语气",butlerPersonaLanguageLabel:"使用语言",butlerPersonaSummaryStyleLabel:"回答风格",butlerFocusRiskPreferenceLabel:"处理方式",butlerFocusReportPriorityLabel:"优先提醒",butlerToneDirect:"直接",butlerToneSteady:"稳重",butlerToneFriendly:"亲切",butlerLanguageZhCn:"中文",butlerLanguageEnUs:"英文",butlerLanguageBilingual:"中英双语",butlerSummaryBrief:"简洁",butlerSummaryStructured:"清晰",butlerSummaryThorough:"详细",butlerRiskConservative:"保守稳妥",butlerRiskBalanced:"平衡",butlerRiskProactive:"主动提醒",butlerReportPriorityPresetLabel:"优先提醒",butlerSummaryDebounceLabel:"摘要节奏",butlerSettingsTitle:"助手设置",butlerSettingsSaveAction:"保存设置",butlerSettingsSaving:"保存中...",butlerSettingsSaved:"助手设置已保存",butlerSettingsSaveFailed:"保存助手设置失败",butlerInitSubmitting:"保存中...",butlerInitSubmit:"完成设置",butlerInitSuccess:"助手已设置完成",butlerInitFailed:"助手设置失败",butlerInitNameRequired:"请先填写助手名称",affairsInitPill:"文档与工作台",affairsInitSubmit:"完成助手初始化",affairsInitSuccess:"助手初始化已完成",affairsInitFailed:"助手初始化失败",affairsInitPreviewRuleLabel:"文档和工作台助手",affairsInitLibraryTitle:"文档库设置",affairsInitLibraryDescription:"先决定文档和工作台要不要直接接入文档库。",affairsInitLibraryEnabledLabel:"文档库",affairsInitLibraryEnabledHint:"启用后会在初始化完成后直接接入。",affairsInitLibraryPathHint:"这里填文档库路径,后面还能修改。",affairsInitLibraryPathRequired:"启用文档库前,请先选择文档库路径",affairsConnectionCheckingTitle:"正在检查助手服务",affairsConnectionCheckingDescription:"先确认 Host 能不能连上,再加载文档、工作台和助手能力。",affairsConnectionCheckingSidebarEmpty:"正在检查连接状态,文档和工作台入口稍后再加载。",affairsConnectionCheckingAuxiliaryEmpty:"正在检查连接状态,右侧详情区稍后再加载。",affairsHostUnavailableTitle:"暂时连不上助手服务",affairsHostUnavailableDescription:"这不是没初始化,而是前端现在连不上 Host。",affairsHostUnavailableRetryAction:"重新连接",affairsHostUnavailableRetryHint:"重试只会重新检查连接,不会改你的初始化状态。",affairsHostUnavailableErrorTitle:"连接报错",affairsHostUnavailableSidebarEmpty:"连接恢复前,左侧分区内容暂时加载不出来。",affairsHostUnavailableAuxiliaryEmpty:"连接恢复前,右侧详情区暂时拿不到对象内容。",affairsInitRouteGuardHint:"文档和工作台需要先完成助手初始化,完成后会回到你刚才要打开的位置。",affairsInitRouteGuardSidebarEmpty:"先完成初始化,左侧分区内容才会出现。",affairsInitRouteGuardAuxiliaryEmpty:"先完成初始化,右侧详情区才会出现对象内容。"},db={butlerInitTitle:"Set Up Butler",butlerInitDescription:"Finish a few basic settings first.",butlerInitPreviewTitle:"Preview",butlerInitPreviewDescription:"",butlerInitBasicsTitle:"Basic Info",butlerInitBasicsDescription:"",butlerInitPersonaTitle:"Voice",butlerInitPersonaDescription:"",butlerInitPreferenceTitle:"Default Preferences",butlerInitPreferenceDescription:"",butlerInitRuleLabel:"Rule Style",butlerInitPreviewRuleLabel:"Mode",butlerInitTipAutoWorkspace:"",butlerInitTipProviderSwitch:"",butlerInitTipReportPriority:"",butlerDisplayNameLabel:"Butler Name",butlerDisplayNamePlaceholder:"Example: Butler",butlerDisplayNameHint:"This name appears on the Butler page.",butlerProviderLabel:"Engine",butlerAgentsModeLabel:"Rule Style",butlerAgentsModeInline:"Auto",butlerAgentsModeFile:"Editable File",butlerAgentsModeInlineDescription:"Rules are managed automatically.",butlerAgentsModeFileDescription:"An editable rule file will be created.",butlerPersonaToneLabel:"Tone",butlerPersonaLanguageLabel:"Language",butlerPersonaSummaryStyleLabel:"Reply Style",butlerFocusRiskPreferenceLabel:"Work Style",butlerFocusReportPriorityLabel:"Priority",butlerToneDirect:"Direct",butlerToneSteady:"Steady",butlerToneFriendly:"Friendly",butlerLanguageZhCn:"Chinese",butlerLanguageEnUs:"English",butlerLanguageBilingual:"Bilingual",butlerSummaryBrief:"Brief",butlerSummaryStructured:"Clear",butlerSummaryThorough:"Detailed",butlerRiskConservative:"Conservative",butlerRiskBalanced:"Balanced",butlerRiskProactive:"Proactive",butlerReportPriorityPresetLabel:"Priority",butlerSummaryDebounceLabel:"Summary Cadence",butlerSettingsTitle:"Butler Settings",butlerSettingsSaveAction:"Save Settings",butlerSettingsSaving:"Saving...",butlerSettingsSaved:"Butler settings saved",butlerSettingsSaveFailed:"Failed to save Butler settings",butlerInitSubmitting:"Saving...",butlerInitSubmit:"Finish Setup",butlerInitSuccess:"Butler is ready",butlerInitFailed:"Failed to save Butler settings",butlerInitNameRequired:"Please enter a Butler name",affairsInitPill:"Documents and Workbench",affairsInitSubmit:"Finish assistant setup",affairsInitSuccess:"Assistant setup is complete",affairsInitFailed:"Failed to save assistant setup",affairsInitPreviewRuleLabel:"Documents and workbench assistant",affairsInitLibraryTitle:"Library setup",affairsInitLibraryDescription:"Decide whether documents and workbench should connect the document library right away.",affairsInitLibraryEnabledLabel:"Document library",affairsInitLibraryEnabledHint:"When enabled, it will be connected as soon as setup finishes.",affairsInitLibraryPathHint:"Set the library path here. You can change it later.",affairsInitLibraryPathRequired:"Choose a library path before enabling the document library",affairsInitRouteGuardHint:"Documents and workbench need assistant setup first. After setup finishes, you will return to the place you opened.",affairsInitRouteGuardSidebarEmpty:"Finish setup before the left-side sections appear.",affairsInitRouteGuardAuxiliaryEmpty:"Finish setup before the detail panel shows object content."};function Ad(i,r){const o=i.shell;return{...i,shell:{...o&&typeof o=="object"?o:{},...r}}}const Lp={"zh-CN":Ad(lb,ub),"en-US":Ad(cb,db)};function An(i,r){const o=i.split(".");let c=r;for(const u of o){if(!c||typeof c=="string")return i;const p=c[u];if(p==null)return i;c=p}return typeof c=="string"?c:i}function pb(){return ri.getState().profile.language??"zh-CN"}function tt(i,r){const c=pb()==="en-US"?["en-US","zh-CN"]:["zh-CN"];for(const u of c){const p=An(i,Lp[u]);if(p!==i)return Os(p,r);const y=An(i,Ap[u]);if(y!==i)return Os(y,r)}return Os(i,r)}function Os(i,r){return r?i.replace(/\{([^}]+)\}/g,(o,c)=>{const u=r[c];return u==null?o:String(u)}):i}function SS({children:i,language:r}){return He.useEffect(()=>{document.documentElement.setAttribute("lang",r)},[r]),i}function TS(){const i=sb(r=>r.profile.language);return r=>{const o=i==="en-US"?["en-US","zh-CN"]:["zh-CN"];for(const c of o){const u=An(r,Lp[c]);if(u!==r)return u;const p=An(r,Ap[c]);if(p!==r)return p}return r}}const js="codingns.auth_expired_at";function fb(){sessionStorage.setItem(js,String(Date.now()))}function kS(){const i=sessionStorage.getItem(js);return i?(sessionStorage.removeItem(js),Date.now()-Number(i)<5e3):!1}async function hb(i){var c,u;const r=new Date().toISOString(),o=Fn(`/api/client/runtime-config?platform=${encodeURIComponent(i.platform)}`,i.baseUrl);try{const p=await fetch(o,{method:"GET",headers:{Authorization:`Bearer ${i.accessToken}`}}),y=await mb(p);if(!p.ok){const W=Gi(y==null?void 0:y.error_code),j=Gi(y==null?void 0:y.detail)??`HTTP ${p.status}`;return p.status===401||p.status===403?{status:"unauthorized",checkedAt:r,errorCode:W??"UNAUTHORIZED",errorDetail:j,responseHostBaseUrl:null,responseBindingId:null,responseHostFingerprint:null}:{status:"mismatch",checkedAt:r,errorCode:W??"HTTP_ERROR",errorDetail:j,responseHostBaseUrl:null,responseBindingId:null,responseHostFingerprint:null}}const S=y,A=Gi((c=S==null?void 0:S.relayTunnel)==null?void 0:c.bindingId),O=Gi((u=S==null?void 0:S.relayTunnel)==null?void 0:u.hostFingerprint),E=Gi(S==null?void 0:S.hostBaseUrl);return A&&O&&A===i.expectedBindingId&&O===i.expectedHostFingerprint?{status:"verified",checkedAt:r,errorCode:null,errorDetail:null,responseHostBaseUrl:E,responseBindingId:A,responseHostFingerprint:O}:{status:"mismatch",checkedAt:r,errorCode:"HOST_IDENTITY_MISMATCH",errorDetail:"候选入口返回的 Host 身份与当前激活 Host 不一致",responseHostBaseUrl:E,responseBindingId:A,responseHostFingerprint:O}}catch(p){return{status:"unreachable",checkedAt:r,errorCode:"NETWORK_ERROR",errorDetail:p instanceof Error?p.message:"未知网络错误",responseHostBaseUrl:null,responseBindingId:null,responseHostFingerprint:null}}}async function mb(i){const r=await i.text();if(!r.trim())return null;try{return JSON.parse(r)}catch{return null}}function Gi(i){return typeof i=="string"&&i.trim()?i.trim():null}class gb{constructor(){L(this,"state",{epoch:0,activeHostId:Tn(Z.getState()),connectionSignature:Ld(Z.getState()),candidateProbeSignature:null,candidateProbePhase:"idle",candidateProbeStartedAt:null,candidateProbeFinishedAt:null,candidateEndpoints:[],preferredCandidateEndpointId:null,preferredDirectCandidateEndpointId:null});L(this,"listeners",new Set);L(this,"probeRunId",0);L(this,"subscribe",r=>(this.listeners.add(r),()=>{this.listeners.delete(r)}));L(this,"getState",()=>this.state);Z.subscribe(()=>{this.handleDependencyChange()}),Me.subscribe(()=>{this.handleDependencyChange()}),this.handleDependencyChange()}handleDependencyChange(){var A;const r=Z.getState(),o=Tn(r),c=Ld(r),u=bb(r,((A=Me.getState().session)==null?void 0:A.accessToken)??null),p=(u==null?void 0:u.signature)??null;let y=!1,S=this.state;if((o!==this.state.activeHostId||c!==this.state.connectionSignature)&&(S={...S,epoch:this.state.epoch+1,activeHostId:o,connectionSignature:c},y=!0),p!==this.state.candidateProbeSignature)if(this.probeRunId+=1,!u)S={...S,candidateProbeSignature:null,candidateProbePhase:"idle",candidateProbeStartedAt:null,candidateProbeFinishedAt:null,candidateEndpoints:[],preferredCandidateEndpointId:null,preferredDirectCandidateEndpointId:null},y=!0;else{const O=new Date().toISOString();S={...S,candidateProbeSignature:p,candidateProbePhase:"probing",candidateProbeStartedAt:O,candidateProbeFinishedAt:null,candidateEndpoints:u.candidateEndpoints.map(E=>({...E,status:"pending",checkedAt:null,errorCode:null,errorDetail:null,responseHostBaseUrl:null,responseBindingId:null,responseHostFingerprint:null})),preferredCandidateEndpointId:null,preferredDirectCandidateEndpointId:null},y=!0,this.runCandidateProbe(u,this.probeRunId)}y&&(this.state=S,this.emit())}async runCandidateProbe(r,o){const c=await Promise.all(r.candidateEndpoints.map(async u=>{const p=await hb({baseUrl:u.url,accessToken:r.accessToken,platform:r.platform,expectedBindingId:r.expectedBindingId,expectedHostFingerprint:r.expectedHostFingerprint});return{...u,status:p.status,checkedAt:p.checkedAt,errorCode:p.errorCode,errorDetail:p.errorDetail,responseHostBaseUrl:p.responseHostBaseUrl,responseBindingId:p.responseBindingId,responseHostFingerprint:p.responseHostFingerprint}}));o===this.probeRunId&&(this.state={...this.state,candidateProbePhase:"ready",candidateProbeFinishedAt:new Date().toISOString(),candidateEndpoints:c,preferredCandidateEndpointId:Sb(c),preferredDirectCandidateEndpointId:Tb(c)},this.emit())}emit(){for(const r of this.listeners)r()}}const $i=new gb;function wS(){return He.useSyncExternalStore($i.subscribe,()=>{const i=$i.getState();return`${i.activeHostId??"anonymous"}:${i.epoch}`})}function vS(i){return He.useSyncExternalStore($i.subscribe,()=>i($i.getState()))}function Ld(i){const r=Da(i);return r?JSON.stringify({id:r.id,baseUrl:r.baseUrl,relayTunnel:r.relayTunnel}):"no-host"}function bb(i,r){var O,E;const o=Da(i),c=o==null?void 0:o.relayTunnel,u=(O=c==null?void 0:c.bindingId)==null?void 0:O.trim(),p=(E=c==null?void 0:c.hostFingerprint)==null?void 0:E.trim(),y=(c==null?void 0:c.candidateEndpoints)??[];if(!o||!r||!u||!p||y.length===0)return null;const S=i.platform==="web"?"web":"desktop";if(S==="web")return null;const A=y.filter(W=>yb(W,S));return A.length===0?null:{signature:JSON.stringify({hostId:o.id,platform:S,accessToken:r,bindingId:u,hostFingerprint:p,candidateEndpoints:A.map(W=>({endpointId:W.endpointId,url:W.url,kind:W.kind,priority:W.priority}))}),platform:S,accessToken:r,expectedBindingId:u,expectedHostFingerprint:p,candidateEndpoints:A}}function yb(i,r){return r!=="web"}function Sb(i){var r;return((r=i.find(o=>o.status==="verified"))==null?void 0:r.endpointId)??null}function Tb(i){var r;return((r=i.find(o=>o.status==="verified"&&o.kind!=="relay"))==null?void 0:r.endpointId)??null}const Rp=Ue("https://channel.codingns.com:1443");function CS(){return Rp}function DS(){return!1}function kb(i){if(!(i!=null&&i.trim()))return null;try{return Ue(i)}catch{return null}}function PS(i){return kb(i)??Rp}function wb(i){try{const r=Ue(i),c=new URL(r).hostname.trim().toLowerCase(),u=c.split(".");if(u.length<4||u[1]!=="channel")return null;const p=new URL(r);return p.hostname=u.slice(1).join("."),p.pathname="",p.search="",p.hash="",{tunnelDomain:c,controlBaseUrl:Ue(p.toString()),relayBaseUrl:r}}catch{return null}}class vb{async fetch(r){return fetch(r.url,r.init)}createWebSocket(r){return new WebSocket(r.url,r.protocols)}}const qs=new vb;class Cb{constructor(r){L(this,"nextStreamId",0);L(this,"pendingHttpRequests",new Map);L(this,"sockets",new Map);L(this,"unsubscribe");this.session=r,this.unsubscribe=r.subscribe(o=>{this.handlePacket(o)})}async fetch(r){const o=this.createStreamId("http"),c={type:"http.request",streamId:o,method:Ab(r.init.method),path:Rd(r.path,r.url),headers:Lb(r.init.headers),bodyBase64Url:await Rb(r.init.body)};return await new Promise((u,p)=>{this.pendingHttpRequests.set(o,{resolve:u,reject:p,streamController:null,responseStarted:!1}),this.session.send(c)})}createWebSocket(r){const o=this.createStreamId("ws"),c=new Db({streamId:o,path:Rd(r.path,r.url),headers:{},protocols:Pb(r.protocols)},this.session,()=>{this.sockets.delete(o)});return this.sockets.set(o,c),c}close(){var r;this.unsubscribe();for(const o of this.pendingHttpRequests.values()){const c=new Error("隧道会话已经关闭");if(o.responseStarted){(r=o.streamController)==null||r.error(c);continue}o.reject(c)}this.pendingHttpRequests.clear();for(const o of this.sockets.values())o.forceClose(1011,"隧道会话已经关闭");this.sockets.clear()}handlePacket(r){var o,c,u;switch(r.type){case"http.response":this.handleHttpResponse(r);return;case"http.response.start":this.handleHttpResponseStart(r);return;case"http.response.chunk":this.handleHttpResponseChunk(r);return;case"http.response.end":this.handleHttpResponseEnd(r);return;case"ws.opened":(o=this.sockets.get(r.streamId))==null||o.handleOpened(r);return;case"ws.message":(c=this.sockets.get(r.streamId))==null||c.handleMessage(r);return;case"ws.closed":(u=this.sockets.get(r.streamId))==null||u.handleClosed(r);return;case"error":this.handleError(r);return;default:return}}handleHttpResponse(r){const o=this.pendingHttpRequests.get(r.streamId);o&&(this.pendingHttpRequests.delete(r.streamId),o.resolve(new Response(Mb(r.bodyBase64Url),{status:r.status,headers:r.headers})))}handleHttpResponseStart(r){const o=this.pendingHttpRequests.get(r.streamId);if(!o||o.responseStarted)return;if(o.responseStarted=!0,Ib(r.status)){this.pendingHttpRequests.delete(r.streamId),o.resolve(new Response(null,{status:r.status,headers:r.headers}));return}const c=new ReadableStream({start:u=>{o.streamController=u},cancel:()=>{o.streamController=null}});o.resolve(new Response(c,{status:r.status,headers:r.headers}))}handleHttpResponseChunk(r){var u;const o=this.pendingHttpRequests.get(r.streamId);if(!(o!=null&&o.responseStarted))return;const c=Fp(r.bodyChunkBase64Url);(u=o.streamController)==null||u.enqueue(c)}handleHttpResponseEnd(r){var c;const o=this.pendingHttpRequests.get(r.streamId);o&&((c=o.streamController)==null||c.close(),o.streamController=null,this.pendingHttpRequests.delete(r.streamId))}handleError(r){var o,c;if(r.streamId&&this.pendingHttpRequests.has(r.streamId)){const u=this.pendingHttpRequests.get(r.streamId),p=new Error(`${r.errorCode}: ${r.detail}`);this.pendingHttpRequests.delete(r.streamId),u!=null&&u.responseStarted?(o=u.streamController)==null||o.error(p):u==null||u.reject(p);return}r.streamId&&((c=this.sockets.get(r.streamId))==null||c.handleError(r))}createStreamId(r){return this.nextStreamId+=1,`${r}-${this.nextStreamId}`}}class Db extends EventTarget{constructor(o,c,u){super();L(this,"streamId");L(this,"mutableReadyState",0);L(this,"closed",!1);this.options=o,this.session=c,this.onClosed=u,this.streamId=o.streamId,this.open()}get readyState(){return this.mutableReadyState}send(o){if(this.mutableReadyState!==1)throw new Error("当前隧道 WebSocket 尚未打开");const c=Ob(o),u={type:"ws.message",streamId:this.streamId,binary:typeof c!="string",dataBase64Url:Eb(c)};this.session.send(u)}close(o,c){this.closed||(this.closed=!0,this.mutableReadyState=2,this.session.send({type:"ws.closed",streamId:this.streamId,code:o??1e3,reason:c??null}))}handleOpened(o){this.closed||(this.mutableReadyState=1,this.dispatchEvent(new Event("open")))}handleMessage(o){if(this.closed)return;const c=o.binary?rl(o.dataBase64Url):xb(o.dataBase64Url);this.dispatchEvent(new MessageEvent("message",{data:c}))}handleClosed(o){this.forceClose(o.code,o.reason??"")}handleError(o){this.closed||(this.dispatchEvent(new ErrorEvent("error",{message:`${o.errorCode}: ${o.detail}`})),this.forceClose(1011,o.detail))}forceClose(o,c){this.mutableReadyState!==3&&(this.closed=!0,this.mutableReadyState=3,this.dispatchEvent(new CloseEvent("close",{code:o,reason:c})),this.onClosed())}open(){const o={type:"ws.open",streamId:this.streamId,path:this.options.path,headers:this.options.headers,protocols:this.options.protocols.length>0?this.options.protocols:void 0};this.session.send(o)}}function Pb(i){if(!i)return[];const r=Array.isArray(i)?i:[i],o=new Set,c=[];for(const u of r){const p=u.trim();!p||o.has(p)||(o.add(p),c.push(p))}return c}function Ab(i){return(i==null?void 0:i.trim().toUpperCase())||"GET"}function Lb(i){const r=new Headers(i),o={};return r.forEach((c,u)=>{o[u]=c}),o}async function Rb(i){if(i==null)return null;const r=await Fb(i);return r.byteLength>0?gn(r):null}async function Fb(i){if(typeof i=="string")return Gs.encode(i);if(i instanceof URLSearchParams)return Gs.encode(i.toString());if(i instanceof ArrayBuffer)return new Uint8Array(i);if(ArrayBuffer.isView(i))return new Uint8Array(i.buffer,i.byteOffset,i.byteLength);if(typeof Blob<"u"&&i instanceof Blob)return new Uint8Array(await i.arrayBuffer());throw new Error("当前隧道 transport 不支持这种请求体类型")}function Rd(i,r){const o=new URL(r),c=i.trim();return c?c.includes("?")||!o.search?c:`${c}${o.search}`:`${o.pathname}${o.search}`}function Eb(i){return typeof i=="string"?gn(Gs.encode(i)):ArrayBuffer.isView(i)?gn(new Uint8Array(i.buffer,i.byteOffset,i.byteLength)):gn(new Uint8Array(i))}function rl(i){return i?Fp(i):null}function Mb(i){const r=rl(i);if(!r)return null;const o=new Uint8Array(r.byteLength);return o.set(r),o.buffer}function Ib(i){return i===101||i===103||i===204||i===205||i===304}function xb(i){const r=rl(i);return r?Nb.decode(r):""}function Ob(i){if(Hb(i))throw new Error("当前隧道 WebSocket 暂不支持直接发送 Blob");return i}function Hb(i){return typeof Blob<"u"&&i instanceof Blob}function gn(i){let r="";for(let o=0;o<i.length;o+=Fd){const c=i.subarray(o,o+Fd);r+=String.fromCharCode(...c)}return btoa(r).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/g,"")}function Fp(i){const r=i.replace(/-/g,"+").replace(/_/g,"/"),o=r.padEnd(Math.ceil(r.length/4)*4,"="),c=atob(o),u=new Uint8Array(c.length);for(let p=0;p<c.length;p+=1)u[p]=c.charCodeAt(p);return u}const Gs=new TextEncoder,Nb=new TextDecoder,Fd=32768,La=1,ca="x25519-hkdf-sha256-aes-256-gcm",Bb=12,bn=16,Ub=32;class Ne extends Error{constructor(r,o){super(o),this.code=r,this.name="RelayTunnelProtocolError"}}async function Ep(i){const r=xp(i,"PUBLIC KEY"),o=await ct().digest("SHA-256",Be(r));return`SHA256:${ty(new Uint8Array(o))}`}async function Wb(i){const r=xd(i.expectedHostFingerprint,"expectedHostFingerprint"),o=xd(i.expectedHostPublicKey,"expectedHostPublicKey");if(await Ep(o)!==r)throw new Ne("RELAY_TUNNEL_HOST_FINGERPRINT_MISMATCH","客户端持有的 Host 公钥和指纹不一致");const u=ct(),p=await u.generateKey(In,!0,["deriveBits"]),y={version:La,cipherSuite:ca,clientEphemeralPublicKey:ii(new Uint8Array(await u.exportKey("spki",p.publicKey))),clientNonce:ii(Hp(16)),expectedHostFingerprint:r};return{pendingHandshake:{expectedHostPublicKey:o,expectedHostFingerprint:r,clientEphemeralPrivateKey:p.privateKey,clientHello:y},clientHello:y}}async function _b(i){if(Gb(i.pendingHandshake.clientHello),Kb(i.serverHello),i.serverHello.hostKeyFingerprint!==i.pendingHandshake.expectedHostFingerprint)throw new Ne("RELAY_TUNNEL_HOST_FINGERPRINT_MISMATCH","服务端返回的 Host 指纹和客户端预期不一致");if(await Ep(i.serverHello.hostPublicKey)!==i.pendingHandshake.expectedHostFingerprint)throw new Ne("RELAY_TUNNEL_HOST_FINGERPRINT_MISMATCH","服务端返回的 Host 公钥与指纹不一致");if(Ln(i.serverHello.hostPublicKey)!==Ln(i.pendingHandshake.expectedHostPublicKey))throw new Ne("RELAY_TUNNEL_HOST_PUBLIC_KEY_MISMATCH","服务端返回的 Host 公钥和客户端持有的公钥不一致");const o=await Yb(i.pendingHandshake.clientHello,i.serverHello),c=await Jb(i.pendingHandshake.expectedHostPublicKey),u=await Xb(i.serverHello.serverEphemeralPublicKey),p=await Id(i.pendingHandshake.clientEphemeralPrivateKey,c),y=await Id(i.pendingHandshake.clientEphemeralPrivateKey,u),S=Op([p,y]),A=await $b(S,o),O=ni.encode(A),E=ni.encode(i.serverHello.proof);if(!ey(O,E))throw new Ne("RELAY_TUNNEL_HANDSHAKE_PROOF_INVALID","服务端握手证明无效");return await jb({sessionId:i.serverHello.sessionId,peerHostFingerprint:i.serverHello.hostKeyFingerprint,ikm:S,transcriptHash:o})}async function Vb(i,r){const o=ct(),c=i.sendSequence+1,u="client_to_host",p=Hp(Bb),y=Ip({sessionId:i.sessionId,direction:u,sequence:c}),S=Zb(r),A=new Uint8Array(await o.encrypt({name:"AES-GCM",iv:Be(p),additionalData:Be(y),tagLength:bn*8},i.sendKey,Be(S)));return i.sendSequence=c,{version:La,cipherSuite:ca,sessionId:i.sessionId,direction:u,sequence:c,iv:ii(p),authTag:ii(A.slice(-bn)),ciphertext:ii(A.slice(0,-bn))}}async function zb(i,r){if(Qb(r),r.sessionId!==i.sessionId)throw new Ne("RELAY_TUNNEL_FRAME_SESSION_MISMATCH","加密帧的会话标识和当前会话不匹配");if(r.direction!=="host_to_client")throw new Ne("RELAY_TUNNEL_FRAME_DIRECTION_MISMATCH","加密帧方向和当前接收方向不匹配");const o=i.receiveSequence+1,c=qb(r);if(r.sequence===i.receiveSequence&&i.lastReceivedFrameFingerprint===c)return null;if(r.sequence!==o)throw new Ne("RELAY_TUNNEL_FRAME_SEQUENCE_MISMATCH",`加密帧序号错误,期望 ${o},实际 ${r.sequence}`);const u=ct(),p=Ip({sessionId:r.sessionId,direction:r.direction,sequence:r.sequence}),y=yn(r.ciphertext),S=yn(r.authTag),A=Op([y,S]);try{const O=new Uint8Array(await u.decrypt({name:"AES-GCM",iv:Be(yn(r.iv)),additionalData:Be(p),tagLength:bn*8},i.receiveKey,Be(A)));return i.receiveSequence=r.sequence,i.lastReceivedFrameFingerprint=c,O}catch{throw new Ne("RELAY_TUNNEL_FRAME_AUTH_INVALID","加密帧完整性校验失败")}}async function jb(i){const r=await Ed(i.ikm,i.transcriptHash,"codingns-relay-client-to-host"),o=await Ed(i.ikm,i.transcriptHash,"codingns-relay-host-to-client");return{sessionId:i.sessionId,role:"client",cipherSuite:ca,peerHostFingerprint:i.peerHostFingerprint,sendSequence:0,receiveSequence:0,lastReceivedFrameFingerprint:null,sendKey:await Md(r,"encrypt"),receiveKey:await Md(o,"decrypt")}}function qb(i){return[i.sessionId,i.direction,String(i.sequence),i.iv,i.authTag,i.ciphertext].join(":")}function Gb(i){if(i.version!==La||i.cipherSuite!==ca)throw new Ne("RELAY_TUNNEL_PROTOCOL_UNSUPPORTED","客户端握手协议版本或套件不受支持")}function Kb(i){if(i.version!==La||i.cipherSuite!==ca)throw new Ne("RELAY_TUNNEL_PROTOCOL_UNSUPPORTED","服务端握手协议版本或套件不受支持")}function Qb(i){if(i.version!==La||i.cipherSuite!==ca)throw new Ne("RELAY_TUNNEL_PROTOCOL_UNSUPPORTED","加密帧协议版本或套件不受支持")}async function Yb(i,r){const o=JSON.stringify({version:La,cipherSuite:ca,clientEphemeralPublicKey:i.clientEphemeralPublicKey,clientNonce:i.clientNonce,expectedHostFingerprint:i.expectedHostFingerprint,hostPublicKey:Ln(r.hostPublicKey),hostKeyFingerprint:r.hostKeyFingerprint,serverEphemeralPublicKey:r.serverEphemeralPublicKey,serverNonce:r.serverNonce,sessionId:r.sessionId});return new Uint8Array(await ct().digest("SHA-256",ni.encode(o)))}async function $b(i,r){const o=await Mp(i,r,"codingns-relay-handshake-proof"),c=await ct().importKey("raw",Be(o),ry,!1,["sign"]),u=new Uint8Array(await ct().sign("HMAC",c,Be(r)));return ii(u)}async function Ed(i,r,o){return await Mp(i,r,o)}async function Mp(i,r,o){const c=ct(),u=await c.importKey("raw",Be(i),"HKDF",!1,["deriveBits"]),p=await c.deriveBits({name:"HKDF",hash:"SHA-256",salt:Be(r),info:Be(ni.encode(o))},u,Ub*8);return new Uint8Array(p)}async function Md(i,r){return await ct().importKey("raw",Be(i),iy,!1,[r])}async function Jb(i){return await ct().importKey("spki",Be(xp(i,"PUBLIC KEY")),In,!1,[])}async function Xb(i){return await ct().importKey("spki",Be(yn(i)),In,!1,[])}async function Id(i,r){const o=await ct().deriveBits({...In,public:r},i,256);return new Uint8Array(o)}function Ip(i){return ni.encode(JSON.stringify({version:La,cipherSuite:ca,sessionId:i.sessionId,direction:i.direction,sequence:i.sequence}))}function Zb(i){return typeof i=="string"?ni.encode(i):i instanceof Uint8Array?i:new Uint8Array(i)}function xd(i,r){const o=i.trim();if(!o)throw new Ne("RELAY_TUNNEL_PROTOCOL_UNSUPPORTED",`${r} 不能为空`);return o}function Ln(i){return i.trim().replace(/\r\n/g,`
50
- `)}function xp(i,r){const o=Ln(i),c=`-----BEGIN ${r}-----`,u=`-----END ${r}-----`;if(!o.includes(c)||!o.includes(u))throw new Ne("RELAY_TUNNEL_PROTOCOL_UNSUPPORTED",`无效的 ${r} PEM`);const p=o.replace(c,"").replace(u,"").replace(/\s+/g,"");return ay(p)}function ey(i,r){if(i.length!==r.length)return!1;let o=0;for(let c=0;c<i.length;c+=1)o|=i[c]^r[c];return o===0}function Op(i){const r=i.reduce((u,p)=>u+p.length,0),o=new Uint8Array(r);let c=0;for(const u of i)o.set(u,c),c+=u.length;return o}function Hp(i){const r=new Uint8Array(i);return Up().getRandomValues(r),r}function ty(i){return Np(i)}function ii(i){return Np(i).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/g,"")}function ay(i){return Bp(i)}function yn(i){const r=i.replace(/-/g,"+").replace(/_/g,"/"),o=r.padEnd(Math.ceil(r.length/4)*4,"=");return Bp(o)}function Np(i){let r="";for(let o=0;o<i.length;o+=Od)r+=String.fromCharCode(...i.subarray(o,o+Od));return btoa(r)}function Bp(i){const r=atob(i),o=new Uint8Array(r.length);for(let c=0;c<r.length;c+=1)o[c]=r.charCodeAt(c);return o}function Be(i){return Uint8Array.from(i)}function Up(){if(typeof globalThis.crypto>"u")throw new Ne("RELAY_TUNNEL_PROTOCOL_UNSUPPORTED","当前运行环境不支持 Web Crypto");return globalThis.crypto}function ct(){return Up().subtle}const ni=new TextEncoder,Od=32768,In={name:"X25519"},iy={name:"AES-GCM",length:256},ry={name:"HMAC",hash:"SHA-256"};function ny(i){return JSON.stringify(i)}function oy(i){return JSON.parse(i)}class Wp{constructor(r,o){L(this,"listeners",new Set);L(this,"unsubscribeFromChannel");L(this,"closeListeners",new Set);L(this,"unsubscribeFromChannelClose");L(this,"connectPromise",null);L(this,"textEncoder",new TextEncoder);L(this,"textDecoder",new TextDecoder);L(this,"incomingPayloadChain",Promise.resolve());L(this,"outgoingPacketChain",Promise.resolve());L(this,"pendingPackets",[]);L(this,"closedByClient",!1);L(this,"terminationNotified",!1);L(this,"handshakeState",{status:"idle"});this.channel=r,this.options=o,this.unsubscribeFromChannel=r.subscribe(c=>{this.enqueueIncomingPayload(c)}),this.unsubscribeFromChannelClose=r.subscribeClose?r.subscribeClose(c=>{this.handleChannelClosed(c)}):null}async connect(){if(this.handshakeState.status==="ready")return;if(this.connectPromise)return await this.connectPromise;if(this.handshakeState.status==="failed")throw this.handshakeState.error;const{pendingHandshake:r,clientHello:o}=await Wb({expectedHostPublicKey:this.options.expectedHostPublicKey,expectedHostFingerprint:this.options.expectedHostFingerprint});return this.connectPromise=new Promise((c,u)=>{this.handshakeState={status:"waiting_server_hello",pendingHandshake:r,resolve:c,reject:u},this.sendControlPayload(JSON.stringify({type:"client_hello",hello:o}))}),await this.connectPromise}send(r){if(this.handshakeState.status==="ready"){this.enqueueOutgoingPacket(r,this.handshakeState.session);return}if(this.handshakeState.status==="failed")throw this.handshakeState.error;if(this.handshakeState.status==="waiting_server_hello"&&this.connectPromise){this.pendingPackets.push(r);return}throw new Error("当前 CodingNS Connect 会话尚未建立完成")}subscribe(r){return this.listeners.add(r),()=>{this.listeners.delete(r)}}subscribeClose(r){return this.closeListeners.add(r),()=>{this.closeListeners.delete(r)}}close(r,o){var c;this.closedByClient=!0,this.unsubscribeFromChannel(),(c=this.unsubscribeFromChannelClose)==null||c.call(this),this.channel.close(r,o)}async handleIncomingPayload(r){this.recordWireBytes("downstream",r);const o=JSON.parse(r);if(o.type==="server_hello"){await this.handleServerHello(o);return}if(o.type==="encrypted_frame"){await this.handleEncryptedFrame(o);return}o.type==="error"&&this.failSession(new Error(`${o.errorCode}: ${o.detail}`))}async handleServerHello(r){if(this.handshakeState.status==="waiting_server_hello")try{const o=await _b({pendingHandshake:this.handshakeState.pendingHandshake,serverHello:r.hello}),c=this.handshakeState.resolve;this.handshakeState={status:"ready",session:o},this.connectPromise=null,await this.flushPendingPackets(o),c()}catch(o){this.failSession(Ki(o))}}async handleEncryptedFrame(r){const o=this.requireReadySession();try{const c=await zb(o.session,r.frame);if(!c)return;const u=oy(this.textDecoder.decode(c));for(const p of this.listeners)p(u)}catch(c){this.failSession(Ki(c))}}requireReadySession(){if(this.handshakeState.status==="failed")throw this.handshakeState.error;if(this.handshakeState.status!=="ready")throw new Error("当前 CodingNS Connect 会话尚未建立完成");return this.handshakeState}failSession(r){if(this.pendingPackets=[],this.handshakeState.status==="waiting_server_hello"){const o=this.handshakeState.reject;this.handshakeState={status:"failed",error:r},this.connectPromise=null,this.notifyTermination(r),o(r);return}this.handshakeState={status:"failed",error:r},this.connectPromise=null,this.notifyTermination(r)}handleChannelClosed(r){this.closedByClient||this.failSession(r)}sendControlPayload(r){return this.recordWireBytes("upstream",r),this.channel.send(r)}enqueueIncomingPayload(r){this.incomingPayloadChain=this.incomingPayloadChain.catch(()=>{}).then(async()=>{await this.handleIncomingPayload(r)}).catch(o=>{this.failSession(Ki(o))})}async flushPendingPackets(r){const o=this.pendingPackets;if(o.length!==0){this.pendingPackets=[];for(const c of o)await this.sendEncryptedPacket(c,r)}}enqueueOutgoingPacket(r,o){this.outgoingPacketChain=this.outgoingPacketChain.catch(()=>{}).then(async()=>{await this.sendEncryptedPacket(r,o)}).catch(c=>{this.failSession(Ki(c))})}async sendEncryptedPacket(r,o){try{const c=await Vb(o,ny(r));await this.sendControlPayload(JSON.stringify({type:"encrypted_frame",frame:c}))}catch(c){const u=Ki(c);throw this.failSession(u),u}}recordWireBytes(r,o){var c,u;(u=(c=this.options).onWireBytes)==null||u.call(c,r,this.textEncoder.encode(o).byteLength)}notifyTermination(r){if(!this.terminationNotified){this.terminationNotified=!0;for(const o of this.closeListeners)o(r)}}}function Ki(i){return i instanceof Error?i:new Error(String(i))}const _p=3,sy=250;async function ly(i){const r=i.fetchFn??fetch,o=new URL(`/api/v1/tunnels/${encodeURIComponent(hy(i.tunnelDomain))}/connect-init`,qp(i.controlBaseUrl)).toString(),c=await r(o,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({clientContext:my()})});if(!c.ok)throw await fy(c,"初始化隧道连接失败");return await c.json()}async function cy(i,r={}){const o=await ly({controlBaseUrl:i.controlBaseUrl,tunnelDomain:i.tunnelDomain,fetchFn:r.fetchFn}),c={bindingId:o.bindingId,tunnelDomain:o.tunnelDomain,hostPublicKey:o.hostPublicKey,hostFingerprint:o.hostFingerprint,relayBaseUrl:o.relayBaseUrl,controlBaseUrl:o.controlBaseUrl,status:o.status},u={sessionId:o.sessionId,bindingId:o.bindingId,tunnelDomain:o.tunnelDomain,connectTicket:o.connectTicket,remainingBytes:o.remainingBytes,sessionRateLimitBytesPerSecond:o.sessionRateLimitBytesPerSecond,upstreamConnected:o.upstreamConnected,downstreamConnected:o.downstreamConnected,expiresAt:o.expiresAt},y=(r.createWebSocket??Gp)(zp(c.relayBaseUrl,u.sessionId,Kp(u)));return await jp(y),{binding:c,reservation:u,channel:new Vp(y)}}async function uy(i,r={}){const c=(r.createWebSocket??Gp)(zp(i.binding.relayBaseUrl,i.reservation.sessionId,Kp(i.reservation)));return await jp(c),{binding:i.binding,reservation:i.reservation,channel:new Vp(c)}}async function dy(i,r={}){let o=null;for(let c=1;c<=_p;c+=1){let u=null;try{u=await cy(i,r);const p=new Wp(u.channel,{expectedHostPublicKey:u.binding.hostPublicKey,expectedHostFingerprint:u.binding.hostFingerprint,onWireBytes:i.onWireBytes});return await p.connect(),{...u,clientSession:p}}catch(p){const y=Ty(p);if(o=y,u==null||u.channel.close(1011,"relay_client_session_connect_failed"),!yy(y,c))throw y;await Sy(sy*c)}}throw o??new Error("当前 CodingNS Connect 会话建立失败")}async function py(i,r={}){const o=await uy({binding:i.binding,reservation:i.reservation},r),c=new Wp(o.channel,{expectedHostPublicKey:o.binding.hostPublicKey,expectedHostFingerprint:o.binding.hostFingerprint,onWireBytes:i.onWireBytes});return await c.connect(),{...o,clientSession:c}}class Vp{constructor(r){L(this,"terminalError",null);L(this,"closeNotified",!1);L(this,"closeListeners",new Set);L(this,"handleClose",r=>{const o=r;this.terminalError=new Error(`relay-edge 原始链路关闭:${o.code}${o.reason?` ${o.reason}`:""}`),this.notifyClose(this.terminalError)});L(this,"handleError",()=>{this.terminalError||(this.terminalError=new Error("relay-edge 原始链路建立失败")),this.notifyClose(this.terminalError)});this.socket=r,this.socket.addEventListener("close",this.handleClose),this.socket.addEventListener("error",this.handleError)}send(r){if(this.socket.readyState!==1)throw this.terminalError??new Error("当前 relay-edge 原始链路尚未建立完成");this.socket.send(r)}subscribe(r){const o=c=>{const u=c;typeof u.data=="string"&&r(u.data)};return this.socket.addEventListener("message",o),()=>{this.socket.removeEventListener("message",o)}}subscribeClose(r){return this.closeListeners.add(r),()=>{this.closeListeners.delete(r)}}close(r,o){this.socket.removeEventListener("close",this.handleClose),this.socket.removeEventListener("error",this.handleError),this.socket.close(r,o)}notifyClose(r){if(!this.closeNotified){this.closeNotified=!0;for(const o of this.closeListeners)o(r)}}}function zp(i,r,o){const c=by(i,"ws");return c.searchParams.set("sessionId",r),c.searchParams.set("role","downstream"),c.searchParams.set("connectTicket",o),c.protocol=c.protocol==="https:"||c.protocol==="wss:"?"wss:":"ws:",c.toString()}async function jp(i){i.readyState!==1&&await new Promise((r,o)=>{const c=()=>{y(),r()},u=S=>{y();const A=S;o(new Error(`relay-edge 原始链路关闭:${A.code}${A.reason?` ${A.reason}`:""}`))},p=()=>{y(),o(new Error("relay-edge 原始链路建立失败"))},y=()=>{i.removeEventListener("open",c),i.removeEventListener("close",u),i.removeEventListener("error",p)};i.addEventListener("open",c),i.addEventListener("close",u),i.addEventListener("error",p)})}async function fy(i,r){const c=(await i.text()).trim();if(!c)return new Error(`${r}(HTTP ${i.status})`);try{const u=JSON.parse(c);if(typeof u.detail=="string"&&typeof u.errorCode=="string")return new Error(`${u.errorCode}: ${u.detail}`)}catch{}return new Error(`${r}:${c}`)}function hy(i){const r=i.trim().toLowerCase();if(!r)throw new Error("tunnelDomain 不能为空");return r}function qp(i){return i.endsWith("/")?i:`${i}/`}function my(){const i=Z.getState().platform??null,r=typeof navigator>"u"?null:Sn(navigator.userAgent),o=typeof navigator>"u"?null:Sn(navigator.platform),c=typeof navigator>"u"?null:Sn(navigator.language),u=gy();return{runtimePlatform:i,systemPlatform:o,userAgent:r,language:c,timezone:u}}function gy(){try{return Sn(Intl.DateTimeFormat().resolvedOptions().timeZone)}catch{return null}}function by(i,r){return new URL(r.replace(/^\/+/,""),qp(i))}function Gp(i){return new WebSocket(i)}function Kp(i){var o;const r=(o=i.connectTicket)==null?void 0:o.trim();if(!r)throw new Error("当前 CodingNS Connect 会话缺少 connectTicket,不能继续续接");return r}function yy(i,r){if(r>=_p)return!1;const o=i.message;return o.includes("relay-edge 原始链路")||o.includes("HOST_NOT_CONNECTED")||o.includes("HOST_UPSTREAM_DISCONNECTED")}async function Sy(i){await new Promise(r=>{setTimeout(r,i)})}function Sn(i){const r=i==null?void 0:i.trim();return r||null}function Ty(i){return i instanceof Error?i:new Error(String(i))}const Hs={startedAt:null,updatedAt:null,upstreamBytes:0,downstreamBytes:0,totalBytes:0};class ky{constructor(){L(this,"state",{byHostId:{}});L(this,"listeners",new Set);L(this,"subscribe",r=>(this.listeners.add(r),()=>{this.listeners.delete(r)}));Me.subscribe(()=>{Me.getState().session||this.reset()})}getSummary(r){return r?this.state.byHostId[r]??Hs:Hs}recordWireBytes(r,o,c){if(!r||!Number.isFinite(c)||c<=0)return;const u=this.state.byHostId[r]??Hs,p=new Date().toISOString(),y={startedAt:u.startedAt??p,updatedAt:p,upstreamBytes:o==="upstream"?u.upstreamBytes+c:u.upstreamBytes,downstreamBytes:o==="downstream"?u.downstreamBytes+c:u.downstreamBytes,totalBytes:u.totalBytes+c};this.state={byHostId:{...this.state.byHostId,[r]:y}},this.emit()}reset(){Object.keys(this.state.byHostId).length!==0&&(this.state={byHostId:{}},this.emit())}emit(){for(const r of this.listeners)r()}}const Ks=new ky;function Hd(i,r,o){Ks.recordWireBytes(i,r,o)}function AS(i){return He.useSyncExternalStore(Ks.subscribe,()=>Ks.getSummary(i))}class Nd{constructor(r,o={}){L(this,"connectPromise",null);L(this,"fallbackTransport",null);L(this,"resumeState",null);this.options=r,this.dependencies=o}async fetch(r){return await(await this.getActiveTransport()).transport.fetch(r)}createWebSocket(r){return new wy(this.getActiveTransport(),r)}close(){const r=this.connectPromise;this.connectPromise=null,this.fallbackTransport=null,this.resumeState=null,r&&r.then(o=>{o.close()}).catch(()=>{})}async getActiveTransport(){return this.fallbackTransport?{transport:this.fallbackTransport,close:()=>{}}:(this.connectPromise||(this.connectPromise=this.createActiveTransport()),await this.connectPromise)}async createActiveTransport(){var u,p;const r=this.dependencies.connectSession??dy,o=this.dependencies.resumeSession??py,c=this.dependencies.createTransport??(y=>new Cb(y));try{const y=await this.connectWithResume(r,o),S=c(y.clientSession);this.resumeState={binding:y.binding,reservation:y.reservation};let A=!1;const O=((p=(u=y.clientSession).subscribeClose)==null?void 0:p.call(u,E=>{var W;A||(A=!0,(W=S.close)==null||W.call(S),this.connectPromise&&(this.connectPromise=null),Bd(E)&&(this.resumeState=null))}))??(()=>{});return{transport:S,close:()=>{var E;A=!0,O(),(E=S.close)==null||E.call(S),y.clientSession.close(1e3,"host_transport_closed")}}}catch(y){const S=this.dependencies.fallbackTransport;if(!S)throw y;return this.fallbackTransport=S,this.connectPromise=null,{transport:S,close:()=>{}}}}async connectWithResume(r,o){if(this.resumeState)try{return await o({binding:this.resumeState.binding,reservation:this.resumeState.reservation,onWireBytes:(c,u)=>{Hd(this.options.hostId,c,u)}})}catch(c){if(Bd(c))this.resumeState=null;else throw c}return await r({controlBaseUrl:this.options.controlBaseUrl,tunnelDomain:this.options.tunnelDomain,onWireBytes:(c,u)=>{Hd(this.options.hostId,c,u)}})}}function Bd(i){const r=i instanceof Error?i.message:String(i);return r.includes("SESSION_NOT_FOUND")||r.includes("CONNECT_TICKET_INVALID")||r.includes("SESSION_INSTANCE_MISMATCH")||r.includes("缺少 connectTicket")}class wy extends EventTarget{constructor(o,c){super();L(this,"innerSocket",null);L(this,"mutableReadyState",0);L(this,"closed",!1);o.then(u=>{if(this.closed)return;const p=u.transport.createWebSocket(c);this.innerSocket=p,this.mutableReadyState=p.readyState,p.addEventListener("open",()=>{this.mutableReadyState=1,this.dispatchEvent(new Event("open"))}),p.addEventListener("message",y=>{const S=y;this.dispatchEvent(new MessageEvent("message",{data:S.data}))}),p.addEventListener("error",y=>{const S=y;this.dispatchEvent(new ErrorEvent("error",{message:S.message}))}),p.addEventListener("close",y=>{const S=y;this.mutableReadyState=3,this.closed=!0,this.dispatchEvent(new CloseEvent("close",{code:S.code,reason:S.reason,wasClean:S.wasClean}))})}).catch(u=>{this.closed||(this.mutableReadyState=3,this.closed=!0,this.dispatchEvent(new ErrorEvent("error",{message:u instanceof Error?u.message:String(u)})),this.dispatchEvent(new CloseEvent("close",{code:1011,reason:u instanceof Error?u.message:String(u)})))})}get readyState(){var o;return((o=this.innerSocket)==null?void 0:o.readyState)??this.mutableReadyState}send(o){if(!this.innerSocket)throw new Error("当前 CodingNS Connect WebSocket 尚未建立完成");this.innerSocket.send(o)}close(o,c){if(!this.closed){if(this.closed=!0,this.mutableReadyState=2,this.innerSocket){this.innerSocket.close(o,c);return}this.mutableReadyState=3,this.dispatchEvent(new CloseEvent("close",{code:o??1e3,reason:c??""}))}}}const mn=new Map,Ud=new Map,vy=({baseUrl:i})=>{const r=mm(Z.getState(),i),o=r==null?void 0:r.relayTunnel;if(r&&(o!=null&&o.enabled)&&Ay(i,r.baseUrl,o)){const u=JSON.stringify({baseUrl:r.baseUrl,relayTunnel:o}),p=mn.get(r.id);if(p&&p.signature===u)return p.transport;p==null||p.transport.close();const y=new Nd({hostId:r.id,controlBaseUrl:o.controlBaseUrl,tunnelDomain:o.tunnelDomain},{fallbackTransport:Wd(Z.getState().platform,r.baseUrl,o.tunnelDomain)});return mn.set(r.id,{signature:u,transport:y}),y}if(r){const u=mn.get(r.id);if(u&&(u.transport.close(),mn.delete(r.id)),(o==null?void 0:o.provider)==="codingns_relay"&&!o.enabled)return qs}const c=wb(i);if(c){const u=JSON.stringify({tunnelDomain:c.tunnelDomain,controlBaseUrl:c.controlBaseUrl}),p=Ud.get(u);if(p)return p;const y=new Nd({hostId:`inferred:${c.tunnelDomain}`,controlBaseUrl:c.controlBaseUrl,tunnelDomain:c.tunnelDomain},{fallbackTransport:Wd(Z.getState().platform,i,c.tunnelDomain)});return Ud.set(u,y),y}return qs};let Cy=vy;function Dy(i){const r=Py(i);return{baseUrl:r,transport:Cy({baseUrl:r})}}function Py(i){var y;const r=Z.getState(),o=Da(r);if(!o||o.baseUrl!==i||r.platform==="web"&&((y=o.relayTunnel)!=null&&y.enabled))return i;const c=$i.getState();if(c.activeHostId!==o.id||c.candidateProbePhase!=="ready"){const S=Ca.get(o.id);return(S==null?void 0:S.baseUrl)??i}const u=c.preferredDirectCandidateEndpointId??c.preferredCandidateEndpointId;if(!u){const S=Ca.get(o.id);return(S==null?void 0:S.baseUrl)??i}const p=c.candidateEndpoints.find(S=>S.endpointId===u&&S.status==="verified");return(p==null?void 0:p.url)??i}function Ay(i,r,o){var u;const c=(u=o==null?void 0:o.candidateEndpoints)==null?void 0:u.find(p=>p.url===i);if(c)return c.kind==="relay";if(!(o!=null&&o.tunnelDomain))return!1;try{return new URL(i).hostname.toLowerCase()===o.tunnelDomain.trim().toLowerCase()}catch{try{return new URL(r).hostname.toLowerCase()===o.tunnelDomain.trim().toLowerCase()}catch{return!1}}}function Wd(i,r,o){if(i!=="web")return qs}class Ly{async request(r,o={}){const c=await this.performRequest(r,o);if(c.status===204||c.status===205)return;const u=await c.text();if(u)try{return JSON.parse(u)}catch(p){const y=p instanceof Error?`:${p.message}`:"";throw new et(0,{detail:`服务返回了无效的 JSON 响应${y}`,error_code:"INVALID_RESPONSE"})}}async requestBlob(r,o={}){return(await this.performRequest(r,o)).blob()}async requestRaw(r,o={}){return await this.performRequest(r,o)}async performRequest(r,o){var ye;const c=new Headers(o.headers),u=o.body!==void 0&&o.body!==null,p=Ry(r,o.targetHostId),y=o.targetHostId?vn():o.baseUrl??vn(),S=Dy(y),A=S.baseUrl,O=Fn(p,A),E=S.transport,W=o.omitCompatibilityHeaders||Fy(y);if(W&&Ey(c),u&&!c.has("Content-Type")&&c.set("Content-Type","application/json"),!W)for(const[ie,Q]of Object.entries(np()))c.has(ie)||c.set(ie,Q);if(!o.skipAuth){if(Me.shouldRefreshCurrentSession()){const Q=await Me.refresh();if(Q.status==="invalid")throw new et(401,{detail:"登录态已经失效,请重新登录",error_code:"UNAUTHORIZED"});if(Q.status==="deferred")throw new et(0,{detail:"登录态暂时无法恢复,请稍后重试",error_code:"AUTH_REFRESH_UNAVAILABLE"})}const ie=(ye=Me.getState().session)==null?void 0:ye.accessToken;if(!ie)throw Me.clear(),new et(401,{detail:"当前没有可用的登录态",error_code:"UNAUTHORIZED"});c.set("Authorization",`Bearer ${ie}`)}let j;try{j=await E.fetch({path:p,baseUrl:A,url:O,init:{...o,headers:c}})}catch(ie){if(!W&&My(ie)){const ee=await this.performRequest(r,{...o,omitCompatibilityHeaders:!0}).catch(()=>null);if(ee)return Qp.add(y),ee}const Q=ie instanceof Error?ie.message:"未知网络错误";throw new et(0,{detail:`请求 ${O} 失败:${Q}`,error_code:"NETWORK_ERROR"})}if(!j.ok){const ie=await Iy(j);if(Yp(j.status,ie.error_code)&&!o.targetHostId&&!o.skipAuth&&!o.retryAfterRefresh){const Q=await Me.refresh();if(Q.status==="refreshed")return this.performRequest(r,{...o,retryAfterRefresh:!0});throw Q.status==="invalid"?new et(401,{detail:"登录态已经失效,请重新登录",error_code:"UNAUTHORIZED"}):new et(0,{detail:"登录态暂时无法恢复,请稍后重试",error_code:"AUTH_REFRESH_UNAVAILABLE"})}throw!o.skipAuth&&!o.targetHostId&&Oy(j.status,ie.error_code)&&(fb(),Me.clear()),new et(j.status,ie)}return j}}const nl=new Ly;function Ry(i,r){if(!r)return i;const o=r.trim();if(!o)return i;const c=`/api/host-proxy/hosts/${encodeURIComponent(o)}`,u=i.indexOf("?"),p=u>=0?i.slice(0,u):i,y=u>=0?i.slice(u):"",S=p.startsWith("/")?p:`/${p}`;return`${c}${S}${y}`}const Qp=new Set;function Fy(i){return Qp.has(i)}function Ey(i){for(const r of Array.from(i.keys()))r.toLowerCase().startsWith("x-codingns-")&&i.delete(r)}function My(i){if(!(i instanceof Error))return!1;const r=i.message.trim().toLowerCase();return r==="load failed"||r==="failed to fetch"}async function Iy(i){const r=await i.text();if(!r)return _d(i.status);try{const o=JSON.parse(r);if(typeof o.detail=="string"&&typeof o.error_code=="string")return{detail:o.detail,error_code:o.error_code,field:typeof o.field=="string"?o.field:void 0,data:xy(o.data)?o.data:void 0,timestamp:typeof o.timestamp=="string"?o.timestamp:void 0}}catch{}return _d(i.status,r)}function _d(i,r){return{detail:(r==null?void 0:r.trim())||`请求失败(HTTP ${i})`,error_code:i===401?"UNAUTHORIZED":"HTTP_ERROR"}}function xy(i){return typeof i=="object"&&i!==null&&!Array.isArray(i)}function Yp(i,r){return i!==401?!1:r==="UNAUTHORIZED"||r==="TOKEN_EXPIRED"||r==="TOKEN_INVALID"}function Oy(i,r){return i===403&&r==="BOOTSTRAP_REQUIRED"?!0:Yp(i,r)}function $p(i){return nl.request("/api/public/bootstrap-status",{baseUrl:i,skipAuth:!0})}function Hy(i,r){return nl.request("/api/public/setup",{method:"POST",body:JSON.stringify(i),baseUrl:r,skipAuth:!0})}function Ny(i,r){return nl.request("/api/auth/login",{method:"POST",body:JSON.stringify(i),baseUrl:r,skipAuth:!0})}const Ns=Object.freeze(Object.defineProperty({__proto__:null,getBootstrapStatus:$p,loginRequest:Ny,setupRequest:Hy},Symbol.toStringTag,{value:"Module"}));async function Jp(i){try{return{...await $p(i),reachable:!0}}catch{return{initialized:!1,reachable:!1}}}const LS=Object.freeze(Object.defineProperty({__proto__:null,probeHost:Jp},Symbol.toStringTag,{value:"Module"})),By=1e4;function Xp(){return new Date().toISOString()}function Uy(i){return typeof i!="string"||!i.trim()?null:i.trim().replace(/\\/g,"/").replace(/\/+/g,"/").replace(/\/$/,"")}function Wy(i,r){return r?`local-discovered:${i}:${r}`:`local-discovered:${i}`}function _y(i){try{return new URL(i).host}catch{return i}}function Vy(i,r){return!i.dataDir&&r.dataDir||(i.pid??Number.MAX_SAFE_INTEGER)>(r.pid??Number.MAX_SAFE_INTEGER)?r:i}function zy(i){const r=new Map;for(const o of i){if(!o.baseUrl)continue;let c;try{c=Ue(o.baseUrl)}catch{continue}const u=r.get(c);if(!u){r.set(c,{...o,baseUrl:c});continue}r.set(c,Vy(u,{...o,baseUrl:c}))}return Array.from(r.values())}async function jy(i){const r=zy(i),o=Xp();return(await Promise.all(r.map(async u=>{const p=u.baseUrl;if(!p||!(await Jp(p)).reachable)return null;const S=Uy(u.dataDir),A=Wy(p,S);return{id:A,discoveryKey:A,name:_y(p),baseUrl:p,kind:"local",alias:"本机",peerEnabled:!1,peerHostId:null,createdAt:o,updatedAt:o,lastConnectedAt:null,lastUserId:null,lastUsername:null,source:"desktop-process-scan",pid:u.pid??null,executable:u.executable??null,dataDir:S,discoveredAt:o,lastReachableAt:o}}))).filter(u=>u!==null)}function RS(i){const r=new Set(i.hosts.map(o=>Ue(o.baseUrl)));return i.discoveredHosts.filter(o=>!r.has(Ue(o.baseUrl)))}function qy(i){const r=Tn(i);return r?i.hosts.find(o=>o.id===r)??i.discoveredHosts.find(o=>o.id===r)??null:null}class Gy{constructor(){L(this,"inFlight",null)}initialize(){this.refresh()}async refresh(r={}){if(this.inFlight)return this.inFlight;const o=this.performRefresh(r).finally(()=>{this.inFlight===o&&(this.inFlight=null)});return this.inFlight=o,o}setActiveDiscoveredHost(r){const o=Z.getState(),c=r&&o.discoveredHosts.some(u=>u.id===r)?r:null;c!==o.activeDiscoveredHostId&&Z.updateRuntime({activeDiscoveredHostId:c})}async performRefresh({force:r=!1}){const o=Rn(),c=Z.getState();if(!o.isDesktop||o.ui.osFamily!=="windows"&&o.ui.osFamily!=="macos"){Z.updateRuntime({discoveredHosts:[],activeDiscoveredHostId:null,localHostDiscovery:{status:"unsupported",lastScannedAt:c.localHostDiscovery.lastScannedAt,cooldownUntil:null,errorCode:"PLATFORM_NOT_SUPPORTED",errorDetail:"当前平台不支持本机 HOST 自动发现。"}});return}const u=c.localHostDiscovery.cooldownUntil?Date.parse(c.localHostDiscovery.cooldownUntil):Number.NaN;if(!r&&Number.isFinite(u)&&u>Date.now())return;Z.updateRuntime({localHostDiscovery:{...c.localHostDiscovery,status:"refreshing",errorCode:null,errorDetail:null}});const p=await o.bridge.scanLocalHosts(),y=Xp(),S=new Date(Date.now()+By).toISOString();if(!p.ok){Z.updateRuntime({localHostDiscovery:{status:p.errorCode==="PLATFORM_NOT_SUPPORTED"?"unsupported":"failed",lastScannedAt:y,cooldownUntil:S,errorCode:p.errorCode??"LOCAL_HOST_DISCOVERY_FAILED",errorDetail:p.detail??"本机 HOST 扫描失败。"}});return}const A=await jy(p.value??[]),O=qy(Z.getState()),E=zd(O)&&A.some(W=>W.id===O.id)?O.id:null;Z.updateRuntime({discoveredHosts:A,activeDiscoveredHostId:E,localHostDiscovery:{status:"ready",lastScannedAt:y,cooldownUntil:S,errorCode:null,errorDetail:null}})}}const Ky=new Gy;async function Qy(){const i=Rn();return await Z.initialize(),Ky.initialize(),ob().catch(()=>{}),{platform:i.platform}}const Yy=He.lazy(async()=>({default:(await Wt(()=>import("./App-Pe30N_Dy.js").then(r=>r.E),__vite__mapDeps([2,3]))).App}));function $y(){const[i,r]=He.useState(!1),[o,c]=He.useState(null);return He.useEffect(()=>{let u=!1;return Qy().then(()=>{u||r(!0)}).catch(p=>{u||c(p instanceof Error&&p.message.trim()?p.message:tt("shell.navigationLoadFailed"))}),()=>{u=!0}},[]),i?la.jsx(He.Suspense,{fallback:null,children:la.jsx(Yy,{})}):la.jsx("main",{className:"page-center app-shell",children:la.jsxs("section",{className:"auth-card surface-card",children:[la.jsx("h1",{children:"CodingNS"}),la.jsx("p",{className:"status-text",children:tt("common.loading")}),o?la.jsx("p",{className:"status-text","data-tone":"error",children:o}):null]})})}lm.createRoot(document.getElementById("root")).render(la.jsx($y,{}));export{AS as $,tS as A,et as B,wS as C,Fn as D,Pg as E,Ag as F,nb as G,sm as H,SS as I,vn as J,dm as K,CS as L,DS as M,PS as N,kb as O,gm as P,Pp as Q,Xy as R,iS as S,Dy as T,oS as U,hm as V,Jp as W,eS as X,Ky as Y,vS as Z,Wt as _,yS as a,sS as a0,lS as a1,fS as a2,hS as a3,mS as a4,Hg as a5,dS as a6,hp as a7,gS as a8,pp as a9,pS as aa,rS as ab,uS as ac,bS as ad,LS as ae,He as b,Rn as c,ri as d,Z as e,nS as f,Vd as g,nl as h,Da as i,la as j,zd as k,wb as l,RS as m,Ue as n,Me as o,TS as p,Tn as q,nm as r,Um as s,tt as t,sb as u,Zy as v,ym as w,cS as x,kS as y,aS as z};
50
+ `)}function xp(i,r){const o=Ln(i),c=`-----BEGIN ${r}-----`,u=`-----END ${r}-----`;if(!o.includes(c)||!o.includes(u))throw new Ne("RELAY_TUNNEL_PROTOCOL_UNSUPPORTED",`无效的 ${r} PEM`);const p=o.replace(c,"").replace(u,"").replace(/\s+/g,"");return ay(p)}function ey(i,r){if(i.length!==r.length)return!1;let o=0;for(let c=0;c<i.length;c+=1)o|=i[c]^r[c];return o===0}function Op(i){const r=i.reduce((u,p)=>u+p.length,0),o=new Uint8Array(r);let c=0;for(const u of i)o.set(u,c),c+=u.length;return o}function Hp(i){const r=new Uint8Array(i);return Up().getRandomValues(r),r}function ty(i){return Np(i)}function ii(i){return Np(i).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/g,"")}function ay(i){return Bp(i)}function yn(i){const r=i.replace(/-/g,"+").replace(/_/g,"/"),o=r.padEnd(Math.ceil(r.length/4)*4,"=");return Bp(o)}function Np(i){let r="";for(let o=0;o<i.length;o+=Od)r+=String.fromCharCode(...i.subarray(o,o+Od));return btoa(r)}function Bp(i){const r=atob(i),o=new Uint8Array(r.length);for(let c=0;c<r.length;c+=1)o[c]=r.charCodeAt(c);return o}function Be(i){return Uint8Array.from(i)}function Up(){if(typeof globalThis.crypto>"u")throw new Ne("RELAY_TUNNEL_PROTOCOL_UNSUPPORTED","当前运行环境不支持 Web Crypto");return globalThis.crypto}function ct(){return Up().subtle}const ni=new TextEncoder,Od=32768,In={name:"X25519"},iy={name:"AES-GCM",length:256},ry={name:"HMAC",hash:"SHA-256"};function ny(i){return JSON.stringify(i)}function oy(i){return JSON.parse(i)}class Wp{constructor(r,o){L(this,"listeners",new Set);L(this,"unsubscribeFromChannel");L(this,"closeListeners",new Set);L(this,"unsubscribeFromChannelClose");L(this,"connectPromise",null);L(this,"textEncoder",new TextEncoder);L(this,"textDecoder",new TextDecoder);L(this,"incomingPayloadChain",Promise.resolve());L(this,"outgoingPacketChain",Promise.resolve());L(this,"pendingPackets",[]);L(this,"closedByClient",!1);L(this,"terminationNotified",!1);L(this,"handshakeState",{status:"idle"});this.channel=r,this.options=o,this.unsubscribeFromChannel=r.subscribe(c=>{this.enqueueIncomingPayload(c)}),this.unsubscribeFromChannelClose=r.subscribeClose?r.subscribeClose(c=>{this.handleChannelClosed(c)}):null}async connect(){if(this.handshakeState.status==="ready")return;if(this.connectPromise)return await this.connectPromise;if(this.handshakeState.status==="failed")throw this.handshakeState.error;const{pendingHandshake:r,clientHello:o}=await Wb({expectedHostPublicKey:this.options.expectedHostPublicKey,expectedHostFingerprint:this.options.expectedHostFingerprint});return this.connectPromise=new Promise((c,u)=>{this.handshakeState={status:"waiting_server_hello",pendingHandshake:r,resolve:c,reject:u},this.sendControlPayload(JSON.stringify({type:"client_hello",hello:o}))}),await this.connectPromise}send(r){if(this.handshakeState.status==="ready"){this.enqueueOutgoingPacket(r,this.handshakeState.session);return}if(this.handshakeState.status==="failed")throw this.handshakeState.error;if(this.handshakeState.status==="waiting_server_hello"&&this.connectPromise){this.pendingPackets.push(r);return}throw new Error("当前 CodingNS Connect 会话尚未建立完成")}subscribe(r){return this.listeners.add(r),()=>{this.listeners.delete(r)}}subscribeClose(r){return this.closeListeners.add(r),()=>{this.closeListeners.delete(r)}}close(r,o){var c;this.closedByClient=!0,this.unsubscribeFromChannel(),(c=this.unsubscribeFromChannelClose)==null||c.call(this),this.channel.close(r,o)}async handleIncomingPayload(r){this.recordWireBytes("downstream",r);const o=JSON.parse(r);if(o.type==="server_hello"){await this.handleServerHello(o);return}if(o.type==="encrypted_frame"){await this.handleEncryptedFrame(o);return}o.type==="error"&&this.failSession(new Error(`${o.errorCode}: ${o.detail}`))}async handleServerHello(r){if(this.handshakeState.status==="waiting_server_hello")try{const o=await _b({pendingHandshake:this.handshakeState.pendingHandshake,serverHello:r.hello}),c=this.handshakeState.resolve;this.handshakeState={status:"ready",session:o},this.connectPromise=null,await this.flushPendingPackets(o),c()}catch(o){this.failSession(Ki(o))}}async handleEncryptedFrame(r){const o=this.requireReadySession();try{const c=await zb(o.session,r.frame);if(!c)return;const u=oy(this.textDecoder.decode(c));for(const p of this.listeners)p(u)}catch(c){this.failSession(Ki(c))}}requireReadySession(){if(this.handshakeState.status==="failed")throw this.handshakeState.error;if(this.handshakeState.status!=="ready")throw new Error("当前 CodingNS Connect 会话尚未建立完成");return this.handshakeState}failSession(r){if(this.pendingPackets=[],this.handshakeState.status==="waiting_server_hello"){const o=this.handshakeState.reject;this.handshakeState={status:"failed",error:r},this.connectPromise=null,this.notifyTermination(r),o(r);return}this.handshakeState={status:"failed",error:r},this.connectPromise=null,this.notifyTermination(r)}handleChannelClosed(r){this.closedByClient||this.failSession(r)}sendControlPayload(r){return this.recordWireBytes("upstream",r),this.channel.send(r)}enqueueIncomingPayload(r){this.incomingPayloadChain=this.incomingPayloadChain.catch(()=>{}).then(async()=>{await this.handleIncomingPayload(r)}).catch(o=>{this.failSession(Ki(o))})}async flushPendingPackets(r){const o=this.pendingPackets;if(o.length!==0){this.pendingPackets=[];for(const c of o)await this.sendEncryptedPacket(c,r)}}enqueueOutgoingPacket(r,o){this.outgoingPacketChain=this.outgoingPacketChain.catch(()=>{}).then(async()=>{await this.sendEncryptedPacket(r,o)}).catch(c=>{this.failSession(Ki(c))})}async sendEncryptedPacket(r,o){try{const c=await Vb(o,ny(r));await this.sendControlPayload(JSON.stringify({type:"encrypted_frame",frame:c}))}catch(c){const u=Ki(c);throw this.failSession(u),u}}recordWireBytes(r,o){var c,u;(u=(c=this.options).onWireBytes)==null||u.call(c,r,this.textEncoder.encode(o).byteLength)}notifyTermination(r){if(!this.terminationNotified){this.terminationNotified=!0;for(const o of this.closeListeners)o(r)}}}function Ki(i){return i instanceof Error?i:new Error(String(i))}const _p=3,sy=250;async function ly(i){const r=i.fetchFn??fetch,o=new URL(`/api/v1/tunnels/${encodeURIComponent(hy(i.tunnelDomain))}/connect-init`,qp(i.controlBaseUrl)).toString(),c=await r(o,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({clientContext:my()})});if(!c.ok)throw await fy(c,"初始化隧道连接失败");return await c.json()}async function cy(i,r={}){const o=await ly({controlBaseUrl:i.controlBaseUrl,tunnelDomain:i.tunnelDomain,fetchFn:r.fetchFn}),c={bindingId:o.bindingId,tunnelDomain:o.tunnelDomain,hostPublicKey:o.hostPublicKey,hostFingerprint:o.hostFingerprint,relayBaseUrl:o.relayBaseUrl,controlBaseUrl:o.controlBaseUrl,status:o.status},u={sessionId:o.sessionId,bindingId:o.bindingId,tunnelDomain:o.tunnelDomain,connectTicket:o.connectTicket,remainingBytes:o.remainingBytes,sessionRateLimitBytesPerSecond:o.sessionRateLimitBytesPerSecond,upstreamConnected:o.upstreamConnected,downstreamConnected:o.downstreamConnected,expiresAt:o.expiresAt},y=(r.createWebSocket??Gp)(zp(c.relayBaseUrl,u.sessionId,Kp(u)));return await jp(y),{binding:c,reservation:u,channel:new Vp(y)}}async function uy(i,r={}){const c=(r.createWebSocket??Gp)(zp(i.binding.relayBaseUrl,i.reservation.sessionId,Kp(i.reservation)));return await jp(c),{binding:i.binding,reservation:i.reservation,channel:new Vp(c)}}async function dy(i,r={}){let o=null;for(let c=1;c<=_p;c+=1){let u=null;try{u=await cy(i,r);const p=new Wp(u.channel,{expectedHostPublicKey:u.binding.hostPublicKey,expectedHostFingerprint:u.binding.hostFingerprint,onWireBytes:i.onWireBytes});return await p.connect(),{...u,clientSession:p}}catch(p){const y=Ty(p);if(o=y,u==null||u.channel.close(1011,"relay_client_session_connect_failed"),!yy(y,c))throw y;await Sy(sy*c)}}throw o??new Error("当前 CodingNS Connect 会话建立失败")}async function py(i,r={}){const o=await uy({binding:i.binding,reservation:i.reservation},r),c=new Wp(o.channel,{expectedHostPublicKey:o.binding.hostPublicKey,expectedHostFingerprint:o.binding.hostFingerprint,onWireBytes:i.onWireBytes});return await c.connect(),{...o,clientSession:c}}class Vp{constructor(r){L(this,"terminalError",null);L(this,"closeNotified",!1);L(this,"closeListeners",new Set);L(this,"handleClose",r=>{const o=r;this.terminalError=new Error(`relay-edge 原始链路关闭:${o.code}${o.reason?` ${o.reason}`:""}`),this.notifyClose(this.terminalError)});L(this,"handleError",()=>{this.terminalError||(this.terminalError=new Error("relay-edge 原始链路建立失败")),this.notifyClose(this.terminalError)});this.socket=r,this.socket.addEventListener("close",this.handleClose),this.socket.addEventListener("error",this.handleError)}send(r){if(this.socket.readyState!==1)throw this.terminalError??new Error("当前 relay-edge 原始链路尚未建立完成");this.socket.send(r)}subscribe(r){const o=c=>{const u=c;typeof u.data=="string"&&r(u.data)};return this.socket.addEventListener("message",o),()=>{this.socket.removeEventListener("message",o)}}subscribeClose(r){return this.closeListeners.add(r),()=>{this.closeListeners.delete(r)}}close(r,o){this.socket.removeEventListener("close",this.handleClose),this.socket.removeEventListener("error",this.handleError),this.socket.close(r,o)}notifyClose(r){if(!this.closeNotified){this.closeNotified=!0;for(const o of this.closeListeners)o(r)}}}function zp(i,r,o){const c=by(i,"ws");return c.searchParams.set("sessionId",r),c.searchParams.set("role","downstream"),c.searchParams.set("connectTicket",o),c.protocol=c.protocol==="https:"||c.protocol==="wss:"?"wss:":"ws:",c.toString()}async function jp(i){i.readyState!==1&&await new Promise((r,o)=>{const c=()=>{y(),r()},u=S=>{y();const A=S;o(new Error(`relay-edge 原始链路关闭:${A.code}${A.reason?` ${A.reason}`:""}`))},p=()=>{y(),o(new Error("relay-edge 原始链路建立失败"))},y=()=>{i.removeEventListener("open",c),i.removeEventListener("close",u),i.removeEventListener("error",p)};i.addEventListener("open",c),i.addEventListener("close",u),i.addEventListener("error",p)})}async function fy(i,r){const c=(await i.text()).trim();if(!c)return new Error(`${r}(HTTP ${i.status})`);try{const u=JSON.parse(c);if(typeof u.detail=="string"&&typeof u.errorCode=="string")return new Error(`${u.errorCode}: ${u.detail}`)}catch{}return new Error(`${r}:${c}`)}function hy(i){const r=i.trim().toLowerCase();if(!r)throw new Error("tunnelDomain 不能为空");return r}function qp(i){return i.endsWith("/")?i:`${i}/`}function my(){const i=Z.getState().platform??null,r=typeof navigator>"u"?null:Sn(navigator.userAgent),o=typeof navigator>"u"?null:Sn(navigator.platform),c=typeof navigator>"u"?null:Sn(navigator.language),u=gy();return{runtimePlatform:i,systemPlatform:o,userAgent:r,language:c,timezone:u}}function gy(){try{return Sn(Intl.DateTimeFormat().resolvedOptions().timeZone)}catch{return null}}function by(i,r){return new URL(r.replace(/^\/+/,""),qp(i))}function Gp(i){return new WebSocket(i)}function Kp(i){var o;const r=(o=i.connectTicket)==null?void 0:o.trim();if(!r)throw new Error("当前 CodingNS Connect 会话缺少 connectTicket,不能继续续接");return r}function yy(i,r){if(r>=_p)return!1;const o=i.message;return o.includes("relay-edge 原始链路")||o.includes("HOST_NOT_CONNECTED")||o.includes("HOST_UPSTREAM_DISCONNECTED")}async function Sy(i){await new Promise(r=>{setTimeout(r,i)})}function Sn(i){const r=i==null?void 0:i.trim();return r||null}function Ty(i){return i instanceof Error?i:new Error(String(i))}const Hs={startedAt:null,updatedAt:null,upstreamBytes:0,downstreamBytes:0,totalBytes:0};class ky{constructor(){L(this,"state",{byHostId:{}});L(this,"listeners",new Set);L(this,"subscribe",r=>(this.listeners.add(r),()=>{this.listeners.delete(r)}));Me.subscribe(()=>{Me.getState().session||this.reset()})}getSummary(r){return r?this.state.byHostId[r]??Hs:Hs}recordWireBytes(r,o,c){if(!r||!Number.isFinite(c)||c<=0)return;const u=this.state.byHostId[r]??Hs,p=new Date().toISOString(),y={startedAt:u.startedAt??p,updatedAt:p,upstreamBytes:o==="upstream"?u.upstreamBytes+c:u.upstreamBytes,downstreamBytes:o==="downstream"?u.downstreamBytes+c:u.downstreamBytes,totalBytes:u.totalBytes+c};this.state={byHostId:{...this.state.byHostId,[r]:y}},this.emit()}reset(){Object.keys(this.state.byHostId).length!==0&&(this.state={byHostId:{}},this.emit())}emit(){for(const r of this.listeners)r()}}const Ks=new ky;function Hd(i,r,o){Ks.recordWireBytes(i,r,o)}function AS(i){return He.useSyncExternalStore(Ks.subscribe,()=>Ks.getSummary(i))}class Nd{constructor(r,o={}){L(this,"connectPromise",null);L(this,"fallbackTransport",null);L(this,"resumeState",null);this.options=r,this.dependencies=o}async fetch(r){return await(await this.getActiveTransport()).transport.fetch(r)}createWebSocket(r){return new wy(this.getActiveTransport(),r)}close(){const r=this.connectPromise;this.connectPromise=null,this.fallbackTransport=null,this.resumeState=null,r&&r.then(o=>{o.close()}).catch(()=>{})}async getActiveTransport(){return this.fallbackTransport?{transport:this.fallbackTransport,close:()=>{}}:(this.connectPromise||(this.connectPromise=this.createActiveTransport()),await this.connectPromise)}async createActiveTransport(){var u,p;const r=this.dependencies.connectSession??dy,o=this.dependencies.resumeSession??py,c=this.dependencies.createTransport??(y=>new Cb(y));try{const y=await this.connectWithResume(r,o),S=c(y.clientSession);this.resumeState={binding:y.binding,reservation:y.reservation};let A=!1;const O=((p=(u=y.clientSession).subscribeClose)==null?void 0:p.call(u,E=>{var W;A||(A=!0,(W=S.close)==null||W.call(S),this.connectPromise&&(this.connectPromise=null),Bd(E)&&(this.resumeState=null))}))??(()=>{});return{transport:S,close:()=>{var E;A=!0,O(),(E=S.close)==null||E.call(S),y.clientSession.close(1e3,"host_transport_closed")}}}catch(y){const S=this.dependencies.fallbackTransport;if(!S)throw y;return this.fallbackTransport=S,this.connectPromise=null,{transport:S,close:()=>{}}}}async connectWithResume(r,o){if(this.resumeState)try{return await o({binding:this.resumeState.binding,reservation:this.resumeState.reservation,onWireBytes:(c,u)=>{Hd(this.options.hostId,c,u)}})}catch(c){if(Bd(c))this.resumeState=null;else throw c}return await r({controlBaseUrl:this.options.controlBaseUrl,tunnelDomain:this.options.tunnelDomain,onWireBytes:(c,u)=>{Hd(this.options.hostId,c,u)}})}}function Bd(i){const r=i instanceof Error?i.message:String(i);return r.includes("SESSION_NOT_FOUND")||r.includes("CONNECT_TICKET_INVALID")||r.includes("SESSION_INSTANCE_MISMATCH")||r.includes("缺少 connectTicket")}class wy extends EventTarget{constructor(o,c){super();L(this,"innerSocket",null);L(this,"mutableReadyState",0);L(this,"closed",!1);o.then(u=>{if(this.closed)return;const p=u.transport.createWebSocket(c);this.innerSocket=p,this.mutableReadyState=p.readyState,p.addEventListener("open",()=>{this.mutableReadyState=1,this.dispatchEvent(new Event("open"))}),p.addEventListener("message",y=>{const S=y;this.dispatchEvent(new MessageEvent("message",{data:S.data}))}),p.addEventListener("error",y=>{const S=y;this.dispatchEvent(new ErrorEvent("error",{message:S.message}))}),p.addEventListener("close",y=>{const S=y;this.mutableReadyState=3,this.closed=!0,this.dispatchEvent(new CloseEvent("close",{code:S.code,reason:S.reason,wasClean:S.wasClean}))})}).catch(u=>{this.closed||(this.mutableReadyState=3,this.closed=!0,this.dispatchEvent(new ErrorEvent("error",{message:u instanceof Error?u.message:String(u)})),this.dispatchEvent(new CloseEvent("close",{code:1011,reason:u instanceof Error?u.message:String(u)})))})}get readyState(){var o;return((o=this.innerSocket)==null?void 0:o.readyState)??this.mutableReadyState}send(o){if(!this.innerSocket)throw new Error("当前 CodingNS Connect WebSocket 尚未建立完成");this.innerSocket.send(o)}close(o,c){if(!this.closed){if(this.closed=!0,this.mutableReadyState=2,this.innerSocket){this.innerSocket.close(o,c);return}this.mutableReadyState=3,this.dispatchEvent(new CloseEvent("close",{code:o??1e3,reason:c??""}))}}}const mn=new Map,Ud=new Map,vy=({baseUrl:i})=>{const r=mm(Z.getState(),i),o=r==null?void 0:r.relayTunnel;if(r&&(o!=null&&o.enabled)&&Ay(i,r.baseUrl,o)){const u=JSON.stringify({baseUrl:r.baseUrl,relayTunnel:o}),p=mn.get(r.id);if(p&&p.signature===u)return p.transport;p==null||p.transport.close();const y=new Nd({hostId:r.id,controlBaseUrl:o.controlBaseUrl,tunnelDomain:o.tunnelDomain},{fallbackTransport:Wd(Z.getState().platform,r.baseUrl,o.tunnelDomain)});return mn.set(r.id,{signature:u,transport:y}),y}if(r){const u=mn.get(r.id);if(u&&(u.transport.close(),mn.delete(r.id)),(o==null?void 0:o.provider)==="codingns_relay"&&!o.enabled)return qs}const c=wb(i);if(c){const u=JSON.stringify({tunnelDomain:c.tunnelDomain,controlBaseUrl:c.controlBaseUrl}),p=Ud.get(u);if(p)return p;const y=new Nd({hostId:`inferred:${c.tunnelDomain}`,controlBaseUrl:c.controlBaseUrl,tunnelDomain:c.tunnelDomain},{fallbackTransport:Wd(Z.getState().platform,i,c.tunnelDomain)});return Ud.set(u,y),y}return qs};let Cy=vy;function Dy(i){const r=Py(i);return{baseUrl:r,transport:Cy({baseUrl:r})}}function Py(i){var y;const r=Z.getState(),o=Da(r);if(!o||o.baseUrl!==i||r.platform==="web"&&((y=o.relayTunnel)!=null&&y.enabled))return i;const c=$i.getState();if(c.activeHostId!==o.id||c.candidateProbePhase!=="ready"){const S=Ca.get(o.id);return(S==null?void 0:S.baseUrl)??i}const u=c.preferredDirectCandidateEndpointId??c.preferredCandidateEndpointId;if(!u){const S=Ca.get(o.id);return(S==null?void 0:S.baseUrl)??i}const p=c.candidateEndpoints.find(S=>S.endpointId===u&&S.status==="verified");return(p==null?void 0:p.url)??i}function Ay(i,r,o){var u;const c=(u=o==null?void 0:o.candidateEndpoints)==null?void 0:u.find(p=>p.url===i);if(c)return c.kind==="relay";if(!(o!=null&&o.tunnelDomain))return!1;try{return new URL(i).hostname.toLowerCase()===o.tunnelDomain.trim().toLowerCase()}catch{try{return new URL(r).hostname.toLowerCase()===o.tunnelDomain.trim().toLowerCase()}catch{return!1}}}function Wd(i,r,o){if(i!=="web")return qs}class Ly{async request(r,o={}){const c=await this.performRequest(r,o);if(c.status===204||c.status===205)return;const u=await c.text();if(u)try{return JSON.parse(u)}catch(p){const y=p instanceof Error?`:${p.message}`:"";throw new et(0,{detail:`服务返回了无效的 JSON 响应${y}`,error_code:"INVALID_RESPONSE"})}}async requestBlob(r,o={}){return(await this.performRequest(r,o)).blob()}async requestRaw(r,o={}){return await this.performRequest(r,o)}async performRequest(r,o){var ye;const c=new Headers(o.headers),u=o.body!==void 0&&o.body!==null,p=Ry(r,o.targetHostId),y=o.targetHostId?vn():o.baseUrl??vn(),S=Dy(y),A=S.baseUrl,O=Fn(p,A),E=S.transport,W=o.omitCompatibilityHeaders||Fy(y);if(W&&Ey(c),u&&!c.has("Content-Type")&&c.set("Content-Type","application/json"),!W)for(const[ie,Q]of Object.entries(np()))c.has(ie)||c.set(ie,Q);if(!o.skipAuth){if(Me.shouldRefreshCurrentSession()){const Q=await Me.refresh();if(Q.status==="invalid")throw new et(401,{detail:"登录态已经失效,请重新登录",error_code:"UNAUTHORIZED"});if(Q.status==="deferred")throw new et(0,{detail:"登录态暂时无法恢复,请稍后重试",error_code:"AUTH_REFRESH_UNAVAILABLE"})}const ie=(ye=Me.getState().session)==null?void 0:ye.accessToken;if(!ie)throw Me.clear(),new et(401,{detail:"当前没有可用的登录态",error_code:"UNAUTHORIZED"});c.set("Authorization",`Bearer ${ie}`)}let j;try{j=await E.fetch({path:p,baseUrl:A,url:O,init:{...o,headers:c}})}catch(ie){if(!W&&My(ie)){const ee=await this.performRequest(r,{...o,omitCompatibilityHeaders:!0}).catch(()=>null);if(ee)return Qp.add(y),ee}const Q=ie instanceof Error?ie.message:"未知网络错误";throw new et(0,{detail:`请求 ${O} 失败:${Q}`,error_code:"NETWORK_ERROR"})}if(!j.ok){const ie=await Iy(j);if(Yp(j.status,ie.error_code)&&!o.targetHostId&&!o.skipAuth&&!o.retryAfterRefresh){const Q=await Me.refresh();if(Q.status==="refreshed")return this.performRequest(r,{...o,retryAfterRefresh:!0});throw Q.status==="invalid"?new et(401,{detail:"登录态已经失效,请重新登录",error_code:"UNAUTHORIZED"}):new et(0,{detail:"登录态暂时无法恢复,请稍后重试",error_code:"AUTH_REFRESH_UNAVAILABLE"})}throw!o.skipAuth&&!o.targetHostId&&Oy(j.status,ie.error_code)&&(fb(),Me.clear()),new et(j.status,ie)}return j}}const nl=new Ly;function Ry(i,r){if(!r)return i;const o=r.trim();if(!o)return i;const c=`/api/host-proxy/hosts/${encodeURIComponent(o)}`,u=i.indexOf("?"),p=u>=0?i.slice(0,u):i,y=u>=0?i.slice(u):"",S=p.startsWith("/")?p:`/${p}`;return`${c}${S}${y}`}const Qp=new Set;function Fy(i){return Qp.has(i)}function Ey(i){for(const r of Array.from(i.keys()))r.toLowerCase().startsWith("x-codingns-")&&i.delete(r)}function My(i){if(!(i instanceof Error))return!1;const r=i.message.trim().toLowerCase();return r==="load failed"||r==="failed to fetch"}async function Iy(i){const r=await i.text();if(!r)return _d(i.status);try{const o=JSON.parse(r);if(typeof o.detail=="string"&&typeof o.error_code=="string")return{detail:o.detail,error_code:o.error_code,field:typeof o.field=="string"?o.field:void 0,data:xy(o.data)?o.data:void 0,timestamp:typeof o.timestamp=="string"?o.timestamp:void 0}}catch{}return _d(i.status,r)}function _d(i,r){return{detail:(r==null?void 0:r.trim())||`请求失败(HTTP ${i})`,error_code:i===401?"UNAUTHORIZED":"HTTP_ERROR"}}function xy(i){return typeof i=="object"&&i!==null&&!Array.isArray(i)}function Yp(i,r){return i!==401?!1:r==="UNAUTHORIZED"||r==="TOKEN_EXPIRED"||r==="TOKEN_INVALID"}function Oy(i,r){return i===403&&r==="BOOTSTRAP_REQUIRED"?!0:Yp(i,r)}function $p(i){return nl.request("/api/public/bootstrap-status",{baseUrl:i,skipAuth:!0})}function Hy(i,r){return nl.request("/api/public/setup",{method:"POST",body:JSON.stringify(i),baseUrl:r,skipAuth:!0})}function Ny(i,r){return nl.request("/api/auth/login",{method:"POST",body:JSON.stringify(i),baseUrl:r,skipAuth:!0})}const Ns=Object.freeze(Object.defineProperty({__proto__:null,getBootstrapStatus:$p,loginRequest:Ny,setupRequest:Hy},Symbol.toStringTag,{value:"Module"}));async function Jp(i){try{return{...await $p(i),reachable:!0}}catch{return{initialized:!1,reachable:!1}}}const LS=Object.freeze(Object.defineProperty({__proto__:null,probeHost:Jp},Symbol.toStringTag,{value:"Module"})),By=1e4;function Xp(){return new Date().toISOString()}function Uy(i){return typeof i!="string"||!i.trim()?null:i.trim().replace(/\\/g,"/").replace(/\/+/g,"/").replace(/\/$/,"")}function Wy(i,r){return r?`local-discovered:${i}:${r}`:`local-discovered:${i}`}function _y(i){try{return new URL(i).host}catch{return i}}function Vy(i,r){return!i.dataDir&&r.dataDir||(i.pid??Number.MAX_SAFE_INTEGER)>(r.pid??Number.MAX_SAFE_INTEGER)?r:i}function zy(i){const r=new Map;for(const o of i){if(!o.baseUrl)continue;let c;try{c=Ue(o.baseUrl)}catch{continue}const u=r.get(c);if(!u){r.set(c,{...o,baseUrl:c});continue}r.set(c,Vy(u,{...o,baseUrl:c}))}return Array.from(r.values())}async function jy(i){const r=zy(i),o=Xp();return(await Promise.all(r.map(async u=>{const p=u.baseUrl;if(!p||!(await Jp(p)).reachable)return null;const S=Uy(u.dataDir),A=Wy(p,S);return{id:A,discoveryKey:A,name:_y(p),baseUrl:p,kind:"local",alias:"本机",peerEnabled:!1,peerHostId:null,createdAt:o,updatedAt:o,lastConnectedAt:null,lastUserId:null,lastUsername:null,source:"desktop-process-scan",pid:u.pid??null,executable:u.executable??null,dataDir:S,discoveredAt:o,lastReachableAt:o}}))).filter(u=>u!==null)}function RS(i){const r=new Set(i.hosts.map(o=>Ue(o.baseUrl)));return i.discoveredHosts.filter(o=>!r.has(Ue(o.baseUrl)))}function qy(i){const r=Tn(i);return r?i.hosts.find(o=>o.id===r)??i.discoveredHosts.find(o=>o.id===r)??null:null}class Gy{constructor(){L(this,"inFlight",null)}initialize(){this.refresh()}async refresh(r={}){if(this.inFlight)return this.inFlight;const o=this.performRefresh(r).finally(()=>{this.inFlight===o&&(this.inFlight=null)});return this.inFlight=o,o}setActiveDiscoveredHost(r){const o=Z.getState(),c=r&&o.discoveredHosts.some(u=>u.id===r)?r:null;c!==o.activeDiscoveredHostId&&Z.updateRuntime({activeDiscoveredHostId:c})}async performRefresh({force:r=!1}){const o=Rn(),c=Z.getState();if(!o.isDesktop||o.ui.osFamily!=="windows"&&o.ui.osFamily!=="macos"){Z.updateRuntime({discoveredHosts:[],activeDiscoveredHostId:null,localHostDiscovery:{status:"unsupported",lastScannedAt:c.localHostDiscovery.lastScannedAt,cooldownUntil:null,errorCode:"PLATFORM_NOT_SUPPORTED",errorDetail:"当前平台不支持本机 HOST 自动发现。"}});return}const u=c.localHostDiscovery.cooldownUntil?Date.parse(c.localHostDiscovery.cooldownUntil):Number.NaN;if(!r&&Number.isFinite(u)&&u>Date.now())return;Z.updateRuntime({localHostDiscovery:{...c.localHostDiscovery,status:"refreshing",errorCode:null,errorDetail:null}});const p=await o.bridge.scanLocalHosts(),y=Xp(),S=new Date(Date.now()+By).toISOString();if(!p.ok){Z.updateRuntime({localHostDiscovery:{status:p.errorCode==="PLATFORM_NOT_SUPPORTED"?"unsupported":"failed",lastScannedAt:y,cooldownUntil:S,errorCode:p.errorCode??"LOCAL_HOST_DISCOVERY_FAILED",errorDetail:p.detail??"本机 HOST 扫描失败。"}});return}const A=await jy(p.value??[]),O=qy(Z.getState()),E=zd(O)&&A.some(W=>W.id===O.id)?O.id:null;Z.updateRuntime({discoveredHosts:A,activeDiscoveredHostId:E,localHostDiscovery:{status:"ready",lastScannedAt:y,cooldownUntil:S,errorCode:null,errorDetail:null}})}}const Ky=new Gy;async function Qy(){const i=Rn();return await Z.initialize(),Ky.initialize(),ob().catch(()=>{}),{platform:i.platform}}const Yy=He.lazy(async()=>({default:(await Wt(()=>import("./App-CHsm-VrM.js").then(r=>r.E),__vite__mapDeps([2,3]))).App}));function $y(){const[i,r]=He.useState(!1),[o,c]=He.useState(null);return He.useEffect(()=>{let u=!1;return Qy().then(()=>{u||r(!0)}).catch(p=>{u||c(p instanceof Error&&p.message.trim()?p.message:tt("shell.navigationLoadFailed"))}),()=>{u=!0}},[]),i?la.jsx(He.Suspense,{fallback:null,children:la.jsx(Yy,{})}):la.jsx("main",{className:"page-center app-shell",children:la.jsxs("section",{className:"auth-card surface-card",children:[la.jsx("h1",{children:"CodingNS"}),la.jsx("p",{className:"status-text",children:tt("common.loading")}),o?la.jsx("p",{className:"status-text","data-tone":"error",children:o}):null]})})}lm.createRoot(document.getElementById("root")).render(la.jsx($y,{}));export{AS as $,tS as A,et as B,wS as C,Fn as D,Pg as E,Ag as F,nb as G,sm as H,SS as I,vn as J,dm as K,CS as L,DS as M,PS as N,kb as O,gm as P,Pp as Q,Xy as R,iS as S,Dy as T,oS as U,hm as V,Jp as W,eS as X,Ky as Y,vS as Z,Wt as _,yS as a,sS as a0,lS as a1,fS as a2,hS as a3,mS as a4,Hg as a5,dS as a6,hp as a7,gS as a8,pp as a9,pS as aa,rS as ab,uS as ac,bS as ad,LS as ae,He as b,Rn as c,ri as d,Z as e,nS as f,Vd as g,nl as h,Da as i,la as j,zd as k,wb as l,RS as m,Ue as n,Me as o,TS as p,Tn as q,nm as r,Um as s,tt as t,sb as u,Zy as v,ym as w,cS as x,kS as y,aS as z};