dsh-home-hosted 0.1.2 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -39,7 +39,7 @@ Everything a person toggles lives in `<stateDir>/settings.json`, including **Opt
39
39
 
40
40
  - A plugin cannot act at boot: it installs and re-syncs the OS entry while dsh runs, and the OS starts home-hosted from then on.
41
41
  - The plugin ships its own `home-hosted` (pinned range) and runs that copy by default; Options in the page can switch to a global install instead. Boot entries run a small stable launcher it writes, so a `node_modules` path that moves never breaks boot.
42
- - Boot (pre-login) scope needs privilege somewhere — a system unit, or `loginctl enable-linger` on Linux. When the process cannot elevate, the page shows the exact commands to run by hand.
42
+ - Boot (pre-login) needs privilege somewhere, and the page shows the exact commands when it cannot elevate: on macOS pick the boot-scope **launchd-daemon** (a one-time `sudo` install), on Linux **systemd-system** or `loginctl enable-linger`. A `LaunchAgent` and an XDG entry start at login only.
43
43
  - The panel API token this plugin uses is minted on first write and kept 0600 under the plugin state directory; it is never rendered or logged.
44
44
  - `onPortConflict: kill` needs home-hosted 0.6.0 or newer; against an older panel the plugin refuses that write and says so, because that panel cannot parse the config it would produce.
45
45
 
package/docs/DESIGN.md CHANGED
@@ -41,6 +41,16 @@ 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: agent or daemon
45
+
46
+ A `LaunchAgent` starts at login; starting before login means a `LaunchDaemon` in
47
+ `/Library/LaunchDaemons`, which is root-owned and needs a one-time `sudo`
48
+ install. The daemon is therefore offered even when this process cannot elevate:
49
+ install stages the plist and returns the three commands to run. The daemon plist
50
+ names the invoking user in `UserName`, Apple's sanctioned way to avoid running
51
+ the panel as root, and the recommendation still prefers a mechanism this process
52
+ can install on its own so "Automatic" stays a single click.
53
+
44
54
  ## macOS: reachable launchd is not a requirement
45
55
 
46
56
  A plist in `~/Library/LaunchAgents` is loaded by launchd at the next login whether
