@hermespilot/link 0.1.9 → 0.2.0

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.
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/cli/index.ts","../../src/autostart/autostart.ts","../../src/daemon/process.ts","../../src/daemon/service.ts","../../src/relay/control-client.ts","../../src/i18n.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { Command } from 'commander'\nimport qrcode from 'qrcode-terminal'\nimport { LINK_COMMAND, LINK_VERSION } from '../constants.js'\nimport { enableAutostart, disableAutostart, getAutostartStatus } from '../autostart/autostart.js'\nimport { loadConfig } from '../config/config.js'\nimport {\n getDaemonStatus,\n startDaemonProcess,\n stopDaemonProcess,\n daemonLogFile,\n probeLocalLinkService,\n} from '../daemon/process.js'\nimport { startLinkService, type LinkService } from '../daemon/service.js'\nimport { ensureHermesApiServerConfig } from '../hermes/config.js'\nimport { ensureHermesApiServerAvailable } from '../hermes/gateway.js'\nimport { ensureIdentity, getIdentityStatus, loadIdentity } from '../identity/identity.js'\nimport { detectSystemLanguage, localizeErrorMessage, resolveLanguage, translate } from '../i18n.js'\nimport { clearPairingClaim, preparePairing, readPairingClaim } from '../pairing/pairing.js'\nimport { getLinkLogFile } from '../runtime/logger.js'\nimport { resolveRuntimePaths, type RuntimePaths } from '../runtime/paths.js'\n\nconst program = new Command()\nconst helpLanguage = detectSystemLanguage()\nconst helpText = translate.bind(null, helpLanguage)\n\nprogram\n .name(LINK_COMMAND)\n .description(helpText('program.description'))\n .version(LINK_VERSION, '-v, --version', helpText('program.version'))\n\nprogram\n .command('status')\n .option('--json', helpText('status.json'))\n .description(helpText('status.description'))\n .action(async (options: { json?: boolean }) => {\n const paths = resolveRuntimePaths()\n const [identity, config] = await Promise.all([loadIdentity(paths), loadConfig(paths)])\n const language = resolveLanguage(config.language)\n const t = translate.bind(null, language)\n const payload = {\n version: LINK_VERSION,\n runtimeHome: paths.homeDir,\n paired: Boolean(identity?.link_id),\n mode: identity?.link_id ? 'paired' : 'local-only',\n port: config.port,\n identity: identity ? getIdentityStatus(identity) : null,\n relay: {\n configured: Boolean(config.relayBaseUrl),\n connected: false,\n },\n }\n if (options.json) {\n console.log(JSON.stringify(payload, null, 2))\n return\n }\n console.log(`Hermes Link ${payload.version}`)\n console.log(t('status.runtime', { value: payload.runtimeHome }))\n console.log(t('status.mode', { value: payload.mode }))\n console.log(t('status.port', { value: payload.port }))\n console.log(t('status.linkId', { value: payload.identity?.linkId ?? t('status.notPaired') }))\n })\n\nprogram\n .command('start')\n .description(helpText('start.description'))\n .action(async () => {\n const [config, status] = await Promise.all([loadConfig(), getDaemonStatus()])\n const language = resolveLanguage(config.language)\n const t = translate.bind(null, language)\n if (status.running && status.pid) {\n console.log(t('start.alreadyRunning', { pid: status.pid }))\n return\n }\n const nextStatus = await startDaemonProcess()\n console.log(t('start.backgroundStarted', { pid: nextStatus.pid ?? 'unknown' }))\n })\n\nprogram\n .command('stop')\n .description(helpText('stop.description'))\n .action(async () => {\n const config = await loadConfig()\n const language = resolveLanguage(config.language)\n const t = translate.bind(null, language)\n const before = await getDaemonStatus()\n if (!before.running) {\n console.log(t('stop.notRunning'))\n return\n }\n await stopDaemonProcess()\n console.log(t('stop.stopped'))\n })\n\nprogram\n .command('restart')\n .description(helpText('restart.description'))\n .action(async () => {\n const config = await loadConfig()\n const language = resolveLanguage(config.language)\n const t = translate.bind(null, language)\n await stopDaemonProcess()\n const status = await startDaemonProcess()\n console.log(t('start.backgroundStarted', { pid: status.pid ?? 'unknown' }))\n })\n\nprogram\n .command('daemon')\n .option('--foreground', 'run in foreground')\n .description(helpText('daemon.description'))\n .action(async () => {\n const config = await loadConfig()\n const language = resolveLanguage(config.language)\n const t = translate.bind(null, language)\n const service = await startLinkService({ writePidFile: true })\n console.log(t('daemon.foreground'))\n await waitForShutdown(async () => {\n await service.close()\n })\n })\n\nprogram\n .command('pair')\n .description(helpText('pair.description'))\n .action(async () => {\n const paths = resolveRuntimePaths()\n const config = await loadConfig(paths)\n const language = resolveLanguage(config.language)\n const t = translate.bind(null, language)\n console.log(t('pair.preparing'))\n console.log(t('pair.server', { url: config.serverBaseUrl }))\n console.log(t('pair.relay', { url: config.relayBaseUrl }))\n await ensureIdentity(paths)\n const probeBeforePair = await probeLocalLinkService({ port: config.port })\n const prepared = await preparePairing(paths)\n await clearPairingClaim(prepared.sessionId, paths)\n const probe = await probeLocalLinkService({ port: config.port, linkId: prepared.linkId })\n if (probe.reachable && !probe.reusable) {\n throw new Error(\n `Local Hermes Link on port ${config.port} belongs to ${probe.linkId ?? 'an unassigned Link'}, not ${prepared.linkId}.`,\n )\n }\n const reusedRunningService = probe.reusable\n const restartReusedServiceAfterClaim = reusedRunningService && !probeBeforePair.linkId\n const service: LinkService | null = reusedRunningService ? null : await startLinkService({ paths })\n const qrValue = JSON.stringify(prepared.qrPayload)\n console.log(t('pair.linkId', { value: prepared.linkId }))\n console.log(t('pair.code', { value: prepared.code }))\n console.log(t('pair.localApi', { port: config.port }))\n console.log(t('pair.scan'))\n qrcode.generate(qrValue, { small: true })\n console.log(t('pair.expires'))\n const result = await waitForPairingOrShutdown(prepared.sessionId, paths)\n if (service) {\n await service.close()\n }\n if (result === 'claimed') {\n await clearPairingClaim(prepared.sessionId, paths)\n console.log(t(reusedRunningService ? 'pair.claimedRunning' : 'pair.claimed'))\n try {\n const autostart = await enableAutostart()\n if (autostart.supported && autostart.enabled) {\n console.log(t('autostart.enabled', { method: autostart.method, path: autostart.filePath ?? '' }))\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n console.log(t('pair.autostartFailed', { message }))\n }\n if (restartReusedServiceAfterClaim) {\n await stopDaemonProcess(paths)\n const status = await startDaemonProcess(paths)\n console.log(t('start.backgroundStarted', { pid: status.pid ?? 'unknown' }))\n } else if (!reusedRunningService) {\n const status = await startDaemonProcess(paths)\n console.log(t('start.backgroundStarted', { pid: status.pid ?? 'unknown' }))\n }\n }\n })\n\nconst autostart = program.command('autostart').description(helpText('autostart.description'))\n\nautostart\n .command('on')\n .description(helpText('autostart.on.description'))\n .action(async () => {\n const config = await loadConfig()\n const language = resolveLanguage(config.language)\n const t = translate.bind(null, language)\n const status = await enableAutostart()\n if (!status.supported) {\n console.log(t('autostart.unsupported'))\n return\n }\n console.log(t('autostart.enabled', { method: status.method, path: status.filePath ?? '' }))\n })\n\nautostart\n .command('off')\n .description(helpText('autostart.off.description'))\n .action(async () => {\n const config = await loadConfig()\n const language = resolveLanguage(config.language)\n const t = translate.bind(null, language)\n await disableAutostart()\n console.log(t('autostart.disabled'))\n })\n\nautostart\n .command('status')\n .description(helpText('autostart.status.description'))\n .action(async () => {\n const config = await loadConfig()\n const language = resolveLanguage(config.language)\n const t = translate.bind(null, language)\n const status = await getAutostartStatus()\n if (!status.supported) {\n console.log(t('autostart.unsupported'))\n return\n }\n console.log(\n t(status.enabled ? 'autostart.status.enabled' : 'autostart.status.disabled', {\n method: status.method,\n path: status.filePath ?? '',\n }),\n )\n })\n\nprogram\n .command('logs')\n .description(helpText('logs.description'))\n .action(async () => {\n const paths = resolveRuntimePaths()\n const config = await loadConfig(paths)\n const language = resolveLanguage(config.language)\n const t = translate.bind(null, language)\n console.log(t('logs.servicePath', { path: getLinkLogFile(paths) }))\n console.log(t('logs.daemonPath', { path: daemonLogFile(paths) }))\n })\n\nprogram\n .command('doctor')\n .description(helpText('doctor.description'))\n .action(async () => {\n const [identity, config] = await Promise.all([ensureIdentity(), loadConfig()])\n const language = resolveLanguage(config.language)\n const t = translate.bind(null, language)\n const hermesConfig = await ensureHermesApiServerConfig()\n console.log(t('doctor.identityOk'))\n console.log(t('doctor.installId', { value: identity.install_id }))\n console.log(t('doctor.linkId', { value: identity.link_id ?? t('doctor.notAssigned') }))\n if (hermesConfig.notice) {\n console.log(hermesConfig.notice)\n if (hermesConfig.backupPath) {\n console.log(`Hermes config backup: ${hermesConfig.backupPath}`)\n }\n }\n try {\n const availability = await ensureHermesApiServerAvailable({ timeoutMs: 5_000 })\n console.log(t(availability.started ? 'doctor.apiStarted' : 'doctor.apiReady'))\n } catch (error) {\n console.log(t('doctor.apiUnavailable', { message: error instanceof Error ? error.message : String(error) }))\n }\n })\n\nprogram.parseAsync(process.argv).catch(async (error) => {\n const language = await loadCliLanguage().catch(() => detectSystemLanguage())\n console.error(localizeErrorMessage(error, language))\n process.exitCode = 1\n})\n\nasync function loadCliLanguage() {\n const config = await loadConfig()\n return resolveLanguage(config.language)\n}\n\nasync function waitForShutdown(cleanup: () => Promise<void>): Promise<void> {\n await new Promise<void>((resolve) => {\n const stop = () => resolve()\n process.once('SIGINT', stop)\n process.once('SIGTERM', stop)\n })\n await cleanup()\n}\n\nasync function waitForPairingOrShutdown(\n sessionId: string,\n paths: RuntimePaths,\n): Promise<'claimed' | 'shutdown'> {\n let shutdownRequested = false\n const stop = () => {\n shutdownRequested = true\n }\n process.once('SIGINT', stop)\n process.once('SIGTERM', stop)\n try {\n while (!shutdownRequested) {\n const record = await readPairingClaim(sessionId, paths)\n if (record) {\n return 'claimed'\n }\n await sleep(250)\n }\n return 'shutdown'\n } finally {\n process.off('SIGINT', stop)\n process.off('SIGTERM', stop)\n }\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms))\n}\n","import { execFile } from 'node:child_process'\nimport { mkdir, readFile, rm, writeFile } from 'node:fs/promises'\nimport os from 'node:os'\nimport path from 'node:path'\nimport { promisify } from 'node:util'\nimport { currentCliScriptPath } from '../daemon/process.js'\n\nconst execFileAsync = promisify(execFile)\nconst MACOS_LABEL = 'com.hermespilot.link'\n\nexport interface AutostartStatus {\n supported: boolean\n enabled: boolean\n method: 'launchd' | 'systemd-user' | 'xdg-autostart' | 'windows-startup' | 'unsupported'\n filePath: string | null\n}\n\nexport async function enableAutostart(): Promise<AutostartStatus> {\n const definition = await resolveAutostartDefinition()\n if (!definition) {\n return unsupportedStatus()\n }\n await mkdir(path.dirname(definition.filePath), { recursive: true, mode: 0o700 })\n await writeFile(definition.filePath, definition.content, { mode: 0o600 })\n if (definition.method === 'systemd-user') {\n await execFileAsync('systemctl', ['--user', 'enable', path.basename(definition.filePath)]).catch(async () => {\n await rm(definition.filePath, { force: true }).catch(() => undefined)\n const fallback = xdgAutostartDefinition()\n await mkdir(path.dirname(fallback.filePath), { recursive: true, mode: 0o700 })\n await writeFile(fallback.filePath, fallback.content, { mode: 0o600 })\n })\n }\n return await getAutostartStatus()\n}\n\nexport async function disableAutostart(): Promise<AutostartStatus> {\n const definitions = await allAutostartDefinitions()\n for (const definition of definitions) {\n if (definition.method === 'systemd-user') {\n await execFileAsync('systemctl', ['--user', 'disable', path.basename(definition.filePath)]).catch(() => undefined)\n }\n await rm(definition.filePath, { force: true }).catch(() => undefined)\n }\n return await getAutostartStatus()\n}\n\nexport async function getAutostartStatus(): Promise<AutostartStatus> {\n const definitions = await allAutostartDefinitions()\n if (definitions.length === 0) {\n return unsupportedStatus()\n }\n for (const definition of definitions) {\n const content = await readFile(definition.filePath, 'utf8').catch(() => null)\n if (content !== null) {\n return {\n supported: true,\n enabled: true,\n method: definition.method,\n filePath: definition.filePath,\n }\n }\n }\n const primary = definitions[0]\n return {\n supported: true,\n enabled: false,\n method: primary.method,\n filePath: primary.filePath,\n }\n}\n\nasync function resolveAutostartDefinition(): Promise<AutostartDefinition | null> {\n if (process.platform === 'darwin') {\n return launchdDefinition()\n }\n if (process.platform === 'win32') {\n return windowsStartupDefinition()\n }\n if (process.platform === 'linux') {\n return await hasSystemctlUser() ? systemdUserDefinition() : xdgAutostartDefinition()\n }\n return null\n}\n\nasync function allAutostartDefinitions(): Promise<AutostartDefinition[]> {\n if (process.platform === 'darwin') {\n return [launchdDefinition()]\n }\n if (process.platform === 'win32') {\n return [windowsStartupDefinition()]\n }\n if (process.platform === 'linux') {\n return [systemdUserDefinition(), xdgAutostartDefinition()]\n }\n return []\n}\n\nasync function hasSystemctlUser(): Promise<boolean> {\n try {\n await execFileAsync('systemctl', ['--user', 'show-environment'])\n return true\n } catch {\n return false\n }\n}\n\nfunction launchdDefinition(): AutostartDefinition {\n const filePath = path.join(os.homedir(), 'Library', 'LaunchAgents', `${MACOS_LABEL}.plist`)\n return {\n method: 'launchd',\n filePath,\n content: `<?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 <key>Label</key>\n <string>${MACOS_LABEL}</string>\n <key>ProgramArguments</key>\n <array>\n <string>${xmlEscape(process.execPath)}</string>\n <string>${xmlEscape(currentCliScriptPath())}</string>\n <string>daemon</string>\n <string>--foreground</string>\n </array>\n <key>RunAtLoad</key>\n <true/>\n <key>KeepAlive</key>\n <false/>\n <key>StandardOutPath</key>\n <string>${xmlEscape(path.join(os.homedir(), '.hermeslink', 'logs', 'daemon.log'))}</string>\n <key>StandardErrorPath</key>\n <string>${xmlEscape(path.join(os.homedir(), '.hermeslink', 'logs', 'daemon.log'))}</string>\n</dict>\n</plist>\n`,\n }\n}\n\nfunction systemdUserDefinition(): AutostartDefinition {\n const filePath = path.join(os.homedir(), '.config', 'systemd', 'user', 'hermeslink.service')\n return {\n method: 'systemd-user',\n filePath,\n content: `[Unit]\nDescription=Hermes Link\nAfter=network-online.target\n\n[Service]\nType=simple\nExecStart=${systemdQuote(process.execPath)} ${systemdQuote(currentCliScriptPath())} daemon --foreground\nRestart=no\n\n[Install]\nWantedBy=default.target\n`,\n }\n}\n\nfunction xdgAutostartDefinition(): AutostartDefinition {\n const filePath = path.join(os.homedir(), '.config', 'autostart', 'hermeslink.desktop')\n return {\n method: 'xdg-autostart',\n filePath,\n content: `[Desktop Entry]\nType=Application\nName=Hermes Link\nExec=${desktopQuote(process.execPath)} ${desktopQuote(currentCliScriptPath())} daemon --foreground\nTerminal=false\nX-GNOME-Autostart-enabled=true\n`,\n }\n}\n\nfunction windowsStartupDefinition(): AutostartDefinition {\n const appData = process.env.APPDATA ?? path.join(os.homedir(), 'AppData', 'Roaming')\n const filePath = path.join(appData, 'Microsoft', 'Windows', 'Start Menu', 'Programs', 'Startup', 'HermesLink.cmd')\n return {\n method: 'windows-startup',\n filePath,\n content: `@echo off\\r\\nstart \"\" /min \"${process.execPath}\" \"${currentCliScriptPath()}\" daemon --foreground\\r\\n`,\n }\n}\n\nfunction unsupportedStatus(): AutostartStatus {\n return {\n supported: false,\n enabled: false,\n method: 'unsupported',\n filePath: null,\n }\n}\n\nfunction xmlEscape(value: string): string {\n return value\n .replaceAll('&', '&amp;')\n .replaceAll('<', '&lt;')\n .replaceAll('>', '&gt;')\n .replaceAll('\"', '&quot;')\n .replaceAll(\"'\", '&apos;')\n}\n\nfunction systemdQuote(value: string): string {\n return `\"${value.replaceAll('\\\\', '\\\\\\\\').replaceAll('\"', '\\\\\"')}\"`\n}\n\nfunction desktopQuote(value: string): string {\n return `\"${value.replaceAll('\\\\', '\\\\\\\\').replaceAll('\"', '\\\\\"')}\"`\n}\n\ninterface AutostartDefinition {\n method: AutostartStatus['method']\n filePath: string\n content: string\n}\n","import { spawn } from 'node:child_process'\nimport { mkdir, open, readFile, rm } from 'node:fs/promises'\nimport path from 'node:path'\nimport { pidFilePath } from './service.js'\nimport { resolveRuntimePaths, type RuntimePaths } from '../runtime/paths.js'\n\nexport interface DaemonStatus {\n running: boolean\n pid: number | null\n pidFile: string\n logFile: string\n}\n\nexport interface LocalLinkServiceProbe {\n reachable: boolean\n reusable: boolean\n linkId: string | null\n version: string | null\n}\n\nexport async function startDaemonProcess(paths: RuntimePaths = resolveRuntimePaths()): Promise<DaemonStatus> {\n const status = await getDaemonStatus(paths)\n if (status.running) {\n return status\n }\n await mkdir(paths.logsDir, { recursive: true, mode: 0o700 })\n await mkdir(paths.runDir, { recursive: true, mode: 0o700 })\n const log = await open(daemonLogFile(paths), 'a', 0o600)\n const scriptPath = currentCliScriptPath()\n const child = spawn(process.execPath, [scriptPath, 'daemon', '--foreground'], {\n detached: true,\n stdio: ['ignore', log.fd, log.fd],\n env: process.env,\n })\n child.unref()\n await log.close()\n for (let index = 0; index < 12; index += 1) {\n await wait(250)\n const next = await getDaemonStatus(paths)\n if (next.running) {\n return next\n }\n }\n return await getDaemonStatus(paths)\n}\n\nexport async function probeLocalLinkService(options: {\n port: number\n linkId?: string\n timeoutMs?: number\n}): Promise<LocalLinkServiceProbe> {\n const unreachable: LocalLinkServiceProbe = {\n reachable: false,\n reusable: false,\n linkId: null,\n version: null,\n }\n let response: Response\n try {\n response = await fetch(`http://127.0.0.1:${options.port}/api/v1/bootstrap`, {\n headers: { accept: 'application/json' },\n signal: AbortSignal.timeout(options.timeoutMs ?? 1_000),\n })\n } catch {\n return unreachable\n }\n if (!response.ok) {\n return unreachable\n }\n const payload = (await response.json().catch(() => null)) as Record<string, unknown> | null\n if (!payload || payload.api_version !== 1) {\n return unreachable\n }\n const linkId = typeof payload.link_id === 'string' ? payload.link_id : null\n return {\n reachable: true,\n reusable: options.linkId ? linkId === options.linkId : true,\n linkId,\n version: typeof payload.version === 'string' ? payload.version : null,\n }\n}\n\nexport async function stopDaemonProcess(paths: RuntimePaths = resolveRuntimePaths()): Promise<DaemonStatus> {\n const status = await getDaemonStatus(paths)\n if (!status.running || !status.pid) {\n return status\n }\n try {\n process.kill(status.pid, 'SIGTERM')\n } catch {\n await rm(pidFilePath(paths), { force: true }).catch(() => undefined)\n return await getDaemonStatus(paths)\n }\n for (let index = 0; index < 20; index += 1) {\n await wait(250)\n if (!isProcessAlive(status.pid)) {\n break\n }\n }\n if (!isProcessAlive(status.pid)) {\n await rm(pidFilePath(paths), { force: true }).catch(() => undefined)\n }\n return await getDaemonStatus(paths)\n}\n\nexport async function getDaemonStatus(paths: RuntimePaths = resolveRuntimePaths()): Promise<DaemonStatus> {\n const pidFile = pidFilePath(paths)\n const pid = await readPid(pidFile)\n if (pid && !isProcessAlive(pid)) {\n await rm(pidFile, { force: true }).catch(() => undefined)\n return {\n running: false,\n pid: null,\n pidFile,\n logFile: daemonLogFile(paths),\n }\n }\n return {\n running: Boolean(pid),\n pid,\n pidFile,\n logFile: daemonLogFile(paths),\n }\n}\n\nexport function daemonLogFile(paths: RuntimePaths = resolveRuntimePaths()): string {\n return path.join(paths.logsDir, 'daemon.log')\n}\n\nexport function currentCliScriptPath(): string {\n return process.argv[1]\n}\n\nasync function readPid(filePath: string): Promise<number | null> {\n const raw = await readFile(filePath, 'utf8').catch(() => null)\n if (!raw) {\n return null\n }\n const pid = Number.parseInt(raw.trim(), 10)\n return Number.isInteger(pid) && pid > 0 ? pid : null\n}\n\nfunction isProcessAlive(pid: number): boolean {\n try {\n process.kill(pid, 0)\n return true\n } catch {\n return false\n }\n}\n\nfunction wait(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms))\n}\n","import { createServer, type Server } from 'node:http'\nimport { mkdir, rm, writeFile } from 'node:fs/promises'\nimport { createApp, type CreateAppOptions } from '../http/app.js'\nimport { loadConfig } from '../config/config.js'\nimport { loadIdentity } from '../identity/identity.js'\nimport { connectRelayControl, type RelayControlClient } from '../relay/control-client.js'\nimport { createFileLogger } from '../runtime/logger.js'\nimport { resolveRuntimePaths, type RuntimePaths } from '../runtime/paths.js'\n\nexport interface LinkService {\n close(): Promise<void>\n}\n\nexport interface StartLinkServiceOptions extends CreateAppOptions {\n paths?: RuntimePaths\n writePidFile?: boolean\n relayMaxReconnectAttempts?: number\n}\n\nexport async function startLinkService(options: StartLinkServiceOptions = {}): Promise<LinkService> {\n const paths = options.paths ?? resolveRuntimePaths()\n const logger = createFileLogger({ paths })\n const [identity, config] = await Promise.all([loadIdentity(paths), loadConfig(paths)])\n await logger.info('service_starting', {\n port: config.port,\n mode: identity?.link_id ? 'paired' : 'local-only',\n })\n const app = await createApp({ paths, logger, onPairingClaimed: options.onPairingClaimed })\n const server = createServer(app.callback())\n try {\n await listenServer(server, config.port)\n } catch (error) {\n await logger.error('service_start_failed', {\n port: config.port,\n error: error instanceof Error ? error.message : String(error),\n })\n await logger.flush()\n throw error\n }\n server.on('error', (error) => {\n void logger.error('service_error', { error: error.message })\n })\n void logger.info('service_started', {\n port: config.port,\n link_id: identity?.link_id ?? null,\n })\n let relay: RelayControlClient | null = null\n if (identity?.link_id) {\n relay = connectRelayControl({\n relayBaseUrl: config.relayBaseUrl,\n linkId: identity.link_id,\n localPort: config.port,\n maxReconnectAttempts: options.relayMaxReconnectAttempts ?? 5,\n backoffBaseMs: 1_000,\n backoffMaxMs: 30_000,\n onStatus: (status) => {\n void logger.info('relay_status', status)\n },\n })\n } else {\n void logger.info('relay_skipped', { reason: 'link_not_paired' })\n }\n if (options.writePidFile) {\n await writePidFile(paths)\n }\n return {\n async close() {\n relay?.close()\n await closeServer(server)\n await logger.info('service_stopped')\n await logger.flush()\n if (options.writePidFile) {\n await rm(pidFilePath(paths), { force: true }).catch(() => undefined)\n }\n },\n }\n}\n\nexport function pidFilePath(paths: RuntimePaths = resolveRuntimePaths()): string {\n return `${paths.runDir}/hermeslink.pid`\n}\n\nasync function writePidFile(paths: RuntimePaths): Promise<void> {\n await mkdir(paths.runDir, { recursive: true, mode: 0o700 })\n await writeFile(pidFilePath(paths), `${process.pid}\\n`, { mode: 0o600 })\n}\n\nasync function closeServer(server: Server): Promise<void> {\n await new Promise<void>((resolve, reject) => {\n server.close((error) => {\n if (error) {\n reject(error)\n return\n }\n resolve()\n })\n })\n}\n\nasync function listenServer(server: Server, port: number): Promise<void> {\n await new Promise<void>((resolve, reject) => {\n const cleanup = () => {\n server.off('error', onError)\n server.off('listening', onListening)\n }\n const onError = (error: Error) => {\n cleanup()\n reject(error)\n }\n const onListening = () => {\n cleanup()\n resolve()\n }\n\n server.once('error', onError)\n server.once('listening', onListening)\n server.listen(port)\n })\n}\n","import WebSocket from 'ws'\nimport { LINK_VERSION } from '../constants.js'\n\ninterface RelayRequestFrame {\n type: 'http.request'\n id: string\n method: string\n path: string\n headers?: Record<string, string>\n bodyBase64?: string | null\n}\n\ninterface RelayCancelFrame {\n type: 'http.cancel'\n id: string\n}\n\ntype RelayFrame = RelayRequestFrame | RelayCancelFrame\n\nexport interface RelayControlClient {\n close(): void\n}\n\nexport function connectRelayControl(options: {\n relayBaseUrl: string\n linkId: string\n localPort: number\n maxReconnectAttempts?: number\n backoffBaseMs?: number\n backoffMaxMs?: number\n onStatus?: (status: { state: 'connecting' | 'connected' | 'disconnected' | 'retrying' | 'failed'; attempt: number; message?: string }) => void\n}): RelayControlClient {\n const wsUrl = new URL(`${options.relayBaseUrl.replace(/\\/+$/u, '')}/api/v1/relay/link/connect`)\n wsUrl.protocol = wsUrl.protocol === 'https:' ? 'wss:' : 'ws:'\n wsUrl.searchParams.set('link_id', options.linkId)\n\n const maxReconnectAttempts = options.maxReconnectAttempts ?? 5\n const backoffBaseMs = options.backoffBaseMs ?? 1_000\n const backoffMaxMs = options.backoffMaxMs ?? 30_000\n let reconnectAttempts = 0\n let closedByUser = false\n let socket: WebSocket | null = null\n let retryTimer: ReturnType<typeof setTimeout> | null = null\n let abortControllers = new Map<string, AbortController>()\n\n const connect = () => {\n options.onStatus?.({ state: 'connecting', attempt: reconnectAttempts })\n socket = new WebSocket(wsUrl, {\n headers: {\n 'x-hermes-link-version': LINK_VERSION,\n },\n })\n socket.on('open', () => {\n reconnectAttempts = 0\n options.onStatus?.({ state: 'connected', attempt: reconnectAttempts })\n })\n socket.on('message', (raw) => {\n if (!socket || (typeof raw !== 'string' && !Buffer.isBuffer(raw))) {\n return\n }\n void handleFrame(socket, String(raw), options.localPort, abortControllers).catch((error) => {\n const message = error instanceof Error ? error.message : 'Relay request failed'\n socket?.send(JSON.stringify({ type: 'http.error', id: 'unknown', status: 502, message }))\n })\n })\n socket.on('error', (error) => {\n const message = error instanceof Error ? error.message : 'Relay websocket error'\n options.onStatus?.({ state: 'disconnected', attempt: reconnectAttempts, message })\n })\n socket.on('close', () => {\n abortAll(abortControllers)\n abortControllers = new Map<string, AbortController>()\n if (closedByUser) {\n options.onStatus?.({ state: 'disconnected', attempt: reconnectAttempts })\n return\n }\n if (reconnectAttempts >= maxReconnectAttempts) {\n options.onStatus?.({ state: 'failed', attempt: reconnectAttempts, message: 'Relay reconnect attempts exhausted' })\n return\n }\n reconnectAttempts += 1\n const delay = computeBackoffMs(reconnectAttempts, backoffBaseMs, backoffMaxMs)\n options.onStatus?.({ state: 'retrying', attempt: reconnectAttempts, message: `Retrying in ${delay}ms` })\n retryTimer = setTimeout(connect, delay)\n retryTimer.unref?.()\n })\n }\n\n connect()\n\n return {\n close() {\n closedByUser = true\n if (retryTimer) {\n clearTimeout(retryTimer)\n }\n abortAll(abortControllers)\n socket?.close()\n },\n }\n}\n\nfunction abortAll(abortControllers: Map<string, AbortController>): void {\n for (const controller of abortControllers.values()) {\n controller.abort()\n }\n abortControllers.clear()\n}\n\nfunction computeBackoffMs(attempt: number, baseMs: number, maxMs: number): number {\n const exponential = Math.min(maxMs, baseMs * 2 ** Math.max(0, attempt - 1))\n const jitter = Math.floor(Math.random() * Math.min(1_000, exponential * 0.2))\n return exponential + jitter\n}\n\nasync function handleFrame(\n socket: WebSocket,\n raw: string,\n localPort: number,\n abortControllers: Map<string, AbortController>,\n): Promise<void> {\n const frame = JSON.parse(raw) as RelayFrame\n if (frame.type === 'http.cancel') {\n abortControllers.get(frame.id)?.abort()\n abortControllers.delete(frame.id)\n return\n }\n if (frame.type !== 'http.request') {\n return\n }\n const abortController = new AbortController()\n abortControllers.set(frame.id, abortController)\n try {\n const response = await fetch(`http://127.0.0.1:${localPort}${frame.path}`, {\n method: frame.method,\n headers: frame.headers ?? {},\n body: frame.bodyBase64 ? Buffer.from(frame.bodyBase64, 'base64') : undefined,\n signal: abortController.signal,\n })\n const headers = Object.fromEntries(response.headers.entries())\n const contentType = response.headers.get('content-type') ?? ''\n if (response.body && contentType.includes('text/event-stream')) {\n socket.send(JSON.stringify({ type: 'http.stream.start', id: frame.id, status: response.status, headers }))\n const reader = response.body.getReader()\n while (true) {\n const next = await reader.read()\n if (next.done) {\n break\n }\n socket.send(JSON.stringify({ type: 'http.stream.chunk', id: frame.id, bodyBase64: Buffer.from(next.value).toString('base64') }))\n }\n socket.send(JSON.stringify({ type: 'http.stream.end', id: frame.id }))\n return\n }\n const body = Buffer.from(await response.arrayBuffer()).toString('base64')\n socket.send(JSON.stringify({ type: 'http.response', id: frame.id, status: response.status, headers, bodyBase64: body }))\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Relay request failed'\n socket.send(JSON.stringify({ type: 'http.error', id: frame.id, status: 502, message }))\n } finally {\n abortControllers.delete(frame.id)\n }\n}\n","export type SupportedLanguage = 'zh-CN' | 'en'\nexport type ConfiguredLanguage = SupportedLanguage | 'auto'\n\nconst messages = {\n en: {\n 'program.description': 'Hermes Link companion service',\n 'program.version': 'print Hermes Link version',\n 'status.description': 'Show local Hermes Link status',\n 'status.json': 'print machine-readable status',\n 'status.runtime': 'Runtime: {value}',\n 'status.mode': 'Mode: {value}',\n 'status.port': 'Local port: {value}',\n 'status.linkId': 'Link ID: {value}',\n 'status.notPaired': 'not paired',\n 'start.description': 'Start Hermes Link daemon',\n 'start.backgroundStarted': 'Hermes Link is running in the background. PID: {pid}',\n 'start.alreadyRunning': 'Hermes Link is already running. PID: {pid}',\n 'start.notPaired': 'Hermes Link is not paired yet. Starting in local-only maintenance mode.',\n 'start.notPaired.detail':\n 'Relay, Server polling, and LAN entrypoints stay disabled until you run `hermeslink pair`.',\n 'start.listening': 'Hermes Link API listening on http://127.0.0.1:{port}',\n 'start.relayConnecting': 'Relay control connecting for {linkId}',\n 'stop.description': 'Stop the background Hermes Link daemon',\n 'stop.stopped': 'Hermes Link stopped.',\n 'stop.notRunning': 'Hermes Link is not running.',\n 'restart.description': 'Restart the background Hermes Link daemon',\n 'daemon.description': 'Run Hermes Link in the foreground',\n 'daemon.foreground': 'Hermes Link foreground daemon is running. Press Ctrl+C to stop.',\n 'logs.description': 'Show Hermes Link log paths',\n 'logs.servicePath': 'Service log: {path}',\n 'logs.daemonPath': 'Daemon stdout/stderr log: {path}',\n 'autostart.description': 'Manage boot autostart',\n 'autostart.on.description': 'Enable boot autostart',\n 'autostart.off.description': 'Disable boot autostart',\n 'autostart.status.description': 'Show boot autostart status',\n 'autostart.enabled': 'Boot autostart enabled via {method}: {path}',\n 'autostart.disabled': 'Boot autostart disabled.',\n 'autostart.status.enabled': 'Boot autostart: enabled via {method}: {path}',\n 'autostart.status.disabled': 'Boot autostart: disabled. Method: {method}. File: {path}',\n 'autostart.unsupported': 'Boot autostart is not supported on this platform yet.',\n 'pair.description': 'Create a Hermes Link pairing session',\n 'pair.preparing': 'Preparing pairing session through HermesPilot Server and Relay...',\n 'pair.server': 'Server: {url}',\n 'pair.relay': 'Relay: {url}',\n 'pair.linkId': 'Hermes Link ID: {value}',\n 'pair.code': 'Pairing code: {value}',\n 'pair.localApi': 'Local API: http://127.0.0.1:{port}',\n 'pair.scan': 'Scan this QR code with the HermesPilot App:',\n 'pair.expires': 'Pairing expires in 10 minutes. Press Ctrl+C to cancel waiting.',\n 'pair.claimed': 'Pairing succeeded. Starting Hermes Link in the background...',\n 'pair.claimedRunning': 'Pairing succeeded. Hermes Link is already running in the background.',\n 'pair.autostartFailed': 'Pairing succeeded, but boot autostart could not be enabled: {message}',\n 'doctor.description': 'Run local diagnostics',\n 'doctor.identityOk': 'Runtime identity: OK',\n 'doctor.installId': 'Install ID: {value}',\n 'doctor.linkId': 'Link ID: {value}',\n 'doctor.notAssigned': 'not assigned',\n 'doctor.apiReady': 'Hermes API Server: ready',\n 'doctor.apiStarted': 'Hermes API Server: started and ready',\n 'doctor.apiUnavailable': 'Hermes API Server: unavailable. {message}',\n 'error.relayPublicKeyMismatch':\n 'Relay rejected the pairing request because the Server-issued bootstrap token does not match this Link public key. Make sure Server and Relay are deployed with the same bootstrap key configuration, then run `hermeslink pair` again.',\n 'error.relayChallengeInvalid': 'Relay did not return a valid install challenge.',\n 'error.relayLinkInvalid': 'Relay did not return a valid link_id.',\n 'error.relayEmpty': 'Relay returned an empty response.',\n 'error.serverHttp': 'HermesPilot Server request failed with HTTP {status}.',\n 'error.portInUse':\n 'Local port {port} is already in use by another process. Stop that process or change the Hermes Link port, then run `hermeslink pair` again.',\n 'error.pairingRequires':\n 'Pairing needs HermesPilot Server and Relay, but this command could not start a complete pairing session.',\n 'error.pairingRequires.detail':\n 'The deployed services may be healthy, but the installed Link package must call Server for a short-lived relay bootstrap token before it can request a link_id.',\n },\n 'zh-CN': {\n 'program.description': 'Hermes Link 本地伴随服务',\n 'program.version': '输出 Hermes Link 版本号',\n 'status.description': '查看本机 Hermes Link 状态',\n 'status.json': '输出机器可读的状态 JSON',\n 'status.runtime': '运行目录:{value}',\n 'status.mode': '模式:{value}',\n 'status.port': '本地端口:{value}',\n 'status.linkId': 'Link ID:{value}',\n 'status.notPaired': '尚未配对',\n 'start.description': '启动 Hermes Link 服务',\n 'start.backgroundStarted': 'Hermes Link 已在后台运行。PID:{pid}',\n 'start.alreadyRunning': 'Hermes Link 已经在运行。PID:{pid}',\n 'start.notPaired': 'Hermes Link 还没有配对,将以本地维护模式启动。',\n 'start.notPaired.detail': '在你运行 `hermeslink pair` 前,Relay、Server 轮询和局域网入口都会保持关闭。',\n 'start.listening': 'Hermes Link API 正在监听 http://127.0.0.1:{port}',\n 'start.relayConnecting': '正在为 {linkId} 连接 Relay 控制通道',\n 'stop.description': '停止后台 Hermes Link 服务',\n 'stop.stopped': 'Hermes Link 已停止。',\n 'stop.notRunning': 'Hermes Link 没有在运行。',\n 'restart.description': '重启后台 Hermes Link 服务',\n 'daemon.description': '以前台方式运行 Hermes Link',\n 'daemon.foreground': 'Hermes Link 前台服务正在运行。按 Ctrl+C 停止。',\n 'logs.description': '显示 Hermes Link 日志路径',\n 'logs.servicePath': '服务日志:{path}',\n 'logs.daemonPath': 'Daemon 标准输出/错误日志:{path}',\n 'autostart.description': '管理开机自启',\n 'autostart.on.description': '启用开机自启',\n 'autostart.off.description': '关闭开机自启',\n 'autostart.status.description': '查看开机自启状态',\n 'autostart.enabled': '已启用开机自启,方式:{method},文件:{path}',\n 'autostart.disabled': '已关闭开机自启。',\n 'autostart.status.enabled': '开机自启:已启用,方式:{method},文件:{path}',\n 'autostart.status.disabled': '开机自启:未启用。方式:{method},文件:{path}',\n 'autostart.unsupported': '当前平台暂不支持开机自启。',\n 'pair.description': '创建 Hermes Link 配对会话',\n 'pair.preparing': '正在通过 HermesPilot Server 和 Relay 创建配对会话...',\n 'pair.server': 'Server:{url}',\n 'pair.relay': 'Relay:{url}',\n 'pair.linkId': 'Hermes Link ID:{value}',\n 'pair.code': '配对码:{value}',\n 'pair.localApi': '本地 API:http://127.0.0.1:{port}',\n 'pair.scan': '请使用 HermesPilot App 扫描这个二维码:',\n 'pair.expires': '配对会话 10 分钟后过期。按 Ctrl+C 退出等待。',\n 'pair.claimed': '配对已成功。正在把 Hermes Link 切换到后台运行...',\n 'pair.claimedRunning': '配对已成功。Hermes Link 已在后台持续运行。',\n 'pair.autostartFailed': '配对已成功,但启用开机自启失败:{message}',\n 'doctor.description': '运行本机诊断',\n 'doctor.identityOk': '运行身份:正常',\n 'doctor.installId': 'Install ID:{value}',\n 'doctor.linkId': 'Link ID:{value}',\n 'doctor.notAssigned': '尚未分配',\n 'doctor.apiReady': 'Hermes API Server:已就绪',\n 'doctor.apiStarted': 'Hermes API Server:已自动启动并就绪',\n 'doctor.apiUnavailable': 'Hermes API Server:不可用。{message}',\n 'error.relayPublicKeyMismatch':\n 'Relay 拒绝了配对请求:Server 签发的 bootstrap token 与本机 Link 公钥不匹配。请确认 Server 和 Relay 使用同一套 bootstrap key 配置,然后重新运行 `hermeslink pair`。',\n 'error.relayChallengeInvalid': 'Relay 没有返回有效的安装挑战。',\n 'error.relayLinkInvalid': 'Relay 没有返回有效的 link_id。',\n 'error.relayEmpty': 'Relay 返回了空响应。',\n 'error.serverHttp': 'HermesPilot Server 请求失败,HTTP 状态码:{status}。',\n 'error.portInUse':\n '本地端口 {port} 已被其他进程占用。请先停止占用该端口的程序,或调整 Hermes Link 端口后重新运行 `hermeslink pair`。',\n 'error.pairingRequires': '配对需要 HermesPilot Server 和 Relay,但当前命令没有能启动完整配对会话。',\n 'error.pairingRequires.detail':\n '云端服务可以是已部署且健康的;本机 Link 仍必须先向 Server 申请短期 relay bootstrap token,才能再向 Relay 申请 link_id。',\n },\n} satisfies Record<SupportedLanguage, Record<string, string>>\n\nexport type MessageKey = keyof (typeof messages)['en']\n\nexport function detectSystemLanguage(env: NodeJS.ProcessEnv = process.env): SupportedLanguage {\n const candidates = [\n env.HERMESLINK_LANG,\n env.HERMESLINK_LANGUAGE,\n env.LC_ALL,\n env.LC_MESSAGES,\n env.LANG,\n env.LANGUAGE?.split(':')[0],\n Intl.DateTimeFormat().resolvedOptions().locale,\n ]\n for (const candidate of candidates) {\n const language = parseLanguage(candidate)\n if (language) {\n return language\n }\n }\n return 'en'\n}\n\nexport function resolveLanguage(setting?: ConfiguredLanguage | string | null): SupportedLanguage {\n const configured = parseLanguage(setting)\n if (configured) {\n return configured\n }\n return detectSystemLanguage()\n}\n\nexport function translate(\n language: SupportedLanguage,\n key: MessageKey,\n values: Record<string, string | number> = {},\n): string {\n const template = messages[language][key] ?? messages.en[key]\n return template.replace(/\\{(\\w+)\\}/gu, (_, name: string) => String(values[name] ?? ''))\n}\n\nexport function localizeErrorMessage(error: unknown, language: SupportedLanguage): string {\n const message = error instanceof Error ? error.message : String(error)\n if (language === 'en') {\n return message\n }\n const mapped = translateKnownError(message, language)\n return mapped ?? message\n}\n\nfunction translateKnownError(message: string, language: SupportedLanguage): string | null {\n if (message === 'Relay bootstrap token does not match public key') {\n return translate(language, 'error.relayPublicKeyMismatch')\n }\n if (message === 'Relay did not return a valid install challenge') {\n return translate(language, 'error.relayChallengeInvalid')\n }\n if (message === 'Relay did not return a valid link_id') {\n return translate(language, 'error.relayLinkInvalid')\n }\n if (message === 'Relay returned an empty response') {\n return translate(language, 'error.relayEmpty')\n }\n const portInUse = /^listen EADDRINUSE: address already in use .*:(?<port>\\d+)$/u.exec(message)\n if (portInUse?.groups?.port) {\n return translate(language, 'error.portInUse', { port: portInUse.groups.port })\n }\n const serverHttp = /^HermesPilot Server request failed with HTTP (?<status>\\d+)$/u.exec(message)\n if (serverHttp?.groups?.status) {\n return translate(language, 'error.serverHttp', { status: serverHttp.groups.status })\n }\n if (message.includes('Pairing requires HermesPilot Server and Relay')) {\n return [translate(language, 'error.pairingRequires'), translate(language, 'error.pairingRequires.detail')].join('\\n')\n }\n return null\n}\n\nfunction parseLanguage(value: string | null | undefined): SupportedLanguage | null {\n const normalized = value?.trim().replace('_', '-').toLowerCase()\n if (!normalized || normalized === 'auto' || normalized === 'c' || normalized === 'posix') {\n return null\n }\n if (normalized.startsWith('zh')) {\n return 'zh-CN'\n }\n if (normalized.startsWith('en')) {\n return 'en'\n }\n return null\n}\n"],"mappings":"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","names":["mkdir","readFile","rm","writeFile","path","mkdir","rm","mkdir","rm","mkdir","path","writeFile","rm","readFile","autostart"]}
1
+ {"version":3,"sources":["../../src/cli/index.ts","../../src/autostart/autostart.ts","../../src/daemon/process.ts","../../src/daemon/service.ts","../../src/relay/control-client.ts","../../src/daemon/scheduler.ts","../../src/i18n.ts","../../src/pairing/preflight.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { Command } from 'commander'\nimport qrcode from 'qrcode-terminal'\nimport { LINK_COMMAND, LINK_VERSION } from '../constants.js'\nimport { enableAutostart, disableAutostart, getAutostartStatus } from '../autostart/autostart.js'\nimport { loadConfig } from '../config/config.js'\nimport {\n getDaemonStatus,\n startDaemonProcess,\n stopDaemonProcess,\n daemonLogFile,\n probeLocalLinkService,\n runDaemonSupervisor,\n} from '../daemon/process.js'\nimport { startLinkService, type LinkService } from '../daemon/service.js'\nimport { ensureHermesApiServerConfig } from '../hermes/config.js'\nimport { ensureHermesApiServerAvailable } from '../hermes/gateway.js'\nimport { ensureIdentity, getIdentityStatus, loadIdentity } from '../identity/identity.js'\nimport { detectSystemLanguage, localizeErrorMessage, resolveLanguage, translate } from '../i18n.js'\nimport { clearPairingClaim, preparePairing, readPairingClaim } from '../pairing/pairing.js'\nimport { assertPairingPreflightReady } from '../pairing/preflight.js'\nimport { getLinkLogFile } from '../runtime/logger.js'\nimport { resolveRuntimePaths, type RuntimePaths } from '../runtime/paths.js'\nimport { hasActiveDevices } from '../security/devices.js'\n\nconst program = new Command()\nconst helpLanguage = detectSystemLanguage()\nconst helpText = translate.bind(null, helpLanguage)\n\nprogram\n .name(LINK_COMMAND)\n .description(helpText('program.description'))\n .version(LINK_VERSION, '-v, --version', helpText('program.version'))\n\nprogram\n .command('status')\n .option('--json', helpText('status.json'))\n .description(helpText('status.description'))\n .action(async (options: { json?: boolean }) => {\n const paths = resolveRuntimePaths()\n const [identity, config] = await Promise.all([loadIdentity(paths), loadConfig(paths)])\n const language = resolveLanguage(config.language)\n const t = translate.bind(null, language)\n const payload = {\n version: LINK_VERSION,\n runtimeHome: paths.homeDir,\n paired: Boolean(identity?.link_id),\n mode: identity?.link_id ? 'paired' : 'local-only',\n port: config.port,\n identity: identity ? getIdentityStatus(identity) : null,\n relay: {\n configured: Boolean(config.relayBaseUrl),\n connected: false,\n },\n }\n if (options.json) {\n console.log(JSON.stringify(payload, null, 2))\n return\n }\n console.log(`Hermes Link ${payload.version}`)\n console.log(t('status.runtime', { value: payload.runtimeHome }))\n console.log(t('status.mode', { value: payload.mode }))\n console.log(t('status.port', { value: payload.port }))\n console.log(t('status.linkId', { value: payload.identity?.linkId ?? t('status.notPaired') }))\n })\n\nprogram\n .command('start')\n .description(helpText('start.description'))\n .action(async () => {\n const [config, status] = await Promise.all([loadConfig(), getDaemonStatus()])\n const language = resolveLanguage(config.language)\n const t = translate.bind(null, language)\n if (status.running && status.pid) {\n console.log(t('start.alreadyRunning', { pid: status.pid }))\n return\n }\n const nextStatus = await startDaemonProcess()\n console.log(t('start.backgroundStarted', { pid: nextStatus.pid ?? 'unknown' }))\n })\n\nprogram\n .command('stop')\n .description(helpText('stop.description'))\n .action(async () => {\n const config = await loadConfig()\n const language = resolveLanguage(config.language)\n const t = translate.bind(null, language)\n const before = await getDaemonStatus()\n if (!before.running) {\n console.log(t('stop.notRunning'))\n return\n }\n await stopDaemonProcess()\n console.log(t('stop.stopped'))\n })\n\nprogram\n .command('restart')\n .description(helpText('restart.description'))\n .action(async () => {\n const config = await loadConfig()\n const language = resolveLanguage(config.language)\n const t = translate.bind(null, language)\n await stopDaemonProcess()\n const status = await startDaemonProcess()\n console.log(t('start.backgroundStarted', { pid: status.pid ?? 'unknown' }))\n })\n\nprogram\n .command('daemon')\n .option('--foreground', 'run in foreground')\n .description(helpText('daemon.description'))\n .action(async () => {\n const config = await loadConfig()\n const language = resolveLanguage(config.language)\n const t = translate.bind(null, language)\n const service = await startLinkService({ writePidFile: true })\n console.log(t('daemon.foreground'))\n await waitForShutdown(async () => {\n await service.close()\n })\n process.exit(0)\n })\n\nprogram\n .command('daemon-supervisor', { hidden: true })\n .action(async () => {\n process.exitCode = await runDaemonSupervisor()\n })\n\nprogram\n .command('pair')\n .description(helpText('pair.description'))\n .action(async () => {\n const paths = resolveRuntimePaths()\n const config = await loadConfig(paths)\n const language = resolveLanguage(config.language)\n const t = translate.bind(null, language)\n console.log(t('pair.preflight'))\n const preflight = await assertPairingPreflightReady({ paths })\n console.log(t('pair.hermesHome', { path: preflight.hermesHome }))\n console.log(t('pair.apiReady', { port: preflight.apiServer.port ?? 'unknown' }))\n console.log(t('pair.preparing'))\n console.log(t('pair.server', { url: config.serverBaseUrl }))\n console.log(t('pair.relay', { url: config.relayBaseUrl }))\n await ensureIdentity(paths)\n const hadActiveDevices = await hasActiveDevices(paths)\n const probeBeforePair = await probeLocalLinkService({ port: config.port })\n const prepared = await preparePairing(paths)\n await clearPairingClaim(prepared.sessionId, paths)\n const probe = await probeLocalLinkService({ port: config.port, linkId: prepared.linkId })\n if (probe.reachable && !probe.reusable) {\n throw new Error(\n `Local Hermes Link on port ${config.port} belongs to ${probe.linkId ?? 'an unassigned Link'}, not ${prepared.linkId}.`,\n )\n }\n const reusedRunningService = probe.reusable\n const restartReusedServiceAfterClaim = reusedRunningService && !probeBeforePair.linkId\n const service: LinkService | null = reusedRunningService ? null : await startLinkService({ paths })\n const qrValue = JSON.stringify(prepared.qrPayload)\n console.log(t('pair.linkId', { value: prepared.linkId }))\n console.log(t('pair.code', { value: prepared.code }))\n console.log(t('pair.localApi', { port: config.port }))\n console.log(t('pair.scan'))\n qrcode.generate(qrValue, { small: true })\n console.log(t('pair.expires'))\n const result = await waitForPairingOrShutdown(prepared.sessionId, paths)\n if (service) {\n await service.close()\n }\n if (result === 'claimed') {\n await clearPairingClaim(prepared.sessionId, paths)\n console.log(t(reusedRunningService ? 'pair.claimedRunning' : 'pair.claimed'))\n try {\n if (hadActiveDevices) {\n console.log(t('pair.autostartUnchanged'))\n } else {\n const currentAutostart = await getAutostartStatus()\n if (currentAutostart.supported && currentAutostart.enabled) {\n console.log(\n t('autostart.alreadyEnabled', {\n method: currentAutostart.method,\n path: currentAutostart.filePath ?? '',\n }),\n )\n } else {\n const autostart = await enableAutostart()\n if (autostart.supported && autostart.enabled) {\n console.log(t('autostart.enabled', { method: autostart.method, path: autostart.filePath ?? '' }))\n }\n }\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n console.log(t('pair.autostartFailed', { message }))\n }\n if (restartReusedServiceAfterClaim) {\n await stopDaemonProcess(paths)\n const status = await startDaemonProcess(paths)\n console.log(t('start.backgroundStarted', { pid: status.pid ?? 'unknown' }))\n } else if (!reusedRunningService) {\n const status = await startDaemonProcess(paths)\n console.log(t('start.backgroundStarted', { pid: status.pid ?? 'unknown' }))\n }\n }\n })\n\nconst autostart = program.command('autostart').description(helpText('autostart.description'))\n\nautostart\n .command('on')\n .description(helpText('autostart.on.description'))\n .action(async () => {\n const config = await loadConfig()\n const language = resolveLanguage(config.language)\n const t = translate.bind(null, language)\n const status = await enableAutostart()\n if (!status.supported) {\n console.log(t('autostart.unsupported'))\n return\n }\n console.log(t('autostart.enabled', { method: status.method, path: status.filePath ?? '' }))\n })\n\nautostart\n .command('off')\n .description(helpText('autostart.off.description'))\n .action(async () => {\n const config = await loadConfig()\n const language = resolveLanguage(config.language)\n const t = translate.bind(null, language)\n await disableAutostart()\n console.log(t('autostart.disabled'))\n })\n\nautostart\n .command('status')\n .description(helpText('autostart.status.description'))\n .action(async () => {\n const config = await loadConfig()\n const language = resolveLanguage(config.language)\n const t = translate.bind(null, language)\n const status = await getAutostartStatus()\n if (!status.supported) {\n console.log(t('autostart.unsupported'))\n return\n }\n console.log(\n t(status.enabled ? 'autostart.status.enabled' : 'autostart.status.disabled', {\n method: status.method,\n path: status.filePath ?? '',\n }),\n )\n })\n\nprogram\n .command('logs')\n .description(helpText('logs.description'))\n .action(async () => {\n const paths = resolveRuntimePaths()\n const config = await loadConfig(paths)\n const language = resolveLanguage(config.language)\n const t = translate.bind(null, language)\n console.log(t('logs.servicePath', { path: getLinkLogFile(paths) }))\n console.log(t('logs.daemonPath', { path: daemonLogFile(paths) }))\n })\n\nprogram\n .command('doctor')\n .description(helpText('doctor.description'))\n .action(async () => {\n const [identity, config] = await Promise.all([ensureIdentity(), loadConfig()])\n const language = resolveLanguage(config.language)\n const t = translate.bind(null, language)\n const hermesConfig = await ensureHermesApiServerConfig()\n console.log(t('doctor.identityOk'))\n console.log(t('doctor.installId', { value: identity.install_id }))\n console.log(t('doctor.linkId', { value: identity.link_id ?? t('doctor.notAssigned') }))\n if (hermesConfig.notice) {\n console.log(hermesConfig.notice)\n if (hermesConfig.backupPath) {\n console.log(`Hermes config backup: ${hermesConfig.backupPath}`)\n }\n }\n try {\n const availability = await ensureHermesApiServerAvailable({ timeoutMs: 5_000 })\n console.log(t(availability.started ? 'doctor.apiStarted' : 'doctor.apiReady'))\n } catch (error) {\n console.log(t('doctor.apiUnavailable', { message: error instanceof Error ? error.message : String(error) }))\n }\n })\n\nprogram.parseAsync(process.argv).catch(async (error) => {\n const language = await loadCliLanguage().catch(() => detectSystemLanguage())\n console.error(localizeErrorMessage(error, language))\n process.exitCode = 1\n})\n\nasync function loadCliLanguage() {\n const config = await loadConfig()\n return resolveLanguage(config.language)\n}\n\nasync function waitForShutdown(cleanup: () => Promise<void>): Promise<void> {\n await new Promise<void>((resolve) => {\n const stop = () => resolve()\n process.once('SIGINT', stop)\n process.once('SIGTERM', stop)\n })\n await cleanup()\n}\n\nasync function waitForPairingOrShutdown(\n sessionId: string,\n paths: RuntimePaths,\n): Promise<'claimed' | 'shutdown'> {\n let shutdownRequested = false\n const stop = () => {\n shutdownRequested = true\n }\n process.once('SIGINT', stop)\n process.once('SIGTERM', stop)\n try {\n while (!shutdownRequested) {\n const record = await readPairingClaim(sessionId, paths)\n if (record) {\n return 'claimed'\n }\n await sleep(250)\n }\n return 'shutdown'\n } finally {\n process.off('SIGINT', stop)\n process.off('SIGTERM', stop)\n }\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms))\n}\n","import { execFile } from 'node:child_process'\nimport { mkdir, readFile, rm, writeFile } from 'node:fs/promises'\nimport os from 'node:os'\nimport path from 'node:path'\nimport { promisify } from 'node:util'\nimport { currentCliScriptPath } from '../daemon/process.js'\n\nconst execFileAsync = promisify(execFile)\nconst MACOS_LABEL = 'com.hermespilot.link'\n\nexport interface AutostartStatus {\n supported: boolean\n enabled: boolean\n method: 'launchd' | 'systemd-user' | 'xdg-autostart' | 'windows-startup' | 'unsupported'\n filePath: string | null\n}\n\nexport async function enableAutostart(): Promise<AutostartStatus> {\n const definition = await resolveAutostartDefinition()\n if (!definition) {\n return unsupportedStatus()\n }\n await mkdir(path.dirname(definition.filePath), { recursive: true, mode: 0o700 })\n await writeFile(definition.filePath, definition.content, { mode: 0o600 })\n if (definition.method === 'systemd-user') {\n await execFileAsync('systemctl', ['--user', 'enable', path.basename(definition.filePath)]).catch(async () => {\n await rm(definition.filePath, { force: true }).catch(() => undefined)\n const fallback = xdgAutostartDefinition()\n await mkdir(path.dirname(fallback.filePath), { recursive: true, mode: 0o700 })\n await writeFile(fallback.filePath, fallback.content, { mode: 0o600 })\n })\n }\n return await getAutostartStatus()\n}\n\nexport async function disableAutostart(): Promise<AutostartStatus> {\n const definitions = await allAutostartDefinitions()\n for (const definition of definitions) {\n if (definition.method === 'systemd-user') {\n await execFileAsync('systemctl', ['--user', 'disable', path.basename(definition.filePath)]).catch(() => undefined)\n }\n await rm(definition.filePath, { force: true }).catch(() => undefined)\n }\n return await getAutostartStatus()\n}\n\nexport async function getAutostartStatus(): Promise<AutostartStatus> {\n const definitions = await allAutostartDefinitions()\n if (definitions.length === 0) {\n return unsupportedStatus()\n }\n for (const definition of definitions) {\n const content = await readFile(definition.filePath, 'utf8').catch(() => null)\n if (content !== null) {\n return {\n supported: true,\n enabled: true,\n method: definition.method,\n filePath: definition.filePath,\n }\n }\n }\n const primary = definitions[0]\n return {\n supported: true,\n enabled: false,\n method: primary.method,\n filePath: primary.filePath,\n }\n}\n\nasync function resolveAutostartDefinition(): Promise<AutostartDefinition | null> {\n if (process.platform === 'darwin') {\n return launchdDefinition()\n }\n if (process.platform === 'win32') {\n return windowsStartupDefinition()\n }\n if (process.platform === 'linux') {\n return await hasSystemctlUser() ? systemdUserDefinition() : xdgAutostartDefinition()\n }\n return null\n}\n\nasync function allAutostartDefinitions(): Promise<AutostartDefinition[]> {\n if (process.platform === 'darwin') {\n return [launchdDefinition()]\n }\n if (process.platform === 'win32') {\n return [windowsStartupDefinition()]\n }\n if (process.platform === 'linux') {\n return [systemdUserDefinition(), xdgAutostartDefinition()]\n }\n return []\n}\n\nasync function hasSystemctlUser(): Promise<boolean> {\n try {\n await execFileAsync('systemctl', ['--user', 'show-environment'])\n return true\n } catch {\n return false\n }\n}\n\nfunction launchdDefinition(): AutostartDefinition {\n const filePath = path.join(os.homedir(), 'Library', 'LaunchAgents', `${MACOS_LABEL}.plist`)\n return {\n method: 'launchd',\n filePath,\n content: `<?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 <key>Label</key>\n <string>${MACOS_LABEL}</string>\n <key>ProgramArguments</key>\n <array>\n <string>${xmlEscape(process.execPath)}</string>\n <string>${xmlEscape(currentCliScriptPath())}</string>\n <string>daemon-supervisor</string>\n </array>\n <key>RunAtLoad</key>\n <true/>\n <key>KeepAlive</key>\n <false/>\n</dict>\n</plist>\n`,\n }\n}\n\nfunction systemdUserDefinition(): AutostartDefinition {\n const filePath = path.join(os.homedir(), '.config', 'systemd', 'user', 'hermeslink.service')\n return {\n method: 'systemd-user',\n filePath,\n content: `[Unit]\nDescription=Hermes Link\nAfter=network-online.target\n\n[Service]\nType=simple\nExecStart=${systemdQuote(process.execPath)} ${systemdQuote(currentCliScriptPath())} daemon-supervisor\nRestart=no\n\n[Install]\nWantedBy=default.target\n`,\n }\n}\n\nfunction xdgAutostartDefinition(): AutostartDefinition {\n const filePath = path.join(os.homedir(), '.config', 'autostart', 'hermeslink.desktop')\n return {\n method: 'xdg-autostart',\n filePath,\n content: `[Desktop Entry]\nType=Application\nName=Hermes Link\nExec=${desktopQuote(process.execPath)} ${desktopQuote(currentCliScriptPath())} daemon-supervisor\nTerminal=false\nX-GNOME-Autostart-enabled=true\n`,\n }\n}\n\nfunction windowsStartupDefinition(): AutostartDefinition {\n const appData = process.env.APPDATA ?? path.join(os.homedir(), 'AppData', 'Roaming')\n const filePath = path.join(appData, 'Microsoft', 'Windows', 'Start Menu', 'Programs', 'Startup', 'HermesLink.cmd')\n return {\n method: 'windows-startup',\n filePath,\n content: `@echo off\\r\\nstart \"\" /min \"${process.execPath}\" \"${currentCliScriptPath()}\" daemon-supervisor\\r\\n`,\n }\n}\n\nfunction unsupportedStatus(): AutostartStatus {\n return {\n supported: false,\n enabled: false,\n method: 'unsupported',\n filePath: null,\n }\n}\n\nfunction xmlEscape(value: string): string {\n return value\n .replaceAll('&', '&amp;')\n .replaceAll('<', '&lt;')\n .replaceAll('>', '&gt;')\n .replaceAll('\"', '&quot;')\n .replaceAll(\"'\", '&apos;')\n}\n\nfunction systemdQuote(value: string): string {\n return `\"${value.replaceAll('\\\\', '\\\\\\\\').replaceAll('\"', '\\\\\"')}\"`\n}\n\nfunction desktopQuote(value: string): string {\n return `\"${value.replaceAll('\\\\', '\\\\\\\\').replaceAll('\"', '\\\\\"')}\"`\n}\n\ninterface AutostartDefinition {\n method: AutostartStatus['method']\n filePath: string\n content: string\n}\n","import { spawn } from 'node:child_process'\nimport { mkdir, readFile, rm } from 'node:fs/promises'\nimport path from 'node:path'\nimport { pidFilePath } from './service.js'\nimport { loadConfig } from '../config/config.js'\nimport {\n createRotatingTextLogWriter,\n getDaemonLogFile,\n} from '../runtime/logger.js'\nimport { resolveRuntimePaths, type RuntimePaths } from '../runtime/paths.js'\n\nexport interface DaemonStatus {\n running: boolean\n pid: number | null\n pidFile: string\n logFile: string\n}\n\nexport interface LocalLinkServiceProbe {\n reachable: boolean\n reusable: boolean\n linkId: string | null\n version: string | null\n}\n\nexport async function startDaemonProcess(paths: RuntimePaths = resolveRuntimePaths()): Promise<DaemonStatus> {\n const config = await loadConfig(paths)\n let status = await getDaemonStatus(paths)\n if (status.running) {\n const probe = await probeLocalLinkService({ port: config.port, timeoutMs: 500 })\n if (probe.reachable) {\n return status\n }\n await stopDaemonProcess(paths)\n status = await getDaemonStatus(paths)\n if (status.running) {\n return status\n }\n }\n await mkdir(paths.logsDir, { recursive: true, mode: 0o700 })\n await mkdir(paths.runDir, { recursive: true, mode: 0o700 })\n const scriptPath = currentCliScriptPath()\n const child = spawn(process.execPath, [scriptPath, 'daemon-supervisor'], {\n detached: true,\n stdio: 'ignore',\n env: process.env,\n })\n child.unref()\n for (let index = 0; index < 12; index += 1) {\n await wait(250)\n const next = await getDaemonStatus(paths)\n if (next.running && (await probeLocalLinkService({ port: config.port, timeoutMs: 500 })).reachable) {\n return next\n }\n }\n return await getDaemonStatus(paths)\n}\n\nexport async function runDaemonSupervisor(paths: RuntimePaths = resolveRuntimePaths()): Promise<number> {\n await mkdir(paths.logsDir, { recursive: true, mode: 0o700 })\n const log = createRotatingTextLogWriter({\n paths,\n fileName: path.basename(daemonLogFile(paths)),\n })\n const scriptPath = currentCliScriptPath()\n const child = spawn(process.execPath, [scriptPath, 'daemon', '--foreground'], {\n stdio: ['ignore', 'pipe', 'pipe'],\n env: process.env,\n })\n const write = (chunk: Buffer | string) => {\n void log.write(chunk)\n }\n write(`[${new Date().toISOString()}] daemon supervisor started\\n`)\n child.stdout?.on('data', write)\n child.stderr?.on('data', write)\n\n const forwardStop = () => {\n if (child.pid && isProcessAlive(child.pid)) {\n child.kill('SIGTERM')\n }\n }\n process.once('SIGINT', forwardStop)\n process.once('SIGTERM', forwardStop)\n const result = await new Promise<{ code: number | null; signal: NodeJS.Signals | null }>((resolve, reject) => {\n child.once('error', reject)\n child.once('exit', (code, signal) => resolve({ code, signal }))\n }).catch((error: unknown) => {\n write(`[${new Date().toISOString()}] daemon supervisor failed: ${error instanceof Error ? error.message : String(error)}\\n`)\n return { code: 1, signal: null }\n })\n process.off('SIGINT', forwardStop)\n process.off('SIGTERM', forwardStop)\n write(\n `[${new Date().toISOString()}] daemon supervisor stopped code=${result.code ?? 'null'} signal=${result.signal ?? 'null'}\\n`,\n )\n await log.flush()\n return result.code ?? (result.signal ? 0 : 1)\n}\n\nexport async function probeLocalLinkService(options: {\n port: number\n linkId?: string\n timeoutMs?: number\n}): Promise<LocalLinkServiceProbe> {\n const unreachable: LocalLinkServiceProbe = {\n reachable: false,\n reusable: false,\n linkId: null,\n version: null,\n }\n let response: Response\n try {\n response = await fetch(`http://127.0.0.1:${options.port}/api/v1/bootstrap`, {\n headers: { accept: 'application/json' },\n signal: AbortSignal.timeout(options.timeoutMs ?? 1_000),\n })\n } catch {\n return unreachable\n }\n if (!response.ok) {\n return unreachable\n }\n const payload = (await response.json().catch(() => null)) as Record<string, unknown> | null\n if (!payload || payload.api_version !== 1) {\n return unreachable\n }\n const linkId = typeof payload.link_id === 'string' ? payload.link_id : null\n return {\n reachable: true,\n reusable: options.linkId ? linkId === options.linkId : true,\n linkId,\n version: typeof payload.version === 'string' ? payload.version : null,\n }\n}\n\nexport async function stopDaemonProcess(paths: RuntimePaths = resolveRuntimePaths()): Promise<DaemonStatus> {\n const status = await getDaemonStatus(paths)\n if (!status.running || !status.pid) {\n return status\n }\n try {\n process.kill(status.pid, 'SIGTERM')\n } catch {\n await rm(pidFilePath(paths), { force: true }).catch(() => undefined)\n return await getDaemonStatus(paths)\n }\n for (let index = 0; index < 20; index += 1) {\n await wait(250)\n if (!isProcessAlive(status.pid)) {\n break\n }\n }\n if (isProcessAlive(status.pid)) {\n try {\n process.kill(status.pid, 'SIGKILL')\n } catch {\n // The process may have exited between the liveness check and the forced kill.\n }\n for (let index = 0; index < 10; index += 1) {\n await wait(250)\n if (!isProcessAlive(status.pid)) {\n break\n }\n }\n }\n if (!isProcessAlive(status.pid) || !(await pidBackedServiceIsReachable(paths))) {\n await rm(pidFilePath(paths), { force: true }).catch(() => undefined)\n }\n return await getDaemonStatus(paths)\n}\n\nexport async function getDaemonStatus(paths: RuntimePaths = resolveRuntimePaths()): Promise<DaemonStatus> {\n const pidFile = pidFilePath(paths)\n const pid = await readPid(pidFile)\n if (pid && !isProcessAlive(pid)) {\n await rm(pidFile, { force: true }).catch(() => undefined)\n return {\n running: false,\n pid: null,\n pidFile,\n logFile: daemonLogFile(paths),\n }\n }\n return {\n running: Boolean(pid),\n pid,\n pidFile,\n logFile: daemonLogFile(paths),\n }\n}\n\nexport function daemonLogFile(paths: RuntimePaths = resolveRuntimePaths()): string {\n return getDaemonLogFile(paths)\n}\n\nexport function currentCliScriptPath(): string {\n return process.argv[1]\n}\n\nasync function readPid(filePath: string): Promise<number | null> {\n const raw = await readFile(filePath, 'utf8').catch(() => null)\n if (!raw) {\n return null\n }\n const pid = Number.parseInt(raw.trim(), 10)\n return Number.isInteger(pid) && pid > 0 ? pid : null\n}\n\nfunction isProcessAlive(pid: number): boolean {\n try {\n process.kill(pid, 0)\n return true\n } catch {\n return false\n }\n}\n\nasync function pidBackedServiceIsReachable(paths: RuntimePaths): Promise<boolean> {\n const config = await loadConfig(paths).catch(() => null)\n if (!config) {\n return false\n }\n return (await probeLocalLinkService({ port: config.port, timeoutMs: 500 })).reachable\n}\n\nfunction wait(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms))\n}\n","import { createServer, type Server } from 'node:http'\nimport { mkdir, rm, writeFile } from 'node:fs/promises'\nimport { createApp, type CreateAppOptions } from '../http/app.js'\nimport { loadConfig } from '../config/config.js'\nimport { ConversationService } from '../conversations/conversation-service.js'\nimport { loadIdentity } from '../identity/identity.js'\nimport { connectRelayControl, type RelayControlClient } from '../relay/control-client.js'\nimport { createFileLogger } from '../runtime/logger.js'\nimport { resolveRuntimePaths, type RuntimePaths } from '../runtime/paths.js'\nimport { migrateLinkDatabase } from '../database/link-database.js'\nimport { startCronDeliveryScheduler } from './scheduler.js'\n\nexport interface LinkService {\n close(): Promise<void>\n}\n\nexport interface StartLinkServiceOptions extends CreateAppOptions {\n paths?: RuntimePaths\n writePidFile?: boolean\n relayMaxReconnectAttempts?: number\n}\n\nexport async function startLinkService(options: StartLinkServiceOptions = {}): Promise<LinkService> {\n const paths = options.paths ?? resolveRuntimePaths()\n const logger = createFileLogger({ paths })\n const [identity, config] = await Promise.all([loadIdentity(paths), loadConfig(paths)])\n await logger.info('service_starting', {\n port: config.port,\n mode: identity?.link_id ? 'paired' : 'local-only',\n })\n const migration = await migrateLinkDatabase(paths)\n if (migration.appliedVersions.length > 0) {\n await logger.info('database_migrated', {\n database_file: migration.databaseFile,\n applied_versions: migration.appliedVersions,\n current_version: migration.currentVersion,\n })\n }\n const conversations = new ConversationService(paths, logger)\n await conversations.rebuildStatisticsIndex()\n const app = await createApp({\n paths,\n logger,\n conversations,\n onPairingClaimed: options.onPairingClaimed,\n })\n const server = createServer(app.callback())\n try {\n await listenServer(server, config.port)\n } catch (error) {\n await logger.error('service_start_failed', {\n port: config.port,\n error: error instanceof Error ? error.message : String(error),\n })\n await logger.flush()\n throw error\n }\n server.on('error', (error) => {\n void logger.error('service_error', { error: error.message })\n })\n void logger.info('service_started', {\n port: config.port,\n link_id: identity?.link_id ?? null,\n })\n const scheduler = startCronDeliveryScheduler({\n paths,\n conversations,\n logger,\n })\n let relay: RelayControlClient | null = null\n if (identity?.link_id) {\n relay = connectRelayControl({\n relayBaseUrl: config.relayBaseUrl,\n linkId: identity.link_id,\n localPort: config.port,\n maxReconnectAttempts: options.relayMaxReconnectAttempts ?? 5,\n backoffBaseMs: 1_000,\n backoffMaxMs: 30_000,\n onStatus: (status) => {\n void logger.info('relay_status', status)\n },\n })\n } else {\n void logger.info('relay_skipped', { reason: 'link_not_paired' })\n }\n if (options.writePidFile) {\n await writePidFile(paths)\n }\n return {\n async close() {\n scheduler.close()\n relay?.close()\n await closeServer(server)\n await logger.info('service_stopped')\n await logger.flush()\n if (options.writePidFile) {\n await rm(pidFilePath(paths), { force: true }).catch(() => undefined)\n }\n },\n }\n}\n\nexport function pidFilePath(paths: RuntimePaths = resolveRuntimePaths()): string {\n return `${paths.runDir}/hermeslink.pid`\n}\n\nasync function writePidFile(paths: RuntimePaths): Promise<void> {\n await mkdir(paths.runDir, { recursive: true, mode: 0o700 })\n await writeFile(pidFilePath(paths), `${process.pid}\\n`, { mode: 0o600 })\n}\n\nasync function closeServer(server: Server): Promise<void> {\n await new Promise<void>((resolve, reject) => {\n let settled = false\n let forceCloseTimer: ReturnType<typeof setTimeout>\n let timeoutTimer: ReturnType<typeof setTimeout>\n const settle = (error?: Error) => {\n if (settled) {\n return\n }\n settled = true\n clearTimeout(forceCloseTimer)\n clearTimeout(timeoutTimer)\n if (error) {\n reject(error)\n return\n }\n resolve()\n }\n forceCloseTimer = setTimeout(() => {\n server.closeIdleConnections?.()\n server.closeAllConnections?.()\n }, 250)\n timeoutTimer = setTimeout(() => {\n server.closeAllConnections?.()\n settle()\n }, 5_000)\n server.close((error) => {\n if (error) {\n settle(error)\n return\n }\n settle()\n })\n server.closeIdleConnections?.()\n })\n}\n\nasync function listenServer(server: Server, port: number): Promise<void> {\n await new Promise<void>((resolve, reject) => {\n const cleanup = () => {\n server.off('error', onError)\n server.off('listening', onListening)\n }\n const onError = (error: Error) => {\n cleanup()\n reject(error)\n }\n const onListening = () => {\n cleanup()\n resolve()\n }\n\n server.once('error', onError)\n server.once('listening', onListening)\n server.listen(port)\n })\n}\n","import WebSocket from 'ws'\nimport { LINK_VERSION } from '../constants.js'\n\ninterface RelayRequestFrame {\n type: 'http.request'\n id: string\n method: string\n path: string\n headers?: Record<string, string>\n bodyBase64?: string | null\n}\n\ninterface RelayCancelFrame {\n type: 'http.cancel'\n id: string\n}\n\ntype RelayFrame = RelayRequestFrame | RelayCancelFrame\n\nexport interface RelayControlClient {\n close(): void\n}\n\nexport function connectRelayControl(options: {\n relayBaseUrl: string\n linkId: string\n localPort: number\n maxReconnectAttempts?: number\n backoffBaseMs?: number\n backoffMaxMs?: number\n onStatus?: (status: { state: 'connecting' | 'connected' | 'disconnected' | 'retrying' | 'failed'; attempt: number; message?: string }) => void\n}): RelayControlClient {\n const wsUrl = new URL(`${options.relayBaseUrl.replace(/\\/+$/u, '')}/api/v1/relay/link/connect`)\n wsUrl.protocol = wsUrl.protocol === 'https:' ? 'wss:' : 'ws:'\n wsUrl.searchParams.set('link_id', options.linkId)\n\n const maxReconnectAttempts = options.maxReconnectAttempts ?? 5\n const backoffBaseMs = options.backoffBaseMs ?? 1_000\n const backoffMaxMs = options.backoffMaxMs ?? 30_000\n let reconnectAttempts = 0\n let closedByUser = false\n let socket: WebSocket | null = null\n let retryTimer: ReturnType<typeof setTimeout> | null = null\n let abortControllers = new Map<string, AbortController>()\n let fatalRelayRejection: string | null = null\n\n const connect = () => {\n options.onStatus?.({ state: 'connecting', attempt: reconnectAttempts })\n fatalRelayRejection = null\n socket = new WebSocket(wsUrl, {\n headers: {\n 'x-hermes-link-version': LINK_VERSION,\n },\n })\n socket.on('open', () => {\n reconnectAttempts = 0\n options.onStatus?.({ state: 'connected', attempt: reconnectAttempts })\n })\n socket.on('message', (raw) => {\n if (!socket || (typeof raw !== 'string' && !Buffer.isBuffer(raw))) {\n return\n }\n void handleFrame(socket, String(raw), options.localPort, abortControllers).catch((error) => {\n const message = error instanceof Error ? error.message : 'Relay request failed'\n socket?.send(JSON.stringify({ type: 'http.error', id: 'unknown', status: 502, message }))\n })\n })\n socket.on('error', (error) => {\n const message = error instanceof Error ? error.message : 'Relay websocket error'\n fatalRelayRejection = resolveFatalRelayRejection(message)\n options.onStatus?.({\n state: 'disconnected',\n attempt: reconnectAttempts,\n message: fatalRelayRejection ?? message,\n })\n })\n socket.on('close', () => {\n abortAll(abortControllers)\n abortControllers = new Map<string, AbortController>()\n if (fatalRelayRejection) {\n options.onStatus?.({\n state: 'failed',\n attempt: reconnectAttempts,\n message: fatalRelayRejection,\n })\n return\n }\n if (closedByUser) {\n options.onStatus?.({ state: 'disconnected', attempt: reconnectAttempts })\n return\n }\n if (reconnectAttempts >= maxReconnectAttempts) {\n options.onStatus?.({ state: 'failed', attempt: reconnectAttempts, message: 'Relay reconnect attempts exhausted' })\n return\n }\n reconnectAttempts += 1\n const delay = computeBackoffMs(reconnectAttempts, backoffBaseMs, backoffMaxMs)\n options.onStatus?.({ state: 'retrying', attempt: reconnectAttempts, message: `Retrying in ${delay}ms` })\n retryTimer = setTimeout(connect, delay)\n retryTimer.unref?.()\n })\n }\n\n connect()\n\n return {\n close() {\n closedByUser = true\n if (retryTimer) {\n clearTimeout(retryTimer)\n retryTimer = null\n }\n abortAll(abortControllers)\n socket?.terminate()\n },\n }\n}\n\nfunction resolveFatalRelayRejection(message: string): string | null {\n if (!/Unexpected server response:\\s*(400|401|403|426)\\b/u.test(message)) {\n return null\n }\n return 'Relay refused the Hermes Link connection. Check Link version and pairing state before retrying.'\n}\n\nfunction abortAll(abortControllers: Map<string, AbortController>): void {\n for (const controller of abortControllers.values()) {\n controller.abort()\n }\n abortControllers.clear()\n}\n\nfunction computeBackoffMs(attempt: number, baseMs: number, maxMs: number): number {\n const exponential = Math.min(maxMs, baseMs * 2 ** Math.max(0, attempt - 1))\n const jitter = Math.floor(Math.random() * Math.min(1_000, exponential * 0.2))\n return exponential + jitter\n}\n\nasync function handleFrame(\n socket: WebSocket,\n raw: string,\n localPort: number,\n abortControllers: Map<string, AbortController>,\n): Promise<void> {\n const frame = JSON.parse(raw) as RelayFrame\n if (frame.type === 'http.cancel') {\n abortControllers.get(frame.id)?.abort()\n abortControllers.delete(frame.id)\n return\n }\n if (frame.type !== 'http.request') {\n return\n }\n const abortController = new AbortController()\n abortControllers.set(frame.id, abortController)\n try {\n const response = await fetch(`http://127.0.0.1:${localPort}${frame.path}`, {\n method: frame.method,\n headers: frame.headers ?? {},\n body: frame.bodyBase64 ? Buffer.from(frame.bodyBase64, 'base64') : undefined,\n signal: abortController.signal,\n })\n const headers = Object.fromEntries(response.headers.entries())\n const contentType = response.headers.get('content-type') ?? ''\n if (response.body && contentType.includes('text/event-stream')) {\n socket.send(JSON.stringify({ type: 'http.stream.start', id: frame.id, status: response.status, headers }))\n const reader = response.body.getReader()\n while (true) {\n const next = await reader.read()\n if (next.done) {\n break\n }\n socket.send(JSON.stringify({ type: 'http.stream.chunk', id: frame.id, bodyBase64: Buffer.from(next.value).toString('base64') }))\n }\n socket.send(JSON.stringify({ type: 'http.stream.end', id: frame.id }))\n return\n }\n const body = Buffer.from(await response.arrayBuffer()).toString('base64')\n socket.send(JSON.stringify({ type: 'http.response', id: frame.id, status: response.status, headers, bodyBase64: body }))\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Relay request failed'\n socket.send(JSON.stringify({ type: 'http.error', id: frame.id, status: 502, message }))\n } finally {\n abortControllers.delete(frame.id)\n }\n}\n","import type { ConversationService } from '../conversations/conversation-service.js'\nimport { syncHermesLinkCronDeliveries } from '../hermes/cron-link-delivery.js'\nimport type { FileLogger } from '../runtime/logger.js'\nimport type { RuntimePaths } from '../runtime/paths.js'\n\nexport interface LinkScheduler {\n close(): void\n}\n\nexport function startCronDeliveryScheduler(options: {\n paths: RuntimePaths\n conversations: ConversationService\n logger: FileLogger\n intervalMs?: number\n}): LinkScheduler {\n let running = false\n const syncCronDeliveries = async () => {\n if (running) {\n return\n }\n running = true\n try {\n await syncHermesLinkCronDeliveries(\n options.paths,\n options.conversations,\n options.logger,\n )\n } catch (error) {\n void options.logger.warn('cron_link_delivery_sync_failed', {\n error: error instanceof Error ? error.message : String(error),\n })\n } finally {\n running = false\n }\n }\n\n const timer = setInterval(() => {\n void syncCronDeliveries()\n }, options.intervalMs ?? 30_000)\n timer.unref?.()\n\n return {\n close() {\n clearInterval(timer)\n },\n }\n}\n","export type SupportedLanguage = 'zh-CN' | 'en'\nexport type ConfiguredLanguage = SupportedLanguage | 'auto'\n\nconst messages = {\n en: {\n 'program.description': 'Hermes Link companion service',\n 'program.version': 'print Hermes Link version',\n 'status.description': 'Show local Hermes Link status',\n 'status.json': 'print machine-readable status',\n 'status.runtime': 'Runtime: {value}',\n 'status.mode': 'Mode: {value}',\n 'status.port': 'Local port: {value}',\n 'status.linkId': 'Link ID: {value}',\n 'status.notPaired': 'not paired',\n 'start.description': 'Start Hermes Link daemon',\n 'start.backgroundStarted': 'Hermes Link is running in the background. PID: {pid}',\n 'start.alreadyRunning': 'Hermes Link is already running. PID: {pid}',\n 'start.notPaired': 'Hermes Link is not paired yet. Starting in local-only maintenance mode.',\n 'start.notPaired.detail':\n 'Relay, Server polling, and LAN entrypoints stay disabled until you run `hermeslink pair`.',\n 'start.listening': 'Hermes Link API listening on http://127.0.0.1:{port}',\n 'start.relayConnecting': 'Relay control connecting for {linkId}',\n 'stop.description': 'Stop the background Hermes Link daemon',\n 'stop.stopped': 'Hermes Link stopped.',\n 'stop.notRunning': 'Hermes Link is not running.',\n 'restart.description': 'Restart the background Hermes Link daemon',\n 'daemon.description': 'Run Hermes Link in the foreground',\n 'daemon.foreground': 'Hermes Link foreground daemon is running. Press Ctrl+C to stop.',\n 'logs.description': 'Show Hermes Link log paths',\n 'logs.servicePath': 'Service log: {path}',\n 'logs.daemonPath': 'Daemon stdout/stderr log: {path}',\n 'autostart.description': 'Manage boot autostart',\n 'autostart.on.description': 'Enable boot autostart',\n 'autostart.off.description': 'Disable boot autostart',\n 'autostart.status.description': 'Show boot autostart status',\n 'autostart.enabled': 'Boot autostart enabled via {method}: {path}',\n 'autostart.disabled': 'Boot autostart disabled.',\n 'autostart.status.enabled': 'Boot autostart: enabled via {method}: {path}',\n 'autostart.status.disabled': 'Boot autostart: disabled. Method: {method}. File: {path}',\n 'autostart.unsupported': 'Boot autostart is not supported on this platform yet.',\n 'autostart.alreadyEnabled': 'Boot autostart is already enabled via {method}: {path}',\n 'pair.description': 'Create a Hermes Link pairing session',\n 'pair.preflight': 'Checking local Hermes configuration before pairing...',\n 'pair.hermesHome': 'Hermes home: {path}',\n 'pair.apiReady': 'Hermes API Server is ready on 127.0.0.1:{port}',\n 'pair.preparing': 'Preparing pairing session through HermesPilot Server and Relay...',\n 'pair.server': 'Server: {url}',\n 'pair.relay': 'Relay: {url}',\n 'pair.linkId': 'Hermes Link ID: {value}',\n 'pair.code': 'Pairing code: {value}',\n 'pair.localApi': 'Local API: http://127.0.0.1:{port}',\n 'pair.scan': 'Scan this QR code with the HermesPilot App:',\n 'pair.expires': 'Pairing expires in 10 minutes. Press Ctrl+C to cancel waiting.',\n 'pair.claimed': 'Pairing succeeded. Starting Hermes Link in the background...',\n 'pair.claimedRunning': 'Pairing succeeded. Hermes Link is already running in the background.',\n 'pair.autostartUnchanged': 'Existing paired devices found. Boot autostart settings were left unchanged.',\n 'pair.autostartFailed': 'Pairing succeeded, but boot autostart could not be enabled: {message}',\n 'doctor.description': 'Run local diagnostics',\n 'doctor.identityOk': 'Runtime identity: OK',\n 'doctor.installId': 'Install ID: {value}',\n 'doctor.linkId': 'Link ID: {value}',\n 'doctor.notAssigned': 'not assigned',\n 'doctor.apiReady': 'Hermes API Server: ready',\n 'doctor.apiStarted': 'Hermes API Server: started and ready',\n 'doctor.apiUnavailable': 'Hermes API Server: unavailable. {message}',\n 'error.relayPublicKeyMismatch':\n 'Relay rejected the pairing request because the Server-issued bootstrap token does not match this Link public key. Make sure Server and Relay are deployed with the same bootstrap key configuration, then run `hermeslink pair` again.',\n 'error.relayChallengeInvalid': 'Relay did not return a valid install challenge.',\n 'error.relayLinkInvalid': 'Relay did not return a valid link_id.',\n 'error.relayEmpty': 'Relay returned an empty response.',\n 'error.serverHttp': 'HermesPilot Server request failed with HTTP {status}.',\n 'error.portInUse':\n 'Local port {port} is already in use by another process. Stop that process or change the Hermes Link port, then run `hermeslink pair` again.',\n 'error.pairingRequires':\n 'Pairing needs HermesPilot Server and Relay, but this command could not start a complete pairing session.',\n 'error.pairingRequires.detail':\n 'The deployed services may be healthy, but the installed Link package must call Server for a short-lived relay bootstrap token before it can request a link_id.',\n },\n 'zh-CN': {\n 'program.description': 'Hermes Link 本地伴随服务',\n 'program.version': '输出 Hermes Link 版本号',\n 'status.description': '查看本机 Hermes Link 状态',\n 'status.json': '输出机器可读的状态 JSON',\n 'status.runtime': '运行目录:{value}',\n 'status.mode': '模式:{value}',\n 'status.port': '本地端口:{value}',\n 'status.linkId': 'Link ID:{value}',\n 'status.notPaired': '尚未配对',\n 'start.description': '启动 Hermes Link 服务',\n 'start.backgroundStarted': 'Hermes Link 已在后台运行。PID:{pid}',\n 'start.alreadyRunning': 'Hermes Link 已经在运行。PID:{pid}',\n 'start.notPaired': 'Hermes Link 还没有配对,将以本地维护模式启动。',\n 'start.notPaired.detail': '在你运行 `hermeslink pair` 前,Relay、Server 轮询和局域网入口都会保持关闭。',\n 'start.listening': 'Hermes Link API 正在监听 http://127.0.0.1:{port}',\n 'start.relayConnecting': '正在为 {linkId} 连接 Relay 控制通道',\n 'stop.description': '停止后台 Hermes Link 服务',\n 'stop.stopped': 'Hermes Link 已停止。',\n 'stop.notRunning': 'Hermes Link 没有在运行。',\n 'restart.description': '重启后台 Hermes Link 服务',\n 'daemon.description': '以前台方式运行 Hermes Link',\n 'daemon.foreground': 'Hermes Link 前台服务正在运行。按 Ctrl+C 停止。',\n 'logs.description': '显示 Hermes Link 日志路径',\n 'logs.servicePath': '服务日志:{path}',\n 'logs.daemonPath': 'Daemon 标准输出/错误日志:{path}',\n 'autostart.description': '管理开机自启',\n 'autostart.on.description': '启用开机自启',\n 'autostart.off.description': '关闭开机自启',\n 'autostart.status.description': '查看开机自启状态',\n 'autostart.enabled': '已启用开机自启,方式:{method},文件:{path}',\n 'autostart.disabled': '已关闭开机自启。',\n 'autostart.status.enabled': '开机自启:已启用,方式:{method},文件:{path}',\n 'autostart.status.disabled': '开机自启:未启用。方式:{method},文件:{path}',\n 'autostart.unsupported': '当前平台暂不支持开机自启。',\n 'autostart.alreadyEnabled': '开机自启已启用,方式:{method},文件:{path}',\n 'pair.description': '创建 Hermes Link 配对会话',\n 'pair.preflight': '正在配对前检查本机 Hermes 配置...',\n 'pair.hermesHome': 'Hermes 数据目录:{path}',\n 'pair.apiReady': 'Hermes API Server 已就绪:127.0.0.1:{port}',\n 'pair.preparing': '正在通过 HermesPilot Server 和 Relay 创建配对会话...',\n 'pair.server': 'Server:{url}',\n 'pair.relay': 'Relay:{url}',\n 'pair.linkId': 'Hermes Link ID:{value}',\n 'pair.code': '配对码:{value}',\n 'pair.localApi': '本地 API:http://127.0.0.1:{port}',\n 'pair.scan': '请使用 HermesPilot App 扫描这个二维码:',\n 'pair.expires': '配对会话 10 分钟后过期。按 Ctrl+C 退出等待。',\n 'pair.claimed': '配对已成功。正在把 Hermes Link 切换到后台运行...',\n 'pair.claimedRunning': '配对已成功。Hermes Link 已在后台持续运行。',\n 'pair.autostartUnchanged': '检测到已有配对设备,开机自启设置保持不变。',\n 'pair.autostartFailed': '配对已成功,但启用开机自启失败:{message}',\n 'doctor.description': '运行本机诊断',\n 'doctor.identityOk': '运行身份:正常',\n 'doctor.installId': 'Install ID:{value}',\n 'doctor.linkId': 'Link ID:{value}',\n 'doctor.notAssigned': '尚未分配',\n 'doctor.apiReady': 'Hermes API Server:已就绪',\n 'doctor.apiStarted': 'Hermes API Server:已自动启动并就绪',\n 'doctor.apiUnavailable': 'Hermes API Server:不可用。{message}',\n 'error.relayPublicKeyMismatch':\n 'Relay 拒绝了配对请求:Server 签发的 bootstrap token 与本机 Link 公钥不匹配。请确认 Server 和 Relay 使用同一套 bootstrap key 配置,然后重新运行 `hermeslink pair`。',\n 'error.relayChallengeInvalid': 'Relay 没有返回有效的安装挑战。',\n 'error.relayLinkInvalid': 'Relay 没有返回有效的 link_id。',\n 'error.relayEmpty': 'Relay 返回了空响应。',\n 'error.serverHttp': 'HermesPilot Server 请求失败,HTTP 状态码:{status}。',\n 'error.portInUse':\n '本地端口 {port} 已被其他进程占用。请先停止占用该端口的程序,或调整 Hermes Link 端口后重新运行 `hermeslink pair`。',\n 'error.pairingRequires': '配对需要 HermesPilot Server 和 Relay,但当前命令没有能启动完整配对会话。',\n 'error.pairingRequires.detail':\n '云端服务可以是已部署且健康的;本机 Link 仍必须先向 Server 申请短期 relay bootstrap token,才能再向 Relay 申请 link_id。',\n },\n} satisfies Record<SupportedLanguage, Record<string, string>>\n\nexport type MessageKey = keyof (typeof messages)['en']\n\nexport function detectSystemLanguage(env: NodeJS.ProcessEnv = process.env): SupportedLanguage {\n const candidates = [\n env.HERMESLINK_LANG,\n env.HERMESLINK_LANGUAGE,\n env.LC_ALL,\n env.LC_MESSAGES,\n env.LANG,\n env.LANGUAGE?.split(':')[0],\n Intl.DateTimeFormat().resolvedOptions().locale,\n ]\n for (const candidate of candidates) {\n const language = parseLanguage(candidate)\n if (language) {\n return language\n }\n }\n return 'en'\n}\n\nexport function resolveLanguage(setting?: ConfiguredLanguage | string | null): SupportedLanguage {\n const configured = parseLanguage(setting)\n if (configured) {\n return configured\n }\n return detectSystemLanguage()\n}\n\nexport function translate(\n language: SupportedLanguage,\n key: MessageKey,\n values: Record<string, string | number> = {},\n): string {\n const template = messages[language][key] ?? messages.en[key]\n return template.replace(/\\{(\\w+)\\}/gu, (_, name: string) => String(values[name] ?? ''))\n}\n\nexport function localizeErrorMessage(error: unknown, language: SupportedLanguage): string {\n const message = error instanceof Error ? error.message : String(error)\n if (language === 'en') {\n return message\n }\n const mapped = translateKnownError(message, language)\n return mapped ?? message\n}\n\nfunction translateKnownError(message: string, language: SupportedLanguage): string | null {\n if (message === 'Relay bootstrap token does not match public key') {\n return translate(language, 'error.relayPublicKeyMismatch')\n }\n if (message === 'Relay did not return a valid install challenge') {\n return translate(language, 'error.relayChallengeInvalid')\n }\n if (message === 'Relay did not return a valid link_id') {\n return translate(language, 'error.relayLinkInvalid')\n }\n if (message === 'Relay returned an empty response') {\n return translate(language, 'error.relayEmpty')\n }\n const portInUse = /^listen EADDRINUSE: address already in use .*:(?<port>\\d+)$/u.exec(message)\n if (portInUse?.groups?.port) {\n return translate(language, 'error.portInUse', { port: portInUse.groups.port })\n }\n const serverHttp = /^HermesPilot Server request failed with HTTP (?<status>\\d+)$/u.exec(message)\n if (serverHttp?.groups?.status) {\n return translate(language, 'error.serverHttp', { status: serverHttp.groups.status })\n }\n if (message.includes('Pairing requires HermesPilot Server and Relay')) {\n return [translate(language, 'error.pairingRequires'), translate(language, 'error.pairingRequires.detail')].join('\\n')\n }\n return null\n}\n\nfunction parseLanguage(value: string | null | undefined): SupportedLanguage | null {\n const normalized = value?.trim().replace('_', '-').toLowerCase()\n if (!normalized || normalized === 'auto' || normalized === 'c' || normalized === 'posix') {\n return null\n }\n if (normalized.startsWith('zh')) {\n return 'zh-CN'\n }\n if (normalized.startsWith('en')) {\n return 'en'\n }\n return null\n}\n","import { access, stat } from 'node:fs/promises'\nimport path from 'node:path'\nimport { LinkHttpError } from '../core/errors.js'\nimport {\n readHermesApiServerConfig,\n resolveHermesConfigPath,\n resolveHermesProfileDir,\n} from '../hermes/config.js'\nimport {\n ensureHermesApiServerAvailable,\n type EnsureHermesApiAvailableOptions,\n} from '../hermes/gateway.js'\nimport type { RuntimePaths } from '../runtime/paths.js'\n\nexport interface PairingPreflightResult {\n profileName: string\n hermesHome: string\n configPath: string\n envPath: string\n apiServer: {\n available: true\n started: boolean\n host: string | null\n port: number | null\n }\n}\n\nexport interface PairingPreflightOptions {\n profileName?: string\n paths?: RuntimePaths\n fetchImpl?: typeof fetch\n ensureApiServerAvailable?: (\n options: EnsureHermesApiAvailableOptions,\n ) => Promise<Awaited<ReturnType<typeof ensureHermesApiServerAvailable>>>\n}\n\nexport async function assertPairingPreflightReady(\n options: PairingPreflightOptions = {},\n): Promise<PairingPreflightResult> {\n const profileName = normalizeProfileName(options.profileName)\n const hermesHome = resolveHermesProfileDir(profileName)\n const configPath = resolveHermesConfigPath(profileName)\n const envPath = path.join(hermesHome, '.env')\n const failures: PairingPreflightFailure[] = []\n\n if (!(await isDirectory(hermesHome))) {\n failures.push({\n code: 'hermes_home_missing',\n zh: `没有找到当前 Hermes 数据目录:${hermesHome}`,\n en: `Current Hermes home was not found: ${hermesHome}`,\n actionZh:\n '请先运行 `hermes setup` 初始化 Hermes;如果 Hermes 在 Docker、WSL 或另一个 Windows 环境中运行,请在启动 Link 前设置 HERMES_HOME 指向 Link 能访问到的同一个目录。',\n actionEn:\n 'Run `hermes setup` first. If Hermes runs in Docker, WSL, or another Windows environment, start Link with HERMES_HOME pointing to the same directory that Link can access.',\n })\n }\n\n if (!(await isReadableFile(configPath))) {\n failures.push({\n code: 'hermes_config_missing',\n zh: `没有找到 Hermes 配置文件:${configPath}`,\n en: `Hermes config file was not found: ${configPath}`,\n actionZh:\n '请先运行 `hermes setup` 生成配置,或确认 Link 与 Hermes 使用的是同一个 HERMES_HOME。',\n actionEn:\n 'Run `hermes setup` to create the config, or make sure Link and Hermes use the same HERMES_HOME.',\n })\n }\n\n if (!(await isReadableFile(envPath))) {\n failures.push({\n code: 'hermes_env_missing',\n zh: `没有找到 Hermes 环境配置文件:${envPath}`,\n en: `Hermes environment file was not found: ${envPath}`,\n actionZh:\n '请先运行 `hermes setup` 创建 `.env` 并配置模型/API Key;Link 需要能读取它,才能复用 Hermes 的实际配置。',\n actionEn:\n 'Run `hermes setup` to create `.env` and configure model/API keys. Link must be able to read it to reuse Hermes settings.',\n })\n }\n\n if (failures.length > 0) {\n throwPairingPreflightError(failures)\n }\n\n const apiServerConfig = await readHermesApiServerConfig(profileName, configPath)\n if (apiServerConfig.enabled !== true) {\n throwPairingPreflightError([\n {\n code: 'hermes_api_server_disabled',\n zh: 'Hermes API Server 还没有开启。',\n en: 'Hermes API Server is not enabled.',\n actionZh:\n '请运行 `hermeslink doctor` 让 Link 自动补齐 API Server 配置,或在 Hermes 配置中启用 platforms.api_server。',\n actionEn:\n 'Run `hermeslink doctor` so Link can prepare the API Server config, or enable platforms.api_server in Hermes config.',\n },\n ])\n }\n\n try {\n const ensureAvailable =\n options.ensureApiServerAvailable ?? ensureHermesApiServerAvailable\n const availability = await ensureAvailable({\n paths: options.paths,\n profileName,\n fetchImpl: options.fetchImpl,\n timeoutMs: 5_000,\n autoStart: true,\n })\n return {\n profileName,\n hermesHome,\n configPath,\n envPath,\n apiServer: {\n available: true,\n started: availability.started,\n host: availability.configResult.apiServer.host ?? null,\n port: availability.configResult.apiServer.port ?? null,\n },\n }\n } catch (error) {\n throwPairingPreflightError([\n {\n code: 'hermes_api_server_unavailable',\n zh: 'Hermes API Server 当前不可用,Link 不能确认 App 配对后可以发送消息。',\n en: 'Hermes API Server is not available, so Link cannot confirm that the App will be able to send messages after pairing.',\n actionZh:\n '请先运行 `hermes gateway run --replace` 或 `hermeslink doctor`,确认 /health 可以访问后再重新执行 `hermeslink pair`。',\n actionEn:\n 'Run `hermes gateway run --replace` or `hermeslink doctor` first, then retry `hermeslink pair` after /health is reachable.',\n detail: error instanceof Error ? error.message : String(error),\n },\n ])\n }\n}\n\ninterface PairingPreflightFailure {\n code: string\n zh: string\n en: string\n actionZh: string\n actionEn: string\n detail?: string\n}\n\nfunction throwPairingPreflightError(failures: PairingPreflightFailure[]): never {\n throw new LinkHttpError(\n 503,\n failures[0]?.code ?? 'pairing_preflight_failed',\n formatPairingPreflightMessage(failures),\n )\n}\n\nfunction formatPairingPreflightMessage(failures: PairingPreflightFailure[]): string {\n const lines = [\n '配对前检查没有通过,暂时不会向 HermesPilot Server 或 Relay 申请配对二维码/配对码。',\n 'Pairing preflight failed. Link did not request a pairing QR code or pairing code from HermesPilot Server or Relay.',\n '',\n ]\n failures.forEach((failure, index) => {\n const prefix = failures.length > 1 ? `${index + 1}. ` : ''\n lines.push(`${prefix}${failure.zh}`)\n lines.push(` ${failure.en}`)\n lines.push(` 处理建议:${failure.actionZh}`)\n lines.push(` Suggested fix: ${failure.actionEn}`)\n if (failure.detail) {\n lines.push(` Detail: ${failure.detail}`)\n }\n })\n return lines.join('\\n')\n}\n\nasync function isDirectory(filePath: string): Promise<boolean> {\n return stat(filePath)\n .then((value) => value.isDirectory())\n .catch(() => false)\n}\n\nasync function isReadableFile(filePath: string): Promise<boolean> {\n return access(filePath)\n .then(() => stat(filePath))\n .then((value) => value.isFile())\n .catch(() => false)\n}\n\nfunction normalizeProfileName(profileName?: string): string {\n const value = profileName?.trim() || 'default'\n if (!/^[a-zA-Z0-9._-]{1,64}$/u.test(value)) {\n throw new LinkHttpError(\n 400,\n 'invalid_profile_name',\n 'invalid profile name',\n )\n }\n return value\n}\n"],"mappings":"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","names":["mkdir","readFile","rm","writeFile","path","mkdir","rm","mkdir","rm","mkdir","path","writeFile","rm","readFile","path","path","autostart"]}