dsh-home-hosted 0.1.0 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/docs/DESIGN.md CHANGED
@@ -41,6 +41,15 @@ CLI that will parse it next. Below 0.6.0 the write is refused with
41
41
  `KILL_UNSUPPORTED` and the page offers the fix it already has — replace the panel
42
42
  with the preferred copy, or choose another policy.
43
43
 
44
+ ## macOS: reachable launchd is not a requirement
45
+
46
+ A plist in `~/Library/LaunchAgents` is loaded by launchd at the next login whether
47
+ or not the process that wrote it can reach `gui/$UID` (SSH sessions often cannot).
48
+ So the agent stays `available` and its install writes the plist and reports "loads
49
+ at the next login" instead of refusing; only the `bootstrap`/`enable`/`print`
50
+ steps need the domain, and they are skipped when it is unreachable. The daemon
51
+ scope still needs root for `/Library/LaunchDaemons`.
52
+
44
53
  ## Starting and replacing the panel
45
54
 
46
55
  `panel.start` runs the preferred CLI's `up`, which detaches itself and returns
package/lib/client.js CHANGED
@@ -1,9 +1,10 @@
1
1
  window.__ModuleLoader__.load({ id: "dsh-home-hosted", factory: (require) => {
2
2
  var module = { exports: {} }; var exports = module.exports;
3
- "use strict";var G=Object.defineProperty;var Be=Object.getOwnPropertyDescriptor;var Ie=Object.getOwnPropertyNames;var Me=Object.prototype.hasOwnProperty;var De=(e,t)=>{for(var n in t)G(e,n,{get:t[n],enumerable:!0})},Ue=(e,t,n,s)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of Ie(t))!Me.call(e,r)&&r!==n&&G(e,r,{get:()=>t[r],enumerable:!(s=Be(t,r))||s.enumerable});return e};var $e=e=>Ue(G({},"__esModule",{value:!0}),e);var it={};De(it,{apply:()=>st,inject:()=>rt});module.exports=$e(it);var $="homeHosted",K={tab:"Home Hosted",pageDesc:"Boot autostart and home-hosted server management.",loading:"Loading\u2026",refresh:"Refresh",retry:"Retry",errorTitle:"Error",statusUnavailable:"The panel did not answer.",yes:"Yes",no:"No",copy:"Copy",copied:"Copied",panelTitle:"Panel",panelDesc:"Reachability and identity of the home-hosted panel.",panelReachable:"Reachable",panelHome:"$HHOSTED_HOME",panelUrl:"URL",panelVersion:"Version",panelPid:"PID",panelWriteVia:"Writes via",panelToken:"API token",panelCliSource:"CLI",panelCliPath:"CLI path",panelCliConfig:"configured command",panelCliDependency:"pinned dependency",panelCliPathSource:"global install (PATH)",panelCliMissing:"not found",panelCliNotPinned:"This host uses a global home-hosted instead of the plugin's pinned copy ({range}); reinstall the plugin with its dependencies to use the pinned one.",panelCliLauncherFailed:"The boot launcher did not answer; a boot entry may fail to start the panel.",panelStart:"Start the panel",panelReplace:"Replace with {version}",panelAlreadyPreferred:"The running panel is already the preferred copy.",panelTakeoverTitle:"Replace the running panel?",panelTakeoverBody:"This stops the running panel and every server it supervises \u2014 including this dsh, so this page disconnects. It only works when the dsh entry is adopted with autostart enabled.",confirmCancel:"Cancel",confirmReplace:"Replace",writeViaApi:"authenticated API",writeViaFile:"config file",writeViaNone:"unavailable",tokenEnrolled:"enrolled",tokenPresent:"present",tokenAbsent:"absent",tokenUnknown:"unknown",optionsTitle:"Options",optionsDesc:"Which home-hosted to run, and how to get a global copy.",optionsCliUnavailable:"The host did not report any CLI information.",optionsCurrent:"CLI in use",optionsVersion:"Version",optionsPath:"Path",optionsPreferPinned:"Pinned dependency (recommended)",optionsPreferGlobal:"Global install (PATH)",optionsNotResolved:"not resolved",optionsPreferHint:"This choice decides which copy boot autostart and the panel actions run.",optionsInstallHint:"No global home-hosted was found. Install the pinned range, then pick the global copy above:",optionsInstall:"Install globally",optionsOutput:"Command output",optionsConfigOverride:"The plugin row's homeHostedCommand overrides this choice.",bootTitle:"Boot autostart",bootDesc:"Start the panel automatically when the machine boots.",bootEnabled:"Enable autostart",bootMechanism:"Mechanism",bootMechanismAuto:"Automatic (recommended)",bootState:"State",bootStateNotInstalled:"not installed",bootStateInstalledDisabled:"installed, disabled",bootStateEnabledRunning:"enabled, running",bootStateEnabledFailing:"enabled, failing",bootStateUnsupported:"unsupported",bootBootCapable:"Starts before login",bootPrivileged:"This process can install it",bootUnitPath:"Unit path",bootCommands:"Manual commands",bootCommandsExplain:"This process could not elevate. Run these commands yourself to install autostart:",bootRecheck:"Re-check",entriesTitle:"Managed entries",entriesDesc:"What this plugin wants each entry to be, and what the panel reports.",entriesEmpty:"No managed entries are configured yet.",entriesExists:"exists",entriesMissing:"missing",entriesManaged:"managed",entriesUnmanaged:"unmanaged",entriesDrift:"Drift",entriesLive:"Live",entriesNotRunning:"not running",entriesAutostart:"Autostart",entriesOnPortConflict:"On port conflict",entriesStopKillPortHolders:"Stop port holders",entriesAdopt:"Adopt",entriesPause:"Pause",entriesRestore:"Restore",agentTitle:"Agent tools",agentDesc:"Which of this plugin\u2019s tools the agent may call.",agentMaster:"Enable agent tools",agentApproval:"Mutating tools ask for approval before they run.",agentToolMutating:"{name} \xB7 asks approval",serversTitle:"Servers",serversDesc:"Servers supervised by the panel.",serversHintPanel:"Add, edit and remove entries in the home-hosted panel: {url}",serversHintNoPanel:"Add, edit and remove entries in the home-hosted panel (it is not running right now).",serversEmpty:"The panel reports no servers.",serversPid:"PID",serversUrl:"URL",serversStart:"Start",serversStop:"Stop",serversRestart:"Restart"},te={tab:"Home Hosted",pageDesc:"\u5F00\u673A\u81EA\u542F\u4E0E home-hosted \u670D\u52A1\u5668\u7BA1\u7406\u3002",loading:"\u52A0\u8F7D\u4E2D\u2026",refresh:"\u5237\u65B0",retry:"\u91CD\u8BD5",errorTitle:"\u9519\u8BEF",statusUnavailable:"\u9762\u677F\u6CA1\u6709\u54CD\u5E94\u3002",yes:"\u662F",no:"\u5426",copy:"\u590D\u5236",copied:"\u5DF2\u590D\u5236",panelTitle:"\u9762\u677F",panelDesc:"home-hosted \u9762\u677F\u7684\u53EF\u8FBE\u6027\u4E0E\u8EAB\u4EFD\u3002",panelReachable:"\u53EF\u8FBE",panelHome:"$HHOSTED_HOME",panelUrl:"URL",panelVersion:"\u7248\u672C",panelPid:"PID",panelWriteVia:"\u5199\u5165\u65B9\u5F0F",panelToken:"API \u4EE4\u724C",panelCliSource:"CLI",panelCliPath:"CLI \u8DEF\u5F84",panelCliConfig:"\u914D\u7F6E\u7684\u547D\u4EE4",panelCliDependency:"\u56FA\u5B9A\u7684\u4F9D\u8D56\u7248\u672C",panelCliPathSource:"\u5168\u5C40\u5B89\u88C5\uFF08PATH\uFF09",panelCliMissing:"\u672A\u627E\u5230",panelCliNotPinned:"\u6B64\u5BBF\u4E3B\u4F7F\u7528\u5168\u5C40 home-hosted\uFF0C\u800C\u4E0D\u662F\u63D2\u4EF6\u56FA\u5B9A\u7684\u526F\u672C\uFF08{range}\uFF09\uFF1B\u91CD\u65B0\u5B89\u88C5\u63D2\u4EF6\u53CA\u5176\u4F9D\u8D56\u5373\u53EF\u4F7F\u7528\u56FA\u5B9A\u7248\u672C\u3002",panelCliLauncherFailed:"\u542F\u52A8\u5668\u6CA1\u6709\u5E94\u7B54\uFF1B\u5F00\u673A\u9879\u53EF\u80FD\u65E0\u6CD5\u542F\u52A8\u9762\u677F\u3002",panelStart:"\u542F\u52A8\u9762\u677F",panelReplace:"\u66FF\u6362\u4E3A {version}",panelAlreadyPreferred:"\u6B63\u5728\u8FD0\u884C\u7684\u9762\u677F\u5DF2\u7ECF\u662F\u9996\u9009\u526F\u672C\u3002",panelTakeoverTitle:"\u66FF\u6362\u6B63\u5728\u8FD0\u884C\u7684\u9762\u677F\uFF1F",panelTakeoverBody:"\u8FD9\u4F1A\u505C\u6B62\u6B63\u5728\u8FD0\u884C\u7684\u9762\u677F\u4EE5\u53CA\u5B83\u76D1\u7BA1\u7684\u6240\u6709\u670D\u52A1\u5668\u2014\u2014\u5305\u62EC\u672C dsh\uFF0C\u56E0\u6B64\u672C\u9875\u9762\u4F1A\u65AD\u5F00\u8FDE\u63A5\u3002\u4EC5\u5F53 dsh \u6761\u76EE\u5DF2\u63A5\u7BA1\u5E76\u542F\u7528\u81EA\u542F\u65F6\u624D\u53EF\u7528\u3002",confirmCancel:"\u53D6\u6D88",confirmReplace:"\u66FF\u6362",writeViaApi:"\u5DF2\u8BA4\u8BC1 API",writeViaFile:"\u914D\u7F6E\u6587\u4EF6",writeViaNone:"\u4E0D\u53EF\u7528",tokenEnrolled:"\u5DF2\u767B\u8BB0",tokenPresent:"\u5DF2\u5B58\u5728",tokenAbsent:"\u4E0D\u5B58\u5728",tokenUnknown:"\u672A\u77E5",optionsTitle:"\u9009\u9879",optionsDesc:"\u8FD0\u884C\u54EA\u4E2A home-hosted\uFF0C\u4EE5\u53CA\u5982\u4F55\u83B7\u5F97\u5168\u5C40\u526F\u672C\u3002",optionsCliUnavailable:"\u5BBF\u4E3B\u6CA1\u6709\u62A5\u544A\u4EFB\u4F55 CLI \u4FE1\u606F\u3002",optionsCurrent:"\u5F53\u524D CLI",optionsVersion:"\u7248\u672C",optionsPath:"\u8DEF\u5F84",optionsPreferPinned:"\u56FA\u5B9A\u4F9D\u8D56\uFF08\u63A8\u8350\uFF09",optionsPreferGlobal:"\u5168\u5C40\u5B89\u88C5\uFF08PATH\uFF09",optionsNotResolved:"\u672A\u89E3\u6790",optionsPreferHint:"\u8BE5\u9009\u62E9\u51B3\u5B9A\u5F00\u673A\u81EA\u542F\u4E0E\u9762\u677F\u64CD\u4F5C\u8FD0\u884C\u54EA\u4E2A\u526F\u672C\u3002",optionsInstallHint:"\u672A\u627E\u5230\u5168\u5C40 home-hosted\u3002\u5B89\u88C5\u56FA\u5B9A\u7248\u672C\u8303\u56F4\u540E\uFF0C\u5728\u4E0A\u65B9\u9009\u62E9\u5168\u5C40\u526F\u672C\uFF1A",optionsInstall:"\u5168\u5C40\u5B89\u88C5",optionsOutput:"\u547D\u4EE4\u8F93\u51FA",optionsConfigOverride:"\u63D2\u4EF6\u884C\u7684 homeHostedCommand \u4F1A\u8986\u76D6\u6B64\u9009\u62E9\u3002",bootTitle:"\u5F00\u673A\u81EA\u542F",bootDesc:"\u968F\u673A\u5668\u542F\u52A8\u81EA\u52A8\u62C9\u8D77\u9762\u677F\u3002",bootEnabled:"\u542F\u7528\u81EA\u542F",bootMechanism:"\u673A\u5236",bootMechanismAuto:"\u81EA\u52A8\uFF08\u63A8\u8350\uFF09",bootState:"\u72B6\u6001",bootStateNotInstalled:"\u672A\u5B89\u88C5",bootStateInstalledDisabled:"\u5DF2\u5B89\u88C5\uFF0C\u672A\u542F\u7528",bootStateEnabledRunning:"\u5DF2\u542F\u7528\uFF0C\u8FD0\u884C\u4E2D",bootStateEnabledFailing:"\u5DF2\u542F\u7528\uFF0C\u542F\u52A8\u5931\u8D25",bootStateUnsupported:"\u4E0D\u652F\u6301",bootBootCapable:"\u767B\u5F55\u524D\u542F\u52A8",bootPrivileged:"\u672C\u8FDB\u7A0B\u53EF\u5B89\u88C5",bootUnitPath:"\u5355\u5143\u6587\u4EF6\u8DEF\u5F84",bootCommands:"\u624B\u52A8\u547D\u4EE4",bootCommandsExplain:"\u672C\u8FDB\u7A0B\u65E0\u6CD5\u63D0\u6743\u3002\u8BF7\u81EA\u884C\u6267\u884C\u4EE5\u4E0B\u547D\u4EE4\u6765\u5B89\u88C5\u81EA\u542F\uFF1A",bootRecheck:"\u91CD\u65B0\u68C0\u67E5",entriesTitle:"\u53D7\u7BA1\u6761\u76EE",entriesDesc:"\u672C\u63D2\u4EF6\u5E0C\u671B\u6BCF\u6761\u76EE\u6210\u4E3A\u7684\u6837\u5B50\uFF0C\u4EE5\u53CA\u9762\u677F\u5B9E\u9645\u62A5\u544A\u7684\u72B6\u6001\u3002",entriesEmpty:"\u5C1A\u672A\u914D\u7F6E\u4EFB\u4F55\u53D7\u7BA1\u6761\u76EE\u3002",entriesExists:"\u5B58\u5728",entriesMissing:"\u7F3A\u5931",entriesManaged:"\u5DF2\u63A5\u7BA1",entriesUnmanaged:"\u672A\u63A5\u7BA1",entriesDrift:"\u6F02\u79FB",entriesLive:"\u5B9E\u65F6",entriesNotRunning:"\u672A\u8FD0\u884C",entriesAutostart:"\u81EA\u542F",entriesOnPortConflict:"\u7AEF\u53E3\u51B2\u7A81\u65F6",entriesStopKillPortHolders:"\u505C\u6B62\u7AEF\u53E3\u5360\u7528\u8005",entriesAdopt:"\u63A5\u7BA1",entriesPause:"\u6682\u505C",entriesRestore:"\u8FD8\u539F",agentTitle:"Agent \u5DE5\u5177",agentDesc:"Agent \u53EF\u4EE5\u8C03\u7528\u672C\u63D2\u4EF6\u7684\u54EA\u4E9B\u5DE5\u5177\u3002",agentMaster:"\u542F\u7528 Agent \u5DE5\u5177",agentApproval:"\u4F1A\u6539\u53D8\u72B6\u6001\u7684\u5DE5\u5177\u5728\u8FD0\u884C\u524D\u4F1A\u8BF7\u6C42\u6279\u51C6\u3002",agentToolMutating:"{name} \xB7 \u9700\u6279\u51C6",serversTitle:"\u670D\u52A1\u5668",serversDesc:"\u9762\u677F\u76D1\u7BA1\u7684\u670D\u52A1\u5668\u3002",serversHintPanel:"\u5728 home-hosted \u9762\u677F\u4E2D\u6DFB\u52A0\u3001\u7F16\u8F91\u548C\u5220\u9664\u6761\u76EE\uFF1A{url}",serversHintNoPanel:"\u5728 home-hosted \u9762\u677F\u4E2D\u6DFB\u52A0\u3001\u7F16\u8F91\u548C\u5220\u9664\u6761\u76EE\uFF08\u5F53\u524D\u672A\u8FD0\u884C\uFF09\u3002",serversEmpty:"\u9762\u677F\u672A\u62A5\u544A\u4EFB\u4F55\u670D\u52A1\u5668\u3002",serversPid:"PID",serversUrl:"URL",serversStart:"\u542F\u52A8",serversStop:"\u505C\u6B62",serversRestart:"\u91CD\u542F"};function Le(e,t){return t===void 0?e:e.replace(/\{(\w+)\}/g,(n,s)=>Object.prototype.hasOwnProperty.call(t,s)?String(t[s]):n)}var ne=(e,t)=>Le(K[e]??e,t);function oe(e){if(e!==void 0)try{let t=e.bind($);if(typeof t=="function")return t}catch{}return ne}function re(e,t=ne){return e===void 0?t:(n,s)=>{let r;try{r=e(n,s)}catch{r=void 0}return r===void 0||r.length===0||r===n?t(n,s):r}}var B=require("react");var A=require("react");var se="/home-hosted";var L=["status","servers_list","servers_start","servers_stop","servers_restart","servers_create","servers_update","servers_delete","autostart_install","autostart_uninstall"],ie=["servers_start","servers_stop","servers_restart","servers_create","servers_update","servers_delete","autostart_install","autostart_uninstall"];var Ve="/api";function k(e,t,n){return{ok:!1,error:n===void 0?{code:e,message:t}:{code:e,message:t,detail:n}}}function W(e){return typeof e=="object"&&e!==null}function je(e){return e instanceof Error?e.message:String(e)}function Fe(e){if(!W(e))return k("bad-response","The panel returned a non-object response");if(typeof e.v=="number"&&e.v!==1)return k("version-mismatch",`Response protocol v${e.v} does not match the expected v${1}`);let t=e.result;if(!W(t))return k("bad-response","The panel returned no result");if(t.ok===!0)return"value"in t?{ok:!0,value:t.value}:k("bad-response","A successful response carried no value");if(t.ok===!1){let n=t.error;return W(n)&&typeof n.message=="string"?k(typeof n.code=="string"?n.code:"error",n.message,n.detail):k("error","The panel reported a failure without a message")}return k("bad-response","The panel returned an unrecognised result")}async function h(e,t,n={}){let s=n.fetch??globalThis.fetch;if(typeof s!="function")return k("no-fetch","No fetch implementation is available");let r={v:1,endpoint:e,payload:t},o;try{o=await s(`${Ve}${se}`,{method:"POST",credentials:"same-origin",headers:{"content-type":"application/json"},body:JSON.stringify(r)})}catch(p){return k("network",je(p))}if(!o.ok){let p=o.statusText.length>0?` ${o.statusText}`:"";return k("http",`HTTP ${o.status}${p}`)}let i;try{i=await o.json()}catch{return k("bad-json","The panel returned invalid JSON")}return Fe(i)}function ae(e,t={}){return h("settings.update",{patch:e},t)}var ze=5e3;function le(e=ze){let[t,n]=(0,A.useState)(null),[s,r]=(0,A.useState)(null),[o,i]=(0,A.useState)(!0),p=(0,A.useRef)(!0),v=(0,A.useCallback)(async()=>{let S=await h("status",{});p.current&&(S.ok?(n(S.value),r(null)):r(S.error),i(!1))},[]);return(0,A.useEffect)(()=>{p.current=!0,v();let S=setInterval(()=>{v()},e);return()=>{p.current=!1,clearInterval(S)}},[v,e]),{data:t,error:s,loading:o,refresh:v}}var V="\u2014";function b(e){if(e==null)return V;let t=String(e);return t.length>0?t:V}function pe(e){return e.length>0?e.join(", "):V}function de(e){return ie.includes(e)}var ce={api:"writeViaApi",file:"writeViaFile",none:"writeViaNone"},ue={enrolled:"tokenEnrolled",present:"tokenPresent",absent:"tokenAbsent",unknown:"tokenUnknown"},ge={"not-installed":"bootStateNotInstalled","installed-disabled":"bootStateInstalledDisabled","enabled-running":"bootStateEnabledRunning","enabled-failing":"bootStateEnabledFailing",unsupported:"bootStateUnsupported"},j={config:"panelCliConfig",dependency:"panelCliDependency",path:"panelCliPathSource",none:"panelCliMissing"};function q(e){return e==null?V:`${b(e.version)} \xB7 ${b(e.path)}`}function fe(e){let t=n=>e.source===n&&e.path!==null?{source:n,path:e.path,version:e.version}:null;return{dependency:e.dependency??t("dependency"),global:e.global??t("path")}}function me(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function Ge(e,t){if(Object.is(e,t))return!0;try{return JSON.stringify(e)===JSON.stringify(t)}catch{return!1}}function he(e,t){let n={};for(let s of Object.keys(t)){let r=e[s],o=t[s];if(me(r)&&me(o)){let i=he(r,o);Object.keys(i).length>0&&(n[s]=i)}else Ge(r,o)||(n[s]=o)}return n}function be(e,t){return he(e,t)}function ve(e,t,n){let s=new Set(e);return n?s.add(t):s.delete(t),L.filter(r=>s.has(r))}var d=require("react/jsx-runtime"),F="var(--dsw-alias-label-secondary, #8b8b8b)",J="var(--dsw-alias-border-secondary, rgba(128, 128, 128, 0.25))",ye="var(--dsw-alias-state-error-primary, #e53e3e)",Ke={fontFamily:"ui-monospace, SFMono-Regular, Menlo, monospace",wordBreak:"break-all",textAlign:"right"};function T({title:e,description:t,children:n}){return(0,d.jsxs)("section",{style:{display:"flex",flexDirection:"column",gap:8,padding:"14px 0",borderTop:`1px solid ${J}`},children:[(0,d.jsxs)("header",{style:{display:"flex",flexDirection:"column",gap:2},children:[(0,d.jsx)("h3",{style:{margin:0,fontSize:14,fontWeight:600},children:e}),t!==void 0&&t.length>0?(0,d.jsx)("p",{style:{margin:0,fontSize:12,color:F},children:t}):null]}),n]})}function a({label:e,children:t}){return(0,d.jsxs)("div",{style:{display:"flex",alignItems:"baseline",gap:12,justifyContent:"space-between",fontSize:13},children:[(0,d.jsx)("span",{style:{color:F},children:e}),(0,d.jsx)("span",{style:Ke,children:t})]})}function c({children:e}){return typeof e=="string"&&(typeof e=="string"?e:"").length===0?null:(0,d.jsx)("p",{style:{margin:0,fontSize:12,color:F,lineHeight:1.5},children:e})}function u({children:e,onClick:t,disabled:n,busy:s}){return(0,d.jsx)("button",{type:"button",onClick:t,disabled:n===!0||s===!0,style:{padding:"4px 10px",fontSize:12,borderRadius:6,border:`1px solid ${J}`,background:"transparent",color:"inherit",cursor:n===!0||s===!0?"default":"pointer",opacity:n===!0||s===!0?.6:1},children:e})}function M({label:e,checked:t,disabled:n,onChange:s}){return(0,d.jsxs)("label",{style:{display:"flex",alignItems:"center",gap:8,fontSize:13,opacity:n===!0?.6:1,cursor:n===!0?"default":"pointer"},children:[(0,d.jsx)("input",{type:"checkbox",checked:t,disabled:n,onChange:r=>s(r.target.checked)}),(0,d.jsx)("span",{children:e})]})}function Se({value:e,options:t,disabled:n,onChange:s}){return(0,d.jsx)("select",{value:e,disabled:n,onChange:r=>s(r.target.value),style:{padding:"3px 6px",fontSize:12,borderRadius:6,border:`1px solid ${J}`,background:"transparent",color:"inherit"},children:t.map(r=>(0,d.jsx)("option",{value:r.value,children:r.label},r.value))})}function X({label:e,description:t,checked:n,disabled:s,onChange:r}){return(0,d.jsxs)("label",{style:{display:"flex",alignItems:"flex-start",gap:8,fontSize:13,opacity:s===!0?.6:1,cursor:s===!0?"default":"pointer"},children:[(0,d.jsx)("input",{type:"radio",checked:n,disabled:s,onChange:()=>r(),style:{marginTop:2}}),(0,d.jsxs)("span",{style:{display:"flex",flexDirection:"column",gap:2},children:[(0,d.jsx)("span",{children:e}),t!==void 0&&t.length>0?(0,d.jsx)("span",{style:{fontSize:12,color:F},children:t}):null]})]})}function D({error:e,title:t}){return e===null?null:(0,d.jsxs)("div",{role:"alert",style:{padding:"8px 10px",borderRadius:6,fontSize:12,lineHeight:1.5,border:`1px solid ${ye}`,color:ye},children:[(0,d.jsx)("strong",{children:t}),": ",(0,d.jsx)("code",{children:e.code})," \u2014 ",e.message]})}var O=require("react/jsx-runtime");function Ce({t:e,status:t,updateSettings:n}){let s=t.settings.agentTools,r=s.allow??[];return(0,O.jsxs)(T,{title:e("agentTitle"),description:e("agentDesc"),children:[(0,O.jsx)(M,{label:e("agentMaster"),checked:s.enabled,onChange:o=>n(i=>({...i,agentTools:{...i.agentTools,enabled:o}}))}),(0,O.jsx)(c,{children:e("agentApproval")}),(0,O.jsx)("div",{style:{display:"flex",flexDirection:"column",gap:6},children:L.map(o=>(0,O.jsx)(M,{label:de(o)?e("agentToolMutating",{name:o}):o,checked:r.includes(o),disabled:!s.enabled,onChange:i=>n(p=>({...p,agentTools:{...p.agentTools,allow:ve(p.agentTools.allow??[],o,i)}}))},o))})]})}var Pe=require("react");async function z(e){try{if(typeof navigator<"u"&&navigator.clipboard!==void 0)return await navigator.clipboard.writeText(e),!0}catch{}return!1}var y=require("react/jsx-runtime"),We={width:"100%",minHeight:60,marginTop:6,padding:8,borderRadius:6,border:"1px solid var(--dsw-alias-border-secondary, rgba(128, 128, 128, 0.25))",background:"transparent",color:"inherit",fontFamily:"ui-monospace, SFMono-Regular, Menlo, monospace",fontSize:12,resize:"vertical"};function Re({t:e,status:t,run:n,updateSettings:s,busy:r}){let o=t.boot,i=t.settings.autostart,p=o.candidates??[],v=o.commands??[],[S,x]=(0,Pe.useState)(!1),w=r==="settings",C=["auto",...p.filter(m=>m.available).map(m=>m.mechanism)];C.includes(i.mechanism)||C.push(i.mechanism);let E=C.map(m=>({value:m,label:m==="auto"?e("bootMechanismAuto"):m})),_=async()=>{x(await z(v.join(`
4
- `)))};return(0,y.jsxs)(T,{title:e("bootTitle"),description:e("bootDesc"),children:[(0,y.jsx)(M,{label:e("bootEnabled"),checked:i.enabled,disabled:w,onChange:m=>s(H=>({...H,autostart:{...H.autostart,enabled:m}}))}),(0,y.jsx)(a,{label:e("bootMechanism"),children:(0,y.jsx)(Se,{value:i.mechanism,options:E,disabled:w,onChange:m=>s(H=>({...H,autostart:{...H.autostart,mechanism:m}}))})}),(0,y.jsx)(a,{label:e("bootState"),children:e(ge[o.state]??"bootStateUnsupported")}),(0,y.jsx)(a,{label:e("bootBootCapable"),children:o.bootCapable?e("yes"):e("no")}),(0,y.jsx)(a,{label:e("bootPrivileged"),children:o.privileged?e("yes"):e("no")}),(0,y.jsx)(a,{label:e("bootUnitPath"),children:b(o.unitPath)}),(0,y.jsx)(c,{children:o.detail}),v.length>0?(0,y.jsxs)("div",{children:[(0,y.jsx)(c,{children:e("bootCommandsExplain")}),(0,y.jsx)("textarea",{readOnly:!0,value:v.join(`
5
- `),rows:Math.min(v.length,6),style:We}),(0,y.jsx)("div",{style:{display:"flex",gap:8,marginTop:6},children:(0,y.jsx)(u,{onClick:()=>{_()},children:e(S?"copied":"copy")})})]}):null,(0,y.jsx)("div",{children:(0,y.jsx)(u,{busy:r==="boot.verify",onClick:()=>n("boot.verify",()=>h("boot.verify",{})),children:e("bootRecheck")})})]})}var P=require("react/jsx-runtime"),Ye={display:"flex",flexDirection:"column",gap:6,padding:10,borderRadius:6,border:"1px solid var(--dsw-alias-border-secondary, rgba(128, 128, 128, 0.25))"},qe={display:"flex",alignItems:"baseline",justifyContent:"space-between",gap:12,fontSize:13},Je={display:"flex",flexWrap:"wrap",gap:8};function xe({t:e,status:t,run:n,busy:s}){let r=t.entries??[];return(0,P.jsx)(T,{title:e("entriesTitle"),description:e("entriesDesc"),children:r.length===0?(0,P.jsx)(c,{children:e("entriesEmpty")}):r.map(o=>{let i=o.intent.id,p=o.live;return(0,P.jsxs)("div",{style:Ye,children:[(0,P.jsxs)("div",{style:qe,children:[(0,P.jsx)("strong",{children:i}),(0,P.jsxs)("span",{style:{color:"var(--dsw-alias-label-secondary, #8b8b8b)"},children:[o.exists?e("entriesExists"):e("entriesMissing")," \xB7 ",o.managed?e("entriesManaged"):e("entriesUnmanaged")]})]}),(0,P.jsx)(a,{label:e("entriesDrift"),children:pe(o.drift)}),(0,P.jsx)(a,{label:e("entriesLive"),children:p===null?e("entriesNotRunning"):`${b(p.status)}${p.pid===null?"":` \xB7 pid ${p.pid}`}`}),(0,P.jsx)(a,{label:e("entriesAutostart"),children:o.intent.autostart?e("yes"):e("no")}),(0,P.jsx)(a,{label:e("entriesOnPortConflict"),children:o.intent.onPortConflict}),(0,P.jsx)(a,{label:e("entriesStopKillPortHolders"),children:o.intent.stopKillPortHolders?e("yes"):e("no")}),(0,P.jsxs)("div",{style:Je,children:[(0,P.jsx)(u,{busy:s===`entries.adopt:${i}`,onClick:()=>n(`entries.adopt:${i}`,()=>h("entries.apply",{intents:[o.intent]})),children:e("entriesAdopt")}),(0,P.jsx)(u,{busy:s===`entries.pause:${i}`,onClick:()=>n(`entries.pause:${i}`,()=>h("entries.apply",{intents:[{...o.intent,autostart:!1}]})),children:e("entriesPause")}),(0,P.jsx)(u,{busy:s===`entries.restore:${i}`,disabled:!o.managed,onClick:()=>n(`entries.restore:${i}`,()=>h("entries.restore",{id:i})),children:e("entriesRestore")})]})]},i)})})}var Te=require("react");var l=require("react/jsx-runtime"),Xe={display:"flex",flexDirection:"column",gap:8,padding:10,borderRadius:6,border:"1px solid var(--dsw-alias-state-error-primary, #e53e3e)"},Z={display:"flex",flexWrap:"wrap",gap:8};function we({t:e,status:t,run:n,busy:s}){let r=t.panel,o=t.cli,i=o?.prefer??t.settings.cli?.prefer??"pinned",[p,v]=(0,Te.useState)(!1),S=o?.version??null,x=r.version,w=S!==null&&x!==null,C=r.reachable&&w&&S===x,E=r.reachable&&w&&S!==x;return(0,l.jsxs)(T,{title:e("panelTitle"),description:e("panelDesc"),children:[(0,l.jsx)(a,{label:e("panelReachable"),children:r.reachable?e("yes"):e("no")}),(0,l.jsx)(a,{label:e("panelHome"),children:b(r.home)}),(0,l.jsx)(a,{label:e("panelUrl"),children:b(r.url)}),(0,l.jsx)(a,{label:e("panelVersion"),children:b(r.version)}),(0,l.jsx)(a,{label:e("panelPid"),children:b(r.pid)}),(0,l.jsx)(a,{label:e("panelWriteVia"),children:e(ce[r.writeVia]??"writeViaNone")}),(0,l.jsx)(a,{label:e("panelToken"),children:e(ue[r.token]??"tokenUnknown")}),o!==void 0&&(0,l.jsxs)(l.Fragment,{children:[(0,l.jsx)(a,{label:e("panelCliSource"),children:`${e(j[o.source]??"panelCliMissing")} \xB7 ${b(o.version)}`}),(0,l.jsx)(a,{label:e("panelCliPath"),children:b(o.path)}),o.source==="path"&&i!=="global"&&(0,l.jsx)(c,{children:e("panelCliNotPinned",{range:o.expectedRange})}),o.launcherPath!=null&&o.launcherVersion==null&&(0,l.jsx)(c,{children:e("panelCliLauncherFailed")})]}),(0,l.jsx)(c,{children:r.detail}),r.reachable?null:(0,l.jsx)("div",{style:Z,children:(0,l.jsx)(u,{busy:s==="panel.start",onClick:()=>{n("panel.start",()=>h("panel.start",{}))},children:e("panelStart")})}),C?(0,l.jsx)(c,{children:e("panelAlreadyPreferred")}):null,E?p?(0,l.jsxs)("div",{style:Xe,role:"alertdialog","aria-label":e("panelTakeoverTitle"),children:[(0,l.jsx)("strong",{children:e("panelTakeoverTitle")}),(0,l.jsx)(c,{children:e("panelTakeoverBody")}),(0,l.jsxs)("div",{style:Z,children:[(0,l.jsx)(u,{onClick:()=>v(!1),children:e("confirmCancel")}),(0,l.jsx)(u,{busy:s==="panel.takeover",onClick:()=>{v(!1),n("panel.takeover",()=>h("panel.takeover",{}))},children:e("confirmReplace")})]})]}):(0,l.jsx)("div",{style:Z,children:(0,l.jsx)(u,{onClick:()=>v(!0),children:e("panelReplace",{version:S})})}):null]})}var Q=require("react");var g=require("react/jsx-runtime"),Ze={display:"flex",flexDirection:"column",gap:6,padding:10,borderRadius:6,border:"1px solid var(--dsw-alias-border-secondary, rgba(128, 128, 128, 0.25))"},Qe={width:"100%",minHeight:48,padding:8,borderRadius:6,border:"1px solid var(--dsw-alias-border-secondary, rgba(128, 128, 128, 0.25))",background:"transparent",color:"inherit",fontFamily:"ui-monospace, SFMono-Regular, Menlo, monospace",fontSize:12,resize:"vertical"},et={display:"flex",flexWrap:"wrap",gap:8},tt={maxHeight:180,margin:"6px 0 0",padding:8,overflow:"auto",borderRadius:6,border:"1px solid var(--dsw-alias-border-secondary, rgba(128, 128, 128, 0.25))",fontFamily:"ui-monospace, SFMono-Regular, Menlo, monospace",fontSize:12,whiteSpace:"pre-wrap"};function ke({t:e,status:t,run:n,updateSettings:s,busy:r}){let o=t.cli,[i,p]=(0,Q.useState)(!1),[v,S]=(0,Q.useState)(null);if(o===void 0)return(0,g.jsx)(T,{title:e("optionsTitle"),description:e("optionsDesc"),children:(0,g.jsx)(c,{children:e("optionsCliUnavailable")})});let x=o.prefer??t.settings.cli?.prefer??"pinned",{dependency:w,global:C}=fe(o),E=[`pnpm add -g home-hosted@${o.expectedRange}`,`npm install -g home-hosted@${o.expectedRange}`],_=r==="settings",m=async()=>{p(await z(E.join(`
6
- `)))},H=async()=>{let U=await n("cli.installGlobal",()=>h("cli.installGlobal",{}));if(!U.ok)return;let I=U.value;S(typeof I?.output=="string"?I.output:null)},ee=U=>{s(I=>({...I,cli:{...I.cli,prefer:U}}))};return(0,g.jsxs)(T,{title:e("optionsTitle"),description:e("optionsDesc"),children:[(0,g.jsx)(a,{label:e("optionsCurrent"),children:e(j[o.source]??"cliSourceNone")}),(0,g.jsx)(a,{label:e("optionsVersion"),children:b(o.version)}),(0,g.jsx)(a,{label:e("optionsPath"),children:b(o.path)}),(0,g.jsx)(c,{children:o.detail}),o.source==="config"?(0,g.jsx)(c,{children:e("optionsConfigOverride")}):null,(0,g.jsxs)("div",{style:{display:"flex",flexDirection:"column",gap:8},children:[(0,g.jsx)(X,{label:e("optionsPreferPinned"),description:w===null?e("optionsNotResolved"):q(w),checked:x==="pinned",disabled:w===null||_,onChange:()=>ee("pinned")}),(0,g.jsx)(X,{label:e("optionsPreferGlobal"),description:C===null?e("optionsNotResolved"):q(C),checked:x==="global",disabled:C===null||_,onChange:()=>ee("global")})]}),(0,g.jsx)(c,{children:e("optionsPreferHint")}),C===null?(0,g.jsxs)("div",{style:Ze,children:[(0,g.jsx)(c,{children:e("optionsInstallHint")}),(0,g.jsx)("textarea",{readOnly:!0,value:E.join(`
7
- `),rows:2,style:Qe}),(0,g.jsxs)("div",{style:et,children:[(0,g.jsx)(u,{onClick:()=>{m()},children:e(i?"copied":"copy")}),(0,g.jsx)(u,{busy:r==="cli.installGlobal",onClick:()=>{H()},children:e("optionsInstall")}),(0,g.jsx)(u,{busy:r==="status.refresh",onClick:()=>{n("status.refresh",()=>h("status",{refresh:!0}))},children:e("refresh")})]}),v===null?null:(0,g.jsxs)("details",{children:[(0,g.jsx)("summary",{style:{fontSize:12,cursor:"pointer"},children:e("optionsOutput")}),(0,g.jsx)("pre",{style:tt,children:v})]})]}):null]})}var R=require("react/jsx-runtime"),nt={display:"flex",flexDirection:"column",gap:6,padding:10,borderRadius:6,border:"1px solid var(--dsw-alias-border-secondary, rgba(128, 128, 128, 0.25))"},ot={display:"flex",alignItems:"baseline",justifyContent:"space-between",gap:12,fontSize:13},Ee={display:"flex",flexWrap:"wrap",gap:8};function He({t:e,status:t,run:n,busy:s}){let r=t.servers??[];return(0,R.jsxs)(T,{title:e("serversTitle"),description:e("serversDesc"),children:[(0,R.jsx)("div",{style:Ee,children:(0,R.jsx)(u,{busy:s==="status.refresh",onClick:()=>n("status.refresh",()=>h("status",{refresh:!0})),children:e("refresh")})}),(0,R.jsx)(c,{children:t.panel.url===null?e("serversHintNoPanel"):e("serversHintPanel",{url:t.panel.url})}),r.length===0?(0,R.jsx)(c,{children:e("serversEmpty")}):r.map(o=>(0,R.jsxs)("div",{style:nt,children:[(0,R.jsxs)("div",{style:ot,children:[(0,R.jsx)("strong",{children:o.id}),(0,R.jsx)("span",{children:b(o.status)})]}),(0,R.jsx)(a,{label:e("serversPid"),children:b(o.pid)}),(0,R.jsx)(a,{label:e("serversUrl"),children:b(o.url)}),(0,R.jsxs)("div",{style:Ee,children:[(0,R.jsx)(u,{busy:s===`servers.start:${o.id}`,onClick:()=>n(`servers.start:${o.id}`,()=>h("servers.start",{id:o.id})),children:e("serversStart")}),(0,R.jsx)(u,{busy:s===`servers.stop:${o.id}`,onClick:()=>n(`servers.stop:${o.id}`,()=>h("servers.stop",{id:o.id})),children:e("serversStop")}),(0,R.jsx)(u,{busy:s===`servers.restart:${o.id}`,onClick:()=>n(`servers.restart:${o.id}`,()=>h("servers.restart",{id:o.id})),children:e("serversRestart")})]})]},o.id))]})}var f=require("react/jsx-runtime");function Ae(e){let t=re(e.t),{data:n,error:s,loading:r,refresh:o}=le(),[i,p]=(0,B.useState)(null),[v,S]=(0,B.useState)(null),x=(0,B.useCallback)((E,_)=>(S(E),p(null),(async()=>{try{let m=await _();return m.ok||p(m.error),m}catch(m){let H={code:"client",message:m instanceof Error?m.message:String(m)};return p(H),{ok:!1,error:H}}finally{S(null),await o()}})()),[o]),w=(0,B.useCallback)(E=>{if(n===null)return;let _=be(n.settings,E(n.settings));Object.keys(_).length!==0&&x("settings",()=>ae(_))},[n,x]);if(n===null)return(0,f.jsxs)("div",{style:{display:"flex",flexDirection:"column",gap:8},children:[r?(0,f.jsx)(c,{children:t("loading")}):(0,f.jsx)(D,{error:s??{code:"status",message:t("statusUnavailable")},title:t("errorTitle")}),r?null:(0,f.jsx)("div",{children:(0,f.jsx)(u,{onClick:()=>{o()},children:t("retry")})})]});let C={t,status:n,run:x,updateSettings:w,busy:v};return(0,f.jsxs)("div",{style:{display:"flex",flexDirection:"column"},children:[(0,f.jsxs)("header",{style:{display:"flex",alignItems:"flex-start",justifyContent:"space-between",gap:12},children:[(0,f.jsxs)("div",{children:[(0,f.jsx)("h2",{style:{margin:0,fontSize:16},children:t("tab")}),(0,f.jsx)("p",{style:{margin:"2px 0 0",fontSize:12,color:"var(--dsw-alias-label-secondary, #8b8b8b)"},children:t("pageDesc")})]}),(0,f.jsx)(u,{busy:v==="status.refresh",onClick:()=>x("status.refresh",()=>h("status",{refresh:!0})),children:t("refresh")})]}),n.lastError===null?null:(0,f.jsx)(D,{error:{code:"panel",message:n.lastError},title:t("errorTitle")}),(0,f.jsx)(D,{error:s,title:t("errorTitle")}),(0,f.jsx)(D,{error:i,title:t("errorTitle")}),(0,f.jsx)(we,{...C}),(0,f.jsx)(ke,{...C}),(0,f.jsx)(Re,{...C}),(0,f.jsx)(xe,{...C}),(0,f.jsx)(Ce,{...C}),(0,f.jsx)(He,{...C})]})}var rt=["slots","locale"],_e="[dsh-home-hosted]";function N(e,t){t===void 0?console.warn(`${_e} ${e}`):console.warn(`${_e} ${e}`,t)}function Ne(e,t){try{let n=e.get?.(t);if(n!=null)return n}catch{}try{let n=e[t];if(n!=null)return n}catch{}}function Oe(e,t,n){if(typeof e.effect=="function")try{e.effect(t,n);return}catch(s){N(`registering the effect "${n}" failed`,s);return}try{t()}catch(s){N(`the effect "${n}" failed`,s)}}function st(e){try{let t=Ne(e,"locale"),n=oe(t);t===void 0?N("the locale service is unavailable; the page keeps its bundled English copy"):Oe(e,()=>{let r=[];try{r.push(t.register($,{en:K,zh:te}))}catch(o){N("registering the dictionaries failed",o)}return()=>{for(let o of r)try{o()}catch(i){N("disposing a dictionary failed",i)}}},"dsh-home-hosted: dictionaries");let s=Ne(e,"slots");if(s===void 0){N("the slots service is unavailable; the settings section was not registered");return}Oe(e,()=>{try{return s.inject("settings.section",()=>{try{return s.register({name:"settings.section",id:"home-hosted",order:60,label:()=>n("tab"),locale:$,inject:()=>({t:n})},Ae)}catch(r){return N("registering the settings section failed",r),()=>{}}})}catch(r){return N("injecting into settings.section failed",r),()=>{}}},"dsh-home-hosted: settings section")}catch(t){N("client bootstrap failed",t)}}
3
+ "use strict";var Z=Object.defineProperty;var Ge=Object.getOwnPropertyDescriptor;var Ke=Object.getOwnPropertyNames;var We=Object.prototype.hasOwnProperty;var Ye=(e,t)=>{for(var n in t)Z(e,n,{get:t[n],enumerable:!0})},qe=(e,t,n,i)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of Ke(t))!We.call(e,r)&&r!==n&&Z(e,r,{get:()=>t[r],enumerable:!(i=Ge(t,r))||i.enumerable});return e};var Je=e=>qe(Z({},"__esModule",{value:!0}),e);var ht={};Ye(ht,{apply:()=>bt,inject:()=>mt});module.exports=Je(ht);var j="homeHosted",Q={tab:"Home Hosted",pageDesc:"Boot autostart and home-hosted server management.",loading:"Loading\u2026",refresh:"Refresh",retry:"Retry",errorTitle:"Error",statusUnavailable:"The panel did not answer.",yes:"Yes",no:"No",copy:"Copy",copied:"Copied",panelTitle:"Panel",panelDesc:"Reachability and identity of the home-hosted panel.",panelReachable:"Reachable",panelHome:"$HHOSTED_HOME",panelUrl:"URL",panelVersion:"Version",panelPid:"PID",panelWriteVia:"Writes via",panelToken:"API token",panelCliSource:"CLI",panelCliPath:"CLI path",panelCliConfig:"configured command",panelCliDependency:"pinned dependency",panelCliPathSource:"global install (PATH)",panelCliMissing:"not found",panelCliNotPinned:"This host uses a global home-hosted instead of the plugin's pinned copy ({range}); reinstall the plugin with its dependencies to use the pinned one.",panelCliLauncherFailed:"The boot launcher did not answer; a boot entry may fail to start the panel.",panelStart:"Start the panel",panelReplace:"Replace with {version}",panelAlreadyPreferred:"The running panel is already the preferred copy.",panelTakeoverTitle:"Replace the running panel?",panelTakeoverBody:"This stops the running panel and every server it supervises \u2014 including this dsh, so this page disconnects. It only works when the dsh entry is adopted with autostart enabled.",confirmCancel:"Cancel",confirmReplace:"Replace",writeViaApi:"authenticated API",writeViaFile:"config file",writeViaNone:"unavailable",tokenEnrolled:"enrolled",tokenPresent:"present",tokenAbsent:"absent",tokenUnknown:"unknown",optionsTitle:"Options",optionsDesc:"Which home-hosted to run, and how to get a global copy.",optionsCliUnavailable:"The host did not report any CLI information.",optionsCurrent:"CLI in use",optionsVersion:"Version",optionsPath:"Path",optionsPreferPinned:"Pinned dependency (recommended)",optionsPreferGlobal:"Global install (PATH)",optionsNotResolved:"not resolved",optionsPreferHint:"This choice decides which copy boot autostart and the panel actions run.",optionsInstallHint:"No global home-hosted was found. Install the pinned range, then pick the global copy above:",optionsInstall:"Install globally",optionsOutput:"Command output",optionsConfigOverride:"The plugin row's homeHostedCommand overrides this choice.",bootTitle:"Boot autostart",bootDesc:"Start the panel automatically when the machine boots.",bootEnabled:"Enable autostart",bootMechanism:"Mechanism",bootMechanismAuto:"Automatic (recommended)",bootState:"State",bootStateNotInstalled:"not installed",bootStateInstalledDisabled:"installed, disabled",bootStateEnabledRunning:"enabled, running",bootStateEnabledFailing:"enabled, failing",bootStateUnsupported:"unsupported",bootBootCapable:"Starts before login",bootPrivileged:"This process can install it",bootUnitPath:"Unit path",bootCommands:"Manual commands",bootCommandsExplain:"This process could not elevate. Run these commands yourself to install autostart:",bootRecheck:"Re-check",bootActionInstall:"install",bootActionUninstall:"uninstall",bootRequestedNotInstalled:"Autostart is requested, but no boot entry is installed yet.",bootAttemptFailed:"Last attempt: {action} failed",bootAttemptSucceeded:"Last attempt: {action} succeeded \u2014 {detail}",bootAttemptNoDetail:"The host did not explain the refusal.",bootAttemptCommands:"Commands you can run yourself:",entriesTitle:"Managed entries",entriesDesc:"What this plugin wants each entry to be, and what the panel reports.",entriesEmpty:"No managed entries are configured yet.",entriesExists:"exists",entriesMissing:"missing",entriesManaged:"managed",entriesUnmanaged:"unmanaged",entriesDrift:"Drift",entriesLive:"Live",entriesNotRunning:"not running",entriesAutostart:"Autostart",entriesOnPortConflict:"On port conflict",entriesStopKillPortHolders:"Stop port holders",entriesAdopt:"Adopt",entriesPause:"Pause",entriesRestore:"Restore",agentTitle:"Agent tools",agentDesc:"Which of this plugin\u2019s tools the agent may call.",agentMaster:"Enable agent tools",agentApproval:"Mutating tools ask for approval before they run.",agentToolMutating:"{name} \xB7 asks approval",serversTitle:"Servers",serversDesc:"Servers supervised by the panel.",serversHintPanel:"Add, edit and remove entries in the home-hosted panel:",serversHintNoPanel:"Add, edit and remove entries in the home-hosted panel (it is not running right now).",serversEmpty:"The panel reports no servers.",serversPid:"PID",serversUrl:"URL",serversStart:"Start",serversStop:"Stop",serversRestart:"Restart"},ce={tab:"Home Hosted",pageDesc:"\u5F00\u673A\u81EA\u542F\u4E0E home-hosted \u670D\u52A1\u5668\u7BA1\u7406\u3002",loading:"\u52A0\u8F7D\u4E2D\u2026",refresh:"\u5237\u65B0",retry:"\u91CD\u8BD5",errorTitle:"\u9519\u8BEF",statusUnavailable:"\u9762\u677F\u6CA1\u6709\u54CD\u5E94\u3002",yes:"\u662F",no:"\u5426",copy:"\u590D\u5236",copied:"\u5DF2\u590D\u5236",panelTitle:"\u9762\u677F",panelDesc:"home-hosted \u9762\u677F\u7684\u53EF\u8FBE\u6027\u4E0E\u8EAB\u4EFD\u3002",panelReachable:"\u53EF\u8FBE",panelHome:"$HHOSTED_HOME",panelUrl:"URL",panelVersion:"\u7248\u672C",panelPid:"PID",panelWriteVia:"\u5199\u5165\u65B9\u5F0F",panelToken:"API \u4EE4\u724C",panelCliSource:"CLI",panelCliPath:"CLI \u8DEF\u5F84",panelCliConfig:"\u914D\u7F6E\u7684\u547D\u4EE4",panelCliDependency:"\u56FA\u5B9A\u7684\u4F9D\u8D56\u7248\u672C",panelCliPathSource:"\u5168\u5C40\u5B89\u88C5\uFF08PATH\uFF09",panelCliMissing:"\u672A\u627E\u5230",panelCliNotPinned:"\u6B64\u5BBF\u4E3B\u4F7F\u7528\u5168\u5C40 home-hosted\uFF0C\u800C\u4E0D\u662F\u63D2\u4EF6\u56FA\u5B9A\u7684\u526F\u672C\uFF08{range}\uFF09\uFF1B\u91CD\u65B0\u5B89\u88C5\u63D2\u4EF6\u53CA\u5176\u4F9D\u8D56\u5373\u53EF\u4F7F\u7528\u56FA\u5B9A\u7248\u672C\u3002",panelCliLauncherFailed:"\u542F\u52A8\u5668\u6CA1\u6709\u5E94\u7B54\uFF1B\u5F00\u673A\u9879\u53EF\u80FD\u65E0\u6CD5\u542F\u52A8\u9762\u677F\u3002",panelStart:"\u542F\u52A8\u9762\u677F",panelReplace:"\u66FF\u6362\u4E3A {version}",panelAlreadyPreferred:"\u6B63\u5728\u8FD0\u884C\u7684\u9762\u677F\u5DF2\u7ECF\u662F\u9996\u9009\u526F\u672C\u3002",panelTakeoverTitle:"\u66FF\u6362\u6B63\u5728\u8FD0\u884C\u7684\u9762\u677F\uFF1F",panelTakeoverBody:"\u8FD9\u4F1A\u505C\u6B62\u6B63\u5728\u8FD0\u884C\u7684\u9762\u677F\u4EE5\u53CA\u5B83\u76D1\u7BA1\u7684\u6240\u6709\u670D\u52A1\u5668\u2014\u2014\u5305\u62EC\u672C dsh\uFF0C\u56E0\u6B64\u672C\u9875\u9762\u4F1A\u65AD\u5F00\u8FDE\u63A5\u3002\u4EC5\u5F53 dsh \u6761\u76EE\u5DF2\u63A5\u7BA1\u5E76\u542F\u7528\u81EA\u542F\u65F6\u624D\u53EF\u7528\u3002",confirmCancel:"\u53D6\u6D88",confirmReplace:"\u66FF\u6362",writeViaApi:"\u5DF2\u8BA4\u8BC1 API",writeViaFile:"\u914D\u7F6E\u6587\u4EF6",writeViaNone:"\u4E0D\u53EF\u7528",tokenEnrolled:"\u5DF2\u767B\u8BB0",tokenPresent:"\u5DF2\u5B58\u5728",tokenAbsent:"\u4E0D\u5B58\u5728",tokenUnknown:"\u672A\u77E5",optionsTitle:"\u9009\u9879",optionsDesc:"\u8FD0\u884C\u54EA\u4E2A home-hosted\uFF0C\u4EE5\u53CA\u5982\u4F55\u83B7\u5F97\u5168\u5C40\u526F\u672C\u3002",optionsCliUnavailable:"\u5BBF\u4E3B\u6CA1\u6709\u62A5\u544A\u4EFB\u4F55 CLI \u4FE1\u606F\u3002",optionsCurrent:"\u5F53\u524D CLI",optionsVersion:"\u7248\u672C",optionsPath:"\u8DEF\u5F84",optionsPreferPinned:"\u56FA\u5B9A\u4F9D\u8D56\uFF08\u63A8\u8350\uFF09",optionsPreferGlobal:"\u5168\u5C40\u5B89\u88C5\uFF08PATH\uFF09",optionsNotResolved:"\u672A\u89E3\u6790",optionsPreferHint:"\u8BE5\u9009\u62E9\u51B3\u5B9A\u5F00\u673A\u81EA\u542F\u4E0E\u9762\u677F\u64CD\u4F5C\u8FD0\u884C\u54EA\u4E2A\u526F\u672C\u3002",optionsInstallHint:"\u672A\u627E\u5230\u5168\u5C40 home-hosted\u3002\u5B89\u88C5\u56FA\u5B9A\u7248\u672C\u8303\u56F4\u540E\uFF0C\u5728\u4E0A\u65B9\u9009\u62E9\u5168\u5C40\u526F\u672C\uFF1A",optionsInstall:"\u5168\u5C40\u5B89\u88C5",optionsOutput:"\u547D\u4EE4\u8F93\u51FA",optionsConfigOverride:"\u63D2\u4EF6\u884C\u7684 homeHostedCommand \u4F1A\u8986\u76D6\u6B64\u9009\u62E9\u3002",bootTitle:"\u5F00\u673A\u81EA\u542F",bootDesc:"\u968F\u673A\u5668\u542F\u52A8\u81EA\u52A8\u62C9\u8D77\u9762\u677F\u3002",bootEnabled:"\u542F\u7528\u81EA\u542F",bootMechanism:"\u673A\u5236",bootMechanismAuto:"\u81EA\u52A8\uFF08\u63A8\u8350\uFF09",bootState:"\u72B6\u6001",bootStateNotInstalled:"\u672A\u5B89\u88C5",bootStateInstalledDisabled:"\u5DF2\u5B89\u88C5\uFF0C\u672A\u542F\u7528",bootStateEnabledRunning:"\u5DF2\u542F\u7528\uFF0C\u8FD0\u884C\u4E2D",bootStateEnabledFailing:"\u5DF2\u542F\u7528\uFF0C\u542F\u52A8\u5931\u8D25",bootStateUnsupported:"\u4E0D\u652F\u6301",bootBootCapable:"\u767B\u5F55\u524D\u542F\u52A8",bootPrivileged:"\u672C\u8FDB\u7A0B\u53EF\u5B89\u88C5",bootUnitPath:"\u5355\u5143\u6587\u4EF6\u8DEF\u5F84",bootCommands:"\u624B\u52A8\u547D\u4EE4",bootCommandsExplain:"\u672C\u8FDB\u7A0B\u65E0\u6CD5\u63D0\u6743\u3002\u8BF7\u81EA\u884C\u6267\u884C\u4EE5\u4E0B\u547D\u4EE4\u6765\u5B89\u88C5\u81EA\u542F\uFF1A",bootRecheck:"\u91CD\u65B0\u68C0\u67E5",bootActionInstall:"\u5B89\u88C5",bootActionUninstall:"\u5378\u8F7D",bootRequestedNotInstalled:"\u5DF2\u8BF7\u6C42\u5F00\u673A\u81EA\u542F\uFF0C\u4F46\u5C1A\u672A\u5B89\u88C5\u4EFB\u4F55\u5F00\u673A\u9879\u3002",bootAttemptFailed:"\u4E0A\u6B21\u5C1D\u8BD5\uFF1A{action}\u5931\u8D25",bootAttemptSucceeded:"\u4E0A\u6B21\u5C1D\u8BD5\uFF1A{action}\u6210\u529F \u2014 {detail}",bootAttemptNoDetail:"\u5BBF\u4E3B\u6CA1\u6709\u8BF4\u660E\u5931\u8D25\u539F\u56E0\u3002",bootAttemptCommands:"\u4F60\u53EF\u4EE5\u81EA\u884C\u8FD0\u884C\u4EE5\u4E0B\u547D\u4EE4\uFF1A",entriesTitle:"\u53D7\u7BA1\u6761\u76EE",entriesDesc:"\u672C\u63D2\u4EF6\u5E0C\u671B\u6BCF\u6761\u76EE\u6210\u4E3A\u7684\u6837\u5B50\uFF0C\u4EE5\u53CA\u9762\u677F\u5B9E\u9645\u62A5\u544A\u7684\u72B6\u6001\u3002",entriesEmpty:"\u5C1A\u672A\u914D\u7F6E\u4EFB\u4F55\u53D7\u7BA1\u6761\u76EE\u3002",entriesExists:"\u5B58\u5728",entriesMissing:"\u7F3A\u5931",entriesManaged:"\u5DF2\u63A5\u7BA1",entriesUnmanaged:"\u672A\u63A5\u7BA1",entriesDrift:"\u6F02\u79FB",entriesLive:"\u5B9E\u65F6",entriesNotRunning:"\u672A\u8FD0\u884C",entriesAutostart:"\u81EA\u542F",entriesOnPortConflict:"\u7AEF\u53E3\u51B2\u7A81\u65F6",entriesStopKillPortHolders:"\u505C\u6B62\u7AEF\u53E3\u5360\u7528\u8005",entriesAdopt:"\u63A5\u7BA1",entriesPause:"\u6682\u505C",entriesRestore:"\u8FD8\u539F",agentTitle:"Agent \u5DE5\u5177",agentDesc:"Agent \u53EF\u4EE5\u8C03\u7528\u672C\u63D2\u4EF6\u7684\u54EA\u4E9B\u5DE5\u5177\u3002",agentMaster:"\u542F\u7528 Agent \u5DE5\u5177",agentApproval:"\u4F1A\u6539\u53D8\u72B6\u6001\u7684\u5DE5\u5177\u5728\u8FD0\u884C\u524D\u4F1A\u8BF7\u6C42\u6279\u51C6\u3002",agentToolMutating:"{name} \xB7 \u9700\u6279\u51C6",serversTitle:"\u670D\u52A1\u5668",serversDesc:"\u9762\u677F\u76D1\u7BA1\u7684\u670D\u52A1\u5668\u3002",serversHintPanel:"\u5728 home-hosted \u9762\u677F\u4E2D\u6DFB\u52A0\u3001\u7F16\u8F91\u548C\u5220\u9664\u6761\u76EE\uFF1A",serversHintNoPanel:"\u5728 home-hosted \u9762\u677F\u4E2D\u6DFB\u52A0\u3001\u7F16\u8F91\u548C\u5220\u9664\u6761\u76EE\uFF08\u5F53\u524D\u672A\u8FD0\u884C\uFF09\u3002",serversEmpty:"\u9762\u677F\u672A\u62A5\u544A\u4EFB\u4F55\u670D\u52A1\u5668\u3002",serversPid:"PID",serversUrl:"URL",serversStart:"\u542F\u52A8",serversStop:"\u505C\u6B62",serversRestart:"\u91CD\u542F"};function Xe(e,t){return t===void 0?e:e.replace(/\{(\w+)\}/g,(n,i)=>Object.prototype.hasOwnProperty.call(t,i)?String(t[i]):n)}var ue=(e,t)=>Xe(Q[e]??e,t);function ge(e){if(e!==void 0)try{let t=e.bind(j);if(typeof t=="function")return t}catch{}return ue}function fe(e,t=ue){return e===void 0?t:(n,i)=>{let r;try{r=e(n,i)}catch{r=void 0}return r===void 0||r.length===0||r===n?t(n,i):r}}var M=require("react");var B=require("react");var me="/home-hosted";var z=["status","servers_list","servers_start","servers_stop","servers_restart","servers_create","servers_update","servers_delete","autostart_install","autostart_uninstall"],be=["servers_start","servers_stop","servers_restart","servers_create","servers_update","servers_delete","autostart_install","autostart_uninstall"];var Ze="/api";function H(e,t,n){return{ok:!1,error:n===void 0?{code:e,message:t}:{code:e,message:t,detail:n}}}function ee(e){return typeof e=="object"&&e!==null}function Qe(e){return e instanceof Error?e.message:String(e)}function et(e){if(!ee(e))return H("bad-response","The panel returned a non-object response");if(typeof e.v=="number"&&e.v!==1)return H("version-mismatch",`Response protocol v${e.v} does not match the expected v${1}`);let t=e.result;if(!ee(t))return H("bad-response","The panel returned no result");if(t.ok===!0)return"value"in t?{ok:!0,value:t.value}:H("bad-response","A successful response carried no value");if(t.ok===!1){let n=t.error;return ee(n)&&typeof n.message=="string"?H(typeof n.code=="string"?n.code:"error",n.message,n.detail):H("error","The panel reported a failure without a message")}return H("bad-response","The panel returned an unrecognised result")}async function b(e,t,n={}){let i=n.fetch??globalThis.fetch;if(typeof i!="function")return H("no-fetch","No fetch implementation is available");let r={v:1,endpoint:e,payload:t},o;try{o=await i(`${Ze}${me}`,{method:"POST",credentials:"same-origin",headers:{"content-type":"application/json"},body:JSON.stringify(r)})}catch(u){return H("network",Qe(u))}if(!o.ok){let u=o.statusText.length>0?` ${o.statusText}`:"";return H("http",`HTTP ${o.status}${u}`)}let s;try{s=await o.json()}catch{return H("bad-json","The panel returned invalid JSON")}return et(s)}function G(e,t={}){return b("settings.update",{patch:e},t)}var tt=5e3;function he(e=tt){let[t,n]=(0,B.useState)(null),[i,r]=(0,B.useState)(null),[o,s]=(0,B.useState)(!0),u=(0,B.useRef)(!0),S=(0,B.useCallback)(async()=>{let C=await b("status",{});u.current&&(C.ok?(n(C.value),r(null)):r(C.error),s(!1))},[]);return(0,B.useEffect)(()=>{u.current=!0,S();let C=setInterval(()=>{S()},e);return()=>{u.current=!1,clearInterval(C)}},[S,e]),{data:t,error:i,loading:o,refresh:S}}var K="\u2014";function y(e){if(e==null)return K;let t=String(e);return t.length>0?t:K}function ve(e){return e.length>0?e.join(", "):K}function ye(e){return be.includes(e)}var Se={api:"writeViaApi",file:"writeViaFile",none:"writeViaNone"},Ce={enrolled:"tokenEnrolled",present:"tokenPresent",absent:"tokenAbsent",unknown:"tokenUnknown"},Pe={"not-installed":"bootStateNotInstalled","installed-disabled":"bootStateInstalledDisabled","enabled-running":"bootStateEnabledRunning","enabled-failing":"bootStateEnabledFailing",unsupported:"bootStateUnsupported"},W={config:"panelCliConfig",dependency:"panelCliDependency",path:"panelCliPathSource",none:"panelCliMissing"};function ne(e){return e==null?K:`${y(e.version)} \xB7 ${y(e.path)}`}function xe(e){let t=n=>e.source===n&&e.path!==null?{source:n,path:e.path,version:e.version}:null;return{dependency:e.dependency??t("dependency"),global:e.global??t("path")}}function Re(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function nt(e,t){if(Object.is(e,t))return!0;try{return JSON.stringify(e)===JSON.stringify(t)}catch{return!1}}function we(e,t){let n={};for(let i of Object.keys(t)){let r=e[i],o=t[i];if(Re(r)&&Re(o)){let s=we(r,o);Object.keys(s).length>0&&(n[i]=s)}else nt(r,o)||(n[i]=o)}return n}function Y(e,t){return we(e,t)}function ke(e,t,n){let i=new Set(e);return n?i.add(t):i.delete(t),z.filter(r=>i.has(r))}var p=require("react/jsx-runtime"),L="var(--dsw-alias-label-secondary, #8b8b8b)",oe="var(--dsw-alias-border-secondary, rgba(128, 128, 128, 0.25))",q="var(--dsw-alias-state-error-primary, #e53e3e)",ot={fontFamily:"ui-monospace, SFMono-Regular, Menlo, monospace",wordBreak:"break-all",textAlign:"right"};function k({title:e,description:t,children:n}){return(0,p.jsxs)("section",{style:{display:"flex",flexDirection:"column",gap:8,padding:"14px 0",borderTop:`1px solid ${oe}`},children:[(0,p.jsxs)("header",{style:{display:"flex",flexDirection:"column",gap:2},children:[(0,p.jsx)("h3",{style:{margin:0,fontSize:14,fontWeight:600},children:e}),t!==void 0&&t.length>0?(0,p.jsx)("p",{style:{margin:0,fontSize:12,color:L},children:t}):null]}),n]})}function l({label:e,children:t}){return(0,p.jsxs)("div",{style:{display:"flex",alignItems:"baseline",gap:12,justifyContent:"space-between",fontSize:13},children:[(0,p.jsx)("span",{style:{color:L},children:e}),(0,p.jsx)("span",{style:ot,children:t})]})}function d({children:e}){return typeof e=="string"&&(typeof e=="string"?e:"").length===0?null:(0,p.jsx)("p",{style:{margin:0,fontSize:12,color:L,lineHeight:1.5},children:e})}function U({href:e,children:t}){return(0,p.jsx)("a",{href:e,target:"_blank",rel:"noreferrer noopener",style:{color:L,textDecoration:"underline",overflowWrap:"anywhere"},children:t??e})}function Te({title:e,detail:t}){return(0,p.jsxs)("div",{role:"alert",style:{padding:"8px 10px",borderRadius:6,fontSize:12,lineHeight:1.5,border:`1px solid ${q}`,color:q},children:[(0,p.jsx)("strong",{children:e}),t.length>0?(0,p.jsx)("p",{style:{margin:"4px 0 0"},children:t}):null]})}function g({children:e,onClick:t,disabled:n,busy:i}){return(0,p.jsx)("button",{type:"button",onClick:t,disabled:n===!0||i===!0,style:{padding:"4px 10px",fontSize:12,borderRadius:6,border:`1px solid ${oe}`,background:"transparent",color:"inherit",cursor:n===!0||i===!0?"default":"pointer",opacity:n===!0||i===!0?.6:1},children:e})}function V({label:e,checked:t,disabled:n,onChange:i}){return(0,p.jsxs)("label",{style:{display:"flex",alignItems:"center",gap:8,fontSize:13,opacity:n===!0?.6:1,cursor:n===!0?"default":"pointer"},children:[(0,p.jsx)("input",{type:"checkbox",checked:t,disabled:n,onChange:r=>i(r.target.checked)}),(0,p.jsx)("span",{children:e})]})}function Ee({value:e,options:t,disabled:n,onChange:i}){return(0,p.jsx)("select",{value:e,disabled:n,onChange:r=>i(r.target.value),style:{padding:"3px 6px",fontSize:12,borderRadius:6,border:`1px solid ${oe}`,background:"transparent",color:"inherit"},children:t.map(r=>(0,p.jsx)("option",{value:r.value,children:r.label},r.value))})}function re({label:e,description:t,checked:n,disabled:i,onChange:r}){return(0,p.jsxs)("label",{style:{display:"flex",alignItems:"flex-start",gap:8,fontSize:13,opacity:i===!0?.6:1,cursor:i===!0?"default":"pointer"},children:[(0,p.jsx)("input",{type:"radio",checked:n,disabled:i,onChange:()=>r(),style:{marginTop:2}}),(0,p.jsxs)("span",{style:{display:"flex",flexDirection:"column",gap:2},children:[(0,p.jsx)("span",{children:e}),t!==void 0&&t.length>0?(0,p.jsx)("span",{style:{fontSize:12,color:L},children:t}):null]})]})}function $({error:e,title:t}){return e===null?null:(0,p.jsxs)("div",{role:"alert",style:{padding:"8px 10px",borderRadius:6,fontSize:12,lineHeight:1.5,border:`1px solid ${q}`,color:q},children:[(0,p.jsx)("strong",{children:t}),": ",(0,p.jsx)("code",{children:e.code})," \u2014 ",e.message]})}var O=require("react/jsx-runtime");function Ae({t:e,status:t,updateSettings:n}){let i=t.settings.agentTools,r=i.allow??[];return(0,O.jsxs)(k,{title:e("agentTitle"),description:e("agentDesc"),children:[(0,O.jsx)(V,{label:e("agentMaster"),checked:i.enabled,onChange:o=>n(s=>({...s,agentTools:{...s.agentTools,enabled:o}}))}),(0,O.jsx)(d,{children:e("agentApproval")}),(0,O.jsx)("div",{style:{display:"flex",flexDirection:"column",gap:6},children:z.map(o=>(0,O.jsx)(V,{label:ye(o)?e("agentToolMutating",{name:o}):o,checked:r.includes(o),disabled:!i.enabled,onChange:s=>n(u=>({...u,agentTools:{...u.agentTools,allow:ke(u.agentTools.allow??[],o,s)}}))},o))})]})}var ie=require("react");function He(e){return Array.isArray(e)?e.filter(t=>typeof t=="string"):[]}function Be(e){if(typeof e!="object"||e===null)return null;let t=e.result;if(typeof t!="object"||t===null)return null;let{ok:n,detail:i,commands:r}=t;return n!==!1?null:{detail:typeof i=="string"?i:"",commands:He(r)}}function Ne(e){return e===void 0?null:{ok:e.ok===!0,action:e.action==="uninstall"?"uninstall":"install",detail:typeof e.detail=="string"?e.detail:"",commands:He(e.commands)}}async function J(e){try{if(typeof navigator<"u"&&navigator.clipboard!==void 0)return await navigator.clipboard.writeText(e),!0}catch{}return!1}var c=require("react/jsx-runtime"),rt={width:"100%",minHeight:60,marginTop:6,padding:8,borderRadius:6,border:"1px solid var(--dsw-alias-border-secondary, rgba(128, 128, 128, 0.25))",background:"transparent",color:"inherit",fontFamily:"ui-monospace, SFMono-Regular, Menlo, monospace",fontSize:12,resize:"vertical"};function _e({text:e,copyLabel:t,copiedLabel:n}){let[i,r]=(0,ie.useState)(!1);return(0,c.jsxs)("div",{children:[(0,c.jsx)("textarea",{readOnly:!0,value:e,rows:Math.min(e.split(`
4
+ `).length,6),style:rt}),(0,c.jsx)("div",{style:{display:"flex",gap:8,marginTop:6},children:(0,c.jsx)(g,{onClick:()=>{J(e).then(r)},children:i?n:t})})]})}function Oe({t:e,status:t,run:n,updateSettings:i,busy:r}){let o=t.boot,s=t.settings.autostart,u=o.candidates??[],S=o.commands??[],[C,w]=(0,ie.useState)(null),A=r==="boot.install"||r==="boot.uninstall",R=r==="settings"||A,T=["auto",...u.filter(m=>m.available).map(m=>m.mechanism)];T.includes(s.mechanism)||T.push(s.mechanism);let N=T.map(m=>({value:m,label:m==="auto"?e("bootMechanismAuto"):m})),E=m=>e(m==="install"?"bootActionInstall":"bootActionUninstall"),I=async m=>{let D=m?"install":"uninstall",le=Y(t.settings,{...t.settings,autostart:{...s,enabled:m}}),pe=await n(`boot.${D}`,async()=>{if(Object.keys(le).length>0){let de=await G(le);if(!de.ok)return de}return m?b("boot.install",s.mechanism==="auto"?{}:{mechanism:s.mechanism}):b("boot.uninstall",{})});if(!pe.ok){w(null);return}let X=Be(pe.value);w(X===null?null:{ok:!1,action:D,detail:X.detail,commands:X.commands})},F=Ne(s.lastAttempt),x=C??F;return(0,c.jsxs)(k,{title:e("bootTitle"),description:e("bootDesc"),children:[(0,c.jsx)(V,{label:e("bootEnabled"),checked:s.enabled,disabled:A,onChange:m=>{I(m)}}),(0,c.jsx)(l,{label:e("bootMechanism"),children:(0,c.jsx)(Ee,{value:s.mechanism,options:N,disabled:R,onChange:m=>i(D=>({...D,autostart:{...D.autostart,mechanism:m}}))})}),(0,c.jsx)(l,{label:e("bootState"),children:e(Pe[o.state]??"bootStateUnsupported")}),(0,c.jsx)(l,{label:e("bootBootCapable"),children:o.bootCapable?e("yes"):e("no")}),(0,c.jsx)(l,{label:e("bootPrivileged"),children:o.privileged?e("yes"):e("no")}),(0,c.jsx)(l,{label:e("bootUnitPath"),children:y(o.unitPath)}),(0,c.jsx)(d,{children:o.detail}),s.enabled&&o.state==="not-installed"?(0,c.jsx)(d,{children:e("bootRequestedNotInstalled")}):null,x!==null&&!x.ok?(0,c.jsxs)("div",{children:[(0,c.jsx)(Te,{title:e("bootAttemptFailed",{action:E(x.action)}),detail:x.detail.length>0?x.detail:e("bootAttemptNoDetail")}),x.commands.length>0?(0,c.jsxs)("div",{children:[(0,c.jsx)(d,{children:e("bootAttemptCommands")}),(0,c.jsx)(_e,{text:x.commands.join(`
5
+ `),copyLabel:e("copy"),copiedLabel:e("copied")})]}):null]}):null,x!==null&&x.ok?(0,c.jsx)(d,{children:e("bootAttemptSucceeded",{action:E(x.action),detail:x.detail})}):null,S.length>0?(0,c.jsxs)("div",{children:[(0,c.jsx)(d,{children:e("bootCommandsExplain")}),(0,c.jsx)(_e,{text:S.join(`
6
+ `),copyLabel:e("copy"),copiedLabel:e("copied")})]}):null,(0,c.jsx)("div",{children:(0,c.jsx)(g,{busy:r==="boot.verify",onClick:()=>n("boot.verify",()=>b("boot.verify",{})),children:e("bootRecheck")})})]})}var P=require("react/jsx-runtime"),it={display:"flex",flexDirection:"column",gap:6,padding:10,borderRadius:6,border:"1px solid var(--dsw-alias-border-secondary, rgba(128, 128, 128, 0.25))"},st={display:"flex",alignItems:"baseline",justifyContent:"space-between",gap:12,fontSize:13},at={display:"flex",flexWrap:"wrap",gap:8};function Ie({t:e,status:t,run:n,busy:i}){let r=t.entries??[];return(0,P.jsx)(k,{title:e("entriesTitle"),description:e("entriesDesc"),children:r.length===0?(0,P.jsx)(d,{children:e("entriesEmpty")}):r.map(o=>{let s=o.intent.id,u=o.live;return(0,P.jsxs)("div",{style:it,children:[(0,P.jsxs)("div",{style:st,children:[(0,P.jsx)("strong",{children:s}),(0,P.jsxs)("span",{style:{color:"var(--dsw-alias-label-secondary, #8b8b8b)"},children:[o.exists?e("entriesExists"):e("entriesMissing")," \xB7 ",o.managed?e("entriesManaged"):e("entriesUnmanaged")]})]}),(0,P.jsx)(l,{label:e("entriesDrift"),children:ve(o.drift)}),(0,P.jsx)(l,{label:e("entriesLive"),children:u===null?e("entriesNotRunning"):`${y(u.status)}${u.pid===null?"":` \xB7 pid ${u.pid}`}`}),(0,P.jsx)(l,{label:e("entriesAutostart"),children:o.intent.autostart?e("yes"):e("no")}),(0,P.jsx)(l,{label:e("entriesOnPortConflict"),children:o.intent.onPortConflict}),(0,P.jsx)(l,{label:e("entriesStopKillPortHolders"),children:o.intent.stopKillPortHolders?e("yes"):e("no")}),(0,P.jsxs)("div",{style:at,children:[(0,P.jsx)(g,{busy:i===`entries.adopt:${s}`,onClick:()=>n(`entries.adopt:${s}`,()=>b("entries.apply",{intents:[o.intent]})),children:e("entriesAdopt")}),(0,P.jsx)(g,{busy:i===`entries.pause:${s}`,onClick:()=>n(`entries.pause:${s}`,()=>b("entries.apply",{intents:[{...o.intent,autostart:!1}]})),children:e("entriesPause")}),(0,P.jsx)(g,{busy:i===`entries.restore:${s}`,disabled:!o.managed,onClick:()=>n(`entries.restore:${s}`,()=>b("entries.restore",{id:s})),children:e("entriesRestore")})]})]},s)})})}var Me=require("react");var a=require("react/jsx-runtime"),lt={display:"flex",flexDirection:"column",gap:8,padding:10,borderRadius:6,border:"1px solid var(--dsw-alias-state-error-primary, #e53e3e)"},se={display:"flex",flexWrap:"wrap",gap:8};function De({t:e,status:t,run:n,busy:i}){let r=t.panel,o=t.cli,s=o?.prefer??t.settings.cli?.prefer??"pinned",[u,S]=(0,Me.useState)(!1),C=o?.version??null,w=r.version,A=C!==null&&w!==null,R=r.reachable&&A&&C===w,T=r.reachable&&A&&C!==w;return(0,a.jsxs)(k,{title:e("panelTitle"),description:e("panelDesc"),children:[(0,a.jsx)(l,{label:e("panelReachable"),children:r.reachable?e("yes"):e("no")}),(0,a.jsx)(l,{label:e("panelHome"),children:y(r.home)}),(0,a.jsx)(l,{label:e("panelUrl"),children:r.url===null?y(r.url):(0,a.jsx)(U,{href:r.url,children:r.url})}),(0,a.jsx)(l,{label:e("panelVersion"),children:y(r.version)}),(0,a.jsx)(l,{label:e("panelPid"),children:y(r.pid)}),(0,a.jsx)(l,{label:e("panelWriteVia"),children:e(Se[r.writeVia]??"writeViaNone")}),(0,a.jsx)(l,{label:e("panelToken"),children:e(Ce[r.token]??"tokenUnknown")}),o!==void 0&&(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(l,{label:e("panelCliSource"),children:`${e(W[o.source]??"panelCliMissing")} \xB7 ${y(o.version)}`}),(0,a.jsx)(l,{label:e("panelCliPath"),children:y(o.path)}),o.source==="path"&&s!=="global"&&(0,a.jsx)(d,{children:e("panelCliNotPinned",{range:o.expectedRange})}),o.launcherPath!=null&&o.launcherVersion==null&&(0,a.jsx)(d,{children:e("panelCliLauncherFailed")})]}),(0,a.jsx)(d,{children:r.detail}),r.reachable?null:(0,a.jsx)("div",{style:se,children:(0,a.jsx)(g,{busy:i==="panel.start",onClick:()=>{n("panel.start",()=>b("panel.start",{}))},children:e("panelStart")})}),R?(0,a.jsx)(d,{children:e("panelAlreadyPreferred")}):null,T?u?(0,a.jsxs)("div",{style:lt,role:"alertdialog","aria-label":e("panelTakeoverTitle"),children:[(0,a.jsx)("strong",{children:e("panelTakeoverTitle")}),(0,a.jsx)(d,{children:e("panelTakeoverBody")}),(0,a.jsxs)("div",{style:se,children:[(0,a.jsx)(g,{onClick:()=>S(!1),children:e("confirmCancel")}),(0,a.jsx)(g,{busy:i==="panel.takeover",onClick:()=>{S(!1),n("panel.takeover",()=>b("panel.takeover",{}))},children:e("confirmReplace")})]})]}):(0,a.jsx)("div",{style:se,children:(0,a.jsx)(g,{onClick:()=>S(!0),children:e("panelReplace",{version:C})})}):null]})}var ae=require("react");var f=require("react/jsx-runtime"),pt={display:"flex",flexDirection:"column",gap:6,padding:10,borderRadius:6,border:"1px solid var(--dsw-alias-border-secondary, rgba(128, 128, 128, 0.25))"},dt={width:"100%",minHeight:48,padding:8,borderRadius:6,border:"1px solid var(--dsw-alias-border-secondary, rgba(128, 128, 128, 0.25))",background:"transparent",color:"inherit",fontFamily:"ui-monospace, SFMono-Regular, Menlo, monospace",fontSize:12,resize:"vertical"},ct={display:"flex",flexWrap:"wrap",gap:8},ut={maxHeight:180,margin:"6px 0 0",padding:8,overflow:"auto",borderRadius:6,border:"1px solid var(--dsw-alias-border-secondary, rgba(128, 128, 128, 0.25))",fontFamily:"ui-monospace, SFMono-Regular, Menlo, monospace",fontSize:12,whiteSpace:"pre-wrap"};function Le({t:e,status:t,run:n,updateSettings:i,busy:r}){let o=t.cli,[s,u]=(0,ae.useState)(!1),[S,C]=(0,ae.useState)(null);if(o===void 0)return(0,f.jsx)(k,{title:e("optionsTitle"),description:e("optionsDesc"),children:(0,f.jsx)(d,{children:e("optionsCliUnavailable")})});let w=o.prefer??t.settings.cli?.prefer??"pinned",{dependency:A,global:R}=xe(o),T=[`pnpm add -g home-hosted@${o.expectedRange}`,`npm install -g home-hosted@${o.expectedRange}`],N=r==="settings",E=async()=>{u(await J(T.join(`
7
+ `)))},I=async()=>{let x=await n("cli.installGlobal",()=>b("cli.installGlobal",{}));if(!x.ok)return;let m=x.value;C(typeof m?.output=="string"?m.output:null)},F=x=>{i(m=>({...m,cli:{...m.cli,prefer:x}}))};return(0,f.jsxs)(k,{title:e("optionsTitle"),description:e("optionsDesc"),children:[(0,f.jsx)(l,{label:e("optionsCurrent"),children:e(W[o.source]??"cliSourceNone")}),(0,f.jsx)(l,{label:e("optionsVersion"),children:y(o.version)}),(0,f.jsx)(l,{label:e("optionsPath"),children:y(o.path)}),(0,f.jsx)(d,{children:o.detail}),o.source==="config"?(0,f.jsx)(d,{children:e("optionsConfigOverride")}):null,(0,f.jsxs)("div",{style:{display:"flex",flexDirection:"column",gap:8},children:[(0,f.jsx)(re,{label:e("optionsPreferPinned"),description:A===null?e("optionsNotResolved"):ne(A),checked:w==="pinned",disabled:A===null||N,onChange:()=>F("pinned")}),(0,f.jsx)(re,{label:e("optionsPreferGlobal"),description:R===null?e("optionsNotResolved"):ne(R),checked:w==="global",disabled:R===null||N,onChange:()=>F("global")})]}),(0,f.jsx)(d,{children:e("optionsPreferHint")}),R===null?(0,f.jsxs)("div",{style:pt,children:[(0,f.jsx)(d,{children:e("optionsInstallHint")}),(0,f.jsx)("textarea",{readOnly:!0,value:T.join(`
8
+ `),rows:2,style:dt}),(0,f.jsxs)("div",{style:ct,children:[(0,f.jsx)(g,{onClick:()=>{E()},children:e(s?"copied":"copy")}),(0,f.jsx)(g,{busy:r==="cli.installGlobal",onClick:()=>{I()},children:e("optionsInstall")}),(0,f.jsx)(g,{busy:r==="status.refresh",onClick:()=>{n("status.refresh",()=>b("status",{refresh:!0}))},children:e("refresh")})]}),S===null?null:(0,f.jsxs)("details",{children:[(0,f.jsx)("summary",{style:{fontSize:12,cursor:"pointer"},children:e("optionsOutput")}),(0,f.jsx)("pre",{style:ut,children:S})]})]}):null]})}var h=require("react/jsx-runtime"),gt={display:"flex",flexDirection:"column",gap:6,padding:10,borderRadius:6,border:"1px solid var(--dsw-alias-border-secondary, rgba(128, 128, 128, 0.25))"},ft={display:"flex",alignItems:"baseline",justifyContent:"space-between",gap:12,fontSize:13},Ue={display:"flex",flexWrap:"wrap",gap:8};function Ve({t:e,status:t,run:n,busy:i}){let r=t.servers??[];return(0,h.jsxs)(k,{title:e("serversTitle"),description:e("serversDesc"),children:[(0,h.jsx)("div",{style:Ue,children:(0,h.jsx)(g,{busy:i==="status.refresh",onClick:()=>n("status.refresh",()=>b("status",{refresh:!0})),children:e("refresh")})}),(0,h.jsx)(d,{children:t.panel.url===null?e("serversHintNoPanel"):(0,h.jsxs)(h.Fragment,{children:[`${e("serversHintPanel")} `,(0,h.jsx)(U,{href:t.panel.url,children:t.panel.url})]})}),r.length===0?(0,h.jsx)(d,{children:e("serversEmpty")}):r.map(o=>(0,h.jsxs)("div",{style:gt,children:[(0,h.jsxs)("div",{style:ft,children:[(0,h.jsx)("strong",{children:o.id}),(0,h.jsx)("span",{children:y(o.status)})]}),(0,h.jsx)(l,{label:e("serversPid"),children:y(o.pid)}),(0,h.jsx)(l,{label:e("serversUrl"),children:o.url===null?y(o.url):(0,h.jsx)(U,{href:o.url,children:o.url})}),(0,h.jsxs)("div",{style:Ue,children:[(0,h.jsx)(g,{busy:i===`servers.start:${o.id}`,onClick:()=>n(`servers.start:${o.id}`,()=>b("servers.start",{id:o.id})),children:e("serversStart")}),(0,h.jsx)(g,{busy:i===`servers.stop:${o.id}`,onClick:()=>n(`servers.stop:${o.id}`,()=>b("servers.stop",{id:o.id})),children:e("serversStop")}),(0,h.jsx)(g,{busy:i===`servers.restart:${o.id}`,onClick:()=>n(`servers.restart:${o.id}`,()=>b("servers.restart",{id:o.id})),children:e("serversRestart")})]})]},o.id))]})}var v=require("react/jsx-runtime");function $e(e){let t=fe(e.t),{data:n,error:i,loading:r,refresh:o}=he(),[s,u]=(0,M.useState)(null),[S,C]=(0,M.useState)(null),w=(0,M.useCallback)((T,N)=>(C(T),u(null),(async()=>{try{let E=await N();return E.ok||u(E.error),E}catch(E){let I={code:"client",message:E instanceof Error?E.message:String(E)};return u(I),{ok:!1,error:I}}finally{C(null),await o()}})()),[o]),A=(0,M.useCallback)(T=>{if(n===null)return;let N=Y(n.settings,T(n.settings));Object.keys(N).length!==0&&w("settings",()=>G(N))},[n,w]);if(n===null)return(0,v.jsxs)("div",{style:{display:"flex",flexDirection:"column",gap:8},children:[r?(0,v.jsx)(d,{children:t("loading")}):(0,v.jsx)($,{error:i??{code:"status",message:t("statusUnavailable")},title:t("errorTitle")}),r?null:(0,v.jsx)("div",{children:(0,v.jsx)(g,{onClick:()=>{o()},children:t("retry")})})]});let R={t,status:n,run:w,updateSettings:A,busy:S};return(0,v.jsxs)("div",{style:{display:"flex",flexDirection:"column"},children:[(0,v.jsxs)("header",{style:{display:"flex",alignItems:"flex-start",justifyContent:"space-between",gap:12},children:[(0,v.jsxs)("div",{children:[(0,v.jsx)("h2",{style:{margin:0,fontSize:16},children:t("tab")}),(0,v.jsx)("p",{style:{margin:"2px 0 0",fontSize:12,color:"var(--dsw-alias-label-secondary, #8b8b8b)"},children:t("pageDesc")})]}),(0,v.jsx)(g,{busy:S==="status.refresh",onClick:()=>w("status.refresh",()=>b("status",{refresh:!0})),children:t("refresh")})]}),n.lastError===null?null:(0,v.jsx)($,{error:{code:"panel",message:n.lastError},title:t("errorTitle")}),(0,v.jsx)($,{error:i,title:t("errorTitle")}),(0,v.jsx)($,{error:s,title:t("errorTitle")}),(0,v.jsx)(De,{...R}),(0,v.jsx)(Le,{...R}),(0,v.jsx)(Oe,{...R}),(0,v.jsx)(Ie,{...R}),(0,v.jsx)(Ae,{...R}),(0,v.jsx)(Ve,{...R})]})}var mt=["slots","locale"],Fe="[dsh-home-hosted]";function _(e,t){t===void 0?console.warn(`${Fe} ${e}`):console.warn(`${Fe} ${e}`,t)}function je(e,t){try{let n=e.get?.(t);if(n!=null)return n}catch{}try{let n=e[t];if(n!=null)return n}catch{}}function ze(e,t,n){if(typeof e.effect=="function")try{e.effect(t,n);return}catch(i){_(`registering the effect "${n}" failed`,i);return}try{t()}catch(i){_(`the effect "${n}" failed`,i)}}function bt(e){try{let t=je(e,"locale"),n=ge(t);t===void 0?_("the locale service is unavailable; the page keeps its bundled English copy"):ze(e,()=>{let r=[];try{r.push(t.register(j,{en:Q,zh:ce}))}catch(o){_("registering the dictionaries failed",o)}return()=>{for(let o of r)try{o()}catch(s){_("disposing a dictionary failed",s)}}},"dsh-home-hosted: dictionaries");let i=je(e,"slots");if(i===void 0){_("the slots service is unavailable; the settings section was not registered");return}ze(e,()=>{try{return i.inject("settings.section",()=>{try{return i.register({name:"settings.section",id:"home-hosted",order:60,label:()=>n("tab"),locale:j,inject:()=>({t:n})},$e)}catch(r){return _("registering the settings section failed",r),()=>{}}})}catch(r){return _("injecting into settings.section failed",r),()=>{}}},"dsh-home-hosted: settings section")}catch(t){_("client bootstrap failed",t)}}
8
9
 
