dsh-home-hosted 0.2.2 → 0.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/index.js.map CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../src/index.ts", "../src/config.ts", "../src/shared/contracts.ts", "../src/service.ts", "../src/boot/ladder.ts", "../src/util/exec.ts", "../src/boot/common.ts", "../src/util/fsx.ts", "../src/boot/systemd.ts", "../src/boot/escape.ts", "../src/boot/launchd.ts", "../src/boot/xdg.ts", "../src/boot/windows.ts", "../src/boot/fallback.ts", "../src/home-hosted/config-file.ts", "../src/util/paths.ts", "../src/home-hosted/dsh-entry.ts", "../src/home-hosted/launch.ts", "../src/home-hosted/entries.ts", "../src/home-hosted/resolve.ts", "../src/home-hosted/launcher.ts", "../src/home-hosted/panel-control.ts", "../src/home-hosted/panel.ts", "../src/home-hosted/runtime.ts", "../src/home-hosted/token.ts", "../src/rpc.ts", "../src/home-hosted/web-notice.ts", "../src/settings.ts", "../src/tools.ts"],
4
- "sourcesContent": ["/**\n * `dsh-home-hosted` \u2014 boot autostart for the home-hosted panel, and home-hosted\n * server management, from inside DeepSeek Harness.\n *\n * The plugin supplies no server entries of its own: everything it manages is\n * declared by the person using the page, and nothing here knows a blessed id\n * beyond the one it is told to treat as the running harness.\n */\nimport type { Context } from '@deepseek-ai/cordis'\nimport path from 'node:path'\nimport { Config } from './config.js'\nimport type { Config as ConfigShape } from './config.js'\nimport { registerRpc } from './rpc.js'\nimport { HomeHostedService } from './service.js'\nimport { registerAuthNotice } from './home-hosted/web-notice.js'\nimport { SettingsStore } from './settings.js'\nimport { registerAgentTools } from './tools.js'\nimport { ensureDir } from './util/fsx.js'\nimport { homeHostedHome, pluginStateDir } from './util/paths.js'\n\nexport const name = 'dsh-home-hosted'\n\nexport { Config }\n\nexport const inject: string[] = []\n\nexport function apply(ctx: Context, config?: ConfigShape): void {\n const resolved: ConfigShape = {\n stateDir: config?.stateDir,\n homeHostedCommand: config?.homeHostedCommand,\n defaultEntryId: config?.defaultEntryId ?? 'dsh',\n }\n\n const stateDir = pluginStateDir(resolved.stateDir)\n ensureDir(stateDir, 0o700)\n\n const settings = new SettingsStore(path.join(stateDir, 'settings.json'), resolved.defaultEntryId)\n const service = new HomeHostedService(ctx, {\n home: homeHostedHome(),\n stateDir,\n homeHostedCommand: resolved.homeHostedCommand,\n defaultEntryId: resolved.defaultEntryId,\n settings,\n })\n\n registerRpc(ctx, service)\n registerAgentTools(ctx, service, settings)\n // Read per 401, so the setting takes effect without re-installing the wrapper.\n registerAuthNotice(ctx, () => (settings.get().authNotice ? service.panelLogUrl() : null))\n\n // Re-assert an enabled boot entry shortly after startup: a node or CLI upgrade\n // moves the paths a unit was written with, and the fix is to rewrite it.\n ctx.effect(() => {\n const timer = setTimeout(() => {\n void service.reconcile().catch(() => {\n // the page reads the resulting status; a failed repair is not a startup failure\n })\n }, 5000)\n return () => clearTimeout(timer)\n }, 'dsh-home-hosted: startup reconcile')\n}\n", "/**\n * The Cordis row configuration: operator overrides only. Everything a person\n * changes in the plugin's own page lives in `settings.json` under the plugin\n * state directory, so the two never fight over the same field.\n */\nimport z from '@deepseek-ai/schemastery'\n\nexport interface Config {\n /** Override the plugin state directory (defaults to `$DSH_HOME/dsh-home-hosted`). */\n stateDir?: string\n /** Override the home-hosted executable used in generated boot entries. */\n homeHostedCommand?: string\n /** The entry this plugin manages for the running harness. */\n defaultEntryId: string\n}\n\nexport const Config: z<Config> = z.object({\n stateDir: z.string().description('Plugin state directory; defaults to $DSH_HOME/dsh-home-hosted'),\n homeHostedCommand: z.string().description('home-hosted executable to put in a generated autostart entry'),\n defaultEntryId: z.string().default('dsh').description('Server entry id used for the running harness'),\n})\n", "/**\n * The one wire contract shared by the host half and the browser half.\n *\n * Nothing here may import a Node builtin: the browser bundle includes this\n * module verbatim.\n */\n\n/** Exact Fetch route registered on DeepSeek Harness's authenticated `/api` channel. */\nexport const RPC_PATH = '/home-hosted'\n\n/** Bumped when a payload shape changes; a mismatch is reported, never guessed at. */\nexport const RPC_VERSION = 1\n\nexport interface RpcError {\n code: string\n message: string\n detail?: unknown\n}\n\nexport type Envelope<T> = { ok: true, value: T } | { ok: false, error: RpcError }\n\n/** Endpoints the browser and the agent tools both speak. */\nexport type RpcEndpoint =\n | 'status'\n | 'servers.list'\n | 'servers.get'\n | 'servers.create'\n | 'servers.update'\n | 'servers.delete'\n | 'servers.start'\n | 'servers.stop'\n | 'servers.restart'\n | 'servers.freePort'\n | 'entries.apply'\n | 'entries.remove'\n | 'entries.restore'\n | 'boot.install'\n | 'boot.uninstall'\n | 'boot.verify'\n | 'panel.start'\n | 'panel.takeover'\n | 'cli.installGlobal'\n | 'ui.manage'\n | 'settings.update'\n\n/** A settings write sends only the changed subtree; the host merges group by group. */\nexport interface SettingsPatch {\n autostart?: Partial<PluginSettings['autostart']>\n manageDsh?: boolean\n entries?: PluginSettings['entries']\n panel?: Partial<PluginSettings['panel']>\n authNotice?: boolean\n uiStyle?: UiStyle\n agentTools?: Partial<PluginSettings['agentTools']>\n cli?: Partial<PluginSettings['cli']>\n}\n\nexport interface EndpointPayloads {\n /** `refresh` is accepted and ignored: every status call re-reads live state. */\n 'status': { refresh?: boolean }\n 'servers.list': Record<string, never>\n 'servers.get': { id: string }\n 'servers.create': { entry: ServerEntry }\n 'servers.update': { id: string, patch: ServerEntryPatch }\n 'servers.delete': { id: string }\n 'servers.start': { id: string }\n 'servers.stop': { id: string }\n 'servers.restart': { id: string }\n 'servers.freePort': { id: string }\n 'entries.apply': { intents: EntryIntent[] }\n /** Stop managing an entry: restore what it was, or remove it when we created it. */\n 'entries.remove': { id: string }\n 'entries.restore': { id: string }\n 'boot.install': { mechanism?: BootMechanism }\n 'boot.uninstall': { mechanism?: BootMechanism }\n 'boot.verify': Record<string, never>\n /** Start the preferred CLI as a detached panel; refused while one already answers. */\n 'panel.start': Record<string, never>\n /** Stop the answering panel and start the preferred copy instead. */\n 'panel.takeover': { force?: boolean }\n /** Install the pinned range as a global CLI, so the `global` preference can use it. */\n 'cli.installGlobal': Record<string, never>\n /** Drive the panel's own UI: status, update, revert, or switch to a local build. */\n 'ui.manage': { action: UiAction, file?: string }\n 'settings.update': { patch: SettingsPatch }\n}\n\nexport interface RpcRequest {\n v: number\n endpoint: RpcEndpoint\n payload?: unknown\n}\n\n// ---------------------------------------------------------------------------\n// Server entries\n// ---------------------------------------------------------------------------\n\nexport type OnPortConflict = 'block' | 'warn' | 'follow' | 'reclaim' | 'kill'\n\n/** Every policy home-hosted's config schema accepts; anything else stops it booting. */\nexport const ON_PORT_CONFLICT_POLICIES: readonly OnPortConflict[] = ['block', 'warn', 'follow', 'reclaim', 'kill']\n\nexport function isOnPortConflict(value: unknown): value is OnPortConflict {\n return typeof value === 'string' && (ON_PORT_CONFLICT_POLICIES as readonly string[]).includes(value)\n}\n\n/** Only the fields this plugin reads or writes are typed; the rest is preserved. */\nexport interface ServerEntry {\n id: string\n label?: string\n enabled?: boolean\n autostart?: boolean\n command?: string\n args?: string[]\n cwd?: string\n env?: Record<string, string>\n dataEnvs?: Record<string, string>\n port?: number | null\n bind?: string\n onPortConflict?: OnPortConflict\n stop?: { killPortHolders?: boolean, [key: string]: unknown }\n health?: Record<string, unknown>\n restart?: Record<string, unknown>\n [key: string]: unknown\n}\n\nexport type ServerEntryPatch = Partial<ServerEntry>\n\n/** What the plugin decides about one entry, and the keys it therefore owns. */\nexport interface EntryIntent {\n id: string\n /**\n * Run under home-hosted's nanny, so stopping or restarting the *panel* leaves\n * this process alive. Needs home-hosted 0.6.3.\n */\n persistent: boolean\n autostart: boolean\n onPortConflict: OnPortConflict\n stopKillPortHolders: boolean\n}\n\n/** Keys an intent owns: a patch touches these and nothing else. */\nexport const OWNED_ENTRY_KEYS = ['autostart', 'onPortConflict', 'stop'] as const\n\nexport interface ServerEntryView {\n id: string\n status: string\n pid: number | null\n url: string | null\n config: ServerEntry\n}\n\nexport interface ManagedEntryStatus {\n intent: EntryIntent\n exists: boolean\n /** True once the plugin has adopted the entry and holds a snapshot of what it was. */\n managed: boolean\n /** Owned keys whose live value differs from the intent. */\n drift: string[]\n live: ServerEntryView | null\n snapshot: ServerEntry | null\n}\n\n// ---------------------------------------------------------------------------\n// Panel\n// ---------------------------------------------------------------------------\n\nexport type TokenState = 'enrolled' | 'present' | 'absent' | 'unknown'\n\nexport interface PanelStatus {\n /** `$HHOSTED_HOME` this plugin resolved, whether or not the panel answers. */\n home: string\n reachable: boolean\n /** The port the panel's own config holds (what a restart would use). */\n configPort?: number | null\n url: string | null\n version: string | null\n pid: number | null\n /** How writes are authenticated right now. */\n writeVia: 'api' | 'file' | 'none'\n token: TokenState\n detail: string\n}\n\n/** Which home-hosted CLI the plugin drives, and where it came from. */\nexport type CliSource = 'config' | 'dependency' | 'path' | 'none'\n\n/** One place a CLI could come from, with the version found there. */\nexport interface CliCandidate {\n source: 'config' | 'dependency' | 'path'\n path: string | null\n version: string | null\n}\n\nexport type UiAction = 'status' | 'update' | 'revert' | 'switch'\n\nexport interface UiResult {\n ok: boolean\n detail: string\n /** The active UI, when the action reported or changed one. */\n ui?: { name: string | null, version: string | null, repo?: string | null, tag?: string | null } | null\n output?: string\n}\n\nexport interface PanelControlResult {\n ok: boolean\n detail: string\n url?: string | null\n version?: string | null\n}\n\nexport interface CliStatus {\n /** `config` (operator override), `dependency` (the pinned copy), `path`, or none. */\n source: CliSource\n path: string | null\n version: string | null\n /** The range the plugin ships in its own dependencies. */\n expectedRange: string\n /** False when the resolved CLI is older than the oldest release this plugin supports. */\n supported: boolean\n /** The stable launcher a boot entry runs instead of a moving node_modules path. */\n launcherPath?: string | null\n /** What the launcher answers right now, as the boot entry would invoke it. */\n launcherVersion?: string | null\n /** Which copy the plugin prefers. */\n prefer?: 'pinned' | 'global'\n /** The plugin's own copy, when it resolves. */\n dependency?: CliCandidate | null\n /** The global install on PATH, when there is one. */\n global?: CliCandidate | null\n detail: string\n}\n\n// ---------------------------------------------------------------------------\n// Boot autostart\n// ---------------------------------------------------------------------------\n\nexport type BootMechanism =\n | 'systemd-user'\n | 'systemd-system'\n | 'xdg-autostart'\n | 'launchd-agent'\n | 'launchd-daemon'\n | 'windows-run'\n | 'windows-task'\n | 'container'\n | 'unsupported'\n\nexport type BootState =\n | 'not-installed'\n | 'installed-disabled'\n | 'enabled-running'\n | 'enabled-failing'\n | 'unsupported'\n\nexport interface BootCandidate {\n mechanism: BootMechanism\n available: boolean\n /** Starts before an interactive login. */\n bootCapable: boolean\n /** This process can drive it without an elevation prompt. */\n privileged: boolean\n reason: string\n}\n\nexport interface BootStatus {\n platform: 'linux' | 'darwin' | 'win32' | 'other'\n mechanism: BootMechanism | null\n recommended: BootMechanism | null\n state: BootState\n bootCapable: boolean\n privileged: boolean\n unitPath: string | null\n /** Exact commands a person can run when this process cannot elevate. */\n commands: string[]\n detail: string\n candidates: BootCandidate[]\n}\n\n// ---------------------------------------------------------------------------\n// Plugin settings (UI-managed, persisted outside the Cordis config)\n// ---------------------------------------------------------------------------\n\nexport type AgentToolName =\n | 'status'\n | 'servers_list'\n | 'servers_lifecycle'\n | 'servers_edit'\n | 'autostart_manage'\n | 'ui_manage'\n\nexport const AGENT_TOOL_NAMES: readonly AgentToolName[] = [\n 'status',\n 'servers_list',\n 'servers_lifecycle',\n 'servers_edit',\n 'autostart_manage',\n 'ui_manage',\n]\n\n/**\n * Tools that change something. They ask for approval only when the calling\n * session is not already `danger-full-access`.\n */\nexport const MUTATING_AGENT_TOOLS: readonly AgentToolName[] = [\n 'servers_lifecycle',\n 'servers_edit',\n 'autostart_manage',\n 'ui_manage',\n]\n\n/** The shape this release writes; a file without it was written by 0.1.x. */\nexport const SETTINGS_VERSION = 2\n\nexport type UiStyle = 'detailed' | 'compact'\n\nexport interface PluginSettings {\n version: number\n autostart: {\n enabled: boolean\n /** `auto` picks the best available mechanism; an explicit one is honoured only when available. */\n mechanism: 'auto' | BootMechanism\n /** The last install/uninstall attempt, kept so a failure survives a reload. */\n lastAttempt?: BootAttempt\n }\n /** Manage the running harness as a home-hosted entry. */\n manageDsh: boolean\n entries: EntryIntent[]\n agentTools: {\n enabled: boolean\n allow: AgentToolName[]\n }\n /** Port the panel should listen on; `null` keeps whatever the config holds. */\n panel: {\n port: number | null\n }\n /** Point dsh web's sign-in page at the panel log that holds the tokenised URL. */\n authNotice: boolean\n /** `detailed` shows cards and open disclosures; `compact` folds both away. */\n uiStyle: UiStyle\n cli: {\n /** `pinned` runs the copy this plugin ships; `global` runs the one on PATH. */\n prefer: 'pinned' | 'global'\n }\n}\n\nexport interface BootAttempt {\n ok: boolean\n /** `install` or `uninstall`. */\n action: 'install' | 'uninstall'\n mechanism: BootMechanism | null\n detail: string\n /** The exact commands a person can run when the attempt needed privilege. */\n commands: string[]\n at: number\n}\n\nexport const DEFAULT_SETTINGS: PluginSettings = {\n version: SETTINGS_VERSION,\n autostart: { enabled: false, mechanism: 'auto' },\n manageDsh: false,\n entries: [],\n // Every tool on by default; the session's own permission mode is what gates them.\n agentTools: { enabled: true, allow: [...AGENT_TOOL_NAMES] },\n panel: { port: null },\n authNotice: true,\n uiStyle: 'detailed',\n cli: { prefer: 'pinned' },\n}\n\nexport interface HomeHostedStatus {\n /** The entry id this plugin manages; the page must not assume \"dsh\". */\n defaultEntryId: string\n panel: PanelStatus\n boot: BootStatus\n entries: ManagedEntryStatus[]\n servers: ServerEntryView[]\n settings: PluginSettings\n /** The CLI the plugin drives; absent only from a host older than this field. */\n cli?: CliStatus\n /** Set when the panel could not be reached, so the UI can show a degraded page. */\n lastError: string | null\n}\n", "/**\n * The one implementation behind both surfaces: the browser page and the agent\n * tools call the same endpoints, so they cannot drift apart.\n *\n * Writes prefer the panel API (the store ignores its own writes, so nothing is\n * restarted behind the user's back) and fall back to an atomic config-file write\n * only when the panel is not answering.\n */\nimport { Service, type Context } from '@deepseek-ai/cordis'\nimport fs from 'node:fs'\nimport path from 'node:path'\nimport process from 'node:process'\nimport { fileURLToPath } from 'node:url'\nimport type { BootMechanism, BootStatus, EntryIntent, HomeHostedStatus, ManagedEntryStatus, PanelControlResult, PanelStatus, RpcEndpoint, ServerEntry, ServerEntryPatch, ServerEntryView, UiAction, UiResult } from './shared/contracts.js'\nimport { isOnPortConflict, ON_PORT_CONFLICT_POLICIES } from './shared/contracts.js'\nimport type { BootSpec } from './boot/types.js'\nimport { createBootLadder } from './boot/index.js'\nimport { findEntry, patchControl, patchEntry, readConfig, removeEntry as removeConfigEntry, upsertEntry, writeConfig } from './home-hosted/config-file.js'\nimport { buildDshEntry, detectProfile, resolveDshLaunch } from './home-hosted/dsh-entry.js'\nimport { defaultIntent, ownedDrift, ownedPatch, restorePatch, snapshotOwned } from './home-hosted/entries.js'\nimport { buildHomeHostedBootSpec, homeHostedEnv } from './home-hosted/launch.js'\nimport type { CliResolution } from './home-hosted/resolve.js'\nimport { compareVersions, EXPECTED_RANGE, MIN_KILL_VERSION, MIN_PERSISTENT_VERSION, MIN_SUPPORTED_VERSION, resolveCli } from './home-hosted/resolve.js'\nimport { preflightLauncher, writeLauncher } from './home-hosted/launcher.js'\nimport type { PanelControlDeps } from './home-hosted/panel-control.js'\nimport { installGlobal, spawnTakeover, startPanel as startPanelProcess } from './home-hosted/panel-control.js'\nimport { PanelClient, PanelError, verifyToken } from './home-hosted/panel.js'\nimport { readRuntime, probePanel, pidAlive } from './home-hosted/runtime.js'\nimport { apiTokenEnrolled, ensureToken, readStoredToken } from './home-hosted/token.js'\nimport type { SettingsStore } from './settings.js'\nimport { dshHome } from './util/paths.js'\nimport type { RunResult } from './util/exec.js'\nimport { run } from './util/exec.js'\nimport { readJson, writeJsonAtomic } from './util/fsx.js'\n\nconst ENTRY_ID_PATTERN = /^[a-z0-9][a-z0-9_-]*$/\n\n/** This plugin's own package root, used as a search hint for the pinned CLI. */\nfunction pluginRoot(): string | null {\n try {\n return path.dirname(path.dirname(fileURLToPath(import.meta.url)))\n }\n catch {\n return null\n }\n}\n\n/** What a boot install/uninstall answers with; mirrors the boot module's shape. */\nexport interface BootInstallResult {\n ok: boolean\n changed: boolean\n detail: string\n commands: string[]\n needsPrivilege: boolean\n /** Present on install; an uninstall names no mechanism. */\n mechanism?: BootMechanism | null\n status: BootStatus\n}\n\n/** The subset of the boot ladder this service uses. */\nexport interface BootLadderLike {\n status: (spec: BootSpec, mechanism?: BootMechanism) => Promise<BootStatus>\n install: (spec: BootSpec, mechanism?: BootMechanism) => Promise<BootInstallResult>\n uninstall: (spec: BootSpec, mechanism?: BootMechanism) => Promise<BootInstallResult>\n}\n\nexport class HomeHostedError extends Error {\n constructor(message: string, readonly code: string) {\n super(message)\n this.name = 'HomeHostedError'\n }\n}\n\nexport interface HomeHostedServiceOptions {\n home: string\n stateDir: string\n homeHostedCommand?: string\n defaultEntryId: string\n settings: SettingsStore\n /** Test seam: run the home-hosted CLI without spawning it. */\n execCli?: (args: string[], env: Record<string, string | undefined>) => Promise<RunResult>\n /** Test seam: supply the boot ladder instead of probing the real OS. */\n createLadder?: () => BootLadderLike\n}\n\ninterface CachedClient {\n client: PanelClient\n until: number\n}\n\ninterface LiveEntry {\n view: ServerEntryView\n config: ServerEntry\n}\n\nexport class HomeHostedService extends Service {\n private clientCache: CachedClient | null = null\n private tokenDetail = ''\n private readonly snapshotsFile: string\n\n constructor(ctx: Context, private readonly options: HomeHostedServiceOptions) {\n super(ctx, 'homeHosted')\n this.snapshotsFile = path.join(options.stateDir, 'snapshots.json')\n }\n\n // -------------------------------------------------------------------------\n // Facts\n // -------------------------------------------------------------------------\n\n private runtime() {\n return readRuntime(this.options.home)\n }\n\n /** The entry id this very process was started as, when the panel supervises us. */\n selfEntryId(): string | null {\n const id = process.env.HHOSTED_SERVER_ID\n return id !== undefined && id.length > 0 ? id : null\n }\n\n /** What the config's `meta.writtenBy` names: the panel release when we can read it. */\n private writtenBy(): string {\n return this.runtime()?.version ?? 'dsh-home-hosted'\n }\n\n private webServer(): { port: number | null, host: string } {\n const service = this.ctx.get('webServer') as { port?: unknown, host?: unknown } | undefined\n const port = typeof service?.port === 'number' ? service.port : null\n const host = typeof service?.host === 'string' ? service.host : '127.0.0.1'\n return { port, host }\n }\n\n private cliCache: { prefer: 'pinned' | 'global', resolution: CliResolution, launcher: string | null, launcherVersion: string | null, until: number } | null = null\n\n /**\n * Resolve the preferred CLI, refresh the stable launcher a boot entry runs, and\n * preflight that launcher the same way the entry will invoke it.\n */\n private async cli(): Promise<{ resolution: CliResolution, launcher: string | null, launcherVersion: string | null }> {\n const prefer = this.options.settings.get().cli.prefer\n if (this.cliCache !== null && this.cliCache.until > Date.now() && this.cliCache.prefer === prefer)\n return this.cliCache\n const resolution = await resolveCli({ override: this.options.homeHostedCommand, prefer })\n let launcher: string | null = null\n let launcherVersion: string | null = null\n if (resolution.launch !== null) {\n launcher = writeLauncher({\n stateDir: this.options.stateDir,\n dshHome: dshHome(),\n resolvedEntry: resolution.launch.cliEntry ?? resolution.launch.shimPath ?? null,\n resolvedVersion: resolution.status.version,\n pluginRoot: pluginRoot(),\n minVersion: MIN_SUPPORTED_VERSION,\n }).path\n launcherVersion = await preflightLauncher(this.options.stateDir)\n }\n this.cliCache = { prefer, resolution, launcher, launcherVersion, until: Date.now() + 60_000 }\n return this.cliCache\n }\n\n private async panelControlDeps(): Promise<PanelControlDeps> {\n const { resolution } = await this.cli()\n const launch = resolution.launch\n const projectDir = process.env.HHOSTED_PROJECT ?? this.runtime()?.projectDir ?? null\n return {\n launch,\n home: this.options.home,\n projectDir,\n stateDir: this.options.stateDir,\n env: launch === null ? {} : homeHostedEnv({ home: this.options.home, projectDir }, launch),\n }\n }\n\n private async cliExec(args: string[], env: Record<string, string | undefined>) {\n if (this.options.execCli !== undefined)\n return await this.options.execCli(args, env)\n const { resolution } = await this.cli()\n const launch = resolution.launch\n if (launch === null)\n throw new HomeHostedError(resolution.status.detail, 'CLI_NOT_FOUND')\n return await run(launch.program, [...launch.args, ...args], { env, timeoutMs: 30_000 })\n }\n\n // -------------------------------------------------------------------------\n // Panel\n // -------------------------------------------------------------------------\n\n /** The panel page showing this session's log, where its tokenised URL is. */\n panelLogUrl(): string | null {\n const url = this.runtime()?.url\n if (url === undefined || url.length === 0)\n return null\n return `${url.replace(/\\/+$/, '')}/logs?server=${encodeURIComponent(this.options.defaultEntryId)}`\n }\n\n /** The port the panel's config holds, without touching a running panel. */\n private configuredPort(): number | null {\n const control = readConfig(this.options.home).raw?.control as { port?: unknown } | undefined\n return typeof control?.port === 'number' ? control.port : null\n }\n\n /** Write the chosen panel port into the state the panel boots from. */\n private applyPanelPort(): void {\n const port = this.options.settings.get().panel.port\n if (port === null || port === this.configuredPort())\n return\n const read = readConfig(this.options.home)\n if (read.error !== null)\n throw new HomeHostedError(read.error, 'CONFIG_UNREADABLE')\n writeConfig(this.options.home, patchControl(read.raw ?? {}, { port }), this.writtenBy())\n }\n\n async panelStatus(): Promise<PanelStatus> {\n const runtime = this.runtime()\n const stored = readStoredToken(this.options.stateDir)\n const enrolledOnDisk = apiTokenEnrolled(this.options.home)\n const reachable = runtime !== null && (pidAlive(runtime.pid) || await probePanel(runtime.url))\n const answered = runtime !== null && await probePanel(runtime.url)\n\n const token: PanelStatus['token'] = stored !== null ? 'enrolled' : (enrolledOnDisk ? 'present' : 'absent')\n const writeVia: PanelStatus['writeVia'] = answered && stored !== null ? 'api' : 'file'\n\n return {\n home: this.options.home,\n reachable: answered,\n configPort: this.configuredPort(),\n url: runtime?.url ?? null,\n version: runtime?.version ?? null,\n pid: runtime?.pid ?? null,\n writeVia,\n token,\n detail: answered\n ? (stored !== null\n ? (this.tokenDetail || 'the panel is answering and this plugin holds a token')\n : (enrolledOnDisk\n ? 'the panel is answering, but home-hosted already holds an API token this plugin does not have'\n : 'the panel is answering; a token will be enrolled on the first write'))\n : (runtime === null\n ? 'no run.json: the panel is not running, so entries are written straight to servers.config.json'\n : reachable ? 'the panel process is alive but is not answering' : 'the panel is not running'),\n }\n }\n\n private async tryClient(): Promise<PanelClient | null> {\n if (this.clientCache !== null && this.clientCache.until > Date.now())\n return this.clientCache.client\n const runtime = this.runtime()\n if (runtime === null || !(await probePanel(runtime.url)))\n return null\n\n const ensured = await ensureToken({\n home: this.options.home,\n stateDir: this.options.stateDir,\n exec: (args, env) => this.cliExec(args, env),\n })\n this.tokenDetail = ensured.detail\n if (ensured.token === null)\n return null\n if (!(await verifyToken(runtime.url, ensured.token)))\n return null\n\n const client = new PanelClient({ baseUrl: runtime.url, token: ensured.token })\n this.clientCache = { client, until: Date.now() + 30_000 }\n return client\n }\n\n private async requireClient(): Promise<PanelClient> {\n const client = await this.tryClient()\n if (client === null) {\n const status = await this.panelStatus()\n throw new HomeHostedError(status.detail, 'PANEL_UNAVAILABLE')\n }\n return client\n }\n\n // -------------------------------------------------------------------------\n // Snapshot bookkeeping\n // -------------------------------------------------------------------------\n\n private snapshots(): Record<string, ServerEntry> {\n return readJson<Record<string, ServerEntry>>(this.snapshotsFile) ?? {}\n }\n\n private saveSnapshots(snapshots: Record<string, ServerEntry>): void {\n writeJsonAtomic(this.snapshotsFile, snapshots, 0o600)\n }\n\n // -------------------------------------------------------------------------\n // Entries\n // -------------------------------------------------------------------------\n\n private async liveEntries(): Promise<Map<string, LiveEntry>> {\n const map = new Map<string, LiveEntry>()\n const client = await this.tryClient()\n if (client !== null) {\n try {\n for (const view of await client.listServers())\n map.set(view.id, { view, config: view.config })\n return map\n }\n catch {\n // fall through to the file, which is still the best available truth\n }\n }\n const read = readConfig(this.options.home)\n for (const entry of read.raw?.servers ?? [])\n map.set(entry.id, { view: { id: entry.id, status: 'unknown', pid: null, url: null, config: entry }, config: entry })\n return map\n }\n\n private async createEntry(intent: EntryIntent, patch: ServerEntryPatch, live: ServerEntry | null): Promise<ServerEntry | null> {\n if (intent.id !== this.options.defaultEntryId)\n return null\n const dsh = await resolveDshLaunch()\n const { port, host } = this.webServer()\n const generated = buildDshEntry({\n id: intent.id,\n port,\n host,\n profile: detectProfile(process.argv, process.env),\n dshHome: process.env.DSH_HOME ?? dshHome(),\n launch: dsh,\n })\n return { ...(live ?? generated), ...generated, ...patch }\n }\n\n private async writeOwned(intent: EntryIntent): Promise<void> {\n const live = (await this.liveEntries()).get(intent.id) ?? null\n const snapshots = this.snapshots()\n if (snapshots[intent.id] === undefined) {\n snapshots[intent.id] = live === null ? { id: intent.id } : snapshotOwned(live.config)\n this.saveSnapshots(snapshots)\n }\n\n const patch = ownedPatch(intent, live?.config ?? null, { persistent: await this.supportsPersistent() })\n const client = await this.tryClient()\n if (client !== null) {\n if (live !== null) {\n await client.updateServer(intent.id, patch)\n return\n }\n const entry = await this.createEntry(intent, patch, null)\n if (entry === null) {\n throw new HomeHostedError(\n `no server \"${intent.id}\" exists; create it first, then this plugin can adopt its autostart and conflict policy`,\n 'ENTRY_MISSING',\n )\n }\n await client.createServer(entry)\n return\n }\n\n const read = readConfig(this.options.home)\n if (read.error !== null)\n throw new HomeHostedError(read.error, 'CONFIG_UNREADABLE')\n let raw = read.raw ?? {}\n if (findEntry(raw, intent.id) !== null) {\n writeConfig(this.options.home, patchEntry(raw, intent.id, patch), this.writtenBy())\n return\n }\n\n const entry = await this.createEntry(intent, patch, null)\n if (entry === null)\n throw new HomeHostedError(`no server \"${intent.id}\" exists in ${this.options.home}/servers.config.json`, 'ENTRY_MISSING')\n\n // While a panel is running, an external write is a real change and a newly\n // added autostart entry would be started at once. Adding it disabled and\n // flipping autostart in a second write makes that a changed definition\n // instead, which only takes effect at that entry's next start.\n if (await this.panelRunning()) {\n writeConfig(this.options.home, upsertEntry(raw, { ...entry, autostart: false }), this.writtenBy())\n raw = readConfig(this.options.home).raw ?? raw\n writeConfig(this.options.home, patchEntry(raw, intent.id, { autostart: intent.autostart }), this.writtenBy())\n return\n }\n\n writeConfig(this.options.home, upsertEntry(raw, entry), this.writtenBy())\n }\n\n private async panelRunning(): Promise<boolean> {\n const runtime = this.runtime()\n return runtime !== null && (pidAlive(runtime.pid) || await probePanel(runtime.url))\n }\n\n /**\n * The version whose schema will parse what we write: the answering panel, or\n * the CLI that will parse it next. `kill` did not exist before 0.6.0, and an\n * older panel refuses to *boot* with it \u2014 so this is checked before any write.\n */\n private async configVersion(): Promise<string | null> {\n const runtime = this.runtime()\n if (runtime !== null && runtime.version !== null && (pidAlive(runtime.pid) || await probePanel(runtime.url)))\n return runtime.version\n const { resolution } = await this.cli()\n return resolution.status.version\n }\n\n /** Whether the panel whose schema parses our write knows `persistent`. */\n private async supportsPersistent(): Promise<boolean> {\n const version = await this.configVersion()\n return version !== null && compareVersions(version, MIN_PERSISTENT_VERSION) >= 0\n }\n\n private async assertPolicySupported(intent: EntryIntent): Promise<void> {\n if (intent.onPortConflict !== 'kill')\n return\n const version = await this.configVersion()\n if (version === null || compareVersions(version, MIN_KILL_VERSION) >= 0)\n return\n const { resolution } = await this.cli()\n throw new HomeHostedError(\n `the home-hosted that would parse this config is ${version}, which has no \"kill\" policy `\n + `(added in ${MIN_KILL_VERSION}); replace it with ${resolution.status.version ?? 'the pinned copy'} from this page, `\n + 'or set the entry\\'s on-port-conflict policy to block',\n 'KILL_UNSUPPORTED',\n )\n }\n\n private async applyIntents(intents: EntryIntent[]): Promise<ManagedEntryStatus[]> {\n for (const raw of intents) {\n if (!ENTRY_ID_PATTERN.test(raw.id))\n throw new HomeHostedError(`\"${raw.id}\" is not a valid server id`, 'INVALID_ID')\n const requested: unknown = raw.onPortConflict\n if (requested !== undefined && requested !== null && !isOnPortConflict(requested))\n throw new HomeHostedError(\n `\"${String(requested)}\" is not a port-conflict policy; use one of ${ON_PORT_CONFLICT_POLICIES.join(', ')}`,\n 'INVALID_POLICY',\n )\n const fallback = defaultIntent(raw.id)\n const intent: EntryIntent = {\n id: raw.id,\n autostart: raw.autostart === true,\n onPortConflict: isOnPortConflict(requested) ? requested : fallback.onPortConflict,\n stopKillPortHolders: raw.stopKillPortHolders ?? fallback.stopKillPortHolders,\n persistent: raw.persistent ?? fallback.persistent,\n }\n await this.assertPolicySupported(intent)\n await this.writeOwned(intent)\n const current = this.options.settings.get()\n const entries = current.entries.filter(entry => entry.id !== intent.id)\n entries.push(intent)\n this.options.settings.update({\n // The page's toggle reads this flag, so managing the harness has to record\n // itself; restoring or removing that entry clears it again.\n ...(intent.id === this.options.defaultEntryId ? { manageDsh: true } : {}),\n entries,\n })\n }\n return await this.entriesStatus()\n }\n\n /**\n * Stop managing an entry: restore what it was when we only adopted it, or\n * remove it when this plugin created it. Removing an entry the panel\n * supervises stops that process \u2014 which may be this session.\n */\n private async removeManagedEntry(id: string): Promise<ManagedEntryStatus[]> {\n const snapshots = this.snapshots()\n const snapshot = snapshots[id]\n const adopted = snapshot !== undefined && Object.keys(snapshot).some(key => key !== 'id')\n if (adopted)\n return await this.restoreEntry(id)\n\n // Deleting this entry stops the process running this session, and nothing\n // would start it again \u2014 so \"stop managing\" pauses it instead: the entry\n // stays, it is simply no longer started for us.\n if (id === this.selfEntryId())\n return await this.pauseManagedEntry(id)\n\n const client = await this.tryClient()\n if (client !== null) {\n try {\n await client.deleteServer(id)\n }\n catch (error) {\n // Already gone is the outcome we wanted.\n const missing = error instanceof PanelError && (error.status === 404 || error.code === 'UNKNOWN_SERVER')\n if (!missing)\n throw error\n }\n }\n else {\n const read = readConfig(this.options.home)\n if (read.error !== null || read.raw === null)\n throw new HomeHostedError(read.error ?? 'the config file is unreadable', 'CONFIG_UNREADABLE')\n writeConfig(this.options.home, removeConfigEntry(read.raw, id), this.writtenBy())\n }\n delete snapshots[id]\n this.saveSnapshots(snapshots)\n const current = this.options.settings.get()\n this.options.settings.update({\n // Only the harness entry drives the page's manage toggle.\n ...(id === this.options.defaultEntryId ? { manageDsh: false } : {}),\n entries: current.entries.filter(entry => entry.id !== id),\n })\n return await this.entriesStatus()\n }\n\n /** Turn off the autostart intent for one entry, keeping the entry itself. */\n private async pauseManagedEntry(id: string): Promise<ManagedEntryStatus[]> {\n const intent = this.options.settings.intentFor(id)\n await this.applyIntents([{ ...intent, autostart: false }])\n const current = this.options.settings.get()\n this.options.settings.update({\n ...(id === this.options.defaultEntryId ? { manageDsh: false } : {}),\n entries: current.entries,\n })\n return await this.entriesStatus()\n }\n\n /** Drive the panel's own UI through its CLI, and report what is installed. */\n async uiManage(action: UiAction, file?: string): Promise<UiResult> {\n const cli = action === 'status' ? null : await this.cli()\n\n const runUi = async (args: string[]): Promise<{ code: number | null, output: string }> => {\n const launch = cli?.resolution.launch ?? null\n if (launch === null)\n throw new HomeHostedError(cli?.resolution.status.detail ?? 'no home-hosted CLI could be resolved', 'CLI_NOT_FOUND')\n const result = await run(launch.program, [...launch.args, ...args, '--home', this.options.home], {\n env: { ...process.env, HHOSTED_HOME: this.options.home },\n timeoutMs: 300_000,\n })\n // A CLI that never started has no stdout to show, so its spawn error is the\n // only thing that explains the failure.\n const output = [result.error, result.stdout, result.stderr].filter(part => typeof part === 'string' && part.trim().length > 0).join('\\n').trim()\n return { code: result.code, output }\n }\n\n interface ActiveUi { name: string | null, version: string | null, repo: string | null, tag: string | null }\n const active = (): ActiveUi | null => {\n const meta = readJson<{ name?: string, version?: string | null, repo?: string, tag?: string }>(path.join(this.options.home, '.ui', 'ui.json'))\n return meta === null ? null : { name: meta.name ?? null, version: meta.version ?? null, repo: meta.repo ?? null, tag: meta.tag ?? null }\n }\n\n switch (action) {\n case 'status': {\n const ui = active()\n return { ok: true, ui, detail: ui === null ? 'the panel is using its stock UI' : `${ui.name ?? 'a custom UI'}${ui.version === null ? '' : ` ${ui.version}`}` }\n }\n case 'update': {\n const result = await runUi(['ui-update', '--yes'])\n return { ok: result.code === 0, detail: result.code === 0 ? 'the panel UI is up to date' : 'the update did not run', ui: active(), output: result.output }\n }\n case 'revert': {\n const result = await runUi(['ui-revert'])\n return { ok: result.code === 0, detail: result.code === 0 ? 'back to the stock UI' : 'the revert did not run', ui: active(), output: result.output }\n }\n case 'switch': {\n if (file === undefined || file.trim().length === 0)\n throw new HomeHostedError('switching the UI needs the zip to install', 'UI_FILE_REQUIRED')\n if (!fs.existsSync(file))\n throw new HomeHostedError(`no file at ${file}`, 'UI_FILE_MISSING')\n const result = await runUi(['ui-switch', '--file', file, '--yes'])\n return { ok: result.code === 0, detail: result.code === 0 ? 'the UI was replaced' : 'the switch did not run', ui: active(), output: result.output }\n }\n default:\n throw new HomeHostedError(`unknown ui action \"${String(action)}\"`, 'UNKNOWN_UI_ACTION')\n }\n }\n\n private async restoreEntry(id: string): Promise<ManagedEntryStatus[]> {\n const live = (await this.liveEntries()).get(id) ?? null\n if (live === null)\n throw new HomeHostedError(`no server \"${id}\" exists`, 'ENTRY_MISSING')\n const snapshots = this.snapshots()\n // A restore without a snapshot would write schema defaults over the person's\n // own autostart and conflict policy, silently and irreversibly.\n if (snapshots[id] === undefined)\n throw new HomeHostedError(`\"${id}\" was never adopted by this plugin, so there is nothing to restore; adopt it first`, 'NOT_ADOPTED')\n const patch = restorePatch(live.config, snapshots[id] ?? null)\n const client = await this.tryClient()\n if (client !== null)\n await client.updateServer(id, patch)\n else {\n const read = readConfig(this.options.home)\n if (read.error !== null || read.raw === null)\n throw new HomeHostedError(read.error ?? 'the config file is unreadable', 'CONFIG_UNREADABLE')\n writeConfig(this.options.home, patchEntry(read.raw, id, patch), this.writtenBy())\n }\n delete snapshots[id]\n this.saveSnapshots(snapshots)\n const current = this.options.settings.get()\n this.options.settings.update({\n ...(id === this.options.defaultEntryId ? { manageDsh: false } : {}),\n entries: current.entries.filter(entry => entry.id !== id),\n })\n return await this.entriesStatus()\n }\n\n async entriesStatus(): Promise<ManagedEntryStatus[]> {\n const settings = this.options.settings.get()\n const live = await this.liveEntries()\n const snapshots = this.snapshots()\n const persistent = await this.supportsPersistent()\n const ids = new Set<string>([this.options.defaultEntryId, ...settings.entries.map(entry => entry.id)])\n return [...ids].map((id) => {\n const intent = this.options.settings.intentFor(id)\n const entry = live.get(id) ?? null\n return {\n intent,\n exists: entry !== null,\n managed: snapshots[id] !== undefined,\n drift: entry === null ? ['missing entry'] : ownedDrift(entry.config, intent, { persistent }),\n live: entry?.view ?? null,\n snapshot: snapshots[id] ?? null,\n }\n })\n }\n\n // -------------------------------------------------------------------------\n // Boot autostart\n // -------------------------------------------------------------------------\n\n private ladder(): BootLadderLike {\n if (this.options.createLadder !== undefined)\n return this.options.createLadder()\n return createBootLadder({ env: process.env })\n }\n\n private async bootSpec(): Promise<BootSpec | null> {\n const { resolution, launcher } = await this.cli()\n const launch = resolution.launch\n if (launch === null)\n return null\n const runtime = this.runtime()\n const spec = buildHomeHostedBootSpec(\n {\n home: this.options.home,\n projectDir: process.env.HHOSTED_PROJECT ?? runtime?.projectDir ?? null,\n version: runtime?.version ?? null,\n },\n launch,\n { stateDir: this.options.stateDir },\n )\n\n // The entry runs the stable launcher, not the pinned node_modules path: that\n // path carries a version and a peer hash, and moves on the next install.\n if (launcher !== null) {\n const cliArgs = spec.args.slice(launch.args.length)\n if (process.platform === 'win32') {\n spec.command = process.execPath\n spec.args = [launcher, ...cliArgs]\n }\n else {\n spec.command = launcher\n spec.args = cliArgs\n }\n }\n return spec\n }\n\n async bootStatus(mechanism?: BootMechanism): Promise<BootStatus> {\n const platform: BootStatus['platform'] = process.platform === 'linux'\n ? 'linux'\n : process.platform === 'darwin' ? 'darwin' : process.platform === 'win32' ? 'win32' : 'other'\n const spec = await this.bootSpec()\n if (spec === null) {\n return {\n platform,\n mechanism: null,\n recommended: null,\n state: 'unsupported',\n bootCapable: false,\n privileged: false,\n unitPath: null,\n commands: [],\n detail: 'no home-hosted CLI is available, so no boot entry can be generated; install the plugin with its dependencies',\n candidates: [],\n }\n }\n const settings = this.options.settings.get()\n const requested = mechanism ?? (settings.autostart.mechanism === 'auto' ? undefined : settings.autostart.mechanism)\n return await this.ladder().status(spec, requested)\n }\n\n async installBoot(mechanism?: BootMechanism): Promise<{ result: BootInstallResult, status: BootStatus }> {\n const spec = await this.bootSpec()\n if (spec === null)\n throw new HomeHostedError((await this.cli()).resolution.status.detail, 'CLI_NOT_FOUND')\n const result = await this.ladder().install(spec, mechanism)\n const current = this.options.settings.get().autostart\n this.options.settings.update({\n autostart: {\n // The preference follows the outcome for a real install, and the last\n // attempt is recorded either way so a failure is visible after a reload.\n enabled: result.ok ? true : current.enabled,\n mechanism: result.ok\n ? (mechanism ?? result.mechanism ?? current.mechanism)\n : current.mechanism,\n lastAttempt: {\n ok: result.ok,\n action: 'install',\n mechanism: result.mechanism ?? mechanism ?? null,\n detail: result.detail,\n commands: result.commands,\n at: Date.now(),\n },\n },\n })\n return { result, status: await this.bootStatus(mechanism) }\n }\n\n async uninstallBoot(mechanism?: BootMechanism): Promise<{ result: BootInstallResult, status: BootStatus }> {\n const spec = await this.bootSpec()\n if (spec === null)\n throw new HomeHostedError((await this.cli()).resolution.status.detail, 'CLI_NOT_FOUND')\n const result = await this.ladder().uninstall(spec, mechanism)\n const current = this.options.settings.get().autostart\n this.options.settings.update({\n autostart: {\n ...current,\n enabled: result.ok ? false : current.enabled,\n lastAttempt: {\n ok: result.ok,\n action: 'uninstall',\n mechanism: result.mechanism ?? mechanism ?? null,\n detail: result.detail,\n commands: result.commands,\n at: Date.now(),\n },\n },\n })\n return { result, status: await this.bootStatus(mechanism) }\n }\n\n // -------------------------------------------------------------------------\n // Panel lifecycle\n // -------------------------------------------------------------------------\n\n /** Out-of-the-box start: run the preferred CLI's `up`, which detaches itself. */\n async startPanelNow(): Promise<PanelControlResult> {\n const { resolution } = await this.cli()\n const deps = await this.panelControlDeps()\n if (deps.launch === null)\n throw new HomeHostedError(resolution.status.detail, 'CLI_NOT_FOUND')\n const runtime = this.runtime()\n if (runtime !== null && await probePanel(runtime.url)) {\n return { ok: true, detail: 'a panel is already answering', url: runtime.url, version: runtime.version }\n }\n this.applyPanelPort()\n const result = await startPanelProcess(deps)\n this.clientCache = null\n return result\n }\n\n /**\n * Replace an answering panel with the preferred copy.\n *\n * That stops the servers the old panel supervises \u2014 this process included \u2014 so\n * the work is handed to a detached helper and the guard demands that this\n * session is an adopted, autostarting entry the new panel will bring back.\n */\n async takeoverPanel(force = false): Promise<PanelControlResult> {\n const { resolution } = await this.cli()\n const deps = await this.panelControlDeps()\n if (deps.launch === null)\n throw new HomeHostedError(resolution.status.detail, 'CLI_NOT_FOUND')\n\n const runtime = this.runtime()\n if (runtime === null || !(await probePanel(runtime.url)))\n return await this.startPanelNow()\n\n if (runtime.version !== null && resolution.status.version !== null && runtime.version === resolution.status.version) {\n return { ok: true, detail: `the answering panel is already ${runtime.version}`, url: runtime.url, version: runtime.version }\n }\n\n if (!force) {\n const id = this.selfEntryId()\n const live = id === null ? null : (await this.liveEntries()).get(id) ?? null\n if (id === null || live === null || live.config.autostart !== true) {\n throw new HomeHostedError(\n 'replacing the panel stops every server it supervises, including this session, and nothing would start it again: '\n + 'adopt this entry with autostart first, or pass force',\n 'TAKEOVER_UNSAFE',\n )\n }\n }\n\n return spawnTakeover(deps, runtime.pid)\n }\n\n /** Install the pinned range globally, so the `global` preference has a copy to run. */\n async installGlobalCli(): Promise<PanelControlResult & { output?: string }> {\n const result = await installGlobal(EXPECTED_RANGE)\n this.cliCache = null\n return { ok: result.ok, detail: result.detail, output: result.output }\n }\n\n /** Re-assert an entry that is already installed: a node or CLI upgrade moves the\n * paths a unit was written with, and the fix is to rewrite it.\n *\n * Never installs one that is not there. Installing is a deliberate act \u2014 it can\n * need root and it makes this machine start something at boot \u2014 so it happens on\n * an explicit click or an approved tool call, not as a side effect of startup.\n */\n async reconcile(): Promise<void> {\n if (!this.options.settings.get().autostart.enabled)\n return\n const status = await this.bootStatus()\n if (status.state !== 'enabled-failing' && status.state !== 'installed-disabled')\n return\n // Belt on top of the probe: a file-backed entry is only repaired when the file\n // is actually there, so a reporting slip can never turn startup into an install.\n const fileBacked = status.mechanism === 'systemd-user'\n || status.mechanism === 'systemd-system'\n || status.mechanism === 'xdg-autostart'\n || status.mechanism === 'launchd-agent'\n || status.mechanism === 'launchd-daemon'\n if (fileBacked && (status.unitPath === null || !fs.existsSync(status.unitPath)))\n return\n try {\n await this.installBoot()\n }\n catch {\n // a failed repair is reported by the status the page reads\n }\n }\n\n // -------------------------------------------------------------------------\n // Status\n // -------------------------------------------------------------------------\n\n async status(): Promise<HomeHostedStatus> {\n // Resolve the client first: enrolling a token changes which write path is\n // available, and the page should see the state after that, not before.\n const client = await this.tryClient()\n const panel = await this.panelStatus()\n const { resolution, launcher, launcherVersion } = await this.cli()\n const cliDetail = resolution.status.detail\n const panelVersion = this.runtime()?.version ?? null\n const cli = {\n ...resolution.status,\n launcherPath: launcher,\n launcherVersion,\n // A panel left running from an older install is the usual reason to see\n // two versions on this page; say so instead of leaving it ambiguous.\n detail: panelVersion !== null && resolution.status.version !== null && panelVersion !== resolution.status.version\n ? `${cliDetail}; the running panel is ${panelVersion}`\n : cliDetail,\n }\n let servers: ServerEntryView[] = []\n let lastError: string | null = null\n if (client !== null) {\n try {\n servers = await client.listServers()\n }\n catch (error) {\n lastError = error instanceof Error ? error.message : String(error)\n }\n }\n else if (panel.reachable) {\n lastError = panel.detail\n }\n\n return {\n defaultEntryId: this.options.defaultEntryId,\n panel,\n boot: await this.bootStatus(),\n entries: await this.entriesStatus(),\n servers,\n settings: this.options.settings.get(),\n cli,\n lastError,\n }\n }\n\n // -------------------------------------------------------------------------\n // Endpoint dispatch\n // -------------------------------------------------------------------------\n\n async call(endpoint: RpcEndpoint, payload: unknown): Promise<unknown> {\n const input = (payload ?? {}) as Record<string, unknown>\n switch (endpoint) {\n case 'status':\n return await this.status()\n\n case 'settings.update': {\n const patch = (input.patch ?? {}) as Parameters<SettingsStore['update']>[0]\n this.options.settings.update(patch)\n return await this.status()\n }\n\n case 'servers.list':\n return await (await this.requireClient()).listServers()\n\n case 'servers.get':\n return await (await this.requireClient()).getServer(String(input.id))\n\n case 'servers.create': {\n const entry = input.entry as ServerEntry\n if (typeof entry?.id !== 'string' || !ENTRY_ID_PATTERN.test(entry.id))\n throw new HomeHostedError('a server entry needs an id matching ^[a-z0-9][a-z0-9_-]*$', 'INVALID_ID')\n return await (await this.requireClient()).createServer(entry)\n }\n\n case 'servers.update':\n return await (await this.requireClient()).updateServer(String(input.id), (input.patch ?? {}) as ServerEntryPatch)\n\n case 'servers.delete': {\n const id = String(input.id)\n if (id === this.selfEntryId()) {\n throw new HomeHostedError(\n `\"${id}\" is the entry this very process runs as, and deleting it stops this session; `\n + 'pause it (autostart off) or restore it instead',\n 'SELF_ENTRY',\n )\n }\n await (await this.requireClient()).deleteServer(id)\n return { id }\n }\n\n case 'servers.start':\n await (await this.requireClient()).startServer(String(input.id))\n return await this.entriesStatus()\n\n case 'servers.stop':\n await (await this.requireClient()).stopServer(String(input.id))\n return await this.entriesStatus()\n\n case 'servers.restart':\n await (await this.requireClient()).restartServer(String(input.id))\n return await this.entriesStatus()\n\n case 'servers.freePort':\n return await (await this.requireClient()).freePort(String(input.id))\n\n case 'entries.apply': {\n const intents = Array.isArray(input.intents) ? input.intents as EntryIntent[] : []\n return await this.applyIntents(intents)\n }\n\n case 'entries.remove':\n return await this.removeManagedEntry(String(input.id))\n\n case 'entries.restore':\n return await this.restoreEntry(String(input.id))\n\n case 'ui.manage':\n return await this.uiManage(input.action as UiAction, typeof input.file === 'string' ? input.file : undefined)\n\n case 'boot.install':\n return await this.installBoot(input.mechanism as BootMechanism | undefined)\n\n case 'boot.uninstall':\n return await this.uninstallBoot(input.mechanism as BootMechanism | undefined)\n\n case 'boot.verify':\n return await this.bootStatus()\n\n case 'panel.start':\n return await this.startPanelNow()\n\n case 'panel.takeover':\n return await this.takeoverPanel(input.force === true)\n\n case 'cli.installGlobal':\n return await this.installGlobalCli()\n\n default:\n throw new HomeHostedError(`unknown endpoint \"${String(endpoint)}\"`, 'UNKNOWN_ENDPOINT')\n }\n }\n}\n\ndeclare module '@deepseek-ai/cordis' {\n interface Context {\n homeHosted: HomeHostedService\n }\n}\n", "/**\n * The boot ladder: which mechanisms exist on this platform, which one is\n * installed, and which one this process should use. Everything platform\n * specific is inside a provider's `detect()`/`status()`/`install()` \u2014 this file\n * only orders them and never runs at import time.\n */\nimport os from 'node:os'\nimport process from 'node:process'\nimport type { BootCandidate, BootMechanism, BootStatus } from '../shared/contracts.js'\nimport { run as execRun, sudoAvailable } from '../util/exec.js'\nimport type {\n BootActionResult,\n BootLadder,\n BootLadderOptions,\n BootProvider,\n BootProviderContext,\n BootProviderStatus,\n BootSpec,\n} from './types.js'\nimport { errorMessage, failed, isInstalledState } from './common.js'\nimport { createSystemdSystemProvider, createSystemdUserProvider } from './systemd.js'\nimport { createLaunchdAgentProvider, createLaunchdDaemonProvider } from './launchd.js'\nimport { createXdgAutostartProvider } from './xdg.js'\nimport { createWindowsRunProvider, createWindowsTaskProvider } from './windows.js'\nimport { createContainerProvider, createUnsupportedProvider } from './fallback.js'\n\nfunction platformKind(platform: NodeJS.Platform): BootStatus['platform'] {\n if (platform === 'linux' || platform === 'darwin' || platform === 'win32')\n return platform\n return 'other'\n}\n\n/** Ordered by preference within a platform; the terminal providers come last. */\nexport function bootProviders(\n ctx: BootProviderContext,\n platform: NodeJS.Platform = ctx.platform,\n): BootProvider[] {\n const container = createContainerProvider(ctx)\n const unsupported = createUnsupportedProvider(platform)\n switch (platform) {\n case 'linux':\n return [createSystemdUserProvider(ctx), createSystemdSystemProvider(ctx), createXdgAutostartProvider(ctx), container, unsupported]\n case 'darwin':\n return [createLaunchdAgentProvider(ctx), createLaunchdDaemonProvider(ctx), unsupported]\n case 'win32':\n return [createWindowsRunProvider(ctx), createWindowsTaskProvider(ctx), unsupported]\n default:\n return [container, unsupported]\n }\n}\n\nexport function createBootLadder(options: BootLadderOptions = {}): BootLadder {\n const platform = options.platform ?? process.platform\n const isRoot = process.getuid?.() === 0\n const ctx: BootProviderContext = {\n platform,\n home: options.home ?? os.homedir(),\n env: options.env ?? process.env,\n run: options.run ?? execRun,\n sudo: options.sudo ?? (async () => (isRoot ? true : await sudoAvailable())),\n isRoot,\n exists: options.exists,\n }\n const providers = bootProviders(ctx, platform)\n const kind = platformKind(platform)\n\n async function detectAll(): Promise<{ platform: BootStatus['platform'], candidates: BootCandidate[] }> {\n const candidates = await Promise.all(providers.map(async (provider) => {\n try {\n return await provider.detect()\n }\n catch (error) {\n return {\n mechanism: provider.mechanism,\n available: false,\n bootCapable: false,\n privileged: false,\n reason: `detection failed: ${errorMessage(error)}`,\n } satisfies BootCandidate\n }\n }))\n return { platform: kind, candidates }\n }\n\n async function safeStatus(provider: BootProvider, spec: BootSpec): Promise<BootProviderStatus> {\n try {\n return await provider.status(spec)\n }\n catch (error) {\n return { state: 'not-installed', unitPath: null, detail: errorMessage(error), commands: [] }\n }\n }\n\n function recommend(candidates: BootCandidate[]): BootMechanism | null {\n const byMechanism = new Map(candidates.map(candidate => [candidate.mechanism, candidate]))\n const available = providers\n .map(provider => provider.mechanism)\n .filter(mechanism => byMechanism.get(mechanism)?.available === true)\n const usable = (mechanism: string): boolean => mechanism !== 'container' && mechanism !== 'unsupported'\n // Inside a container no OS entry starts anything, so the honest advice is the\n // restart policy \u2014 ahead of anything else that merely looks available.\n if (available.includes('container'))\n return 'container'\n // A boot-capable mechanism that needs a password prompt is offered, but it is\n // not the *recommendation*: automatic should mean zero manual steps.\n const readyBoot = available.find(mechanism => usable(mechanism)\n && byMechanism.get(mechanism)?.bootCapable === true\n && byMechanism.get(mechanism)?.privileged === true)\n if (readyBoot)\n return readyBoot\n const ready = available.find(mechanism => usable(mechanism) && byMechanism.get(mechanism)?.privileged === true)\n if (ready)\n return ready\n const bootCapable = available.find(mechanism => usable(mechanism) && byMechanism.get(mechanism)?.bootCapable === true)\n if (bootCapable)\n return bootCapable\n return available.find(mechanism => mechanism !== 'unsupported')\n ?? available[0]\n ?? null\n }\n\n async function buildStatus(spec: BootSpec, mechanism?: BootMechanism): Promise<BootStatus> {\n const { candidates } = await detectAll()\n const byMechanism = new Map(candidates.map(candidate => [candidate.mechanism, candidate]))\n const statuses = new Map<BootMechanism, BootProviderStatus>()\n for (const [provider, status] of await Promise.all(providers.map(async provider => [provider, await safeStatus(provider, spec)] as const)))\n statuses.set(provider.mechanism, status)\n\n const explicit = mechanism ? providers.find(provider => provider.mechanism === mechanism) : undefined\n const installedProvider = providers.find((provider) => {\n const status = statuses.get(provider.mechanism)\n return status !== undefined && isInstalledState(status.state)\n })\n const recommended = recommend(candidates)\n const target = explicit\n ?? installedProvider\n ?? (recommended ? providers.find(provider => provider.mechanism === recommended) : undefined)\n\n const explicitStatus = explicit ? statuses.get(explicit.mechanism) : undefined\n const installedMechanism = explicit && explicitStatus && isInstalledState(explicitStatus.state)\n ? explicit.mechanism\n : installedProvider?.mechanism ?? null\n\n const common = { platform: kind, mechanism: installedMechanism, recommended, candidates }\n if (!target) {\n return {\n ...common,\n state: 'unsupported',\n bootCapable: false,\n privileged: false,\n unitPath: null,\n commands: [],\n detail: `no boot mechanism is available on ${platform}`,\n }\n }\n\n const status = statuses.get(target.mechanism)\n const candidate = byMechanism.get(target.mechanism)\n const alsoInstalled = providers\n .filter(provider => provider.mechanism !== target.mechanism && isInstalledState(statuses.get(provider.mechanism)?.state ?? 'unsupported'))\n .map(provider => provider.mechanism)\n return {\n ...common,\n state: status?.state ?? 'unsupported',\n bootCapable: candidate?.bootCapable ?? false,\n privileged: candidate?.privileged ?? false,\n unitPath: status?.unitPath ?? null,\n commands: status?.commands ?? [],\n detail: `${status?.detail ?? 'no detail'}${alsoInstalled.length ? `; also installed: ${alsoInstalled.join(', ')}` : ''}`,\n }\n }\n\n async function safeInstall(provider: BootProvider, spec: BootSpec): Promise<BootActionResult> {\n try {\n return await provider.install(spec)\n }\n catch (error) {\n return failed(errorMessage(error))\n }\n }\n\n async function safeUninstall(provider: BootProvider, spec: BootSpec): Promise<BootActionResult> {\n try {\n return await provider.uninstall(spec)\n }\n catch (error) {\n return failed(errorMessage(error))\n }\n }\n\n return {\n providers,\n\n detect: detectAll,\n\n status: buildStatus,\n\n async install(spec: BootSpec, mechanism?: BootMechanism) {\n const before = await buildStatus(spec, mechanism)\n const chosen = mechanism ?? before.mechanism ?? before.recommended\n const target = chosen ? providers.find(provider => provider.mechanism === chosen) : undefined\n if (!target) {\n return {\n ...failed(`no boot mechanism is available on ${platform}`),\n mechanism: null,\n status: before,\n }\n }\n const result = await safeInstall(target, spec)\n const status = await buildStatus(spec, mechanism)\n return {\n ...result,\n mechanism: result.ok ? target.mechanism : status.mechanism,\n status,\n }\n },\n\n async uninstall(spec: BootSpec, mechanism?: BootMechanism) {\n const before = await buildStatus(spec, mechanism)\n const chosen = mechanism ?? before.mechanism\n const target = chosen ? providers.find(provider => provider.mechanism === chosen) : undefined\n if (!target) {\n return {\n ok: true,\n changed: false,\n detail: 'no OS boot entry is installed for this plugin, so there is nothing to uninstall',\n commands: [],\n needsPrivilege: false,\n status: before,\n }\n }\n const result = await safeUninstall(target, spec)\n const status = await buildStatus(spec, mechanism)\n return { ...result, status }\n },\n }\n}\n", "/**\n * The only place this plugin starts a process.\n *\n * Every call is an argv array with no shell, so a path or a value can never\n * become a command. Callers pass absolute programs; nothing here resolves\n * through a shell profile.\n */\nimport { spawn } from 'node:child_process'\n\nexport interface RunOptions {\n cwd?: string\n env?: Record<string, string | undefined>\n timeoutMs?: number\n /** Cap on each captured stream; a chatty command is truncated, not buffered forever. */\n maxBytes?: number\n}\n\nexport interface RunResult {\n command: string\n args: string[]\n code: number | null\n signal: NodeJS.Signals | null\n stdout: string\n stderr: string\n timedOut: boolean\n error: string | null\n}\n\n/** Run a program and always resolve; a non-zero code is data, not a throw. */\nexport async function run(command: string, args: string[] = [], options: RunOptions = {}): Promise<RunResult> {\n const maxBytes = options.maxBytes ?? 256 * 1024\n const timeoutMs = options.timeoutMs ?? 20_000\n\n return await new Promise<RunResult>((resolve) => {\n let settled = false\n let stdout = ''\n let stderr = ''\n let timedOut = false\n\n const finish = (result: Partial<RunResult>): void => {\n if (settled)\n return\n settled = true\n resolve({\n command,\n args,\n code: result.code ?? null,\n signal: result.signal ?? null,\n stdout: result.stdout ?? stdout,\n stderr: result.stderr ?? stderr,\n timedOut,\n error: result.error ?? null,\n })\n }\n\n let child\n try {\n child = spawn(command, args, {\n cwd: options.cwd,\n env: { ...process.env, ...options.env },\n shell: false,\n windowsHide: true,\n stdio: ['ignore', 'pipe', 'pipe'],\n })\n }\n catch (error) {\n finish({ error: error instanceof Error ? error.message : String(error) })\n return\n }\n\n const timer = setTimeout(() => {\n timedOut = true\n child.kill('SIGKILL')\n }, timeoutMs)\n\n child.stdout?.on('data', (chunk: Buffer) => {\n if (stdout.length < maxBytes)\n stdout += chunk.toString('utf8').slice(0, maxBytes - stdout.length)\n })\n child.stderr?.on('data', (chunk: Buffer) => {\n if (stderr.length < maxBytes)\n stderr += chunk.toString('utf8').slice(0, maxBytes - stderr.length)\n })\n\n child.on('error', (error) => {\n clearTimeout(timer)\n finish({ error: error.message })\n })\n child.on('close', (code, signal) => {\n clearTimeout(timer)\n finish({ code, signal })\n })\n })\n}\n\n/** Run a program and fail loudly on anything but success. */\nexport async function runOk(command: string, args: string[] = [], options: RunOptions = {}): Promise<RunResult> {\n const result = await run(command, args, options)\n if (result.error !== null)\n throw new Error(`${command} failed: ${result.error}`)\n if (result.code !== 0)\n throw new Error(`${command} exited ${String(result.code)}: ${result.stderr.trim() || result.stdout.trim()}`)\n return result\n}\n\n/** True when the program exists and answers to `--version` or similar. */\nexport async function hasCommand(command: string): Promise<boolean> {\n const probe = process.platform === 'win32' ? 'where.exe' : 'which'\n const result = await run(probe, [command], { timeoutMs: 5000 })\n return result.code === 0\n}\n\n/**\n * Whether this process can run one privileged command with no prompt.\n * `sudo -n` never asks for a password, so a failure is a definitive \"not\n * available\" rather than something to retry interactively.\n */\nexport async function sudoAvailable(): Promise<boolean> {\n if (process.getuid?.() === 0)\n return true\n const result = await run('sudo', ['-n', 'true'], { timeoutMs: 5000 })\n return result.code === 0\n}\n", "/**\n * Shared pieces of the boot ladder: where each mechanism's artifact lives, how\n * ownership of an existing artifact is proven before it is touched, and how a\n * probe's answers collapse into one `BootState`. No process is started here.\n */\nimport fs from 'node:fs'\nimport os from 'node:os'\nimport path from 'node:path'\nimport { readText, writeFileAtomic } from '../util/fsx.js'\nimport type { BootState } from '../shared/contracts.js'\nimport type { BootActionResult, BootProviderContext } from './types.js'\n\nexport function errorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error)\n}\n\n/** Existence check through the injected seam, so a probe is testable without touching the host. */\nexport function existsOf(ctx: BootProviderContext, file: string): boolean {\n return ctx.exists ? ctx.exists(file) : fs.existsSync(file)\n}\n\nexport function posixJoin(...parts: string[]): string {\n return path.posix.join(...parts)\n}\n\n/** `$XDG_CONFIG_HOME`, else `~/.config`. */\nexport function configHome(ctx: BootProviderContext): string {\n const xdg = ctx.env.XDG_CONFIG_HOME?.trim()\n return xdg ? path.posix.resolve(xdg) : posixJoin(ctx.home, '.config')\n}\n\n/** `%LOCALAPPDATA%`, else `~\\AppData\\Local`. */\nexport function localAppData(ctx: BootProviderContext): string {\n const value = ctx.env.LOCALAPPDATA?.trim()\n return value ? value : path.join(ctx.home, 'AppData', 'Local')\n}\n\n/** A writable scratch directory, used to stage a unit before `sudo install`. */\nexport function tempDir(ctx: BootProviderContext): string {\n const value = ctx.env.TMPDIR?.trim() || ctx.env.TEMP?.trim() || ctx.env.TMP?.trim()\n return value || os.tmpdir()\n}\n\nexport function currentUser(ctx: BootProviderContext): string | null {\n const value = ctx.env.USER?.trim() || ctx.env.LOGNAME?.trim() || ctx.env.USERNAME?.trim()\n if (value)\n return value\n try {\n return os.userInfo().username\n }\n catch {\n return null\n }\n}\n\n/** The invoking user's name, so a root-level entry can drop to it. */\nexport function userNameOf(ctx: BootProviderContext): string | null {\n const configured = ctx.env.USER?.trim() ?? ctx.env.USERNAME?.trim()\n if (configured !== undefined && configured.length > 0)\n return configured\n try {\n return os.userInfo().username\n }\n catch {\n return null\n }\n}\n\nexport function uidOf(ctx: BootProviderContext): string | null {\n const configured = ctx.env.UID?.trim()\n if (configured)\n return configured\n const uid = process.getuid?.()\n return uid === undefined ? null : String(uid)\n}\n\n// ---------------------------------------------------------------------------\n// Ownership\n// ---------------------------------------------------------------------------\n\nexport interface FileOwnership {\n exists: boolean\n owned: boolean\n text: string | null\n reason: string | null\n}\n\n/**\n * An artifact belongs to this plugin only when it carries the marker. A file\n * we cannot read is treated as foreign: we must never overwrite or delete a\n * unit somebody else wrote.\n */\nexport function inspectOwned(file: string, marker: string): FileOwnership {\n if (!fs.existsSync(file))\n return { exists: false, owned: false, text: null, reason: null }\n const text = readText(file)\n if (text === null)\n return { exists: true, owned: false, text: null, reason: `${file} exists but is unreadable, so it cannot be proven to be ours` }\n if (!text.includes(marker))\n return { exists: true, owned: false, text, reason: `${file} exists and does not carry this plugin's marker (${marker}); refusing to touch an artifact we did not write` }\n return { exists: true, owned: true, text, reason: null }\n}\n\n/** Write our artifact if the bytes differ; never overwrite a foreign one. */\nexport function writeOwned(file: string, marker: string, content: string, mode = 0o644): { changed: boolean, refusal: string | null } {\n const own = inspectOwned(file, marker)\n if (own.exists && !own.owned)\n return { changed: false, refusal: own.reason }\n if (own.exists && own.text === content)\n return { changed: false, refusal: null }\n writeFileAtomic(file, content, mode)\n return { changed: true, refusal: null }\n}\n\n/** Delete our artifact only; a missing file is already the desired state. */\nexport function removeOwned(file: string, marker: string): { removed: boolean, refusal: string | null } {\n const own = inspectOwned(file, marker)\n if (!own.exists)\n return { removed: false, refusal: null }\n if (!own.owned)\n return { removed: false, refusal: own.reason }\n try {\n fs.rmSync(file, { force: true })\n return { removed: true, refusal: null }\n }\n catch (error) {\n return { removed: false, refusal: `could not delete ${file}: ${errorMessage(error)}` }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Results\n// ---------------------------------------------------------------------------\n\nexport function failed(detail: string, extra: Partial<BootActionResult> = {}): BootActionResult {\n return { ok: false, changed: false, detail, commands: [], needsPrivilege: false, ...extra }\n}\n\n/** Installed + enabled + last run failed is `enabled-failing`; never a guessed success. */\nexport function bootState(installed: boolean, enabled: boolean, failing: boolean): BootState {\n if (!installed)\n return 'not-installed'\n if (!enabled)\n return 'installed-disabled'\n return failing ? 'enabled-failing' : 'enabled-running'\n}\n\nexport function isInstalledState(state: BootState): boolean {\n return state === 'installed-disabled' || state === 'enabled-running' || state === 'enabled-failing'\n}\n", "/**\n * Small filesystem helpers. Every write is atomic (temp file + rename) so a\n * reader never sees half a file, and secret-bearing files are created 0600.\n */\nimport fs from 'node:fs'\nimport path from 'node:path'\nimport process from 'node:process'\n\nexport function fileExists(file: string): boolean {\n try {\n return fs.statSync(file).isFile()\n }\n catch {\n return false\n }\n}\n\nexport function readText(file: string): string | null {\n try {\n return fs.readFileSync(file, 'utf8')\n }\n catch {\n return null\n }\n}\n\nexport function readJson<T>(file: string): T | null {\n const text = readText(file)\n if (text === null)\n return null\n try {\n return JSON.parse(text) as T\n }\n catch {\n return null\n }\n}\n\nexport function ensureDir(dir: string, mode = 0o700): void {\n fs.mkdirSync(dir, { recursive: true, mode })\n}\n\n/** Write a file through a sibling temp file, then rename it into place. */\nexport function writeFileAtomic(file: string, data: string, mode?: number): void {\n ensureDir(path.dirname(file))\n const temp = path.join(path.dirname(file), `.${path.basename(file)}.${process.pid}.${Date.now()}.tmp`)\n const fd = fs.openSync(temp, 'w', mode ?? 0o644)\n try {\n fs.writeFileSync(fd, data, 'utf8')\n fs.fsyncSync(fd)\n }\n finally {\n fs.closeSync(fd)\n }\n if (mode !== undefined)\n fs.chmodSync(temp, mode)\n fs.renameSync(temp, file)\n}\n\nexport function writeJsonAtomic(file: string, value: unknown, mode?: number): void {\n writeFileAtomic(file, `${JSON.stringify(value, null, 2)}\\n`, mode)\n}\n\n/** Best-effort removal; a missing file is not an error. */\nexport function removeFile(file: string): void {\n try {\n fs.rmSync(file, { force: true })\n }\n catch {\n // ignored: the caller only cares that it is gone, and reconciliation reports the rest\n }\n}\n", "/**\n * systemd: a user unit (`~/.config/systemd/user`) and a system unit\n * (`/etc/systemd/system`). The system one needs root, so every privileged call\n * goes through `sudo -n` \u2014 it never prompts \u2014 and the copy-pasteable `sudo \u2026`\n * form is reported when elevation is not available.\n */\nimport fs from 'node:fs'\nimport type { BootCandidate, BootState } from '../shared/contracts.js'\nimport type { BootActionResult, BootProvider, BootProviderContext, BootProviderStatus, BootSpec } from './types.js'\nimport {\n assertAbsolute,\n assertArg,\n assertEnvKey,\n assertLabel,\n assertMarker,\n assertUnitName,\n shellCommand,\n systemdEnvLine,\n systemdExecWord,\n systemdPath,\n systemdText,\n} from './escape.js'\nimport {\n bootState,\n configHome,\n currentUser,\n errorMessage,\n existsOf,\n failed,\n inspectOwned,\n posixJoin,\n removeOwned,\n tempDir,\n writeOwned,\n} from './common.js'\n\nconst ENABLED_UNIT_STATES = new Set(['enabled', 'enabled-runtime', 'alias', 'static', 'indirect', 'generated', 'transient'])\nconst FAILED_RESULTS = new Set(['failed', 'exit-code', 'signal', 'timeout', 'core-dump', 'watchdog', 'start-limit-hit', 'oom-kill'])\n\ntype Scope = 'user' | 'system'\n\nfunction validate(spec: BootSpec): void {\n assertUnitName(spec.unitName)\n assertMarker(spec.marker)\n assertLabel(spec.label)\n assertAbsolute(spec.command, 'spec.command')\n assertAbsolute(spec.cwd, 'spec.cwd')\n assertAbsolute(spec.logDir, 'spec.logDir')\n for (const arg of spec.args)\n assertArg(arg)\n for (const key of Object.keys(spec.env))\n assertEnvKey(key)\n}\n\nfunction envLines(spec: BootSpec): string[] {\n return Object.entries(spec.env).map(([key, value]) => `Environment=${systemdEnvLine(key, value)}`)\n}\n\nconst MANAGED = (spec: BootSpec): string => `# Managed by ${spec.marker}`\n\n/** `Type=exec` with an explicit environment; boot capability comes from linger, not from this file. */\nexport function systemdUserUnit(spec: BootSpec): string {\n validate(spec)\n return `${[\n MANAGED(spec),\n '[Unit]',\n `Description=${systemdText(spec.label)}`,\n 'After=network-online.target',\n '',\n '[Service]',\n 'Type=exec',\n `ExecStart=${[spec.command, ...spec.args].map(systemdExecWord).join(' ')}`,\n `WorkingDirectory=${systemdPath(spec.cwd, 'spec.cwd')}`,\n 'Restart=always',\n 'RestartSec=5',\n ...envLines(spec),\n '',\n '[Install]',\n 'WantedBy=default.target',\n '',\n ].join('\\n')}`\n}\n\n/**\n * The system unit. `StartLimit*` belongs in `[Unit]`, not `[Service]`; `User=`\n * is written only when we are root and know the target account.\n */\nexport function systemdSystemUnit(spec: BootSpec, user: string | null = null): string {\n validate(spec)\n return `${[\n MANAGED(spec),\n '[Unit]',\n `Description=${systemdText(spec.label)}`,\n 'After=network-online.target',\n 'StartLimitIntervalSec=60',\n 'StartLimitBurst=5',\n '',\n '[Service]',\n ...(user ? [`User=${user}`] : []),\n 'Type=exec',\n `ExecStart=${[spec.command, ...spec.args].map(systemdExecWord).join(' ')}`,\n `WorkingDirectory=${systemdPath(spec.cwd, 'spec.cwd')}`,\n 'Restart=always',\n 'RestartSec=5',\n ...envLines(spec),\n '',\n '[Install]',\n 'WantedBy=multi-user.target',\n '',\n ].join('\\n')}`\n}\n\nfunction codeOf(result: { code: number | null, error?: string | null }): number | null {\n return result.error ? null : result.code\n}\n\nfunction parseKeyValues(stdout: string): Record<string, string> {\n const out: Record<string, string> = {}\n for (const line of stdout.split('\\n')) {\n const eq = line.indexOf('=')\n if (eq > 0)\n out[line.slice(0, eq).trim()] = line.slice(eq + 1).trim()\n }\n return out\n}\n\ninterface UnitProbe {\n unitFileState: string\n activeState: string\n result: string\n nRestarts: string\n enabled: boolean\n installed: boolean\n reachable: boolean\n detail: string\n}\n\nasync function readUnit(ctx: BootProviderContext, unit: string, scope: Scope): Promise<UnitProbe> {\n const scopeArgs = scope === 'user' ? ['--user'] : []\n const show = await ctx.run('systemctl', [...scopeArgs, 'show', '-p', 'UnitFileState', '-p', 'ActiveState', '-p', 'Result', '-p', 'NRestarts', unit])\n const props = parseKeyValues(show.stdout)\n const isEnabled = await ctx.run('systemctl', [...scopeArgs, 'is-enabled', unit])\n const enabledCode = codeOf(isEnabled)\n const unitFileState = props.UnitFileState ?? ''\n /**\n * `is-enabled` exits 1 both for a disabled unit and for a unit it cannot even\n * look up, so only a known `UnitFileState` (or an explicit exit 0) proves the\n * unit exists. A user-bus failure must not read as `installed-disabled`.\n */\n const knownState = unitFileState !== '' && unitFileState !== 'not-found'\n const enabled = enabledCode === 0 || ENABLED_UNIT_STATES.has(unitFileState)\n const installed = enabled || knownState\n const result = props.Result ?? ''\n return {\n unitFileState,\n activeState: props.ActiveState ?? '',\n result,\n nRestarts: props.NRestarts ?? '',\n enabled,\n installed,\n reachable: show.error === undefined || show.error === null,\n detail: `UnitFileState=${unitFileState || '(none)'} ActiveState=${props.ActiveState || '(none)'} Result=${result || '(none)'} NRestarts=${props.NRestarts ?? '0'}`,\n }\n}\n\nasync function userScopeReachable(ctx: BootProviderContext): Promise<{ reachable: boolean, reason: string }> {\n const probe = await ctx.run('systemctl', ['--user', 'is-system-running'])\n if (probe.error)\n return { reachable: false, reason: `systemctl --user is not available here (${probe.error})` }\n if (`${probe.stdout}\\n${probe.stderr}`.includes('Failed to connect to user scope bus'))\n return { reachable: false, reason: 'systemctl --user cannot reach a user manager: Failed to connect to user scope bus' }\n return { reachable: true, reason: '' }\n}\n\nasync function lingerEnabled(ctx: BootProviderContext): Promise<boolean> {\n const user = currentUser(ctx)\n if (!user)\n return false\n const probe = await ctx.run('loginctl', ['show-user', user, '--property=Linger'])\n if (codeOf(probe) !== 0)\n return false\n return /(^|\\n)Linger=yes(\\n|$)/.test(probe.stdout)\n}\n\nfunction problem(run: { code: number | null, error?: string | null, stdout: string, stderr: string }, command: string): string | null {\n const code = codeOf(run)\n if (code === 0)\n return null\n if (code === null)\n return run.error ? `${command}: ${run.error}` : `${command}: no exit code`\n return `${command} exited ${code}: ${(run.stderr || run.stdout).trim() || '(no output)'}`\n}\n\nexport function createSystemdUserProvider(ctx: BootProviderContext): BootProvider {\n const mechanism = 'systemd-user' as const\n const unitOf = (spec: BootSpec): string => `${assertUnitName(spec.unitName)}.service`\n const pathOf = (spec: BootSpec): string => posixJoin(configHome(ctx), 'systemd', 'user', unitOf(spec))\n\n return {\n mechanism,\n\n async detect(): Promise<BootCandidate> {\n if (ctx.platform !== 'linux')\n return { mechanism, available: false, bootCapable: false, privileged: false, reason: 'systemd is Linux-only' }\n const bus = await userScopeReachable(ctx)\n if (!bus.reachable)\n return { mechanism, available: false, bootCapable: false, privileged: false, reason: bus.reason }\n const linger = await lingerEnabled(ctx)\n const privileged = linger || (await ctx.sudo())\n return {\n mechanism,\n available: true,\n bootCapable: linger,\n privileged,\n reason: linger\n ? 'a systemd user manager is reachable and linger is on, so the unit starts at boot'\n : 'a systemd user manager is reachable, but linger is off: the unit starts at login until `loginctl enable-linger` succeeds',\n }\n },\n\n async status(spec: BootSpec): Promise<BootProviderStatus> {\n try {\n const unit = unitOf(spec)\n const file = pathOf(spec)\n const own = inspectOwned(file, assertMarker(spec.marker))\n if (own.exists && !own.owned)\n return { state: 'not-installed', unitPath: file, detail: own.reason ?? 'foreign file', commands: [] }\n const probe = await readUnit(ctx, unit, 'user')\n const installed = own.owned || probe.installed\n const state: BootState = bootState(installed, probe.enabled, FAILED_RESULTS.has(probe.result))\n const user = currentUser(ctx)\n const linger = await lingerEnabled(ctx)\n const commands: string[] = []\n if (!linger && user)\n commands.push(shellCommand('sudo', ['loginctl', 'enable-linger', user]))\n const detail = `${probe.detail}; ${linger ? 'linger is on (boot-capable)' : 'linger is off (login-scoped)'}`\n return { state, unitPath: file, detail, commands }\n }\n catch (error) {\n return { state: 'not-installed', unitPath: null, detail: errorMessage(error), commands: [] }\n }\n },\n\n async install(spec: BootSpec): Promise<BootActionResult> {\n try {\n validate(spec)\n const unit = unitOf(spec)\n const file = pathOf(spec)\n const write = writeOwned(file, spec.marker, systemdUserUnit(spec), 0o644)\n if (write.refusal)\n return failed(write.refusal)\n\n const before = await readUnit(ctx, unit, 'user')\n let changed = write.changed\n if (write.changed || !before.enabled) {\n const reloadCommand = shellCommand('systemctl', ['--user', 'daemon-reload'])\n const reload = await ctx.run('systemctl', ['--user', 'daemon-reload'])\n const reloadProblem = problem(reload, reloadCommand)\n if (reloadProblem)\n return failed(reloadProblem, { changed, commands: [reloadCommand] })\n\n const enableCommand = shellCommand('systemctl', ['--user', 'enable', '--now', unit])\n const enable = await ctx.run('systemctl', ['--user', 'enable', '--now', unit])\n const enableProblem = problem(enable, enableCommand)\n if (enableProblem)\n return failed(enableProblem, { changed: true, commands: [enableCommand] })\n changed = true\n }\n\n const after = await readUnit(ctx, unit, 'user')\n if (!after.enabled)\n return failed(`unit ${unit} is not enabled after install (${after.detail})`, { changed })\n\n let linger = await lingerEnabled(ctx)\n const user = currentUser(ctx)\n const commands: string[] = []\n if (!linger && user) {\n const res = await ctx.run('loginctl', ['enable-linger', user])\n if (codeOf(res) === 0) {\n linger = true\n changed = true\n }\n else {\n commands.push(shellCommand('sudo', ['loginctl', 'enable-linger', user]))\n }\n }\n const detail = linger\n ? `${file} installed and enabled; linger is on, so ${unit} starts at boot`\n : `${file} installed and enabled, but linger is off: ${unit} starts at login only. ${commands.length ? `Run \\`${commands[0]}\\` to make it boot-capable.` : 'No target user could be determined to enable linger for.'}`\n return { ok: true, changed, detail, commands, needsPrivilege: !linger }\n }\n catch (error) {\n return failed(errorMessage(error))\n }\n },\n\n async uninstall(spec: BootSpec): Promise<BootActionResult> {\n try {\n validate(spec)\n const unit = unitOf(spec)\n const file = pathOf(spec)\n const own = inspectOwned(file, spec.marker)\n if (own.exists && !own.owned)\n return failed(own.reason ?? 'foreign file')\n\n const before = await readUnit(ctx, unit, 'user')\n if (!before.reachable && !own.exists) {\n return { ok: true, changed: false, detail: `no unit file at ${file} and systemctl is unavailable; nothing to remove`, commands: [], needsPrivilege: false }\n }\n // A unit of the same name can come from anywhere on the search path; with\n // no file of ours, disabling by name would stop somebody else's unit.\n if (!own.owned && !own.exists && before.installed)\n return failed(`a unit named ${unit} exists but no unit file of ours is at ${file}; refusing to disable a unit this plugin did not install`)\n if (own.owned && before.reachable) {\n const disableCommand = shellCommand('systemctl', ['--user', 'disable', '--now', unit])\n const disable = await ctx.run('systemctl', ['--user', 'disable', '--now', unit])\n const disableCode = codeOf(disable)\n if (disableCode !== 0 && disableCode !== 1 && disableCode !== 4)\n return failed(problem(disable, disableCommand) ?? 'disable failed', { commands: [disableCommand] })\n }\n\n const remove = removeOwned(file, spec.marker)\n if (remove.refusal)\n return failed(remove.refusal)\n\n let changed = remove.removed\n if (before.installed || remove.removed) {\n await ctx.run('systemctl', ['--user', 'daemon-reload'])\n changed = true\n }\n\n const after = await readUnit(ctx, unit, 'user')\n if (after.installed)\n return failed(`unit ${unit} is still known to systemd after removal (${after.detail})`, { changed })\n\n return {\n ok: true,\n changed,\n detail: remove.removed ? `disabled and removed ${file}` : `${file} was already gone`,\n commands: [],\n needsPrivilege: false,\n }\n }\n catch (error) {\n return failed(errorMessage(error))\n }\n },\n }\n}\n\nfunction systemUserName(ctx: BootProviderContext): string | null {\n const user = currentUser(ctx)\n return user && /^[A-Za-z_][A-Za-z0-9._-]*$/.test(user) ? user : null\n}\n\nfunction stageUnit(ctx: BootProviderContext, unit: string, content: string): string {\n const staged = posixJoin(tempDir(ctx), `home-hosted-${unit}`)\n fs.writeFileSync(staged, content, { mode: 0o644 })\n return staged\n}\n\nexport function createSystemdSystemProvider(ctx: BootProviderContext): BootProvider {\n const mechanism = 'systemd-system' as const\n const unitOf = (spec: BootSpec): string => `${assertUnitName(spec.unitName)}.service`\n const pathOf = (spec: BootSpec): string => posixJoin('/etc', 'systemd', 'system', unitOf(spec))\n const contentOf = (spec: BootSpec): string => systemdSystemUnit(spec, ctx.isRoot ? systemUserName(ctx) : null)\n\n const installCommands = (staged: string, file: string, unit: string): string[] => [\n shellCommand('sudo', ['install', '-m', '0644', staged, file]),\n shellCommand('sudo', ['systemctl', 'daemon-reload']),\n shellCommand('sudo', ['systemctl', 'enable', '--now', unit]),\n ]\n\n return {\n mechanism,\n\n async detect(): Promise<BootCandidate> {\n if (ctx.platform !== 'linux')\n return { mechanism, available: false, bootCapable: false, privileged: false, reason: 'systemd is Linux-only' }\n if (!existsOf(ctx, '/run/systemd/system'))\n return { mechanism, available: false, bootCapable: false, privileged: false, reason: 'systemd is not the init system here (no /run/systemd/system)' }\n const privileged = ctx.isRoot || (await ctx.sudo())\n return {\n mechanism,\n available: privileged,\n bootCapable: privileged,\n privileged,\n reason: privileged\n ? 'systemd is PID 1 and this process can use root, so a system unit starts at boot'\n : 'systemd is PID 1, but installing a system unit needs root or passwordless sudo',\n }\n },\n\n async status(spec: BootSpec): Promise<BootProviderStatus> {\n try {\n const unit = unitOf(spec)\n const file = pathOf(spec)\n const own = inspectOwned(file, assertMarker(spec.marker))\n if (own.exists && !own.owned)\n return { state: 'not-installed', unitPath: file, detail: own.reason ?? 'foreign file', commands: [] }\n const probe = await readUnit(ctx, unit, 'system')\n const installed = own.owned || probe.installed\n const state: BootState = bootState(installed, probe.enabled, FAILED_RESULTS.has(probe.result))\n const privileged = ctx.isRoot || (await ctx.sudo())\n const commands: string[] = []\n if (installed && !probe.enabled && !privileged)\n commands.push(shellCommand('sudo', ['systemctl', 'enable', '--now', unit]))\n return {\n state,\n unitPath: file,\n detail: `${probe.detail}${privileged ? '' : '; needs root to change'}`,\n commands,\n }\n }\n catch (error) {\n return { state: 'not-installed', unitPath: null, detail: errorMessage(error), commands: [] }\n }\n },\n\n async install(spec: BootSpec): Promise<BootActionResult> {\n try {\n validate(spec)\n const unit = unitOf(spec)\n const file = pathOf(spec)\n const content = contentOf(spec)\n const own = inspectOwned(file, spec.marker)\n if (own.exists && !own.owned)\n return failed(own.reason ?? 'foreign file')\n\n const before = await readUnit(ctx, unit, 'system')\n const changed = !own.exists || own.text !== content\n\n if (!ctx.isRoot && !(await ctx.sudo())) {\n const staged = stageUnit(ctx, unit, content)\n return failed(`installing a system unit needs root; the unit is staged at ${staged}`, {\n changed: false,\n needsPrivilege: true,\n commands: installCommands(staged, file, unit),\n })\n }\n\n if (ctx.isRoot) {\n const write = writeOwned(file, spec.marker, content, 0o644)\n if (write.refusal)\n return failed(write.refusal)\n }\n else {\n const staged = stageUnit(ctx, unit, content)\n const installCommand = shellCommand('sudo', ['install', '-m', '0644', staged, file])\n const install = await ctx.run('sudo', ['-n', 'install', '-m', '0644', staged, file])\n const installProblem = problem(install, installCommand)\n if (installProblem)\n return failed(installProblem, { needsPrivilege: true, commands: installCommands(staged, file, unit) })\n fs.rmSync(staged, { force: true })\n }\n\n if (changed || !before.enabled) {\n const sudoPrefix = ctx.isRoot ? [] : ['-n']\n const reloadCommand = shellCommand('sudo', ['systemctl', 'daemon-reload'])\n const reload = await ctx.run('sudo', [...sudoPrefix, 'systemctl', 'daemon-reload'])\n const reloadProblem = problem(reload, reloadCommand)\n if (reloadProblem)\n return failed(reloadProblem, { changed, needsPrivilege: !ctx.isRoot, commands: [reloadCommand] })\n\n const enableCommand = shellCommand('sudo', ['systemctl', 'enable', '--now', unit])\n const enable = await ctx.run('sudo', [...sudoPrefix, 'systemctl', 'enable', '--now', unit])\n const enableProblem = problem(enable, enableCommand)\n if (enableProblem)\n return failed(enableProblem, { changed: true, needsPrivilege: !ctx.isRoot, commands: [enableCommand] })\n }\n\n const after = await readUnit(ctx, unit, 'system')\n if (!after.enabled)\n return failed(`unit ${unit} is not enabled after install (${after.detail})`, { changed })\n\n return {\n ok: true,\n changed: changed || !before.enabled,\n detail: `${file} installed and enabled as a system unit (${after.detail})`,\n commands: [],\n needsPrivilege: !ctx.isRoot,\n }\n }\n catch (error) {\n return failed(errorMessage(error))\n }\n },\n\n async uninstall(spec: BootSpec): Promise<BootActionResult> {\n try {\n const unit = unitOf(spec)\n const file = pathOf(spec)\n const own = inspectOwned(file, spec.marker)\n if (own.exists && !own.owned)\n return failed(own.reason ?? 'foreign file')\n\n const privileged = ctx.isRoot || (await ctx.sudo())\n if (!privileged) {\n if (!own.exists)\n return { ok: true, changed: false, detail: `no unit file at ${file} and no privilege to change systemd; nothing to remove`, commands: [], needsPrivilege: false }\n return failed('removing a system unit needs root', {\n needsPrivilege: true,\n commands: [\n shellCommand('sudo', ['systemctl', 'disable', '--now', unit]),\n shellCommand('sudo', ['rm', '-f', file]),\n shellCommand('sudo', ['systemctl', 'daemon-reload']),\n ],\n })\n }\n\n const prefix = ctx.isRoot ? [] : ['-n']\n // With no file of ours at the path we write, a same-named unit belongs to\n // somebody else (a vendor unit in /usr/lib/systemd/system): leave it alone.\n if (!own.exists && !own.owned)\n return failed(`no unit file of ours at ${file}; refusing to disable a unit this plugin did not install`)\n const disableCommand = shellCommand('sudo', ['systemctl', 'disable', '--now', unit])\n const disable = await ctx.run('sudo', [...prefix, 'systemctl', 'disable', '--now', unit])\n const disableCode = codeOf(disable)\n if (disableCode !== 0 && disableCode !== 1 && disableCode !== 4)\n return failed(problem(disable, disableCommand) ?? 'disable failed', { needsPrivilege: !ctx.isRoot, commands: [disableCommand] })\n\n if (own.exists) {\n if (ctx.isRoot) {\n const remove = removeOwned(file, spec.marker)\n if (remove.refusal)\n return failed(remove.refusal)\n }\n else {\n // The check above ran as the invoking user, which cannot read a\n // root-only file; re-prove ownership before the privileged delete.\n if (!own.owned)\n return failed(own.reason ?? 'foreign file')\n const rmCommand = shellCommand('sudo', ['rm', '-f', file])\n const rm = await ctx.run('sudo', ['-n', 'rm', '-f', file])\n const rmProblem = problem(rm, rmCommand)\n if (rmProblem)\n return failed(rmProblem, { needsPrivilege: true, commands: [rmCommand] })\n }\n }\n\n await ctx.run('sudo', [...prefix, 'systemctl', 'daemon-reload'])\n const after = await readUnit(ctx, unit, 'system')\n if (after.installed)\n return failed(`unit ${unit} is still known to systemd after removal (${after.detail})`, { changed: true, needsPrivilege: !ctx.isRoot })\n\n return {\n ok: true,\n changed: own.exists || disableCode === 0,\n detail: own.exists ? `disabled and removed ${file}` : `${file} was already gone`,\n commands: [],\n needsPrivilege: !ctx.isRoot,\n }\n }\n catch (error) {\n return failed(errorMessage(error))\n }\n },\n }\n}\n", "/**\n * Escaping for every format this plugin writes.\n *\n * None of this builds a shell command: a unit file, a plist, a `.desktop`\n * entry, a task XML and a registry value each have their own parser, and each\n * value is quoted for exactly that parser. Values that carry control\n * characters (newlines included) are rejected outright, because a newline is\n * how a value escapes its field in every one of these formats.\n */\n\nconst CONTROL = /[\\u0000-\\u001F\\u007F]/\n\nexport function assertNoControl(value: string, what: string): string {\n if (CONTROL.test(value))\n throw new Error(`${what} must not contain control characters or newlines`)\n return value\n}\n\nexport function assertUnitName(name: string): string {\n if (!/^[A-Za-z0-9._@-]+$/.test(name))\n throw new Error(`unit name ${JSON.stringify(name)} must match ^[A-Za-z0-9._@-]+$`)\n if (name.startsWith('-') || name.startsWith('.') || name.includes('..'))\n throw new Error(`unit name ${JSON.stringify(name)} must not be option-like or traverse paths`)\n return name\n}\n\nexport function assertMarker(marker: string): string {\n if (marker.trim() === '')\n throw new Error('marker must not be empty')\n return assertNoControl(marker, 'marker')\n}\n\nexport function assertEnvKey(key: string): string {\n if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(key))\n throw new Error(`environment key ${JSON.stringify(key)} is not a valid name`)\n return key\n}\n\n/** POSIX-absolute, Windows-drive-absolute or UNC; checked without consulting the host OS. */\nexport function isAbsolutePath(value: string): boolean {\n return value.startsWith('/') || /^[A-Za-z]:[\\\\/]/.test(value) || value.startsWith('\\\\\\\\')\n}\n\nexport function assertAbsolute(value: string, what: string): string {\n if (!isAbsolutePath(value))\n throw new Error(`${what} must be absolute, got ${JSON.stringify(value)}`)\n return assertNoControl(value, what)\n}\n\nexport function assertLabel(value: string): string {\n if (value.trim() === '')\n throw new Error('label must not be empty')\n return assertNoControl(value, 'label')\n}\n\nexport function assertArg(value: string, what = 'argument'): string {\n return assertNoControl(value, what)\n}\n\nfunction replaceAll(value: string, pairs: Array<[string, string]>): string {\n let out = value\n for (const [from, to] of pairs)\n out = out.split(from).join(to)\n return out\n}\n\n/** Single-quote a value the way a POSIX shell would, for `commands[]`. */\nexport function shellQuote(value: string): string {\n if (value !== '' && /^[A-Za-z0-9._/:=@%+,-]+$/.test(value))\n return value\n return `'${value.split('\\'').join('\\'\\\\\\'\\'')}'`\n}\n\n/** The exact line a person can paste into a shell. */\nexport function shellCommand(program: string, args: string[]): string {\n return [program, ...args].map(shellQuote).join(' ')\n}\n\n// ---------------------------------------------------------------------------\n// systemd\n// ---------------------------------------------------------------------------\n\n/**\n * A word in `ExecStart=`/`ExecStop=`. systemd expands `%` specifiers and `$`\n * variables there before it splits the line, so both are pinned, and `;` \u2014 the\n * multi-command separator \u2014 is quoted rather than left bare.\n */\nexport function systemdExecWord(value: string): string {\n assertNoControl(value, 'ExecStart word')\n const escaped = replaceAll(value, [['\\\\', '\\\\\\\\'], ['\"', '\\\\\"'], ['$', '$$'], ['%', '%%']])\n return escaped !== value || /[\\s\"';]/.test(value) ? `\"${escaped}\"` : value\n}\n\n/**\n * A single-line free-text setting such as `Description=` (specifiers only).\n */\nexport function systemdText(value: string): string {\n assertNoControl(value, 'unit setting')\n // A trailing backslash would continue the directive onto the next line.\n return replaceAll(value, [['\\\\', '\\\\\\\\'], ['%', '%%']])\n}\n\n/**\n * A path setting (`WorkingDirectory=`). systemd does not unquote these, but it\n * does expand `%` specifiers (an unknown one is fatal, verified with\n * `systemd-analyze verify`), and a trailing `\\` continues the line into the next\n * directive. So both are escaped rather than passed raw.\n */\nexport function systemdPath(value: string, what = 'path'): string {\n assertAbsolute(value, what)\n assertNoControl(value, what)\n if (value.includes('\"'))\n throw new Error(`${what} must not contain a double quote: ${JSON.stringify(value)}`)\n return replaceAll(value, [['\\\\', '\\\\\\\\'], ['%', '%%']])\n}\n\n/** `Environment=KEY=value`, quoted as one assignment when the value needs it. */\nexport function systemdEnvLine(key: string, value: string): string {\n assertEnvKey(key)\n assertNoControl(value, `environment value for ${key}`)\n const escaped = replaceAll(value, [['\\\\', '\\\\\\\\'], ['\"', '\\\\\"'], ['%', '%%']])\n return escaped !== value || /[\\s\"']/.test(value) ? `\"${key}=${escaped}\"` : `${key}=${value}`\n}\n\n// ---------------------------------------------------------------------------\n// XML (launchd plist, scheduled-task XML)\n// ---------------------------------------------------------------------------\n\nexport function xmlEscape(value: string): string {\n assertNoControl(value, 'xml value')\n return replaceAll(value, [['&', '&amp;'], ['<', '&lt;'], ['>', '&gt;'], ['\"', '&quot;'], ['\\'', '&apos;']])\n}\n\nexport function xmlUnescape(value: string): string {\n return replaceAll(value, [['&lt;', '<'], ['&gt;', '>'], ['&quot;', '\"'], ['&apos;', '\\''], ['&amp;', '&']])\n}\n\n/** A marker inside an XML comment may not contain `--`. */\nexport function assertXmlCommentSafe(value: string): string {\n if (value.includes('--'))\n throw new Error('marker must not contain `--` when it is written inside an XML comment')\n return value\n}\n\n// ---------------------------------------------------------------------------\n// freedesktop .desktop\n// ---------------------------------------------------------------------------\n\nconst DESKTOP_RESERVED = /[\\s\"'\\\\><~|&;$*?#()`]/\n\nexport function desktopWord(value: string): string {\n assertNoControl(value, 'desktop Exec word')\n const escaped = replaceAll(value, [['\\\\', '\\\\\\\\'], ['\"', '\\\\\"'], ['`', '\\\\`'], ['$', '\\\\$'], ['%', '%%']])\n return DESKTOP_RESERVED.test(value) || escaped !== value ? `\"${escaped}\"` : value\n}\n\nexport function desktopExec(program: string, args: string[]): string {\n return [program, ...args].map(desktopWord).join(' ')\n}\n\n/** A `Key=value` line in a `.desktop` file; the marker is written verbatim. */\nexport function desktopValue(key: string, value: string): string {\n assertNoControl(value, `desktop ${key}`)\n if (key.includes('=') || key.includes('\\n'))\n throw new Error(`desktop key ${JSON.stringify(key)} is not valid`)\n return `${key}=${value}`\n}\n\n// ---------------------------------------------------------------------------\n// Windows\n// ---------------------------------------------------------------------------\n\n/** Quote one argv word the way `CreateProcess`/`cmd` parse a command line. */\nexport function windowsArg(value: string): string {\n assertNoControl(value, 'windows argument')\n if (value !== '' && !/[\\s\"]/.test(value))\n return value\n\n let out = '\"'\n let backslashes = 0\n for (const char of value) {\n if (char === '\\\\') {\n backslashes += 1\n continue\n }\n if (char === '\"') {\n out += `${'\\\\'.repeat(backslashes * 2 + 1)}\"`\n backslashes = 0\n continue\n }\n out += `${'\\\\'.repeat(backslashes)}${char}`\n backslashes = 0\n }\n out += `${'\\\\'.repeat(backslashes * 2)}\"`\n return out\n}\n\nexport function windowsCommandLine(program: string, args: string[]): string {\n return [program, ...args].map(windowsArg).join(' ')\n}\n\n/** A line for a `.cmd` wrapper: `%` is a batch metacharacter and is doubled. */\nexport function batchCommandLine(program: string, args: string[]): string {\n return batchEscape(windowsCommandLine(program, args))\n}\n\n/**\n * Make one already-quoted command line safe inside a batch file. `%` is doubled\n * last: the `^` inserted for a metacharacter must not itself gain a caret.\n */\nfunction batchEscape(line: string): string {\n assertNoControl(line, 'batch command line')\n return replaceAll(line, [\n ['^', '^^'],\n ['&', '^&'],\n ['|', '^|'],\n ['<', '^<'],\n ['>', '^>'],\n ['(', '^('],\n [')', '^)'],\n ['%', '%%'],\n ])\n}\n\n/** A single-quoted PowerShell literal. */\nexport function powershellLiteral(value: string): string {\n assertNoControl(value, 'powershell value')\n return `'${value.split('\\'').join('\\'\\'')}'`\n}\n\n/** Quote one word the way `cmd.exe` takes it, for a copy-pasteable `commands[]` entry. */\nexport function cmdQuote(value: string): string {\n if (value !== '' && !/[\\s\"&|<>^]/.test(value))\n return value\n return `\"${value.split('\"').join('\"\"')}\"`\n}\n\nexport function windowsDisplayCommand(program: string, args: string[]): string {\n return [program, ...args].map(cmdQuote).join(' ')\n}\n\n// ---------------------------------------------------------------------------\n// launchd / registry value names\n// ---------------------------------------------------------------------------\n\nexport function assertRegistryValueName(name: string): string {\n if (name.trim() === '')\n throw new Error('registry value name must not be empty')\n return assertNoControl(name, 'registry value name')\n}\n", "/**\n * launchd: a per-user agent (`~/Library/LaunchAgents`) and a system daemon\n * (`/Library/LaunchDaemons`). `launchctl print` is read for its exit code only\n * \u2014 its output is explicitly not API. Loading is `bootstrap`, unloading is\n * `bootout`, and exit 5 from bootstrap means the job is already loaded.\n */\nimport fs from 'node:fs'\nimport path from 'node:path'\nimport type { BootCandidate, BootState } from '../shared/contracts.js'\nimport type { BootActionResult, BootProvider, BootProviderContext, BootProviderStatus, BootSpec } from './types.js'\nimport {\n assertAbsolute,\n assertArg,\n assertEnvKey,\n assertLabel,\n assertMarker,\n assertUnitName,\n assertXmlCommentSafe,\n shellCommand,\n xmlEscape,\n} from './escape.js'\nimport {\n bootState,\n errorMessage,\n failed,\n inspectOwned,\n posixJoin,\n removeOwned,\n tempDir,\n uidOf,\n userNameOf,\n writeOwned,\n} from './common.js'\n\n/** Both scopes label with the same reverse-DNS prefix. */\nexport const LAUNCHD_LABEL_PREFIX = 'dev.home-hosted.'\n/** bootstrap on an already-loaded job reports EIO. */\nconst LAUNCHCTL_ALREADY_LOADED = 5\n/** `launchctl print` for a label that is not loaded. */\nconst LAUNCHCTL_NOT_LOADED = 113\n/** `launchctl bootout` for a job that is not there. */\nconst LAUNCHCTL_NO_SUCH_PROCESS = 3\n\nfunction validate(spec: BootSpec): void {\n assertUnitName(spec.unitName)\n assertMarker(spec.marker)\n assertLabel(spec.label)\n assertAbsolute(spec.command, 'spec.command')\n assertAbsolute(spec.cwd, 'spec.cwd')\n assertAbsolute(spec.logDir, 'spec.logDir')\n for (const arg of spec.args)\n assertArg(arg)\n for (const key of Object.keys(spec.env))\n assertEnvKey(key)\n}\n\nexport function launchdLabel(spec: BootSpec): string {\n return `${LAUNCHD_LABEL_PREFIX}${assertUnitName(spec.unitName)}`\n}\n\n/** The full property list. The marker rides in an XML comment, which launchd ignores. */\nexport interface LaunchdPlistOptions {\n /** Set for a LaunchDaemon: launchd would otherwise run the panel as root. */\n userName?: string | null\n}\n\nexport function launchdPlist(spec: BootSpec, options: LaunchdPlistOptions = {}): string {\n validate(spec)\n const label = launchdLabel(spec)\n const userName = options.userName?.trim()\n const out = path.posix.join(spec.logDir, `${label}.out.log`)\n const err = path.posix.join(spec.logDir, `${label}.err.log`)\n const envKeys = Object.keys(spec.env)\n const lines = [\n '<?xml version=\"1.0\" encoding=\"UTF-8\"?>',\n '<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">',\n '<plist version=\"1.0\">',\n '<dict>',\n '\\t<key>Label</key>',\n `\\t<string>${xmlEscape(label)}</string>`,\n ...(userName === undefined || userName.length === 0\n ? []\n : ['\\t<key>UserName</key>', `\\t<string>${xmlEscape(userName)}</string>`]),\n '\\t<key>ProgramArguments</key>',\n '\\t<array>',\n ...[spec.command, ...spec.args].map(arg => `\\t\\t<string>${xmlEscape(arg)}</string>`),\n '\\t</array>',\n '\\t<key>RunAtLoad</key>',\n '\\t<true/>',\n '\\t<key>KeepAlive</key>',\n '\\t<dict>',\n '\\t\\t<key>SuccessfulExit</key>',\n '\\t\\t<false/>',\n '\\t</dict>',\n '\\t<key>ThrottleInterval</key>',\n '\\t<integer>10</integer>',\n '\\t<key>WorkingDirectory</key>',\n `\\t<string>${xmlEscape(spec.cwd)}</string>`,\n ...(envKeys.length\n ? [\n '\\t<key>EnvironmentVariables</key>',\n '\\t<dict>',\n ...envKeys.flatMap(key => [`\\t\\t<key>${xmlEscape(key)}</key>`, `\\t\\t<string>${xmlEscape(spec.env[key] ?? '')}</string>`]),\n '\\t</dict>',\n ]\n : []),\n '\\t<key>StandardOutPath</key>',\n `\\t<string>${xmlEscape(out)}</string>`,\n '\\t<key>StandardErrorPath</key>',\n `\\t<string>${xmlEscape(err)}</string>`,\n `\\t<!-- Managed by ${assertXmlCommentSafe(spec.marker)} -->`,\n '</dict>',\n '</plist>',\n '',\n ]\n return lines.join('\\n')\n}\n\nfunction codeOf(result: { code: number | null, error?: string | null }): number | null {\n return result.error ? null : result.code\n}\n\nfunction problem(run: { code: number | null, error?: string | null, stdout: string, stderr: string }, command: string): string | null {\n const code = codeOf(run)\n if (code === 0)\n return null\n if (code === null)\n return run.error ? `${command}: ${run.error}` : `${command}: no exit code`\n return `${command} exited ${code}: ${(run.stderr || run.stdout).trim() || '(no output)'}`\n}\n\ntype LaunchdMode = 'agent' | 'daemon'\n\n/** Best effort: `/Library/LaunchDaemons` exists on macOS, and only the privileged write can create it. */\nfunction ensureDirQuiet(dir: string): void {\n try {\n fs.mkdirSync(dir, { recursive: true })\n }\n catch {\n // the privileged install reports the real failure\n }\n}\n\nfunction createLaunchdProvider(ctx: BootProviderContext, mode: LaunchdMode): BootProvider {\n const mechanism = mode === 'agent' ? 'launchd-agent' as const : 'launchd-daemon' as const\n const pathOf = (spec: BootSpec): string => mode === 'agent'\n ? posixJoin(ctx.home, 'Library', 'LaunchAgents', `${launchdLabel(spec)}.plist`)\n : posixJoin('/Library', 'LaunchDaemons', `${launchdLabel(spec)}.plist`)\n\n /** `system` for the daemon; `gui/$UID`, else `user/$UID` for the agent. */\n const domainOf = async (): Promise<string | null> => {\n if (mode === 'daemon')\n return 'system'\n const uid = uidOf(ctx)\n if (!uid)\n return null\n const gui = `gui/${uid}`\n if (codeOf(await ctx.run('launchctl', ['print', gui])) === 0)\n return gui\n const user = `user/${uid}`\n if (codeOf(await ctx.run('launchctl', ['print', user])) === 0)\n return user\n return null\n }\n\n const privileged = async (): Promise<boolean> =>\n mode === 'agent' ? true : ctx.isRoot || (await ctx.sudo())\n\n /** Root runs launchctl directly; everything else goes through `sudo -n`. */\n const runPrivileged = async (program: string, args: string[]) =>\n mode === 'agent' || ctx.isRoot ? await ctx.run(program, args) : await ctx.run('sudo', ['-n', program, ...args])\n\n /** The sudo form of what is left to do when this process cannot write the file itself. */\n const commands = (file: string, label: string): string[] => mode === 'agent'\n ? []\n : [\n shellCommand('sudo', ['launchctl', 'bootstrap', 'system', file]),\n shellCommand('sudo', ['launchctl', 'enable', `system/${label}`]),\n ]\n\n return {\n mechanism,\n\n async detect(): Promise<BootCandidate> {\n if (ctx.platform !== 'darwin')\n return { mechanism, available: false, bootCapable: false, privileged: false, reason: 'launchd is macOS-only' }\n if (mode === 'agent') {\n const domain = await domainOf()\n return {\n mechanism,\n // A plist in ~/Library/LaunchAgents is loaded at login whether or not\n // this process can reach launchd right now, so an unreachable domain\n // is a diagnostic, not a reason to refuse.\n available: true,\n bootCapable: false,\n privileged: true,\n reason: domain === null\n ? `a LaunchAgent loads at login; launchd's domain is not reachable from this process for uid ${uidOf(ctx) ?? '?'} right now, so it is loaded at the next login`\n : `launchd ${domain} domain is reachable; a LaunchAgent loads at login, not at boot`,\n }\n }\n const canElevate = ctx.isRoot || (await ctx.sudo())\n return {\n mechanism,\n // Always selectable: without root the plugin stages the plist and hands\n // over the three sudo commands, which is the only way to start before\n // login on a Mac that has no passwordless sudo.\n available: true,\n bootCapable: true,\n privileged: canElevate,\n reason: canElevate\n ? 'this process can write /Library/LaunchDaemons, so a LaunchDaemon starts at boot'\n : 'a LaunchDaemon starts at boot but needs root here, so the plugin stages the plist and shows the sudo commands',\n }\n },\n\n async status(spec: BootSpec): Promise<BootProviderStatus> {\n try {\n const file = pathOf(spec)\n const label = launchdLabel(spec)\n const own = inspectOwned(file, assertMarker(spec.marker))\n if (own.exists && !own.owned)\n return { state: 'not-installed', unitPath: file, detail: own.reason ?? 'foreign file', commands: [] }\n const domain = await domainOf()\n if (!own.owned)\n return { state: 'not-installed', unitPath: file, detail: `no plist at ${file}`, commands: [] }\n if (domain === null)\n return { state: 'enabled-running', unitPath: file, detail: `${file} is present; launchd has no reachable domain for uid ${uidOf(ctx) ?? '?'}, so it loads at the next login`, commands: [] }\n const probe = await ctx.run('launchctl', ['print', `${domain}/${label}`])\n const loaded = codeOf(probe) === 0\n const state: BootState = bootState(true, true, false)\n return {\n state,\n unitPath: file,\n detail: `${file} is present; ${loaded ? `loaded in ${domain}` : `not loaded right now (RunAtLoad loads it at the next login)`}`,\n commands: [],\n }\n }\n catch (error) {\n return { state: 'not-installed', unitPath: null, detail: errorMessage(error), commands: [] }\n }\n },\n\n async install(spec: BootSpec): Promise<BootActionResult> {\n try {\n validate(spec)\n const file = pathOf(spec)\n const label = launchdLabel(spec)\n const content = launchdPlist(spec, mode === 'daemon' ? { userName: userNameOf(ctx) } : {})\n const own = inspectOwned(file, spec.marker)\n if (own.exists && !own.owned)\n return failed(own.reason ?? 'foreign file')\n const staged = posixJoin(tempDir(ctx), `${label}.plist`)\n if (!(await privileged())) {\n // The command below installs this exact file, so it has to exist.\n ensureDirQuiet(path.posix.dirname(staged))\n fs.writeFileSync(staged, content, { mode: 0o644 })\n return failed('writing /Library/LaunchDaemons needs root; the plist is staged for you to install', {\n needsPrivilege: true,\n commands: [\n shellCommand('sudo', ['install', '-m', '0644', staged, file]),\n shellCommand('sudo', ['launchctl', 'bootstrap', 'system', file]),\n shellCommand('sudo', ['launchctl', 'enable', `system/${label}`]),\n ],\n })\n }\n\n const domain = await domainOf()\n\n ensureDirQuiet(path.posix.dirname(file))\n ensureDirQuiet(spec.logDir)\n\n const loaded = domain !== null && codeOf(await ctx.run('launchctl', ['print', `${domain}/${label}`])) === 0\n const before = { text: own.text, exists: own.exists }\n\n let changed = false\n if (mode === 'agent' || ctx.isRoot) {\n const write = writeOwned(file, spec.marker, content, 0o644)\n if (write.refusal)\n return failed(write.refusal)\n changed = write.changed\n }\n else {\n ensureDirQuiet(path.dirname(staged))\n fs.writeFileSync(staged, content, { mode: 0o644 })\n changed = !before.exists || before.text !== content\n if (!changed) {\n fs.rmSync(staged, { force: true })\n }\n else {\n const installCommand = shellCommand('sudo', ['install', '-m', '0644', staged, file])\n const install = await runPrivileged('install', ['-m', '0644', staged, file])\n if (codeOf(install) !== 0)\n return failed(problem(install, installCommand) ?? 'launchctl failed', { needsPrivilege: true, commands: [installCommand] })\n fs.rmSync(staged, { force: true })\n }\n }\n\n const lint = await runPrivileged('plutil', ['-lint', file])\n if (codeOf(lint) !== 0)\n return failed(`plutil -lint rejected the generated plist: ${(lint.stderr || lint.stdout).trim() || 'no output'}`, { changed, commands: commands(file, label) })\n\n if (domain === null) {\n return {\n ok: true,\n changed,\n detail: `${file} is in place; launchd's domain is not reachable from this process, so it loads at the next login`,\n commands: [],\n needsPrivilege: false,\n }\n }\n\n if (loaded && changed) {\n const bootout = await runPrivileged('launchctl', ['bootout', `${domain}/${label}`])\n const bootoutCode = codeOf(bootout)\n if (bootoutCode !== 0 && bootoutCode !== LAUNCHCTL_NO_SUCH_PROCESS && bootoutCode !== LAUNCHCTL_NOT_LOADED)\n return failed(problem(bootout, shellCommand('launchctl', ['bootout', `${domain}/${label}`])) ?? 'launchctl failed', { changed, commands: commands(file, label) })\n }\n\n if (changed || !loaded) {\n const boot = await runPrivileged('launchctl', ['bootstrap', domain, file])\n const bootCode = codeOf(boot)\n if (bootCode !== 0 && bootCode !== LAUNCHCTL_ALREADY_LOADED)\n return failed(problem(boot, shellCommand('launchctl', ['bootstrap', domain, file])) ?? 'launchctl failed', { changed, commands: commands(file, label) })\n if (bootCode === 0)\n changed = true\n const enable = await runPrivileged('launchctl', ['enable', `${domain}/${label}`])\n if (codeOf(enable) !== 0)\n return failed(problem(enable, shellCommand('launchctl', ['enable', `${domain}/${label}`])) ?? 'launchctl failed', { changed, commands: commands(file, label) })\n }\n\n const verify = await runPrivileged('launchctl', ['print', `${domain}/${label}`])\n if (codeOf(verify) !== 0)\n return failed(`launchctl print ${domain}/${label} did not confirm the job (exit ${String(codeOf(verify))})`, { changed, commands: commands(file, label) })\n\n return {\n ok: true,\n changed,\n detail: `${file} installed and loaded in ${domain}`,\n commands: [],\n needsPrivilege: mode === 'daemon' && !ctx.isRoot,\n }\n }\n catch (error) {\n return failed(errorMessage(error))\n }\n },\n\n async uninstall(spec: BootSpec): Promise<BootActionResult> {\n try {\n const file = pathOf(spec)\n const label = launchdLabel(spec)\n const own = inspectOwned(file, spec.marker)\n if (own.exists && !own.owned)\n return failed(own.reason ?? 'foreign file')\n if (mode === 'daemon' && !ctx.isRoot && !(await ctx.sudo())) {\n if (!own.exists)\n return { ok: true, changed: false, detail: `no plist at ${file} and no privilege to change launchd; nothing to remove`, commands: [], needsPrivilege: false }\n return failed('removing a LaunchDaemon needs root', {\n needsPrivilege: true,\n commands: [\n shellCommand('sudo', ['launchctl', 'bootout', `system/${label}`]),\n shellCommand('sudo', ['rm', '-f', file]),\n ],\n })\n }\n\n const domain = await domainOf()\n // A job under this label may belong to a plist we did not write; never\n // boot out a job whose own file is not ours.\n if (!own.exists && !own.owned)\n return failed(`no plist of ours at ${file}; refusing to unload a job this plugin did not install`)\n let changed = false\n if (domain !== null) {\n const bootout = await runPrivileged('launchctl', ['bootout', `${domain}/${label}`])\n const bootoutCode = codeOf(bootout)\n if (bootoutCode === 0)\n changed = true\n else if (bootoutCode !== LAUNCHCTL_NO_SUCH_PROCESS && bootoutCode !== LAUNCHCTL_NOT_LOADED)\n return failed(problem(bootout, shellCommand('launchctl', ['bootout', `${domain}/${label}`])) ?? 'launchctl failed', { commands: commands(file, label) })\n }\n\n if (own.exists) {\n if (mode === 'agent' || ctx.isRoot) {\n const remove = removeOwned(file, spec.marker)\n if (remove.refusal)\n return failed(remove.refusal)\n if (remove.removed)\n changed = true\n }\n else {\n // Re-prove ownership before the privileged delete: the check above\n // ran as the invoking user, which may not be able to read the file.\n if (!own.owned)\n return failed(own.reason ?? 'foreign file')\n const rmCommand = shellCommand('sudo', ['rm', '-f', file])\n const rm = await runPrivileged('rm', ['-f', file])\n if (codeOf(rm) !== 0)\n return failed(problem(rm, rmCommand) ?? 'launchctl failed', { needsPrivilege: true, commands: [rmCommand] })\n changed = true\n }\n }\n\n if (domain !== null) {\n const verify = await runPrivileged('launchctl', ['print', `${domain}/${label}`])\n if (codeOf(verify) === 0)\n return failed(`${label} is still loaded in ${domain} after bootout`, { changed })\n }\n\n return {\n ok: true,\n changed,\n detail: own.exists ? `unloaded and removed ${file}` : `no plist at ${file} (already gone)`,\n commands: [],\n needsPrivilege: mode === 'daemon' && !ctx.isRoot,\n }\n }\n catch (error) {\n return failed(errorMessage(error))\n }\n },\n }\n}\n\nexport function createLaunchdAgentProvider(ctx: BootProviderContext): BootProvider {\n return createLaunchdProvider(ctx, 'agent')\n}\n\nexport function createLaunchdDaemonProvider(ctx: BootProviderContext): BootProvider {\n return createLaunchdProvider(ctx, 'daemon')\n}\n", "/**\n * freedesktop XDG autostart: `~/.config/autostart/<unitName>.desktop`.\n * This runs at login, never at boot, and needs no privilege. `Exec=` is not a\n * shell, so every word is quoted for the desktop entry parser and `$`/`%` are\n * escaped rather than expanded.\n */\nimport fs from 'node:fs'\nimport path from 'node:path'\nimport type { BootCandidate, BootState } from '../shared/contracts.js'\nimport type { BootActionResult, BootProvider, BootProviderContext, BootProviderStatus, BootSpec } from './types.js'\nimport { assertAbsolute, assertArg, assertEnvKey, assertLabel, assertMarker, assertUnitName, desktopExec } from './escape.js'\nimport { bootState, configHome, errorMessage, failed, inspectOwned, posixJoin, removeOwned, writeOwned } from './common.js'\n\nfunction validate(spec: BootSpec): void {\n assertUnitName(spec.unitName)\n assertMarker(spec.marker)\n assertLabel(spec.label)\n assertAbsolute(spec.command, 'spec.command')\n assertAbsolute(spec.cwd, 'spec.cwd')\n for (const arg of spec.args)\n assertArg(arg)\n for (const key of Object.keys(spec.env))\n assertEnvKey(key)\n}\n\nexport function xdgDesktopEntry(spec: BootSpec): string {\n validate(spec)\n return `${[\n '[Desktop Entry]',\n 'Type=Application',\n `Name=${spec.label}`,\n `Comment=home-hosted daemon, managed by ${spec.marker}`,\n `Exec=${desktopExec(spec.command, spec.args)}`,\n `Path=${spec.cwd}`,\n 'Terminal=false',\n 'X-GNOME-Autostart-enabled=true',\n `X-HomeHosted-Marker=${spec.marker}`,\n '',\n ].join('\\n')}`\n}\n\nfunction desktopFlag(text: string, key: string): string | null {\n for (const line of text.split('\\n')) {\n const trimmed = line.trim()\n if (trimmed.startsWith(`${key}=`))\n return trimmed.slice(key.length + 1).trim()\n }\n return null\n}\n\nexport function createXdgAutostartProvider(ctx: BootProviderContext): BootProvider {\n const mechanism = 'xdg-autostart' as const\n const unitOf = (spec: BootSpec): string => `${assertUnitName(spec.unitName)}.desktop`\n const pathOf = (spec: BootSpec): string => posixJoin(configHome(ctx), 'autostart', unitOf(spec))\n\n return {\n mechanism,\n\n async detect(): Promise<BootCandidate> {\n if (ctx.platform !== 'linux')\n return { mechanism, available: false, bootCapable: false, privileged: false, reason: 'XDG autostart is Linux-only' }\n return {\n mechanism,\n available: true,\n bootCapable: false,\n privileged: true,\n reason: `a .desktop entry under ${posixJoin(configHome(ctx), 'autostart')} needs no privilege, but it starts at login rather than at boot`,\n }\n },\n\n async status(spec: BootSpec): Promise<BootProviderStatus> {\n try {\n const file = pathOf(spec)\n const own = inspectOwned(file, assertMarker(spec.marker))\n if (own.exists && !own.owned)\n return { state: 'not-installed', unitPath: file, detail: own.reason ?? 'foreign file', commands: [] }\n if (!own.owned || own.text === null)\n return { state: 'not-installed', unitPath: file, detail: `no autostart entry at ${file}`, commands: [] }\n const enabled = desktopFlag(own.text, 'X-GNOME-Autostart-enabled') !== 'false'\n && desktopFlag(own.text, 'Hidden') !== 'true'\n const state: BootState = bootState(true, enabled, false)\n return {\n state,\n unitPath: file,\n detail: `${file} is present; ${enabled ? 'it starts at login' : 'it is disabled'} (login scope, not boot)`,\n commands: [],\n }\n }\n catch (error) {\n return { state: 'not-installed', unitPath: null, detail: errorMessage(error), commands: [] }\n }\n },\n\n async install(spec: BootSpec): Promise<BootActionResult> {\n try {\n validate(spec)\n const file = pathOf(spec)\n fs.mkdirSync(path.dirname(file), { recursive: true })\n const write = writeOwned(file, spec.marker, xdgDesktopEntry(spec), 0o644)\n if (write.refusal)\n return failed(write.refusal)\n\n const text = inspectOwned(file, spec.marker).text\n const enabled = text !== null\n && desktopFlag(text, 'X-GNOME-Autostart-enabled') !== 'false'\n && desktopFlag(text, 'Hidden') !== 'true'\n if (!enabled)\n return failed(`${file} was written but does not read back as enabled`, { changed: write.changed })\n\n return {\n ok: true,\n changed: write.changed,\n detail: write.changed\n ? `${file} installed; it starts at login (not at boot)`\n : `${file} was already installed and enabled`,\n commands: [],\n needsPrivilege: false,\n }\n }\n catch (error) {\n return failed(errorMessage(error))\n }\n },\n\n async uninstall(spec: BootSpec): Promise<BootActionResult> {\n try {\n const file = pathOf(spec)\n const own = inspectOwned(file, spec.marker)\n if (own.exists && !own.owned)\n return failed(own.reason ?? 'foreign file')\n const remove = removeOwned(file, spec.marker)\n if (remove.refusal)\n return failed(remove.refusal)\n return {\n ok: true,\n changed: remove.removed,\n detail: remove.removed ? `removed ${file}` : `${file} was already gone`,\n commands: [],\n needsPrivilege: false,\n }\n }\n catch (error) {\n return failed(errorMessage(error))\n }\n },\n }\n}\n", "/**\n * Windows: the per-user `Run` key (login scope, no admin) and a scheduled task\n * (admin). `sc.exe` is never used \u2014 a plain Node process has no service\n * dispatcher and would fail with error 1053.\n *\n * The `Run` key starts *every* value it holds, so the ownership marker cannot\n * live beside the command there; it lives under this plugin's own key\n * (`HKCU\\Software\\home-hosted`), and a `Run` value is only touched when that\n * marker proves we wrote it.\n */\nimport fs from 'node:fs'\nimport path from 'node:path'\nimport type { BootCandidate, BootState } from '../shared/contracts.js'\nimport type { BootActionResult, BootProvider, BootProviderContext, BootProviderStatus, BootSpec } from './types.js'\nimport {\n assertAbsolute,\n assertArg,\n assertEnvKey,\n assertLabel,\n assertMarker,\n assertRegistryValueName,\n assertUnitName,\n batchCommandLine,\n powershellLiteral,\n windowsArg,\n windowsCommandLine,\n windowsDisplayCommand,\n xmlEscape,\n xmlUnescape,\n} from './escape.js'\nimport { bootState, errorMessage, failed, inspectOwned, localAppData, removeOwned, tempDir, writeOwned } from './common.js'\n\nexport const RUN_KEY = 'HKCU\\\\Software\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Run'\nexport const MARKER_KEY = 'HKCU\\\\Software\\\\home-hosted'\nconst RUN_VALUE_LIMIT = 260\n\nfunction validate(spec: BootSpec): void {\n assertUnitName(spec.unitName)\n assertMarker(spec.marker)\n assertLabel(spec.label)\n assertAbsolute(spec.command, 'spec.command')\n assertAbsolute(spec.cwd, 'spec.cwd')\n for (const arg of spec.args)\n assertArg(arg)\n for (const key of Object.keys(spec.env))\n assertEnvKey(key)\n}\n\nfunction codeOf(result: { code: number | null, error?: string | null }): number | null {\n return result.error ? null : result.code\n}\n\nfunction problem(run: { code: number | null, error?: string | null, stdout: string, stderr: string }, command: string): string | null {\n const code = codeOf(run)\n if (code === 0)\n return null\n if (code === null)\n return run.error ? `${command}: ${run.error}` : `${command}: no exit code`\n return `${command} exited ${code}: ${(run.stderr || run.stdout).trim() || '(no output)'}`\n}\n\ninterface RegValue {\n exists: boolean\n data: string | null\n}\n\nasync function queryReg(ctx: BootProviderContext, key: string, name: string): Promise<RegValue> {\n const res = await ctx.run('reg.exe', ['query', key, '/v', name])\n if (res.error || res.code !== 0)\n return { exists: false, data: null }\n for (const line of res.stdout.split(/\\r?\\n/)) {\n const match = /^\\s{2,}(.+?)\\s{2,}(REG_[A-Z_]+)\\s{2,}(.*)$/.exec(line)\n if (match && match[1]?.trim() === name)\n return { exists: true, data: (match[3] ?? '').trim() }\n }\n return { exists: false, data: null }\n}\n\nexport interface WindowsRunPayload {\n /** The exact `Run` value data. */\n data: string\n /** Set when the command line exceeded the `Run` value limit and a `.cmd` wrapper is needed. */\n wrapperPath: string | null\n wrapperContent: string | null\n}\n\nexport function windowsRunPayload(ctx: BootProviderContext, spec: BootSpec): WindowsRunPayload {\n const direct = windowsCommandLine(spec.command, spec.args)\n if (direct.length <= RUN_VALUE_LIMIT)\n return { data: direct, wrapperPath: null, wrapperContent: null }\n const wrapperPath = path.join(localAppData(ctx), 'home-hosted', `${spec.unitName}.cmd`)\n return {\n data: `cmd.exe /c ${windowsArg(wrapperPath)}`,\n wrapperPath,\n wrapperContent: `@echo off\\r\\nrem ${spec.marker}\\r\\n${batchCommandLine(spec.command, spec.args)}\\r\\n`,\n }\n}\n\nfunction createWindowsRunProviderImpl(ctx: BootProviderContext): BootProvider {\n const mechanism = 'windows-run' as const\n const nameOf = (spec: BootSpec): string => assertRegistryValueName(assertUnitName(spec.unitName))\n\n const addValue = (key: string, name: string, data: string) =>\n ctx.run('reg.exe', ['add', key, '/v', name, '/t', 'REG_SZ', '/d', data, '/f'])\n\n return {\n mechanism,\n\n async detect(): Promise<BootCandidate> {\n if (ctx.platform !== 'win32')\n return { mechanism, available: false, bootCapable: false, privileged: false, reason: 'the Run key is Windows-only' }\n return {\n mechanism,\n available: true,\n bootCapable: false,\n privileged: true,\n reason: `HKCU\\\\\u2026\\\\Run needs no admin, but it starts at login rather than at boot`,\n }\n },\n\n async status(spec: BootSpec): Promise<BootProviderStatus> {\n try {\n const name = nameOf(spec)\n const marker = assertMarker(spec.marker)\n const value = await queryReg(ctx, RUN_KEY, name)\n if (!value.exists)\n return { state: 'not-installed', unitPath: RUN_KEY, detail: `no ${RUN_KEY}\\\\${name} value`, commands: [] }\n const markerValue = await queryReg(ctx, MARKER_KEY, name)\n const owned = markerValue.data?.includes(marker) === true\n if (!owned)\n return { state: 'not-installed', unitPath: RUN_KEY, detail: `${name} exists under ${RUN_KEY} but is not marked as ours; refusing to treat it as this plugin's entry`, commands: [] }\n const state: BootState = bootState(true, true, false)\n return { state, unitPath: RUN_KEY, detail: `${RUN_KEY}\\\\${name} starts at login (not at boot)`, commands: [] }\n }\n catch (error) {\n return { state: 'not-installed', unitPath: RUN_KEY, detail: errorMessage(error), commands: [] }\n }\n },\n\n async install(spec: BootSpec): Promise<BootActionResult> {\n try {\n validate(spec)\n const name = nameOf(spec)\n const marker = assertMarker(spec.marker)\n const payload = windowsRunPayload(ctx, spec)\n const wrapperExists = payload.wrapperPath !== null && fs.existsSync(payload.wrapperPath)\n const wrapperOwn = payload.wrapperPath ? inspectOwned(payload.wrapperPath, marker) : null\n if (wrapperOwn?.exists && !wrapperOwn.owned)\n return failed(wrapperOwn.reason ?? 'foreign wrapper')\n\n const markerValue = await queryReg(ctx, MARKER_KEY, name)\n const owned = markerValue.data?.includes(marker) === true\n const current = await queryReg(ctx, RUN_KEY, name)\n // A value the marker does not prove is ours is never touched and never\n // claimed, even when it already equals what we would write.\n if (current.exists && !owned)\n return failed(`${RUN_KEY}\\\\${name} already exists and was not written by this plugin; refusing to overwrite it`)\n\n const commands: string[] = [\n windowsDisplayCommand('reg.exe', ['add', RUN_KEY, '/v', name, '/t', 'REG_SZ', '/d', payload.data, '/f']),\n ]\n\n let changed = false\n if (payload.wrapperPath && payload.wrapperContent) {\n const write = writeOwned(payload.wrapperPath, marker, payload.wrapperContent, 0o644)\n if (write.refusal)\n return failed(write.refusal)\n changed = write.changed || changed\n }\n\n if (!current.exists || current.data !== payload.data) {\n const add = await addValue(RUN_KEY, name, payload.data)\n const addProblem = problem(add, commands[0] ?? 'reg.exe add')\n if (addProblem)\n return failed(addProblem, { changed, commands })\n changed = true\n }\n if (!owned) {\n const mark = await addValue(MARKER_KEY, name, marker)\n const markProblem = problem(mark, windowsDisplayCommand('reg.exe', ['add', MARKER_KEY, '/v', name, '/t', 'REG_SZ', '/d', marker, '/f']))\n if (markProblem)\n return failed(markProblem, { changed, commands })\n changed = true\n }\n\n const after = await queryReg(ctx, RUN_KEY, name)\n if (after.data !== payload.data)\n return failed(`${RUN_KEY}\\\\${name} does not read back as the value that was written`, { changed, commands })\n\n // A wrapper we no longer need is cleaned up so the Run value converges on the direct form.\n if (!payload.wrapperPath && wrapperExists && wrapperOwn?.owned) {\n removeOwned(path.join(localAppData(ctx), 'home-hosted', `${spec.unitName}.cmd`), marker)\n }\n\n return {\n ok: true,\n changed,\n detail: changed ? `${RUN_KEY}\\\\${name} installed; it starts at login (not at boot)` : `${RUN_KEY}\\\\${name} was already installed`,\n commands: [],\n needsPrivilege: false,\n }\n }\n catch (error) {\n return failed(errorMessage(error))\n }\n },\n\n async uninstall(spec: BootSpec): Promise<BootActionResult> {\n try {\n const name = nameOf(spec)\n const marker = assertMarker(spec.marker)\n const current = await queryReg(ctx, RUN_KEY, name)\n const markerValue = await queryReg(ctx, MARKER_KEY, name)\n const owned = markerValue.data?.includes(marker) === true\n if (current.exists && !owned) {\n const payload = windowsRunPayload(ctx, spec)\n const wrapperOwned = payload.wrapperPath !== null ? inspectOwned(payload.wrapperPath, marker).owned : false\n if (current.data !== payload.data && !wrapperOwned)\n return failed(`${RUN_KEY}\\\\${name} is not marked as ours; refusing to delete a foreign Run value`)\n }\n\n let changed = false\n if (current.exists) {\n const del = await ctx.run('reg.exe', ['delete', RUN_KEY, '/v', name, '/f'])\n const delCode = codeOf(del)\n if (delCode !== 0 && delCode !== 1)\n return failed(problem(del, windowsDisplayCommand('reg.exe', ['delete', RUN_KEY, '/v', name, '/f'])) ?? 'reg.exe delete failed')\n changed = delCode === 0\n }\n if (owned) {\n await ctx.run('reg.exe', ['delete', MARKER_KEY, '/v', name, '/f'])\n changed = true\n }\n\n const payload = windowsRunPayload(ctx, spec)\n if (payload.wrapperPath) {\n const remove = removeOwned(payload.wrapperPath, marker)\n if (remove.refusal)\n return failed(remove.refusal)\n changed = remove.removed || changed\n }\n const stale = path.join(localAppData(ctx), 'home-hosted', `${spec.unitName}.cmd`)\n const staleRemove = removeOwned(stale, marker)\n if (staleRemove.refusal)\n return failed(staleRemove.refusal)\n changed = staleRemove.removed || changed\n\n const after = await queryReg(ctx, RUN_KEY, name)\n if (after.exists)\n return failed(`${RUN_KEY}\\\\${name} still exists after removal`, { changed })\n\n return {\n ok: true,\n changed,\n detail: changed ? `removed ${RUN_KEY}\\\\${name}` : `${RUN_KEY}\\\\${name} was already gone`,\n commands: [],\n needsPrivilege: false,\n }\n }\n catch (error) {\n return failed(errorMessage(error))\n }\n },\n }\n}\n\n// ---------------------------------------------------------------------------\n// Scheduled task\n// ---------------------------------------------------------------------------\n\nexport function scheduledTaskXml(spec: BootSpec): string {\n validate(spec)\n const args = spec.args.map(windowsArg).join(' ')\n return `${[\n '<?xml version=\"1.0\" encoding=\"UTF-16\"?>',\n '<Task version=\"1.2\" xmlns=\"http://schemas.microsoft.com/windows/2004/02/mit/task\">',\n '<RegistrationInfo>',\n `<Description>${xmlEscape(spec.marker)}</Description>`,\n '</RegistrationInfo>',\n '<Triggers>',\n '<LogonTrigger>',\n '<Enabled>true</Enabled>',\n '</LogonTrigger>',\n '</Triggers>',\n '<Principals>',\n '<Principal id=\"Author\">',\n '<LogonType>InteractiveToken</LogonType>',\n '<RunLevel>LeastPrivilege</RunLevel>',\n '</Principal>',\n '</Principals>',\n '<Settings>',\n '<MultipleInstancesPolicy>IgnoreNew</MultipleInstancesPolicy>',\n '<DisallowStartIfOnBatteries>false</DisallowStartIfOnBatteries>',\n '<StopIfGoingOnBatteries>false</StopIfGoingOnBatteries>',\n '<StartWhenAvailable>true</StartWhenAvailable>',\n '<RestartOnFailure>',\n '<Interval>PT1M</Interval>',\n '<Count>3</Count>',\n '</RestartOnFailure>',\n '<ExecutionTimeLimit>PT0S</ExecutionTimeLimit>',\n '</Settings>',\n '<Actions Context=\"Author\">',\n '<Exec>',\n `<Command>${xmlEscape(spec.command)}</Command>`,\n `<Arguments>${xmlEscape(args)}</Arguments>`,\n `<WorkingDirectory>${xmlEscape(spec.cwd)}</WorkingDirectory>`,\n '</Exec>',\n '</Actions>',\n '</Task>',\n '',\n ].join('\\r\\n')}`\n}\n\nexport function registerTaskScript(spec: BootSpec): string {\n validate(spec)\n const args = spec.args.map(windowsArg).join(' ')\n return [\n `$action = New-ScheduledTaskAction -Execute ${powershellLiteral(spec.command)} -Argument ${powershellLiteral(args)} -WorkingDirectory ${powershellLiteral(spec.cwd)}`,\n '$trigger = New-ScheduledTaskTrigger -AtLogOn',\n '$settings = New-ScheduledTaskSettingsSet -RestartCount 3 -RestartInterval (New-TimeSpan -Minutes 1) -StartWhenAvailable -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries',\n `Register-ScheduledTask -TaskName ${powershellLiteral(spec.unitName)} -Action $action -Trigger $trigger -Settings $settings -Description ${powershellLiteral(spec.marker)} -Force | Out-Null`,\n ].join('; ')\n}\n\nexport function unregisterTaskScript(name: string): string {\n return `Unregister-ScheduledTask -TaskName ${powershellLiteral(assertUnitName(name))} -Confirm:$false`\n}\n\nfunction xmlTag(xml: string, tag: string): string | null {\n const match = new RegExp(`<${tag}>([\\\\s\\\\S]*?)</${tag}>`).exec(xml)\n return match?.[1] === undefined ? null : xmlUnescape(match[1].trim())\n}\n\ninterface TaskInfo {\n exists: boolean\n xml: string | null\n marked: boolean\n matches: boolean\n}\n\nexport function createWindowsTaskProvider(ctx: BootProviderContext): BootProvider {\n const mechanism = 'windows-task' as const\n const nameOf = (spec: BootSpec): string => assertUnitName(spec.unitName)\n\n const query = async (name: string): Promise<{ exists: boolean, xml: string | null }> => {\n const res = await ctx.run('schtasks.exe', ['/Query', '/TN', name, '/XML'])\n if (res.error || res.code !== 0)\n return { exists: false, xml: null }\n return { exists: true, xml: res.stdout }\n }\n\n const inspect = async (spec: BootSpec): Promise<TaskInfo> => {\n const found = await query(nameOf(spec))\n if (!found.exists || found.xml === null)\n return { exists: false, xml: null, marked: false, matches: false }\n const marked = xmlUnescape(found.xml).includes(spec.marker)\n const args = spec.args.map(windowsArg).join(' ')\n const matches = marked\n && xmlTag(found.xml, 'Command') === spec.command\n && xmlTag(found.xml, 'Arguments') === args\n && (xmlTag(found.xml, 'WorkingDirectory') ?? spec.cwd) === spec.cwd\n return { exists: true, xml: found.xml, marked, matches }\n }\n\n const hasRegisterCmdlet = async (): Promise<boolean> => {\n const probe = await ctx.run('powershell.exe', ['-NoProfile', '-Command', 'Get-Command Register-ScheduledTask'])\n return probe.error === undefined || probe.error === null\n ? /Register-ScheduledTask/.test(probe.stdout)\n : false\n }\n\n const isElevated = async (): Promise<boolean> => {\n const script = '([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)'\n const probe = await ctx.run('powershell.exe', ['-NoProfile', '-Command', script])\n return probe.error === undefined || probe.error === null ? /^true$/im.test(probe.stdout.trim()) : false\n }\n\n return {\n mechanism,\n\n async detect(): Promise<BootCandidate> {\n if (ctx.platform !== 'win32')\n return { mechanism, available: false, bootCapable: false, privileged: false, reason: 'scheduled tasks are Windows-only' }\n const elevated = await isElevated()\n return {\n mechanism,\n available: elevated,\n bootCapable: false,\n privileged: elevated,\n reason: elevated\n ? 'administrator rights are available; the task is registered for logon (not for boot)'\n : 'registering a scheduled task needs an elevated process',\n }\n },\n\n async status(spec: BootSpec): Promise<BootProviderStatus> {\n try {\n const name = nameOf(spec)\n const info = await inspect(spec)\n if (!info.exists)\n return { state: 'not-installed', unitPath: null, detail: `no scheduled task named ${name}`, commands: [] }\n if (!info.marked)\n return { state: 'not-installed', unitPath: null, detail: `task ${name} exists but does not carry this plugin's marker; refusing to treat it as this plugin's entry`, commands: [] }\n const state: BootState = bootState(true, true, false)\n return { state, unitPath: null, detail: `scheduled task ${name} is registered (runs at logon, not at boot)`, commands: [] }\n }\n catch (error) {\n return { state: 'not-installed', unitPath: null, detail: errorMessage(error), commands: [] }\n }\n },\n\n async install(spec: BootSpec): Promise<BootActionResult> {\n try {\n validate(spec)\n const name = nameOf(spec)\n const info = await inspect(spec)\n if (info.exists && !info.marked)\n return failed(`scheduled task ${name} already exists and was not written by this plugin; refusing to overwrite it`)\n if (!(await isElevated()))\n return failed('registering a scheduled task needs an elevated process', { needsPrivilege: true })\n\n const elevatedCommands = [\n windowsDisplayCommand('powershell.exe', ['-NoProfile', '-Command', unregisterTaskScript(name)]),\n windowsDisplayCommand('schtasks.exe', ['/Query', '/TN', name, '/XML']),\n ]\n\n if (info.exists && info.matches) {\n const verify = await query(name)\n if (verify.exists)\n return { ok: true, changed: false, detail: `scheduled task ${name} is already registered`, commands: [], needsPrivilege: true }\n }\n\n const cmdlet = await hasRegisterCmdlet()\n if (cmdlet) {\n const script = registerTaskScript(spec)\n const res = await ctx.run('powershell.exe', ['-NoProfile', '-Command', script])\n if (codeOf(res) !== 0)\n return failed(problem(res, windowsDisplayCommand('powershell.exe', ['-NoProfile', '-Command', script])) ?? 'Register-ScheduledTask failed', { needsPrivilege: true, commands: elevatedCommands })\n }\n else {\n const xmlFile = path.join(tempDir(ctx), `${name}.xml`)\n fs.mkdirSync(path.dirname(xmlFile), { recursive: true })\n fs.writeFileSync(xmlFile, Buffer.from(`\\uFEFF${scheduledTaskXml(spec)}`, 'utf16le'))\n const createCommand = windowsDisplayCommand('schtasks.exe', ['/Create', '/TN', name, '/XML', xmlFile, '/F'])\n const create = await ctx.run('schtasks.exe', ['/Create', '/TN', name, '/XML', xmlFile, '/F'])\n if (codeOf(create) !== 0)\n return failed(problem(create, createCommand) ?? 'schtasks /Create failed', { needsPrivilege: true, commands: [createCommand] })\n fs.rmSync(xmlFile, { force: true })\n }\n\n const after = await query(name)\n if (!after.exists)\n return failed(`scheduled task ${name} was not found after registration`, { changed: true, needsPrivilege: true, commands: elevatedCommands })\n\n return {\n ok: true,\n changed: true,\n detail: `scheduled task ${name} registered (runs at logon, not at boot)`,\n commands: [],\n needsPrivilege: true,\n }\n }\n catch (error) {\n return failed(errorMessage(error))\n }\n },\n\n async uninstall(spec: BootSpec): Promise<BootActionResult> {\n try {\n const name = nameOf(spec)\n const info = await inspect(spec)\n if (!info.exists)\n return { ok: true, changed: false, detail: `no scheduled task named ${name}; already gone`, commands: [], needsPrivilege: false }\n if (!info.marked)\n return failed(`scheduled task ${name} is not marked as ours; refusing to delete a foreign task`)\n if (!(await isElevated()))\n return failed('deleting a scheduled task needs an elevated process', { needsPrivilege: true })\n\n const cmdlet = await hasRegisterCmdlet()\n const res = cmdlet\n ? await ctx.run('powershell.exe', ['-NoProfile', '-Command', unregisterTaskScript(name)])\n : await ctx.run('schtasks.exe', ['/Delete', '/TN', name, '/F'])\n const code = codeOf(res)\n if (code !== 0 && code !== 1)\n return failed(problem(res, cmdlet ? 'powershell.exe Unregister-ScheduledTask' : windowsDisplayCommand('schtasks.exe', ['/Delete', '/TN', name, '/F'])) ?? 'unregistering the task failed', { needsPrivilege: true })\n\n const after = await query(name)\n if (after.exists)\n return failed(`scheduled task ${name} still exists after removal`, { changed: true, needsPrivilege: true })\n\n return {\n ok: true,\n changed: true,\n detail: `unregistered scheduled task ${name}`,\n commands: [],\n needsPrivilege: true,\n }\n }\n catch (error) {\n return failed(errorMessage(error))\n }\n },\n }\n}\n\nexport function createWindowsRunProvider(ctx: BootProviderContext): BootProvider {\n return createWindowsRunProviderImpl(ctx)\n}\n", "/**\n * The two terminals of the ladder: a container (an OS boot entry would land\n * outside it, so the right answer is the container's own restart policy) and a\n * platform this plugin has no mechanism for.\n */\n\nimport type { BootCandidate } from '../shared/contracts.js'\nimport type { BootActionResult, BootProvider, BootProviderContext, BootProviderStatus, BootSpec } from './types.js'\nimport { readText } from '../util/fsx.js'\nimport { failed, existsOf } from './common.js'\n\nconst RESTART_POLICY = 'use the container restart policy instead: `docker run --restart unless-stopped`, or `restart: unless-stopped` in a compose file'\n\n/** A human-readable description of the container we are inside, or null. */\nexport function detectContainer(ctx: BootProviderContext): string | null {\n if (existsOf(ctx, '/.dockerenv'))\n return 'Docker (/.dockerenv)'\n if (existsOf(ctx, '/run/.containerenv'))\n return 'Podman (/run/.containerenv)'\n if (ctx.env.container?.trim())\n return `container environment (container=${ctx.env.container.trim()})`\n const cgroup = existsOf(ctx, '/proc/1/cgroup') ? readText('/proc/1/cgroup') : null\n if (cgroup) {\n if (cgroup.includes('kubepods'))\n return 'Kubernetes (cgroup kubepods)'\n if (cgroup.includes('docker'))\n return 'Docker (cgroup docker)'\n if (cgroup.includes('lxc'))\n return 'LXC (cgroup lxc)'\n if (cgroup.includes('containerd'))\n return 'containerd (cgroup)'\n }\n return null\n}\n\nexport function createContainerProvider(ctx: BootProviderContext): BootProvider {\n const mechanism = 'container' as const\n return {\n mechanism,\n\n async detect(): Promise<BootCandidate> {\n const container = detectContainer(ctx)\n return {\n mechanism,\n available: container !== null,\n bootCapable: false,\n privileged: false,\n reason: container === null\n ? 'this process does not look like it is inside a container'\n : `this process runs inside ${container}; an OS boot entry would live on the host, not here`,\n }\n },\n\n async status(): Promise<BootProviderStatus> {\n const container = detectContainer(ctx)\n return {\n state: 'unsupported',\n unitPath: null,\n detail: container === null\n ? 'no container detected'\n : `running inside ${container}; ${RESTART_POLICY}`,\n commands: [],\n }\n },\n\n async install(): Promise<BootActionResult> {\n const container = detectContainer(ctx)\n return failed(\n container === null\n ? `no container detected; ${RESTART_POLICY}`\n : `this process runs inside ${container}; an OS boot entry would be installed outside the container \u2014 ${RESTART_POLICY}`,\n )\n },\n\n async uninstall(): Promise<BootActionResult> {\n return failed('nothing to uninstall: this plugin installed no OS boot entry for a container; the container restart policy is what starts it')\n },\n }\n}\n\nexport function createUnsupportedProvider(platform: NodeJS.Platform): BootProvider {\n const mechanism = 'unsupported' as const\n const reason = `no boot mechanism is known for ${platform}`\n return {\n mechanism,\n\n async detect(): Promise<BootCandidate> {\n return { mechanism, available: true, bootCapable: false, privileged: false, reason }\n },\n\n async status(_spec: BootSpec): Promise<BootProviderStatus> {\n return { state: 'unsupported', unitPath: null, detail: reason, commands: [] }\n },\n\n async install(_spec: BootSpec): Promise<BootActionResult> {\n return failed(`this plugin has no boot mechanism for ${platform}; start home-hosted from your platform's own service manager`)\n },\n\n async uninstall(_spec: BootSpec): Promise<BootActionResult> {\n return failed(`this plugin has no boot mechanism for ${platform}, so it installed nothing to remove`)\n },\n }\n}\n", "/**\n * Writing `servers.config.json` directly, for the case where the panel is not\n * running (no API to call, and nobody watching the file).\n *\n * When the panel *is* running this path is a fallback: its file watcher treats\n * an external edit as a real change, and a newly added `autostart` entry is\n * started at once. `addEntrySafely` therefore writes the entry disabled first\n * and only then flips `autostart`, which the watcher sees as a changed\n * definition \u2014 applied on that entry's next start, never started now.\n */\nimport fs from 'node:fs'\nimport type { ServerEntry, ServerEntryPatch } from '../shared/contracts.js'\nimport { readJson, writeFileAtomic } from '../util/fsx.js'\nimport { configFile } from '../util/paths.js'\n\nexport interface RawConfig {\n meta?: Record<string, unknown>\n servers?: ServerEntry[]\n [key: string]: unknown\n}\n\nexport interface ConfigReadResult {\n raw: RawConfig | null\n exists: boolean\n error: string | null\n}\n\nexport function readConfig(home: string): ConfigReadResult {\n const file = configFile(home)\n const raw = readJson<RawConfig>(file)\n if (raw === null) {\n // Distinguish \"no file yet\" from \"unreadable\", because only the first is safe to create.\n const exists = fs.existsSync(file)\n return { raw: null, exists, error: exists ? 'the config file could not be parsed' : null }\n }\n if (!Array.isArray(raw.servers) && raw.servers !== undefined)\n return { raw: null, exists: true, error: 'the config file has a servers field that is not an array' }\n return { raw, exists: true, error: null }\n}\n\n/**\n * Write the file back with home-hosted's own `meta` contract, which records the\n * release that wrote the file and the shape it wrote.\n *\n * `schema` is never invented here: a file that declared one keeps it, and one\n * that did not stays without it \u2014 home-hosted reads an absent schema as \"the\n * current one\", so stamping our own idea of the schema would one day fail its\n * own guard (\"this release understands schema N\") and stop the panel booting\n * from a file this plugin only patched.\n */\nexport function writeConfig(home: string, raw: RawConfig, writtenBy = 'dsh-home-hosted'): void {\n const meta = { ...(raw.meta ?? {}), writtenBy }\n const next: RawConfig = { ...raw, meta }\n writeFileAtomic(configFile(home), `${JSON.stringify(next, null, 2)}\\n`)\n}\n\nexport function findEntry(raw: RawConfig, id: string): ServerEntry | null {\n return (raw.servers ?? []).find(entry => entry.id === id) ?? null\n}\n\n/** Insert or replace one entry, preserving every other key in the file. */\nexport function upsertEntry(raw: RawConfig, entry: ServerEntry): RawConfig {\n const servers = [...(raw.servers ?? [])]\n const index = servers.findIndex(candidate => candidate.id === entry.id)\n if (index >= 0)\n servers[index] = entry\n else\n servers.push(entry)\n return { ...raw, servers }\n}\n\nexport function patchEntry(raw: RawConfig, id: string, patch: ServerEntryPatch): RawConfig {\n const servers = (raw.servers ?? []).map((entry) => {\n if (entry.id !== id)\n return entry\n const merged: ServerEntry = { ...entry, ...patch }\n if (patch.stop !== undefined && typeof entry.stop === 'object' && entry.stop !== null)\n merged.stop = { ...entry.stop, ...patch.stop }\n return merged\n })\n return { ...raw, servers }\n}\n\n/** Patch the panel's own `control` block (its port, its bind). */\nexport function patchControl(raw: RawConfig, patch: Record<string, unknown>): RawConfig {\n return { ...raw, control: { ...(raw.control ?? {}), ...patch } }\n}\n\nexport function removeEntry(raw: RawConfig, id: string): RawConfig {\n return { ...raw, servers: (raw.servers ?? []).filter(entry => entry.id !== id) }\n}\n", "/**\n * Where things live. The harness home comes from `$DSH_HOME`; home-hosted's\n * state comes from `$HHOSTED_HOME`. Neither is ever hard-coded into a file this\n * plugin writes \u2014 the resolved value is written into generated units instead.\n */\nimport os from 'node:os'\nimport path from 'node:path'\n\nexport function expandHome(value: string): string {\n if (value === '~')\n return os.homedir()\n if (value.startsWith('~/') || value.startsWith('~\\\\'))\n return path.join(os.homedir(), value.slice(2))\n return value\n}\n\n/** DeepSeek Harness home: `$DSH_HOME`, else `~/.dsh`. */\nexport function dshHome(): string {\n const configured = process.env.DSH_HOME?.trim()\n return configured ? path.resolve(expandHome(configured)) : path.join(os.homedir(), '.dsh')\n}\n\n/** home-hosted state root: `$HHOSTED_HOME`, else `~/.home-hosted`. */\nexport function homeHostedHome(): string {\n const configured = process.env.HHOSTED_HOME?.trim()\n return configured ? path.resolve(expandHome(configured)) : path.join(os.homedir(), '.home-hosted')\n}\n\n/** Where this plugin keeps its own durable state (settings, snapshots, token). */\nexport function pluginStateDir(override?: string): string {\n const configured = override?.trim()\n if (configured)\n return path.resolve(expandHome(configured))\n return path.join(dshHome(), 'dsh-home-hosted')\n}\n\n/** home-hosted's own tokens file, written by the panel at startup. */\nexport function runtimeFile(home = homeHostedHome()): string {\n return path.join(home, 'run.json')\n}\n\n/** home-hosted's secrets file (0600): proves whether an API token is enrolled. */\nexport function secretsFile(home = homeHostedHome()): string {\n return path.join(home, '.control-secrets.json')\n}\n\nexport function configFile(home = homeHostedHome()): string {\n return path.join(home, 'servers.config.json')\n}\n", "/**\n * The server entry that represents the running harness.\n *\n * An existing entry is never rewritten: this plugin only owns `autostart`,\n * `onPortConflict` and `stop.killPortHolders`. A generated entry (only used when\n * there is none) mirrors how this process was actually launched where that is\n * knowable, and otherwise falls back to the `dsh web` app arguments.\n */\nimport path from 'node:path'\nimport process from 'node:process'\nimport type { ServerEntry } from '../shared/contracts.js'\nimport type { CliLaunch } from './launch.js'\nimport { resolveShimmedCli, which } from './launch.js'\n\n/**\n * Which profile this process is running.\n *\n * `DSH_PROFILE` alone is not trustworthy: it can be inherited from a parent\n * shell that ran a different profile (that is how an entry once ended up booting\n * `web` under another profile's home). The process's own argv is authoritative,\n * then the profile directory the launcher pointed at, then the env var.\n */\nexport function detectProfile(argv: readonly string[], env: Record<string, string | undefined> = {}): string {\n for (let index = 0; index < argv.length; index += 1) {\n const arg = argv[index]\n if (arg === '--profile' && typeof argv[index + 1] === 'string' && !argv[index + 1]!.startsWith('-'))\n return argv[index + 1]!\n if (arg?.startsWith('--profile='))\n return arg.slice('--profile='.length)\n }\n\n const dir = env.DSH_PROFILE_DIR\n if (typeof dir === 'string' && dir.length > 0) {\n const base = path.basename(dir)\n if (base.length > 0 && base !== '.' && base !== path.sep)\n return base\n }\n\n const app = argv.slice(2).find(candidate => candidate !== undefined && !candidate.startsWith('-'))\n if (app !== undefined && app.length > 0)\n return app\n\n const fromEnv = env.DSH_PROFILE\n return typeof fromEnv === 'string' && fromEnv.length > 0 ? fromEnv : 'web'\n}\n\nexport interface DshFacts {\n id: string\n port: number | null\n host: string\n profile: string | null\n dshHome: string\n launch: CliLaunch | null\n}\n\n/** Where the running harness's own CLI entry is, if we can tell. */\nexport async function resolveDshLaunch(): Promise<CliLaunch | null> {\n const fromArgv = process.argv[1]\n if (typeof fromArgv === 'string' && /\\.[cm]?js$/.test(fromArgv) && path.isAbsolute(fromArgv))\n return { program: process.execPath, args: [fromArgv], cliEntry: fromArgv, shimPath: null, source: 'entry' }\n const found = await which('dsh')\n return found === null ? null : resolveShimmedCli(found, process.execPath)\n}\n\nexport function buildDshEntry(facts: DshFacts): ServerEntry {\n const launch = facts.launch\n const entryArgs = launch?.args ?? []\n const profile = facts.profile === null || facts.profile === undefined ? 'web' : facts.profile\n\n const appArgs: string[] = []\n if (facts.port !== null) {\n appArgs.push(\n '--port', '{port}',\n '--host', '{host}',\n '--no-open',\n '--trusted-host', `localhost:{port}`,\n )\n if (facts.host === '0.0.0.0')\n appArgs.push('--trusted-host', '{lanIp}:{port}')\n }\n\n const launcherArgs = profile === 'web' ? ['web'] : ['--profile', profile]\n const args = [...entryArgs, ...launcherArgs, ...appArgs]\n\n return {\n id: facts.id,\n label: 'DSH web',\n enabled: true,\n autostart: true,\n command: launch?.program ?? 'dsh',\n args,\n bind: facts.host === '0.0.0.0' ? 'lan' : 'local',\n port: facts.port,\n cwd: process.cwd(),\n env: {},\n dataEnvs: { DSH_HOME: facts.dshHome },\n onPortConflict: 'kill',\n stop: { killPortHolders: true },\n health: {\n enabled: true,\n mode: 'http',\n // 401 is normal here: the panel answers the login route when auth is on.\n http: { path: '/', method: 'GET', expectStatusBelow: 500, expectBody: '' },\n },\n }\n}\n", "/**\n * How the home-hosted daemon is launched, and what a boot entry for it contains.\n *\n * The executable is resolved to an absolute program plus argv: a generated boot\n * entry must not depend on a login shell's PATH. When the resolved command is a\n * package-manager shim, its `cmd-shim-target` comment names the real entry, and\n * node runs that directly \u2014 the same guarantee the shim itself gives.\n */\nimport fs from 'node:fs'\nimport path from 'node:path'\nimport process from 'node:process'\nimport type { BootSpec } from '../boot/types.js'\nimport { run } from '../util/exec.js'\nimport { readText } from '../util/fsx.js'\n\nexport interface CliLaunch {\n program: string\n /** Args that must precede the command, e.g. the CLI entry path. */\n args: string[]\n cliEntry: string | null\n shimPath: string | null\n source: 'override' | 'entry' | 'shim-target' | 'shim'\n}\n\nexport async function which(command: string): Promise<string | null> {\n const probe = process.platform === 'win32' ? 'where.exe' : 'which'\n const result = await run(probe, [command], { timeoutMs: 5000 })\n if (result.code !== 0)\n return null\n const first = result.stdout.split(/\\r?\\n/).map(line => line.trim()).filter(Boolean)[0]\n return first ?? null\n}\n\n/** Turn a resolved CLI path into an absolute program + argv. */\nexport function resolveShimmedCli(absolute: string, nodePath = process.execPath): CliLaunch | null {\n if (!fs.existsSync(absolute))\n return null\n if (/\\.(?:mjs|cjs|js)$/.test(absolute))\n return { program: nodePath, args: [absolute], cliEntry: absolute, shimPath: null, source: 'entry' }\n\n const shimTarget = /^#\\s*cmd-shim-target=(.+)$/m.exec(readText(absolute) ?? '')?.[1]?.trim()\n if (shimTarget !== undefined && fs.existsSync(shimTarget))\n return { program: nodePath, args: [shimTarget], cliEntry: shimTarget, shimPath: absolute, source: 'shim-target' }\n\n // A shim with no readable target still works when node is on the entry's PATH.\n return { program: absolute, args: [], cliEntry: null, shimPath: absolute, source: 'shim' }\n}\n\nexport async function resolveHomeHostedLaunch(override?: string | null): Promise<CliLaunch | null> {\n const configured = override?.trim()\n const found = configured && configured.length > 0 ? configured : (await which('home-hosted')) ?? (await which('hh'))\n if (found === null || found === undefined)\n return null\n\n const launch = resolveShimmedCli(path.resolve(found))\n if (launch === null)\n return null\n return configured ? { ...launch, source: 'override' } : launch\n}\n\nexport interface HomeHostedFacts {\n home: string\n projectDir?: string | null\n version?: string | null\n}\n\n/** A deterministic environment for a boot-time entry, with absolute values. */\nexport function homeHostedEnv(facts: HomeHostedFacts, launch: CliLaunch, extra: Record<string, string> = {}): Record<string, string> {\n const dirs = [\n launch.shimPath === null ? null : path.dirname(launch.shimPath),\n path.dirname(process.execPath),\n ...(process.env.PATH ?? '').split(path.delimiter),\n '/usr/local/bin',\n '/usr/bin',\n '/bin',\n ].filter((dir): dir is string => typeof dir === 'string' && dir.length > 0)\n const seen = new Set<string>()\n const pathValue = dirs.filter((dir) => {\n if (seen.has(dir))\n return false\n seen.add(dir)\n return true\n }).join(path.delimiter)\n\n const env: Record<string, string> = {\n PATH: pathValue,\n HOME: process.env.HOME ?? process.env.USERPROFILE ?? '',\n HHOSTED_HOME: facts.home,\n ...extra,\n }\n if (facts.projectDir)\n env.HHOSTED_PROJECT = facts.projectDir\n return env\n}\n\nexport interface BootSpecOptions {\n stateDir: string\n marker?: string\n}\n\nexport function buildHomeHostedBootSpec(\n facts: HomeHostedFacts,\n launch: CliLaunch,\n options: BootSpecOptions,\n): BootSpec {\n const logDir = path.join(facts.home, '.logs')\n fs.mkdirSync(logDir, { recursive: true })\n const args = [...launch.args, 'up', '--foreground', '--home', facts.home]\n if (facts.projectDir)\n args.push('--project', facts.projectDir)\n\n return {\n command: launch.program,\n args,\n cwd: facts.projectDir ?? facts.home,\n env: homeHostedEnv(facts, launch),\n marker: options.marker ?? 'managed by dsh-home-hosted',\n unitName: 'home-hosted',\n label: 'home-hosted control panel',\n logDir,\n }\n}\n", "/**\n * What this plugin decides about a server entry, and how that intent maps onto\n * the entry: only the keys in `OWNED_ENTRY_KEYS` are ever written, so a person's\n * own command, args, env, health block and everything else survive untouched.\n */\nimport type { EntryIntent, OnPortConflict, ServerEntry, ServerEntryPatch } from '../shared/contracts.js'\nimport { isOnPortConflict } from '../shared/contracts.js'\n\n/**\n * A detached restart of dsh is recognisable by its own marker/argv on POSIX, so\n * `follow` adopts it without killing anything. Windows cannot read another\n * process's environment and a `.cmd` shim hides the argv, so only `kill`\n * reliably reclaims the port there.\n */\nexport function defaultOnPortConflict(platform: NodeJS.Platform = process.platform): OnPortConflict {\n return platform === 'win32' ? 'kill' : 'follow'\n}\n\nexport function defaultIntent(id: string, platform: NodeJS.Platform = process.platform): EntryIntent {\n return {\n id,\n autostart: true,\n onPortConflict: defaultOnPortConflict(platform),\n stopKillPortHolders: true,\n persistent: true,\n }\n}\n\n/**\n * The owned keys as a patch, preserving any sibling keys inside `stop`.\n *\n * `persistent` is omitted unless the panel that would parse the write knows the\n * key: an older schema drops it and warns, so writing one is noise at best.\n */\nexport function ownedPatch(intent: EntryIntent, live?: ServerEntry | null, options: { persistent?: boolean } = {}): ServerEntryPatch {\n const stop = (live?.stop ?? {}) as Record<string, unknown>\n return {\n autostart: intent.autostart,\n onPortConflict: intent.onPortConflict,\n ...(options.persistent === false ? {} : { persistent: intent.persistent }),\n stop: { ...stop, killPortHolders: intent.stopKillPortHolders },\n }\n}\n\n/**\n * Owned keys whose live value differs from the intent.\n *\n * The intent keeps what the person asked for; a key the panel cannot parse is\n * not drift, or every entry would report one on an older panel.\n */\nexport function ownedDrift(live: ServerEntry | null, intent: EntryIntent, options: { persistent?: boolean } = {}): string[] {\n if (live === null)\n return ['missing entry']\n const drift: string[] = []\n if (live.autostart !== intent.autostart)\n drift.push('autostart')\n if (live.onPortConflict !== intent.onPortConflict)\n drift.push('onPortConflict')\n if (options.persistent !== false && (live.persistent ?? false) !== intent.persistent)\n drift.push('persistent')\n const killPortHolders = (live.stop as Record<string, unknown> | undefined)?.killPortHolders\n if (killPortHolders !== intent.stopKillPortHolders)\n drift.push('stop.killPortHolders')\n return drift\n}\n\n/**\n * Only the owned keys, as they were before this plugin touched the entry.\n *\n * A key the entry left out is recorded as the panel's schema default rather than\n * omitted: `{ id }` alone is what marks an entry this plugin created, so an\n * adopted entry with nothing explicit has to be distinguishable from it \u2014 or\n * \"stop managing\" deletes a server the person wrote.\n */\nexport function snapshotOwned(live: ServerEntry): ServerEntry {\n const killPortHolders = (live.stop as Record<string, unknown> | undefined)?.killPortHolders\n return {\n id: live.id,\n autostart: typeof live.autostart === 'boolean' ? live.autostart : false,\n onPortConflict: isOnPortConflict(live.onPortConflict) ? live.onPortConflict : 'block',\n persistent: live.persistent === true,\n stop: { killPortHolders: typeof killPortHolders === 'boolean' ? killPortHolders : false },\n }\n}\n\n/**\n * Restore an entry to what it was before adoption. A key the snapshot does not\n * carry was inherited from the panel's defaults, and a PATCH cannot delete a\n * key, so it is restored to that schema default instead.\n */\nexport function restorePatch(live: ServerEntry, snapshot: ServerEntry | null): ServerEntryPatch {\n const stop = (live.stop ?? {}) as Record<string, unknown>\n const previous = (snapshot?.stop ?? {}) as Record<string, unknown>\n return {\n autostart: snapshot?.autostart ?? false,\n onPortConflict: snapshot?.onPortConflict ?? 'block',\n persistent: snapshot?.persistent === true,\n stop: {\n ...stop,\n killPortHolders: typeof previous.killPortHolders === 'boolean' ? previous.killPortHolders : false,\n },\n }\n}\n", "/**\n * Which home-hosted CLI this plugin drives.\n *\n * The plugin ships its own pinned copy as a dependency and prefers it, so the\n * version that runs the panel at boot is the version this plugin was built\n * against \u2014 not whatever `home-hosted` happens to be on PATH. Preferring a\n * global install is a supported setting, not an accident.\n *\n * Resolution order: the operator's `homeHostedCommand` override always wins,\n * then the preferred copy, then the other one as a fallback.\n */\nimport { createRequire } from 'node:module'\nimport fs from 'node:fs'\nimport path from 'node:path'\nimport process from 'node:process'\nimport type { CliCandidate, CliSource, CliStatus } from '../shared/contracts.js'\nimport { run } from '../util/exec.js'\nimport type { CliLaunch } from './launch.js'\nimport { resolveShimmedCli, which } from './launch.js'\n\n/** The range the plugin ships and is tested against. */\nexport const EXPECTED_RANGE = '^0.6.4'\n\n/** Oldest release whose API and config schema this plugin relies on. */\nexport const MIN_SUPPORTED_VERSION = '0.4.1'\n\n/** Oldest release whose config schema accepts `onPortConflict: kill`. */\nexport const MIN_KILL_VERSION = '0.6.0'\n/** `persistent` (the nanny that keeps an entry alive across panel restarts). */\nexport const MIN_PERSISTENT_VERSION = '0.6.3'\n\nexport type CliPreference = 'pinned' | 'global'\n\nexport interface CliResolution {\n launch: CliLaunch | null\n status: CliStatus\n}\n\nexport interface ResolveCliOptions {\n override?: string | null\n /** Which copy to run when both exist. */\n prefer?: CliPreference\n /** Test seam: the pinned package's manifest path, or null when it is not installed. */\n packageManifest?: () => string | null\n /** Test seam: ask a CLI for its own version. */\n readVersion?: (launch: CliLaunch) => Promise<string | null>\n /** Test seam: locate a command on PATH. */\n findOnPath?: (command: string) => Promise<string | null>\n timeoutMs?: number\n}\n\ninterface Candidate {\n candidate: CliCandidate\n launch: CliLaunch\n}\n\n/** Where the pinned `home-hosted` manifest is, resolved from this module. */\nexport function pinnedManifestPath(): string | null {\n try {\n return createRequire(import.meta.url).resolve('home-hosted/package.json')\n }\n catch {\n return null\n }\n}\n\n/** The `home-hosted` bin entry a package manifest declares. */\nexport function binEntryFromManifest(manifestPath: string): string | null {\n try {\n const manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf8')) as { bin?: string | Record<string, string> }\n const declared = typeof manifest.bin === 'string'\n ? manifest.bin\n : manifest.bin?.['home-hosted'] ?? Object.values(manifest.bin ?? {})[0]\n return typeof declared === 'string' && declared.length > 0\n ? path.resolve(path.dirname(manifestPath), declared)\n : null\n }\n catch {\n return null\n }\n}\n\n/** The first `x.y.z[-pre]` in a CLI's output. */\nexport function parseVersion(output: string | null): string | null {\n const match = /(\\d+)\\.(\\d+)\\.(\\d+)(?:-([0-9A-Za-z.-]+))?/.exec(output ?? '')\n return match === null ? null : `${match[1]}.${match[2]}.${match[3]}${match[4] === undefined ? '' : `-${match[4]}`}`\n}\n\n/** Numeric comparison; a prerelease sorts below its own release. */\nexport function compareVersions(a: string, b: string): number {\n const split = (value: string): { parts: number[], pre: string | null } => {\n const [core, pre = null] = value.split('-', 2)\n return { parts: (core ?? '').split('.').map(part => Number.parseInt(part, 10) || 0), pre }\n }\n const left = split(a)\n const right = split(b)\n for (let index = 0; index < 3; index += 1) {\n const diff = (left.parts[index] ?? 0) - (right.parts[index] ?? 0)\n if (diff !== 0)\n return diff < 0 ? -1 : 1\n }\n if (left.pre === right.pre)\n return 0\n if (left.pre === null)\n return 1\n if (right.pre === null)\n return -1\n return left.pre < right.pre ? -1 : 1\n}\n\nfunction detailFor(source: CliSource, version: string | null, supported: boolean, prefer: CliPreference, unusableOverride: string | null = null): string {\n const shown = version ?? 'unknown version'\n switch (source) {\n case 'config':\n return unusableOverride === null\n ? `from the configured command (${shown})`\n : `the configured command could not be used: ${unusableOverride} does not exist (or is not a file this plugin can run); fix homeHostedCommand, or clear it to let the plugin choose`\n case 'dependency':\n return supported\n ? `the pinned dependency (${shown})`\n : `the pinned dependency is below the oldest supported release (${MIN_SUPPORTED_VERSION})`\n case 'path':\n if (!supported)\n return `the global install on PATH (${shown}) is below the oldest supported release (${MIN_SUPPORTED_VERSION})`\n return prefer === 'global'\n ? `the global install on PATH (${shown})`\n : `a global install on PATH (${shown}), not the pinned dependency ${EXPECTED_RANGE}`\n default:\n return 'no home-hosted CLI found: install the plugin with its dependencies, or put home-hosted on PATH'\n }\n}\n\nasync function defaultReadVersion(launch: CliLaunch, timeoutMs: number): Promise<string | null> {\n const result = await run(launch.program, [...launch.args, '--version'], { timeoutMs })\n return parseVersion(result.stdout) ?? parseVersion(result.stderr)\n}\n\nexport async function resolveCli(options: ResolveCliOptions = {}): Promise<CliResolution> {\n const timeoutMs = options.timeoutMs ?? 5000\n const prefer = options.prefer ?? 'pinned'\n const readVersion = options.readVersion ?? (launch => defaultReadVersion(launch, timeoutMs))\n const locate = options.findOnPath ?? which\n\n // 1. An explicit override is not a preference: it is an instruction. An\n // instruction that cannot be carried out is reported, never silently\n // replaced by a copy the operator did not ask for.\n const override = options.override?.trim()\n let unusableOverride: string | null = null\n if (override !== undefined && override.length > 0) {\n const launch = resolveShimmedCli(path.resolve(override))\n if (launch === null) {\n unusableOverride = override\n }\n else {\n const version = await readVersion(launch)\n const supported = version === null || compareVersions(version, MIN_SUPPORTED_VERSION) >= 0\n return {\n launch,\n status: {\n source: 'config',\n path: launch.cliEntry ?? launch.shimPath ?? launch.program,\n version,\n expectedRange: EXPECTED_RANGE,\n supported,\n prefer,\n dependency: null,\n global: null,\n detail: detailFor('config', version, supported, prefer),\n },\n }\n }\n }\n\n // 2. The two copies this plugin knows about.\n const manifest = (options.packageManifest ?? pinnedManifestPath)()\n const dependencyEntry = manifest === null ? null : binEntryFromManifest(manifest)\n let dependency: Candidate | null = null\n if (dependencyEntry !== null && fs.existsSync(dependencyEntry)) {\n let version: string | null = null\n try {\n version = (JSON.parse(fs.readFileSync(manifest as string, 'utf8')) as { version?: string }).version ?? null\n }\n catch {\n version = null\n }\n dependency = {\n candidate: { source: 'dependency', path: dependencyEntry, version },\n launch: { program: process.execPath, args: [dependencyEntry], cliEntry: dependencyEntry, shimPath: null, source: 'entry' },\n }\n }\n\n let global: Candidate | null = null\n const found = (await locate('home-hosted')) ?? (await locate('hh'))\n if (found !== null) {\n const launch = resolveShimmedCli(path.resolve(found))\n if (launch !== null) {\n global = {\n candidate: { source: 'path', path: launch.cliEntry ?? launch.shimPath ?? launch.program, version: await readVersion(launch) },\n launch,\n }\n }\n }\n\n const order = prefer === 'global' ? [global, dependency] : [dependency, global]\n const chosen = order.find(item => item !== null) ?? null\n const dependencySummary = dependency?.candidate ?? null\n const globalSummary = global?.candidate ?? null\n\n if (unusableOverride !== null) {\n return {\n launch: null,\n status: {\n source: 'config',\n path: unusableOverride,\n version: null,\n expectedRange: EXPECTED_RANGE,\n supported: false,\n prefer,\n dependency: dependencySummary,\n global: globalSummary,\n detail: detailFor('config', null, false, prefer, unusableOverride),\n },\n }\n }\n\n if (chosen === null) {\n return {\n launch: null,\n status: {\n source: 'none',\n path: null,\n version: null,\n expectedRange: EXPECTED_RANGE,\n supported: false,\n prefer,\n dependency: dependencySummary,\n global: globalSummary,\n detail: detailFor('none', null, false, prefer),\n },\n }\n }\n\n const version = chosen.candidate.version\n const supported = version === null || compareVersions(version, MIN_SUPPORTED_VERSION) >= 0\n return {\n launch: chosen.launch,\n status: {\n source: chosen.candidate.source,\n path: chosen.candidate.path,\n version,\n expectedRange: EXPECTED_RANGE,\n supported,\n prefer,\n dependency: dependencySummary,\n global: globalSummary,\n detail: detailFor(chosen.candidate.source, version, supported, prefer),\n },\n }\n}\n", "/**\n * A stable launcher for the pinned CLI.\n *\n * A dependency resolves to a pnpm path that carries the version and the peer\n * hash (`\u2026/.pnpm/home-hosted@0.6.1_zod@4.6.5/node_modules/home-hosted/\u2026`), which\n * moves on the next install and disappears when the profile is rebuilt. A boot\n * entry that baked that path in would fail at exactly the moment it exists for.\n *\n * So the plugin generates one small script in its own state directory and points\n * the boot entry at *that*. At boot the launcher finds the pinned copy again\n * (recorded path \u2192 profile node_modules, flat or pnpm) and falls back to PATH,\n * which is why the entry survives plugin upgrades and profile reinstalls.\n */\nimport fs from 'node:fs'\nimport path from 'node:path'\nimport process from 'node:process'\nimport { run } from '../util/exec.js'\nimport { readJson, writeFileAtomic, writeJsonAtomic } from '../util/fsx.js'\nimport { compareVersions, parseVersion } from './resolve.js'\n\nexport interface LauncherOptions {\n stateDir: string\n dshHome: string\n /** Where the pinned copy is right now; recorded as the fast path. */\n resolvedEntry: string | null\n /** The pinned copy's version, recorded for diagnostics. */\n resolvedVersion?: string | null\n /** The plugin's own package root, as a search hint. */\n pluginRoot?: string | null\n minVersion: string\n marker?: string\n}\n\nexport interface LauncherWrite {\n path: string\n changed: boolean\n}\n\ninterface LauncherRecord {\n entry: string | null\n version: string | null\n pluginRoot: string | null\n writtenAt: number\n}\n\nexport function launcherDir(stateDir: string): string {\n return path.join(stateDir, 'bin')\n}\n\nexport function launcherPath(stateDir: string): string {\n return path.join(launcherDir(stateDir), 'home-hosted.mjs')\n}\n\nexport function launcherRecordPath(stateDir: string): string {\n return path.join(launcherDir(stateDir), 'resolved.json')\n}\n\nexport function readLauncherRecord(stateDir: string): LauncherRecord | null {\n return readJson<LauncherRecord>(launcherRecordPath(stateDir))\n}\n\n/** The generated script's source; exported so a test can inspect it. */\nexport function buildLauncherSource(options: LauncherOptions): string {\n const marker = options.marker ?? 'managed by dsh-home-hosted'\n const record = launcherRecordPath(options.stateDir)\n return `#!/usr/bin/env node\n// ${marker} \u2014 rewritten on every plugin start; do not edit.\nimport fs from 'node:fs'\nimport path from 'node:path'\nimport process from 'node:process'\nimport { spawnSync } from 'node:child_process'\n\nconst DSH_HOME = ${JSON.stringify(options.dshHome)}\nconst RECORD = ${JSON.stringify(record)}\nconst MIN_VERSION = ${JSON.stringify(options.minVersion)}\nconst PLUGIN_ROOT = ${JSON.stringify(options.pluginRoot ?? null)}\n\nfunction readRecord() {\n try { return JSON.parse(fs.readFileSync(RECORD, 'utf8')) } catch { return null }\n}\n\nfunction versionOf(entry) {\n let dir = path.dirname(entry)\n for (let hop = 0; hop < 4; hop += 1) {\n try {\n const manifest = JSON.parse(fs.readFileSync(path.join(dir, 'package.json'), 'utf8'))\n if (typeof manifest.version === 'string') return manifest.version\n } catch {}\n dir = path.dirname(dir)\n }\n return null\n}\n\nfunction compare(a, b) {\n const split = value => {\n const [core, pre = null] = String(value).split('-', 2)\n return { parts: core.split('.').map(part => Number.parseInt(part, 10) || 0), pre }\n }\n const left = split(a); const right = split(b)\n for (let i = 0; i < 3; i += 1) {\n const diff = (left.parts[i] ?? 0) - (right.parts[i] ?? 0)\n if (diff !== 0) return diff < 0 ? -1 : 1\n }\n if (left.pre === right.pre) return 0\n if (left.pre === null) return 1\n if (right.pre === null) return -1\n return left.pre < right.pre ? -1 : 1\n}\n\nfunction collect(out, entry) {\n if (typeof entry === 'string' && entry.length > 0 && fs.existsSync(entry)) out.push(entry)\n}\n\nfunction collectRoot(root, out) {\n collect(out, path.join(root, 'node_modules', 'home-hosted', 'bin', 'home-hosted.mjs'))\n const store = path.join(root, 'node_modules', '.pnpm')\n let names = []\n try { names = fs.readdirSync(store) } catch { return }\n for (const name of names) {\n if (name.startsWith('home-hosted@') || name.startsWith('dsh-home-hosted@'))\n collect(out, path.join(store, name, 'node_modules', 'home-hosted', 'bin', 'home-hosted.mjs'))\n }\n}\n\nfunction candidates() {\n const out = []\n const record = readRecord()\n if (record && typeof record.entry === 'string') collect(out, record.entry)\n if (PLUGIN_ROOT !== null) collectRoot(PLUGIN_ROOT, out)\n try {\n for (const name of fs.readdirSync(path.join(DSH_HOME, 'profiles')))\n collectRoot(path.join(DSH_HOME, 'profiles', name), out)\n } catch {}\n collectRoot(path.join(DSH_HOME), out)\n // Last resort: a global install on the entry's own PATH.\n for (const dir of (process.env.PATH ?? '').split(path.delimiter)) {\n if (dir.length === 0) continue\n collect(out, path.join(dir, 'home-hosted'))\n collect(out, path.join(dir, 'home-hosted.cmd'))\n }\n return out\n}\n\nfunction choose() {\n const found = candidates().map(entry => ({ entry, version: versionOf(entry) }))\n const supported = found.filter(item => item.version !== null && compare(item.version, MIN_VERSION) >= 0)\n supported.sort((a, b) => compare(b.version, a.version))\n return (supported[0] ?? found[0] ?? null)?.entry ?? null\n}\n\nconst entry = choose()\nif (entry === null) {\n console.error('[dsh-home-hosted] no home-hosted CLI found (looked in ' + DSH_HOME + ' and PATH). Reinstall the plugin with its dependencies, or set homeHostedCommand in the plugin row.')\n process.exit(1)\n}\n\nconst args = process.argv.slice(2)\nconst isScript = /\\\\.(mjs|cjs|js)$/.test(entry)\nconst result = isScript\n ? spawnSync(process.execPath, [entry, ...args], { stdio: 'inherit' })\n : spawnSync(entry, args, { stdio: 'inherit', shell: process.platform === 'win32' && /\\\\.(cmd|bat)$/i.test(entry) })\nprocess.exit(typeof result.status === 'number' ? result.status : 1)\n`\n}\n\nexport function writeLauncher(options: LauncherOptions): LauncherWrite {\n const file = launcherPath(options.stateDir)\n const source = buildLauncherSource(options)\n const previous = fs.existsSync(file) ? fs.readFileSync(file, 'utf8') : null\n const changed = previous !== source\n if (changed) {\n writeFileAtomic(file, source, 0o755)\n fs.chmodSync(file, 0o755)\n }\n writeJsonAtomic(launcherRecordPath(options.stateDir), {\n entry: options.resolvedEntry,\n version: options.resolvedVersion ?? null,\n pluginRoot: options.pluginRoot ?? null,\n writtenAt: Date.now(),\n } satisfies LauncherRecord, 0o600)\n return { path: file, changed }\n}\n\n/** Run the launcher the way the boot entry will, and read the version it answers. */\nexport async function preflightLauncher(stateDir: string, timeoutMs = 10_000): Promise<string | null> {\n const file = launcherPath(stateDir)\n if (!fs.existsSync(file))\n return null\n const result = process.platform === 'win32'\n ? await run(process.execPath, [file, '--version'], { timeoutMs })\n : await run(file, ['--version'], { timeoutMs })\n return parseVersion(result.stdout) ?? parseVersion(result.stderr)\n}\n\n/** The version a CLI entry belongs to, read from the nearest package.json. */\nexport function versionOfEntry(entry: string): string | null {\n let dir = path.dirname(entry)\n for (let hop = 0; hop < 4; hop += 1) {\n const manifest = readJson<{ version?: string }>(path.join(dir, 'package.json'))\n if (typeof manifest?.version === 'string')\n return manifest.version\n dir = path.dirname(dir)\n }\n return null\n}\n\n/** Candidate entries under one root: a flat install, or a pnpm store. */\nexport function candidatesUnder(root: string): string[] {\n const out: string[] = []\n const direct = path.join(root, 'node_modules', 'home-hosted', 'bin', 'home-hosted.mjs')\n if (fs.existsSync(direct))\n out.push(direct)\n const store = path.join(root, 'node_modules', '.pnpm')\n if (fs.existsSync(store)) {\n for (const name of fs.readdirSync(store)) {\n if (!name.startsWith('home-hosted@') && !name.startsWith('dsh-home-hosted@'))\n continue\n const entry = path.join(store, name, 'node_modules', 'home-hosted', 'bin', 'home-hosted.mjs')\n if (fs.existsSync(entry))\n out.push(entry)\n }\n }\n return out\n}\n\n/** Highest satisfying candidate among explicit roots; exported for tests. */\nexport function findCandidate(roots: string[], minVersion: string): string | null {\n const found = roots.flatMap(root => candidatesUnder(root).map(entry => ({ entry, version: versionOfEntry(entry) })))\n const supported = found.filter(item => item.version !== null && compareVersions(item.version, minVersion) >= 0)\n supported.sort((a, b) => compareVersions(b.version ?? '0.0.0', a.version ?? '0.0.0'))\n return (supported[0] ?? found[0] ?? null)?.entry ?? null\n}\n", "/**\n * Starting, replacing and globally installing the panel.\n *\n * Starting it is the same thing a person does by hand: run the CLI's `up`, which\n * re-spawns itself detached, writes `run.json` and returns once the panel\n * answers. Replacing a panel *is* different \u2014 stopping the one that is answering\n * also stops the servers it supervises, including the dsh this plugin runs in \u2014\n * so the replacement is done by a detached helper that outlives this process.\n */\nimport { spawn } from 'node:child_process'\nimport type { ChildProcess } from 'node:child_process'\nimport fs from 'node:fs'\nimport path from 'node:path'\nimport process from 'node:process'\nimport type { PanelControlResult } from '../shared/contracts.js'\nimport { run } from '../util/exec.js'\nimport { writeFileAtomic } from '../util/fsx.js'\nimport type { CliLaunch } from './launch.js'\nimport { launcherDir } from './launcher.js'\n\nexport interface PanelControlDeps {\n /** The CLI to run, already resolved. */\n launch: CliLaunch | null\n home: string\n projectDir?: string | null\n stateDir: string\n /** Environment for the spawned CLI (absolute PATH, HOME, HHOSTED_HOME). */\n env: Record<string, string>\n timeoutMs?: number\n}\n\nfunction cliArgs(deps: PanelControlDeps, command: 'up' | 'down' | 'restart'): string[] {\n const args = [...(deps.launch?.args ?? []), command, '--home', deps.home]\n if (deps.projectDir)\n args.push('--project', deps.projectDir)\n return args\n}\n\nasync function runCli(deps: PanelControlDeps, command: 'up' | 'down' | 'restart'): Promise<{ code: number | null, stdout: string, stderr: string }> {\n const launch = deps.launch\n if (launch === null)\n return { code: null, stdout: '', stderr: 'no home-hosted CLI is available' }\n return await run(launch.program, cliArgs(deps, command), {\n env: deps.env,\n timeoutMs: deps.timeoutMs ?? 90_000,\n })\n}\n\n/** Start the preferred CLI as a detached panel; the CLI itself does the detaching. */\nexport async function startPanel(deps: PanelControlDeps): Promise<PanelControlResult> {\n const result = await runCli(deps, 'up')\n if (result.code !== 0) {\n const detail = result.stderr.trim() || result.stdout.trim() || `the CLI exited ${String(result.code)}`\n return { ok: false, detail }\n }\n const match = /https?:\\/\\/[^\\s]+/.exec(result.stdout)\n return { ok: true, detail: 'the panel is answering', url: match?.[0] ?? null }\n}\n\nexport function takeoverHelperPath(stateDir: string): string {\n return path.join(launcherDir(stateDir), 'panel-takeover.mjs')\n}\n\nexport function takeoverLogPath(stateDir: string): string {\n return path.join(launcherDir(stateDir), 'panel-takeover.log')\n}\n\n/** The generated helper's source; exported so a test can inspect it. */\nexport function buildTakeoverSource(deps: PanelControlDeps, oldPid: number | null, marker = 'managed by dsh-home-hosted'): string {\n const program = deps.launch?.program ?? process.execPath\n const args = deps.launch === null\n ? []\n : [...deps.launch.args, 'up', '--home', deps.home, ...(deps.projectDir ? ['--project', deps.projectDir] : [])]\n const downArgs = [...(deps.launch?.args ?? []), 'down', '--home', deps.home]\n return `#!/usr/bin/env node\n// ${marker} \u2014 replaces the panel; do not edit.\nimport fs from 'node:fs'\nimport { spawnSync } from 'node:child_process'\n\nconst OLD_PID = ${JSON.stringify(oldPid)}\nconst DOWN_ARGS = ${JSON.stringify(downArgs)}\nconst PROGRAM = ${JSON.stringify(program)}\nconst ARGS = ${JSON.stringify(args)}\nconst ENV = ${JSON.stringify(deps.env)}\nconst LOG = ${JSON.stringify(takeoverLogPath(deps.stateDir))}\n\nfunction log(line) {\n try { fs.appendFileSync(LOG, new Date().toISOString() + ' ' + line + '\\\\n') } catch {}\n}\n\nfunction alive(pid) {\n if (typeof pid !== 'number') return false\n try { process.kill(pid, 0); return true } catch { return false }\n}\n\nconst sleep = ms => new Promise(resolve => setTimeout(resolve, ms))\n\nlog('stopping the answering panel: ' + PROGRAM + ' ' + DOWN_ARGS.join(' '))\nconst down = spawnSync(PROGRAM, DOWN_ARGS, { env: { ...process.env, ...ENV }, stdio: 'ignore' })\nlog('down exited ' + String(down.status))\n\nfor (let i = 0; i < 40 && alive(OLD_PID); i += 1)\n await sleep(250)\n\nif (alive(OLD_PID)) {\n log('still alive; sending SIGTERM')\n try { process.kill(OLD_PID, 'SIGTERM') } catch {}\n for (let i = 0; i < 40 && alive(OLD_PID); i += 1)\n await sleep(250)\n}\n\nif (alive(OLD_PID)) {\n log('still alive; sending SIGKILL')\n try { process.kill(OLD_PID, 'SIGKILL') } catch {}\n for (let i = 0; i < 20 && alive(OLD_PID); i += 1)\n await sleep(250)\n}\n\nlog('starting ' + PROGRAM + ' ' + ARGS.join(' '))\nconst result = spawnSync(PROGRAM, ARGS, { env: { ...process.env, ...ENV }, stdio: 'ignore' })\nlog('started with exit ' + String(result.status))\n`\n}\n\nexport function writeTakeoverHelper(deps: PanelControlDeps, oldPid: number | null): string {\n const file = takeoverHelperPath(deps.stateDir)\n writeFileAtomic(file, buildTakeoverSource(deps, oldPid), 0o755)\n fs.chmodSync(file, 0o755)\n return file\n}\n\n/** Spawn a helper process; injected so a test can drive the failure paths. */\nexport type SpawnDetached = (program: string, args: string[]) => ChildProcess\n\nfunction spawnDetached(program: string, args: string[]): ChildProcess {\n return spawn(program, args, { detached: true, stdio: 'ignore' })\n}\n\n/**\n * Spawn the helper detached and return immediately: the old panel's shutdown is\n * about to stop this very process, so waiting for the result would lose it.\n */\nexport function spawnTakeover(deps: PanelControlDeps, oldPid: number | null, spawnChild: SpawnDetached = spawnDetached): PanelControlResult {\n const helper = writeTakeoverHelper(deps, oldPid)\n let child: ChildProcess\n try {\n child = spawnChild(process.execPath, [helper])\n }\n catch (error) {\n return { ok: false, detail: `could not start the panel-replacement helper: ${error instanceof Error ? error.message : String(error)}` }\n }\n // A detached child reports a failed start asynchronously; an unhandled 'error'\n // event is thrown, and that would end this process instead of the helper's.\n child.on('error', () => {})\n child.unref()\n return {\n ok: true,\n detail: 'replacing the panel now; this page will disconnect and come back under the preferred copy',\n }\n}\n\n/** Install the pinned range globally, so the `global` preference has something to use. */\nexport async function installGlobal(\n range: string,\n options: { pnpm?: boolean, run?: typeof run } = {},\n): Promise<{ ok: boolean, detail: string, output: string }> {\n const execute = options.run ?? run\n const usePnpm = options.pnpm ?? true\n const result = usePnpm\n ? await execute('pnpm', ['add', '-g', `home-hosted@${range}`], { timeoutMs: 300_000 })\n : await execute('npm', ['install', '-g', `home-hosted@${range}`], { timeoutMs: 300_000 })\n const output = `${result.stdout}\\n${result.stderr}`.trim()\n if (result.code !== 0)\n return { ok: false, detail: result.error ?? `the installer exited ${String(result.code)}`, output }\n return { ok: true, detail: `installed home-hosted@${range} globally`, output }\n}\n", "/**\n * The home-hosted HTTP API client.\n *\n * Every call carries the plugin's own API token; the panel verifies it from its\n * secrets file on each request. A write through this client is the safe path:\n * the config store records the bytes it wrote, so the panel's own file watcher\n * never treats the change as an external edit.\n */\nimport type { ServerEntry, ServerEntryPatch, ServerEntryView } from '../shared/contracts.js'\n\nexport class PanelError extends Error {\n constructor(\n message: string,\n readonly code: string,\n readonly status: number | null = null,\n /** The panel's own diagnostic, when it sent one. */\n readonly detail: unknown = undefined,\n ) {\n super(message)\n this.name = 'PanelError'\n }\n}\n\nexport interface PanelClientOptions {\n baseUrl: string\n token: string\n timeoutMs?: number\n}\n\nexport class PanelClient {\n private readonly baseUrl: string\n private readonly token: string\n private readonly timeoutMs: number\n\n constructor(options: PanelClientOptions) {\n this.baseUrl = options.baseUrl.replace(/\\/+$/, '')\n this.token = options.token\n this.timeoutMs = options.timeoutMs ?? 10_000\n }\n\n private async request<T>(method: string, path: string, body?: unknown): Promise<T> {\n let response: Response\n try {\n response = await fetch(`${this.baseUrl}${path}`, {\n method,\n headers: {\n authorization: `Bearer ${this.token}`,\n ...(body === undefined ? {} : { 'content-type': 'application/json' }),\n },\n body: body === undefined ? undefined : JSON.stringify(body),\n signal: AbortSignal.timeout(this.timeoutMs),\n })\n }\n catch (error) {\n throw new PanelError(\n error instanceof Error ? error.message : String(error),\n 'PANEL_UNREACHABLE',\n )\n }\n\n const text = await response.text()\n let parsed: unknown = null\n try {\n parsed = text.length > 0 ? JSON.parse(text) : null\n }\n catch {\n throw new PanelError(`the panel answered ${response.status} with a non-JSON body`, 'PANEL_BAD_RESPONSE', response.status)\n }\n\n if (!response.ok) {\n const record = parsed as { message?: unknown, code?: unknown, detail?: unknown } | null\n const message = typeof record?.message === 'string' ? record.message : `the panel answered ${response.status}`\n const code = typeof record?.code === 'string' ? record.code : 'PANEL_ERROR'\n throw new PanelError(message, code, response.status, record?.detail)\n }\n\n return parsed as T\n }\n\n async listServers(): Promise<ServerEntryView[]> {\n const answer = await this.request<{ servers: ServerEntryView[] }>('GET', '/api/servers')\n return answer.servers\n }\n\n async getServer(id: string): Promise<ServerEntryView> {\n const answer = await this.request<{ server: ServerEntryView }>('GET', `/api/servers/${encodeURIComponent(id)}`)\n return answer.server\n }\n\n async createServer(entry: ServerEntry): Promise<ServerEntryView> {\n const answer = await this.request<{ server: ServerEntryView }>('POST', '/api/servers', entry)\n return answer.server\n }\n\n async updateServer(id: string, patch: ServerEntryPatch): Promise<ServerEntryView> {\n const answer = await this.request<{ server: ServerEntryView }>('PATCH', `/api/servers/${encodeURIComponent(id)}`, patch)\n return answer.server\n }\n\n async deleteServer(id: string): Promise<void> {\n await this.request('DELETE', `/api/servers/${encodeURIComponent(id)}`)\n }\n\n async startServer(id: string): Promise<void> {\n await this.request('POST', `/api/servers/${encodeURIComponent(id)}/start`)\n }\n\n async stopServer(id: string): Promise<void> {\n await this.request('POST', `/api/servers/${encodeURIComponent(id)}/stop`)\n }\n\n async restartServer(id: string): Promise<void> {\n await this.request('POST', `/api/servers/${encodeURIComponent(id)}/restart`)\n }\n\n /** Re-list the port's listeners and stop what is not the panel's own tree. */\n async freePort(id: string): Promise<{ stopped?: number[] }> {\n return await this.request<{ stopped?: number[] }>('POST', `/api/servers/${encodeURIComponent(id)}/free-port`)\n }\n}\n\n/** Prove a token works, without needing any write permission. */\nexport async function verifyToken(baseUrl: string, token: string, timeoutMs = 5000): Promise<boolean> {\n try {\n await new PanelClient({ baseUrl, token, timeoutMs }).listServers()\n return true\n }\n catch {\n return false\n }\n}\n", "/**\n * Facts about the running home-hosted panel, read from the `run.json` it writes\n * at startup. Its token field is deliberately never read: the plugin\n * authenticates with its own enrolled API token instead.\n */\nimport http from 'node:http'\nimport https from 'node:https'\nimport process from 'node:process'\nimport { readJson } from '../util/fsx.js'\nimport { runtimeFile } from '../util/paths.js'\n\nexport interface PanelRuntime {\n version: string\n pid: number\n url: string\n probeUrl?: string\n protocol?: string\n port: number\n bindHost?: string\n projectDir?: string\n dataRoot?: string\n configPath?: string\n logFile?: string\n}\n\nexport function readRuntime(home: string): PanelRuntime | null {\n const raw = readJson<Record<string, unknown>>(runtimeFile(home))\n if (raw === null)\n return null\n const url = typeof raw.url === 'string' ? raw.url : null\n const pid = typeof raw.pid === 'number' ? raw.pid : null\n if (url === null || pid === null)\n return null\n return {\n version: typeof raw.version === 'string' ? raw.version : 'unknown',\n pid,\n url: url.replace(/\\/+$/, ''),\n probeUrl: typeof raw.probeUrl === 'string' ? raw.probeUrl : undefined,\n protocol: typeof raw.protocol === 'string' ? raw.protocol : undefined,\n port: typeof raw.port === 'number' ? raw.port : 0,\n bindHost: typeof raw.bindHost === 'string' ? raw.bindHost : undefined,\n projectDir: typeof raw.projectDir === 'string' ? raw.projectDir : undefined,\n dataRoot: typeof raw.dataRoot === 'string' ? raw.dataRoot : undefined,\n configPath: typeof raw.configPath === 'string' ? raw.configPath : undefined,\n logFile: typeof raw.logFile === 'string' ? raw.logFile : undefined,\n }\n}\n\nexport function pidAlive(pid: number): boolean {\n try {\n process.kill(pid, 0)\n return true\n }\n catch {\n return false\n }\n}\n\n/**\n * Ask the panel's public health route whether it is answering. Uses the raw\n * http/https modules so a self-signed TLS pair answers too.\n */\nexport async function probePanel(url: string, timeoutMs = 2000): Promise<boolean> {\n const target = `${url.replace(/\\/+$/, '')}/healthz`\n return await new Promise<boolean>((resolve) => {\n let settled = false\n const done = (value: boolean): void => {\n if (settled)\n return\n settled = true\n resolve(value)\n }\n\n let parsed: URL\n try {\n parsed = new URL(target)\n }\n catch {\n done(false)\n return\n }\n\n const transport = parsed.protocol === 'https:' ? https : http\n const request = transport.get(\n {\n hostname: parsed.hostname,\n port: parsed.port,\n path: `${parsed.pathname}${parsed.search}`,\n timeout: timeoutMs,\n rejectUnauthorized: false,\n },\n (response) => {\n response.resume()\n done(typeof response.statusCode === 'number')\n },\n )\n request.on('timeout', () => {\n request.destroy()\n done(false)\n })\n request.on('error', () => done(false))\n })\n}\n", "/**\n * The plugin's own credential for the home-hosted panel.\n *\n * home-hosted keeps only the token's hash, so a token this plugin did not\n * create can never be recovered from disk. When none is enrolled, the plugin\n * mints one and hands it to `home-hosted set-token` through `HHOSTED_TOKEN`,\n * which stores the hash and prints nothing. The plaintext lives 0600 under the\n * plugin state directory and is never logged, rendered, or sent to the browser.\n */\nimport { randomBytes } from 'node:crypto'\nimport path from 'node:path'\nimport type { RunResult } from '../util/exec.js'\nimport { readJson, readText, writeFileAtomic } from '../util/fsx.js'\nimport { secretsFile } from '../util/paths.js'\n\nexport type CliExecutor = (args: string[], env: Record<string, string | undefined>) => Promise<RunResult>\n\nexport interface EnsureTokenOptions {\n home: string\n stateDir: string\n exec: CliExecutor\n}\n\nexport interface EnsureTokenResult {\n token: string | null\n /** True when this call created the token. */\n enrolled: boolean\n detail: string\n}\n\nexport function storedTokenPath(stateDir: string): string {\n return path.join(stateDir, 'panel-token')\n}\n\nexport function readStoredToken(stateDir: string): string | null {\n const text = readText(storedTokenPath(stateDir))?.trim()\n return text !== undefined && text.length > 0 ? text : null\n}\n\nexport function storeToken(stateDir: string, token: string): void {\n writeFileAtomic(storedTokenPath(stateDir), `${token}\\n`, 0o600)\n}\n\nexport function generateToken(): string {\n return randomBytes(32).toString('base64url')\n}\n\n/** Whether home-hosted already holds an API token (only its hash is on disk). */\nexport function apiTokenEnrolled(home: string): boolean {\n const secrets = readJson<{ apiToken?: unknown }>(secretsFile(home))\n return secrets !== null && secrets.apiToken !== null && secrets.apiToken !== undefined\n}\n\n/** One in-flight enrolment per state directory, so two callers cannot race. */\nconst inFlight = new Map<string, Promise<EnsureTokenResult>>()\n\nexport async function ensureToken(options: EnsureTokenOptions): Promise<EnsureTokenResult> {\n const key = path.resolve(options.stateDir)\n const pending = inFlight.get(key)\n if (pending !== undefined)\n return await pending\n const attempt = enrollToken(options)\n inFlight.set(key, attempt)\n try {\n return await attempt\n }\n finally {\n inFlight.delete(key)\n }\n}\n\n/**\n * Mint a token when none is enrolled.\n *\n * Two concurrent callers used to mint two tokens: both `set-token` calls land, and\n * the loser's token is the one stored on disk while the panel keeps the winner's\n * hash \u2014 after which the plugin can never authenticate, and never re-enrols,\n * because home-hosted already holds an API token. `ensureToken` serialises them.\n */\nasync function enrollToken(options: EnsureTokenOptions): Promise<EnsureTokenResult> {\n const stored = readStoredToken(options.stateDir)\n if (stored !== null)\n return { token: stored, enrolled: false, detail: 'using the stored panel token' }\n\n if (apiTokenEnrolled(options.home)) {\n return {\n token: null,\n enrolled: false,\n detail: 'home-hosted already has an API token, and this plugin does not have it; '\n + 'run `home-hosted set-token --generate` and store that token, or clear it and re-enable',\n }\n }\n\n const token = generateToken()\n const result = await options.exec(['--home', options.home, 'set-token'], { HHOSTED_TOKEN: token })\n if (result.code !== 0) {\n return {\n token: null,\n enrolled: false,\n detail: `could not enrol an API token: ${result.stderr.trim() || result.stdout.trim() || `exit ${String(result.code)}`}`,\n }\n }\n\n storeToken(options.stateDir, token)\n return { token, enrolled: true, detail: 'enrolled a new panel API token' }\n}\n", "/**\n * The browser half's one entry point.\n *\n * The route is registered on DeepSeek Harness's shared `/api` channel, so the\n * physical carrier has already applied the Host/Origin fence and browser\n * authentication before this handler runs: only the local operator reaches it.\n * Domain failures travel inside the envelope, protocol failures as HTTP status.\n */\nimport type { Context } from '@deepseek-ai/cordis'\nimport type { RpcEndpoint, RpcRequest } from './shared/contracts.js'\nimport { RPC_PATH, RPC_VERSION } from './shared/contracts.js'\nimport type { HomeHostedService } from './service.js'\nimport { HomeHostedError } from './service.js'\n\ninterface FetchRoute {\n path: string\n methods: readonly string[]\n requestBody: 'buffered' | 'streaming'\n fetch: (request: Request) => Promise<Response>\n}\n\ninterface ConnectionLike {\n fetch: { register: (route: FetchRoute) => () => unknown }\n}\n\ninterface ConnectionHost {\n connection: ConnectionLike\n}\n\ninterface LoggerLike {\n warn?: (message: string) => void\n}\n\nfunction answer(endpoint: RpcEndpoint | string, result: unknown): Response {\n return Response.json({ v: RPC_VERSION, endpoint, result })\n}\n\nexport function registerRpc(ctx: Context, service: HomeHostedService): void {\n ctx.inject(['connection'], (scoped) => {\n const connection = (scoped as unknown as ConnectionHost).connection\n if (connection?.fetch?.register === undefined)\n return\n\n scoped.effect(() => {\n let dispose: () => unknown\n try {\n dispose = connection.fetch.register({\n // The exact-route registry is keyed by the full request path, so the\n // `/api` prefix belongs here; the page composes the same URL from\n // API_BASE + RPC_PATH.\n path: `/api${RPC_PATH}`,\n methods: ['POST'],\n requestBody: 'buffered',\n fetch: async (request: Request) => {\n let body: RpcRequest\n try {\n body = await request.json() as RpcRequest\n }\n catch {\n return Response.json({ error: 'the request body is not JSON' }, { status: 400 })\n }\n\n if (body === null || typeof body !== 'object' || body.v !== RPC_VERSION) {\n return Response.json(\n { error: `this page and the host disagree on the protocol version (expected ${String(RPC_VERSION)})` },\n { status: 409 },\n )\n }\n\n try {\n const value = await service.call(body.endpoint, body.payload)\n return answer(body.endpoint, { ok: true, value })\n }\n catch (error) {\n const code = error instanceof HomeHostedError ? error.code : 'INTERNAL'\n const message = error instanceof Error ? error.message : String(error)\n const detail = (error as { detail?: unknown } | null)?.detail\n return answer(body.endpoint, { ok: false, error: { code, message, ...(detail === undefined ? {} : { detail }) } })\n }\n },\n })\n }\n catch (error) {\n // A registration the carrier refuses would otherwise look like a page\n // that silently 404s; say so where an operator can see it.\n const logger = (scoped as unknown as { logger?: LoggerLike }).logger\n logger?.warn?.(`[dsh-home-hosted] could not register ${RPC_PATH}: ${error instanceof Error ? error.message : String(error)}`)\n return () => {}\n }\n\n return () => {\n // A disposer that rejects would otherwise surface as an unhandled\n // rejection, which ends the process on Node 24.\n void Promise.resolve(dispose()).catch(() => {})\n }\n }, 'dsh-home-hosted: rpc route')\n })\n}\n", "import type { Context } from '@deepseek-ai/cordis'\n\n/**\n * dsh web answers an unauthenticated browser with a plain-text 401 line written\n * by the in-box connection plugin. That text is not configurable and no event\n * covers it, so a home-hosted deployment \u2014 which is where this session's log,\n * and with it the tokenised URL, actually lives \u2014 appends where to look.\n *\n * It reaches one internal field, `connection.browserAuth.writeUnauthorized`, and\n * fails soft: if that shape is ever gone, dsh's own text is left untouched.\n */\nexport const STOCK_UNAUTHORIZED = 'dsh web authentication required; reopen the URL printed by dsh web.'\n\n/** The 401 body: dsh's own line, plus where this deployment's log page is. */\nexport function authNoticeBody(logUrl: string | null): string {\n if (logUrl === null)\n return `${STOCK_UNAUTHORIZED}\\n`\n return `${STOCK_UNAUTHORIZED}\\nhome-hosted: the URL with its token is in the dsh log at ${logUrl}. An authentication plugin can sign you in seamlessly instead.\\n`\n}\n\ninterface AuthLike {\n writeUnauthorized?: unknown\n}\n\n/**\n * Wrap the auth object's 401 writer so the body carries the notice.\n * @returns the disposer that puts the original back.\n */\nfunction wrap(auth: { writeUnauthorized: (req: unknown, res: unknown) => void }, logUrlOf: () => string | null): () => void {\n const original = auth.writeUnauthorized.bind(auth)\n auth.writeUnauthorized = (req, res) => {\n const response = res as {\n end?: (...args: unknown[]) => unknown\n once?: (event: string, listener: () => void) => unknown\n writableEnded?: boolean\n }\n const end = response.end\n if (typeof end !== 'function' || response.writableEnded === true) {\n original(req, res)\n return\n }\n\n let restored = false\n const restore = (): void => {\n if (restored) return\n restored = true\n try {\n response.end = end\n }\n catch {\n // a response that refuses the assignment keeps the original writer\n }\n }\n\n try {\n response.end = (...args: unknown[]) => {\n restore()\n const [chunk, ...rest] = args\n let body = chunk\n // Only the untouched stock line is ours to rewrite; an authentication\n // plugin's own page (or the same sentence inside longer text) is left alone.\n if (typeof chunk === 'string' && chunk.trim() === STOCK_UNAUTHORIZED) {\n try {\n body = authNoticeBody(logUrlOf())\n }\n catch {\n body = chunk\n }\n }\n return end.call(response, body, ...rest)\n }\n }\n catch {\n original(req, res)\n return\n }\n\n // A writer that ends later still gets the notice; one that never ends must\n // not leave our wrapper on the response.\n try {\n response.once?.('finish', restore)\n response.once?.('close', restore)\n }\n catch {\n // events are best-effort tidiness, never a reason to lose the 401\n }\n original(req, res)\n }\n return () => {\n auth.writeUnauthorized = original\n }\n}\n\n/**\n * Install the notice once the connection service is up. `logUrlOf` is read per\n * 401, so turning the setting off takes effect without re-installing anything.\n */\nexport function registerAuthNotice(ctx: Context, logUrlOf: () => string | null): void {\n ctx.inject(['connection'], (scoped) => {\n scoped.effect(() => {\n const connection = scoped.get('connection') as { browserAuth?: AuthLike } | undefined\n const auth = connection?.browserAuth\n if (typeof auth?.writeUnauthorized !== 'function')\n return () => {}\n return wrap(auth as { writeUnauthorized: (req: unknown, res: unknown) => void }, logUrlOf)\n }, 'dsh-home-hosted: sign-in notice')\n })\n}\n", "/**\n * The plugin's own settings, kept in a 0600 JSON file under its state directory.\n *\n * These are the things a person toggles; the Cordis row config stays for\n * operator overrides only, so neither surface can silently overwrite the other.\n */\nimport { AGENT_TOOL_NAMES, DEFAULT_SETTINGS, isOnPortConflict } from './shared/contracts.js'\nimport type { AgentToolName, EntryIntent, PluginSettings, SettingsPatch } from './shared/contracts.js'\nimport { SETTINGS_VERSION } from './shared/contracts.js'\nimport { readJson, writeJsonAtomic } from './util/fsx.js'\nimport { defaultIntent } from './home-hosted/entries.js'\n\nfunction knownTool(value: unknown): value is AgentToolName {\n return typeof value === 'string' && (AGENT_TOOL_NAMES as readonly string[]).includes(value)\n}\n\nfunction normalizeIntent(value: Partial<EntryIntent> | null | undefined, fallbackId: string): EntryIntent {\n const base = defaultIntent(typeof value?.id === 'string' && value.id.length > 0 ? value.id : fallbackId)\n return {\n id: base.id,\n autostart: typeof value?.autostart === 'boolean' ? value.autostart : base.autostart,\n // Absent means a stored intent from before persistence existed: it wants it.\n persistent: typeof value?.persistent === 'boolean' ? value.persistent : base.persistent,\n // Only a policy the panel's own schema parses may reach the config it boots from.\n onPortConflict: isOnPortConflict(value?.onPortConflict) ? value.onPortConflict : base.onPortConflict,\n stopKillPortHolders: typeof value?.stopKillPortHolders === 'boolean' ? value.stopKillPortHolders : base.stopKillPortHolders,\n }\n}\n\n/**\n * Tools that were split apart before 0.2.0 and merged since. An allowlist\n * written by an older release lists the old names, and an unknown name is\n * dropped \u2014 which would silently turn every tool off on upgrade.\n */\nconst LEGACY_TOOL_NAMES: Record<string, string> = {\n servers_start: 'servers_lifecycle',\n servers_stop: 'servers_lifecycle',\n servers_restart: 'servers_lifecycle',\n servers_create: 'servers_edit',\n servers_update: 'servers_edit',\n servers_delete: 'servers_edit',\n autostart_install: 'autostart_manage',\n autostart_uninstall: 'autostart_manage',\n}\n\n/** The pair an older release wrote when nobody had chosen anything. */\nfunction isLegacyDefaultAllowlist(names: readonly string[]): boolean {\n return names.length === 2 && names.includes('status') && names.includes('servers_list')\n}\n\nconst BOOT_MECHANISMS: readonly string[] = ['auto', 'systemd-user', 'systemd-system', 'launchd-agent', 'launchd-daemon', 'xdg-autostart', 'windows-run', 'windows-task', 'container', 'unsupported']\n\nfunction isBootMechanism(value: unknown): value is PluginSettings['autostart']['mechanism'] {\n return typeof value === 'string' && BOOT_MECHANISMS.includes(value)\n}\n\nfunction normalize(raw: Partial<PluginSettings> | null, fallbackEntryId: string): PluginSettings {\n const entries = Array.isArray(raw?.entries)\n ? raw.entries.map(intent => normalizeIntent(intent, fallbackEntryId))\n : []\n const declared = Array.isArray(raw?.agentTools?.allow) ? raw.agentTools.allow : null\n // Only a file written before the version stamp needs translating: the release\n // that wrote it named tools this one merged, and dropping those names silently\n // would turn every tool off on upgrade.\n const legacyFile = (typeof raw?.version === 'number' ? raw.version : 1) < SETTINGS_VERSION\n const migrated = declared === null\n ? null\n : [...new Set(declared.map(name => (legacyFile ? LEGACY_TOOL_NAMES[name] ?? name : name)).filter(knownTool))] as AgentToolName[]\n // In a legacy file the old default pair is not a choice, it is what that\n // release wrote for \"unset\".\n const choseNothing = legacyFile && declared !== null && migrated !== null && isLegacyDefaultAllowlist(declared)\n const allow = migrated === null || choseNothing ? [...DEFAULT_SETTINGS.agentTools.allow] : migrated\n const attempt = raw?.autostart?.lastAttempt\n return {\n version: SETTINGS_VERSION,\n autostart: {\n enabled: raw?.autostart?.enabled === true,\n mechanism: isBootMechanism(raw?.autostart?.mechanism) ? raw.autostart.mechanism : 'auto',\n ...(attempt === undefined ? {} : { lastAttempt: attempt }),\n },\n // A pre-0.2.0 file expressed management only by holding an intent for the\n // harness entry; the page's toggle needs the flag it never had.\n manageDsh: raw?.manageDsh === true\n || (legacyFile && entries.some(entry => entry.id === fallbackEntryId)),\n entries,\n panel: {\n // An integer in range, or nothing: the panel's schema rejects anything else,\n // and a value it cannot parse stops it booting at all.\n port: typeof raw?.panel?.port === 'number' && Number.isInteger(raw.panel.port) && raw.panel.port >= 1 && raw.panel.port <= 65535\n ? raw.panel.port\n : null,\n },\n authNotice: raw?.authNotice === undefined ? DEFAULT_SETTINGS.authNotice : raw.authNotice === true,\n uiStyle: raw?.uiStyle === 'compact' ? 'compact' : 'detailed',\n agentTools: {\n // Absent means the default (on), and so does the pair the previous\n // release wrote for it; any other explicit false stays false.\n enabled: choseNothing || raw?.agentTools?.enabled === undefined\n ? DEFAULT_SETTINGS.agentTools.enabled\n : raw.agentTools.enabled === true,\n // Absent means every tool; an explicit empty list means none of them.\n allow,\n },\n cli: {\n prefer: raw?.cli?.prefer === 'global' ? 'global' : 'pinned',\n },\n }\n}\n\nexport class SettingsStore {\n private current: PluginSettings\n private readonly listeners = new Set<(settings: PluginSettings) => void>()\n\n constructor(\n readonly file: string,\n private readonly fallbackEntryId: string,\n ) {\n this.current = normalize(readJson<Partial<PluginSettings>>(file), fallbackEntryId)\n }\n\n get(): PluginSettings {\n return this.current\n }\n\n /** The intent for an entry, materialising the default when it has none yet. */\n intentFor(id: string): EntryIntent {\n return this.current.entries.find(entry => entry.id === id) ?? defaultIntent(id)\n }\n\n update(patch: SettingsPatch): PluginSettings {\n const next = normalize({\n // A patch is not a legacy file: the migration belongs to reading one.\n version: SETTINGS_VERSION,\n autostart: { ...this.current.autostart, ...(patch.autostart ?? {}) },\n manageDsh: patch.manageDsh ?? this.current.manageDsh,\n entries: patch.entries ?? this.current.entries,\n panel: { ...this.current.panel, ...(patch.panel ?? {}) },\n authNotice: patch.authNotice ?? this.current.authNotice,\n uiStyle: patch.uiStyle ?? this.current.uiStyle,\n agentTools: { ...this.current.agentTools, ...(patch.agentTools ?? {}) },\n cli: { ...this.current.cli, ...(patch.cli ?? {}) },\n }, this.fallbackEntryId)\n this.current = next\n writeJsonAtomic(this.file, next, 0o600)\n for (const listener of this.listeners)\n listener(next)\n return next\n }\n\n onChange(listener: (settings: PluginSettings) => void): () => void {\n this.listeners.add(listener)\n return () => {\n this.listeners.delete(listener)\n }\n }\n}\n", "/**\n * Agent tools, on by default and allowlisted by name.\n *\n * The list is read at registration time and re-read whenever the settings file\n * changes, so toggling a tool takes effect without a restart. A tool that\n * changes something asks the approval service only when the calling session is\n * not already `danger-full-access` \u2014 the session has then granted exactly what\n * the tool would be asking about, and asking anyway is what makes a\n * Full-access run fail against an auto-rejecting approval channel.\n */\nimport type { Context } from '@deepseek-ai/cordis'\nimport type { ParameterSchemaSpec } from '@deepseek-ai/dsh-tools'\nimport { defineTool } from '@deepseek-ai/dsh-tools'\nimport type { AgentToolName, RpcEndpoint, UiAction } from './shared/contracts.js'\nimport { MUTATING_AGENT_TOOLS } from './shared/contracts.js'\nimport type { HomeHostedService } from './service.js'\nimport type { SettingsStore } from './settings.js'\n\ninterface ApprovalLike {\n request: (request: { agent: unknown, toolName: string, reason?: string }) => Promise<string>\n}\n\ninterface SandboxPolicyLike {\n resolve?: (input: { session?: unknown }) => { mode?: string } | undefined\n}\n\n/** The calling session's file-sandbox mode, or null when nothing can report it. */\nfunction sandboxMode(ctx: Context, exec: unknown): string | null {\n const policy = ctx.get('sandboxPolicy') as SandboxPolicyLike | undefined\n if (policy?.resolve === undefined)\n return null\n const session = (exec as { agent?: { session?: unknown } } | undefined)?.agent?.session\n try {\n return policy.resolve({ ...(session === undefined ? {} : { session }) })?.mode ?? null\n }\n catch {\n return null\n }\n}\n\ntype Input = Record<string, unknown>\n\nfunction stringArg(input: Input, key: string): string | null {\n const value = input[key]\n return typeof value === 'string' && value.trim().length > 0 ? value.trim() : null\n}\n\nfunction jsonArg(input: Input, key: string): Record<string, unknown> | null {\n const value = input[key]\n return typeof value === 'object' && value !== null && !Array.isArray(value) ? value as Record<string, unknown> : null\n}\n\ninterface ToolSpec {\n description: string\n parameters: ParameterSchemaSpec\n /** The endpoint call this tool performs, after its own argument handling. */\n run: (input: Input) => { endpoint: RpcEndpoint, payload: unknown }\n}\n\nconst TOOL_SPECS: Record<AgentToolName, ToolSpec> = {\n status: {\n description: 'Report the home-hosted panel state, its boot-autostart entry, and the entries this plugin manages.',\n parameters: {},\n run: () => ({ endpoint: 'status', payload: {} }),\n },\n servers_list: {\n description: 'List every server home-hosted supervises, with status, pid and url.',\n parameters: {},\n run: () => ({ endpoint: 'servers.list', payload: {} }),\n },\n servers_lifecycle: {\n description: 'Start, stop or restart a server supervised by home-hosted. Restarting the entry this session runs as ends the session.',\n parameters: {\n action: { type: 'string', required: true, description: 'start, stop or restart' },\n id: { type: 'string', required: true, description: 'Server entry id' },\n },\n run: (input) => {\n const action = stringArg(input, 'action')\n if (action !== 'start' && action !== 'stop' && action !== 'restart')\n throw new Error('action must be start, stop or restart')\n const id = stringArg(input, 'id')\n if (id === null)\n throw new Error('id is required')\n return { endpoint: `servers.${action}` as RpcEndpoint, payload: { id } }\n },\n },\n servers_edit: {\n description: 'Create, update or delete a home-hosted server entry. Delete is refused for the entry this session runs as.',\n parameters: {\n action: { type: 'string', required: true, description: 'create, update or delete' },\n id: { type: 'string', description: 'Server entry id (update, delete)' },\n entry: { type: 'json', description: 'A full home-hosted server entry, including its id and command (create)' },\n patch: { type: 'json', description: 'Fields to change (update)' },\n },\n run: (input) => {\n const action = stringArg(input, 'action')\n if (action === 'create') {\n const entry = jsonArg(input, 'entry')\n if (entry === null)\n throw new Error('entry is required to create a server')\n return { endpoint: 'servers.create', payload: { entry } }\n }\n if (action === 'update') {\n const id = stringArg(input, 'id')\n const patch = jsonArg(input, 'patch')\n if (id === null || patch === null)\n throw new Error('id and patch are required to update a server')\n return { endpoint: 'servers.update', payload: { id, patch } }\n }\n if (action === 'delete') {\n const id = stringArg(input, 'id')\n if (id === null)\n throw new Error('id is required to delete a server')\n return { endpoint: 'servers.delete', payload: { id } }\n }\n throw new Error('action must be create, update or delete')\n },\n },\n autostart_manage: {\n description: 'Install or remove the OS entry that starts home-hosted at boot or login.',\n parameters: {\n action: { type: 'string', required: true, description: 'install or uninstall' },\n mechanism: { type: 'string', description: 'Explicit mechanism, e.g. launchd-daemon or systemd-system; omit to use the plugin setting' },\n },\n run: (input) => {\n const action = stringArg(input, 'action')\n if (action !== 'install' && action !== 'uninstall')\n throw new Error('action must be install or uninstall')\n const mechanism = stringArg(input, 'mechanism')\n return { endpoint: `boot.${action}` as RpcEndpoint, payload: mechanism === null ? {} : { mechanism } }\n },\n },\n ui_manage: {\n description: 'Inspect or change the home-hosted panel\\'s own web UI: status, update, revert to stock, or switch to a local zip.',\n parameters: {\n action: { type: 'string', required: true, description: 'status, update, revert or switch' },\n file: { type: 'string', description: 'Absolute path to a UI zip (switch)' },\n },\n run: (input) => {\n const action = stringArg(input, 'action')\n if (action !== 'status' && action !== 'update' && action !== 'revert' && action !== 'switch')\n throw new Error('action must be status, update, revert or switch')\n const file = stringArg(input, 'file')\n return { endpoint: 'ui.manage', payload: { action: action as UiAction, ...(file === null ? {} : { file }) } }\n },\n },\n}\n\nexport function toolNameFor(name: AgentToolName): string {\n return `home_hosted_${name}`\n}\n\n/**\n * Actions of an otherwise mutating tool that only read. `ui_manage` carries both,\n * and a status call must not be blocked (or prompted for) as if it changed the UI.\n */\nconst READ_ONLY_ACTIONS: Partial<Record<AgentToolName, (input: Input) => boolean>> = {\n ui_manage: input => stringArg(input, 'action') === 'status',\n}\n\nfunction registerOne(ctx: Context, service: HomeHostedService, name: AgentToolName): () => void {\n const spec = TOOL_SPECS[name]\n const toolName = toolNameFor(name)\n const mutatingTool = MUTATING_AGENT_TOOLS.includes(name)\n\n return ctx.tools.register(defineTool({\n name: toolName,\n description: spec.description,\n parameters: spec.parameters,\n output: {\n schema: { type: 'string' },\n render: (_args, value) => [{ type: 'text', text: value }],\n },\n async execute(args, exec) {\n const input = (args ?? {}) as Input\n const mode = sandboxMode(ctx, exec)\n // Fail closed: only a positively identified read-only action skips the gate,\n // and an unknown action still asks.\n const mutating = mutatingTool && !(READ_ONLY_ACTIONS[name]?.(input) ?? false)\n if (mutating && mode !== 'danger-full-access') {\n const remedy = 'Set the session to Full access (danger-full-access), or use a session where approvals can be answered.'\n const approval = ctx.get('approval') as ApprovalLike | undefined\n if (approval?.request === undefined)\n return `refused: this session runs in ${mode ?? 'an unknown'} sandbox and the deployment has no approval service. ${remedy}`\n const outcome = await approval.request({\n agent: (exec as { agent?: unknown } | undefined)?.agent,\n toolName,\n reason: `${spec.description} (${JSON.stringify(input)})`,\n })\n if (outcome !== 'allowed-once')\n return `refused: approval answered \"${outcome}\" (session sandbox: ${mode ?? 'unknown'}). ${remedy}`\n }\n\n try {\n const { endpoint, payload } = spec.run(input)\n return JSON.stringify(await service.call(endpoint, payload), null, 2)\n }\n catch (error) {\n return `failed: ${error instanceof Error ? error.message : String(error)}`\n }\n },\n }))\n}\n\nexport function registerAgentTools(ctx: Context, service: HomeHostedService, settings: SettingsStore): void {\n ctx.inject(['tools'], (scoped) => {\n const disposers: Array<() => void> = []\n\n const sync = (): void => {\n while (disposers.length > 0)\n disposers.pop()?.()\n const current = settings.get()\n if (!current.agentTools.enabled)\n return\n for (const name of current.agentTools.allow) {\n try {\n disposers.push(registerOne(scoped, service, name))\n }\n catch {\n // one unruly tool must not keep the rest of the allowlist off the model\n }\n }\n }\n\n scoped.effect(() => {\n sync()\n const off = settings.onChange(sync)\n return () => {\n off()\n while (disposers.length > 0)\n disposers.pop()?.()\n }\n }, 'dsh-home-hosted: agent tools')\n })\n}\n"],
5
- "mappings": "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",
6
- "names": ["path", "fs", "path", "process", "os", "process", "fs", "path", "process", "process", "fs", "path", "fs", "name", "name", "run", "fs", "fs", "path", "validate", "path", "codeOf", "problem", "run", "fs", "fs", "path", "validate", "fs", "path", "fs", "path", "validate", "codeOf", "problem", "run", "name", "path", "fs", "payload", "process", "os", "candidate", "status", "provider", "fs", "os", "path", "fs", "path", "process", "fs", "path", "process", "process", "fs", "path", "process", "fs", "path", "process", "fs", "path", "process", "fs", "path", "version", "supported", "process", "fs", "path", "process", "path", "fs", "process", "spawn", "fs", "path", "process", "path", "process", "fs", "spawn", "path", "answer", "process", "process", "path", "path", "path", "process", "entry", "fs", "cliArgs", "name", "name", "path"]
3
+ "sources": ["../src/index.ts", "../src/config.ts", "../src/shared/contracts.ts", "../src/service.ts", "../src/boot/ladder.ts", "../src/util/exec.ts", "../src/boot/common.ts", "../src/util/fsx.ts", "../src/boot/systemd.ts", "../src/boot/escape.ts", "../src/boot/launchd.ts", "../src/boot/xdg.ts", "../src/boot/windows.ts", "../src/boot/fallback.ts", "../src/home-hosted/config-file.ts", "../src/util/paths.ts", "../src/home-hosted/dsh-entry.ts", "../src/home-hosted/launch.ts", "../src/home-hosted/resolve.ts", "../src/home-hosted/launcher.ts", "../src/home-hosted/entries.ts", "../src/home-hosted/panel-control.ts", "../src/home-hosted/panel.ts", "../src/home-hosted/runtime.ts", "../src/home-hosted/token.ts", "../src/rpc.ts", "../src/home-hosted/web-notice.ts", "../src/settings.ts", "../src/tools.ts"],
4
+ "sourcesContent": ["/**\n * `dsh-home-hosted` \u2014 boot autostart for the home-hosted panel, and home-hosted\n * server management, from inside DeepSeek Harness.\n *\n * The plugin supplies no server entries of its own: everything it manages is\n * declared by the person using the page, and nothing here knows a blessed id\n * beyond the one it is told to treat as the running harness.\n */\nimport type { Context } from '@deepseek-ai/cordis'\nimport path from 'node:path'\nimport { Config } from './config.js'\nimport type { Config as ConfigShape } from './config.js'\nimport { registerRpc } from './rpc.js'\nimport { HomeHostedService } from './service.js'\nimport { registerAuthNotice } from './home-hosted/web-notice.js'\nimport { SettingsStore } from './settings.js'\nimport { registerAgentTools } from './tools.js'\nimport { ensureDir } from './util/fsx.js'\nimport { homeHostedHome, pluginStateDir } from './util/paths.js'\n\nexport const name = 'dsh-home-hosted'\n\nexport { Config }\n\nexport const inject: string[] = []\n\nexport function apply(ctx: Context, config?: ConfigShape): void {\n const resolved: ConfigShape = {\n stateDir: config?.stateDir,\n homeHostedCommand: config?.homeHostedCommand,\n defaultEntryId: config?.defaultEntryId ?? 'dsh',\n }\n\n const stateDir = pluginStateDir(resolved.stateDir)\n ensureDir(stateDir, 0o700)\n\n const settings = new SettingsStore(path.join(stateDir, 'settings.json'), resolved.defaultEntryId)\n const service = new HomeHostedService(ctx, {\n home: homeHostedHome(),\n stateDir,\n homeHostedCommand: resolved.homeHostedCommand,\n defaultEntryId: resolved.defaultEntryId,\n settings,\n })\n\n registerRpc(ctx, service)\n registerAgentTools(ctx, service, settings)\n // Read per 401, so the setting takes effect without re-installing the wrapper.\n registerAuthNotice(ctx, () => (settings.get().authNotice ? service.panelLogUrl() : null))\n\n // Re-assert an enabled boot entry shortly after startup: a node or CLI upgrade\n // moves the paths a unit was written with, and the fix is to rewrite it.\n ctx.effect(() => {\n const timer = setTimeout(() => {\n void service.reconcile().catch(() => {\n // the page reads the resulting status; a failed repair is not a startup failure\n })\n }, 5000)\n return () => clearTimeout(timer)\n }, 'dsh-home-hosted: startup reconcile')\n}\n", "/**\n * The Cordis row configuration: operator overrides only. Everything a person\n * changes in the plugin's own page lives in `settings.json` under the plugin\n * state directory, so the two never fight over the same field.\n */\nimport z from '@deepseek-ai/schemastery'\n\nexport interface Config {\n /** Override the plugin state directory (defaults to `$DSH_HOME/dsh-home-hosted`). */\n stateDir?: string\n /** Override the home-hosted executable used in generated boot entries. */\n homeHostedCommand?: string\n /** The entry this plugin manages for the running harness. */\n defaultEntryId: string\n}\n\nexport const Config: z<Config> = z.object({\n stateDir: z.string().description('Plugin state directory; defaults to $DSH_HOME/dsh-home-hosted'),\n homeHostedCommand: z.string().description('home-hosted executable to put in a generated autostart entry'),\n defaultEntryId: z.string().default('dsh').description('Server entry id used for the running harness'),\n})\n", "/**\n * The one wire contract shared by the host half and the browser half.\n *\n * Nothing here may import a Node builtin: the browser bundle includes this\n * module verbatim.\n */\n\n/** Exact Fetch route registered on DeepSeek Harness's authenticated `/api` channel. */\nexport const RPC_PATH = '/home-hosted'\n\n/** Bumped when a payload shape changes; a mismatch is reported, never guessed at. */\nexport const RPC_VERSION = 1\n\nexport interface RpcError {\n code: string\n message: string\n detail?: unknown\n}\n\nexport type Envelope<T> = { ok: true, value: T } | { ok: false, error: RpcError }\n\n/** Endpoints the browser and the agent tools both speak. */\nexport type RpcEndpoint =\n | 'status'\n | 'servers.list'\n | 'servers.get'\n | 'servers.create'\n | 'servers.update'\n | 'servers.delete'\n | 'servers.start'\n | 'servers.stop'\n | 'servers.restart'\n | 'servers.freePort'\n | 'entries.apply'\n | 'entries.remove'\n | 'entries.restore'\n | 'boot.install'\n | 'boot.uninstall'\n | 'boot.verify'\n | 'panel.start'\n | 'panel.takeover'\n | 'panel.reclaimToken'\n | 'cli.installGlobal'\n | 'ui.manage'\n | 'settings.update'\n\n/** A settings write sends only the changed subtree; the host merges group by group. */\nexport interface SettingsPatch {\n autostart?: Partial<PluginSettings['autostart']>\n manageDsh?: boolean\n entries?: PluginSettings['entries']\n panel?: Partial<PluginSettings['panel']>\n authNotice?: boolean\n reclaimToken?: boolean\n uiStyle?: UiStyle\n agentTools?: Partial<PluginSettings['agentTools']>\n cli?: Partial<PluginSettings['cli']>\n}\n\nexport interface EndpointPayloads {\n /** `refresh` is accepted and ignored: every status call re-reads live state. */\n 'status': { refresh?: boolean }\n 'servers.list': Record<string, never>\n 'servers.get': { id: string }\n 'servers.create': { entry: ServerEntry }\n 'servers.update': { id: string, patch: ServerEntryPatch }\n 'servers.delete': { id: string }\n 'servers.start': { id: string }\n 'servers.stop': { id: string }\n 'servers.restart': { id: string }\n 'servers.freePort': { id: string }\n 'entries.apply': { intents: EntryIntent[] }\n /** Stop managing an entry: restore what it was, or remove it when we created it. */\n 'entries.remove': { id: string }\n 'entries.restore': { id: string }\n 'boot.install': { mechanism?: BootMechanism }\n 'boot.uninstall': { mechanism?: BootMechanism }\n 'boot.verify': Record<string, never>\n /** Start the preferred CLI as a detached panel; refused while one already answers. */\n 'panel.start': Record<string, never>\n /** Stop the answering panel and start the preferred copy instead. */\n 'panel.takeover': { force?: boolean }\n /**\n * Mint a fresh panel API token and enrol it, replacing one the panel refuses.\n * Clearing first is what makes it work when home-hosted already holds a hash.\n */\n 'panel.reclaimToken': Record<string, never>\n /** Install the pinned range as a global CLI, so the `global` preference can use it. */\n 'cli.installGlobal': Record<string, never>\n /** Drive the panel's own UI: status, update, revert, or switch to a local build. */\n 'ui.manage': { action: UiAction, file?: string }\n 'settings.update': { patch: SettingsPatch }\n}\n\nexport interface RpcRequest {\n v: number\n endpoint: RpcEndpoint\n payload?: unknown\n}\n\n// ---------------------------------------------------------------------------\n// Server entries\n// ---------------------------------------------------------------------------\n\nexport type OnPortConflict = 'block' | 'warn' | 'follow' | 'reclaim' | 'kill'\n\n/** Every policy home-hosted's config schema accepts; anything else stops it booting. */\nexport const ON_PORT_CONFLICT_POLICIES: readonly OnPortConflict[] = ['block', 'warn', 'follow', 'reclaim', 'kill']\n\nexport function isOnPortConflict(value: unknown): value is OnPortConflict {\n return typeof value === 'string' && (ON_PORT_CONFLICT_POLICIES as readonly string[]).includes(value)\n}\n\n/** Only the fields this plugin reads or writes are typed; the rest is preserved. */\nexport interface ServerEntry {\n id: string\n label?: string\n enabled?: boolean\n autostart?: boolean\n command?: string\n args?: string[]\n cwd?: string\n env?: Record<string, string>\n dataEnvs?: Record<string, string>\n port?: number | null\n bind?: string\n onPortConflict?: OnPortConflict\n stop?: { killPortHolders?: boolean, [key: string]: unknown }\n health?: Record<string, unknown>\n restart?: Record<string, unknown>\n [key: string]: unknown\n}\n\nexport type ServerEntryPatch = Partial<ServerEntry>\n\n/** What the plugin decides about one entry, and the keys it therefore owns. */\nexport interface EntryIntent {\n id: string\n /**\n * Run under home-hosted's nanny, so stopping or restarting the *panel* leaves\n * this process alive. Needs home-hosted 0.6.3.\n */\n persistent: boolean\n autostart: boolean\n onPortConflict: OnPortConflict\n stopKillPortHolders: boolean\n}\n\n/** Keys an intent owns: a patch touches these and nothing else. */\nexport const OWNED_ENTRY_KEYS = ['autostart', 'onPortConflict', 'persistent', 'stop'] as const\n\nexport interface ServerEntryView {\n id: string\n status: string\n pid: number | null\n url: string | null\n config: ServerEntry\n}\n\nexport interface ManagedEntryStatus {\n intent: EntryIntent\n exists: boolean\n /** True once the plugin has adopted the entry and holds a snapshot of what it was. */\n managed: boolean\n /** Owned keys whose live value differs from the intent. */\n drift: string[]\n live: ServerEntryView | null\n snapshot: ServerEntry | null\n}\n\n// ---------------------------------------------------------------------------\n// Panel\n// ---------------------------------------------------------------------------\n\n/**\n * `enrolled` \u2014 the plugin holds a token; `present` \u2014 home-hosted has one this\n * plugin does not hold; `absent` \u2014 none exists yet; `stale` \u2014 the plugin holds\n * one the panel just refused; `unknown` \u2014 the panel was not reachable to ask.\n */\nexport type TokenState = 'enrolled' | 'present' | 'absent' | 'stale' | 'unknown'\n\nexport interface PanelStatus {\n /** `$HHOSTED_HOME` this plugin resolved, whether or not the panel answers. */\n home: string\n reachable: boolean\n /** The port the panel's own config holds (what a restart would use). */\n configPort?: number | null\n url: string | null\n version: string | null\n pid: number | null\n /** How writes are authenticated right now. */\n writeVia: 'api' | 'file' | 'none'\n token: TokenState\n /** True when the panel was asked and accepted the token, so `token` is measured, not assumed. */\n tokenVerified?: boolean\n detail: string\n}\n\n/** Which home-hosted CLI the plugin drives, and where it came from. */\nexport type CliSource = 'config' | 'dependency' | 'path' | 'none'\n\n/** One place a CLI could come from, with the version found there. */\nexport interface CliCandidate {\n source: 'config' | 'dependency' | 'path'\n path: string | null\n version: string | null\n}\n\nexport type UiAction = 'status' | 'update' | 'revert' | 'switch'\n\nexport interface UiResult {\n ok: boolean\n detail: string\n /** The active UI, when the action reported or changed one. */\n ui?: { name: string | null, version: string | null, repo?: string | null, tag?: string | null } | null\n output?: string\n}\n\nexport interface PanelControlResult {\n ok: boolean\n detail: string\n url?: string | null\n version?: string | null\n}\n\nexport interface CliStatus {\n /** `config` (operator override), `dependency` (the pinned copy), `path`, or none. */\n source: CliSource\n path: string | null\n version: string | null\n /** The range the plugin ships in its own dependencies. */\n expectedRange: string\n /** False when the resolved CLI is older than the oldest release this plugin supports. */\n supported: boolean\n /** The stable launcher a boot entry runs instead of a moving node_modules path. */\n launcherPath?: string | null\n /** What the launcher answers right now, as the boot entry would invoke it. */\n launcherVersion?: string | null\n /** Which copy the plugin prefers. */\n prefer?: 'pinned' | 'global'\n /** The plugin's own copy, when it resolves. */\n dependency?: CliCandidate | null\n /** The global install on PATH, when there is one. */\n global?: CliCandidate | null\n detail: string\n}\n\n// ---------------------------------------------------------------------------\n// Boot autostart\n// ---------------------------------------------------------------------------\n\nexport type BootMechanism =\n | 'systemd-user'\n | 'systemd-system'\n | 'xdg-autostart'\n | 'launchd-agent'\n | 'launchd-daemon'\n | 'windows-run'\n | 'windows-task'\n | 'container'\n | 'unsupported'\n\nexport type BootState =\n | 'not-installed'\n | 'installed-disabled'\n | 'enabled-running'\n | 'enabled-failing'\n | 'unsupported'\n\nexport interface BootCandidate {\n mechanism: BootMechanism\n available: boolean\n /** Starts before an interactive login. */\n bootCapable: boolean\n /** This process can drive it without an elevation prompt. */\n privileged: boolean\n reason: string\n}\n\nexport interface BootStatus {\n platform: 'linux' | 'darwin' | 'win32' | 'other'\n mechanism: BootMechanism | null\n recommended: BootMechanism | null\n state: BootState\n bootCapable: boolean\n privileged: boolean\n unitPath: string | null\n /** Exact commands a person can run when this process cannot elevate. */\n commands: string[]\n detail: string\n candidates: BootCandidate[]\n}\n\n// ---------------------------------------------------------------------------\n// Plugin settings (UI-managed, persisted outside the Cordis config)\n// ---------------------------------------------------------------------------\n\nexport type AgentToolName =\n | 'status'\n | 'servers_list'\n | 'servers_lifecycle'\n | 'servers_edit'\n | 'autostart_manage'\n | 'ui_manage'\n\nexport const AGENT_TOOL_NAMES: readonly AgentToolName[] = [\n 'status',\n 'servers_list',\n 'servers_lifecycle',\n 'servers_edit',\n 'autostart_manage',\n 'ui_manage',\n]\n\n/**\n * Tools that change something. They ask for approval only when the calling\n * session is not already `danger-full-access`.\n */\nexport const MUTATING_AGENT_TOOLS: readonly AgentToolName[] = [\n 'servers_lifecycle',\n 'servers_edit',\n 'autostart_manage',\n 'ui_manage',\n]\n\n/** The shape this release writes; a file without it was written by 0.1.x. */\nexport const SETTINGS_VERSION = 2\n\nexport type UiStyle = 'detailed' | 'compact'\n\nexport interface PluginSettings {\n version: number\n autostart: {\n enabled: boolean\n /** `auto` picks the best available mechanism; an explicit one is honoured only when available. */\n mechanism: 'auto' | BootMechanism\n /** The last install/uninstall attempt, kept so a failure survives a reload. */\n lastAttempt?: BootAttempt\n }\n /** Manage the running harness as a home-hosted entry. */\n manageDsh: boolean\n entries: EntryIntent[]\n agentTools: {\n enabled: boolean\n allow: AgentToolName[]\n }\n /** Port the panel should listen on; `null` keeps whatever the config holds. */\n panel: {\n port: number | null\n }\n /** Point dsh web's sign-in page at the panel log that holds the tokenised URL. */\n authNotice: boolean\n /**\n * When the panel refuses the plugin's API token, re-enrol one on the spot\n * instead of failing the call. On by default: a token that went stale (someone\n * cleared it, or minted their own) should not keep an agent tool from working.\n */\n reclaimToken: boolean\n /** `detailed` shows cards and open disclosures; `compact` folds both away. */\n uiStyle: UiStyle\n cli: {\n /** `pinned` runs the copy this plugin ships; `global` runs the one on PATH. */\n prefer: 'pinned' | 'global'\n }\n}\n\nexport interface BootAttempt {\n ok: boolean\n /** `install` or `uninstall`. */\n action: 'install' | 'uninstall'\n mechanism: BootMechanism | null\n detail: string\n /** The exact commands a person can run when the attempt needed privilege. */\n commands: string[]\n at: number\n}\n\nexport const DEFAULT_SETTINGS: PluginSettings = {\n version: SETTINGS_VERSION,\n autostart: { enabled: false, mechanism: 'auto' },\n manageDsh: false,\n entries: [],\n // Every tool on by default; the session's own permission mode is what gates them.\n agentTools: { enabled: true, allow: [...AGENT_TOOL_NAMES] },\n panel: { port: null },\n authNotice: true,\n reclaimToken: true,\n uiStyle: 'detailed',\n cli: { prefer: 'pinned' },\n}\n\nexport interface HomeHostedStatus {\n /** The entry id this plugin manages; the page must not assume \"dsh\". */\n defaultEntryId: string\n panel: PanelStatus\n boot: BootStatus\n entries: ManagedEntryStatus[]\n servers: ServerEntryView[]\n settings: PluginSettings\n /** The CLI the plugin drives; absent only from a host older than this field. */\n cli?: CliStatus\n /** Set when the panel could not be reached, so the UI can show a degraded page. */\n lastError: string | null\n}\n", "/**\n * The one implementation behind both surfaces: the browser page and the agent\n * tools call the same endpoints, so they cannot drift apart.\n *\n * Writes prefer the panel API (the store ignores its own writes, so nothing is\n * restarted behind the user's back) and fall back to an atomic config-file write\n * only when the panel is not answering.\n */\nimport { Service, type Context } from '@deepseek-ai/cordis'\nimport fs from 'node:fs'\nimport path from 'node:path'\nimport process from 'node:process'\nimport { fileURLToPath } from 'node:url'\nimport type { BootMechanism, BootStatus, EntryIntent, HomeHostedStatus, ManagedEntryStatus, PanelControlResult, PanelStatus, RpcEndpoint, ServerEntry, ServerEntryPatch, ServerEntryView, UiAction, UiResult } from './shared/contracts.js'\nimport { isOnPortConflict, ON_PORT_CONFLICT_POLICIES } from './shared/contracts.js'\nimport type { BootSpec } from './boot/types.js'\nimport { createBootLadder } from './boot/index.js'\nimport { findEntry, patchControl, patchEntry, readConfig, removeEntry as removeConfigEntry, upsertEntry, writeConfig } from './home-hosted/config-file.js'\nimport { buildDshEntry, detectProfile, launcherRepair, needsLauncherRepair, resolveDshLaunch } from './home-hosted/dsh-entry.js'\nimport type { DshLaunch } from './home-hosted/dsh-entry.js'\nimport { defaultIntent, ownedDrift, ownedPatch, restorePatch, snapshotOwned } from './home-hosted/entries.js'\nimport { buildHomeHostedBootSpec, homeHostedEnv } from './home-hosted/launch.js'\nimport type { CliResolution } from './home-hosted/resolve.js'\nimport { compareVersions, EXPECTED_RANGE, MIN_KILL_VERSION, MIN_PERSISTENT_VERSION, MIN_SUPPORTED_VERSION, resolveCli } from './home-hosted/resolve.js'\nimport { preflightLauncher, writeLauncher } from './home-hosted/launcher.js'\nimport type { PanelControlDeps } from './home-hosted/panel-control.js'\nimport { installGlobal, spawnTakeover, startPanel as startPanelProcess } from './home-hosted/panel-control.js'\nimport { PanelClient, PanelError, probeToken, verifyToken } from './home-hosted/panel.js'\nimport { readRuntime, probePanel, pidAlive } from './home-hosted/runtime.js'\nimport { apiTokenEnrolled, ensureToken, readStoredToken, reclaimToken } from './home-hosted/token.js'\nimport type { SettingsStore } from './settings.js'\nimport { dshHome } from './util/paths.js'\nimport type { RunResult } from './util/exec.js'\nimport { run } from './util/exec.js'\nimport { readJson, writeJsonAtomic } from './util/fsx.js'\n\nconst ENTRY_ID_PATTERN = /^[a-z0-9][a-z0-9_-]*$/\n\n/** A token probe is an auxiliary fact, not a user action: never let it stall a poll. */\nconst TOKEN_PROBE_TIMEOUT_MS = 3000\n\n/** How often a deleted managed entry may be put back from the status read. */\nconst ENTRY_RECOVERY_INTERVAL_MS = 30_000\n\n/** This plugin's own package root, used as a search hint for the pinned CLI. */\nfunction pluginRoot(): string | null {\n try {\n return path.dirname(path.dirname(fileURLToPath(import.meta.url)))\n }\n catch {\n return null\n }\n}\n\n/** What a boot install/uninstall answers with; mirrors the boot module's shape. */\nexport interface BootInstallResult {\n ok: boolean\n changed: boolean\n detail: string\n commands: string[]\n needsPrivilege: boolean\n /** Present on install; an uninstall names no mechanism. */\n mechanism?: BootMechanism | null\n status: BootStatus\n}\n\n/** The subset of the boot ladder this service uses. */\nexport interface BootLadderLike {\n status: (spec: BootSpec, mechanism?: BootMechanism) => Promise<BootStatus>\n install: (spec: BootSpec, mechanism?: BootMechanism) => Promise<BootInstallResult>\n uninstall: (spec: BootSpec, mechanism?: BootMechanism) => Promise<BootInstallResult>\n}\n\nexport class HomeHostedError extends Error {\n constructor(message: string, readonly code: string) {\n super(message)\n this.name = 'HomeHostedError'\n }\n}\n\nexport interface HomeHostedServiceOptions {\n home: string\n stateDir: string\n homeHostedCommand?: string\n defaultEntryId: string\n settings: SettingsStore\n /** Test seam: run the home-hosted CLI without spawning it. */\n execCli?: (args: string[], env: Record<string, string | undefined>) => Promise<RunResult>\n /** Test seam: supply the boot ladder instead of probing the real OS. */\n createLadder?: () => BootLadderLike\n /** Test seam: resolve the running harness instead of reading this process. */\n resolveDsh?: (options: { dshHome: string, stateDir: string }) => Promise<DshLaunch | null>\n}\n\ninterface CachedClient {\n client: PanelClient\n until: number\n}\n\ninterface LiveEntry {\n view: ServerEntryView\n config: ServerEntry\n}\n\nexport class HomeHostedService extends Service {\n private clientCache: CachedClient | null = null\n /** The last token this service proved against a panel, so a poll does not re-probe it. */\n private tokenProof: { url: string, token: string, until: number } | null = null\n private tokenDetail = ''\n /** When a missing managed entry was last put back, so a poll cannot become a write loop. */\n private entryRecoveryAt = 0\n private readonly snapshotsFile: string\n\n constructor(ctx: Context, private readonly options: HomeHostedServiceOptions) {\n super(ctx, 'homeHosted')\n this.snapshotsFile = path.join(options.stateDir, 'snapshots.json')\n }\n\n private async resolveDsh(dshHome: string): Promise<DshLaunch | null> {\n return await (this.options.resolveDsh ?? (options => resolveDshLaunch(options)))({\n dshHome,\n stateDir: this.options.stateDir,\n })\n }\n\n // -------------------------------------------------------------------------\n // Facts\n // -------------------------------------------------------------------------\n\n private runtime() {\n return readRuntime(this.options.home)\n }\n\n /** The entry id this very process was started as, when the panel supervises us. */\n selfEntryId(): string | null {\n const id = process.env.HHOSTED_SERVER_ID\n return id !== undefined && id.length > 0 ? id : null\n }\n\n /** What the config's `meta.writtenBy` names: the panel release when we can read it. */\n private writtenBy(): string {\n return this.runtime()?.version ?? 'dsh-home-hosted'\n }\n\n private webServer(): { port: number | null, host: string } {\n const service = this.ctx.get('webServer') as { port?: unknown, host?: unknown } | undefined\n const port = typeof service?.port === 'number' ? service.port : null\n const host = typeof service?.host === 'string' ? service.host : '127.0.0.1'\n return { port, host }\n }\n\n private cliCache: { prefer: 'pinned' | 'global', resolution: CliResolution, launcher: string | null, launcherVersion: string | null, until: number } | null = null\n\n /**\n * Resolve the preferred CLI, refresh the stable launcher a boot entry runs, and\n * preflight that launcher the same way the entry will invoke it.\n */\n private async cli(): Promise<{ resolution: CliResolution, launcher: string | null, launcherVersion: string | null }> {\n const prefer = this.options.settings.get().cli.prefer\n if (this.cliCache !== null && this.cliCache.until > Date.now() && this.cliCache.prefer === prefer)\n return this.cliCache\n const resolution = await resolveCli({ override: this.options.homeHostedCommand, prefer })\n let launcher: string | null = null\n let launcherVersion: string | null = null\n if (resolution.launch !== null) {\n launcher = writeLauncher({\n stateDir: this.options.stateDir,\n dshHome: dshHome(),\n resolvedEntry: resolution.launch.cliEntry ?? resolution.launch.shimPath ?? null,\n resolvedVersion: resolution.status.version,\n pluginRoot: pluginRoot(),\n minVersion: MIN_SUPPORTED_VERSION,\n }).path\n launcherVersion = await preflightLauncher(this.options.stateDir)\n }\n this.cliCache = { prefer, resolution, launcher, launcherVersion, until: Date.now() + 60_000 }\n return this.cliCache\n }\n\n private async panelControlDeps(): Promise<PanelControlDeps> {\n const { resolution } = await this.cli()\n const launch = resolution.launch\n const projectDir = process.env.HHOSTED_PROJECT ?? this.runtime()?.projectDir ?? null\n return {\n launch,\n home: this.options.home,\n projectDir,\n stateDir: this.options.stateDir,\n env: launch === null ? {} : homeHostedEnv({ home: this.options.home, projectDir }, launch),\n }\n }\n\n private async cliExec(args: string[], env: Record<string, string | undefined>) {\n if (this.options.execCli !== undefined)\n return await this.options.execCli(args, env)\n const { resolution } = await this.cli()\n const launch = resolution.launch\n if (launch === null)\n throw new HomeHostedError(resolution.status.detail, 'CLI_NOT_FOUND')\n return await run(launch.program, [...launch.args, ...args], { env, timeoutMs: 30_000 })\n }\n\n // -------------------------------------------------------------------------\n // Panel\n // -------------------------------------------------------------------------\n\n /** The panel page showing this session's log, where its tokenised URL is. */\n panelLogUrl(): string | null {\n const url = this.runtime()?.url\n if (url === undefined || url.length === 0)\n return null\n return `${url.replace(/\\/+$/, '')}/logs?server=${encodeURIComponent(this.options.defaultEntryId)}`\n }\n\n /** The port the panel's config holds, without touching a running panel. */\n private configuredPort(): number | null {\n const control = readConfig(this.options.home).raw?.control as { port?: unknown } | undefined\n return typeof control?.port === 'number' ? control.port : null\n }\n\n /** Write the chosen panel port into the state the panel boots from. */\n private applyPanelPort(): void {\n const port = this.options.settings.get().panel.port\n if (port === null || port === this.configuredPort())\n return\n const read = readConfig(this.options.home)\n if (read.error !== null)\n throw new HomeHostedError(read.error, 'CONFIG_UNREADABLE')\n writeConfig(this.options.home, patchControl(read.raw ?? {}, { port }), this.writtenBy())\n }\n\n /** Whether this exact token was already proved against this exact panel. */\n private tokenProven(url: string, token: string): boolean {\n return this.tokenProof !== null && this.tokenProof.until > Date.now()\n && this.tokenProof.url === url && this.tokenProof.token === token\n }\n\n private proveToken(url: string, token: string): void {\n this.tokenProof = { url, token, until: Date.now() + 30_000 }\n }\n\n async panelStatus(): Promise<PanelStatus> {\n const runtime = this.runtime()\n const stored = readStoredToken(this.options.stateDir)\n const enrolledOnDisk = apiTokenEnrolled(this.options.home)\n const reachable = runtime !== null && (pidAlive(runtime.pid) || await probePanel(runtime.url))\n const answered = runtime !== null && await probePanel(runtime.url)\n\n // The token state is measured, not assumed: when the panel answers, the\n // plugin's own token is proved against it. A refusal is `stale`; a panel\n // that would not answer the API call leaves the state `unknown` rather than\n // claiming a measurement that was never taken.\n let token: PanelStatus['token'] = 'unknown'\n let tokenVerified = false\n if (answered) {\n if (stored === null) {\n token = enrolledOnDisk ? 'present' : 'absent'\n }\n else if (this.tokenProven(runtime.url, stored)) {\n token = 'enrolled'\n tokenVerified = true\n }\n else {\n const probe = await probeToken(runtime.url, stored, TOKEN_PROBE_TIMEOUT_MS)\n if (probe === 'ok') {\n token = 'enrolled'\n tokenVerified = true\n this.proveToken(runtime.url, stored)\n }\n else if (probe === 'refused') {\n token = 'stale'\n tokenVerified = true\n }\n }\n }\n\n // A token the panel refuses is not a write path, however present it is on disk.\n const writeVia: PanelStatus['writeVia'] = token === 'enrolled' ? 'api' : 'file'\n\n return {\n home: this.options.home,\n reachable: answered,\n configPort: this.configuredPort(),\n url: runtime?.url ?? null,\n version: runtime?.version ?? null,\n pid: runtime?.pid ?? null,\n writeVia,\n token,\n tokenVerified,\n detail: answered\n ? (token === 'enrolled'\n ? (this.tokenDetail || 'the panel is answering and this plugin holds a token')\n : token === 'stale'\n ? 'the panel refused this plugin\\'s API token, so writes go straight to servers.config.json; regenerate the token'\n : token === 'present'\n ? 'the panel is answering, but home-hosted already holds an API token this plugin does not have'\n : token === 'absent'\n ? 'the panel is answering but no API token is enrolled for it yet; writes go to servers.config.json until one is'\n : 'the panel answered, but the plugin\\'s token could not be checked')\n : (runtime === null\n ? 'no run.json: the panel is not running, so entries are written straight to servers.config.json'\n : token === 'present' || token === 'stale'\n ? 'the panel process is up but does not answer with this plugin\\'s API token, so this page cannot reach it'\n : 'the panel process is alive but is not answering'),\n }\n }\n\n /**\n * Replace the panel's API token with a fresh one and prove it.\n *\n * home-hosted keeps only a hash, so a token this plugin does not hold cannot\n * be recovered: a new token replaces the old hash in one CLI write, and it is\n * proved against the answering panel before being reported.\n *\n * The panel is not required to be *answering*: a missing or refused token is a\n * common reason it cannot be reached at all, and refusing the repair for that\n * reason would leave no way out from the page. Only a panel that was never\n * started is refused \u2014 there is nothing to enrol a token against yet.\n */\n async reclaimPanelToken(): Promise<HomeHostedStatus> {\n const runtime = this.runtime()\n if (runtime === null) {\n throw new HomeHostedError(\n 'the panel has not been started, so there is nothing to enrol a token against; start it first',\n 'PANEL_UNAVAILABLE',\n )\n }\n const answering = await probePanel(runtime.url)\n\n const result = await reclaimToken({\n home: this.options.home,\n stateDir: this.options.stateDir,\n exec: (args, env) => this.cliExec(args, env),\n })\n // Whatever happened, nothing cached was built from the token in play now.\n this.clientCache = null\n this.tokenProof = null\n this.tokenDetail = result.detail\n if (result.token === null)\n throw new HomeHostedError(result.detail, 'TOKEN_RECLAIM_FAILED')\n\n if (!answering) {\n // Enrolled, but there is nothing to hand it to yet. The page says so\n // instead of claiming a verification it could not take.\n this.tokenDetail = `${result.detail}; the panel is not answering, so it could not be proved yet`\n return await this.status()\n }\n\n const probe = await probeToken(runtime.url, result.token, TOKEN_PROBE_TIMEOUT_MS)\n if (probe !== 'ok') {\n throw new HomeHostedError(\n probe === 'refused'\n ? 'a fresh token was enrolled, but the panel refused it; check the panel log before trying again'\n : 'a fresh token was enrolled, but the panel stopped answering before it could be verified',\n 'TOKEN_RECLAIM_UNVERIFIED',\n )\n }\n this.proveToken(runtime.url, result.token)\n return await this.status()\n }\n\n private async tryClient(): Promise<PanelClient | null> {\n if (this.clientCache !== null && this.clientCache.until > Date.now())\n return this.clientCache.client\n const runtime = this.runtime()\n if (runtime === null || !(await probePanel(runtime.url)))\n return null\n\n const ensured = await ensureToken({\n home: this.options.home,\n stateDir: this.options.stateDir,\n exec: (args, env) => this.cliExec(args, env),\n })\n this.tokenDetail = ensured.detail\n if (ensured.token === null)\n return null\n if (!(await verifyToken(runtime.url, ensured.token)))\n return null\n\n const client = new PanelClient({ baseUrl: runtime.url, token: ensured.token })\n this.clientCache = { client, until: Date.now() + 30_000 }\n this.proveToken(runtime.url, ensured.token)\n return client\n }\n\n private async requireClient(): Promise<PanelClient> {\n const client = await this.tryClient()\n if (client === null) {\n const status = await this.panelStatus()\n throw new HomeHostedError(status.detail, 'PANEL_UNAVAILABLE')\n }\n return client\n }\n\n // -------------------------------------------------------------------------\n // Snapshot bookkeeping\n // -------------------------------------------------------------------------\n\n private snapshots(): Record<string, ServerEntry> {\n return readJson<Record<string, ServerEntry>>(this.snapshotsFile) ?? {}\n }\n\n private saveSnapshots(snapshots: Record<string, ServerEntry>): void {\n writeJsonAtomic(this.snapshotsFile, snapshots, 0o600)\n }\n\n // -------------------------------------------------------------------------\n // Entries\n // -------------------------------------------------------------------------\n\n private async liveEntries(): Promise<Map<string, LiveEntry>> {\n const map = new Map<string, LiveEntry>()\n const client = await this.tryClient()\n if (client !== null) {\n try {\n for (const view of await client.listServers())\n map.set(view.id, { view, config: view.config })\n return map\n }\n catch {\n // fall through to the file, which is still the best available truth\n }\n }\n const read = readConfig(this.options.home)\n for (const entry of read.raw?.servers ?? [])\n map.set(entry.id, { view: { id: entry.id, status: 'unknown', pid: null, url: null, config: entry }, config: entry })\n return map\n }\n\n private async createEntry(intent: EntryIntent, patch: ServerEntryPatch): Promise<ServerEntry | null> {\n if (intent.id !== this.options.defaultEntryId)\n return null\n const harnessHome = process.env.DSH_HOME ?? dshHome()\n // State dir and harness home are the plugin's own, not the defaults: an\n // override has to point the launcher at the same place everything else is.\n const dsh = await this.resolveDsh(harnessHome)\n const { port, host } = this.webServer()\n const generated = buildDshEntry({\n id: intent.id,\n port,\n host,\n profile: detectProfile(process.argv, process.env),\n dshHome: harnessHome,\n launch: dsh,\n launcherPath: dsh?.launcherPath ?? null,\n })\n return { ...generated, ...patch }\n }\n\n /**\n * An entry written before the launcher existed still runs a clone's build\n * output directly. Point it at the stable launcher, or the fix would only\n * ever apply to freshly created entries \u2014 the plugin never rewrites an\n * existing entry's command.\n */\n private async dshCommandRepair(live: ServerEntry | null): Promise<{ command: string, args: string[] } | null> {\n if (live === null || !needsLauncherRepair(live))\n return null\n const harnessHome = process.env.DSH_HOME ?? dshHome()\n const dsh = await this.resolveDsh(harnessHome)\n return launcherRepair(live, dsh)\n }\n\n private async writeOwned(intent: EntryIntent): Promise<void> {\n const live = (await this.liveEntries()).get(intent.id) ?? null\n const snapshots = this.snapshots()\n if (snapshots[intent.id] === undefined) {\n snapshots[intent.id] = live === null ? { id: intent.id } : snapshotOwned(live.config)\n this.saveSnapshots(snapshots)\n }\n\n const patch = ownedPatch(intent, live?.config ?? null, { persistent: await this.supportsPersistent() })\n const repair = intent.id === this.options.defaultEntryId ? await this.dshCommandRepair(live?.config ?? null) : null\n const client = await this.tryClient()\n if (client !== null) {\n if (live !== null) {\n await client.updateServer(intent.id, { ...patch, ...(repair ?? {}) })\n return\n }\n const entry = await this.createEntry(intent, patch)\n if (entry === null) {\n throw new HomeHostedError(\n `no server \"${intent.id}\" exists; create it first, then this plugin can adopt its autostart and conflict policy`,\n 'ENTRY_MISSING',\n )\n }\n await client.createServer(entry)\n return\n }\n\n const read = readConfig(this.options.home)\n if (read.error !== null)\n throw new HomeHostedError(read.error, 'CONFIG_UNREADABLE')\n let raw = read.raw ?? {}\n if (findEntry(raw, intent.id) !== null) {\n writeConfig(this.options.home, patchEntry(raw, intent.id, { ...patch, ...(repair ?? {}) }), this.writtenBy())\n return\n }\n\n const entry = await this.createEntry(intent, patch)\n if (entry === null)\n throw new HomeHostedError(`no server \"${intent.id}\" exists in ${this.options.home}/servers.config.json`, 'ENTRY_MISSING')\n\n // While a panel is running, an external write is a real change and a newly\n // added autostart entry would be started at once. Adding it disabled and\n // flipping autostart in a second write makes that a changed definition\n // instead, which only takes effect at that entry's next start.\n if (await this.panelRunning()) {\n writeConfig(this.options.home, upsertEntry(raw, { ...entry, autostart: false }), this.writtenBy())\n raw = readConfig(this.options.home).raw ?? raw\n writeConfig(this.options.home, patchEntry(raw, intent.id, { autostart: intent.autostart }), this.writtenBy())\n return\n }\n\n writeConfig(this.options.home, upsertEntry(raw, entry), this.writtenBy())\n }\n\n private async panelRunning(): Promise<boolean> {\n const runtime = this.runtime()\n return runtime !== null && (pidAlive(runtime.pid) || await probePanel(runtime.url))\n }\n\n /**\n * The version whose schema will parse what we write: the answering panel, or\n * the CLI that will parse it next. `kill` did not exist before 0.6.0, and an\n * older panel refuses to *boot* with it \u2014 so this is checked before any write.\n */\n private async configVersion(): Promise<string | null> {\n const runtime = this.runtime()\n if (runtime !== null && runtime.version !== null && (pidAlive(runtime.pid) || await probePanel(runtime.url)))\n return runtime.version\n const { resolution } = await this.cli()\n return resolution.status.version\n }\n\n /** Whether the panel whose schema parses our write knows `persistent`. */\n private async supportsPersistent(): Promise<boolean> {\n const version = await this.configVersion()\n return version !== null && compareVersions(version, MIN_PERSISTENT_VERSION) >= 0\n }\n\n private async assertPolicySupported(intent: EntryIntent): Promise<void> {\n if (intent.onPortConflict !== 'kill')\n return\n const version = await this.configVersion()\n if (version === null || compareVersions(version, MIN_KILL_VERSION) >= 0)\n return\n const { resolution } = await this.cli()\n throw new HomeHostedError(\n `the home-hosted that would parse this config is ${version}, which has no \"kill\" policy `\n + `(added in ${MIN_KILL_VERSION}); replace it with ${resolution.status.version ?? 'the pinned copy'} from this page, `\n + 'or set the entry\\'s on-port-conflict policy to block',\n 'KILL_UNSUPPORTED',\n )\n }\n\n private async applyIntents(intents: EntryIntent[]): Promise<ManagedEntryStatus[]> {\n for (const raw of intents) {\n if (!ENTRY_ID_PATTERN.test(raw.id))\n throw new HomeHostedError(`\"${raw.id}\" is not a valid server id`, 'INVALID_ID')\n const requested: unknown = raw.onPortConflict\n if (requested !== undefined && requested !== null && !isOnPortConflict(requested))\n throw new HomeHostedError(\n `\"${String(requested)}\" is not a port-conflict policy; use one of ${ON_PORT_CONFLICT_POLICIES.join(', ')}`,\n 'INVALID_POLICY',\n )\n const fallback = defaultIntent(raw.id)\n const intent: EntryIntent = {\n id: raw.id,\n autostart: raw.autostart === true,\n onPortConflict: isOnPortConflict(requested) ? requested : fallback.onPortConflict,\n stopKillPortHolders: raw.stopKillPortHolders ?? fallback.stopKillPortHolders,\n persistent: raw.persistent ?? fallback.persistent,\n }\n await this.assertPolicySupported(intent)\n await this.writeOwned(intent)\n const current = this.options.settings.get()\n const entries = current.entries.filter(entry => entry.id !== intent.id)\n entries.push(intent)\n this.options.settings.update({\n // The page's toggle reads this flag, so managing the harness has to record\n // itself; restoring or removing that entry clears it again. A paused intent\n // (`autostart: false`) is not management, or the toggle could never go off.\n ...(intent.id === this.options.defaultEntryId ? { manageDsh: intent.autostart } : {}),\n entries,\n })\n }\n return await this.entriesStatus()\n }\n\n /**\n * Stop managing an entry: restore what it was when we only adopted it, or\n * remove it when this plugin created it. Removing an entry the panel\n * supervises stops that process \u2014 which may be this session.\n */\n private async removeManagedEntry(id: string): Promise<ManagedEntryStatus[]> {\n const snapshots = this.snapshots()\n const snapshot = snapshots[id]\n const adopted = snapshot !== undefined && Object.keys(snapshot).some(key => key !== 'id')\n if (adopted)\n return await this.restoreEntry(id)\n\n // Deleting this entry stops the process running this session, and nothing\n // would start it again \u2014 so \"stop managing\" pauses it instead: the entry\n // stays, it is simply no longer started for us.\n if (id === this.selfEntryId())\n return await this.pauseManagedEntry(id)\n\n const client = await this.tryClient()\n if (client !== null) {\n try {\n await client.deleteServer(id)\n }\n catch (error) {\n // Already gone is the outcome we wanted.\n const missing = error instanceof PanelError && (error.status === 404 || error.code === 'UNKNOWN_SERVER')\n if (!missing)\n throw error\n }\n }\n else {\n const read = readConfig(this.options.home)\n if (read.error !== null || read.raw === null)\n throw new HomeHostedError(read.error ?? 'the config file is unreadable', 'CONFIG_UNREADABLE')\n writeConfig(this.options.home, removeConfigEntry(read.raw, id), this.writtenBy())\n }\n delete snapshots[id]\n this.saveSnapshots(snapshots)\n const current = this.options.settings.get()\n this.options.settings.update({\n // Only the harness entry drives the page's manage toggle.\n ...(id === this.options.defaultEntryId ? { manageDsh: false } : {}),\n entries: current.entries.filter(entry => entry.id !== id),\n })\n return await this.entriesStatus()\n }\n\n /** Turn off the autostart intent for one entry, keeping the entry itself. */\n private async pauseManagedEntry(id: string): Promise<ManagedEntryStatus[]> {\n const intent = this.options.settings.intentFor(id)\n await this.applyIntents([{ ...intent, autostart: false }])\n const current = this.options.settings.get()\n this.options.settings.update({\n ...(id === this.options.defaultEntryId ? { manageDsh: false } : {}),\n entries: current.entries,\n })\n return await this.entriesStatus()\n }\n\n /** Drive the panel's own UI through its CLI, and report what is installed. */\n async uiManage(action: UiAction, file?: string): Promise<UiResult> {\n const cli = action === 'status' ? null : await this.cli()\n\n const runUi = async (args: string[]): Promise<{ code: number | null, output: string }> => {\n const launch = cli?.resolution.launch ?? null\n if (launch === null)\n throw new HomeHostedError(cli?.resolution.status.detail ?? 'no home-hosted CLI could be resolved', 'CLI_NOT_FOUND')\n const result = await run(launch.program, [...launch.args, ...args, '--home', this.options.home], {\n env: { ...process.env, HHOSTED_HOME: this.options.home },\n timeoutMs: 300_000,\n })\n // A CLI that never started has no stdout to show, so its spawn error is the\n // only thing that explains the failure.\n const output = [result.error, result.stdout, result.stderr].filter(part => typeof part === 'string' && part.trim().length > 0).join('\\n').trim()\n return { code: result.code, output }\n }\n\n interface ActiveUi { name: string | null, version: string | null, repo: string | null, tag: string | null }\n const active = (): ActiveUi | null => {\n const meta = readJson<{ name?: string, version?: string | null, repo?: string, tag?: string }>(path.join(this.options.home, '.ui', 'ui.json'))\n return meta === null ? null : { name: meta.name ?? null, version: meta.version ?? null, repo: meta.repo ?? null, tag: meta.tag ?? null }\n }\n\n switch (action) {\n case 'status': {\n const ui = active()\n return { ok: true, ui, detail: ui === null ? 'the panel is using its stock UI' : `${ui.name ?? 'a custom UI'}${ui.version === null ? '' : ` ${ui.version}`}` }\n }\n case 'update': {\n const result = await runUi(['ui-update', '--yes'])\n return { ok: result.code === 0, detail: result.code === 0 ? 'the panel UI is up to date' : 'the update did not run', ui: active(), output: result.output }\n }\n case 'revert': {\n const result = await runUi(['ui-revert'])\n return { ok: result.code === 0, detail: result.code === 0 ? 'back to the stock UI' : 'the revert did not run', ui: active(), output: result.output }\n }\n case 'switch': {\n if (file === undefined || file.trim().length === 0)\n throw new HomeHostedError('switching the UI needs the zip to install', 'UI_FILE_REQUIRED')\n if (!fs.existsSync(file))\n throw new HomeHostedError(`no file at ${file}`, 'UI_FILE_MISSING')\n const result = await runUi(['ui-switch', '--file', file, '--yes'])\n return { ok: result.code === 0, detail: result.code === 0 ? 'the UI was replaced' : 'the switch did not run', ui: active(), output: result.output }\n }\n default:\n throw new HomeHostedError(`unknown ui action \"${String(action)}\"`, 'UNKNOWN_UI_ACTION')\n }\n }\n\n private async restoreEntry(id: string): Promise<ManagedEntryStatus[]> {\n const live = (await this.liveEntries()).get(id) ?? null\n if (live === null)\n throw new HomeHostedError(`no server \"${id}\" exists`, 'ENTRY_MISSING')\n const snapshots = this.snapshots()\n // A restore without a snapshot would write schema defaults over the person's\n // own autostart and conflict policy, silently and irreversibly.\n if (snapshots[id] === undefined)\n throw new HomeHostedError(`\"${id}\" was never adopted by this plugin, so there is nothing to restore; adopt it first`, 'NOT_ADOPTED')\n const patch = restorePatch(live.config, snapshots[id] ?? null)\n const client = await this.tryClient()\n if (client !== null)\n await client.updateServer(id, patch)\n else {\n const read = readConfig(this.options.home)\n if (read.error !== null || read.raw === null)\n throw new HomeHostedError(read.error ?? 'the config file is unreadable', 'CONFIG_UNREADABLE')\n writeConfig(this.options.home, patchEntry(read.raw, id, patch), this.writtenBy())\n }\n delete snapshots[id]\n this.saveSnapshots(snapshots)\n const current = this.options.settings.get()\n this.options.settings.update({\n ...(id === this.options.defaultEntryId ? { manageDsh: false } : {}),\n entries: current.entries.filter(entry => entry.id !== id),\n })\n return await this.entriesStatus()\n }\n\n async entriesStatus(): Promise<ManagedEntryStatus[]> {\n const settings = this.options.settings.get()\n const live = await this.liveEntries()\n const snapshots = this.snapshots()\n const persistent = await this.supportsPersistent()\n const ids = new Set<string>([this.options.defaultEntryId, ...settings.entries.map(entry => entry.id)])\n return [...ids].map((id) => {\n const intent = this.options.settings.intentFor(id)\n const entry = live.get(id) ?? null\n return {\n intent,\n exists: entry !== null,\n managed: snapshots[id] !== undefined,\n drift: entry === null ? ['missing entry'] : ownedDrift(entry.config, intent, { persistent }),\n live: entry?.view ?? null,\n snapshot: snapshots[id] ?? null,\n }\n })\n }\n\n // -------------------------------------------------------------------------\n // Boot autostart\n // -------------------------------------------------------------------------\n\n private ladder(): BootLadderLike {\n if (this.options.createLadder !== undefined)\n return this.options.createLadder()\n return createBootLadder({ env: process.env })\n }\n\n private async bootSpec(): Promise<BootSpec | null> {\n const { resolution, launcher } = await this.cli()\n const launch = resolution.launch\n if (launch === null)\n return null\n const runtime = this.runtime()\n const spec = buildHomeHostedBootSpec(\n {\n home: this.options.home,\n projectDir: process.env.HHOSTED_PROJECT ?? runtime?.projectDir ?? null,\n version: runtime?.version ?? null,\n },\n launch,\n { stateDir: this.options.stateDir },\n )\n\n // The entry runs the stable launcher, not the pinned node_modules path: that\n // path carries a version and a peer hash, and moves on the next install.\n if (launcher !== null) {\n const cliArgs = spec.args.slice(launch.args.length)\n if (process.platform === 'win32') {\n spec.command = process.execPath\n spec.args = [launcher, ...cliArgs]\n }\n else {\n spec.command = launcher\n spec.args = cliArgs\n }\n }\n return spec\n }\n\n async bootStatus(mechanism?: BootMechanism): Promise<BootStatus> {\n const platform: BootStatus['platform'] = process.platform === 'linux'\n ? 'linux'\n : process.platform === 'darwin' ? 'darwin' : process.platform === 'win32' ? 'win32' : 'other'\n const spec = await this.bootSpec()\n if (spec === null) {\n return {\n platform,\n mechanism: null,\n recommended: null,\n state: 'unsupported',\n bootCapable: false,\n privileged: false,\n unitPath: null,\n commands: [],\n detail: 'no home-hosted CLI is available, so no boot entry can be generated; install the plugin with its dependencies',\n candidates: [],\n }\n }\n const settings = this.options.settings.get()\n const requested = mechanism ?? (settings.autostart.mechanism === 'auto' ? undefined : settings.autostart.mechanism)\n return await this.ladder().status(spec, requested)\n }\n\n async installBoot(mechanism?: BootMechanism): Promise<{ result: BootInstallResult, status: BootStatus }> {\n const spec = await this.bootSpec()\n if (spec === null)\n throw new HomeHostedError((await this.cli()).resolution.status.detail, 'CLI_NOT_FOUND')\n const result = await this.ladder().install(spec, mechanism)\n const current = this.options.settings.get().autostart\n this.options.settings.update({\n autostart: {\n // The preference follows the outcome for a real install, and the last\n // attempt is recorded either way so a failure is visible after a reload.\n enabled: result.ok ? true : current.enabled,\n mechanism: result.ok\n ? (mechanism ?? result.mechanism ?? current.mechanism)\n : current.mechanism,\n lastAttempt: {\n ok: result.ok,\n action: 'install',\n mechanism: result.mechanism ?? mechanism ?? null,\n detail: result.detail,\n commands: result.commands,\n at: Date.now(),\n },\n },\n })\n return { result, status: await this.bootStatus(mechanism) }\n }\n\n async uninstallBoot(mechanism?: BootMechanism): Promise<{ result: BootInstallResult, status: BootStatus }> {\n const spec = await this.bootSpec()\n if (spec === null)\n throw new HomeHostedError((await this.cli()).resolution.status.detail, 'CLI_NOT_FOUND')\n const result = await this.ladder().uninstall(spec, mechanism)\n const current = this.options.settings.get().autostart\n this.options.settings.update({\n autostart: {\n ...current,\n enabled: result.ok ? false : current.enabled,\n lastAttempt: {\n ok: result.ok,\n action: 'uninstall',\n mechanism: result.mechanism ?? mechanism ?? null,\n detail: result.detail,\n commands: result.commands,\n at: Date.now(),\n },\n },\n })\n return { result, status: await this.bootStatus(mechanism) }\n }\n\n // -------------------------------------------------------------------------\n // Panel lifecycle\n // -------------------------------------------------------------------------\n\n /** Out-of-the-box start: run the preferred CLI's `up`, which detaches itself. */\n async startPanelNow(): Promise<PanelControlResult> {\n const { resolution } = await this.cli()\n const deps = await this.panelControlDeps()\n if (deps.launch === null)\n throw new HomeHostedError(resolution.status.detail, 'CLI_NOT_FOUND')\n const runtime = this.runtime()\n if (runtime !== null && await probePanel(runtime.url)) {\n return { ok: true, detail: 'a panel is already answering', url: runtime.url, version: runtime.version }\n }\n this.applyPanelPort()\n const result = await startPanelProcess(deps)\n this.clientCache = null\n return result\n }\n\n /**\n * Replace an answering panel with the preferred copy.\n *\n * That stops the servers the old panel supervises \u2014 this process included \u2014 so\n * the work is handed to a detached helper and the guard demands that this\n * session is an adopted, autostarting entry the new panel will bring back.\n */\n async takeoverPanel(force = false): Promise<PanelControlResult> {\n const { resolution } = await this.cli()\n const deps = await this.panelControlDeps()\n if (deps.launch === null)\n throw new HomeHostedError(resolution.status.detail, 'CLI_NOT_FOUND')\n\n const runtime = this.runtime()\n if (runtime === null || !(await probePanel(runtime.url)))\n return await this.startPanelNow()\n\n if (runtime.version !== null && resolution.status.version !== null && runtime.version === resolution.status.version) {\n return { ok: true, detail: `the answering panel is already ${runtime.version}`, url: runtime.url, version: runtime.version }\n }\n\n if (!force) {\n const id = this.selfEntryId()\n const live = id === null ? null : (await this.liveEntries()).get(id) ?? null\n if (id === null || live === null || live.config.autostart !== true) {\n throw new HomeHostedError(\n 'replacing the panel stops every server it supervises, including this session, and nothing would start it again: '\n + 'adopt this entry with autostart first, or pass force',\n 'TAKEOVER_UNSAFE',\n )\n }\n }\n\n return spawnTakeover(deps, runtime.pid)\n }\n\n /** Install the pinned range globally, so the `global` preference has a copy to run. */\n async installGlobalCli(): Promise<PanelControlResult & { output?: string }> {\n const result = await installGlobal(EXPECTED_RANGE)\n this.cliCache = null\n return { ok: result.ok, detail: result.detail, output: result.output }\n }\n\n /** Re-assert an entry that is already installed: a node or CLI upgrade moves the\n * paths a unit was written with, and the fix is to rewrite it.\n *\n * Never installs one that is not there. Installing is a deliberate act \u2014 it can\n * need root and it makes this machine start something at boot \u2014 so it happens on\n * an explicit click or an approved tool call, not as a side effect of startup.\n */\n async reconcile(): Promise<void> {\n // A managed entry that someone deleted (by mistake, from the panel or by hand)\n // stays \"managed\" in settings with nothing to manage, which is the state the\n // page reports as a missing entry. Recreate it \u2014 the toggle is the intent.\n await this.ensureManagedEntry()\n await this.repairBootEntry()\n }\n\n /**\n * Put back a managed entry that no longer exists, while its intent still wants\n * autostart. A paused intent is a deliberate stop and is left alone.\n *\n * Called from startup `reconcile()` as well as the status read, because a person\n * who deletes the entry from the panel is looking at the page right then \u2014 not\n * at the next plugin start. A failed attempt is not repeated for a while, so a\n * config that cannot be written does not turn every poll into a write.\n */\n private async ensureManagedEntry(): Promise<void> {\n const { settings } = this.options\n const id = this.options.defaultEntryId\n if (!settings.get().manageDsh || !settings.intentFor(id).autostart)\n return\n // Claim the attempt before the first await, so two status calls racing each\n // other cannot both decide to create the same entry.\n const now = Date.now()\n if (now - this.entryRecoveryAt < ENTRY_RECOVERY_INTERVAL_MS)\n return\n this.entryRecoveryAt = now\n if ((await this.entriesStatus()).every(entry => entry.intent.id !== id || entry.exists))\n return\n try {\n await this.writeOwned({ ...settings.intentFor(id), autostart: true })\n }\n catch {\n // an unwritable config is reported by the status the page reads\n }\n }\n\n /** Re-assert the boot entry when the OS still has it but it stopped working. */\n private async repairBootEntry(): Promise<void> {\n if (!this.options.settings.get().autostart.enabled)\n return\n const status = await this.bootStatus()\n if (status.state !== 'enabled-failing' && status.state !== 'installed-disabled')\n return\n // Belt on top of the probe: a file-backed entry is only repaired when the file\n // is actually there, so a reporting slip can never turn startup into an install.\n const fileBacked = status.mechanism === 'systemd-user'\n || status.mechanism === 'systemd-system'\n || status.mechanism === 'xdg-autostart'\n || status.mechanism === 'launchd-agent'\n || status.mechanism === 'launchd-daemon'\n if (fileBacked && (status.unitPath === null || !fs.existsSync(status.unitPath)))\n return\n try {\n await this.installBoot()\n }\n catch {\n // a failed repair is reported by the status the page reads\n }\n }\n\n // -------------------------------------------------------------------------\n // Status\n // -------------------------------------------------------------------------\n\n async status(): Promise<HomeHostedStatus> {\n // Resolve the client first: enrolling a token changes which write path is\n // available, and the page should see the state after that, not before.\n const client = await this.tryClient()\n const panel = await this.panelStatus()\n const { resolution, launcher, launcherVersion } = await this.cli()\n const cliDetail = resolution.status.detail\n const panelVersion = this.runtime()?.version ?? null\n const cli = {\n ...resolution.status,\n launcherPath: launcher,\n launcherVersion,\n // A panel left running from an older install is the usual reason to see\n // two versions on this page; say so instead of leaving it ambiguous.\n detail: panelVersion !== null && resolution.status.version !== null && panelVersion !== resolution.status.version\n ? `${cliDetail}; the running panel is ${panelVersion}`\n : cliDetail,\n }\n let servers: ServerEntryView[] = []\n let lastError: string | null = null\n if (client !== null) {\n try {\n servers = await client.listServers()\n }\n catch (error) {\n lastError = error instanceof Error ? error.message : String(error)\n }\n }\n else if (panel.reachable) {\n lastError = panel.detail\n }\n\n return {\n defaultEntryId: this.options.defaultEntryId,\n panel,\n boot: await this.bootStatus(),\n // A deleted managed entry is put back here as well as at startup: whoever\n // deleted it is looking at the page that reports it missing.\n entries: await this.ensureManagedEntry().then(async () => await this.entriesStatus()),\n servers,\n settings: this.options.settings.get(),\n cli,\n lastError,\n }\n }\n\n // -------------------------------------------------------------------------\n // Endpoint dispatch\n // -------------------------------------------------------------------------\n\n async call(endpoint: RpcEndpoint, payload: unknown): Promise<unknown> {\n const input = (payload ?? {}) as Record<string, unknown>\n switch (endpoint) {\n case 'status':\n return await this.status()\n\n case 'settings.update': {\n const patch = (input.patch ?? {}) as Parameters<SettingsStore['update']>[0]\n this.options.settings.update(patch)\n return await this.status()\n }\n\n case 'servers.list':\n return await (await this.requireClient()).listServers()\n\n case 'servers.get':\n return await (await this.requireClient()).getServer(String(input.id))\n\n case 'servers.create': {\n const entry = input.entry as ServerEntry\n if (typeof entry?.id !== 'string' || !ENTRY_ID_PATTERN.test(entry.id))\n throw new HomeHostedError('a server entry needs an id matching ^[a-z0-9][a-z0-9_-]*$', 'INVALID_ID')\n return await (await this.requireClient()).createServer(entry)\n }\n\n case 'servers.update':\n return await (await this.requireClient()).updateServer(String(input.id), (input.patch ?? {}) as ServerEntryPatch)\n\n case 'servers.delete': {\n const id = String(input.id)\n if (id === this.selfEntryId()) {\n throw new HomeHostedError(\n `\"${id}\" is the entry this very process runs as, and deleting it stops this session; `\n + 'pause it (autostart off) or restore it instead',\n 'SELF_ENTRY',\n )\n }\n await (await this.requireClient()).deleteServer(id)\n return { id }\n }\n\n case 'servers.start':\n await (await this.requireClient()).startServer(String(input.id))\n return await this.entriesStatus()\n\n case 'servers.stop':\n await (await this.requireClient()).stopServer(String(input.id))\n return await this.entriesStatus()\n\n case 'servers.restart':\n await (await this.requireClient()).restartServer(String(input.id))\n return await this.entriesStatus()\n\n case 'servers.freePort':\n return await (await this.requireClient()).freePort(String(input.id))\n\n case 'entries.apply': {\n const intents = Array.isArray(input.intents) ? input.intents as EntryIntent[] : []\n return await this.applyIntents(intents)\n }\n\n case 'entries.remove':\n return await this.removeManagedEntry(String(input.id))\n\n case 'entries.restore':\n return await this.restoreEntry(String(input.id))\n\n case 'ui.manage':\n return await this.uiManage(input.action as UiAction, typeof input.file === 'string' ? input.file : undefined)\n\n case 'boot.install':\n return await this.installBoot(input.mechanism as BootMechanism | undefined)\n\n case 'boot.uninstall':\n return await this.uninstallBoot(input.mechanism as BootMechanism | undefined)\n\n case 'boot.verify':\n return await this.bootStatus()\n\n case 'panel.start':\n return await this.startPanelNow()\n\n case 'panel.takeover':\n return await this.takeoverPanel(input.force === true)\n\n case 'panel.reclaimToken':\n return await this.reclaimPanelToken()\n\n case 'cli.installGlobal':\n return await this.installGlobalCli()\n\n default:\n throw new HomeHostedError(`unknown endpoint \"${String(endpoint)}\"`, 'UNKNOWN_ENDPOINT')\n }\n }\n}\n\ndeclare module '@deepseek-ai/cordis' {\n interface Context {\n homeHosted: HomeHostedService\n }\n}\n", "/**\n * The boot ladder: which mechanisms exist on this platform, which one is\n * installed, and which one this process should use. Everything platform\n * specific is inside a provider's `detect()`/`status()`/`install()` \u2014 this file\n * only orders them and never runs at import time.\n */\nimport os from 'node:os'\nimport process from 'node:process'\nimport type { BootCandidate, BootMechanism, BootStatus } from '../shared/contracts.js'\nimport { run as execRun, sudoAvailable } from '../util/exec.js'\nimport type {\n BootActionResult,\n BootLadder,\n BootLadderOptions,\n BootProvider,\n BootProviderContext,\n BootProviderStatus,\n BootSpec,\n} from './types.js'\nimport { errorMessage, failed, isInstalledState } from './common.js'\nimport { createSystemdSystemProvider, createSystemdUserProvider } from './systemd.js'\nimport { createLaunchdAgentProvider, createLaunchdDaemonProvider } from './launchd.js'\nimport { createXdgAutostartProvider } from './xdg.js'\nimport { createWindowsRunProvider, createWindowsTaskProvider } from './windows.js'\nimport { createContainerProvider, createUnsupportedProvider } from './fallback.js'\n\nfunction platformKind(platform: NodeJS.Platform): BootStatus['platform'] {\n if (platform === 'linux' || platform === 'darwin' || platform === 'win32')\n return platform\n return 'other'\n}\n\n/** Ordered by preference within a platform; the terminal providers come last. */\nexport function bootProviders(\n ctx: BootProviderContext,\n platform: NodeJS.Platform = ctx.platform,\n): BootProvider[] {\n const container = createContainerProvider(ctx)\n const unsupported = createUnsupportedProvider(platform)\n switch (platform) {\n case 'linux':\n return [createSystemdUserProvider(ctx), createSystemdSystemProvider(ctx), createXdgAutostartProvider(ctx), container, unsupported]\n case 'darwin':\n return [createLaunchdAgentProvider(ctx), createLaunchdDaemonProvider(ctx), unsupported]\n case 'win32':\n return [createWindowsRunProvider(ctx), createWindowsTaskProvider(ctx), unsupported]\n default:\n return [container, unsupported]\n }\n}\n\nexport function createBootLadder(options: BootLadderOptions = {}): BootLadder {\n const platform = options.platform ?? process.platform\n const isRoot = process.getuid?.() === 0\n const ctx: BootProviderContext = {\n platform,\n home: options.home ?? os.homedir(),\n env: options.env ?? process.env,\n run: options.run ?? execRun,\n sudo: options.sudo ?? (async () => (isRoot ? true : await sudoAvailable())),\n isRoot,\n exists: options.exists,\n }\n const providers = bootProviders(ctx, platform)\n const kind = platformKind(platform)\n\n async function detectAll(): Promise<{ platform: BootStatus['platform'], candidates: BootCandidate[] }> {\n const candidates = await Promise.all(providers.map(async (provider) => {\n try {\n return await provider.detect()\n }\n catch (error) {\n return {\n mechanism: provider.mechanism,\n available: false,\n bootCapable: false,\n privileged: false,\n reason: `detection failed: ${errorMessage(error)}`,\n } satisfies BootCandidate\n }\n }))\n return { platform: kind, candidates }\n }\n\n async function safeStatus(provider: BootProvider, spec: BootSpec): Promise<BootProviderStatus> {\n try {\n return await provider.status(spec)\n }\n catch (error) {\n return { state: 'not-installed', unitPath: null, detail: errorMessage(error), commands: [] }\n }\n }\n\n function recommend(candidates: BootCandidate[]): BootMechanism | null {\n const byMechanism = new Map(candidates.map(candidate => [candidate.mechanism, candidate]))\n const available = providers\n .map(provider => provider.mechanism)\n .filter(mechanism => byMechanism.get(mechanism)?.available === true)\n const usable = (mechanism: string): boolean => mechanism !== 'container' && mechanism !== 'unsupported'\n // Inside a container no OS entry starts anything, so the honest advice is the\n // restart policy \u2014 ahead of anything else that merely looks available.\n if (available.includes('container'))\n return 'container'\n // A boot-capable mechanism that needs a password prompt is offered, but it is\n // not the *recommendation*: automatic should mean zero manual steps.\n const readyBoot = available.find(mechanism => usable(mechanism)\n && byMechanism.get(mechanism)?.bootCapable === true\n && byMechanism.get(mechanism)?.privileged === true)\n if (readyBoot)\n return readyBoot\n const ready = available.find(mechanism => usable(mechanism) && byMechanism.get(mechanism)?.privileged === true)\n if (ready)\n return ready\n const bootCapable = available.find(mechanism => usable(mechanism) && byMechanism.get(mechanism)?.bootCapable === true)\n if (bootCapable)\n return bootCapable\n return available.find(mechanism => mechanism !== 'unsupported')\n ?? available[0]\n ?? null\n }\n\n async function buildStatus(spec: BootSpec, mechanism?: BootMechanism): Promise<BootStatus> {\n const { candidates } = await detectAll()\n const byMechanism = new Map(candidates.map(candidate => [candidate.mechanism, candidate]))\n const statuses = new Map<BootMechanism, BootProviderStatus>()\n for (const [provider, status] of await Promise.all(providers.map(async provider => [provider, await safeStatus(provider, spec)] as const)))\n statuses.set(provider.mechanism, status)\n\n const explicit = mechanism ? providers.find(provider => provider.mechanism === mechanism) : undefined\n const installedProvider = providers.find((provider) => {\n const status = statuses.get(provider.mechanism)\n return status !== undefined && isInstalledState(status.state)\n })\n const recommended = recommend(candidates)\n const target = explicit\n ?? installedProvider\n ?? (recommended ? providers.find(provider => provider.mechanism === recommended) : undefined)\n\n const explicitStatus = explicit ? statuses.get(explicit.mechanism) : undefined\n const installedMechanism = explicit && explicitStatus && isInstalledState(explicitStatus.state)\n ? explicit.mechanism\n : installedProvider?.mechanism ?? null\n\n const common = { platform: kind, mechanism: installedMechanism, recommended, candidates }\n if (!target) {\n return {\n ...common,\n state: 'unsupported',\n bootCapable: false,\n privileged: false,\n unitPath: null,\n commands: [],\n detail: `no boot mechanism is available on ${platform}`,\n }\n }\n\n const status = statuses.get(target.mechanism)\n const candidate = byMechanism.get(target.mechanism)\n const alsoInstalled = providers\n .filter(provider => provider.mechanism !== target.mechanism && isInstalledState(statuses.get(provider.mechanism)?.state ?? 'unsupported'))\n .map(provider => provider.mechanism)\n return {\n ...common,\n state: status?.state ?? 'unsupported',\n bootCapable: candidate?.bootCapable ?? false,\n privileged: candidate?.privileged ?? false,\n unitPath: status?.unitPath ?? null,\n commands: status?.commands ?? [],\n detail: `${status?.detail ?? 'no detail'}${alsoInstalled.length ? `; also installed: ${alsoInstalled.join(', ')}` : ''}`,\n }\n }\n\n async function safeInstall(provider: BootProvider, spec: BootSpec): Promise<BootActionResult> {\n try {\n return await provider.install(spec)\n }\n catch (error) {\n return failed(errorMessage(error))\n }\n }\n\n async function safeUninstall(provider: BootProvider, spec: BootSpec): Promise<BootActionResult> {\n try {\n return await provider.uninstall(spec)\n }\n catch (error) {\n return failed(errorMessage(error))\n }\n }\n\n return {\n providers,\n\n detect: detectAll,\n\n status: buildStatus,\n\n async install(spec: BootSpec, mechanism?: BootMechanism) {\n const before = await buildStatus(spec, mechanism)\n const chosen = mechanism ?? before.mechanism ?? before.recommended\n const target = chosen ? providers.find(provider => provider.mechanism === chosen) : undefined\n if (!target) {\n return {\n ...failed(`no boot mechanism is available on ${platform}`),\n mechanism: null,\n status: before,\n }\n }\n const result = await safeInstall(target, spec)\n const status = await buildStatus(spec, mechanism)\n return {\n ...result,\n mechanism: result.ok ? target.mechanism : status.mechanism,\n status,\n }\n },\n\n async uninstall(spec: BootSpec, mechanism?: BootMechanism) {\n const before = await buildStatus(spec, mechanism)\n const chosen = mechanism ?? before.mechanism\n const target = chosen ? providers.find(provider => provider.mechanism === chosen) : undefined\n if (!target) {\n return {\n ok: true,\n changed: false,\n detail: 'no OS boot entry is installed for this plugin, so there is nothing to uninstall',\n commands: [],\n needsPrivilege: false,\n status: before,\n }\n }\n const result = await safeUninstall(target, spec)\n const status = await buildStatus(spec, mechanism)\n return { ...result, status }\n },\n }\n}\n", "/**\n * The only place this plugin starts a process.\n *\n * Every call is an argv array with no shell, so a path or a value can never\n * become a command. Callers pass absolute programs; nothing here resolves\n * through a shell profile.\n */\nimport { spawn } from 'node:child_process'\n\nexport interface RunOptions {\n cwd?: string\n env?: Record<string, string | undefined>\n timeoutMs?: number\n /** Cap on each captured stream; a chatty command is truncated, not buffered forever. */\n maxBytes?: number\n}\n\nexport interface RunResult {\n command: string\n args: string[]\n code: number | null\n signal: NodeJS.Signals | null\n stdout: string\n stderr: string\n timedOut: boolean\n error: string | null\n}\n\n/** Run a program and always resolve; a non-zero code is data, not a throw. */\nexport async function run(command: string, args: string[] = [], options: RunOptions = {}): Promise<RunResult> {\n const maxBytes = options.maxBytes ?? 256 * 1024\n const timeoutMs = options.timeoutMs ?? 20_000\n\n return await new Promise<RunResult>((resolve) => {\n let settled = false\n let stdout = ''\n let stderr = ''\n let timedOut = false\n\n const finish = (result: Partial<RunResult>): void => {\n if (settled)\n return\n settled = true\n resolve({\n command,\n args,\n code: result.code ?? null,\n signal: result.signal ?? null,\n stdout: result.stdout ?? stdout,\n stderr: result.stderr ?? stderr,\n timedOut,\n error: result.error ?? null,\n })\n }\n\n let child\n try {\n child = spawn(command, args, {\n cwd: options.cwd,\n env: { ...process.env, ...options.env },\n shell: false,\n windowsHide: true,\n stdio: ['ignore', 'pipe', 'pipe'],\n })\n }\n catch (error) {\n finish({ error: error instanceof Error ? error.message : String(error) })\n return\n }\n\n const timer = setTimeout(() => {\n timedOut = true\n child.kill('SIGKILL')\n }, timeoutMs)\n\n child.stdout?.on('data', (chunk: Buffer) => {\n if (stdout.length < maxBytes)\n stdout += chunk.toString('utf8').slice(0, maxBytes - stdout.length)\n })\n child.stderr?.on('data', (chunk: Buffer) => {\n if (stderr.length < maxBytes)\n stderr += chunk.toString('utf8').slice(0, maxBytes - stderr.length)\n })\n\n child.on('error', (error) => {\n clearTimeout(timer)\n finish({ error: error.message })\n })\n child.on('close', (code, signal) => {\n clearTimeout(timer)\n finish({ code, signal })\n })\n })\n}\n\n/** Run a program and fail loudly on anything but success. */\nexport async function runOk(command: string, args: string[] = [], options: RunOptions = {}): Promise<RunResult> {\n const result = await run(command, args, options)\n if (result.error !== null)\n throw new Error(`${command} failed: ${result.error}`)\n if (result.code !== 0)\n throw new Error(`${command} exited ${String(result.code)}: ${result.stderr.trim() || result.stdout.trim()}`)\n return result\n}\n\n/** True when the program exists and answers to `--version` or similar. */\nexport async function hasCommand(command: string): Promise<boolean> {\n const probe = process.platform === 'win32' ? 'where.exe' : 'which'\n const result = await run(probe, [command], { timeoutMs: 5000 })\n return result.code === 0\n}\n\n/**\n * Whether this process can run one privileged command with no prompt.\n * `sudo -n` never asks for a password, so a failure is a definitive \"not\n * available\" rather than something to retry interactively.\n */\nexport async function sudoAvailable(): Promise<boolean> {\n if (process.getuid?.() === 0)\n return true\n const result = await run('sudo', ['-n', 'true'], { timeoutMs: 5000 })\n return result.code === 0\n}\n", "/**\n * Shared pieces of the boot ladder: where each mechanism's artifact lives, how\n * ownership of an existing artifact is proven before it is touched, and how a\n * probe's answers collapse into one `BootState`. No process is started here.\n */\nimport fs from 'node:fs'\nimport os from 'node:os'\nimport path from 'node:path'\nimport { readText, writeFileAtomic } from '../util/fsx.js'\nimport type { BootState } from '../shared/contracts.js'\nimport type { BootActionResult, BootProviderContext } from './types.js'\n\nexport function errorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error)\n}\n\n/** Existence check through the injected seam, so a probe is testable without touching the host. */\nexport function existsOf(ctx: BootProviderContext, file: string): boolean {\n return ctx.exists ? ctx.exists(file) : fs.existsSync(file)\n}\n\nexport function posixJoin(...parts: string[]): string {\n return path.posix.join(...parts)\n}\n\n/** `$XDG_CONFIG_HOME`, else `~/.config`. */\nexport function configHome(ctx: BootProviderContext): string {\n const xdg = ctx.env.XDG_CONFIG_HOME?.trim()\n return xdg ? path.posix.resolve(xdg) : posixJoin(ctx.home, '.config')\n}\n\n/** `%LOCALAPPDATA%`, else `~\\AppData\\Local`. */\nexport function localAppData(ctx: BootProviderContext): string {\n const value = ctx.env.LOCALAPPDATA?.trim()\n return value ? value : path.join(ctx.home, 'AppData', 'Local')\n}\n\n/** A writable scratch directory, used to stage a unit before `sudo install`. */\nexport function tempDir(ctx: BootProviderContext): string {\n const value = ctx.env.TMPDIR?.trim() || ctx.env.TEMP?.trim() || ctx.env.TMP?.trim()\n return value || os.tmpdir()\n}\n\nexport function currentUser(ctx: BootProviderContext): string | null {\n const value = ctx.env.USER?.trim() || ctx.env.LOGNAME?.trim() || ctx.env.USERNAME?.trim()\n if (value)\n return value\n try {\n return os.userInfo().username\n }\n catch {\n return null\n }\n}\n\n/** The invoking user's name, so a root-level entry can drop to it. */\nexport function userNameOf(ctx: BootProviderContext): string | null {\n const configured = ctx.env.USER?.trim() ?? ctx.env.USERNAME?.trim()\n if (configured !== undefined && configured.length > 0)\n return configured\n try {\n return os.userInfo().username\n }\n catch {\n return null\n }\n}\n\nexport function uidOf(ctx: BootProviderContext): string | null {\n const configured = ctx.env.UID?.trim()\n if (configured)\n return configured\n const uid = process.getuid?.()\n return uid === undefined ? null : String(uid)\n}\n\n// ---------------------------------------------------------------------------\n// Ownership\n// ---------------------------------------------------------------------------\n\nexport interface FileOwnership {\n exists: boolean\n owned: boolean\n text: string | null\n reason: string | null\n}\n\n/**\n * An artifact belongs to this plugin only when it carries the marker. A file\n * we cannot read is treated as foreign: we must never overwrite or delete a\n * unit somebody else wrote.\n */\nexport function inspectOwned(file: string, marker: string): FileOwnership {\n if (!fs.existsSync(file))\n return { exists: false, owned: false, text: null, reason: null }\n const text = readText(file)\n if (text === null)\n return { exists: true, owned: false, text: null, reason: `${file} exists but is unreadable, so it cannot be proven to be ours` }\n if (!text.includes(marker))\n return { exists: true, owned: false, text, reason: `${file} exists and does not carry this plugin's marker (${marker}); refusing to touch an artifact we did not write` }\n return { exists: true, owned: true, text, reason: null }\n}\n\n/** Write our artifact if the bytes differ; never overwrite a foreign one. */\nexport function writeOwned(file: string, marker: string, content: string, mode = 0o644): { changed: boolean, refusal: string | null } {\n const own = inspectOwned(file, marker)\n if (own.exists && !own.owned)\n return { changed: false, refusal: own.reason }\n if (own.exists && own.text === content)\n return { changed: false, refusal: null }\n writeFileAtomic(file, content, mode)\n return { changed: true, refusal: null }\n}\n\n/** Delete our artifact only; a missing file is already the desired state. */\nexport function removeOwned(file: string, marker: string): { removed: boolean, refusal: string | null } {\n const own = inspectOwned(file, marker)\n if (!own.exists)\n return { removed: false, refusal: null }\n if (!own.owned)\n return { removed: false, refusal: own.reason }\n try {\n fs.rmSync(file, { force: true })\n return { removed: true, refusal: null }\n }\n catch (error) {\n return { removed: false, refusal: `could not delete ${file}: ${errorMessage(error)}` }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Results\n// ---------------------------------------------------------------------------\n\nexport function failed(detail: string, extra: Partial<BootActionResult> = {}): BootActionResult {\n return { ok: false, changed: false, detail, commands: [], needsPrivilege: false, ...extra }\n}\n\n/** Installed + enabled + last run failed is `enabled-failing`; never a guessed success. */\nexport function bootState(installed: boolean, enabled: boolean, failing: boolean): BootState {\n if (!installed)\n return 'not-installed'\n if (!enabled)\n return 'installed-disabled'\n return failing ? 'enabled-failing' : 'enabled-running'\n}\n\nexport function isInstalledState(state: BootState): boolean {\n return state === 'installed-disabled' || state === 'enabled-running' || state === 'enabled-failing'\n}\n", "/**\n * Small filesystem helpers. Every write is atomic (temp file + rename) so a\n * reader never sees half a file, and secret-bearing files are created 0600.\n */\nimport fs from 'node:fs'\nimport path from 'node:path'\nimport process from 'node:process'\n\nexport function fileExists(file: string): boolean {\n try {\n return fs.statSync(file).isFile()\n }\n catch {\n return false\n }\n}\n\nexport function readText(file: string): string | null {\n try {\n return fs.readFileSync(file, 'utf8')\n }\n catch {\n return null\n }\n}\n\nexport function readJson<T>(file: string): T | null {\n const text = readText(file)\n if (text === null)\n return null\n try {\n return JSON.parse(text) as T\n }\n catch {\n return null\n }\n}\n\nexport function ensureDir(dir: string, mode = 0o700): void {\n fs.mkdirSync(dir, { recursive: true, mode })\n}\n\n/** Write a file through a sibling temp file, then rename it into place. */\nexport function writeFileAtomic(file: string, data: string, mode?: number): void {\n ensureDir(path.dirname(file))\n const temp = path.join(path.dirname(file), `.${path.basename(file)}.${process.pid}.${Date.now()}.tmp`)\n const fd = fs.openSync(temp, 'w', mode ?? 0o644)\n try {\n fs.writeFileSync(fd, data, 'utf8')\n fs.fsyncSync(fd)\n }\n finally {\n fs.closeSync(fd)\n }\n if (mode !== undefined)\n fs.chmodSync(temp, mode)\n fs.renameSync(temp, file)\n}\n\nexport function writeJsonAtomic(file: string, value: unknown, mode?: number): void {\n writeFileAtomic(file, `${JSON.stringify(value, null, 2)}\\n`, mode)\n}\n\n/** Best-effort removal; a missing file is not an error. */\nexport function removeFile(file: string): void {\n try {\n fs.rmSync(file, { force: true })\n }\n catch {\n // ignored: the caller only cares that it is gone, and reconciliation reports the rest\n }\n}\n", "/**\n * systemd: a user unit (`~/.config/systemd/user`) and a system unit\n * (`/etc/systemd/system`). The system one needs root, so every privileged call\n * goes through `sudo -n` \u2014 it never prompts \u2014 and the copy-pasteable `sudo \u2026`\n * form is reported when elevation is not available.\n */\nimport fs from 'node:fs'\nimport type { BootCandidate, BootState } from '../shared/contracts.js'\nimport type { BootActionResult, BootProvider, BootProviderContext, BootProviderStatus, BootSpec } from './types.js'\nimport {\n assertAbsolute,\n assertArg,\n assertEnvKey,\n assertLabel,\n assertMarker,\n assertUnitName,\n shellCommand,\n systemdEnvLine,\n systemdExecWord,\n systemdPath,\n systemdText,\n} from './escape.js'\nimport {\n bootState,\n configHome,\n currentUser,\n errorMessage,\n existsOf,\n failed,\n inspectOwned,\n posixJoin,\n removeOwned,\n tempDir,\n writeOwned,\n} from './common.js'\n\nconst ENABLED_UNIT_STATES = new Set(['enabled', 'enabled-runtime', 'alias', 'static', 'indirect', 'generated', 'transient'])\nconst FAILED_RESULTS = new Set(['failed', 'exit-code', 'signal', 'timeout', 'core-dump', 'watchdog', 'start-limit-hit', 'oom-kill'])\n\ntype Scope = 'user' | 'system'\n\nfunction validate(spec: BootSpec): void {\n assertUnitName(spec.unitName)\n assertMarker(spec.marker)\n assertLabel(spec.label)\n assertAbsolute(spec.command, 'spec.command')\n assertAbsolute(spec.cwd, 'spec.cwd')\n assertAbsolute(spec.logDir, 'spec.logDir')\n for (const arg of spec.args)\n assertArg(arg)\n for (const key of Object.keys(spec.env))\n assertEnvKey(key)\n}\n\nfunction envLines(spec: BootSpec): string[] {\n return Object.entries(spec.env).map(([key, value]) => `Environment=${systemdEnvLine(key, value)}`)\n}\n\nconst MANAGED = (spec: BootSpec): string => `# Managed by ${spec.marker}`\n\n/** `Type=exec` with an explicit environment; boot capability comes from linger, not from this file. */\nexport function systemdUserUnit(spec: BootSpec): string {\n validate(spec)\n return `${[\n MANAGED(spec),\n '[Unit]',\n `Description=${systemdText(spec.label)}`,\n 'After=network-online.target',\n '',\n '[Service]',\n 'Type=exec',\n `ExecStart=${[spec.command, ...spec.args].map(systemdExecWord).join(' ')}`,\n `WorkingDirectory=${systemdPath(spec.cwd, 'spec.cwd')}`,\n 'Restart=always',\n 'RestartSec=5',\n ...envLines(spec),\n '',\n '[Install]',\n 'WantedBy=default.target',\n '',\n ].join('\\n')}`\n}\n\n/**\n * The system unit. `StartLimit*` belongs in `[Unit]`, not `[Service]`; `User=`\n * is written only when we are root and know the target account.\n */\nexport function systemdSystemUnit(spec: BootSpec, user: string | null = null): string {\n validate(spec)\n return `${[\n MANAGED(spec),\n '[Unit]',\n `Description=${systemdText(spec.label)}`,\n 'After=network-online.target',\n 'StartLimitIntervalSec=60',\n 'StartLimitBurst=5',\n '',\n '[Service]',\n ...(user ? [`User=${user}`] : []),\n 'Type=exec',\n `ExecStart=${[spec.command, ...spec.args].map(systemdExecWord).join(' ')}`,\n `WorkingDirectory=${systemdPath(spec.cwd, 'spec.cwd')}`,\n 'Restart=always',\n 'RestartSec=5',\n ...envLines(spec),\n '',\n '[Install]',\n 'WantedBy=multi-user.target',\n '',\n ].join('\\n')}`\n}\n\nfunction codeOf(result: { code: number | null, error?: string | null }): number | null {\n return result.error ? null : result.code\n}\n\nfunction parseKeyValues(stdout: string): Record<string, string> {\n const out: Record<string, string> = {}\n for (const line of stdout.split('\\n')) {\n const eq = line.indexOf('=')\n if (eq > 0)\n out[line.slice(0, eq).trim()] = line.slice(eq + 1).trim()\n }\n return out\n}\n\ninterface UnitProbe {\n unitFileState: string\n activeState: string\n result: string\n nRestarts: string\n enabled: boolean\n installed: boolean\n reachable: boolean\n detail: string\n}\n\nasync function readUnit(ctx: BootProviderContext, unit: string, scope: Scope): Promise<UnitProbe> {\n const scopeArgs = scope === 'user' ? ['--user'] : []\n const show = await ctx.run('systemctl', [...scopeArgs, 'show', '-p', 'UnitFileState', '-p', 'ActiveState', '-p', 'Result', '-p', 'NRestarts', unit])\n const props = parseKeyValues(show.stdout)\n const isEnabled = await ctx.run('systemctl', [...scopeArgs, 'is-enabled', unit])\n const enabledCode = codeOf(isEnabled)\n const unitFileState = props.UnitFileState ?? ''\n /**\n * `is-enabled` exits 1 both for a disabled unit and for a unit it cannot even\n * look up, so only a known `UnitFileState` (or an explicit exit 0) proves the\n * unit exists. A user-bus failure must not read as `installed-disabled`.\n */\n const knownState = unitFileState !== '' && unitFileState !== 'not-found'\n const enabled = enabledCode === 0 || ENABLED_UNIT_STATES.has(unitFileState)\n const installed = enabled || knownState\n const result = props.Result ?? ''\n return {\n unitFileState,\n activeState: props.ActiveState ?? '',\n result,\n nRestarts: props.NRestarts ?? '',\n enabled,\n installed,\n reachable: show.error === undefined || show.error === null,\n detail: `UnitFileState=${unitFileState || '(none)'} ActiveState=${props.ActiveState || '(none)'} Result=${result || '(none)'} NRestarts=${props.NRestarts ?? '0'}`,\n }\n}\n\nasync function userScopeReachable(ctx: BootProviderContext): Promise<{ reachable: boolean, reason: string }> {\n const probe = await ctx.run('systemctl', ['--user', 'is-system-running'])\n if (probe.error)\n return { reachable: false, reason: `systemctl --user is not available here (${probe.error})` }\n if (`${probe.stdout}\\n${probe.stderr}`.includes('Failed to connect to user scope bus'))\n return { reachable: false, reason: 'systemctl --user cannot reach a user manager: Failed to connect to user scope bus' }\n return { reachable: true, reason: '' }\n}\n\nasync function lingerEnabled(ctx: BootProviderContext): Promise<boolean> {\n const user = currentUser(ctx)\n if (!user)\n return false\n const probe = await ctx.run('loginctl', ['show-user', user, '--property=Linger'])\n if (codeOf(probe) !== 0)\n return false\n return /(^|\\n)Linger=yes(\\n|$)/.test(probe.stdout)\n}\n\nfunction problem(run: { code: number | null, error?: string | null, stdout: string, stderr: string }, command: string): string | null {\n const code = codeOf(run)\n if (code === 0)\n return null\n if (code === null)\n return run.error ? `${command}: ${run.error}` : `${command}: no exit code`\n return `${command} exited ${code}: ${(run.stderr || run.stdout).trim() || '(no output)'}`\n}\n\nexport function createSystemdUserProvider(ctx: BootProviderContext): BootProvider {\n const mechanism = 'systemd-user' as const\n const unitOf = (spec: BootSpec): string => `${assertUnitName(spec.unitName)}.service`\n const pathOf = (spec: BootSpec): string => posixJoin(configHome(ctx), 'systemd', 'user', unitOf(spec))\n\n return {\n mechanism,\n\n async detect(): Promise<BootCandidate> {\n if (ctx.platform !== 'linux')\n return { mechanism, available: false, bootCapable: false, privileged: false, reason: 'systemd is Linux-only' }\n const bus = await userScopeReachable(ctx)\n if (!bus.reachable)\n return { mechanism, available: false, bootCapable: false, privileged: false, reason: bus.reason }\n const linger = await lingerEnabled(ctx)\n const privileged = linger || (await ctx.sudo())\n return {\n mechanism,\n available: true,\n bootCapable: linger,\n privileged,\n reason: linger\n ? 'a systemd user manager is reachable and linger is on, so the unit starts at boot'\n : 'a systemd user manager is reachable, but linger is off: the unit starts at login until `loginctl enable-linger` succeeds',\n }\n },\n\n async status(spec: BootSpec): Promise<BootProviderStatus> {\n try {\n const unit = unitOf(spec)\n const file = pathOf(spec)\n const own = inspectOwned(file, assertMarker(spec.marker))\n if (own.exists && !own.owned)\n return { state: 'not-installed', unitPath: file, detail: own.reason ?? 'foreign file', commands: [] }\n const probe = await readUnit(ctx, unit, 'user')\n const installed = own.owned || probe.installed\n const state: BootState = bootState(installed, probe.enabled, FAILED_RESULTS.has(probe.result))\n const user = currentUser(ctx)\n const linger = await lingerEnabled(ctx)\n const commands: string[] = []\n if (!linger && user)\n commands.push(shellCommand('sudo', ['loginctl', 'enable-linger', user]))\n const detail = `${probe.detail}; ${linger ? 'linger is on (boot-capable)' : 'linger is off (login-scoped)'}`\n return { state, unitPath: file, detail, commands }\n }\n catch (error) {\n return { state: 'not-installed', unitPath: null, detail: errorMessage(error), commands: [] }\n }\n },\n\n async install(spec: BootSpec): Promise<BootActionResult> {\n try {\n validate(spec)\n const unit = unitOf(spec)\n const file = pathOf(spec)\n const write = writeOwned(file, spec.marker, systemdUserUnit(spec), 0o644)\n if (write.refusal)\n return failed(write.refusal)\n\n const before = await readUnit(ctx, unit, 'user')\n let changed = write.changed\n if (write.changed || !before.enabled) {\n const reloadCommand = shellCommand('systemctl', ['--user', 'daemon-reload'])\n const reload = await ctx.run('systemctl', ['--user', 'daemon-reload'])\n const reloadProblem = problem(reload, reloadCommand)\n if (reloadProblem)\n return failed(reloadProblem, { changed, commands: [reloadCommand] })\n\n const enableCommand = shellCommand('systemctl', ['--user', 'enable', '--now', unit])\n const enable = await ctx.run('systemctl', ['--user', 'enable', '--now', unit])\n const enableProblem = problem(enable, enableCommand)\n if (enableProblem)\n return failed(enableProblem, { changed: true, commands: [enableCommand] })\n changed = true\n }\n\n const after = await readUnit(ctx, unit, 'user')\n if (!after.enabled)\n return failed(`unit ${unit} is not enabled after install (${after.detail})`, { changed })\n\n let linger = await lingerEnabled(ctx)\n const user = currentUser(ctx)\n const commands: string[] = []\n if (!linger && user) {\n const res = await ctx.run('loginctl', ['enable-linger', user])\n if (codeOf(res) === 0) {\n linger = true\n changed = true\n }\n else {\n commands.push(shellCommand('sudo', ['loginctl', 'enable-linger', user]))\n }\n }\n const detail = linger\n ? `${file} installed and enabled; linger is on, so ${unit} starts at boot`\n : `${file} installed and enabled, but linger is off: ${unit} starts at login only. ${commands.length ? `Run \\`${commands[0]}\\` to make it boot-capable.` : 'No target user could be determined to enable linger for.'}`\n return { ok: true, changed, detail, commands, needsPrivilege: !linger }\n }\n catch (error) {\n return failed(errorMessage(error))\n }\n },\n\n async uninstall(spec: BootSpec): Promise<BootActionResult> {\n try {\n validate(spec)\n const unit = unitOf(spec)\n const file = pathOf(spec)\n const own = inspectOwned(file, spec.marker)\n if (own.exists && !own.owned)\n return failed(own.reason ?? 'foreign file')\n\n const before = await readUnit(ctx, unit, 'user')\n if (!before.reachable && !own.exists) {\n return { ok: true, changed: false, detail: `no unit file at ${file} and systemctl is unavailable; nothing to remove`, commands: [], needsPrivilege: false }\n }\n // A unit of the same name can come from anywhere on the search path; with\n // no file of ours, disabling by name would stop somebody else's unit.\n if (!own.owned && !own.exists && before.installed)\n return failed(`a unit named ${unit} exists but no unit file of ours is at ${file}; refusing to disable a unit this plugin did not install`)\n if (own.owned && before.reachable) {\n const disableCommand = shellCommand('systemctl', ['--user', 'disable', '--now', unit])\n const disable = await ctx.run('systemctl', ['--user', 'disable', '--now', unit])\n const disableCode = codeOf(disable)\n if (disableCode !== 0 && disableCode !== 1 && disableCode !== 4)\n return failed(problem(disable, disableCommand) ?? 'disable failed', { commands: [disableCommand] })\n }\n\n const remove = removeOwned(file, spec.marker)\n if (remove.refusal)\n return failed(remove.refusal)\n\n let changed = remove.removed\n if (before.installed || remove.removed) {\n await ctx.run('systemctl', ['--user', 'daemon-reload'])\n changed = true\n }\n\n const after = await readUnit(ctx, unit, 'user')\n if (after.installed)\n return failed(`unit ${unit} is still known to systemd after removal (${after.detail})`, { changed })\n\n return {\n ok: true,\n changed,\n detail: remove.removed ? `disabled and removed ${file}` : `${file} was already gone`,\n commands: [],\n needsPrivilege: false,\n }\n }\n catch (error) {\n return failed(errorMessage(error))\n }\n },\n }\n}\n\nfunction systemUserName(ctx: BootProviderContext): string | null {\n const user = currentUser(ctx)\n return user && /^[A-Za-z_][A-Za-z0-9._-]*$/.test(user) ? user : null\n}\n\nfunction stageUnit(ctx: BootProviderContext, unit: string, content: string): string {\n const staged = posixJoin(tempDir(ctx), `home-hosted-${unit}`)\n fs.writeFileSync(staged, content, { mode: 0o644 })\n return staged\n}\n\nexport function createSystemdSystemProvider(ctx: BootProviderContext): BootProvider {\n const mechanism = 'systemd-system' as const\n const unitOf = (spec: BootSpec): string => `${assertUnitName(spec.unitName)}.service`\n const pathOf = (spec: BootSpec): string => posixJoin('/etc', 'systemd', 'system', unitOf(spec))\n const contentOf = (spec: BootSpec): string => systemdSystemUnit(spec, ctx.isRoot ? systemUserName(ctx) : null)\n\n const installCommands = (staged: string, file: string, unit: string): string[] => [\n shellCommand('sudo', ['install', '-m', '0644', staged, file]),\n shellCommand('sudo', ['systemctl', 'daemon-reload']),\n shellCommand('sudo', ['systemctl', 'enable', '--now', unit]),\n ]\n\n return {\n mechanism,\n\n async detect(): Promise<BootCandidate> {\n if (ctx.platform !== 'linux')\n return { mechanism, available: false, bootCapable: false, privileged: false, reason: 'systemd is Linux-only' }\n if (!existsOf(ctx, '/run/systemd/system'))\n return { mechanism, available: false, bootCapable: false, privileged: false, reason: 'systemd is not the init system here (no /run/systemd/system)' }\n const privileged = ctx.isRoot || (await ctx.sudo())\n return {\n mechanism,\n available: privileged,\n bootCapable: privileged,\n privileged,\n reason: privileged\n ? 'systemd is PID 1 and this process can use root, so a system unit starts at boot'\n : 'systemd is PID 1, but installing a system unit needs root or passwordless sudo',\n }\n },\n\n async status(spec: BootSpec): Promise<BootProviderStatus> {\n try {\n const unit = unitOf(spec)\n const file = pathOf(spec)\n const own = inspectOwned(file, assertMarker(spec.marker))\n if (own.exists && !own.owned)\n return { state: 'not-installed', unitPath: file, detail: own.reason ?? 'foreign file', commands: [] }\n const probe = await readUnit(ctx, unit, 'system')\n const installed = own.owned || probe.installed\n const state: BootState = bootState(installed, probe.enabled, FAILED_RESULTS.has(probe.result))\n const privileged = ctx.isRoot || (await ctx.sudo())\n const commands: string[] = []\n if (installed && !probe.enabled && !privileged)\n commands.push(shellCommand('sudo', ['systemctl', 'enable', '--now', unit]))\n return {\n state,\n unitPath: file,\n detail: `${probe.detail}${privileged ? '' : '; needs root to change'}`,\n commands,\n }\n }\n catch (error) {\n return { state: 'not-installed', unitPath: null, detail: errorMessage(error), commands: [] }\n }\n },\n\n async install(spec: BootSpec): Promise<BootActionResult> {\n try {\n validate(spec)\n const unit = unitOf(spec)\n const file = pathOf(spec)\n const content = contentOf(spec)\n const own = inspectOwned(file, spec.marker)\n if (own.exists && !own.owned)\n return failed(own.reason ?? 'foreign file')\n\n const before = await readUnit(ctx, unit, 'system')\n const changed = !own.exists || own.text !== content\n\n if (!ctx.isRoot && !(await ctx.sudo())) {\n const staged = stageUnit(ctx, unit, content)\n return failed(`installing a system unit needs root; the unit is staged at ${staged}`, {\n changed: false,\n needsPrivilege: true,\n commands: installCommands(staged, file, unit),\n })\n }\n\n if (ctx.isRoot) {\n const write = writeOwned(file, spec.marker, content, 0o644)\n if (write.refusal)\n return failed(write.refusal)\n }\n else {\n const staged = stageUnit(ctx, unit, content)\n const installCommand = shellCommand('sudo', ['install', '-m', '0644', staged, file])\n const install = await ctx.run('sudo', ['-n', 'install', '-m', '0644', staged, file])\n const installProblem = problem(install, installCommand)\n if (installProblem)\n return failed(installProblem, { needsPrivilege: true, commands: installCommands(staged, file, unit) })\n fs.rmSync(staged, { force: true })\n }\n\n if (changed || !before.enabled) {\n const sudoPrefix = ctx.isRoot ? [] : ['-n']\n const reloadCommand = shellCommand('sudo', ['systemctl', 'daemon-reload'])\n const reload = await ctx.run('sudo', [...sudoPrefix, 'systemctl', 'daemon-reload'])\n const reloadProblem = problem(reload, reloadCommand)\n if (reloadProblem)\n return failed(reloadProblem, { changed, needsPrivilege: !ctx.isRoot, commands: [reloadCommand] })\n\n const enableCommand = shellCommand('sudo', ['systemctl', 'enable', '--now', unit])\n const enable = await ctx.run('sudo', [...sudoPrefix, 'systemctl', 'enable', '--now', unit])\n const enableProblem = problem(enable, enableCommand)\n if (enableProblem)\n return failed(enableProblem, { changed: true, needsPrivilege: !ctx.isRoot, commands: [enableCommand] })\n }\n\n const after = await readUnit(ctx, unit, 'system')\n if (!after.enabled)\n return failed(`unit ${unit} is not enabled after install (${after.detail})`, { changed })\n\n return {\n ok: true,\n changed: changed || !before.enabled,\n detail: `${file} installed and enabled as a system unit (${after.detail})`,\n commands: [],\n needsPrivilege: !ctx.isRoot,\n }\n }\n catch (error) {\n return failed(errorMessage(error))\n }\n },\n\n async uninstall(spec: BootSpec): Promise<BootActionResult> {\n try {\n const unit = unitOf(spec)\n const file = pathOf(spec)\n const own = inspectOwned(file, spec.marker)\n if (own.exists && !own.owned)\n return failed(own.reason ?? 'foreign file')\n\n const privileged = ctx.isRoot || (await ctx.sudo())\n if (!privileged) {\n if (!own.exists)\n return { ok: true, changed: false, detail: `no unit file at ${file} and no privilege to change systemd; nothing to remove`, commands: [], needsPrivilege: false }\n return failed('removing a system unit needs root', {\n needsPrivilege: true,\n commands: [\n shellCommand('sudo', ['systemctl', 'disable', '--now', unit]),\n shellCommand('sudo', ['rm', '-f', file]),\n shellCommand('sudo', ['systemctl', 'daemon-reload']),\n ],\n })\n }\n\n const prefix = ctx.isRoot ? [] : ['-n']\n // With no file of ours at the path we write, a same-named unit belongs to\n // somebody else (a vendor unit in /usr/lib/systemd/system): leave it alone.\n if (!own.exists && !own.owned)\n return failed(`no unit file of ours at ${file}; refusing to disable a unit this plugin did not install`)\n const disableCommand = shellCommand('sudo', ['systemctl', 'disable', '--now', unit])\n const disable = await ctx.run('sudo', [...prefix, 'systemctl', 'disable', '--now', unit])\n const disableCode = codeOf(disable)\n if (disableCode !== 0 && disableCode !== 1 && disableCode !== 4)\n return failed(problem(disable, disableCommand) ?? 'disable failed', { needsPrivilege: !ctx.isRoot, commands: [disableCommand] })\n\n if (own.exists) {\n if (ctx.isRoot) {\n const remove = removeOwned(file, spec.marker)\n if (remove.refusal)\n return failed(remove.refusal)\n }\n else {\n // The check above ran as the invoking user, which cannot read a\n // root-only file; re-prove ownership before the privileged delete.\n if (!own.owned)\n return failed(own.reason ?? 'foreign file')\n const rmCommand = shellCommand('sudo', ['rm', '-f', file])\n const rm = await ctx.run('sudo', ['-n', 'rm', '-f', file])\n const rmProblem = problem(rm, rmCommand)\n if (rmProblem)\n return failed(rmProblem, { needsPrivilege: true, commands: [rmCommand] })\n }\n }\n\n await ctx.run('sudo', [...prefix, 'systemctl', 'daemon-reload'])\n const after = await readUnit(ctx, unit, 'system')\n if (after.installed)\n return failed(`unit ${unit} is still known to systemd after removal (${after.detail})`, { changed: true, needsPrivilege: !ctx.isRoot })\n\n return {\n ok: true,\n changed: own.exists || disableCode === 0,\n detail: own.exists ? `disabled and removed ${file}` : `${file} was already gone`,\n commands: [],\n needsPrivilege: !ctx.isRoot,\n }\n }\n catch (error) {\n return failed(errorMessage(error))\n }\n },\n }\n}\n", "/**\n * Escaping for every format this plugin writes.\n *\n * None of this builds a shell command: a unit file, a plist, a `.desktop`\n * entry, a task XML and a registry value each have their own parser, and each\n * value is quoted for exactly that parser. Values that carry control\n * characters (newlines included) are rejected outright, because a newline is\n * how a value escapes its field in every one of these formats.\n */\n\nconst CONTROL = /[\\u0000-\\u001F\\u007F]/\n\nexport function assertNoControl(value: string, what: string): string {\n if (CONTROL.test(value))\n throw new Error(`${what} must not contain control characters or newlines`)\n return value\n}\n\nexport function assertUnitName(name: string): string {\n if (!/^[A-Za-z0-9._@-]+$/.test(name))\n throw new Error(`unit name ${JSON.stringify(name)} must match ^[A-Za-z0-9._@-]+$`)\n if (name.startsWith('-') || name.startsWith('.') || name.includes('..'))\n throw new Error(`unit name ${JSON.stringify(name)} must not be option-like or traverse paths`)\n return name\n}\n\nexport function assertMarker(marker: string): string {\n if (marker.trim() === '')\n throw new Error('marker must not be empty')\n return assertNoControl(marker, 'marker')\n}\n\nexport function assertEnvKey(key: string): string {\n if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(key))\n throw new Error(`environment key ${JSON.stringify(key)} is not a valid name`)\n return key\n}\n\n/** POSIX-absolute, Windows-drive-absolute or UNC; checked without consulting the host OS. */\nexport function isAbsolutePath(value: string): boolean {\n return value.startsWith('/') || /^[A-Za-z]:[\\\\/]/.test(value) || value.startsWith('\\\\\\\\')\n}\n\nexport function assertAbsolute(value: string, what: string): string {\n if (!isAbsolutePath(value))\n throw new Error(`${what} must be absolute, got ${JSON.stringify(value)}`)\n return assertNoControl(value, what)\n}\n\nexport function assertLabel(value: string): string {\n if (value.trim() === '')\n throw new Error('label must not be empty')\n return assertNoControl(value, 'label')\n}\n\nexport function assertArg(value: string, what = 'argument'): string {\n return assertNoControl(value, what)\n}\n\nfunction replaceAll(value: string, pairs: Array<[string, string]>): string {\n let out = value\n for (const [from, to] of pairs)\n out = out.split(from).join(to)\n return out\n}\n\n/** Single-quote a value the way a POSIX shell would, for `commands[]`. */\nexport function shellQuote(value: string): string {\n if (value !== '' && /^[A-Za-z0-9._/:=@%+,-]+$/.test(value))\n return value\n return `'${value.split('\\'').join('\\'\\\\\\'\\'')}'`\n}\n\n/** The exact line a person can paste into a shell. */\nexport function shellCommand(program: string, args: string[]): string {\n return [program, ...args].map(shellQuote).join(' ')\n}\n\n// ---------------------------------------------------------------------------\n// systemd\n// ---------------------------------------------------------------------------\n\n/**\n * A word in `ExecStart=`/`ExecStop=`. systemd expands `%` specifiers and `$`\n * variables there before it splits the line, so both are pinned, and `;` \u2014 the\n * multi-command separator \u2014 is quoted rather than left bare.\n */\nexport function systemdExecWord(value: string): string {\n assertNoControl(value, 'ExecStart word')\n const escaped = replaceAll(value, [['\\\\', '\\\\\\\\'], ['\"', '\\\\\"'], ['$', '$$'], ['%', '%%']])\n return escaped !== value || /[\\s\"';]/.test(value) ? `\"${escaped}\"` : value\n}\n\n/**\n * A single-line free-text setting such as `Description=` (specifiers only).\n */\nexport function systemdText(value: string): string {\n assertNoControl(value, 'unit setting')\n // A trailing backslash would continue the directive onto the next line.\n return replaceAll(value, [['\\\\', '\\\\\\\\'], ['%', '%%']])\n}\n\n/**\n * A path setting (`WorkingDirectory=`). systemd does not unquote these, but it\n * does expand `%` specifiers (an unknown one is fatal, verified with\n * `systemd-analyze verify`), and a trailing `\\` continues the line into the next\n * directive. So both are escaped rather than passed raw.\n */\nexport function systemdPath(value: string, what = 'path'): string {\n assertAbsolute(value, what)\n assertNoControl(value, what)\n if (value.includes('\"'))\n throw new Error(`${what} must not contain a double quote: ${JSON.stringify(value)}`)\n return replaceAll(value, [['\\\\', '\\\\\\\\'], ['%', '%%']])\n}\n\n/** `Environment=KEY=value`, quoted as one assignment when the value needs it. */\nexport function systemdEnvLine(key: string, value: string): string {\n assertEnvKey(key)\n assertNoControl(value, `environment value for ${key}`)\n const escaped = replaceAll(value, [['\\\\', '\\\\\\\\'], ['\"', '\\\\\"'], ['%', '%%']])\n return escaped !== value || /[\\s\"']/.test(value) ? `\"${key}=${escaped}\"` : `${key}=${value}`\n}\n\n// ---------------------------------------------------------------------------\n// XML (launchd plist, scheduled-task XML)\n// ---------------------------------------------------------------------------\n\nexport function xmlEscape(value: string): string {\n assertNoControl(value, 'xml value')\n return replaceAll(value, [['&', '&amp;'], ['<', '&lt;'], ['>', '&gt;'], ['\"', '&quot;'], ['\\'', '&apos;']])\n}\n\nexport function xmlUnescape(value: string): string {\n return replaceAll(value, [['&lt;', '<'], ['&gt;', '>'], ['&quot;', '\"'], ['&apos;', '\\''], ['&amp;', '&']])\n}\n\n/** A marker inside an XML comment may not contain `--`. */\nexport function assertXmlCommentSafe(value: string): string {\n if (value.includes('--'))\n throw new Error('marker must not contain `--` when it is written inside an XML comment')\n return value\n}\n\n// ---------------------------------------------------------------------------\n// freedesktop .desktop\n// ---------------------------------------------------------------------------\n\nconst DESKTOP_RESERVED = /[\\s\"'\\\\><~|&;$*?#()`]/\n\nexport function desktopWord(value: string): string {\n assertNoControl(value, 'desktop Exec word')\n const escaped = replaceAll(value, [['\\\\', '\\\\\\\\'], ['\"', '\\\\\"'], ['`', '\\\\`'], ['$', '\\\\$'], ['%', '%%']])\n return DESKTOP_RESERVED.test(value) || escaped !== value ? `\"${escaped}\"` : value\n}\n\nexport function desktopExec(program: string, args: string[]): string {\n return [program, ...args].map(desktopWord).join(' ')\n}\n\n/** A `Key=value` line in a `.desktop` file; the marker is written verbatim. */\nexport function desktopValue(key: string, value: string): string {\n assertNoControl(value, `desktop ${key}`)\n if (key.includes('=') || key.includes('\\n'))\n throw new Error(`desktop key ${JSON.stringify(key)} is not valid`)\n return `${key}=${value}`\n}\n\n// ---------------------------------------------------------------------------\n// Windows\n// ---------------------------------------------------------------------------\n\n/** Quote one argv word the way `CreateProcess`/`cmd` parse a command line. */\nexport function windowsArg(value: string): string {\n assertNoControl(value, 'windows argument')\n if (value !== '' && !/[\\s\"]/.test(value))\n return value\n\n let out = '\"'\n let backslashes = 0\n for (const char of value) {\n if (char === '\\\\') {\n backslashes += 1\n continue\n }\n if (char === '\"') {\n out += `${'\\\\'.repeat(backslashes * 2 + 1)}\"`\n backslashes = 0\n continue\n }\n out += `${'\\\\'.repeat(backslashes)}${char}`\n backslashes = 0\n }\n out += `${'\\\\'.repeat(backslashes * 2)}\"`\n return out\n}\n\nexport function windowsCommandLine(program: string, args: string[]): string {\n return [program, ...args].map(windowsArg).join(' ')\n}\n\n/** A line for a `.cmd` wrapper: `%` is a batch metacharacter and is doubled. */\nexport function batchCommandLine(program: string, args: string[]): string {\n return batchEscape(windowsCommandLine(program, args))\n}\n\n/**\n * Make one already-quoted command line safe inside a batch file. `%` is doubled\n * last: the `^` inserted for a metacharacter must not itself gain a caret.\n */\nfunction batchEscape(line: string): string {\n assertNoControl(line, 'batch command line')\n return replaceAll(line, [\n ['^', '^^'],\n ['&', '^&'],\n ['|', '^|'],\n ['<', '^<'],\n ['>', '^>'],\n ['(', '^('],\n [')', '^)'],\n ['%', '%%'],\n ])\n}\n\n/** A single-quoted PowerShell literal. */\nexport function powershellLiteral(value: string): string {\n assertNoControl(value, 'powershell value')\n return `'${value.split('\\'').join('\\'\\'')}'`\n}\n\n/** Quote one word the way `cmd.exe` takes it, for a copy-pasteable `commands[]` entry. */\nexport function cmdQuote(value: string): string {\n if (value !== '' && !/[\\s\"&|<>^]/.test(value))\n return value\n return `\"${value.split('\"').join('\"\"')}\"`\n}\n\nexport function windowsDisplayCommand(program: string, args: string[]): string {\n return [program, ...args].map(cmdQuote).join(' ')\n}\n\n// ---------------------------------------------------------------------------\n// launchd / registry value names\n// ---------------------------------------------------------------------------\n\nexport function assertRegistryValueName(name: string): string {\n if (name.trim() === '')\n throw new Error('registry value name must not be empty')\n return assertNoControl(name, 'registry value name')\n}\n", "/**\n * launchd: a per-user agent (`~/Library/LaunchAgents`) and a system daemon\n * (`/Library/LaunchDaemons`). `launchctl print` is read for its exit code only\n * \u2014 its output is explicitly not API. Loading is `bootstrap`, unloading is\n * `bootout`, and exit 5 from bootstrap means the job is already loaded.\n */\nimport fs from 'node:fs'\nimport path from 'node:path'\nimport type { BootCandidate, BootState } from '../shared/contracts.js'\nimport type { BootActionResult, BootProvider, BootProviderContext, BootProviderStatus, BootSpec } from './types.js'\nimport {\n assertAbsolute,\n assertArg,\n assertEnvKey,\n assertLabel,\n assertMarker,\n assertUnitName,\n assertXmlCommentSafe,\n shellCommand,\n xmlEscape,\n} from './escape.js'\nimport {\n bootState,\n errorMessage,\n failed,\n inspectOwned,\n posixJoin,\n removeOwned,\n tempDir,\n uidOf,\n userNameOf,\n writeOwned,\n} from './common.js'\n\n/** Both scopes label with the same reverse-DNS prefix. */\nexport const LAUNCHD_LABEL_PREFIX = 'dev.home-hosted.'\n/** bootstrap on an already-loaded job reports EIO. */\nconst LAUNCHCTL_ALREADY_LOADED = 5\n/** `launchctl print` for a label that is not loaded. */\nconst LAUNCHCTL_NOT_LOADED = 113\n/** `launchctl bootout` for a job that is not there. */\nconst LAUNCHCTL_NO_SUCH_PROCESS = 3\n\nfunction validate(spec: BootSpec): void {\n assertUnitName(spec.unitName)\n assertMarker(spec.marker)\n assertLabel(spec.label)\n assertAbsolute(spec.command, 'spec.command')\n assertAbsolute(spec.cwd, 'spec.cwd')\n assertAbsolute(spec.logDir, 'spec.logDir')\n for (const arg of spec.args)\n assertArg(arg)\n for (const key of Object.keys(spec.env))\n assertEnvKey(key)\n}\n\nexport function launchdLabel(spec: BootSpec): string {\n return `${LAUNCHD_LABEL_PREFIX}${assertUnitName(spec.unitName)}`\n}\n\n/** The full property list. The marker rides in an XML comment, which launchd ignores. */\nexport interface LaunchdPlistOptions {\n /** Set for a LaunchDaemon: launchd would otherwise run the panel as root. */\n userName?: string | null\n}\n\nexport function launchdPlist(spec: BootSpec, options: LaunchdPlistOptions = {}): string {\n validate(spec)\n const label = launchdLabel(spec)\n const userName = options.userName?.trim()\n const out = path.posix.join(spec.logDir, `${label}.out.log`)\n const err = path.posix.join(spec.logDir, `${label}.err.log`)\n const envKeys = Object.keys(spec.env)\n const lines = [\n '<?xml version=\"1.0\" encoding=\"UTF-8\"?>',\n '<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">',\n '<plist version=\"1.0\">',\n '<dict>',\n '\\t<key>Label</key>',\n `\\t<string>${xmlEscape(label)}</string>`,\n ...(userName === undefined || userName.length === 0\n ? []\n : ['\\t<key>UserName</key>', `\\t<string>${xmlEscape(userName)}</string>`]),\n '\\t<key>ProgramArguments</key>',\n '\\t<array>',\n ...[spec.command, ...spec.args].map(arg => `\\t\\t<string>${xmlEscape(arg)}</string>`),\n '\\t</array>',\n '\\t<key>RunAtLoad</key>',\n '\\t<true/>',\n '\\t<key>KeepAlive</key>',\n '\\t<dict>',\n '\\t\\t<key>SuccessfulExit</key>',\n '\\t\\t<false/>',\n '\\t</dict>',\n '\\t<key>ThrottleInterval</key>',\n '\\t<integer>10</integer>',\n '\\t<key>WorkingDirectory</key>',\n `\\t<string>${xmlEscape(spec.cwd)}</string>`,\n ...(envKeys.length\n ? [\n '\\t<key>EnvironmentVariables</key>',\n '\\t<dict>',\n ...envKeys.flatMap(key => [`\\t\\t<key>${xmlEscape(key)}</key>`, `\\t\\t<string>${xmlEscape(spec.env[key] ?? '')}</string>`]),\n '\\t</dict>',\n ]\n : []),\n '\\t<key>StandardOutPath</key>',\n `\\t<string>${xmlEscape(out)}</string>`,\n '\\t<key>StandardErrorPath</key>',\n `\\t<string>${xmlEscape(err)}</string>`,\n `\\t<!-- Managed by ${assertXmlCommentSafe(spec.marker)} -->`,\n '</dict>',\n '</plist>',\n '',\n ]\n return lines.join('\\n')\n}\n\nfunction codeOf(result: { code: number | null, error?: string | null }): number | null {\n return result.error ? null : result.code\n}\n\nfunction problem(run: { code: number | null, error?: string | null, stdout: string, stderr: string }, command: string): string | null {\n const code = codeOf(run)\n if (code === 0)\n return null\n if (code === null)\n return run.error ? `${command}: ${run.error}` : `${command}: no exit code`\n return `${command} exited ${code}: ${(run.stderr || run.stdout).trim() || '(no output)'}`\n}\n\ntype LaunchdMode = 'agent' | 'daemon'\n\n/** Best effort: `/Library/LaunchDaemons` exists on macOS, and only the privileged write can create it. */\nfunction ensureDirQuiet(dir: string): void {\n try {\n fs.mkdirSync(dir, { recursive: true })\n }\n catch {\n // the privileged install reports the real failure\n }\n}\n\nfunction createLaunchdProvider(ctx: BootProviderContext, mode: LaunchdMode): BootProvider {\n const mechanism = mode === 'agent' ? 'launchd-agent' as const : 'launchd-daemon' as const\n const pathOf = (spec: BootSpec): string => mode === 'agent'\n ? posixJoin(ctx.home, 'Library', 'LaunchAgents', `${launchdLabel(spec)}.plist`)\n : posixJoin('/Library', 'LaunchDaemons', `${launchdLabel(spec)}.plist`)\n\n /** `system` for the daemon; `gui/$UID`, else `user/$UID` for the agent. */\n const domainOf = async (): Promise<string | null> => {\n if (mode === 'daemon')\n return 'system'\n const uid = uidOf(ctx)\n if (!uid)\n return null\n const gui = `gui/${uid}`\n if (codeOf(await ctx.run('launchctl', ['print', gui])) === 0)\n return gui\n const user = `user/${uid}`\n if (codeOf(await ctx.run('launchctl', ['print', user])) === 0)\n return user\n return null\n }\n\n const privileged = async (): Promise<boolean> =>\n mode === 'agent' ? true : ctx.isRoot || (await ctx.sudo())\n\n /** Root runs launchctl directly; everything else goes through `sudo -n`. */\n const runPrivileged = async (program: string, args: string[]) =>\n mode === 'agent' || ctx.isRoot ? await ctx.run(program, args) : await ctx.run('sudo', ['-n', program, ...args])\n\n /** The sudo form of what is left to do when this process cannot write the file itself. */\n const commands = (file: string, label: string): string[] => mode === 'agent'\n ? []\n : [\n shellCommand('sudo', ['launchctl', 'bootstrap', 'system', file]),\n shellCommand('sudo', ['launchctl', 'enable', `system/${label}`]),\n ]\n\n return {\n mechanism,\n\n async detect(): Promise<BootCandidate> {\n if (ctx.platform !== 'darwin')\n return { mechanism, available: false, bootCapable: false, privileged: false, reason: 'launchd is macOS-only' }\n if (mode === 'agent') {\n const domain = await domainOf()\n return {\n mechanism,\n // A plist in ~/Library/LaunchAgents is loaded at login whether or not\n // this process can reach launchd right now, so an unreachable domain\n // is a diagnostic, not a reason to refuse.\n available: true,\n bootCapable: false,\n privileged: true,\n reason: domain === null\n ? `a LaunchAgent loads at login; launchd's domain is not reachable from this process for uid ${uidOf(ctx) ?? '?'} right now, so it is loaded at the next login`\n : `launchd ${domain} domain is reachable; a LaunchAgent loads at login, not at boot`,\n }\n }\n const canElevate = ctx.isRoot || (await ctx.sudo())\n return {\n mechanism,\n // Always selectable: without root the plugin stages the plist and hands\n // over the three sudo commands, which is the only way to start before\n // login on a Mac that has no passwordless sudo.\n available: true,\n bootCapable: true,\n privileged: canElevate,\n reason: canElevate\n ? 'this process can write /Library/LaunchDaemons, so a LaunchDaemon starts at boot'\n : 'a LaunchDaemon starts at boot but needs root here, so the plugin stages the plist and shows the sudo commands',\n }\n },\n\n async status(spec: BootSpec): Promise<BootProviderStatus> {\n try {\n const file = pathOf(spec)\n const label = launchdLabel(spec)\n const own = inspectOwned(file, assertMarker(spec.marker))\n if (own.exists && !own.owned)\n return { state: 'not-installed', unitPath: file, detail: own.reason ?? 'foreign file', commands: [] }\n const domain = await domainOf()\n if (!own.owned)\n return { state: 'not-installed', unitPath: file, detail: `no plist at ${file}`, commands: [] }\n if (domain === null)\n return { state: 'enabled-running', unitPath: file, detail: `${file} is present; launchd has no reachable domain for uid ${uidOf(ctx) ?? '?'}, so it loads at the next login`, commands: [] }\n const probe = await ctx.run('launchctl', ['print', `${domain}/${label}`])\n const loaded = codeOf(probe) === 0\n const state: BootState = bootState(true, true, false)\n return {\n state,\n unitPath: file,\n detail: `${file} is present; ${loaded ? `loaded in ${domain}` : `not loaded right now (RunAtLoad loads it at the next login)`}`,\n commands: [],\n }\n }\n catch (error) {\n return { state: 'not-installed', unitPath: null, detail: errorMessage(error), commands: [] }\n }\n },\n\n async install(spec: BootSpec): Promise<BootActionResult> {\n try {\n validate(spec)\n const file = pathOf(spec)\n const label = launchdLabel(spec)\n const content = launchdPlist(spec, mode === 'daemon' ? { userName: userNameOf(ctx) } : {})\n const own = inspectOwned(file, spec.marker)\n if (own.exists && !own.owned)\n return failed(own.reason ?? 'foreign file')\n const staged = posixJoin(tempDir(ctx), `${label}.plist`)\n if (!(await privileged())) {\n // The command below installs this exact file, so it has to exist.\n ensureDirQuiet(path.posix.dirname(staged))\n fs.writeFileSync(staged, content, { mode: 0o644 })\n return failed('writing /Library/LaunchDaemons needs root; the plist is staged for you to install', {\n needsPrivilege: true,\n commands: [\n shellCommand('sudo', ['install', '-m', '0644', staged, file]),\n shellCommand('sudo', ['launchctl', 'bootstrap', 'system', file]),\n shellCommand('sudo', ['launchctl', 'enable', `system/${label}`]),\n ],\n })\n }\n\n const domain = await domainOf()\n\n ensureDirQuiet(path.posix.dirname(file))\n ensureDirQuiet(spec.logDir)\n\n const loaded = domain !== null && codeOf(await ctx.run('launchctl', ['print', `${domain}/${label}`])) === 0\n const before = { text: own.text, exists: own.exists }\n\n let changed = false\n if (mode === 'agent' || ctx.isRoot) {\n const write = writeOwned(file, spec.marker, content, 0o644)\n if (write.refusal)\n return failed(write.refusal)\n changed = write.changed\n }\n else {\n ensureDirQuiet(path.dirname(staged))\n fs.writeFileSync(staged, content, { mode: 0o644 })\n changed = !before.exists || before.text !== content\n if (!changed) {\n fs.rmSync(staged, { force: true })\n }\n else {\n const installCommand = shellCommand('sudo', ['install', '-m', '0644', staged, file])\n const install = await runPrivileged('install', ['-m', '0644', staged, file])\n if (codeOf(install) !== 0)\n return failed(problem(install, installCommand) ?? 'launchctl failed', { needsPrivilege: true, commands: [installCommand] })\n fs.rmSync(staged, { force: true })\n }\n }\n\n const lint = await runPrivileged('plutil', ['-lint', file])\n if (codeOf(lint) !== 0)\n return failed(`plutil -lint rejected the generated plist: ${(lint.stderr || lint.stdout).trim() || 'no output'}`, { changed, commands: commands(file, label) })\n\n if (domain === null) {\n return {\n ok: true,\n changed,\n detail: `${file} is in place; launchd's domain is not reachable from this process, so it loads at the next login`,\n commands: [],\n needsPrivilege: false,\n }\n }\n\n if (loaded && changed) {\n const bootout = await runPrivileged('launchctl', ['bootout', `${domain}/${label}`])\n const bootoutCode = codeOf(bootout)\n if (bootoutCode !== 0 && bootoutCode !== LAUNCHCTL_NO_SUCH_PROCESS && bootoutCode !== LAUNCHCTL_NOT_LOADED)\n return failed(problem(bootout, shellCommand('launchctl', ['bootout', `${domain}/${label}`])) ?? 'launchctl failed', { changed, commands: commands(file, label) })\n }\n\n if (changed || !loaded) {\n const boot = await runPrivileged('launchctl', ['bootstrap', domain, file])\n const bootCode = codeOf(boot)\n if (bootCode !== 0 && bootCode !== LAUNCHCTL_ALREADY_LOADED)\n return failed(problem(boot, shellCommand('launchctl', ['bootstrap', domain, file])) ?? 'launchctl failed', { changed, commands: commands(file, label) })\n if (bootCode === 0)\n changed = true\n const enable = await runPrivileged('launchctl', ['enable', `${domain}/${label}`])\n if (codeOf(enable) !== 0)\n return failed(problem(enable, shellCommand('launchctl', ['enable', `${domain}/${label}`])) ?? 'launchctl failed', { changed, commands: commands(file, label) })\n }\n\n const verify = await runPrivileged('launchctl', ['print', `${domain}/${label}`])\n if (codeOf(verify) !== 0)\n return failed(`launchctl print ${domain}/${label} did not confirm the job (exit ${String(codeOf(verify))})`, { changed, commands: commands(file, label) })\n\n return {\n ok: true,\n changed,\n detail: `${file} installed and loaded in ${domain}`,\n commands: [],\n needsPrivilege: mode === 'daemon' && !ctx.isRoot,\n }\n }\n catch (error) {\n return failed(errorMessage(error))\n }\n },\n\n async uninstall(spec: BootSpec): Promise<BootActionResult> {\n try {\n const file = pathOf(spec)\n const label = launchdLabel(spec)\n const own = inspectOwned(file, spec.marker)\n if (own.exists && !own.owned)\n return failed(own.reason ?? 'foreign file')\n if (mode === 'daemon' && !ctx.isRoot && !(await ctx.sudo())) {\n if (!own.exists)\n return { ok: true, changed: false, detail: `no plist at ${file} and no privilege to change launchd; nothing to remove`, commands: [], needsPrivilege: false }\n return failed('removing a LaunchDaemon needs root', {\n needsPrivilege: true,\n commands: [\n shellCommand('sudo', ['launchctl', 'bootout', `system/${label}`]),\n shellCommand('sudo', ['rm', '-f', file]),\n ],\n })\n }\n\n const domain = await domainOf()\n // A job under this label may belong to a plist we did not write; never\n // boot out a job whose own file is not ours.\n if (!own.exists && !own.owned)\n return failed(`no plist of ours at ${file}; refusing to unload a job this plugin did not install`)\n let changed = false\n if (domain !== null) {\n const bootout = await runPrivileged('launchctl', ['bootout', `${domain}/${label}`])\n const bootoutCode = codeOf(bootout)\n if (bootoutCode === 0)\n changed = true\n else if (bootoutCode !== LAUNCHCTL_NO_SUCH_PROCESS && bootoutCode !== LAUNCHCTL_NOT_LOADED)\n return failed(problem(bootout, shellCommand('launchctl', ['bootout', `${domain}/${label}`])) ?? 'launchctl failed', { commands: commands(file, label) })\n }\n\n if (own.exists) {\n if (mode === 'agent' || ctx.isRoot) {\n const remove = removeOwned(file, spec.marker)\n if (remove.refusal)\n return failed(remove.refusal)\n if (remove.removed)\n changed = true\n }\n else {\n // Re-prove ownership before the privileged delete: the check above\n // ran as the invoking user, which may not be able to read the file.\n if (!own.owned)\n return failed(own.reason ?? 'foreign file')\n const rmCommand = shellCommand('sudo', ['rm', '-f', file])\n const rm = await runPrivileged('rm', ['-f', file])\n if (codeOf(rm) !== 0)\n return failed(problem(rm, rmCommand) ?? 'launchctl failed', { needsPrivilege: true, commands: [rmCommand] })\n changed = true\n }\n }\n\n if (domain !== null) {\n const verify = await runPrivileged('launchctl', ['print', `${domain}/${label}`])\n if (codeOf(verify) === 0)\n return failed(`${label} is still loaded in ${domain} after bootout`, { changed })\n }\n\n return {\n ok: true,\n changed,\n detail: own.exists ? `unloaded and removed ${file}` : `no plist at ${file} (already gone)`,\n commands: [],\n needsPrivilege: mode === 'daemon' && !ctx.isRoot,\n }\n }\n catch (error) {\n return failed(errorMessage(error))\n }\n },\n }\n}\n\nexport function createLaunchdAgentProvider(ctx: BootProviderContext): BootProvider {\n return createLaunchdProvider(ctx, 'agent')\n}\n\nexport function createLaunchdDaemonProvider(ctx: BootProviderContext): BootProvider {\n return createLaunchdProvider(ctx, 'daemon')\n}\n", "/**\n * freedesktop XDG autostart: `~/.config/autostart/<unitName>.desktop`.\n * This runs at login, never at boot, and needs no privilege. `Exec=` is not a\n * shell, so every word is quoted for the desktop entry parser and `$`/`%` are\n * escaped rather than expanded.\n */\nimport fs from 'node:fs'\nimport path from 'node:path'\nimport type { BootCandidate, BootState } from '../shared/contracts.js'\nimport type { BootActionResult, BootProvider, BootProviderContext, BootProviderStatus, BootSpec } from './types.js'\nimport { assertAbsolute, assertArg, assertEnvKey, assertLabel, assertMarker, assertUnitName, desktopExec } from './escape.js'\nimport { bootState, configHome, errorMessage, failed, inspectOwned, posixJoin, removeOwned, writeOwned } from './common.js'\n\nfunction validate(spec: BootSpec): void {\n assertUnitName(spec.unitName)\n assertMarker(spec.marker)\n assertLabel(spec.label)\n assertAbsolute(spec.command, 'spec.command')\n assertAbsolute(spec.cwd, 'spec.cwd')\n for (const arg of spec.args)\n assertArg(arg)\n for (const key of Object.keys(spec.env))\n assertEnvKey(key)\n}\n\nexport function xdgDesktopEntry(spec: BootSpec): string {\n validate(spec)\n return `${[\n '[Desktop Entry]',\n 'Type=Application',\n `Name=${spec.label}`,\n `Comment=home-hosted daemon, managed by ${spec.marker}`,\n `Exec=${desktopExec(spec.command, spec.args)}`,\n `Path=${spec.cwd}`,\n 'Terminal=false',\n 'X-GNOME-Autostart-enabled=true',\n `X-HomeHosted-Marker=${spec.marker}`,\n '',\n ].join('\\n')}`\n}\n\nfunction desktopFlag(text: string, key: string): string | null {\n for (const line of text.split('\\n')) {\n const trimmed = line.trim()\n if (trimmed.startsWith(`${key}=`))\n return trimmed.slice(key.length + 1).trim()\n }\n return null\n}\n\nexport function createXdgAutostartProvider(ctx: BootProviderContext): BootProvider {\n const mechanism = 'xdg-autostart' as const\n const unitOf = (spec: BootSpec): string => `${assertUnitName(spec.unitName)}.desktop`\n const pathOf = (spec: BootSpec): string => posixJoin(configHome(ctx), 'autostart', unitOf(spec))\n\n return {\n mechanism,\n\n async detect(): Promise<BootCandidate> {\n if (ctx.platform !== 'linux')\n return { mechanism, available: false, bootCapable: false, privileged: false, reason: 'XDG autostart is Linux-only' }\n return {\n mechanism,\n available: true,\n bootCapable: false,\n privileged: true,\n reason: `a .desktop entry under ${posixJoin(configHome(ctx), 'autostart')} needs no privilege, but it starts at login rather than at boot`,\n }\n },\n\n async status(spec: BootSpec): Promise<BootProviderStatus> {\n try {\n const file = pathOf(spec)\n const own = inspectOwned(file, assertMarker(spec.marker))\n if (own.exists && !own.owned)\n return { state: 'not-installed', unitPath: file, detail: own.reason ?? 'foreign file', commands: [] }\n if (!own.owned || own.text === null)\n return { state: 'not-installed', unitPath: file, detail: `no autostart entry at ${file}`, commands: [] }\n const enabled = desktopFlag(own.text, 'X-GNOME-Autostart-enabled') !== 'false'\n && desktopFlag(own.text, 'Hidden') !== 'true'\n const state: BootState = bootState(true, enabled, false)\n return {\n state,\n unitPath: file,\n detail: `${file} is present; ${enabled ? 'it starts at login' : 'it is disabled'} (login scope, not boot)`,\n commands: [],\n }\n }\n catch (error) {\n return { state: 'not-installed', unitPath: null, detail: errorMessage(error), commands: [] }\n }\n },\n\n async install(spec: BootSpec): Promise<BootActionResult> {\n try {\n validate(spec)\n const file = pathOf(spec)\n fs.mkdirSync(path.dirname(file), { recursive: true })\n const write = writeOwned(file, spec.marker, xdgDesktopEntry(spec), 0o644)\n if (write.refusal)\n return failed(write.refusal)\n\n const text = inspectOwned(file, spec.marker).text\n const enabled = text !== null\n && desktopFlag(text, 'X-GNOME-Autostart-enabled') !== 'false'\n && desktopFlag(text, 'Hidden') !== 'true'\n if (!enabled)\n return failed(`${file} was written but does not read back as enabled`, { changed: write.changed })\n\n return {\n ok: true,\n changed: write.changed,\n detail: write.changed\n ? `${file} installed; it starts at login (not at boot)`\n : `${file} was already installed and enabled`,\n commands: [],\n needsPrivilege: false,\n }\n }\n catch (error) {\n return failed(errorMessage(error))\n }\n },\n\n async uninstall(spec: BootSpec): Promise<BootActionResult> {\n try {\n const file = pathOf(spec)\n const own = inspectOwned(file, spec.marker)\n if (own.exists && !own.owned)\n return failed(own.reason ?? 'foreign file')\n const remove = removeOwned(file, spec.marker)\n if (remove.refusal)\n return failed(remove.refusal)\n return {\n ok: true,\n changed: remove.removed,\n detail: remove.removed ? `removed ${file}` : `${file} was already gone`,\n commands: [],\n needsPrivilege: false,\n }\n }\n catch (error) {\n return failed(errorMessage(error))\n }\n },\n }\n}\n", "/**\n * Windows: the per-user `Run` key (login scope, no admin) and a scheduled task\n * (admin). `sc.exe` is never used \u2014 a plain Node process has no service\n * dispatcher and would fail with error 1053.\n *\n * The `Run` key starts *every* value it holds, so the ownership marker cannot\n * live beside the command there; it lives under this plugin's own key\n * (`HKCU\\Software\\home-hosted`), and a `Run` value is only touched when that\n * marker proves we wrote it.\n */\nimport fs from 'node:fs'\nimport path from 'node:path'\nimport type { BootCandidate, BootState } from '../shared/contracts.js'\nimport type { BootActionResult, BootProvider, BootProviderContext, BootProviderStatus, BootSpec } from './types.js'\nimport {\n assertAbsolute,\n assertArg,\n assertEnvKey,\n assertLabel,\n assertMarker,\n assertRegistryValueName,\n assertUnitName,\n batchCommandLine,\n powershellLiteral,\n windowsArg,\n windowsCommandLine,\n windowsDisplayCommand,\n xmlEscape,\n xmlUnescape,\n} from './escape.js'\nimport { bootState, errorMessage, failed, inspectOwned, localAppData, removeOwned, tempDir, writeOwned } from './common.js'\n\nexport const RUN_KEY = 'HKCU\\\\Software\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Run'\nexport const MARKER_KEY = 'HKCU\\\\Software\\\\home-hosted'\nconst RUN_VALUE_LIMIT = 260\n\nfunction validate(spec: BootSpec): void {\n assertUnitName(spec.unitName)\n assertMarker(spec.marker)\n assertLabel(spec.label)\n assertAbsolute(spec.command, 'spec.command')\n assertAbsolute(spec.cwd, 'spec.cwd')\n for (const arg of spec.args)\n assertArg(arg)\n for (const key of Object.keys(spec.env))\n assertEnvKey(key)\n}\n\nfunction codeOf(result: { code: number | null, error?: string | null }): number | null {\n return result.error ? null : result.code\n}\n\nfunction problem(run: { code: number | null, error?: string | null, stdout: string, stderr: string }, command: string): string | null {\n const code = codeOf(run)\n if (code === 0)\n return null\n if (code === null)\n return run.error ? `${command}: ${run.error}` : `${command}: no exit code`\n return `${command} exited ${code}: ${(run.stderr || run.stdout).trim() || '(no output)'}`\n}\n\ninterface RegValue {\n exists: boolean\n data: string | null\n}\n\nasync function queryReg(ctx: BootProviderContext, key: string, name: string): Promise<RegValue> {\n const res = await ctx.run('reg.exe', ['query', key, '/v', name])\n if (res.error || res.code !== 0)\n return { exists: false, data: null }\n for (const line of res.stdout.split(/\\r?\\n/)) {\n const match = /^\\s{2,}(.+?)\\s{2,}(REG_[A-Z_]+)\\s{2,}(.*)$/.exec(line)\n if (match && match[1]?.trim() === name)\n return { exists: true, data: (match[3] ?? '').trim() }\n }\n return { exists: false, data: null }\n}\n\nexport interface WindowsRunPayload {\n /** The exact `Run` value data. */\n data: string\n /** Set when the command line exceeded the `Run` value limit and a `.cmd` wrapper is needed. */\n wrapperPath: string | null\n wrapperContent: string | null\n}\n\nexport function windowsRunPayload(ctx: BootProviderContext, spec: BootSpec): WindowsRunPayload {\n const direct = windowsCommandLine(spec.command, spec.args)\n if (direct.length <= RUN_VALUE_LIMIT)\n return { data: direct, wrapperPath: null, wrapperContent: null }\n const wrapperPath = path.join(localAppData(ctx), 'home-hosted', `${spec.unitName}.cmd`)\n return {\n data: `cmd.exe /c ${windowsArg(wrapperPath)}`,\n wrapperPath,\n wrapperContent: `@echo off\\r\\nrem ${spec.marker}\\r\\n${batchCommandLine(spec.command, spec.args)}\\r\\n`,\n }\n}\n\nfunction createWindowsRunProviderImpl(ctx: BootProviderContext): BootProvider {\n const mechanism = 'windows-run' as const\n const nameOf = (spec: BootSpec): string => assertRegistryValueName(assertUnitName(spec.unitName))\n\n const addValue = (key: string, name: string, data: string) =>\n ctx.run('reg.exe', ['add', key, '/v', name, '/t', 'REG_SZ', '/d', data, '/f'])\n\n return {\n mechanism,\n\n async detect(): Promise<BootCandidate> {\n if (ctx.platform !== 'win32')\n return { mechanism, available: false, bootCapable: false, privileged: false, reason: 'the Run key is Windows-only' }\n return {\n mechanism,\n available: true,\n bootCapable: false,\n privileged: true,\n reason: `HKCU\\\\\u2026\\\\Run needs no admin, but it starts at login rather than at boot`,\n }\n },\n\n async status(spec: BootSpec): Promise<BootProviderStatus> {\n try {\n const name = nameOf(spec)\n const marker = assertMarker(spec.marker)\n const value = await queryReg(ctx, RUN_KEY, name)\n if (!value.exists)\n return { state: 'not-installed', unitPath: RUN_KEY, detail: `no ${RUN_KEY}\\\\${name} value`, commands: [] }\n const markerValue = await queryReg(ctx, MARKER_KEY, name)\n const owned = markerValue.data?.includes(marker) === true\n if (!owned)\n return { state: 'not-installed', unitPath: RUN_KEY, detail: `${name} exists under ${RUN_KEY} but is not marked as ours; refusing to treat it as this plugin's entry`, commands: [] }\n const state: BootState = bootState(true, true, false)\n return { state, unitPath: RUN_KEY, detail: `${RUN_KEY}\\\\${name} starts at login (not at boot)`, commands: [] }\n }\n catch (error) {\n return { state: 'not-installed', unitPath: RUN_KEY, detail: errorMessage(error), commands: [] }\n }\n },\n\n async install(spec: BootSpec): Promise<BootActionResult> {\n try {\n validate(spec)\n const name = nameOf(spec)\n const marker = assertMarker(spec.marker)\n const payload = windowsRunPayload(ctx, spec)\n const wrapperExists = payload.wrapperPath !== null && fs.existsSync(payload.wrapperPath)\n const wrapperOwn = payload.wrapperPath ? inspectOwned(payload.wrapperPath, marker) : null\n if (wrapperOwn?.exists && !wrapperOwn.owned)\n return failed(wrapperOwn.reason ?? 'foreign wrapper')\n\n const markerValue = await queryReg(ctx, MARKER_KEY, name)\n const owned = markerValue.data?.includes(marker) === true\n const current = await queryReg(ctx, RUN_KEY, name)\n // A value the marker does not prove is ours is never touched and never\n // claimed, even when it already equals what we would write.\n if (current.exists && !owned)\n return failed(`${RUN_KEY}\\\\${name} already exists and was not written by this plugin; refusing to overwrite it`)\n\n const commands: string[] = [\n windowsDisplayCommand('reg.exe', ['add', RUN_KEY, '/v', name, '/t', 'REG_SZ', '/d', payload.data, '/f']),\n ]\n\n let changed = false\n if (payload.wrapperPath && payload.wrapperContent) {\n const write = writeOwned(payload.wrapperPath, marker, payload.wrapperContent, 0o644)\n if (write.refusal)\n return failed(write.refusal)\n changed = write.changed || changed\n }\n\n if (!current.exists || current.data !== payload.data) {\n const add = await addValue(RUN_KEY, name, payload.data)\n const addProblem = problem(add, commands[0] ?? 'reg.exe add')\n if (addProblem)\n return failed(addProblem, { changed, commands })\n changed = true\n }\n if (!owned) {\n const mark = await addValue(MARKER_KEY, name, marker)\n const markProblem = problem(mark, windowsDisplayCommand('reg.exe', ['add', MARKER_KEY, '/v', name, '/t', 'REG_SZ', '/d', marker, '/f']))\n if (markProblem)\n return failed(markProblem, { changed, commands })\n changed = true\n }\n\n const after = await queryReg(ctx, RUN_KEY, name)\n if (after.data !== payload.data)\n return failed(`${RUN_KEY}\\\\${name} does not read back as the value that was written`, { changed, commands })\n\n // A wrapper we no longer need is cleaned up so the Run value converges on the direct form.\n if (!payload.wrapperPath && wrapperExists && wrapperOwn?.owned) {\n removeOwned(path.join(localAppData(ctx), 'home-hosted', `${spec.unitName}.cmd`), marker)\n }\n\n return {\n ok: true,\n changed,\n detail: changed ? `${RUN_KEY}\\\\${name} installed; it starts at login (not at boot)` : `${RUN_KEY}\\\\${name} was already installed`,\n commands: [],\n needsPrivilege: false,\n }\n }\n catch (error) {\n return failed(errorMessage(error))\n }\n },\n\n async uninstall(spec: BootSpec): Promise<BootActionResult> {\n try {\n const name = nameOf(spec)\n const marker = assertMarker(spec.marker)\n const current = await queryReg(ctx, RUN_KEY, name)\n const markerValue = await queryReg(ctx, MARKER_KEY, name)\n const owned = markerValue.data?.includes(marker) === true\n if (current.exists && !owned) {\n const payload = windowsRunPayload(ctx, spec)\n const wrapperOwned = payload.wrapperPath !== null ? inspectOwned(payload.wrapperPath, marker).owned : false\n if (current.data !== payload.data && !wrapperOwned)\n return failed(`${RUN_KEY}\\\\${name} is not marked as ours; refusing to delete a foreign Run value`)\n }\n\n let changed = false\n if (current.exists) {\n const del = await ctx.run('reg.exe', ['delete', RUN_KEY, '/v', name, '/f'])\n const delCode = codeOf(del)\n if (delCode !== 0 && delCode !== 1)\n return failed(problem(del, windowsDisplayCommand('reg.exe', ['delete', RUN_KEY, '/v', name, '/f'])) ?? 'reg.exe delete failed')\n changed = delCode === 0\n }\n if (owned) {\n await ctx.run('reg.exe', ['delete', MARKER_KEY, '/v', name, '/f'])\n changed = true\n }\n\n const payload = windowsRunPayload(ctx, spec)\n if (payload.wrapperPath) {\n const remove = removeOwned(payload.wrapperPath, marker)\n if (remove.refusal)\n return failed(remove.refusal)\n changed = remove.removed || changed\n }\n const stale = path.join(localAppData(ctx), 'home-hosted', `${spec.unitName}.cmd`)\n const staleRemove = removeOwned(stale, marker)\n if (staleRemove.refusal)\n return failed(staleRemove.refusal)\n changed = staleRemove.removed || changed\n\n const after = await queryReg(ctx, RUN_KEY, name)\n if (after.exists)\n return failed(`${RUN_KEY}\\\\${name} still exists after removal`, { changed })\n\n return {\n ok: true,\n changed,\n detail: changed ? `removed ${RUN_KEY}\\\\${name}` : `${RUN_KEY}\\\\${name} was already gone`,\n commands: [],\n needsPrivilege: false,\n }\n }\n catch (error) {\n return failed(errorMessage(error))\n }\n },\n }\n}\n\n// ---------------------------------------------------------------------------\n// Scheduled task\n// ---------------------------------------------------------------------------\n\nexport function scheduledTaskXml(spec: BootSpec): string {\n validate(spec)\n const args = spec.args.map(windowsArg).join(' ')\n return `${[\n '<?xml version=\"1.0\" encoding=\"UTF-16\"?>',\n '<Task version=\"1.2\" xmlns=\"http://schemas.microsoft.com/windows/2004/02/mit/task\">',\n '<RegistrationInfo>',\n `<Description>${xmlEscape(spec.marker)}</Description>`,\n '</RegistrationInfo>',\n '<Triggers>',\n '<LogonTrigger>',\n '<Enabled>true</Enabled>',\n '</LogonTrigger>',\n '</Triggers>',\n '<Principals>',\n '<Principal id=\"Author\">',\n '<LogonType>InteractiveToken</LogonType>',\n '<RunLevel>LeastPrivilege</RunLevel>',\n '</Principal>',\n '</Principals>',\n '<Settings>',\n '<MultipleInstancesPolicy>IgnoreNew</MultipleInstancesPolicy>',\n '<DisallowStartIfOnBatteries>false</DisallowStartIfOnBatteries>',\n '<StopIfGoingOnBatteries>false</StopIfGoingOnBatteries>',\n '<StartWhenAvailable>true</StartWhenAvailable>',\n '<RestartOnFailure>',\n '<Interval>PT1M</Interval>',\n '<Count>3</Count>',\n '</RestartOnFailure>',\n '<ExecutionTimeLimit>PT0S</ExecutionTimeLimit>',\n '</Settings>',\n '<Actions Context=\"Author\">',\n '<Exec>',\n `<Command>${xmlEscape(spec.command)}</Command>`,\n `<Arguments>${xmlEscape(args)}</Arguments>`,\n `<WorkingDirectory>${xmlEscape(spec.cwd)}</WorkingDirectory>`,\n '</Exec>',\n '</Actions>',\n '</Task>',\n '',\n ].join('\\r\\n')}`\n}\n\nexport function registerTaskScript(spec: BootSpec): string {\n validate(spec)\n const args = spec.args.map(windowsArg).join(' ')\n return [\n `$action = New-ScheduledTaskAction -Execute ${powershellLiteral(spec.command)} -Argument ${powershellLiteral(args)} -WorkingDirectory ${powershellLiteral(spec.cwd)}`,\n '$trigger = New-ScheduledTaskTrigger -AtLogOn',\n '$settings = New-ScheduledTaskSettingsSet -RestartCount 3 -RestartInterval (New-TimeSpan -Minutes 1) -StartWhenAvailable -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries',\n `Register-ScheduledTask -TaskName ${powershellLiteral(spec.unitName)} -Action $action -Trigger $trigger -Settings $settings -Description ${powershellLiteral(spec.marker)} -Force | Out-Null`,\n ].join('; ')\n}\n\nexport function unregisterTaskScript(name: string): string {\n return `Unregister-ScheduledTask -TaskName ${powershellLiteral(assertUnitName(name))} -Confirm:$false`\n}\n\nfunction xmlTag(xml: string, tag: string): string | null {\n const match = new RegExp(`<${tag}>([\\\\s\\\\S]*?)</${tag}>`).exec(xml)\n return match?.[1] === undefined ? null : xmlUnescape(match[1].trim())\n}\n\ninterface TaskInfo {\n exists: boolean\n xml: string | null\n marked: boolean\n matches: boolean\n}\n\nexport function createWindowsTaskProvider(ctx: BootProviderContext): BootProvider {\n const mechanism = 'windows-task' as const\n const nameOf = (spec: BootSpec): string => assertUnitName(spec.unitName)\n\n const query = async (name: string): Promise<{ exists: boolean, xml: string | null }> => {\n const res = await ctx.run('schtasks.exe', ['/Query', '/TN', name, '/XML'])\n if (res.error || res.code !== 0)\n return { exists: false, xml: null }\n return { exists: true, xml: res.stdout }\n }\n\n const inspect = async (spec: BootSpec): Promise<TaskInfo> => {\n const found = await query(nameOf(spec))\n if (!found.exists || found.xml === null)\n return { exists: false, xml: null, marked: false, matches: false }\n const marked = xmlUnescape(found.xml).includes(spec.marker)\n const args = spec.args.map(windowsArg).join(' ')\n const matches = marked\n && xmlTag(found.xml, 'Command') === spec.command\n && xmlTag(found.xml, 'Arguments') === args\n && (xmlTag(found.xml, 'WorkingDirectory') ?? spec.cwd) === spec.cwd\n return { exists: true, xml: found.xml, marked, matches }\n }\n\n const hasRegisterCmdlet = async (): Promise<boolean> => {\n const probe = await ctx.run('powershell.exe', ['-NoProfile', '-Command', 'Get-Command Register-ScheduledTask'])\n return probe.error === undefined || probe.error === null\n ? /Register-ScheduledTask/.test(probe.stdout)\n : false\n }\n\n const isElevated = async (): Promise<boolean> => {\n const script = '([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)'\n const probe = await ctx.run('powershell.exe', ['-NoProfile', '-Command', script])\n return probe.error === undefined || probe.error === null ? /^true$/im.test(probe.stdout.trim()) : false\n }\n\n return {\n mechanism,\n\n async detect(): Promise<BootCandidate> {\n if (ctx.platform !== 'win32')\n return { mechanism, available: false, bootCapable: false, privileged: false, reason: 'scheduled tasks are Windows-only' }\n const elevated = await isElevated()\n return {\n mechanism,\n available: elevated,\n bootCapable: false,\n privileged: elevated,\n reason: elevated\n ? 'administrator rights are available; the task is registered for logon (not for boot)'\n : 'registering a scheduled task needs an elevated process',\n }\n },\n\n async status(spec: BootSpec): Promise<BootProviderStatus> {\n try {\n const name = nameOf(spec)\n const info = await inspect(spec)\n if (!info.exists)\n return { state: 'not-installed', unitPath: null, detail: `no scheduled task named ${name}`, commands: [] }\n if (!info.marked)\n return { state: 'not-installed', unitPath: null, detail: `task ${name} exists but does not carry this plugin's marker; refusing to treat it as this plugin's entry`, commands: [] }\n const state: BootState = bootState(true, true, false)\n return { state, unitPath: null, detail: `scheduled task ${name} is registered (runs at logon, not at boot)`, commands: [] }\n }\n catch (error) {\n return { state: 'not-installed', unitPath: null, detail: errorMessage(error), commands: [] }\n }\n },\n\n async install(spec: BootSpec): Promise<BootActionResult> {\n try {\n validate(spec)\n const name = nameOf(spec)\n const info = await inspect(spec)\n if (info.exists && !info.marked)\n return failed(`scheduled task ${name} already exists and was not written by this plugin; refusing to overwrite it`)\n if (!(await isElevated()))\n return failed('registering a scheduled task needs an elevated process', { needsPrivilege: true })\n\n const elevatedCommands = [\n windowsDisplayCommand('powershell.exe', ['-NoProfile', '-Command', unregisterTaskScript(name)]),\n windowsDisplayCommand('schtasks.exe', ['/Query', '/TN', name, '/XML']),\n ]\n\n if (info.exists && info.matches) {\n const verify = await query(name)\n if (verify.exists)\n return { ok: true, changed: false, detail: `scheduled task ${name} is already registered`, commands: [], needsPrivilege: true }\n }\n\n const cmdlet = await hasRegisterCmdlet()\n if (cmdlet) {\n const script = registerTaskScript(spec)\n const res = await ctx.run('powershell.exe', ['-NoProfile', '-Command', script])\n if (codeOf(res) !== 0)\n return failed(problem(res, windowsDisplayCommand('powershell.exe', ['-NoProfile', '-Command', script])) ?? 'Register-ScheduledTask failed', { needsPrivilege: true, commands: elevatedCommands })\n }\n else {\n const xmlFile = path.join(tempDir(ctx), `${name}.xml`)\n fs.mkdirSync(path.dirname(xmlFile), { recursive: true })\n fs.writeFileSync(xmlFile, Buffer.from(`\\uFEFF${scheduledTaskXml(spec)}`, 'utf16le'))\n const createCommand = windowsDisplayCommand('schtasks.exe', ['/Create', '/TN', name, '/XML', xmlFile, '/F'])\n const create = await ctx.run('schtasks.exe', ['/Create', '/TN', name, '/XML', xmlFile, '/F'])\n if (codeOf(create) !== 0)\n return failed(problem(create, createCommand) ?? 'schtasks /Create failed', { needsPrivilege: true, commands: [createCommand] })\n fs.rmSync(xmlFile, { force: true })\n }\n\n const after = await query(name)\n if (!after.exists)\n return failed(`scheduled task ${name} was not found after registration`, { changed: true, needsPrivilege: true, commands: elevatedCommands })\n\n return {\n ok: true,\n changed: true,\n detail: `scheduled task ${name} registered (runs at logon, not at boot)`,\n commands: [],\n needsPrivilege: true,\n }\n }\n catch (error) {\n return failed(errorMessage(error))\n }\n },\n\n async uninstall(spec: BootSpec): Promise<BootActionResult> {\n try {\n const name = nameOf(spec)\n const info = await inspect(spec)\n if (!info.exists)\n return { ok: true, changed: false, detail: `no scheduled task named ${name}; already gone`, commands: [], needsPrivilege: false }\n if (!info.marked)\n return failed(`scheduled task ${name} is not marked as ours; refusing to delete a foreign task`)\n if (!(await isElevated()))\n return failed('deleting a scheduled task needs an elevated process', { needsPrivilege: true })\n\n const cmdlet = await hasRegisterCmdlet()\n const res = cmdlet\n ? await ctx.run('powershell.exe', ['-NoProfile', '-Command', unregisterTaskScript(name)])\n : await ctx.run('schtasks.exe', ['/Delete', '/TN', name, '/F'])\n const code = codeOf(res)\n if (code !== 0 && code !== 1)\n return failed(problem(res, cmdlet ? 'powershell.exe Unregister-ScheduledTask' : windowsDisplayCommand('schtasks.exe', ['/Delete', '/TN', name, '/F'])) ?? 'unregistering the task failed', { needsPrivilege: true })\n\n const after = await query(name)\n if (after.exists)\n return failed(`scheduled task ${name} still exists after removal`, { changed: true, needsPrivilege: true })\n\n return {\n ok: true,\n changed: true,\n detail: `unregistered scheduled task ${name}`,\n commands: [],\n needsPrivilege: true,\n }\n }\n catch (error) {\n return failed(errorMessage(error))\n }\n },\n }\n}\n\nexport function createWindowsRunProvider(ctx: BootProviderContext): BootProvider {\n return createWindowsRunProviderImpl(ctx)\n}\n", "/**\n * The two terminals of the ladder: a container (an OS boot entry would land\n * outside it, so the right answer is the container's own restart policy) and a\n * platform this plugin has no mechanism for.\n */\n\nimport type { BootCandidate } from '../shared/contracts.js'\nimport type { BootActionResult, BootProvider, BootProviderContext, BootProviderStatus, BootSpec } from './types.js'\nimport { readText } from '../util/fsx.js'\nimport { failed, existsOf } from './common.js'\n\nconst RESTART_POLICY = 'use the container restart policy instead: `docker run --restart unless-stopped`, or `restart: unless-stopped` in a compose file'\n\n/** A human-readable description of the container we are inside, or null. */\nexport function detectContainer(ctx: BootProviderContext): string | null {\n if (existsOf(ctx, '/.dockerenv'))\n return 'Docker (/.dockerenv)'\n if (existsOf(ctx, '/run/.containerenv'))\n return 'Podman (/run/.containerenv)'\n if (ctx.env.container?.trim())\n return `container environment (container=${ctx.env.container.trim()})`\n const cgroup = existsOf(ctx, '/proc/1/cgroup') ? readText('/proc/1/cgroup') : null\n if (cgroup) {\n if (cgroup.includes('kubepods'))\n return 'Kubernetes (cgroup kubepods)'\n if (cgroup.includes('docker'))\n return 'Docker (cgroup docker)'\n if (cgroup.includes('lxc'))\n return 'LXC (cgroup lxc)'\n if (cgroup.includes('containerd'))\n return 'containerd (cgroup)'\n }\n return null\n}\n\nexport function createContainerProvider(ctx: BootProviderContext): BootProvider {\n const mechanism = 'container' as const\n return {\n mechanism,\n\n async detect(): Promise<BootCandidate> {\n const container = detectContainer(ctx)\n return {\n mechanism,\n available: container !== null,\n bootCapable: false,\n privileged: false,\n reason: container === null\n ? 'this process does not look like it is inside a container'\n : `this process runs inside ${container}; an OS boot entry would live on the host, not here`,\n }\n },\n\n async status(): Promise<BootProviderStatus> {\n const container = detectContainer(ctx)\n return {\n state: 'unsupported',\n unitPath: null,\n detail: container === null\n ? 'no container detected'\n : `running inside ${container}; ${RESTART_POLICY}`,\n commands: [],\n }\n },\n\n async install(): Promise<BootActionResult> {\n const container = detectContainer(ctx)\n return failed(\n container === null\n ? `no container detected; ${RESTART_POLICY}`\n : `this process runs inside ${container}; an OS boot entry would be installed outside the container \u2014 ${RESTART_POLICY}`,\n )\n },\n\n async uninstall(): Promise<BootActionResult> {\n return failed('nothing to uninstall: this plugin installed no OS boot entry for a container; the container restart policy is what starts it')\n },\n }\n}\n\nexport function createUnsupportedProvider(platform: NodeJS.Platform): BootProvider {\n const mechanism = 'unsupported' as const\n const reason = `no boot mechanism is known for ${platform}`\n return {\n mechanism,\n\n async detect(): Promise<BootCandidate> {\n return { mechanism, available: true, bootCapable: false, privileged: false, reason }\n },\n\n async status(_spec: BootSpec): Promise<BootProviderStatus> {\n return { state: 'unsupported', unitPath: null, detail: reason, commands: [] }\n },\n\n async install(_spec: BootSpec): Promise<BootActionResult> {\n return failed(`this plugin has no boot mechanism for ${platform}; start home-hosted from your platform's own service manager`)\n },\n\n async uninstall(_spec: BootSpec): Promise<BootActionResult> {\n return failed(`this plugin has no boot mechanism for ${platform}, so it installed nothing to remove`)\n },\n }\n}\n", "/**\n * Writing `servers.config.json` directly, for the case where the panel is not\n * running (no API to call, and nobody watching the file).\n *\n * When the panel *is* running this path is a fallback: its file watcher treats\n * an external edit as a real change, and a newly added `autostart` entry is\n * started at once. `addEntrySafely` therefore writes the entry disabled first\n * and only then flips `autostart`, which the watcher sees as a changed\n * definition \u2014 applied on that entry's next start, never started now.\n */\nimport fs from 'node:fs'\nimport type { ServerEntry, ServerEntryPatch } from '../shared/contracts.js'\nimport { readJson, writeFileAtomic } from '../util/fsx.js'\nimport { configFile } from '../util/paths.js'\n\nexport interface RawConfig {\n meta?: Record<string, unknown>\n servers?: ServerEntry[]\n [key: string]: unknown\n}\n\nexport interface ConfigReadResult {\n raw: RawConfig | null\n exists: boolean\n error: string | null\n}\n\nexport function readConfig(home: string): ConfigReadResult {\n const file = configFile(home)\n const raw = readJson<RawConfig>(file)\n if (raw === null) {\n // Distinguish \"no file yet\" from \"unreadable\", because only the first is safe to create.\n const exists = fs.existsSync(file)\n return { raw: null, exists, error: exists ? 'the config file could not be parsed' : null }\n }\n if (!Array.isArray(raw.servers) && raw.servers !== undefined)\n return { raw: null, exists: true, error: 'the config file has a servers field that is not an array' }\n return { raw, exists: true, error: null }\n}\n\n/**\n * Write the file back with home-hosted's own `meta` contract, which records the\n * release that wrote the file and the shape it wrote.\n *\n * `schema` is never invented here: a file that declared one keeps it, and one\n * that did not stays without it \u2014 home-hosted reads an absent schema as \"the\n * current one\", so stamping our own idea of the schema would one day fail its\n * own guard (\"this release understands schema N\") and stop the panel booting\n * from a file this plugin only patched.\n */\nexport function writeConfig(home: string, raw: RawConfig, writtenBy = 'dsh-home-hosted'): void {\n const meta = { ...(raw.meta ?? {}), writtenBy }\n const next: RawConfig = { ...raw, meta }\n writeFileAtomic(configFile(home), `${JSON.stringify(next, null, 2)}\\n`)\n}\n\nexport function findEntry(raw: RawConfig, id: string): ServerEntry | null {\n return (raw.servers ?? []).find(entry => entry.id === id) ?? null\n}\n\n/** Insert or replace one entry, preserving every other key in the file. */\nexport function upsertEntry(raw: RawConfig, entry: ServerEntry): RawConfig {\n const servers = [...(raw.servers ?? [])]\n const index = servers.findIndex(candidate => candidate.id === entry.id)\n if (index >= 0)\n servers[index] = entry\n else\n servers.push(entry)\n return { ...raw, servers }\n}\n\nexport function patchEntry(raw: RawConfig, id: string, patch: ServerEntryPatch): RawConfig {\n const servers = (raw.servers ?? []).map((entry) => {\n if (entry.id !== id)\n return entry\n const merged: ServerEntry = { ...entry, ...patch }\n if (patch.stop !== undefined && typeof entry.stop === 'object' && entry.stop !== null)\n merged.stop = { ...entry.stop, ...patch.stop }\n return merged\n })\n return { ...raw, servers }\n}\n\n/** Patch the panel's own `control` block (its port, its bind). */\nexport function patchControl(raw: RawConfig, patch: Record<string, unknown>): RawConfig {\n return { ...raw, control: { ...(raw.control ?? {}), ...patch } }\n}\n\nexport function removeEntry(raw: RawConfig, id: string): RawConfig {\n return { ...raw, servers: (raw.servers ?? []).filter(entry => entry.id !== id) }\n}\n", "/**\n * Where things live. The harness home comes from `$DSH_HOME`; home-hosted's\n * state comes from `$HHOSTED_HOME`. Neither is ever hard-coded into a file this\n * plugin writes \u2014 the resolved value is written into generated units instead.\n */\nimport os from 'node:os'\nimport path from 'node:path'\n\nexport function expandHome(value: string): string {\n if (value === '~')\n return os.homedir()\n if (value.startsWith('~/') || value.startsWith('~\\\\'))\n return path.join(os.homedir(), value.slice(2))\n return value\n}\n\n/** DeepSeek Harness home: `$DSH_HOME`, else `~/.dsh`. */\nexport function dshHome(): string {\n const configured = process.env.DSH_HOME?.trim()\n return configured ? path.resolve(expandHome(configured)) : path.join(os.homedir(), '.dsh')\n}\n\n/** home-hosted state root: `$HHOSTED_HOME`, else `~/.home-hosted`. */\nexport function homeHostedHome(): string {\n const configured = process.env.HHOSTED_HOME?.trim()\n return configured ? path.resolve(expandHome(configured)) : path.join(os.homedir(), '.home-hosted')\n}\n\n/** Where this plugin keeps its own durable state (settings, snapshots, token). */\nexport function pluginStateDir(override?: string): string {\n const configured = override?.trim()\n if (configured)\n return path.resolve(expandHome(configured))\n return path.join(dshHome(), 'dsh-home-hosted')\n}\n\n/** home-hosted's own tokens file, written by the panel at startup. */\nexport function runtimeFile(home = homeHostedHome()): string {\n return path.join(home, 'run.json')\n}\n\n/** home-hosted's secrets file (0600): proves whether an API token is enrolled. */\nexport function secretsFile(home = homeHostedHome()): string {\n return path.join(home, '.control-secrets.json')\n}\n\nexport function configFile(home = homeHostedHome()): string {\n return path.join(home, 'servers.config.json')\n}\n", "/**\n * The server entry that represents the running harness.\n *\n * An existing entry is never rewritten: this plugin only owns `autostart`,\n * `onPortConflict` and `stop.killPortHolders`. A generated entry (only used when\n * there is none) mirrors how this process was actually launched where that is\n * knowable, and otherwise falls back to the `dsh web` app arguments.\n */\nimport fs from 'node:fs'\nimport path from 'node:path'\nimport process from 'node:process'\nimport type { ServerEntry } from '../shared/contracts.js'\nimport { readJson } from '../util/fsx.js'\nimport { dshHome as resolveDshHome, pluginStateDir } from '../util/paths.js'\nimport type { CliLaunch } from './launch.js'\nimport { resolveShimmedCli, which } from './launch.js'\nimport { compareVersions } from './resolve.js'\nimport { dshCandidatesUnder, dshLauncherPath, dshSearchRoot, writeDshLauncher } from './launcher.js'\n\n/**\n * Which profile this process is running.\n *\n * `DSH_PROFILE` alone is not trustworthy: it can be inherited from a parent\n * shell that ran a different profile (that is how an entry once ended up booting\n * `web` under another profile's home). The process's own argv is authoritative,\n * then the profile directory the launcher pointed at, then the env var.\n */\nexport function detectProfile(argv: readonly string[], env: Record<string, string | undefined> = {}): string {\n for (let index = 0; index < argv.length; index += 1) {\n const arg = argv[index]\n if (arg === '--profile' && typeof argv[index + 1] === 'string' && !argv[index + 1]!.startsWith('-'))\n return argv[index + 1]!\n if (arg?.startsWith('--profile='))\n return arg.slice('--profile='.length)\n }\n\n const dir = env.DSH_PROFILE_DIR\n if (typeof dir === 'string' && dir.length > 0) {\n const base = path.basename(dir)\n if (base.length > 0 && base !== '.' && base !== path.sep)\n return base\n }\n\n const app = argv.slice(2).find(candidate => candidate !== undefined && !candidate.startsWith('-'))\n if (app !== undefined && app.length > 0)\n return app\n\n const fromEnv = env.DSH_PROFILE\n return typeof fromEnv === 'string' && fromEnv.length > 0 ? fromEnv : 'web'\n}\n\nexport interface DshFacts {\n id: string\n port: number | null\n host: string\n profile: string | null\n dshHome: string\n launch: CliLaunch | null\n /**\n * The stable launcher a local/clone entry must boot through, when one exists.\n * Null keeps the older shape: the resolved program and its own argv.\n */\n launcherPath?: string | null\n}\n\nexport interface DshLaunch extends CliLaunch {\n /** The stable launcher written for this launch, or null for `dsh` on PATH. */\n launcherPath: string | null\n}\n\nexport interface ResolveDshLaunchOptions {\n /** The plugin state dir the launcher is written into; defaults to `$DSH_HOME/dsh-home-hosted`. */\n stateDir?: string\n /** The harness home the resolver records as the launcher's search root. */\n dshHome?: string\n /** Test seam: what this process was launched as; defaults to `process.argv[1]`. */\n argv1?: string | null\n /** Test seam: locate a command on PATH. */\n findOnPath?: (command: string) => Promise<string | null>\n}\n\n/** The nearest package.json's version, for ordering clone candidates. */\nfunction versionOf(entry: string): string | null {\n let dir = path.dirname(entry)\n for (let hop = 0; hop < 4; hop += 1) {\n const manifest = readJson<{ version?: string }>(path.join(dir, 'package.json'))\n if (typeof manifest?.version === 'string')\n return manifest.version\n dir = path.dirname(dir)\n }\n return null\n}\n\nfunction isEntry(file: string): boolean {\n return /\\.[cm]?js$/.test(file) && fs.existsSync(file) && !fs.statSync(file).isDirectory()\n}\n\n/** The resolved target behind a shim or symlink; the path itself when that fails. */\nfunction realPath(file: string): string {\n try {\n return fs.realpathSync(file)\n }\n catch {\n return file\n }\n}\n\n/**\n * A local clone's built entry, reconstructed from where a clone keeps its build.\n *\n * A clone installs dsh in its own tree, so `argv[1]` names a *build output*\n * (`lib/bin.js` inside `node_modules`, and after a rebuild a different one): the\n * install root is derived from it and every known build location is checked, so a\n * rebuild does not require a new boot entry.\n */\nexport function cloneEntryFrom(argv1: string): string | null {\n if (!isEntry(argv1))\n return null\n const root = path.dirname(path.dirname(argv1))\n for (const candidate of [\n path.join(root, 'lib', 'bin.js'),\n path.join(root, 'lib', 'bin.mjs'),\n path.join(root, 'lib', 'bin.cjs'),\n path.join(root, 'dist', 'bin.js'),\n path.join(root, 'bin', 'dsh.js'),\n path.join(root, 'bin', 'dsh.mjs'),\n ]) {\n if (isEntry(candidate))\n return candidate\n }\n return argv1\n}\n\n/**\n * The entry this process runs, however it was launched.\n *\n * `argv[1]` is directly the built entry for a clone or an installed copy. When\n * it is instead a package-manager shim (`.bin/dsh`), the shim's own recorded\n * target names the real entry, which is the path a boot entry must carry.\n */\nfunction launchedEntry(argv1: string): string | null {\n const real = realPath(argv1)\n const direct = cloneEntryFrom(real)\n if (direct !== null)\n return direct\n const shimmed = resolveShimmedCli(real, process.execPath)\n return shimmed?.cliEntry == null ? null : cloneEntryFrom(shimmed.cliEntry)\n}\n\n/** The best dsh entry installed under a harness home, flat or pnpm. */\nexport function findDshEntry(dshHome: string): string | null {\n const found: string[] = []\n found.push(...dshCandidatesUnder(dshHome))\n for (const name of readdirNames(path.join(dshHome, 'profiles')))\n found.push(...dshCandidatesUnder(path.join(dshHome, 'profiles', name)))\n const withVersion = found.map(entry => ({ entry, version: versionOf(entry) }))\n withVersion.sort((a, b) => compareVersions(b.version ?? '0.0.0', a.version ?? '0.0.0'))\n return withVersion[0]?.entry ?? null\n}\n\nfunction readdirNames(dir: string): string[] {\n try {\n return fs.readdirSync(dir)\n }\n catch {\n return []\n }\n}\n\n/**\n * Where the running harness's own CLI entry is.\n *\n * A local clone's build path is not stable enough to bake into a boot entry, so\n * the clone case records the entry in a generated launcher and returns that\n * launcher's path; the launcher re-finds dsh at boot. A plain `dsh` on PATH is\n * already resolved to a stable entry and keeps its current shape.\n */\nexport async function resolveDshLaunch(options: ResolveDshLaunchOptions = {}): Promise<DshLaunch | null> {\n const argv1 = options.argv1 === undefined ? process.argv[1] : options.argv1\n const dshHome = options.dshHome ?? resolveDshHome()\n const stateDir = options.stateDir ?? pluginStateDir()\n\n const local = typeof argv1 === 'string' && argv1.length > 0 ? launchedEntry(argv1) : null\n // A process already booted through the launcher is not a clone to snapshot:\n // one more layer would just reimplement the launcher. Both sides are\n // canonicalised first \u2014 on macOS a temp directory is reached as `/var/...`\n // and resolved as `/private/var/...`, and comparing those would stack a\n // second launcher on every boot.\n if (local !== null && realPath(local) !== realPath(dshLauncherPath(stateDir, path.extname(local)))) {\n const launcher = writeDshLauncher({\n stateDir,\n dshHome,\n resolvedEntry: local,\n entryExtension: path.extname(local),\n // Where this install sits, so a rebuilt/moved copy is found next boot.\n searchRoots: [dshSearchRoot(local)].filter((root): root is string => root !== null),\n })\n return { program: process.execPath, args: [local], cliEntry: local, shimPath: null, source: 'entry', launcherPath: launcher.path }\n }\n\n // Not launched as an entry: a clone that is not on PATH still installs into\n // the harness home, and that is a far better answer than \"not found\".\n const installed = findDshEntry(dshHome)\n if (installed !== null) {\n const launcher = writeDshLauncher({ stateDir, dshHome, resolvedEntry: installed, entryExtension: path.extname(installed) })\n return { program: process.execPath, args: [installed], cliEntry: installed, shimPath: null, source: 'entry', launcherPath: launcher.path }\n }\n\n const found = await (options.findOnPath ?? which)('dsh')\n if (found === null)\n return null\n const launch = resolveShimmedCli(found, process.execPath)\n return launch === null ? null : { ...launch, launcherPath: null }\n}\n\nfunction buildCommand(launch: CliLaunch, launcherPath: string | null): { command: string, entryArgs: string[] } {\n if (launcherPath !== null && launcherPath.length > 0)\n return { command: process.execPath, entryArgs: [launcherPath] }\n return { command: launch.program, entryArgs: launch.args }\n}\n\n/** The script a stored entry actually runs, out of its command and leading args. */\nfunction entryScript(config: { command?: string, args?: string[] }): string | null {\n const program = config.command\n if (typeof program !== 'string' || program.length === 0)\n return null\n // A bare command (`dsh`, `dsh.cmd`) is itself the executable. An absolute one\n // is `process.execPath` here, and the script is the argument that follows.\n if (!path.isAbsolute(program))\n return program\n const rest = config.args ?? []\n return rest.find(arg => path.isAbsolute(arg)) ?? program\n}\n\n/**\n * Re-point an entry that boots a local build directly at the stable launcher.\n *\n * Only this shape qualifies: the entry runs the same script this process does,\n * and that script is not already the launcher. An upgrade cannot repair the\n * entry it created in an earlier release otherwise \u2014 the plugin never rewrites\n * an existing entry's command.\n */\n/**\n * Whether an entry *could* need that repair, without resolving anything.\n *\n * Resolving a local dsh walks the harness home, so the write path asks this\n * first: a global `dsh` on PATH, or an entry already on the launcher, is\n * settled here and never triggers the walk.\n */\nexport function needsLauncherRepair(config: { command?: string, args?: string[] }): boolean {\n const program = config.command\n if (typeof program !== 'string' || program.length === 0)\n return false\n if (path.isAbsolute(program))\n return true\n return (config.args ?? []).some((arg, index) => index === 0 && path.isAbsolute(arg))\n}\n\nexport function launcherRepair(\n config: { command?: string, args?: string[] },\n launch: DshLaunch | null,\n): { command: string, args: string[] } | null {\n if (launch?.launcherPath == null || launch.launcherPath.length === 0)\n return null\n const launcher = launch.launcherPath\n const stored = entryScript(config)\n if (stored === null || stored === launcher)\n return null\n if (stored !== launch.cliEntry)\n return null\n // The old argv named the script as an absolute first argument; the launcher\n // takes its place, so that one has to go and every app argument has to stay.\n const rest = (config.args ?? []).filter((arg, index) => !(index === 0 && path.isAbsolute(arg)))\n return { command: process.execPath, args: [launcher, ...rest] }\n}\n\nexport function buildDshEntry(facts: DshFacts): ServerEntry {\n const launch = facts.launch\n const profile = facts.profile === null || facts.profile === undefined ? 'web' : facts.profile\n\n const appArgs: string[] = []\n if (facts.port !== null) {\n appArgs.push(\n '--port', '{port}',\n '--host', '{host}',\n '--no-open',\n '--trusted-host', `localhost:{port}`,\n )\n if (facts.host === '0.0.0.0')\n appArgs.push('--trusted-host', '{lanIp}:{port}')\n }\n\n const launcherArgs = profile === 'web' ? ['web'] : ['--profile', profile]\n const generated = launch === null\n ? { command: 'dsh', entryArgs: [] as string[] }\n : buildCommand(launch, facts.launcherPath ?? null)\n\n return {\n id: facts.id,\n label: 'DSH web',\n enabled: true,\n autostart: true,\n command: generated.command,\n args: [...generated.entryArgs, ...launcherArgs, ...appArgs],\n bind: facts.host === '0.0.0.0' ? 'lan' : 'local',\n port: facts.port,\n cwd: process.cwd(),\n env: {},\n dataEnvs: { DSH_HOME: facts.dshHome },\n onPortConflict: 'kill',\n stop: { killPortHolders: true },\n health: {\n enabled: true,\n mode: 'http',\n // 401 is normal here: the panel answers the login route when auth is on.\n http: { path: '/', method: 'GET', expectStatusBelow: 500, expectBody: '' },\n },\n }\n}\n", "/**\n * How the home-hosted daemon is launched, and what a boot entry for it contains.\n *\n * The executable is resolved to an absolute program plus argv: a generated boot\n * entry must not depend on a login shell's PATH. When the resolved command is a\n * package-manager shim, its `cmd-shim-target` comment names the real entry, and\n * node runs that directly \u2014 the same guarantee the shim itself gives.\n */\nimport fs from 'node:fs'\nimport path from 'node:path'\nimport process from 'node:process'\nimport type { BootSpec } from '../boot/types.js'\nimport { run } from '../util/exec.js'\nimport { readText } from '../util/fsx.js'\n\nexport interface CliLaunch {\n program: string\n /** Args that must precede the command, e.g. the CLI entry path. */\n args: string[]\n cliEntry: string | null\n shimPath: string | null\n source: 'override' | 'entry' | 'shim-target' | 'shim'\n}\n\nexport async function which(command: string): Promise<string | null> {\n const probe = process.platform === 'win32' ? 'where.exe' : 'which'\n const result = await run(probe, [command], { timeoutMs: 5000 })\n if (result.code !== 0)\n return null\n const first = result.stdout.split(/\\r?\\n/).map(line => line.trim()).filter(Boolean)[0]\n return first ?? null\n}\n\n/** Turn a resolved CLI path into an absolute program + argv. */\nexport function resolveShimmedCli(absolute: string, nodePath = process.execPath): CliLaunch | null {\n if (!fs.existsSync(absolute))\n return null\n if (/\\.(?:mjs|cjs|js)$/.test(absolute))\n return { program: nodePath, args: [absolute], cliEntry: absolute, shimPath: null, source: 'entry' }\n\n const shimTarget = /^#\\s*cmd-shim-target=(.+)$/m.exec(readText(absolute) ?? '')?.[1]?.trim()\n if (shimTarget !== undefined && fs.existsSync(shimTarget))\n return { program: nodePath, args: [shimTarget], cliEntry: shimTarget, shimPath: absolute, source: 'shim-target' }\n\n // A shim with no readable target still works when node is on the entry's PATH.\n return { program: absolute, args: [], cliEntry: null, shimPath: absolute, source: 'shim' }\n}\n\nexport async function resolveHomeHostedLaunch(override?: string | null): Promise<CliLaunch | null> {\n const configured = override?.trim()\n const found = configured && configured.length > 0 ? configured : (await which('home-hosted')) ?? (await which('hh'))\n if (found === null || found === undefined)\n return null\n\n const launch = resolveShimmedCli(path.resolve(found))\n if (launch === null)\n return null\n return configured ? { ...launch, source: 'override' } : launch\n}\n\nexport interface HomeHostedFacts {\n home: string\n projectDir?: string | null\n version?: string | null\n}\n\n/** A deterministic environment for a boot-time entry, with absolute values. */\nexport function homeHostedEnv(facts: HomeHostedFacts, launch: CliLaunch, extra: Record<string, string> = {}): Record<string, string> {\n const dirs = [\n launch.shimPath === null ? null : path.dirname(launch.shimPath),\n path.dirname(process.execPath),\n ...(process.env.PATH ?? '').split(path.delimiter),\n '/usr/local/bin',\n '/usr/bin',\n '/bin',\n ].filter((dir): dir is string => typeof dir === 'string' && dir.length > 0)\n const seen = new Set<string>()\n const pathValue = dirs.filter((dir) => {\n if (seen.has(dir))\n return false\n seen.add(dir)\n return true\n }).join(path.delimiter)\n\n const env: Record<string, string> = {\n PATH: pathValue,\n HOME: process.env.HOME ?? process.env.USERPROFILE ?? '',\n HHOSTED_HOME: facts.home,\n ...extra,\n }\n if (facts.projectDir)\n env.HHOSTED_PROJECT = facts.projectDir\n return env\n}\n\nexport interface BootSpecOptions {\n stateDir: string\n marker?: string\n}\n\nexport function buildHomeHostedBootSpec(\n facts: HomeHostedFacts,\n launch: CliLaunch,\n options: BootSpecOptions,\n): BootSpec {\n const logDir = path.join(facts.home, '.logs')\n fs.mkdirSync(logDir, { recursive: true })\n const args = [...launch.args, 'up', '--foreground', '--home', facts.home]\n if (facts.projectDir)\n args.push('--project', facts.projectDir)\n\n return {\n command: launch.program,\n args,\n cwd: facts.projectDir ?? facts.home,\n env: homeHostedEnv(facts, launch),\n marker: options.marker ?? 'managed by dsh-home-hosted',\n unitName: 'home-hosted',\n label: 'home-hosted control panel',\n logDir,\n }\n}\n", "/**\n * Which home-hosted CLI this plugin drives.\n *\n * The plugin ships its own pinned copy as a dependency and prefers it, so the\n * version that runs the panel at boot is the version this plugin was built\n * against \u2014 not whatever `home-hosted` happens to be on PATH. Preferring a\n * global install is a supported setting, not an accident.\n *\n * Resolution order: the operator's `homeHostedCommand` override always wins,\n * then the preferred copy, then the other one as a fallback.\n */\nimport { createRequire } from 'node:module'\nimport fs from 'node:fs'\nimport path from 'node:path'\nimport process from 'node:process'\nimport type { CliCandidate, CliSource, CliStatus } from '../shared/contracts.js'\nimport { run } from '../util/exec.js'\nimport type { CliLaunch } from './launch.js'\nimport { resolveShimmedCli, which } from './launch.js'\n\n/** The range the plugin ships and is tested against. */\nexport const EXPECTED_RANGE = '^0.6.6'\n\n/** Oldest release whose API and config schema this plugin relies on. */\nexport const MIN_SUPPORTED_VERSION = '0.4.1'\n\n/** Oldest release whose config schema accepts `onPortConflict: kill`. */\nexport const MIN_KILL_VERSION = '0.6.0'\n/** `persistent` (the nanny that keeps an entry alive across panel restarts). */\nexport const MIN_PERSISTENT_VERSION = '0.6.3'\n\nexport type CliPreference = 'pinned' | 'global'\n\nexport interface CliResolution {\n launch: CliLaunch | null\n status: CliStatus\n}\n\nexport interface ResolveCliOptions {\n override?: string | null\n /** Which copy to run when both exist. */\n prefer?: CliPreference\n /** Test seam: the pinned package's manifest path, or null when it is not installed. */\n packageManifest?: () => string | null\n /** Test seam: ask a CLI for its own version. */\n readVersion?: (launch: CliLaunch) => Promise<string | null>\n /** Test seam: locate a command on PATH. */\n findOnPath?: (command: string) => Promise<string | null>\n timeoutMs?: number\n}\n\ninterface Candidate {\n candidate: CliCandidate\n launch: CliLaunch\n}\n\n/** Where the pinned `home-hosted` manifest is, resolved from this module. */\nexport function pinnedManifestPath(): string | null {\n try {\n return createRequire(import.meta.url).resolve('home-hosted/package.json')\n }\n catch {\n return null\n }\n}\n\n/** The `home-hosted` bin entry a package manifest declares. */\nexport function binEntryFromManifest(manifestPath: string): string | null {\n try {\n const manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf8')) as { bin?: string | Record<string, string> }\n const declared = typeof manifest.bin === 'string'\n ? manifest.bin\n : manifest.bin?.['home-hosted'] ?? Object.values(manifest.bin ?? {})[0]\n return typeof declared === 'string' && declared.length > 0\n ? path.resolve(path.dirname(manifestPath), declared)\n : null\n }\n catch {\n return null\n }\n}\n\n/** The first `x.y.z[-pre]` in a CLI's output. */\nexport function parseVersion(output: string | null): string | null {\n const match = /(\\d+)\\.(\\d+)\\.(\\d+)(?:-([0-9A-Za-z.-]+))?/.exec(output ?? '')\n return match === null ? null : `${match[1]}.${match[2]}.${match[3]}${match[4] === undefined ? '' : `-${match[4]}`}`\n}\n\n/** Numeric comparison; a prerelease sorts below its own release. */\nexport function compareVersions(a: string, b: string): number {\n const split = (value: string): { parts: number[], pre: string | null } => {\n const [core, pre = null] = value.split('-', 2)\n return { parts: (core ?? '').split('.').map(part => Number.parseInt(part, 10) || 0), pre }\n }\n const left = split(a)\n const right = split(b)\n for (let index = 0; index < 3; index += 1) {\n const diff = (left.parts[index] ?? 0) - (right.parts[index] ?? 0)\n if (diff !== 0)\n return diff < 0 ? -1 : 1\n }\n if (left.pre === right.pre)\n return 0\n if (left.pre === null)\n return 1\n if (right.pre === null)\n return -1\n return left.pre < right.pre ? -1 : 1\n}\n\nfunction detailFor(source: CliSource, version: string | null, supported: boolean, prefer: CliPreference, unusableOverride: string | null = null): string {\n const shown = version ?? 'unknown version'\n switch (source) {\n case 'config':\n return unusableOverride === null\n ? `from the configured command (${shown})`\n : `the configured command could not be used: ${unusableOverride} does not exist (or is not a file this plugin can run); fix homeHostedCommand, or clear it to let the plugin choose`\n case 'dependency':\n return supported\n ? `the pinned dependency (${shown})`\n : `the pinned dependency is below the oldest supported release (${MIN_SUPPORTED_VERSION})`\n case 'path':\n if (!supported)\n return `the global install on PATH (${shown}) is below the oldest supported release (${MIN_SUPPORTED_VERSION})`\n return prefer === 'global'\n ? `the global install on PATH (${shown})`\n : `a global install on PATH (${shown}), not the pinned dependency ${EXPECTED_RANGE}`\n default:\n return 'no home-hosted CLI found: install the plugin with its dependencies, or put home-hosted on PATH'\n }\n}\n\nasync function defaultReadVersion(launch: CliLaunch, timeoutMs: number): Promise<string | null> {\n const result = await run(launch.program, [...launch.args, '--version'], { timeoutMs })\n return parseVersion(result.stdout) ?? parseVersion(result.stderr)\n}\n\nexport async function resolveCli(options: ResolveCliOptions = {}): Promise<CliResolution> {\n const timeoutMs = options.timeoutMs ?? 5000\n const prefer = options.prefer ?? 'pinned'\n const readVersion = options.readVersion ?? (launch => defaultReadVersion(launch, timeoutMs))\n const locate = options.findOnPath ?? which\n\n // 1. An explicit override is not a preference: it is an instruction. An\n // instruction that cannot be carried out is reported, never silently\n // replaced by a copy the operator did not ask for.\n const override = options.override?.trim()\n let unusableOverride: string | null = null\n if (override !== undefined && override.length > 0) {\n const launch = resolveShimmedCli(path.resolve(override))\n if (launch === null) {\n unusableOverride = override\n }\n else {\n const version = await readVersion(launch)\n const supported = version === null || compareVersions(version, MIN_SUPPORTED_VERSION) >= 0\n return {\n launch,\n status: {\n source: 'config',\n path: launch.cliEntry ?? launch.shimPath ?? launch.program,\n version,\n expectedRange: EXPECTED_RANGE,\n supported,\n prefer,\n dependency: null,\n global: null,\n detail: detailFor('config', version, supported, prefer),\n },\n }\n }\n }\n\n // 2. The two copies this plugin knows about.\n const manifest = (options.packageManifest ?? pinnedManifestPath)()\n const dependencyEntry = manifest === null ? null : binEntryFromManifest(manifest)\n let dependency: Candidate | null = null\n if (dependencyEntry !== null && fs.existsSync(dependencyEntry)) {\n let version: string | null = null\n try {\n version = (JSON.parse(fs.readFileSync(manifest as string, 'utf8')) as { version?: string }).version ?? null\n }\n catch {\n version = null\n }\n dependency = {\n candidate: { source: 'dependency', path: dependencyEntry, version },\n launch: { program: process.execPath, args: [dependencyEntry], cliEntry: dependencyEntry, shimPath: null, source: 'entry' },\n }\n }\n\n let global: Candidate | null = null\n const found = (await locate('home-hosted')) ?? (await locate('hh'))\n if (found !== null) {\n const launch = resolveShimmedCli(path.resolve(found))\n if (launch !== null) {\n global = {\n candidate: { source: 'path', path: launch.cliEntry ?? launch.shimPath ?? launch.program, version: await readVersion(launch) },\n launch,\n }\n }\n }\n\n const order = prefer === 'global' ? [global, dependency] : [dependency, global]\n const chosen = order.find(item => item !== null) ?? null\n const dependencySummary = dependency?.candidate ?? null\n const globalSummary = global?.candidate ?? null\n\n if (unusableOverride !== null) {\n return {\n launch: null,\n status: {\n source: 'config',\n path: unusableOverride,\n version: null,\n expectedRange: EXPECTED_RANGE,\n supported: false,\n prefer,\n dependency: dependencySummary,\n global: globalSummary,\n detail: detailFor('config', null, false, prefer, unusableOverride),\n },\n }\n }\n\n if (chosen === null) {\n return {\n launch: null,\n status: {\n source: 'none',\n path: null,\n version: null,\n expectedRange: EXPECTED_RANGE,\n supported: false,\n prefer,\n dependency: dependencySummary,\n global: globalSummary,\n detail: detailFor('none', null, false, prefer),\n },\n }\n }\n\n const version = chosen.candidate.version\n const supported = version === null || compareVersions(version, MIN_SUPPORTED_VERSION) >= 0\n return {\n launch: chosen.launch,\n status: {\n source: chosen.candidate.source,\n path: chosen.candidate.path,\n version,\n expectedRange: EXPECTED_RANGE,\n supported,\n prefer,\n dependency: dependencySummary,\n global: globalSummary,\n detail: detailFor(chosen.candidate.source, version, supported, prefer),\n },\n }\n}\n", "/**\n * A stable launcher for the pinned CLI.\n *\n * A dependency resolves to a pnpm path that carries the version and the peer\n * hash (`\u2026/.pnpm/home-hosted@0.6.1_zod@4.6.5/node_modules/home-hosted/\u2026`), which\n * moves on the next install and disappears when the profile is rebuilt. A boot\n * entry that baked that path in would fail at exactly the moment it exists for.\n *\n * So the plugin generates one small script in its own state directory and points\n * the boot entry at *that*. At boot the launcher finds the pinned copy again\n * (recorded path \u2192 profile node_modules, flat or pnpm) and falls back to PATH,\n * which is why the entry survives plugin upgrades and profile reinstalls.\n */\nimport fs from 'node:fs'\nimport path from 'node:path'\nimport process from 'node:process'\nimport { run } from '../util/exec.js'\nimport { readJson, writeFileAtomic, writeJsonAtomic } from '../util/fsx.js'\nimport { compareVersions, parseVersion } from './resolve.js'\n\nexport interface LauncherOptions {\n stateDir: string\n dshHome: string\n /** Where the pinned copy is right now; recorded as the fast path. */\n resolvedEntry: string | null\n /** The pinned copy's version, recorded for diagnostics. */\n resolvedVersion?: string | null\n /** The plugin's own package root, as a search hint. */\n pluginRoot?: string | null\n minVersion: string\n marker?: string\n}\n\nexport interface LauncherWrite {\n path: string\n changed: boolean\n}\n\ninterface LauncherRecord {\n entry: string | null\n version: string | null\n pluginRoot: string | null\n writtenAt: number\n}\n\nexport function launcherDir(stateDir: string): string {\n return path.join(stateDir, 'bin')\n}\n\nexport function launcherPath(stateDir: string): string {\n return path.join(launcherDir(stateDir), 'home-hosted.mjs')\n}\n\nexport function launcherRecordPath(stateDir: string): string {\n return path.join(launcherDir(stateDir), 'resolved.json')\n}\n\nexport function readLauncherRecord(stateDir: string): LauncherRecord | null {\n return readJson<LauncherRecord>(launcherRecordPath(stateDir))\n}\n\n/** The generated script's source; exported so a test can inspect it. */\nexport function buildLauncherSource(options: LauncherOptions): string {\n const marker = options.marker ?? 'managed by dsh-home-hosted'\n const record = launcherRecordPath(options.stateDir)\n return `#!/usr/bin/env node\n// ${marker} \u2014 rewritten on every plugin start; do not edit.\nimport fs from 'node:fs'\nimport path from 'node:path'\nimport process from 'node:process'\nimport { spawnSync } from 'node:child_process'\n\nconst DSH_HOME = ${JSON.stringify(options.dshHome)}\nconst RECORD = ${JSON.stringify(record)}\nconst MIN_VERSION = ${JSON.stringify(options.minVersion)}\nconst PLUGIN_ROOT = ${JSON.stringify(options.pluginRoot ?? null)}\n\nfunction readRecord() {\n try { return JSON.parse(fs.readFileSync(RECORD, 'utf8')) } catch { return null }\n}\n\nfunction versionOf(entry) {\n let dir = path.dirname(entry)\n for (let hop = 0; hop < 4; hop += 1) {\n try {\n const manifest = JSON.parse(fs.readFileSync(path.join(dir, 'package.json'), 'utf8'))\n if (typeof manifest.version === 'string') return manifest.version\n } catch {}\n dir = path.dirname(dir)\n }\n return null\n}\n\nfunction compare(a, b) {\n const split = value => {\n const [core, pre = null] = String(value).split('-', 2)\n return { parts: core.split('.').map(part => Number.parseInt(part, 10) || 0), pre }\n }\n const left = split(a); const right = split(b)\n for (let i = 0; i < 3; i += 1) {\n const diff = (left.parts[i] ?? 0) - (right.parts[i] ?? 0)\n if (diff !== 0) return diff < 0 ? -1 : 1\n }\n if (left.pre === right.pre) return 0\n if (left.pre === null) return 1\n if (right.pre === null) return -1\n return left.pre < right.pre ? -1 : 1\n}\n\nfunction collect(out, entry) {\n if (typeof entry === 'string' && entry.length > 0 && fs.existsSync(entry)) out.push(entry)\n}\n\nfunction collectRoot(root, out) {\n collect(out, path.join(root, 'node_modules', 'home-hosted', 'bin', 'home-hosted.mjs'))\n const store = path.join(root, 'node_modules', '.pnpm')\n let names = []\n try { names = fs.readdirSync(store) } catch { return }\n for (const name of names) {\n if (name.startsWith('home-hosted@') || name.startsWith('dsh-home-hosted@'))\n collect(out, path.join(store, name, 'node_modules', 'home-hosted', 'bin', 'home-hosted.mjs'))\n }\n}\n\nfunction candidates() {\n const out = []\n const record = readRecord()\n if (record && typeof record.entry === 'string') collect(out, record.entry)\n if (PLUGIN_ROOT !== null) collectRoot(PLUGIN_ROOT, out)\n try {\n for (const name of fs.readdirSync(path.join(DSH_HOME, 'profiles')))\n collectRoot(path.join(DSH_HOME, 'profiles', name), out)\n } catch {}\n collectRoot(path.join(DSH_HOME), out)\n // Last resort: a global install on the entry's own PATH.\n for (const dir of (process.env.PATH ?? '').split(path.delimiter)) {\n if (dir.length === 0) continue\n collect(out, path.join(dir, 'home-hosted'))\n collect(out, path.join(dir, 'home-hosted.cmd'))\n }\n return out\n}\n\nfunction choose() {\n const found = candidates().map(entry => ({ entry, version: versionOf(entry) }))\n const supported = found.filter(item => item.version !== null && compare(item.version, MIN_VERSION) >= 0)\n supported.sort((a, b) => compare(b.version, a.version))\n return (supported[0] ?? found[0] ?? null)?.entry ?? null\n}\n\nconst entry = choose()\nif (entry === null) {\n console.error('[dsh-home-hosted] no home-hosted CLI found (looked in ' + DSH_HOME + ' and PATH). Reinstall the plugin with its dependencies, or set homeHostedCommand in the plugin row.')\n process.exit(1)\n}\n\nconst args = process.argv.slice(2)\nconst isScript = /\\\\.(mjs|cjs|js)$/.test(entry)\nconst result = isScript\n ? spawnSync(process.execPath, [entry, ...args], { stdio: 'inherit' })\n : spawnSync(entry, args, { stdio: 'inherit', shell: process.platform === 'win32' && /\\\\.(cmd|bat)$/i.test(entry) })\nprocess.exit(typeof result.status === 'number' ? result.status : 1)\n`\n}\n\nexport function writeLauncher(options: LauncherOptions): LauncherWrite {\n const file = launcherPath(options.stateDir)\n const source = buildLauncherSource(options)\n const previous = fs.existsSync(file) ? fs.readFileSync(file, 'utf8') : null\n const changed = previous !== source\n if (changed) {\n writeFileAtomic(file, source, 0o755)\n fs.chmodSync(file, 0o755)\n }\n writeJsonAtomic(launcherRecordPath(options.stateDir), {\n entry: options.resolvedEntry,\n version: options.resolvedVersion ?? null,\n pluginRoot: options.pluginRoot ?? null,\n writtenAt: Date.now(),\n } satisfies LauncherRecord, 0o600)\n return { path: file, changed }\n}\n\n/** Run the launcher the way the boot entry will, and read the version it answers. */\nexport async function preflightLauncher(stateDir: string, timeoutMs = 10_000): Promise<string | null> {\n const file = launcherPath(stateDir)\n if (!fs.existsSync(file))\n return null\n const result = process.platform === 'win32'\n ? await run(process.execPath, [file, '--version'], { timeoutMs })\n : await run(file, ['--version'], { timeoutMs })\n return parseVersion(result.stdout) ?? parseVersion(result.stderr)\n}\n\n/** The version a CLI entry belongs to, read from the nearest package.json. */\nexport function versionOfEntry(entry: string): string | null {\n let dir = path.dirname(entry)\n for (let hop = 0; hop < 4; hop += 1) {\n const manifest = readJson<{ version?: string }>(path.join(dir, 'package.json'))\n if (typeof manifest?.version === 'string')\n return manifest.version\n dir = path.dirname(dir)\n }\n return null\n}\n\n/** Candidate entries under one root: a flat install, or a pnpm store. */\nexport function candidatesUnder(root: string): string[] {\n const out: string[] = []\n const direct = path.join(root, 'node_modules', 'home-hosted', 'bin', 'home-hosted.mjs')\n if (fs.existsSync(direct))\n out.push(direct)\n const store = path.join(root, 'node_modules', '.pnpm')\n if (fs.existsSync(store)) {\n for (const name of fs.readdirSync(store)) {\n if (!name.startsWith('home-hosted@') && !name.startsWith('dsh-home-hosted@'))\n continue\n const entry = path.join(store, name, 'node_modules', 'home-hosted', 'bin', 'home-hosted.mjs')\n if (fs.existsSync(entry))\n out.push(entry)\n }\n }\n return out\n}\n\n/** Highest satisfying candidate among explicit roots; exported for tests. */\nexport function findCandidate(roots: string[], minVersion: string): string | null {\n const found = roots.flatMap(root => candidatesUnder(root).map(entry => ({ entry, version: versionOfEntry(entry) })))\n const supported = found.filter(item => item.version !== null && compareVersions(item.version, minVersion) >= 0)\n supported.sort((a, b) => compareVersions(b.version ?? '0.0.0', a.version ?? '0.0.0'))\n return (supported[0] ?? found[0] ?? null)?.entry ?? null\n}\n\n// ---------------------------------------------------------------------------\n// The running harness's own launcher\n// ---------------------------------------------------------------------------\n\nexport interface DshLauncherOptions {\n stateDir: string\n dshHome: string\n /** Where the dsh entry is right now; recorded as the fast path. */\n resolvedEntry: string | null\n /** The extension the launcher must match: a `.cjs` entry gets a `.cjs` launcher. */\n entryExtension?: string | null\n /**\n * Install roots that are neither the harness home nor PATH \u2014 a clone, or a\n * project whose own `node_modules` carries dsh. Recorded and searched, so a\n * moved build is re-found on the next boot.\n */\n searchRoots?: string[] | null\n}\n\nexport interface DshLauncherWrite {\n path: string\n changed: boolean\n}\n\ninterface DshLauncherRecord {\n entry: string | null\n /** Where that entry's install sat, kept across rewrites while it stays valid. */\n roots: string[]\n writtenAt: number\n}\n\n/** The recorded entry a boot entry baked in, for the launcher's fast path. */\nexport function dshLauncherRecordPath(stateDir: string): string {\n return path.join(launcherDir(stateDir), 'dsh-resolved.json')\n}\n\n/** `bin/dsh.mjs`, or `bin/dsh.cjs` when the recorded entry is CommonJS. */\nexport function dshLauncherPath(stateDir: string, entryExtension?: string | null): string {\n const extension = (entryExtension ?? '').toLowerCase() === '.cjs' ? '.cjs' : '.mjs'\n return path.join(launcherDir(stateDir), `dsh${extension}`)\n}\n\nexport function readDshLauncherRecord(stateDir: string): DshLauncherRecord | null {\n return readJson<DshLauncherRecord>(dshLauncherRecordPath(stateDir))\n}\n\n/**\n * The dsh launcher's source.\n *\n * Like the home-hosted launcher, this exists because a clone's build output path\n * (or a versioned pnpm path) moves on the next install/rebuild: the boot entry\n * points at this stable script and the script re-finds dsh at every boot. A\n * `.cjs` entry gets a CommonJS launcher, so node loads it as one.\n */\nexport function buildDshLauncherSource(options: DshLauncherOptions): string {\n const esm = (options.entryExtension ?? '').toLowerCase() !== '.cjs'\n const prelude = esm\n ? `import fs from 'node:fs'\nimport path from 'node:path'\nimport process from 'node:process'\nimport { spawnSync } from 'node:child_process'`\n : `const fs = require('node:fs')\nconst path = require('node:path')\nconst process = require('node:process')\nconst { spawnSync } = require('node:child_process')`\n // A clone or a project install is re-found from the install roots that were\n // recorded with it, so a moved build needs no new boot entry.\n const roots = [options.resolvedEntry === null ? null : dshSearchRoot(options.resolvedEntry), ...(options.searchRoots ?? [])]\n .filter((root): root is string => typeof root === 'string' && root.length > 0)\n\n return `#!/usr/bin/env node\n// managed by dsh-home-hosted \u2014 rewritten on every plugin start; do not edit.\n${prelude}\n\nconst DSH_HOME = ${JSON.stringify(options.dshHome)}\nconst RECORD = ${JSON.stringify(dshLauncherRecordPath(options.stateDir))}\nconst SEARCH_ROOTS = ${JSON.stringify([...new Set(roots)])}\n\nfunction readRecord() {\n try { return JSON.parse(fs.readFileSync(RECORD, 'utf8')) } catch { return null }\n}\n\nfunction isEntry(file) {\n let stat = null\n try { stat = fs.statSync(file) } catch { return false }\n return stat.isFile() && /\\\\.(?:mjs|cjs|js)$/.test(file)\n}\n\nfunction collect(out, entry) {\n if (typeof entry === 'string' && isEntry(entry) && !out.includes(entry)) out.push(entry)\n}\n\nfunction collectStore(root, out) {\n const store = path.join(root, 'node_modules', '.pnpm')\n let names = []\n try { names = fs.readdirSync(store) } catch { return }\n for (const name of names) {\n if (!name.startsWith('dsh@') && !name.startsWith('@deepseek-ai+dsh@')) continue\n collect(out, path.join(store, name, 'node_modules', '@deepseek-ai', 'dsh', 'lib', 'bin.js'))\n collect(out, path.join(store, name, 'node_modules', 'dsh', 'bin', 'dsh.js'))\n }\n}\n\nfunction collectRoot(root, out) {\n collect(out, path.join(root, 'node_modules', '@deepseek-ai', 'dsh', 'lib', 'bin.js'))\n collect(out, path.join(root, 'node_modules', 'dsh', 'bin', 'dsh.js'))\n collectStore(root, out)\n}\n\nfunction candidates() {\n const out = []\n const record = readRecord()\n if (record && typeof record.entry === 'string') collect(out, record.entry)\n for (const root of [...(Array.isArray(record?.roots) ? record.roots : []), ...SEARCH_ROOTS]) collectRoot(root, out)\n collectRoot(DSH_HOME, out)\n let profiles = []\n try { profiles = fs.readdirSync(path.join(DSH_HOME, 'profiles')) } catch {}\n for (const name of profiles) collectRoot(path.join(DSH_HOME, 'profiles', name), out)\n // Last resort: a dsh on the entry's own PATH.\n for (const dir of (process.env.PATH ?? '').split(path.delimiter)) {\n collect(out, path.join(dir, 'dsh'))\n collect(out, path.join(dir, 'dsh.cmd'))\n }\n return out\n}\n\nfunction versionOf(entry) {\n let dir = path.dirname(entry)\n for (let hop = 0; hop < 4; hop += 1) {\n try {\n const manifest = JSON.parse(fs.readFileSync(path.join(dir, 'package.json'), 'utf8'))\n if (typeof manifest.version === 'string') return manifest.version\n } catch {}\n dir = path.dirname(dir)\n }\n return null\n}\n\nfunction compare(a, b) {\n const split = value => {\n const [core, pre = null] = String(value).split('-', 2)\n return { parts: core.split('.').map(part => Number.parseInt(part, 10) || 0), pre }\n }\n const left = split(a); const right = split(b)\n for (let i = 0; i < 3; i += 1) {\n const diff = (left.parts[i] ?? 0) - (right.parts[i] ?? 0)\n if (diff !== 0) return diff < 0 ? -1 : 1\n }\n if (left.pre === right.pre) return 0\n if (left.pre === null) return 1\n if (right.pre === null) return -1\n return left.pre < right.pre ? -1 : 1\n}\n\n// A recorded path that still exists is usually the copy to boot, but never the\n// older one: a rebuild or upgrade that landed elsewhere must win on version.\nfunction choose() {\n const recorded = readRecord()?.entry ?? null\n const found = candidates().map(entry => ({ entry, recorded: entry === recorded, version: versionOf(entry) }))\n const known = found.filter(item => item.version !== null)\n if (known.length > 0) {\n known.sort((a, b) => (compare(b.version, a.version) || (Number(b.recorded) - Number(a.recorded))))\n return known[0].entry\n }\n return (found.find(item => item.recorded) ?? found[0])?.entry ?? null\n}\n\nconst entry = choose()\nif (entry === null) {\n console.error('[dsh-home-hosted] no dsh entry found for ' + DSH_HOME + ' (recorded path, $DSH_HOME node_modules, profiles/*, PATH). Reinstall dsh, or restart: dsh web')\n process.exit(1)\n}\n\nconst args = process.argv.slice(2)\nconst result = /\\\\.(mjs|cjs|js)$/.test(entry)\n ? spawnSync(process.execPath, [entry, ...args], { stdio: 'inherit' })\n : spawnSync(entry, args, { stdio: 'inherit', shell: process.platform === 'win32' && /\\\\.(cmd|bat)$/i.test(entry) })\nprocess.exit(typeof result.status === 'number' ? result.status : 1)\n`\n}\n\n/** Write the launcher and record what `resolveDshLaunch` found. */\nexport function writeDshLauncher(options: DshLauncherOptions): DshLauncherWrite {\n const file = dshLauncherPath(options.stateDir, options.entryExtension)\n const source = buildDshLauncherSource(options)\n const previous = fs.existsSync(file) ? fs.readFileSync(file, 'utf8') : null\n const changed = previous !== source\n if (changed) {\n writeFileAtomic(file, source, 0o755)\n fs.chmodSync(file, 0o755)\n }\n // Roots are kept while they still look like a dsh install: they are what lets\n // a later boot re-find dsh after this install has moved.\n const raw = [dshSearchRoot(options.resolvedEntry), ...(options.searchRoots ?? []), ...(readDshLauncherRecord(options.stateDir)?.roots ?? [])]\n const known = raw.filter((root): root is string => typeof root === 'string' && root.length > 0 && dshRootUsable(root))\n const roots = [...new Set(known)]\n writeJsonAtomic(dshLauncherRecordPath(options.stateDir), {\n entry: options.resolvedEntry,\n roots,\n writtenAt: Date.now(),\n } satisfies DshLauncherRecord, 0o600)\n return { path: file, changed }\n}\n\n/** A dsh entry under one root: a flat install, or either pnpm store layout. */\nexport function dshCandidatesUnder(root: string): string[] {\n const out: string[] = []\n for (const entry of [\n path.join(root, 'node_modules', '@deepseek-ai', 'dsh', 'lib', 'bin.js'),\n path.join(root, 'node_modules', 'dsh', 'bin', 'dsh.js'),\n ]) {\n if (fs.existsSync(entry))\n out.push(entry)\n }\n const store = path.join(root, 'node_modules', '.pnpm')\n if (fs.existsSync(store)) {\n for (const name of fs.readdirSync(store)) {\n if (!name.startsWith('dsh@') && !name.startsWith('@deepseek-ai+dsh@'))\n continue\n for (const entry of [\n path.join(store, name, 'node_modules', '@deepseek-ai', 'dsh', 'lib', 'bin.js'),\n path.join(store, name, 'node_modules', 'dsh', 'bin', 'dsh.js'),\n ]) {\n if (fs.existsSync(entry))\n out.push(entry)\n }\n }\n }\n return out\n}\n\n/**\n * The install root a dsh entry belongs to: the directory whose `node_modules`\n * carries it \u2014 a clone root, or the project that installed dsh. That root is\n * what a rebuilt or upgraded install keeps.\n */\nexport function dshSearchRoot(entry: string | null | undefined): string | null {\n if (typeof entry !== 'string' || entry.length === 0)\n return null\n const parts = entry.split(path.sep)\n // A pnpm store path nests a second node_modules: the real root is the one\n // above `node_modules/.pnpm`, not the store's own package directory.\n const store = parts.indexOf('.pnpm')\n const modules = store > 0 ? store - 1 : parts.lastIndexOf('node_modules')\n return modules > 0 ? parts.slice(0, modules).join(path.sep) : null\n}\n\n/** Whether a root still holds a dsh install, or the store one could land in. */\nfunction dshRootUsable(root: string): boolean {\n return dshCandidatesUnder(root).length > 0 || fs.existsSync(path.join(root, 'node_modules', '.pnpm'))\n}\n\n", "/**\n * What this plugin decides about a server entry, and how that intent maps onto\n * the entry: only the keys in `OWNED_ENTRY_KEYS` are ever written, so a person's\n * own command, args, env, health block and everything else survive untouched.\n */\nimport type { EntryIntent, OnPortConflict, ServerEntry, ServerEntryPatch } from '../shared/contracts.js'\nimport { isOnPortConflict } from '../shared/contracts.js'\n\n/**\n * A detached restart of dsh is recognisable by its own marker/argv on POSIX, so\n * `follow` adopts it without killing anything. Windows cannot read another\n * process's environment and a `.cmd` shim hides the argv, so only `kill`\n * reliably reclaims the port there.\n */\nexport function defaultOnPortConflict(platform: NodeJS.Platform = process.platform): OnPortConflict {\n return platform === 'win32' ? 'kill' : 'follow'\n}\n\nexport function defaultIntent(id: string, platform: NodeJS.Platform = process.platform): EntryIntent {\n return {\n id,\n autostart: true,\n onPortConflict: defaultOnPortConflict(platform),\n stopKillPortHolders: true,\n persistent: true,\n }\n}\n\n/**\n * The owned keys as a patch, preserving any sibling keys inside `stop`.\n *\n * `persistent` is omitted unless the panel that would parse the write knows the\n * key: an older schema drops it and warns, so writing one is noise at best.\n */\nexport function ownedPatch(intent: EntryIntent, live?: ServerEntry | null, options: { persistent?: boolean } = {}): ServerEntryPatch {\n const stop = (live?.stop ?? {}) as Record<string, unknown>\n return {\n autostart: intent.autostart,\n onPortConflict: intent.onPortConflict,\n ...(options.persistent === false ? {} : { persistent: intent.persistent }),\n stop: { ...stop, killPortHolders: intent.stopKillPortHolders },\n }\n}\n\n/**\n * Owned keys whose live value differs from the intent.\n *\n * The intent keeps what the person asked for; a key the panel cannot parse is\n * not drift, or every entry would report one on an older panel.\n */\nexport function ownedDrift(live: ServerEntry | null, intent: EntryIntent, options: { persistent?: boolean } = {}): string[] {\n if (live === null)\n return ['missing entry']\n const drift: string[] = []\n if (live.autostart !== intent.autostart)\n drift.push('autostart')\n if (live.onPortConflict !== intent.onPortConflict)\n drift.push('onPortConflict')\n if (options.persistent !== false && (live.persistent ?? false) !== intent.persistent)\n drift.push('persistent')\n const killPortHolders = (live.stop as Record<string, unknown> | undefined)?.killPortHolders\n if (killPortHolders !== intent.stopKillPortHolders)\n drift.push('stop.killPortHolders')\n return drift\n}\n\n/**\n * Only the owned keys, as they were before this plugin touched the entry.\n *\n * A key the entry left out is recorded as the panel's schema default rather than\n * omitted: `{ id }` alone is what marks an entry this plugin created, so an\n * adopted entry with nothing explicit has to be distinguishable from it \u2014 or\n * \"stop managing\" deletes a server the person wrote.\n */\nexport function snapshotOwned(live: ServerEntry): ServerEntry {\n const killPortHolders = (live.stop as Record<string, unknown> | undefined)?.killPortHolders\n return {\n id: live.id,\n autostart: typeof live.autostart === 'boolean' ? live.autostart : false,\n onPortConflict: isOnPortConflict(live.onPortConflict) ? live.onPortConflict : 'block',\n persistent: live.persistent === true,\n stop: { killPortHolders: typeof killPortHolders === 'boolean' ? killPortHolders : false },\n }\n}\n\n/**\n * Restore an entry to what it was before adoption. A key the snapshot does not\n * carry was inherited from the panel's defaults, and a PATCH cannot delete a\n * key, so it is restored to that schema default instead.\n */\nexport function restorePatch(live: ServerEntry, snapshot: ServerEntry | null): ServerEntryPatch {\n const stop = (live.stop ?? {}) as Record<string, unknown>\n const previous = (snapshot?.stop ?? {}) as Record<string, unknown>\n return {\n autostart: snapshot?.autostart ?? false,\n onPortConflict: snapshot?.onPortConflict ?? 'block',\n persistent: snapshot?.persistent === true,\n stop: {\n ...stop,\n killPortHolders: typeof previous.killPortHolders === 'boolean' ? previous.killPortHolders : false,\n },\n }\n}\n", "/**\n * Starting, replacing and globally installing the panel.\n *\n * Starting it is the same thing a person does by hand: run the CLI's `up`, which\n * re-spawns itself detached, writes `run.json` and returns once the panel\n * answers. Replacing a panel *is* different \u2014 stopping the one that is answering\n * also stops the servers it supervises, including the dsh this plugin runs in \u2014\n * so the replacement is done by a detached helper that outlives this process.\n */\nimport { spawn } from 'node:child_process'\nimport type { ChildProcess } from 'node:child_process'\nimport fs from 'node:fs'\nimport path from 'node:path'\nimport process from 'node:process'\nimport type { PanelControlResult } from '../shared/contracts.js'\nimport { run } from '../util/exec.js'\nimport { writeFileAtomic } from '../util/fsx.js'\nimport type { CliLaunch } from './launch.js'\nimport { launcherDir } from './launcher.js'\n\nexport interface PanelControlDeps {\n /** The CLI to run, already resolved. */\n launch: CliLaunch | null\n home: string\n projectDir?: string | null\n stateDir: string\n /** Environment for the spawned CLI (absolute PATH, HOME, HHOSTED_HOME). */\n env: Record<string, string>\n timeoutMs?: number\n}\n\nfunction cliArgs(deps: PanelControlDeps, command: 'up' | 'down' | 'restart'): string[] {\n const args = [...(deps.launch?.args ?? []), command, '--home', deps.home]\n if (deps.projectDir)\n args.push('--project', deps.projectDir)\n return args\n}\n\nasync function runCli(deps: PanelControlDeps, command: 'up' | 'down' | 'restart'): Promise<{ code: number | null, stdout: string, stderr: string }> {\n const launch = deps.launch\n if (launch === null)\n return { code: null, stdout: '', stderr: 'no home-hosted CLI is available' }\n return await run(launch.program, cliArgs(deps, command), {\n env: deps.env,\n timeoutMs: deps.timeoutMs ?? 90_000,\n })\n}\n\n/** Start the preferred CLI as a detached panel; the CLI itself does the detaching. */\nexport async function startPanel(deps: PanelControlDeps): Promise<PanelControlResult> {\n const result = await runCli(deps, 'up')\n if (result.code !== 0) {\n const detail = result.stderr.trim() || result.stdout.trim() || `the CLI exited ${String(result.code)}`\n return { ok: false, detail }\n }\n const match = /https?:\\/\\/[^\\s]+/.exec(result.stdout)\n return { ok: true, detail: 'the panel is answering', url: match?.[0] ?? null }\n}\n\nexport function takeoverHelperPath(stateDir: string): string {\n return path.join(launcherDir(stateDir), 'panel-takeover.mjs')\n}\n\nexport function takeoverLogPath(stateDir: string): string {\n return path.join(launcherDir(stateDir), 'panel-takeover.log')\n}\n\n/** The generated helper's source; exported so a test can inspect it. */\nexport function buildTakeoverSource(deps: PanelControlDeps, oldPid: number | null, marker = 'managed by dsh-home-hosted'): string {\n const program = deps.launch?.program ?? process.execPath\n const args = deps.launch === null\n ? []\n : [...deps.launch.args, 'up', '--home', deps.home, ...(deps.projectDir ? ['--project', deps.projectDir] : [])]\n const downArgs = [...(deps.launch?.args ?? []), 'down', '--home', deps.home]\n return `#!/usr/bin/env node\n// ${marker} \u2014 replaces the panel; do not edit.\nimport fs from 'node:fs'\nimport { spawnSync } from 'node:child_process'\n\nconst OLD_PID = ${JSON.stringify(oldPid)}\nconst DOWN_ARGS = ${JSON.stringify(downArgs)}\nconst PROGRAM = ${JSON.stringify(program)}\nconst ARGS = ${JSON.stringify(args)}\nconst ENV = ${JSON.stringify(deps.env)}\nconst LOG = ${JSON.stringify(takeoverLogPath(deps.stateDir))}\n\nfunction log(line) {\n try { fs.appendFileSync(LOG, new Date().toISOString() + ' ' + line + '\\\\n') } catch {}\n}\n\nfunction alive(pid) {\n if (typeof pid !== 'number') return false\n try { process.kill(pid, 0); return true } catch { return false }\n}\n\nconst sleep = ms => new Promise(resolve => setTimeout(resolve, ms))\n\nlog('stopping the answering panel: ' + PROGRAM + ' ' + DOWN_ARGS.join(' '))\nconst down = spawnSync(PROGRAM, DOWN_ARGS, { env: { ...process.env, ...ENV }, stdio: 'ignore' })\nlog('down exited ' + String(down.status))\n\nfor (let i = 0; i < 40 && alive(OLD_PID); i += 1)\n await sleep(250)\n\nif (alive(OLD_PID)) {\n log('still alive; sending SIGTERM')\n try { process.kill(OLD_PID, 'SIGTERM') } catch {}\n for (let i = 0; i < 40 && alive(OLD_PID); i += 1)\n await sleep(250)\n}\n\nif (alive(OLD_PID)) {\n log('still alive; sending SIGKILL')\n try { process.kill(OLD_PID, 'SIGKILL') } catch {}\n for (let i = 0; i < 20 && alive(OLD_PID); i += 1)\n await sleep(250)\n}\n\nlog('starting ' + PROGRAM + ' ' + ARGS.join(' '))\nconst result = spawnSync(PROGRAM, ARGS, { env: { ...process.env, ...ENV }, stdio: 'ignore' })\nlog('started with exit ' + String(result.status))\n`\n}\n\nexport function writeTakeoverHelper(deps: PanelControlDeps, oldPid: number | null): string {\n const file = takeoverHelperPath(deps.stateDir)\n writeFileAtomic(file, buildTakeoverSource(deps, oldPid), 0o755)\n fs.chmodSync(file, 0o755)\n return file\n}\n\n/** Spawn a helper process; injected so a test can drive the failure paths. */\nexport type SpawnDetached = (program: string, args: string[]) => ChildProcess\n\nfunction spawnDetached(program: string, args: string[]): ChildProcess {\n return spawn(program, args, { detached: true, stdio: 'ignore' })\n}\n\n/**\n * Spawn the helper detached and return immediately: the old panel's shutdown is\n * about to stop this very process, so waiting for the result would lose it.\n */\nexport function spawnTakeover(deps: PanelControlDeps, oldPid: number | null, spawnChild: SpawnDetached = spawnDetached): PanelControlResult {\n const helper = writeTakeoverHelper(deps, oldPid)\n let child: ChildProcess\n try {\n child = spawnChild(process.execPath, [helper])\n }\n catch (error) {\n return { ok: false, detail: `could not start the panel-replacement helper: ${error instanceof Error ? error.message : String(error)}` }\n }\n // A detached child reports a failed start asynchronously; an unhandled 'error'\n // event is thrown, and that would end this process instead of the helper's.\n child.on('error', () => {})\n child.unref()\n return {\n ok: true,\n detail: 'replacing the panel now; this page will disconnect and come back under the preferred copy',\n }\n}\n\n/** Install the pinned range globally, so the `global` preference has something to use. */\nexport async function installGlobal(\n range: string,\n options: { pnpm?: boolean, run?: typeof run } = {},\n): Promise<{ ok: boolean, detail: string, output: string }> {\n const execute = options.run ?? run\n const usePnpm = options.pnpm ?? true\n const result = usePnpm\n ? await execute('pnpm', ['add', '-g', `home-hosted@${range}`], { timeoutMs: 300_000 })\n : await execute('npm', ['install', '-g', `home-hosted@${range}`], { timeoutMs: 300_000 })\n const output = `${result.stdout}\\n${result.stderr}`.trim()\n if (result.code !== 0)\n return { ok: false, detail: result.error ?? `the installer exited ${String(result.code)}`, output }\n return { ok: true, detail: `installed home-hosted@${range} globally`, output }\n}\n", "/**\n * The home-hosted HTTP API client.\n *\n * Every call carries the plugin's own API token; the panel verifies it from its\n * secrets file on each request. A write through this client is the safe path:\n * the config store records the bytes it wrote, so the panel's own file watcher\n * never treats the change as an external edit.\n */\nimport type { ServerEntry, ServerEntryPatch, ServerEntryView } from '../shared/contracts.js'\n\nexport class PanelError extends Error {\n constructor(\n message: string,\n readonly code: string,\n readonly status: number | null = null,\n /** The panel's own diagnostic, when it sent one. */\n readonly detail: unknown = undefined,\n ) {\n super(message)\n this.name = 'PanelError'\n }\n}\n\nexport interface PanelClientOptions {\n baseUrl: string\n token: string\n timeoutMs?: number\n}\n\nexport class PanelClient {\n private readonly baseUrl: string\n private readonly token: string\n private readonly timeoutMs: number\n\n constructor(options: PanelClientOptions) {\n this.baseUrl = options.baseUrl.replace(/\\/+$/, '')\n this.token = options.token\n this.timeoutMs = options.timeoutMs ?? 10_000\n }\n\n private async request<T>(method: string, path: string, body?: unknown): Promise<T> {\n let response: Response\n try {\n response = await fetch(`${this.baseUrl}${path}`, {\n method,\n headers: {\n authorization: `Bearer ${this.token}`,\n ...(body === undefined ? {} : { 'content-type': 'application/json' }),\n },\n body: body === undefined ? undefined : JSON.stringify(body),\n signal: AbortSignal.timeout(this.timeoutMs),\n })\n }\n catch (error) {\n throw new PanelError(\n error instanceof Error ? error.message : String(error),\n 'PANEL_UNREACHABLE',\n )\n }\n\n const text = await response.text()\n let parsed: unknown = null\n try {\n parsed = text.length > 0 ? JSON.parse(text) : null\n }\n catch {\n throw new PanelError(`the panel answered ${response.status} with a non-JSON body`, 'PANEL_BAD_RESPONSE', response.status)\n }\n\n if (!response.ok) {\n const record = parsed as { message?: unknown, code?: unknown, detail?: unknown } | null\n const message = typeof record?.message === 'string' ? record.message : `the panel answered ${response.status}`\n const code = typeof record?.code === 'string' ? record.code : 'PANEL_ERROR'\n throw new PanelError(message, code, response.status, record?.detail)\n }\n\n return parsed as T\n }\n\n async listServers(): Promise<ServerEntryView[]> {\n const answer = await this.request<{ servers: ServerEntryView[] }>('GET', '/api/servers')\n return answer.servers\n }\n\n async getServer(id: string): Promise<ServerEntryView> {\n const answer = await this.request<{ server: ServerEntryView }>('GET', `/api/servers/${encodeURIComponent(id)}`)\n return answer.server\n }\n\n async createServer(entry: ServerEntry): Promise<ServerEntryView> {\n const answer = await this.request<{ server: ServerEntryView }>('POST', '/api/servers', entry)\n return answer.server\n }\n\n async updateServer(id: string, patch: ServerEntryPatch): Promise<ServerEntryView> {\n const answer = await this.request<{ server: ServerEntryView }>('PATCH', `/api/servers/${encodeURIComponent(id)}`, patch)\n return answer.server\n }\n\n async deleteServer(id: string): Promise<void> {\n await this.request('DELETE', `/api/servers/${encodeURIComponent(id)}`)\n }\n\n async startServer(id: string): Promise<void> {\n await this.request('POST', `/api/servers/${encodeURIComponent(id)}/start`)\n }\n\n async stopServer(id: string): Promise<void> {\n await this.request('POST', `/api/servers/${encodeURIComponent(id)}/stop`)\n }\n\n async restartServer(id: string): Promise<void> {\n await this.request('POST', `/api/servers/${encodeURIComponent(id)}/restart`)\n }\n\n /** Re-list the port's listeners and stop what is not the panel's own tree. */\n async freePort(id: string): Promise<{ stopped?: number[] }> {\n return await this.request<{ stopped?: number[] }>('POST', `/api/servers/${encodeURIComponent(id)}/free-port`)\n }\n}\n\n/**\n * What a token probe measured: `ok` \u2014 the panel accepted it; `refused` \u2014 the\n * panel answered and rejected it; `unreachable` \u2014 the panel was not there to\n * ask, which is not the same as a refusal.\n */\nexport type TokenProbe = 'ok' | 'refused' | 'unreachable'\n\n/**\n * Prove a token with a non-mutating `listServers()`, and say whether the panel\n * refused it or merely was not answering. A timeout or connection error must\n * never be reported as a stale token.\n */\nexport async function probeToken(baseUrl: string, token: string, timeoutMs = 5000): Promise<TokenProbe> {\n try {\n await new PanelClient({ baseUrl, token, timeoutMs }).listServers()\n return 'ok'\n }\n catch (error) {\n if (error instanceof PanelError && (error.code === 'AUTH_REQUIRED' || error.status === 401 || error.status === 403))\n return 'refused'\n return 'unreachable'\n }\n}\n\n/** Prove a token works, without needing any write permission. */\nexport async function verifyToken(baseUrl: string, token: string, timeoutMs = 5000): Promise<boolean> {\n return await probeToken(baseUrl, token, timeoutMs) === 'ok'\n}\n", "/**\n * Facts about the running home-hosted panel, read from the `run.json` it writes\n * at startup. Its token field is deliberately never read: the plugin\n * authenticates with its own enrolled API token instead.\n */\nimport http from 'node:http'\nimport https from 'node:https'\nimport process from 'node:process'\nimport { readJson } from '../util/fsx.js'\nimport { runtimeFile } from '../util/paths.js'\n\nexport interface PanelRuntime {\n version: string\n pid: number\n url: string\n probeUrl?: string\n protocol?: string\n port: number\n bindHost?: string\n projectDir?: string\n dataRoot?: string\n configPath?: string\n logFile?: string\n}\n\nexport function readRuntime(home: string): PanelRuntime | null {\n const raw = readJson<Record<string, unknown>>(runtimeFile(home))\n if (raw === null)\n return null\n const url = typeof raw.url === 'string' ? raw.url : null\n const pid = typeof raw.pid === 'number' ? raw.pid : null\n if (url === null || pid === null)\n return null\n return {\n version: typeof raw.version === 'string' ? raw.version : 'unknown',\n pid,\n url: url.replace(/\\/+$/, ''),\n probeUrl: typeof raw.probeUrl === 'string' ? raw.probeUrl : undefined,\n protocol: typeof raw.protocol === 'string' ? raw.protocol : undefined,\n port: typeof raw.port === 'number' ? raw.port : 0,\n bindHost: typeof raw.bindHost === 'string' ? raw.bindHost : undefined,\n projectDir: typeof raw.projectDir === 'string' ? raw.projectDir : undefined,\n dataRoot: typeof raw.dataRoot === 'string' ? raw.dataRoot : undefined,\n configPath: typeof raw.configPath === 'string' ? raw.configPath : undefined,\n logFile: typeof raw.logFile === 'string' ? raw.logFile : undefined,\n }\n}\n\nexport function pidAlive(pid: number): boolean {\n try {\n process.kill(pid, 0)\n return true\n }\n catch {\n return false\n }\n}\n\n/**\n * Ask the panel's public health route whether it is answering. Uses the raw\n * http/https modules so a self-signed TLS pair answers too.\n */\nexport async function probePanel(url: string, timeoutMs = 2000): Promise<boolean> {\n const target = `${url.replace(/\\/+$/, '')}/healthz`\n return await new Promise<boolean>((resolve) => {\n let settled = false\n const done = (value: boolean): void => {\n if (settled)\n return\n settled = true\n resolve(value)\n }\n\n let parsed: URL\n try {\n parsed = new URL(target)\n }\n catch {\n done(false)\n return\n }\n\n const transport = parsed.protocol === 'https:' ? https : http\n const request = transport.get(\n {\n hostname: parsed.hostname,\n port: parsed.port,\n path: `${parsed.pathname}${parsed.search}`,\n timeout: timeoutMs,\n rejectUnauthorized: false,\n },\n (response) => {\n response.resume()\n done(typeof response.statusCode === 'number')\n },\n )\n request.on('timeout', () => {\n request.destroy()\n done(false)\n })\n request.on('error', () => done(false))\n })\n}\n", "/**\n * The plugin's own credential for the home-hosted panel.\n *\n * home-hosted keeps only the token's hash, so a token this plugin did not\n * create can never be recovered from disk. When none is enrolled, the plugin\n * mints one and hands it to `home-hosted set-token` through `HHOSTED_TOKEN`,\n * which stores the hash and prints nothing; when the panel refuses the stored\n * one, `reclaimToken` replaces it with a fresh token the same way.\n * The plaintext lives 0600 under the plugin state directory and is never logged,\n * rendered, or sent to the browser.\n */\nimport { randomBytes } from 'node:crypto'\nimport path from 'node:path'\nimport type { RunResult } from '../util/exec.js'\nimport { readJson, readText, writeFileAtomic } from '../util/fsx.js'\nimport { secretsFile } from '../util/paths.js'\n\nexport type CliExecutor = (args: string[], env: Record<string, string | undefined>) => Promise<RunResult>\n\nexport interface EnsureTokenOptions {\n home: string\n stateDir: string\n exec: CliExecutor\n}\n\nexport interface EnsureTokenResult {\n token: string | null\n /** True when this call created the token. */\n enrolled: boolean\n detail: string\n}\n\nexport interface ReclaimTokenOptions {\n home: string\n stateDir: string\n exec: CliExecutor\n}\n\nexport interface ReclaimTokenResult {\n token: string | null\n detail: string\n}\n\nexport function storedTokenPath(stateDir: string): string {\n return path.join(stateDir, 'panel-token')\n}\n\nexport function readStoredToken(stateDir: string): string | null {\n const text = readText(storedTokenPath(stateDir))?.trim()\n return text !== undefined && text.length > 0 ? text : null\n}\n\nexport function storeToken(stateDir: string, token: string): void {\n writeFileAtomic(storedTokenPath(stateDir), `${token}\\n`, 0o600)\n}\n\nexport function generateToken(): string {\n return randomBytes(32).toString('base64url')\n}\n\n/** Whether home-hosted already holds an API token (only its hash is on disk). */\nexport function apiTokenEnrolled(home: string): boolean {\n const secrets = readJson<{ apiToken?: unknown }>(secretsFile(home))\n return secrets !== null && secrets.apiToken !== null && secrets.apiToken !== undefined\n}\n\n/**\n * One in-flight token operation per state directory, so two callers cannot race.\n *\n * Two concurrent callers used to mint two tokens: both `set-token` calls land, and\n * the loser's token is the one stored on disk while the panel keeps the winner's\n * hash \u2014 after which the plugin can never authenticate, and never re-enrols,\n * because home-hosted already holds an API token. Every operation on one state\n * directory therefore runs after the previous one has settled.\n */\nconst queue = new Map<string, Promise<unknown>>()\n\nfunction serialised<T>(stateDir: string, work: () => Promise<T>): Promise<T> {\n const key = path.resolve(stateDir)\n const previous = queue.get(key) ?? Promise.resolve()\n // Run even when the previous operation rejected: that failure is its caller's.\n const next = previous.then(work, work)\n const settled = next.then(() => undefined, () => undefined)\n queue.set(key, settled)\n void settled.then(() => {\n if (queue.get(key) === settled) queue.delete(key)\n })\n return next\n}\n\nexport async function ensureToken(options: EnsureTokenOptions): Promise<EnsureTokenResult> {\n return await serialised(options.stateDir, async () => await enrollToken(options))\n}\n\n/**\n * Replace the panel's API token with a fresh one.\n *\n * home-hosted keeps only the token's hash, so a token this plugin does not hold\n * cannot be recovered: a fresh token is minted, enrolled through the same\n * `HHOSTED_TOKEN` path `ensureToken` uses \u2014 one write, since `set-token` replaces\n * whatever hash is there \u2014 and only then is the plaintext stored 0600. The\n * attempted write carries no risk to the stored token: a failure replaced\n * nothing, so the previous plaintext is kept.\n */\nexport async function reclaimToken(options: ReclaimTokenOptions): Promise<ReclaimTokenResult> {\n return await serialised(options.stateDir, async () => await enrollFreshToken(options))\n}\n\ninterface CliAttempt {\n result?: RunResult\n failure?: string\n}\n\n/** Run one CLI step, turning both a non-zero exit and a spawn throw into text. */\nasync function runCli(exec: CliExecutor, args: string[], env: Record<string, string | undefined>): Promise<CliAttempt> {\n try {\n const result = await exec(args, env)\n if (result.code !== 0) {\n return {\n failure: result.error?.trim() || result.stderr.trim() || result.stdout.trim() || `exit ${String(result.code)}`,\n }\n }\n return { result }\n }\n catch (error) {\n return { failure: error instanceof Error ? error.message : String(error) }\n }\n}\n\n/** Mint a token when none is enrolled. */\nasync function enrollToken(options: EnsureTokenOptions): Promise<EnsureTokenResult> {\n const stored = readStoredToken(options.stateDir)\n if (stored !== null)\n return { token: stored, enrolled: false, detail: 'using the stored panel token' }\n\n if (apiTokenEnrolled(options.home)) {\n return {\n token: null,\n enrolled: false,\n detail: 'home-hosted already has an API token, and this plugin does not have it; '\n + 'run `home-hosted set-token --generate` and store that token, or clear it and re-enable',\n }\n }\n\n const token = generateToken()\n const enrolled = await runCli(options.exec, ['--home', options.home, 'set-token'], { HHOSTED_TOKEN: token })\n if (enrolled.result === undefined) {\n return {\n token: null,\n enrolled: false,\n detail: `could not enrol an API token: ${enrolled.failure ?? 'the CLI did not answer'}`,\n }\n }\n\n storeToken(options.stateDir, token)\n return { token, enrolled: true, detail: 'enrolled a new panel API token' }\n}\n\nasync function enrollFreshToken(options: ReclaimTokenOptions): Promise<ReclaimTokenResult> {\n // One write, not a clear-then-set pair: `set-token` replaces whatever hash is\n // there (proved against the real CLI), and clearing first would leave a window\n // in which the panel has no token at all.\n const token = generateToken()\n const enrolled = await runCli(options.exec, ['--home', options.home, 'set-token'], { HHOSTED_TOKEN: token })\n if (enrolled.result === undefined) {\n // Nothing was replaced, so the stored token is still the panel's and is left\n // alone: dropping it would throw away a credential that may still work.\n return {\n token: null,\n detail: `could not enrol a fresh API token: ${enrolled.failure ?? 'the CLI did not answer'}; `\n + 'the previously stored token was kept',\n }\n }\n\n storeToken(options.stateDir, token)\n return { token, detail: 'enrolled a fresh panel API token' }\n}\n", "/**\n * The browser half's one entry point.\n *\n * The route is registered on DeepSeek Harness's shared `/api` channel, so the\n * physical carrier has already applied the Host/Origin fence and browser\n * authentication before this handler runs: only the local operator reaches it.\n * Domain failures travel inside the envelope, protocol failures as HTTP status.\n */\nimport type { Context } from '@deepseek-ai/cordis'\nimport type { RpcEndpoint, RpcRequest } from './shared/contracts.js'\nimport { RPC_PATH, RPC_VERSION } from './shared/contracts.js'\nimport type { HomeHostedService } from './service.js'\nimport { HomeHostedError } from './service.js'\n\ninterface FetchRoute {\n path: string\n methods: readonly string[]\n requestBody: 'buffered' | 'streaming'\n fetch: (request: Request) => Promise<Response>\n}\n\ninterface ConnectionLike {\n fetch: { register: (route: FetchRoute) => () => unknown }\n}\n\ninterface ConnectionHost {\n connection: ConnectionLike\n}\n\ninterface LoggerLike {\n warn?: (message: string) => void\n}\n\nfunction answer(endpoint: RpcEndpoint | string, result: unknown): Response {\n return Response.json({ v: RPC_VERSION, endpoint, result })\n}\n\nexport function registerRpc(ctx: Context, service: HomeHostedService): void {\n ctx.inject(['connection'], (scoped) => {\n const connection = (scoped as unknown as ConnectionHost).connection\n if (connection?.fetch?.register === undefined)\n return\n\n scoped.effect(() => {\n let dispose: () => unknown\n try {\n dispose = connection.fetch.register({\n // The exact-route registry is keyed by the full request path, so the\n // `/api` prefix belongs here; the page composes the same URL from\n // API_BASE + RPC_PATH.\n path: `/api${RPC_PATH}`,\n methods: ['POST'],\n requestBody: 'buffered',\n fetch: async (request: Request) => {\n let body: RpcRequest\n try {\n body = await request.json() as RpcRequest\n }\n catch {\n return Response.json({ error: 'the request body is not JSON' }, { status: 400 })\n }\n\n if (body === null || typeof body !== 'object' || body.v !== RPC_VERSION) {\n return Response.json(\n { error: `this page and the host disagree on the protocol version (expected ${String(RPC_VERSION)})` },\n { status: 409 },\n )\n }\n\n try {\n const value = await service.call(body.endpoint, body.payload)\n return answer(body.endpoint, { ok: true, value })\n }\n catch (error) {\n const code = error instanceof HomeHostedError ? error.code : 'INTERNAL'\n const message = error instanceof Error ? error.message : String(error)\n const detail = (error as { detail?: unknown } | null)?.detail\n return answer(body.endpoint, { ok: false, error: { code, message, ...(detail === undefined ? {} : { detail }) } })\n }\n },\n })\n }\n catch (error) {\n // A registration the carrier refuses would otherwise look like a page\n // that silently 404s; say so where an operator can see it.\n const logger = (scoped as unknown as { logger?: LoggerLike }).logger\n logger?.warn?.(`[dsh-home-hosted] could not register ${RPC_PATH}: ${error instanceof Error ? error.message : String(error)}`)\n return () => {}\n }\n\n return () => {\n // A disposer that rejects would otherwise surface as an unhandled\n // rejection, which ends the process on Node 24.\n void Promise.resolve(dispose()).catch(() => {})\n }\n }, 'dsh-home-hosted: rpc route')\n })\n}\n", "import type { Context } from '@deepseek-ai/cordis'\n\n/**\n * dsh web answers an unauthenticated browser with a plain-text 401 line written\n * by the in-box connection plugin. That text is not configurable and no event\n * covers it, so a home-hosted deployment \u2014 which is where this session's log,\n * and with it the tokenised URL, actually lives \u2014 appends where to look.\n *\n * It reaches one internal field, `connection.browserAuth.writeUnauthorized`, and\n * fails soft: if that shape is ever gone, dsh's own text is left untouched.\n */\nexport const STOCK_UNAUTHORIZED = 'dsh web authentication required; reopen the URL printed by dsh web.'\n\n/** The 401 body: dsh's own line, plus where this deployment's log page is. */\nexport function authNoticeBody(logUrl: string | null): string {\n if (logUrl === null)\n return `${STOCK_UNAUTHORIZED}\\n`\n return `${STOCK_UNAUTHORIZED}\\nhome-hosted: the URL with its token is in the dsh log at ${logUrl}. An authentication plugin can sign you in seamlessly instead.\\n`\n}\n\ninterface AuthLike {\n writeUnauthorized?: unknown\n}\n\n/**\n * Wrap the auth object's 401 writer so the body carries the notice.\n * @returns the disposer that puts the original back.\n */\nfunction wrap(auth: { writeUnauthorized: (req: unknown, res: unknown) => void }, logUrlOf: () => string | null): () => void {\n const original = auth.writeUnauthorized.bind(auth)\n auth.writeUnauthorized = (req, res) => {\n const response = res as {\n end?: (...args: unknown[]) => unknown\n once?: (event: string, listener: () => void) => unknown\n writableEnded?: boolean\n }\n const end = response.end\n if (typeof end !== 'function' || response.writableEnded === true) {\n original(req, res)\n return\n }\n\n let restored = false\n const restore = (): void => {\n if (restored) return\n restored = true\n try {\n response.end = end\n }\n catch {\n // a response that refuses the assignment keeps the original writer\n }\n }\n\n try {\n response.end = (...args: unknown[]) => {\n restore()\n const [chunk, ...rest] = args\n let body = chunk\n // Only the untouched stock line is ours to rewrite; an authentication\n // plugin's own page (or the same sentence inside longer text) is left alone.\n if (typeof chunk === 'string' && chunk.trim() === STOCK_UNAUTHORIZED) {\n try {\n body = authNoticeBody(logUrlOf())\n }\n catch {\n body = chunk\n }\n }\n return end.call(response, body, ...rest)\n }\n }\n catch {\n original(req, res)\n return\n }\n\n // A writer that ends later still gets the notice; one that never ends must\n // not leave our wrapper on the response.\n try {\n response.once?.('finish', restore)\n response.once?.('close', restore)\n }\n catch {\n // events are best-effort tidiness, never a reason to lose the 401\n }\n original(req, res)\n }\n return () => {\n auth.writeUnauthorized = original\n }\n}\n\n/**\n * Install the notice once the connection service is up. `logUrlOf` is read per\n * 401, so turning the setting off takes effect without re-installing anything.\n */\nexport function registerAuthNotice(ctx: Context, logUrlOf: () => string | null): void {\n ctx.inject(['connection'], (scoped) => {\n scoped.effect(() => {\n const connection = scoped.get('connection') as { browserAuth?: AuthLike } | undefined\n const auth = connection?.browserAuth\n if (typeof auth?.writeUnauthorized !== 'function')\n return () => {}\n return wrap(auth as { writeUnauthorized: (req: unknown, res: unknown) => void }, logUrlOf)\n }, 'dsh-home-hosted: sign-in notice')\n })\n}\n", "/**\n * The plugin's own settings, kept in a 0600 JSON file under its state directory.\n *\n * These are the things a person toggles; the Cordis row config stays for\n * operator overrides only, so neither surface can silently overwrite the other.\n */\nimport { AGENT_TOOL_NAMES, DEFAULT_SETTINGS, isOnPortConflict } from './shared/contracts.js'\nimport type { AgentToolName, EntryIntent, PluginSettings, SettingsPatch } from './shared/contracts.js'\nimport { SETTINGS_VERSION } from './shared/contracts.js'\nimport { readJson, writeJsonAtomic } from './util/fsx.js'\nimport { defaultIntent } from './home-hosted/entries.js'\n\nfunction knownTool(value: unknown): value is AgentToolName {\n return typeof value === 'string' && (AGENT_TOOL_NAMES as readonly string[]).includes(value)\n}\n\nfunction normalizeIntent(value: Partial<EntryIntent> | null | undefined, fallbackId: string): EntryIntent {\n const base = defaultIntent(typeof value?.id === 'string' && value.id.length > 0 ? value.id : fallbackId)\n return {\n id: base.id,\n autostart: typeof value?.autostart === 'boolean' ? value.autostart : base.autostart,\n // Absent means a stored intent from before persistence existed: it wants it.\n persistent: typeof value?.persistent === 'boolean' ? value.persistent : base.persistent,\n // Only a policy the panel's own schema parses may reach the config it boots from.\n onPortConflict: isOnPortConflict(value?.onPortConflict) ? value.onPortConflict : base.onPortConflict,\n stopKillPortHolders: typeof value?.stopKillPortHolders === 'boolean' ? value.stopKillPortHolders : base.stopKillPortHolders,\n }\n}\n\n/**\n * Tools that were split apart before 0.2.0 and merged since. An allowlist\n * written by an older release lists the old names, and an unknown name is\n * dropped \u2014 which would silently turn every tool off on upgrade.\n */\nconst LEGACY_TOOL_NAMES: Record<string, string> = {\n servers_start: 'servers_lifecycle',\n servers_stop: 'servers_lifecycle',\n servers_restart: 'servers_lifecycle',\n servers_create: 'servers_edit',\n servers_update: 'servers_edit',\n servers_delete: 'servers_edit',\n autostart_install: 'autostart_manage',\n autostart_uninstall: 'autostart_manage',\n}\n\n/** The pair an older release wrote when nobody had chosen anything. */\nfunction isLegacyDefaultAllowlist(names: readonly string[]): boolean {\n return names.length === 2 && names.includes('status') && names.includes('servers_list')\n}\n\nconst BOOT_MECHANISMS: readonly string[] = ['auto', 'systemd-user', 'systemd-system', 'launchd-agent', 'launchd-daemon', 'xdg-autostart', 'windows-run', 'windows-task', 'container', 'unsupported']\n\nfunction isBootMechanism(value: unknown): value is PluginSettings['autostart']['mechanism'] {\n return typeof value === 'string' && BOOT_MECHANISMS.includes(value)\n}\n\nfunction normalize(raw: Partial<PluginSettings> | null, fallbackEntryId: string): PluginSettings {\n const entries = Array.isArray(raw?.entries)\n ? raw.entries.map(intent => normalizeIntent(intent, fallbackEntryId))\n : []\n const declared = Array.isArray(raw?.agentTools?.allow) ? raw.agentTools.allow : null\n // Only a file written before the version stamp needs translating: the release\n // that wrote it named tools this one merged, and dropping those names silently\n // would turn every tool off on upgrade.\n const legacyFile = (typeof raw?.version === 'number' ? raw.version : 1) < SETTINGS_VERSION\n const migrated = declared === null\n ? null\n : [...new Set(declared.map(name => (legacyFile ? LEGACY_TOOL_NAMES[name] ?? name : name)).filter(knownTool))] as AgentToolName[]\n // In a legacy file the old default pair is not a choice, it is what that\n // release wrote for \"unset\".\n const choseNothing = legacyFile && declared !== null && migrated !== null && isLegacyDefaultAllowlist(declared)\n const allow = migrated === null || choseNothing ? [...DEFAULT_SETTINGS.agentTools.allow] : migrated\n const attempt = raw?.autostart?.lastAttempt\n return {\n version: SETTINGS_VERSION,\n autostart: {\n enabled: raw?.autostart?.enabled === true,\n mechanism: isBootMechanism(raw?.autostart?.mechanism) ? raw.autostart.mechanism : 'auto',\n ...(attempt === undefined ? {} : { lastAttempt: attempt }),\n },\n // A pre-0.2.0 file expressed management only by holding an intent for the\n // harness entry; the page's toggle needs the flag it never had.\n manageDsh: raw?.manageDsh === true\n || (legacyFile && entries.some(entry => entry.id === fallbackEntryId)),\n entries,\n panel: {\n // An integer in range, or nothing: the panel's schema rejects anything else,\n // and a value it cannot parse stops it booting at all.\n port: typeof raw?.panel?.port === 'number' && Number.isInteger(raw.panel.port) && raw.panel.port >= 1 && raw.panel.port <= 65535\n ? raw.panel.port\n : null,\n },\n authNotice: raw?.authNotice === undefined ? DEFAULT_SETTINGS.authNotice : raw.authNotice === true,\n // Absent means on: a stale token is a fault to repair, not a setting to opt into.\n reclaimToken: raw?.reclaimToken === undefined ? DEFAULT_SETTINGS.reclaimToken : raw.reclaimToken === true,\n uiStyle: raw?.uiStyle === 'compact' ? 'compact' : 'detailed',\n agentTools: {\n // Absent means the default (on), and so does the pair the previous\n // release wrote for it; any other explicit false stays false.\n enabled: choseNothing || raw?.agentTools?.enabled === undefined\n ? DEFAULT_SETTINGS.agentTools.enabled\n : raw.agentTools.enabled === true,\n // Absent means every tool; an explicit empty list means none of them.\n allow,\n },\n cli: {\n prefer: raw?.cli?.prefer === 'global' ? 'global' : 'pinned',\n },\n }\n}\n\nexport class SettingsStore {\n private current: PluginSettings\n private readonly listeners = new Set<(settings: PluginSettings) => void>()\n\n constructor(\n readonly file: string,\n private readonly fallbackEntryId: string,\n ) {\n this.current = normalize(readJson<Partial<PluginSettings>>(file), fallbackEntryId)\n }\n\n get(): PluginSettings {\n return this.current\n }\n\n /** The intent for an entry, materialising the default when it has none yet. */\n intentFor(id: string): EntryIntent {\n return this.current.entries.find(entry => entry.id === id) ?? defaultIntent(id)\n }\n\n update(patch: SettingsPatch): PluginSettings {\n const next = normalize({\n // A patch is not a legacy file: the migration belongs to reading one.\n version: SETTINGS_VERSION,\n autostart: { ...this.current.autostart, ...(patch.autostart ?? {}) },\n manageDsh: patch.manageDsh ?? this.current.manageDsh,\n entries: patch.entries ?? this.current.entries,\n panel: { ...this.current.panel, ...(patch.panel ?? {}) },\n authNotice: patch.authNotice ?? this.current.authNotice,\n reclaimToken: patch.reclaimToken ?? this.current.reclaimToken,\n uiStyle: patch.uiStyle ?? this.current.uiStyle,\n agentTools: { ...this.current.agentTools, ...(patch.agentTools ?? {}) },\n cli: { ...this.current.cli, ...(patch.cli ?? {}) },\n }, this.fallbackEntryId)\n this.current = next\n writeJsonAtomic(this.file, next, 0o600)\n for (const listener of this.listeners)\n listener(next)\n return next\n }\n\n onChange(listener: (settings: PluginSettings) => void): () => void {\n this.listeners.add(listener)\n return () => {\n this.listeners.delete(listener)\n }\n }\n}\n", "/**\n * Agent tools, on by default and allowlisted by name.\n *\n * The list is read at registration time and re-read whenever the settings file\n * changes, so toggling a tool takes effect without a restart. A tool that\n * changes something asks the approval service only when the calling session is\n * not already `danger-full-access` \u2014 the session has then granted exactly what\n * the tool would be asking about, and asking anyway is what makes a\n * Full-access run fail against an auto-rejecting approval channel.\n */\nimport type { Context } from '@deepseek-ai/cordis'\nimport type { ParameterSchemaSpec } from '@deepseek-ai/dsh-tools'\nimport { defineTool } from '@deepseek-ai/dsh-tools'\nimport type { AgentToolName, HomeHostedStatus, RpcEndpoint, UiAction } from './shared/contracts.js'\nimport { MUTATING_AGENT_TOOLS } from './shared/contracts.js'\nimport type { HomeHostedService } from './service.js'\nimport type { SettingsStore } from './settings.js'\n\ninterface ApprovalLike {\n request: (request: { agent: unknown, toolName: string, reason?: string }) => Promise<string>\n}\n\ninterface SandboxPolicyLike {\n resolve?: (input: { session?: unknown }) => { mode?: string } | undefined\n}\n\n/** The calling session's file-sandbox mode, or null when nothing can report it. */\nfunction sandboxMode(ctx: Context, exec: unknown): string | null {\n const policy = ctx.get('sandboxPolicy') as SandboxPolicyLike | undefined\n if (policy?.resolve === undefined)\n return null\n const session = (exec as { agent?: { session?: unknown } } | undefined)?.agent?.session\n try {\n return policy.resolve({ ...(session === undefined ? {} : { session }) })?.mode ?? null\n }\n catch {\n return null\n }\n}\n\ntype Input = Record<string, unknown>\n\nfunction stringArg(input: Input, key: string): string | null {\n const value = input[key]\n return typeof value === 'string' && value.trim().length > 0 ? value.trim() : null\n}\n\nfunction jsonArg(input: Input, key: string): Record<string, unknown> | null {\n const value = input[key]\n return typeof value === 'object' && value !== null && !Array.isArray(value) ? value as Record<string, unknown> : null\n}\n\ninterface ToolSpec {\n description: string\n parameters: ParameterSchemaSpec\n /** The endpoint call this tool performs, after its own argument handling. */\n run: (input: Input) => { endpoint: RpcEndpoint, payload: unknown }\n}\n\nconst TOOL_SPECS: Record<AgentToolName, ToolSpec> = {\n status: {\n description: 'Report the home-hosted panel state, its boot-autostart entry, and the entries this plugin manages.',\n parameters: {},\n run: () => ({ endpoint: 'status', payload: {} }),\n },\n servers_list: {\n description: 'List every server home-hosted supervises, with status, pid and url.',\n parameters: {},\n run: () => ({ endpoint: 'servers.list', payload: {} }),\n },\n servers_lifecycle: {\n description: 'Start, stop or restart a server supervised by home-hosted. Restarting the entry this session runs as ends the session.',\n parameters: {\n action: { type: 'string', required: true, description: 'start, stop or restart' },\n id: { type: 'string', required: true, description: 'Server entry id' },\n },\n run: (input) => {\n const action = stringArg(input, 'action')\n if (action !== 'start' && action !== 'stop' && action !== 'restart')\n throw new Error('action must be start, stop or restart')\n const id = stringArg(input, 'id')\n if (id === null)\n throw new Error('id is required')\n return { endpoint: `servers.${action}` as RpcEndpoint, payload: { id } }\n },\n },\n servers_edit: {\n description: 'Create, update or delete a home-hosted server entry. Delete is refused for the entry this session runs as.',\n parameters: {\n action: { type: 'string', required: true, description: 'create, update or delete' },\n id: { type: 'string', description: 'Server entry id (update, delete)' },\n entry: { type: 'json', description: 'A full home-hosted server entry, including its id and command (create)' },\n patch: { type: 'json', description: 'Fields to change (update)' },\n },\n run: (input) => {\n const action = stringArg(input, 'action')\n if (action === 'create') {\n const entry = jsonArg(input, 'entry')\n if (entry === null)\n throw new Error('entry is required to create a server')\n return { endpoint: 'servers.create', payload: { entry } }\n }\n if (action === 'update') {\n const id = stringArg(input, 'id')\n const patch = jsonArg(input, 'patch')\n if (id === null || patch === null)\n throw new Error('id and patch are required to update a server')\n return { endpoint: 'servers.update', payload: { id, patch } }\n }\n if (action === 'delete') {\n const id = stringArg(input, 'id')\n if (id === null)\n throw new Error('id is required to delete a server')\n return { endpoint: 'servers.delete', payload: { id } }\n }\n throw new Error('action must be create, update or delete')\n },\n },\n autostart_manage: {\n description: 'Install or remove the OS entry that starts home-hosted at boot or login.',\n parameters: {\n action: { type: 'string', required: true, description: 'install or uninstall' },\n mechanism: { type: 'string', description: 'Explicit mechanism, e.g. launchd-daemon or systemd-system; omit to use the plugin setting' },\n },\n run: (input) => {\n const action = stringArg(input, 'action')\n if (action !== 'install' && action !== 'uninstall')\n throw new Error('action must be install or uninstall')\n const mechanism = stringArg(input, 'mechanism')\n return { endpoint: `boot.${action}` as RpcEndpoint, payload: mechanism === null ? {} : { mechanism } }\n },\n },\n ui_manage: {\n description: 'Inspect or change the home-hosted panel\\'s own web UI: status, update, revert to stock, or switch to a local zip.',\n parameters: {\n action: { type: 'string', required: true, description: 'status, update, revert or switch' },\n file: { type: 'string', description: 'Absolute path to a UI zip (switch)' },\n },\n run: (input) => {\n const action = stringArg(input, 'action')\n if (action !== 'status' && action !== 'update' && action !== 'revert' && action !== 'switch')\n throw new Error('action must be status, update, revert or switch')\n const file = stringArg(input, 'file')\n return { endpoint: 'ui.manage', payload: { action: action as UiAction, ...(file === null ? {} : { file }) } }\n },\n },\n}\n\nexport function toolNameFor(name: AgentToolName): string {\n return `home_hosted_${name}`\n}\n\n/**\n * Actions of an otherwise mutating tool that only read. `ui_manage` carries both,\n * and a status call must not be blocked (or prompted for) as if it changed the UI.\n */\nconst READ_ONLY_ACTIONS: Partial<Record<AgentToolName, (input: Input) => boolean>> = {\n ui_manage: input => stringArg(input, 'action') === 'status',\n}\n\n/** Error codes that mean the panel refused the plugin's credential. */\nconst TOKEN_REFUSAL_CODES = new Set([\n 'AUTH_REQUIRED',\n 'AUTH_UNARMED',\n 'UNAUTHORIZED',\n 'FORBIDDEN',\n 'INVALID_TOKEN',\n 'TOKEN_STALE',\n 'TOKEN_REFUSED',\n])\n\nfunction errorCode(error: unknown): string | null {\n const code = (error as { code?: unknown } | null | undefined)?.code\n return typeof code === 'string' ? code : null\n}\n\nfunction errorStatus(error: unknown): number | null {\n const status = (error as { status?: unknown } | null | undefined)?.status\n return typeof status === 'number' ? status : null\n}\n\n/** A panel answer that refused the token, as opposed to a bad request or a 404. */\nfunction refusedByPanel(error: unknown): boolean {\n const status = errorStatus(error)\n if (status === 401 || status === 403)\n return true\n const code = errorCode(error)\n return code !== null && TOKEN_REFUSAL_CODES.has(code)\n}\n\n/**\n * Whether a failed call failed because the panel refused this plugin's token.\n *\n * A 401/403 or an auth code is that refusal directly. A client that could not be\n * established at all is ambiguous \u2014 the panel may simply be down \u2014 so the\n * panel's measured token state is asked instead; only `stale`, which the panel\n * sets from an actual refusal, justifies a repair.\n */\nasync function tokenRefused(service: Pick<HomeHostedService, 'call'>, error: unknown): Promise<boolean> {\n if (refusedByPanel(error))\n return true\n if (errorCode(error) !== 'PANEL_UNAVAILABLE')\n return false\n try {\n const status = await service.call('status', {}) as HomeHostedStatus | null\n return status?.panel.token === 'stale'\n }\n catch {\n return false\n }\n}\n\nfunction messageOf(error: unknown): string {\n return error instanceof Error ? error.message : String(error)\n}\n\nfunction failureText(error: unknown): string {\n return `failed: ${messageOf(error)}`\n}\n\nfunction registerOne(ctx: Context, service: HomeHostedService, settings: SettingsStore, name: AgentToolName): () => void {\n const spec = TOOL_SPECS[name]\n const toolName = toolNameFor(name)\n const mutatingTool = MUTATING_AGENT_TOOLS.includes(name)\n\n return ctx.tools.register(defineTool({\n name: toolName,\n description: spec.description,\n parameters: spec.parameters,\n output: {\n schema: { type: 'string' },\n render: (_args, value) => [{ type: 'text', text: value }],\n },\n async execute(args, exec) {\n const input = (args ?? {}) as Input\n const mode = sandboxMode(ctx, exec)\n // Fail closed: only a positively identified read-only action skips the gate,\n // and an unknown action still asks.\n const mutating = mutatingTool && !(READ_ONLY_ACTIONS[name]?.(input) ?? false)\n if (mutating && mode !== 'danger-full-access') {\n const remedy = 'Set the session to Full access (danger-full-access), or use a session where approvals can be answered.'\n const approval = ctx.get('approval') as ApprovalLike | undefined\n if (approval?.request === undefined)\n return `refused: this session runs in ${mode ?? 'an unknown'} sandbox and the deployment has no approval service. ${remedy}`\n const outcome = await approval.request({\n agent: (exec as { agent?: unknown } | undefined)?.agent,\n toolName,\n reason: `${spec.description} (${JSON.stringify(input)})`,\n })\n if (outcome !== 'allowed-once')\n return `refused: approval answered \"${outcome}\" (session sandbox: ${mode ?? 'unknown'}). ${remedy}`\n }\n\n // Argument handling is not a panel call: a bad input is reported as-is,\n // never \"repaired\" by minting a token.\n let request: { endpoint: RpcEndpoint, payload: unknown }\n try {\n request = spec.run(input)\n }\n catch (error) {\n return failureText(error)\n }\n\n try {\n return JSON.stringify(await service.call(request.endpoint, request.payload), null, 2)\n }\n catch (error) {\n if (!settings.get().reclaimToken || !(await tokenRefused(service, error)))\n return failureText(error)\n\n // One repair, one retry. The reclaim is a write, but it repairs this\n // plugin's own credential, not the panel's state, so it runs behind the\n // call's existing approval gate rather than asking for a second one.\n try {\n await service.call('panel.reclaimToken', {})\n }\n catch (reclaimError) {\n return `${failureText(error)} (token reclaim failed: ${messageOf(reclaimError)})`\n }\n try {\n return JSON.stringify(await service.call(request.endpoint, request.payload), null, 2)\n }\n catch (retryError) {\n return failureText(retryError)\n }\n }\n },\n }))\n}\n\nexport function registerAgentTools(ctx: Context, service: HomeHostedService, settings: SettingsStore): void {\n ctx.inject(['tools'], (scoped) => {\n const disposers: Array<() => void> = []\n\n const sync = (): void => {\n while (disposers.length > 0)\n disposers.pop()?.()\n const current = settings.get()\n if (!current.agentTools.enabled)\n return\n for (const name of current.agentTools.allow) {\n try {\n disposers.push(registerOne(scoped, service, settings, name))\n }\n catch {\n // one unruly tool must not keep the rest of the allowlist off the model\n }\n }\n }\n\n scoped.effect(() => {\n sync()\n const off = settings.onChange(sync)\n return () => {\n off()\n while (disposers.length > 0)\n disposers.pop()?.()\n }\n }, 'dsh-home-hosted: agent tools')\n })\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["path", "fs", "path", "process", "os", "process", "fs", "path", "process", "process", "fs", "path", "fs", "name", "name", "run", "fs", "fs", "path", "validate", "path", "codeOf", "problem", "run", "fs", "fs", "path", "validate", "fs", "path", "fs", "path", "validate", "codeOf", "problem", "run", "name", "path", "fs", "payload", "process", "os", "candidate", "status", "provider", "fs", "os", "path", "fs", "fs", "path", "process", "fs", "path", "process", "process", "fs", "path", "process", "fs", "fs", "path", "process", "fs", "path", "version", "supported", "process", "fs", "path", "process", "path", "fs", "process", "path", "fs", "name", "path", "fs", "process", "dshHome", "name", "launcherPath", "spawn", "fs", "path", "process", "path", "process", "fs", "spawn", "path", "answer", "process", "process", "path", "path", "runCli", "path", "dshHome", "process", "entry", "fs", "cliArgs", "name", "name", "path"]
7
7
  }