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 +1 -1
- package/docs/DESIGN.md +10 -0
- package/lib/client.js +6 -6
- package/lib/index.js +30 -8
- package/lib/index.js.map +2 -2
- package/lib/types/boot/common.d.ts +2 -0
- package/lib/types/boot/launchd.d.ts +5 -1
- package/package.json +1 -1
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)
|
|
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
|
|
5
|
-
`),copyLabel:e("copy"),copiedLabel:e("copied")})]}):null]}):null,
|
|
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
|
|
7
|
-
`)))},I=async()=>{let
|
|
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,
|
|
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
|
-
|
|
978
|
-
|
|
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
|
|
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
|
|
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) {
|