9
10
  return module.exports; } });
package/lib/index.js CHANGED
@@ -320,9 +320,10 @@ function systemdText(value) {
320
320
  }
321
321
  function systemdPath(value, what = "path") {
322
322
  assertAbsolute(value, what);
323
+ assertNoControl(value, what);
323
324
  if (value.includes('"'))
324
325
  throw new Error(`${what} must not contain a double quote: ${JSON.stringify(value)}`);
325
- return value;
326
+ return replaceAll(value, [["\\", "\\\\"], ["%", "%%"]]);
326
327
  }
327
328
  function systemdEnvLine(key, value) {
328
329
  assertEnvKey(key);
@@ -961,10 +962,13 @@ function createLaunchdProvider(ctx, mode) {
961
962
  const domain = await domainOf();
962
963
  return {
963
964
  mechanism,
964
- available: domain !== null,
965
+ // A plist in ~/Library/LaunchAgents is loaded at login whether or not
966
+ // this process can reach launchd right now, so an unreachable domain
967
+ // is a diagnostic, not a reason to refuse.
968
+ available: true,
965
969
  bootCapable: false,
966
970
  privileged: true,
967
- reason: domain === null ? `no launchd gui/$UID or user/$UID domain is reachable for uid ${uidOf(ctx) ?? "?"}` : `launchd ${domain} domain is reachable; a LaunchAgent loads at login, not at boot`
971
+ reason: domain === null ? `a LaunchAgent loads at login; launchd's domain is not reachable from this process for uid ${uidOf(ctx) ?? "?"} right now, so it is loaded at the next login` : `launchd ${domain} domain is reachable; a LaunchAgent loads at login, not at boot`
968
972
  };
969
973
  }
970
974
  const canElevate = ctx.isRoot || await ctx.sudo();
@@ -1024,11 +1028,9 @@ function createLaunchdProvider(ctx, mode) {
1024
1028
  });