package/lib/client.js CHANGED
@@ -1,10 +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 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)}}
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",bootLoginScope:"This entry starts at login. To start before login, choose a boot-scope mechanism: launchd-daemon on macOS (needs sudo once), or systemd-system / linger on Linux.",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",bootLoginScope:"\u6B64\u6761\u76EE\u5728\u767B\u5F55\u540E\u542F\u52A8\u3002\u82E5\u8981\u5728\u767B\u5F55\u524D\u542F\u52A8\uFF0C\u8BF7\u9009\u62E9\u5F00\u673A\u7EA7\u673A\u5236\uFF1AmacOS \u7528 launchd-daemon\uFF08\u9700\u4E00\u6B21 sudo\uFF09\uFF0CLinux \u7528 systemd-system \u6216 linger\u3002",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 L=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"},xe={"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 Pe(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"),D="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:D},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:D},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:D,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:D,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:D},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 _=require("react/jsx-runtime");function Ae({t:e,status:t,updateSettings:n}){let i=t.settings.agentTools,r=i.allow??[];return(0,_.jsxs)(k,{title:e("agentTitle"),description:e("agentDesc"),children:[(0,_.jsx)(V,{label:e("agentMaster"),checked:i.enabled,onChange:o=>n(s=>({...s,agentTools:{...s.agentTools,enabled:o}}))}),(0,_.jsx)(d,{children:e("agentApproval")}),(0,_.jsx)("div",{style:{display:"flex",flexDirection:"column",gap:6},children:z.map(o=>(0,_.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 Oe({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 _e({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 M=m?"install":"uninstall",le=Y(t.settings,{...t.settings,autostart:{...s,enabled:m}}),pe=await n(`boot.${M}`,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:M,detail:X.detail,commands:X.commands})},F=Ne(s.lastAttempt),P=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(M=>({...M,autostart:{...M.autostart,mechanism:m}}))})}),(0,c.jsx)(l,{label:e("bootState"),children:e(xe[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)}),o.bootCapable||o.state==="unsupported"?null:(0,c.jsx)(d,{children:e("bootLoginScope")}),(0,c.jsx)(d,{children:o.detail}),s.enabled&&o.state==="not-installed"?(0,c.jsx)(d,{children:e("bootRequestedNotInstalled")}):null,P!==null&&!P.ok?(0,c.jsxs)("div",{children:[(0,c.jsx)(Te,{title:e("bootAttemptFailed",{action:E(P.action)}),detail:P.detail.length>0?P.detail:e("bootAttemptNoDetail")}),P.commands.length>0?(0,c.jsxs)("div",{children:[(0,c.jsx)(d,{children:e("bootAttemptCommands")}),(0,c.jsx)(Oe,{text:P.commands.join(`
5
+ `),copyLabel:e("copy"),copiedLabel:e("copied")})]}):null]}):null,P!==null&&P.ok?(0,c.jsx)(d,{children:e("bootAttemptSucceeded",{action:E(P.action),detail:P.detail})}):null,S.length>0?(0,c.jsxs)("div",{children:[(0,c.jsx)(d,{children:e("bootCommandsExplain")}),(0,c.jsx)(Oe,{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 x=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,x.jsx)(k,{title:e("entriesTitle"),description:e("entriesDesc"),children:r.length===0?(0,x.jsx)(d,{children:e("entriesEmpty")}):r.map(o=>{let s=o.intent.id,u=o.live;return(0,x.jsxs)("div",{style:it,children:[(0,x.jsxs)("div",{style:st,children:[(0,x.jsx)("strong",{children:s}),(0,x.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,x.jsx)(l,{label:e("entriesDrift"),children:ve(o.drift)}),(0,x.jsx)(l,{label:e("entriesLive"),children:u===null?e("entriesNotRunning"):`${y(u.status)}${u.pid===null?"":` \xB7 pid ${u.pid}`}`}),(0,x.jsx)(l,{label:e("entriesAutostart"),children:o.intent.autostart?e("yes"):e("no")}),(0,x.jsx)(l,{label:e("entriesOnPortConflict"),children:o.intent.onPortConflict}),(0,x.jsx)(l,{label:e("entriesStopKillPortHolders"),children:o.intent.stopKillPortHolders?e("yes"):e("no")}),(0,x.jsxs)("div",{style:at,children:[(0,x.jsx)(g,{busy:i===`entries.adopt:${s}`,onClick:()=>n(`entries.adopt:${s}`,()=>b("entries.apply",{intents:[o.intent]})),children:e("entriesAdopt")}),(0,x.jsx)(g,{busy:i===`entries.pause:${s}`,onClick:()=>n(`entries.pause:${s}`,()=>b("entries.apply",{intents:[{...o.intent,autostart:!1}]})),children:e("entriesPause")}),(0,x.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 Le=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 Me({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,Le.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 De({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}=Pe(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 P=await n("cli.installGlobal",()=>b("cli.installGlobal",{}));if(!P.ok)return;let m=P.value;C(typeof m?.output=="string"?m.output:null)},F=P=>{i(m=>({...m,cli:{...m.cli,prefer:P}}))};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,L.useState)(null),[S,C]=(0,L.useState)(null),w=(0,L.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,L.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)(Me,{...R}),(0,v.jsx)(De,{...R}),(0,v.jsx)(_e,{...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 O(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){O(`registering the effect "${n}" failed`,i);return}try{t()}catch(i){O(`the effect "${n}" failed`,i)}}function bt(e){try{let t=je(e,"locale"),n=ge(t);t===void 0?O("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){O("registering the dictionaries failed",o)}return()=>{for(let o of r)try{o()}catch(s){O("disposing a dictionary failed",s)}}},"dsh-home-hosted: dictionaries");let i=je(e,"slots");if(i===void 0){O("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 O("registering the settings section failed",r),()=>{}}})}catch(r){return O("injecting into settings.section failed",r),()=>{}}},"dsh-home-hosted: settings section")}catch(t){O("client bootstrap failed",t)}}
9
9
 
10
10
  return module.exports; } });
package/lib/index.js CHANGED
@@ -199,6 +199,16 @@ function currentUser(ctx) {
199
199
  return null;
200
200
  }
201
201
  }
202
+ function userNameOf(ctx) {
203
+ const configured = ctx.env.USER?.trim() ?? ctx.env.USERNAME?.trim();
204
+ if (configured !== void 0 && configured.length > 0)
205
+ return configured;
206
+ try {
207
+ return os.userInfo().username;
208
+ } catch {
209
+ return null;
210
+ }
211
+ }
202
212
  function uidOf(ctx) {
203
213
  const configured = ctx.env.UID?.trim();
204
214
  if (configured)
@@ -868,9 +878,10 @@ function validate2(spec) {
868
878
  function launchdLabel(spec) {
869
879
  return `${LAUNCHD_LABEL_PREFIX}${assertUnitName(spec.unitName)}`;
870
880
  }
871
- function launchdPlist(spec) {
881
+ function launchdPlist(spec, options = {}) {
872
882
  validate2(spec);
873
883
  const label = launchdLabel(spec);
884
+ const userName = options.userName?.trim();
874
885
  const out = path3.posix.join(spec.logDir, `${label}.out.log`);
875
886
  const err = path3.posix.join(spec.logDir, `${label}.err.log`);
876
887
  const envKeys = Object.keys(spec.env);
@@ -881,6 +892,7 @@ function launchdPlist(spec) {
881
892
  "<dict>",
882
893
  " <key>Label</key>",
883
894
  ` <string>${xmlEscape(label)}</string>`,
895
+ ...userName === void 0 || userName.length === 0 ? [] : [" <key>UserName</key>", ` <string>${xmlEscape(userName)}</string>`],
884
896
  " <key>ProgramArguments</key>",
885
897
  " <array>",
886
898
  ...[spec.command, ...spec.args].map((arg) => ` <string>${xmlEscape(arg)}</string>`),
@@ -974,10 +986,13 @@ function createLaunchdProvider(ctx, mode) {
974
986
  const canElevate = ctx.isRoot || await ctx.sudo();
975
987
  return {
976
988
  mechanism,
977
- available: canElevate,
978
- bootCapable: canElevate,
989
+ // Always selectable: without root the plugin stages the plist and hands
990
+ // over the three sudo commands, which is the only way to start before
991
+ // login on a Mac that has no passwordless sudo.
992
+ available: true,
993
+ bootCapable: true,
979
994
  privileged: canElevate,
980
- reason: canElevate ? "this process can write /Library/LaunchDaemons, so a LaunchDaemon starts at boot" : "a LaunchDaemon needs root or passwordless sudo"
995
+ reason: canElevate ? "this process can write /Library/LaunchDaemons, so a LaunchDaemon starts at boot" : "a LaunchDaemon starts at boot but needs root here, so the plugin stages the plist and shows the sudo commands"
981
996
  };
982
997
  },
983
998
  async status(spec) {
@@ -1010,7 +1025,7 @@ function createLaunchdProvider(ctx, mode) {
1010
1025
  validate2(spec);
1011
1026
  const file = pathOf(spec);
1012
1027
  const label = launchdLabel(spec);
1013
- const content = launchdPlist(spec);
1028
+ const content = launchdPlist(spec, mode === "daemon" ? { userName: userNameOf(ctx) } : {});
1014
1029
  const own = inspectOwned(file, spec.marker);
1015
1030
  if (own.exists && !own.owned)
1016
1031
  return failed(own.reason ?? "foreign file");
@@ -1816,11 +1831,18 @@ function createBootLadder(options = {}) {
1816
1831
  function recommend(candidates) {
1817
1832
  const byMechanism = new Map(candidates.map((candidate) => [candidate.mechanism, candidate]));
1818
1833
  const available = providers.map((provider) => provider.mechanism).filter((mechanism) => byMechanism.get(mechanism)?.available === true);
1819
- const bootCapable = available.find((mechanism) => mechanism !== "container" && byMechanism.get(mechanism)?.bootCapable === true);
1820
- if (bootCapable)
1821
- return bootCapable;
1834
+ const usable = (mechanism) => mechanism !== "container" && mechanism !== "unsupported";
1822
1835
  if (available.includes("container"))
1823
1836
  return "container";
1837
+ const readyBoot = available.find((mechanism) => usable(mechanism) && byMechanism.get(mechanism)?.bootCapable === true && byMechanism.get(mechanism)?.privileged === true);
1838
+ if (readyBoot)
1839
+ return readyBoot;
1840
+ const ready = available.find((mechanism) => usable(mechanism) && byMechanism.get(mechanism)?.privileged === true);
1841
+ if (ready)
1842
+ return ready;
1843
+ const bootCapable = available.find((mechanism) => usable(mechanism) && byMechanism.get(mechanism)?.bootCapable === true);
1844
+ if (bootCapable)
1845
+ return bootCapable;
1824
1846
  return available.find((mechanism) => mechanism !== "unsupported") ?? available[0] ?? null;
1825
1847
  }
1826
1848
  async function buildStatus(spec, mechanism) {