1025
1029
  }
1026
1030
  const domain = await domainOf();
1027
- if (domain === null)
1028
- return failed(`launchd has no reachable domain for uid ${uidOf(ctx) ?? "?"}; refusing to write an agent that could never load`);
1029
1031
  ensureDirQuiet(path3.posix.dirname(file));
1030
1032
  ensureDirQuiet(spec.logDir);
1031
- const loaded = codeOf2(await ctx.run("launchctl", ["print", `${domain}/${label}`])) === 0;
1033
+ const loaded = domain !== null && codeOf2(await ctx.run("launchctl", ["print", `${domain}/${label}`])) === 0;
1032
1034
  const before = { text: own.text, exists: own.exists };
1033
1035
  let changed = false;
1034
1036
  if (mode === "agent" || ctx.isRoot) {
@@ -1053,6 +1055,15 @@ function createLaunchdProvider(ctx, mode) {
1053
1055
  const lint = await runPrivileged("plutil", ["-lint", file]);
1054
1056
  if (codeOf2(lint) !== 0)
1055
1057
  return failed(`plutil -lint rejected the generated plist: ${(lint.stderr || lint.stdout).trim() || "no output"}`, { changed, commands: commands(file, label) });
1058
+ if (domain === null) {
1059
+ return {
1060
+ ok: true,
1061
+ changed,
1062
+ detail: `${file} is in place; launchd's domain is not reachable from this process, so it loads at the next login`,
1063
+ commands: [],
1064
+ needsPrivilege: false
1065
+ };
1066
+ }
1056
1067
  if (loaded && changed) {
1057
1068
  const bootout = await runPrivileged("launchctl", ["bootout", `${domain}/${label}`]);
1058
1069
  const bootoutCode = codeOf2(bootout);
@@ -3207,14 +3218,23 @@ var HomeHostedService = class extends Service {
3207
3218
  if (spec === null)
3208
3219
  throw new HomeHostedError((await this.cli()).resolution.status.detail, "CLI_NOT_FOUND");
3209
3220
  const result = await this.ladder().install(spec, mechanism);
3210
- if (result.ok) {
3211
- this.options.settings.update({
3212
- autostart: {
3213
- enabled: true,
3214
- mechanism: mechanism ?? result.mechanism ?? this.options.settings.get().autostart.mechanism
3221
+ const current = this.options.settings.get().autostart;
3222
+ this.options.settings.update({
3223
+ autostart: {
3224
+ // The preference follows the outcome for a real install, and the last
3225
+ // attempt is recorded either way so a failure is visible after a reload.
3226
+ enabled: result.ok ? true : current.enabled,
3227
+ mechanism: result.ok ? mechanism ?? result.mechanism ?? current.mechanism : current.mechanism,
3228
+ lastAttempt: {
3229
+ ok: result.ok,
3230
+ action: "install",
3231
+ mechanism: result.mechanism ?? mechanism ?? null,
3232
+ detail: result.detail,
3233
+ commands: result.commands,
3234
+ at: Date.now()
3215
3235
  }
3216
- });
3217
- }
3236
+ }
3237
+ });
3218
3238
  return { result, status: await this.bootStatus(mechanism) };
3219
3239
  }
3220
3240
  async uninstallBoot(mechanism) {
@@ -3222,8 +3242,21 @@ var HomeHostedService = class extends Service {
3222
3242
  if (spec === null)
3223
3243
  throw new HomeHostedError((await this.cli()).resolution.status.detail, "CLI_NOT_FOUND");
3224
3244
  const result = await this.ladder().uninstall(spec, mechanism);
3225
- if (result.ok)
3226
- this.options.settings.update({ autostart: { ...this.options.settings.get().autostart, enabled: false } });
3245
+ const current = this.options.settings.get().autostart;
3246
+ this.options.settings.update({
3247
+ autostart: {
3248
+ ...current,
3249
+ enabled: result.ok ? false : current.enabled,
3250
+ lastAttempt: {
3251
+ ok: result.ok,
3252
+ action: "uninstall",
3253
+ mechanism: result.mechanism ?? mechanism ?? null,
3254
+ detail: result.detail,
3255
+ commands: result.commands,
3256
+ at: Date.now()
3257
+ }
3258
+ }
3259
+ });
3227
3260
  return { result, status: await this.bootStatus(mechanism) };
3228
3261
  }
3229
3262
  // -------------------------------------------------------------------------
@@ -3481,10 +3514,12 @@ function normalizeIntent(value, fallbackId) {
3481
3514
  function normalize(raw, fallbackEntryId) {
3482
3515
  const entries = Array.isArray(raw?.entries) ? raw.entries.map((intent) => normalizeIntent(intent, fallbackEntryId)) : [];
3483
3516
  const allow = Array.isArray(raw?.agentTools?.allow) ? raw.agentTools.allow.filter(knownTool) : DEFAULT_SETTINGS.agentTools.allow;
3517
+ const attempt = raw?.autostart?.lastAttempt;
3484
3518
  return {
3485
3519
  autostart: {
3486
3520
  enabled: raw?.autostart?.enabled === true,
3487
- mechanism: raw?.autostart?.mechanism ?? "auto"
3521
+ mechanism: raw?.autostart?.mechanism ?? "auto",
3522
+ ...attempt === void 0 ? {} : { lastAttempt: attempt }
3488
3523
  },
3489
3524
  entries,
3490
3525
  agentTools: {