appostle-installer 0.0.8 → 0.0.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/appostle-installer.js +25 -14
- package/dist/appostle-installer.js.map +2 -2
- package/dist/appostle.js +2179 -586
- package/dist/appostle.js.map +4 -4
- package/dist/worker.js +2549 -1127
- package/dist/worker.js.map +4 -4
- package/package.json +1 -1
|
@@ -105,7 +105,7 @@ async function installAppostleGlobal() {
|
|
|
105
105
|
async function installAutostart() {
|
|
106
106
|
const os = currentPlatform();
|
|
107
107
|
if (os === "darwin") return installLaunchd();
|
|
108
|
-
if (os === "linux") return
|
|
108
|
+
if (os === "linux") return installSystemdSystem();
|
|
109
109
|
if (os === "win32") return installWindowsStartup();
|
|
110
110
|
}
|
|
111
111
|
async function installLaunchd() {
|
|
@@ -171,12 +171,13 @@ async function writeAppostleConfig(osHome) {
|
|
|
171
171
|
await fs.mkdir(configDir, { recursive: true });
|
|
172
172
|
await fs.writeFile(configPath, JSON.stringify(config, null, 2));
|
|
173
173
|
}
|
|
174
|
-
async function
|
|
174
|
+
async function installSystemdSystem() {
|
|
175
175
|
const fs = await import("node:fs/promises");
|
|
176
176
|
const path = await import("node:path");
|
|
177
|
+
const os = await import("node:os");
|
|
177
178
|
const osHome = (await import("node:os")).homedir();
|
|
178
|
-
const
|
|
179
|
-
const unitPath =
|
|
179
|
+
const user = os.userInfo().username;
|
|
180
|
+
const unitPath = "/etc/systemd/system/appostle.service";
|
|
180
181
|
const appostleBin = await resolveBinary("appostle") ?? "/usr/bin/appostle";
|
|
181
182
|
const logPath = path.join(osHome, ".local", "state", "appostle", "daemon.log");
|
|
182
183
|
const unit = `[Unit]
|
|
@@ -185,6 +186,7 @@ After=network.target
|
|
|
185
186
|
|
|
186
187
|
[Service]
|
|
187
188
|
Type=simple
|
|
189
|
+
User=${user}
|
|
188
190
|
ExecStart=${appostleBin} daemon start --foreground
|
|
189
191
|
Restart=on-failure
|
|
190
192
|
RestartSec=10
|
|
@@ -195,14 +197,28 @@ StandardOutput=append:${logPath}
|
|
|
195
197
|
StandardError=append:${logPath}
|
|
196
198
|
|
|
197
199
|
[Install]
|
|
198
|
-
WantedBy=
|
|
200
|
+
WantedBy=multi-user.target
|
|
199
201
|
`;
|
|
200
|
-
await fs.mkdir(unitDir, { recursive: true });
|
|
201
202
|
await fs.mkdir(path.dirname(logPath), { recursive: true });
|
|
202
|
-
|
|
203
|
+
const tempUnitPath = path.join(osHome, ".appostle", "appostle.service");
|
|
204
|
+
await fs.mkdir(path.dirname(tempUnitPath), { recursive: true });
|
|
205
|
+
await fs.writeFile(tempUnitPath, unit);
|
|
203
206
|
await writeAppostleConfig(osHome);
|
|
204
|
-
await runInteractive("systemctl", ["--user", "
|
|
205
|
-
|
|
207
|
+
await runInteractive("systemctl", ["--user", "disable", "--now", "appostle.service"], {
|
|
208
|
+
reject: false,
|
|
209
|
+
stdio: "ignore"
|
|
210
|
+
});
|
|
211
|
+
await runInteractive(
|
|
212
|
+
"sudo",
|
|
213
|
+
["rm", "-f", path.join(osHome, ".config", "systemd", "user", "appostle.service")],
|
|
214
|
+
{
|
|
215
|
+
reject: false,
|
|
216
|
+
stdio: "ignore"
|
|
217
|
+
}
|
|
218
|
+
);
|
|
219
|
+
await runInteractive("sudo", ["cp", tempUnitPath, unitPath]);
|
|
220
|
+
await runInteractive("sudo", ["systemctl", "daemon-reload"]);
|
|
221
|
+
await runInteractive("sudo", ["systemctl", "enable", "--now", "appostle.service"]);
|
|
206
222
|
}
|
|
207
223
|
async function installWindowsStartup() {
|
|
208
224
|
const fs = await import("node:fs/promises");
|
|
@@ -495,11 +511,6 @@ async function main() {
|
|
|
495
511
|
s.start(`Configuring auto-start (${os})\u2026`);
|
|
496
512
|
await installAutostart();
|
|
497
513
|
s.stop("Auto-start configured");
|
|
498
|
-
if (os === "linux") {
|
|
499
|
-
log.info(
|
|
500
|
-
"Tip: run `loginctl enable-linger $USER` if you want the daemon to stay up when you're logged out."
|
|
501
|
-
);
|
|
502
|
-
}
|
|
503
514
|
if (!yes) {
|
|
504
515
|
note(`Paste the pairing link below into ${APPOSTLE_WEB_URL} (or scan the QR).`, "Pair");
|
|
505
516
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/config.ts", "../src/index.ts", "../src/daemon-setup.ts", "../src/util.ts", "../src/providers.ts"],
|
|
4
|
-
"sourcesContent": ["// -----------------------------------------------------------------------------\n// Appostle infrastructure endpoints. These get baked into the daemon's\n// environment so every installed daemon connects to the same relay and the\n// user's pairing link resolves at the shared web UI.\n// -----------------------------------------------------------------------------\n\nexport const APPOSTLE_RELAY_ENDPOINT = \"pair.appostle.app:443\";\nexport const APPOSTLE_WEB_URL = \"https://appostle.app\";\n\n// The single npm package that ships the daemon, the appostle CLI, and the\n// installer flow. `--update` reinstalls this package globally so users get\n// both the new installer and the new daemon in one shot.\nexport const INSTALLER_PACKAGE = \"appostle-installer\";\n", "import {\n cancel,\n confirm,\n intro,\n isCancel,\n log,\n multiselect,\n note,\n outro,\n spinner,\n} from \"@clack/prompts\";\nimport chalk from \"chalk\";\nimport { APPOSTLE_WEB_URL } from \"./config.js\";\nimport { installAutostart, installAppostleGlobal, printPairingLink } from \"./daemon-setup.js\";\nimport { PROVIDERS, type ProviderSpec } from \"./providers.js\";\nimport { currentPlatform, has } from \"./util.js\";\nimport { execa } from \"execa\";\nimport { createRequire } from \"node:module\";\n\n// -----------------------------------------------------------------------------\n// CLI flags\n// --yes Skip all interactive prompts; install daemon only\n// --providers=a,b,c Comma-separated provider ids to install (no auth)\n// --no-auth Skip auth even when providers are selected\n// --update Non-interactive: only refresh the daemon to the\n// latest @appostle/cli, re-apply auto-start (which\n// restarts the running service), and exit. Skips\n// provider selection, auth, and pairing link.\n// Suitable for cron / unattended upgrades.\n// --pair Print a fresh pairing link/QR for the local daemon\n// and exit. No installs, no service changes. Useful\n// when you've already paired but need the link again\n// on a new device or in a new browser profile.\n// -----------------------------------------------------------------------------\nfunction parseArgs(): {\n yes: boolean;\n providerIds: string[];\n noAuth: boolean;\n update: boolean;\n pair: boolean;\n} {\n const args = process.argv.slice(2);\n const yes = args.includes(\"--yes\") || args.includes(\"-y\");\n const noAuth = args.includes(\"--no-auth\");\n const update = args.includes(\"--update\");\n const pair = args.includes(\"--pair\");\n const providersArg = args.find((a) => a.startsWith(\"--providers=\"));\n const providerIds = providersArg\n ? providersArg\n .replace(\"--providers=\", \"\")\n .split(\",\")\n .map((s) => s.trim())\n .filter(Boolean)\n : [];\n return { yes, providerIds, noAuth, update, pair };\n}\n\nasync function shouldReinstallInstallerPackage(): Promise<boolean> {\n const require = createRequire(import.meta.url);\n const packageVersion = (require(\"../package.json\") as { version?: string } | undefined)?.version;\n if (!packageVersion) return true;\n try {\n const { stdout } = await execa(\"npm\", [\"view\", \"appostle-installer\", \"dist-tags.latest\"]);\n const latest = stdout.trim();\n if (!latest) return true;\n return latest !== packageVersion;\n } catch {\n // If version lookup fails (offline / transient npm failure), keep the\n // previous behavior and attempt install.\n return true;\n }\n}\n\nasync function main(): Promise<void> {\n const { yes, providerIds, noAuth, update, pair } = parseArgs();\n\n intro(\n chalk.magentaBright(\"Appostle\") +\n chalk.dim(pair ? \" \u2014 pairing link\" : update ? \" \u2014 daemon updater\" : \" \u2014 daemon installer\"),\n );\n\n const os = currentPlatform();\n log.info(`Detected OS: ${os}`);\n\n // ---------------------------------------------------------------------\n // Preflight: node + npm must be present.\n // ---------------------------------------------------------------------\n if (!(await has(\"npm\"))) {\n log.error(\"`npm` not found on PATH. Install Node.js from https://nodejs.org and re-run.\");\n process.exit(1);\n }\n\n // ---------------------------------------------------------------------\n // --pair fast-path: print a fresh pairing link/QR for the local daemon\n // and exit. No installs, no prompts. Useful when re-pairing on a new\n // device or in a fresh browser profile.\n // ---------------------------------------------------------------------\n if (pair) {\n note(`Paste the pairing link below into ${APPOSTLE_WEB_URL} (or scan the QR).`, \"Pair\");\n try {\n await printPairingLink();\n } catch (err) {\n log.error(`Could not generate pairing link: ${(err as Error).message}`);\n log.info(\"Is the daemon installed? If not, run `npx appostle-installer` first.\");\n process.exit(1);\n }\n outro(chalk.green(\"Done.\"));\n return;\n }\n\n // ---------------------------------------------------------------------\n // --update fast-path: pull the latest @appostle/cli, re-apply auto-start\n // (which restarts the running daemon), and exit. No prompts, no providers,\n // no pairing link. Designed for unattended / scripted upgrades.\n // ---------------------------------------------------------------------\n if (update) {\n const us = spinner();\n us.start(\"Updating Appostle (npm install -g appostle-installer@latest)\u2026\");\n try {\n await installAppostleGlobal();\n us.stop(\"Daemon package up to date\");\n } catch (err) {\n us.stop(\"Daemon update failed\");\n log.error((err as Error).message);\n process.exit(1);\n }\n\n us.start(`Re-applying auto-start (${os}) to restart service\u2026`);\n try {\n await installAutostart();\n us.stop(\"Auto-start refreshed; service restarted\");\n } catch (err) {\n us.stop(\"Auto-start refresh failed\");\n log.error((err as Error).message);\n process.exit(1);\n }\n\n outro(chalk.green(\"Update complete.\"));\n return;\n }\n\n // ---------------------------------------------------------------------\n // 1. Pick agent CLIs\n // ---------------------------------------------------------------------\n let chosen: ProviderSpec[] = [];\n\n if (yes && providerIds.length === 0) {\n // --yes with no --providers: skip provider installs entirely\n log.info(\"--yes: skipping provider selection\");\n } else if (providerIds.length > 0) {\n chosen = PROVIDERS.filter((p) => providerIds.includes(p.id));\n const unknown = providerIds.filter((id) => !PROVIDERS.find((p) => p.id === id));\n if (unknown.length > 0) log.warn(`Unknown provider ids ignored: ${unknown.join(\", \")}`);\n log.info(`Providers to install: ${chosen.map((p) => p.label).join(\", \")}`);\n } else {\n const selection = await multiselect({\n message: \"Which agent CLIs do you want installed?\",\n required: false,\n options: PROVIDERS.map((p) => ({\n value: p.id,\n label: p.label,\n hint: p.description,\n })),\n });\n if (isCancel(selection)) {\n cancel(\"Cancelled.\");\n process.exit(0);\n }\n chosen = PROVIDERS.filter((p) => (selection as string[]).includes(p.id));\n }\n\n // ---------------------------------------------------------------------\n // 2. Install + auth each chosen provider\n // ---------------------------------------------------------------------\n for (const provider of chosen) {\n const s = spinner();\n s.start(`Checking ${provider.label}\u2026`);\n const alreadyInstalled = await provider.detect();\n s.stop(\n alreadyInstalled\n ? `${provider.label} already installed`\n : `${provider.label} not found \u2014 installing`,\n );\n\n if (!alreadyInstalled) {\n try {\n await provider.install();\n } catch (err) {\n log.error(`${provider.label} install failed: ${(err as Error).message}`);\n if (yes || noAuth) {\n log.warn(`Skipping ${provider.label} due to --yes/--no-auth`);\n continue;\n }\n const keepGoing = await confirm({\n message: `Skip ${provider.label} and continue?`,\n initialValue: true,\n });\n if (isCancel(keepGoing) || !keepGoing) {\n cancel(\"Aborting.\");\n process.exit(1);\n }\n continue;\n }\n }\n\n if (yes || noAuth) {\n log.info(`Skipping ${provider.label} auth (--no-auth / --yes)`);\n continue;\n }\n\n const doAuth = await confirm({\n message: `Authenticate ${provider.label} now?`,\n initialValue: true,\n });\n if (isCancel(doAuth)) {\n cancel(\"Cancelled.\");\n process.exit(0);\n }\n if (doAuth) {\n try {\n await provider.auth();\n } catch (err) {\n log.warn(\n `${provider.label} auth returned non-zero \u2014 retry later with its own CLI. (${(err as Error).message})`,\n );\n }\n } else {\n log.info(`Skipping ${provider.label} auth \u2014 you can run it later.`);\n }\n }\n\n // ---------------------------------------------------------------------\n // 3. Install the Appostle daemon\n // ---------------------------------------------------------------------\n if (!yes) {\n note(\n \"Installing Appostle globally (daemon + appostle CLI ship in the same package).\",\n \"Daemon\",\n );\n const proceed = await confirm({ message: \"Continue?\", initialValue: true });\n if (isCancel(proceed) || !proceed) {\n cancel(\"Stopped before daemon install. Re-run any time.\");\n process.exit(0);\n }\n }\n\n const s = spinner();\n s.start(\"Installing daemon (npm install -g appostle-installer)\u2026\");\n try {\n if (await shouldReinstallInstallerPackage()) {\n await installAppostleGlobal();\n s.stop(\"Daemon + appostle CLI installed\");\n } else {\n s.stop(\"Daemon package already at latest; skipping reinstall\");\n }\n } catch (err) {\n s.stop(\"Install failed\");\n log.error((err as Error).message);\n process.exit(1);\n }\n\n // ---------------------------------------------------------------------\n // 4. Auto-start service\n // ---------------------------------------------------------------------\n s.start(`Configuring auto-start (${os})\u2026`);\n await installAutostart();\n s.stop(\"Auto-start configured\");\n\n if (os === \"linux\") {\n log.info(\n \"Tip: run `loginctl enable-linger $USER` if you want the daemon to stay up when you're logged out.\",\n );\n }\n\n // ---------------------------------------------------------------------\n // 5. Pairing link\n // ---------------------------------------------------------------------\n if (!yes) {\n note(`Paste the pairing link below into ${APPOSTLE_WEB_URL} (or scan the QR).`, \"Pair\");\n }\n await printPairingLink();\n\n outro(chalk.green(`Done. Open ${APPOSTLE_WEB_URL}`));\n}\n\nmain().catch((err: unknown) => {\n console.error(chalk.red(\"\\nInstaller failed:\"), err);\n process.exit(1);\n});\n", "import { APPOSTLE_RELAY_ENDPOINT, APPOSTLE_WEB_URL, INSTALLER_PACKAGE } from \"./config.js\";\nimport { currentPlatform, npmInstallGlobal, resolveBinary, runInteractive } from \"./util.js\";\n\n// -----------------------------------------------------------------------------\n// Install appostle-installer globally so both `appostle-installer` and the\n// `appostle` daemon/CLI binary land on PATH (npx alone caches a single tarball\n// invocation; that's fine for the install flow but launchd/systemd need a\n// stable absolute path to `appostle`).\n// -----------------------------------------------------------------------------\nexport async function installAppostleGlobal(): Promise<void> {\n await npmInstallGlobal([`${INSTALLER_PACKAGE}@latest`]);\n}\n\n// -----------------------------------------------------------------------------\n// Auto-start configuration. Writes an OS-specific launcher with the relay\n// endpoint baked in, so the daemon connects to Appostle on boot.\n// -----------------------------------------------------------------------------\nexport async function installAutostart(): Promise<void> {\n const os = currentPlatform();\n if (os === \"darwin\") return installLaunchd();\n if (os === \"linux\") return installSystemdUser();\n if (os === \"win32\") return installWindowsStartup();\n}\n\nasync function installLaunchd(): Promise<void> {\n const fs = await import(\"node:fs/promises\");\n const path = await import(\"node:path\");\n const osHome = (await import(\"node:os\")).homedir();\n\n const plistPath = path.join(osHome, \"Library\", \"LaunchAgents\", \"agency.ohlord.appostle.plist\");\n const logPath = path.join(osHome, \"Library\", \"Logs\", \"appostle.log\");\n const appostleBin = (await resolveBinary(\"appostle\")) ?? \"/usr/local/bin/appostle\";\n\n const plist = `<?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><string>agency.ohlord.appostle</string>\n <key>ProgramArguments</key>\n <array>\n <string>${appostleBin}</string>\n <string>daemon</string>\n <string>start</string>\n <string>--foreground</string>\n </array>\n <key>RunAtLoad</key><true/>\n <key>KeepAlive</key><true/>\n <key>StandardOutPath</key><string>${logPath}</string>\n <key>StandardErrorPath</key><string>${logPath}</string>\n <key>EnvironmentVariables</key>\n <dict>\n <key>PATH</key><string>/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin</string>\n <key>HOME</key><string>${osHome}</string>\n <key>NODE_ENV</key><string>production</string>\n <key>APPOSTLE_RELAY_ENDPOINT</key><string>${APPOSTLE_RELAY_ENDPOINT}</string>\n </dict>\n</dict>\n</plist>\n`;\n await fs.mkdir(path.dirname(plistPath), { recursive: true });\n await fs.writeFile(plistPath, plist);\n await writeAppostleConfig(osHome);\n\n try {\n await runInteractive(\"launchctl\", [\"unload\", plistPath], { stdio: \"ignore\" });\n } catch {\n /* not loaded yet */\n }\n await runInteractive(\"launchctl\", [\"load\", plistPath]);\n}\n\nasync function writeAppostleConfig(osHome: string): Promise<void> {\n const fs = await import(\"node:fs/promises\");\n const path = await import(\"node:path\");\n const configDir = path.join(osHome, \".appostle\");\n const configPath = path.join(configDir, \"config.json\");\n // Default-disable local speech features. They auto-download ML model\n // weights (~800 MB) from third-party sources and load them with\n // onnxruntime-node \u2014 supply-chain risk we don't want on by default in a\n // self-hosted daemon. Users who want voice/dictation locally can flip\n // these flags later and run `appostle speech download --model <id>`.\n const config = {\n version: 1,\n daemon: {\n listen: \"127.0.0.1:6767\",\n cors: { allowedOrigins: [APPOSTLE_WEB_URL] },\n relay: { enabled: true, endpoint: APPOSTLE_RELAY_ENDPOINT },\n },\n app: { baseUrl: APPOSTLE_WEB_URL },\n features: {\n dictation: { enabled: false },\n voiceMode: { enabled: false },\n },\n };\n await fs.mkdir(configDir, { recursive: true });\n await fs.writeFile(configPath, JSON.stringify(config, null, 2));\n}\n\n// Requires `loginctl enable-linger $USER` if the daemon should stay up\n// when nobody is logged in \u2014 otherwise it runs during your session only.\nasync function installSystemdUser(): Promise<void> {\n const fs = await import(\"node:fs/promises\");\n const path = await import(\"node:path\");\n const osHome = (await import(\"node:os\")).homedir();\n\n const unitDir = path.join(osHome, \".config\", \"systemd\", \"user\");\n const unitPath = path.join(unitDir, \"appostle.service\");\n const appostleBin = (await resolveBinary(\"appostle\")) ?? \"/usr/bin/appostle\";\n const logPath = path.join(osHome, \".local\", \"state\", \"appostle\", \"daemon.log\");\n\n const unit = `[Unit]\nDescription=Appostle Daemon\nAfter=network.target\n\n[Service]\nType=simple\nExecStart=${appostleBin} daemon start --foreground\nRestart=on-failure\nRestartSec=10\nEnvironment=NODE_ENV=production\nEnvironment=HOME=${osHome}\nEnvironment=APPOSTLE_RELAY_ENDPOINT=${APPOSTLE_RELAY_ENDPOINT}\nStandardOutput=append:${logPath}\nStandardError=append:${logPath}\n\n[Install]\nWantedBy=default.target\n`;\n\n await fs.mkdir(unitDir, { recursive: true });\n await fs.mkdir(path.dirname(logPath), { recursive: true });\n await fs.writeFile(unitPath, unit);\n await writeAppostleConfig(osHome);\n\n await runInteractive(\"systemctl\", [\"--user\", \"daemon-reload\"]);\n await runInteractive(\"systemctl\", [\"--user\", \"enable\", \"--now\", \"appostle.service\"]);\n}\n\nasync function installWindowsStartup(): Promise<void> {\n const fs = await import(\"node:fs/promises\");\n const path = await import(\"node:path\");\n const osHome = (await import(\"node:os\")).homedir();\n\n const appostleBin = (await resolveBinary(\"appostle\")) ?? \"appostle.cmd\";\n const logDir = path.join(osHome, \"AppData\", \"Local\", \"Appostle\");\n const logPath = path.join(logDir, \"daemon.log\");\n\n const batPath = path.join(logDir, \"appostle-daemon.bat\");\n const vbsPath = path.join(\n osHome,\n \"AppData\",\n \"Roaming\",\n \"Microsoft\",\n \"Windows\",\n \"Start Menu\",\n \"Programs\",\n \"Startup\",\n \"appostle.vbs\",\n );\n\n const bat = `@echo off\nset NODE_ENV=production\nset APPOSTLE_RELAY_ENDPOINT=${APPOSTLE_RELAY_ENDPOINT}\n\"${appostleBin}\" daemon start --foreground >> \"${logPath}\" 2>&1\n`;\n\n const vbs = `Set WshShell = CreateObject(\"WScript.Shell\")\nWshShell.Run \"\"\"${batPath}\"\"\", 0, False\n`;\n\n await fs.mkdir(logDir, { recursive: true });\n await fs.mkdir(path.dirname(vbsPath), { recursive: true });\n await fs.writeFile(batPath, bat);\n await fs.writeFile(vbsPath, vbs);\n await writeAppostleConfig(osHome);\n\n // Also kick it off now so we don't wait for next login.\n await runInteractive(\"wscript\", [vbsPath]);\n}\n\n// -----------------------------------------------------------------------------\n// Emit pairing link. `appostle daemon pair` prints a QR + URL.\n// -----------------------------------------------------------------------------\nexport async function printPairingLink(): Promise<void> {\n const { execa } = await import(\"execa\");\n const { APPOSTLE_WEB_URL } = await import(\"./config.js\");\n\n const result = await execa(\"appostle\", [\"daemon\", \"pair\"], { reject: false });\n const raw =\n (typeof result.stdout === \"string\" ? result.stdout : \"\") +\n (typeof result.stderr === \"string\" ? result.stderr : \"\");\n // Rewrite any origin to our web UI.\n const rewritten = raw.replace(/https?:\\/\\/[^/]+\\/#offer=/g, `${APPOSTLE_WEB_URL}/#offer=`);\n process.stdout.write(rewritten);\n}\n", "import { execa, type Options as ExecaOptions } from \"execa\";\nimport { accessSync, constants } from \"node:fs\";\nimport { platform } from \"node:os\";\nimport which from \"which\";\n\nexport type Platform = \"darwin\" | \"linux\" | \"win32\";\n\nexport function currentPlatform(): Platform {\n const p = platform();\n if (p === \"darwin\" || p === \"linux\" || p === \"win32\") return p;\n throw new Error(`Unsupported platform: ${p}`);\n}\n\n/** True if the given binary resolves on PATH (cross-platform). */\nexport async function has(binary: string): Promise<boolean> {\n try {\n await which(binary);\n return true;\n } catch {\n return false;\n }\n}\n\n/** Absolute path to a binary on PATH, or null. */\nexport async function resolveBinary(binary: string): Promise<string | null> {\n try {\n return await which(binary);\n } catch {\n return null;\n }\n}\n\n/** Run with inherited stdio so the user sees OAuth / password prompts. */\nexport async function runInteractive(\n command: string,\n args: string[] = [],\n options: ExecaOptions = {},\n): Promise<void> {\n await execa(command, args, { stdio: \"inherit\", ...options });\n}\n\nlet cachedNeedsSudo: boolean | null = null;\n\n/**\n * Returns true when `npm install -g` would fail with EACCES because npm's global\n * prefix is owned by root (typical on Debian/Ubuntu/etc with system Node) and we\n * are not root.\n *\n * macOS Homebrew installs npm to a user-writable prefix, so we don't need sudo\n * there. Windows manages globals per-user too. We only need this dance on\n * Linux/Unix when running as a non-root user against a root-owned prefix.\n */\nexport async function npmGlobalNeedsSudo(): Promise<boolean> {\n if (cachedNeedsSudo !== null) return cachedNeedsSudo;\n if (currentPlatform() === \"win32\") return (cachedNeedsSudo = false);\n if (process.getuid?.() === 0) return (cachedNeedsSudo = false);\n\n try {\n const { stdout } = await execa(\"npm\", [\"prefix\", \"-g\"]);\n const prefix = stdout.trim();\n if (!prefix) return (cachedNeedsSudo = false);\n accessSync(prefix, constants.W_OK);\n return (cachedNeedsSudo = false);\n } catch {\n return (cachedNeedsSudo = true);\n }\n}\n\n/**\n * Install one or more npm packages globally. Transparently uses `sudo` when the\n * npm global prefix isn't writable by the current user (e.g. system Node on\n * Linux). Sudo will prompt for password on first call only \u2014 subsequent calls\n * inherit the timestamp cache.\n */\nexport async function npmInstallGlobal(packages: string[]): Promise<void> {\n const useSudo = await npmGlobalNeedsSudo();\n const args = [\"install\", \"-g\", ...packages];\n if (useSudo) {\n await runInteractive(\"sudo\", [\"-E\", \"npm\", ...args]);\n } else {\n await runInteractive(\"npm\", args);\n }\n}\n", "import { has, npmInstallGlobal, runInteractive } from \"./util.js\";\n\nexport interface ProviderSpec {\n /** Stable id; matches the daemon's AGENT_PROVIDER_DEFINITIONS. */\n id: \"claude\" | \"codex\" | \"copilot\" | \"opencode\" | \"pi\";\n label: string;\n description: string;\n\n /** Is the provider's CLI already installed + reachable? */\n detect(): Promise<boolean>;\n\n /** Install the CLI. Should be idempotent. */\n install(): Promise<void>;\n\n /** Walk the user through the provider's native auth flow. */\n auth(): Promise<void>;\n}\n\n// Each provider installs its own CLI from its own public source. We don't\n// abstract their auth flows \u2014 we just invoke them and let the user complete\n// the native OAuth / key-paste prompt.\n\nconst claude: ProviderSpec = {\n id: \"claude\",\n label: \"Claude Code\",\n description: \"Anthropic's agent CLI (MCP, streaming, deep reasoning)\",\n async detect() {\n return has(\"claude\");\n },\n async install() {\n await npmInstallGlobal([\"@anthropic-ai/claude-code@latest\"]);\n },\n async auth() {\n await runInteractive(\"claude\", [\"/login\"]);\n },\n};\n\nconst codex: ProviderSpec = {\n id: \"codex\",\n label: \"Codex\",\n description: \"OpenAI's Codex workspace agent\",\n async detect() {\n return has(\"codex\");\n },\n async install() {\n await npmInstallGlobal([\"@openai/codex@latest\"]);\n },\n async auth() {\n await runInteractive(\"codex\", [\"login\"]);\n },\n};\n\nconst copilot: ProviderSpec = {\n id: \"copilot\",\n label: \"GitHub Copilot\",\n description: \"Standalone Copilot CLI with ACP support\",\n async detect() {\n return has(\"copilot\");\n },\n async install() {\n await npmInstallGlobal([\"@github/copilot@latest\"]);\n },\n async auth() {\n await runInteractive(\"copilot\", [\"auth\", \"login\"]);\n },\n};\n\nconst opencode: ProviderSpec = {\n id: \"opencode\",\n label: \"OpenCode\",\n description: \"Open-source multi-provider coding assistant\",\n async detect() {\n return has(\"opencode\");\n },\n async install() {\n await npmInstallGlobal([\"opencode-ai@latest\"]);\n },\n async auth() {\n await runInteractive(\"opencode\", [\"auth\", \"login\"]);\n },\n};\n\nconst pi: ProviderSpec = {\n id: \"pi\",\n label: \"Pi\",\n description: \"Minimal terminal-based agent with multi-provider LLM support\",\n async detect() {\n return has(\"pi\");\n },\n async install() {\n await npmInstallGlobal([\"@mariozechner/pi-coding-agent@latest\"]);\n },\n async auth() {\n await runInteractive(\"pi\", [\"login\"]);\n },\n};\n\nexport const PROVIDERS: ProviderSpec[] = [claude, codex, copilot, opencode, pi];\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["// -----------------------------------------------------------------------------\n// Appostle infrastructure endpoints. These get baked into the daemon's\n// environment so every installed daemon connects to the same relay and the\n// user's pairing link resolves at the shared web UI.\n// -----------------------------------------------------------------------------\n\nexport const APPOSTLE_RELAY_ENDPOINT = \"pair.appostle.app:443\";\nexport const APPOSTLE_WEB_URL = \"https://appostle.app\";\n\n// The single npm package that ships the daemon, the appostle CLI, and the\n// installer flow. `--update` reinstalls this package globally so users get\n// both the new installer and the new daemon in one shot.\nexport const INSTALLER_PACKAGE = \"appostle-installer\";\n", "import {\n cancel,\n confirm,\n intro,\n isCancel,\n log,\n multiselect,\n note,\n outro,\n spinner,\n} from \"@clack/prompts\";\nimport chalk from \"chalk\";\nimport { APPOSTLE_WEB_URL } from \"./config.js\";\nimport { installAutostart, installAppostleGlobal, printPairingLink } from \"./daemon-setup.js\";\nimport { PROVIDERS, type ProviderSpec } from \"./providers.js\";\nimport { currentPlatform, has } from \"./util.js\";\nimport { execa } from \"execa\";\nimport { createRequire } from \"node:module\";\n\n// -----------------------------------------------------------------------------\n// CLI flags\n// --yes Skip all interactive prompts; install daemon only\n// --providers=a,b,c Comma-separated provider ids to install (no auth)\n// --no-auth Skip auth even when providers are selected\n// --update Non-interactive: only refresh the daemon to the\n// latest @appostle/cli, re-apply auto-start (which\n// restarts the running service), and exit. Skips\n// provider selection, auth, and pairing link.\n// Suitable for cron / unattended upgrades.\n// --pair Print a fresh pairing link/QR for the local daemon\n// and exit. No installs, no service changes. Useful\n// when you've already paired but need the link again\n// on a new device or in a new browser profile.\n// -----------------------------------------------------------------------------\nfunction parseArgs(): {\n yes: boolean;\n providerIds: string[];\n noAuth: boolean;\n update: boolean;\n pair: boolean;\n} {\n const args = process.argv.slice(2);\n const yes = args.includes(\"--yes\") || args.includes(\"-y\");\n const noAuth = args.includes(\"--no-auth\");\n const update = args.includes(\"--update\");\n const pair = args.includes(\"--pair\");\n const providersArg = args.find((a) => a.startsWith(\"--providers=\"));\n const providerIds = providersArg\n ? providersArg\n .replace(\"--providers=\", \"\")\n .split(\",\")\n .map((s) => s.trim())\n .filter(Boolean)\n : [];\n return { yes, providerIds, noAuth, update, pair };\n}\n\nasync function shouldReinstallInstallerPackage(): Promise<boolean> {\n const require = createRequire(import.meta.url);\n const packageVersion = (require(\"../package.json\") as { version?: string } | undefined)?.version;\n if (!packageVersion) return true;\n try {\n const { stdout } = await execa(\"npm\", [\"view\", \"appostle-installer\", \"dist-tags.latest\"]);\n const latest = stdout.trim();\n if (!latest) return true;\n return latest !== packageVersion;\n } catch {\n // If version lookup fails (offline / transient npm failure), keep the\n // previous behavior and attempt install.\n return true;\n }\n}\n\nasync function main(): Promise<void> {\n const { yes, providerIds, noAuth, update, pair } = parseArgs();\n\n intro(\n chalk.magentaBright(\"Appostle\") +\n chalk.dim(pair ? \" \u2014 pairing link\" : update ? \" \u2014 daemon updater\" : \" \u2014 daemon installer\"),\n );\n\n const os = currentPlatform();\n log.info(`Detected OS: ${os}`);\n\n // ---------------------------------------------------------------------\n // Preflight: node + npm must be present.\n // ---------------------------------------------------------------------\n if (!(await has(\"npm\"))) {\n log.error(\"`npm` not found on PATH. Install Node.js from https://nodejs.org and re-run.\");\n process.exit(1);\n }\n\n // ---------------------------------------------------------------------\n // --pair fast-path: print a fresh pairing link/QR for the local daemon\n // and exit. No installs, no prompts. Useful when re-pairing on a new\n // device or in a fresh browser profile.\n // ---------------------------------------------------------------------\n if (pair) {\n note(`Paste the pairing link below into ${APPOSTLE_WEB_URL} (or scan the QR).`, \"Pair\");\n try {\n await printPairingLink();\n } catch (err) {\n log.error(`Could not generate pairing link: ${(err as Error).message}`);\n log.info(\"Is the daemon installed? If not, run `npx appostle-installer` first.\");\n process.exit(1);\n }\n outro(chalk.green(\"Done.\"));\n return;\n }\n\n // ---------------------------------------------------------------------\n // --update fast-path: pull the latest @appostle/cli, re-apply auto-start\n // (which restarts the running daemon), and exit. No prompts, no providers,\n // no pairing link. Designed for unattended / scripted upgrades.\n // ---------------------------------------------------------------------\n if (update) {\n const us = spinner();\n us.start(\"Updating Appostle (npm install -g appostle-installer@latest)\u2026\");\n try {\n await installAppostleGlobal();\n us.stop(\"Daemon package up to date\");\n } catch (err) {\n us.stop(\"Daemon update failed\");\n log.error((err as Error).message);\n process.exit(1);\n }\n\n us.start(`Re-applying auto-start (${os}) to restart service\u2026`);\n try {\n await installAutostart();\n us.stop(\"Auto-start refreshed; service restarted\");\n } catch (err) {\n us.stop(\"Auto-start refresh failed\");\n log.error((err as Error).message);\n process.exit(1);\n }\n\n outro(chalk.green(\"Update complete.\"));\n return;\n }\n\n // ---------------------------------------------------------------------\n // 1. Pick agent CLIs\n // ---------------------------------------------------------------------\n let chosen: ProviderSpec[] = [];\n\n if (yes && providerIds.length === 0) {\n // --yes with no --providers: skip provider installs entirely\n log.info(\"--yes: skipping provider selection\");\n } else if (providerIds.length > 0) {\n chosen = PROVIDERS.filter((p) => providerIds.includes(p.id));\n const unknown = providerIds.filter((id) => !PROVIDERS.find((p) => p.id === id));\n if (unknown.length > 0) log.warn(`Unknown provider ids ignored: ${unknown.join(\", \")}`);\n log.info(`Providers to install: ${chosen.map((p) => p.label).join(\", \")}`);\n } else {\n const selection = await multiselect({\n message: \"Which agent CLIs do you want installed?\",\n required: false,\n options: PROVIDERS.map((p) => ({\n value: p.id,\n label: p.label,\n hint: p.description,\n })),\n });\n if (isCancel(selection)) {\n cancel(\"Cancelled.\");\n process.exit(0);\n }\n chosen = PROVIDERS.filter((p) => (selection as string[]).includes(p.id));\n }\n\n // ---------------------------------------------------------------------\n // 2. Install + auth each chosen provider\n // ---------------------------------------------------------------------\n for (const provider of chosen) {\n const s = spinner();\n s.start(`Checking ${provider.label}\u2026`);\n const alreadyInstalled = await provider.detect();\n s.stop(\n alreadyInstalled\n ? `${provider.label} already installed`\n : `${provider.label} not found \u2014 installing`,\n );\n\n if (!alreadyInstalled) {\n try {\n await provider.install();\n } catch (err) {\n log.error(`${provider.label} install failed: ${(err as Error).message}`);\n if (yes || noAuth) {\n log.warn(`Skipping ${provider.label} due to --yes/--no-auth`);\n continue;\n }\n const keepGoing = await confirm({\n message: `Skip ${provider.label} and continue?`,\n initialValue: true,\n });\n if (isCancel(keepGoing) || !keepGoing) {\n cancel(\"Aborting.\");\n process.exit(1);\n }\n continue;\n }\n }\n\n if (yes || noAuth) {\n log.info(`Skipping ${provider.label} auth (--no-auth / --yes)`);\n continue;\n }\n\n const doAuth = await confirm({\n message: `Authenticate ${provider.label} now?`,\n initialValue: true,\n });\n if (isCancel(doAuth)) {\n cancel(\"Cancelled.\");\n process.exit(0);\n }\n if (doAuth) {\n try {\n await provider.auth();\n } catch (err) {\n log.warn(\n `${provider.label} auth returned non-zero \u2014 retry later with its own CLI. (${(err as Error).message})`,\n );\n }\n } else {\n log.info(`Skipping ${provider.label} auth \u2014 you can run it later.`);\n }\n }\n\n // ---------------------------------------------------------------------\n // 3. Install the Appostle daemon\n // ---------------------------------------------------------------------\n if (!yes) {\n note(\n \"Installing Appostle globally (daemon + appostle CLI ship in the same package).\",\n \"Daemon\",\n );\n const proceed = await confirm({ message: \"Continue?\", initialValue: true });\n if (isCancel(proceed) || !proceed) {\n cancel(\"Stopped before daemon install. Re-run any time.\");\n process.exit(0);\n }\n }\n\n const s = spinner();\n s.start(\"Installing daemon (npm install -g appostle-installer)\u2026\");\n try {\n if (await shouldReinstallInstallerPackage()) {\n await installAppostleGlobal();\n s.stop(\"Daemon + appostle CLI installed\");\n } else {\n s.stop(\"Daemon package already at latest; skipping reinstall\");\n }\n } catch (err) {\n s.stop(\"Install failed\");\n log.error((err as Error).message);\n process.exit(1);\n }\n\n // ---------------------------------------------------------------------\n // 4. Auto-start service\n // ---------------------------------------------------------------------\n s.start(`Configuring auto-start (${os})\u2026`);\n await installAutostart();\n s.stop(\"Auto-start configured\");\n\n // ---------------------------------------------------------------------\n // 5. Pairing link\n // ---------------------------------------------------------------------\n if (!yes) {\n note(`Paste the pairing link below into ${APPOSTLE_WEB_URL} (or scan the QR).`, \"Pair\");\n }\n await printPairingLink();\n\n outro(chalk.green(`Done. Open ${APPOSTLE_WEB_URL}`));\n}\n\nmain().catch((err: unknown) => {\n console.error(chalk.red(\"\\nInstaller failed:\"), err);\n process.exit(1);\n});\n", "import { APPOSTLE_RELAY_ENDPOINT, APPOSTLE_WEB_URL, INSTALLER_PACKAGE } from \"./config.js\";\nimport { currentPlatform, npmInstallGlobal, resolveBinary, runInteractive } from \"./util.js\";\n\n// -----------------------------------------------------------------------------\n// Install appostle-installer globally so both `appostle-installer` and the\n// `appostle` daemon/CLI binary land on PATH (npx alone caches a single tarball\n// invocation; that's fine for the install flow but launchd/systemd need a\n// stable absolute path to `appostle`).\n// -----------------------------------------------------------------------------\nexport async function installAppostleGlobal(): Promise<void> {\n await npmInstallGlobal([`${INSTALLER_PACKAGE}@latest`]);\n}\n\n// -----------------------------------------------------------------------------\n// Auto-start configuration. Writes an OS-specific launcher with the relay\n// endpoint baked in, so the daemon connects to Appostle on boot.\n// -----------------------------------------------------------------------------\nexport async function installAutostart(): Promise<void> {\n const os = currentPlatform();\n if (os === \"darwin\") return installLaunchd();\n if (os === \"linux\") return installSystemdSystem();\n if (os === \"win32\") return installWindowsStartup();\n}\n\nasync function installLaunchd(): Promise<void> {\n const fs = await import(\"node:fs/promises\");\n const path = await import(\"node:path\");\n const osHome = (await import(\"node:os\")).homedir();\n\n const plistPath = path.join(osHome, \"Library\", \"LaunchAgents\", \"agency.ohlord.appostle.plist\");\n const logPath = path.join(osHome, \"Library\", \"Logs\", \"appostle.log\");\n const appostleBin = (await resolveBinary(\"appostle\")) ?? \"/usr/local/bin/appostle\";\n\n const plist = `<?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><string>agency.ohlord.appostle</string>\n <key>ProgramArguments</key>\n <array>\n <string>${appostleBin}</string>\n <string>daemon</string>\n <string>start</string>\n <string>--foreground</string>\n </array>\n <key>RunAtLoad</key><true/>\n <key>KeepAlive</key><true/>\n <key>StandardOutPath</key><string>${logPath}</string>\n <key>StandardErrorPath</key><string>${logPath}</string>\n <key>EnvironmentVariables</key>\n <dict>\n <key>PATH</key><string>/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin</string>\n <key>HOME</key><string>${osHome}</string>\n <key>NODE_ENV</key><string>production</string>\n <key>APPOSTLE_RELAY_ENDPOINT</key><string>${APPOSTLE_RELAY_ENDPOINT}</string>\n </dict>\n</dict>\n</plist>\n`;\n await fs.mkdir(path.dirname(plistPath), { recursive: true });\n await fs.writeFile(plistPath, plist);\n await writeAppostleConfig(osHome);\n\n try {\n await runInteractive(\"launchctl\", [\"unload\", plistPath], { stdio: \"ignore\" });\n } catch {\n /* not loaded yet */\n }\n await runInteractive(\"launchctl\", [\"load\", plistPath]);\n}\n\nasync function writeAppostleConfig(osHome: string): Promise<void> {\n const fs = await import(\"node:fs/promises\");\n const path = await import(\"node:path\");\n const configDir = path.join(osHome, \".appostle\");\n const configPath = path.join(configDir, \"config.json\");\n // Default-disable local speech features. They auto-download ML model\n // weights (~800 MB) from third-party sources and load them with\n // onnxruntime-node \u2014 supply-chain risk we don't want on by default in a\n // self-hosted daemon. Users who want voice/dictation locally can flip\n // these flags later and run `appostle speech download --model <id>`.\n const config = {\n version: 1,\n daemon: {\n listen: \"127.0.0.1:6767\",\n cors: { allowedOrigins: [APPOSTLE_WEB_URL] },\n relay: { enabled: true, endpoint: APPOSTLE_RELAY_ENDPOINT },\n },\n app: { baseUrl: APPOSTLE_WEB_URL },\n features: {\n dictation: { enabled: false },\n voiceMode: { enabled: false },\n },\n };\n await fs.mkdir(configDir, { recursive: true });\n await fs.writeFile(configPath, JSON.stringify(config, null, 2));\n}\n\n// Install as a system service so it survives user-session teardown and\n// behaves like a normal machine daemon on Linux.\nasync function installSystemdSystem(): Promise<void> {\n const fs = await import(\"node:fs/promises\");\n const path = await import(\"node:path\");\n const os = await import(\"node:os\");\n const osHome = (await import(\"node:os\")).homedir();\n const user = os.userInfo().username;\n\n const unitPath = \"/etc/systemd/system/appostle.service\";\n const appostleBin = (await resolveBinary(\"appostle\")) ?? \"/usr/bin/appostle\";\n const logPath = path.join(osHome, \".local\", \"state\", \"appostle\", \"daemon.log\");\n\n const unit = `[Unit]\nDescription=Appostle Daemon\nAfter=network.target\n\n[Service]\nType=simple\nUser=${user}\nExecStart=${appostleBin} daemon start --foreground\nRestart=on-failure\nRestartSec=10\nEnvironment=NODE_ENV=production\nEnvironment=HOME=${osHome}\nEnvironment=APPOSTLE_RELAY_ENDPOINT=${APPOSTLE_RELAY_ENDPOINT}\nStandardOutput=append:${logPath}\nStandardError=append:${logPath}\n\n[Install]\nWantedBy=multi-user.target\n`;\n\n await fs.mkdir(path.dirname(logPath), { recursive: true });\n const tempUnitPath = path.join(osHome, \".appostle\", \"appostle.service\");\n await fs.mkdir(path.dirname(tempUnitPath), { recursive: true });\n await fs.writeFile(tempUnitPath, unit);\n await writeAppostleConfig(osHome);\n\n // Migrate cleanly from the old user service if present.\n await runInteractive(\"systemctl\", [\"--user\", \"disable\", \"--now\", \"appostle.service\"], {\n reject: false,\n stdio: \"ignore\",\n });\n await runInteractive(\n \"sudo\",\n [\"rm\", \"-f\", path.join(osHome, \".config\", \"systemd\", \"user\", \"appostle.service\")],\n {\n reject: false,\n stdio: \"ignore\",\n },\n );\n await runInteractive(\"sudo\", [\"cp\", tempUnitPath, unitPath]);\n await runInteractive(\"sudo\", [\"systemctl\", \"daemon-reload\"]);\n await runInteractive(\"sudo\", [\"systemctl\", \"enable\", \"--now\", \"appostle.service\"]);\n}\n\nasync function installWindowsStartup(): Promise<void> {\n const fs = await import(\"node:fs/promises\");\n const path = await import(\"node:path\");\n const osHome = (await import(\"node:os\")).homedir();\n\n const appostleBin = (await resolveBinary(\"appostle\")) ?? \"appostle.cmd\";\n const logDir = path.join(osHome, \"AppData\", \"Local\", \"Appostle\");\n const logPath = path.join(logDir, \"daemon.log\");\n\n const batPath = path.join(logDir, \"appostle-daemon.bat\");\n const vbsPath = path.join(\n osHome,\n \"AppData\",\n \"Roaming\",\n \"Microsoft\",\n \"Windows\",\n \"Start Menu\",\n \"Programs\",\n \"Startup\",\n \"appostle.vbs\",\n );\n\n const bat = `@echo off\nset NODE_ENV=production\nset APPOSTLE_RELAY_ENDPOINT=${APPOSTLE_RELAY_ENDPOINT}\n\"${appostleBin}\" daemon start --foreground >> \"${logPath}\" 2>&1\n`;\n\n const vbs = `Set WshShell = CreateObject(\"WScript.Shell\")\nWshShell.Run \"\"\"${batPath}\"\"\", 0, False\n`;\n\n await fs.mkdir(logDir, { recursive: true });\n await fs.mkdir(path.dirname(vbsPath), { recursive: true });\n await fs.writeFile(batPath, bat);\n await fs.writeFile(vbsPath, vbs);\n await writeAppostleConfig(osHome);\n\n // Also kick it off now so we don't wait for next login.\n await runInteractive(\"wscript\", [vbsPath]);\n}\n\n// -----------------------------------------------------------------------------\n// Emit pairing link. `appostle daemon pair` prints a QR + URL.\n// -----------------------------------------------------------------------------\nexport async function printPairingLink(): Promise<void> {\n const { execa } = await import(\"execa\");\n const { APPOSTLE_WEB_URL } = await import(\"./config.js\");\n\n const result = await execa(\"appostle\", [\"daemon\", \"pair\"], { reject: false });\n const raw =\n (typeof result.stdout === \"string\" ? result.stdout : \"\") +\n (typeof result.stderr === \"string\" ? result.stderr : \"\");\n // Rewrite any origin to our web UI.\n const rewritten = raw.replace(/https?:\\/\\/[^/]+\\/#offer=/g, `${APPOSTLE_WEB_URL}/#offer=`);\n process.stdout.write(rewritten);\n}\n", "import { execa, type Options as ExecaOptions } from \"execa\";\nimport { accessSync, constants } from \"node:fs\";\nimport { platform } from \"node:os\";\nimport which from \"which\";\n\nexport type Platform = \"darwin\" | \"linux\" | \"win32\";\n\nexport function currentPlatform(): Platform {\n const p = platform();\n if (p === \"darwin\" || p === \"linux\" || p === \"win32\") return p;\n throw new Error(`Unsupported platform: ${p}`);\n}\n\n/** True if the given binary resolves on PATH (cross-platform). */\nexport async function has(binary: string): Promise<boolean> {\n try {\n await which(binary);\n return true;\n } catch {\n return false;\n }\n}\n\n/** Absolute path to a binary on PATH, or null. */\nexport async function resolveBinary(binary: string): Promise<string | null> {\n try {\n return await which(binary);\n } catch {\n return null;\n }\n}\n\n/** Run with inherited stdio so the user sees OAuth / password prompts. */\nexport async function runInteractive(\n command: string,\n args: string[] = [],\n options: ExecaOptions = {},\n): Promise<void> {\n await execa(command, args, { stdio: \"inherit\", ...options });\n}\n\nlet cachedNeedsSudo: boolean | null = null;\n\n/**\n * Returns true when `npm install -g` would fail with EACCES because npm's global\n * prefix is owned by root (typical on Debian/Ubuntu/etc with system Node) and we\n * are not root.\n *\n * macOS Homebrew installs npm to a user-writable prefix, so we don't need sudo\n * there. Windows manages globals per-user too. We only need this dance on\n * Linux/Unix when running as a non-root user against a root-owned prefix.\n */\nexport async function npmGlobalNeedsSudo(): Promise<boolean> {\n if (cachedNeedsSudo !== null) return cachedNeedsSudo;\n if (currentPlatform() === \"win32\") return (cachedNeedsSudo = false);\n if (process.getuid?.() === 0) return (cachedNeedsSudo = false);\n\n try {\n const { stdout } = await execa(\"npm\", [\"prefix\", \"-g\"]);\n const prefix = stdout.trim();\n if (!prefix) return (cachedNeedsSudo = false);\n accessSync(prefix, constants.W_OK);\n return (cachedNeedsSudo = false);\n } catch {\n return (cachedNeedsSudo = true);\n }\n}\n\n/**\n * Install one or more npm packages globally. Transparently uses `sudo` when the\n * npm global prefix isn't writable by the current user (e.g. system Node on\n * Linux). Sudo will prompt for password on first call only \u2014 subsequent calls\n * inherit the timestamp cache.\n */\nexport async function npmInstallGlobal(packages: string[]): Promise<void> {\n const useSudo = await npmGlobalNeedsSudo();\n const args = [\"install\", \"-g\", ...packages];\n if (useSudo) {\n await runInteractive(\"sudo\", [\"-E\", \"npm\", ...args]);\n } else {\n await runInteractive(\"npm\", args);\n }\n}\n", "import { has, npmInstallGlobal, runInteractive } from \"./util.js\";\n\nexport interface ProviderSpec {\n /** Stable id; matches the daemon's AGENT_PROVIDER_DEFINITIONS. */\n id: \"claude\" | \"codex\" | \"copilot\" | \"opencode\" | \"pi\";\n label: string;\n description: string;\n\n /** Is the provider's CLI already installed + reachable? */\n detect(): Promise<boolean>;\n\n /** Install the CLI. Should be idempotent. */\n install(): Promise<void>;\n\n /** Walk the user through the provider's native auth flow. */\n auth(): Promise<void>;\n}\n\n// Each provider installs its own CLI from its own public source. We don't\n// abstract their auth flows \u2014 we just invoke them and let the user complete\n// the native OAuth / key-paste prompt.\n\nconst claude: ProviderSpec = {\n id: \"claude\",\n label: \"Claude Code\",\n description: \"Anthropic's agent CLI (MCP, streaming, deep reasoning)\",\n async detect() {\n return has(\"claude\");\n },\n async install() {\n await npmInstallGlobal([\"@anthropic-ai/claude-code@latest\"]);\n },\n async auth() {\n await runInteractive(\"claude\", [\"/login\"]);\n },\n};\n\nconst codex: ProviderSpec = {\n id: \"codex\",\n label: \"Codex\",\n description: \"OpenAI's Codex workspace agent\",\n async detect() {\n return has(\"codex\");\n },\n async install() {\n await npmInstallGlobal([\"@openai/codex@latest\"]);\n },\n async auth() {\n await runInteractive(\"codex\", [\"login\"]);\n },\n};\n\nconst copilot: ProviderSpec = {\n id: \"copilot\",\n label: \"GitHub Copilot\",\n description: \"Standalone Copilot CLI with ACP support\",\n async detect() {\n return has(\"copilot\");\n },\n async install() {\n await npmInstallGlobal([\"@github/copilot@latest\"]);\n },\n async auth() {\n await runInteractive(\"copilot\", [\"auth\", \"login\"]);\n },\n};\n\nconst opencode: ProviderSpec = {\n id: \"opencode\",\n label: \"OpenCode\",\n description: \"Open-source multi-provider coding assistant\",\n async detect() {\n return has(\"opencode\");\n },\n async install() {\n await npmInstallGlobal([\"opencode-ai@latest\"]);\n },\n async auth() {\n await runInteractive(\"opencode\", [\"auth\", \"login\"]);\n },\n};\n\nconst pi: ProviderSpec = {\n id: \"pi\",\n label: \"Pi\",\n description: \"Minimal terminal-based agent with multi-provider LLM support\",\n async detect() {\n return has(\"pi\");\n },\n async install() {\n await npmInstallGlobal([\"@mariozechner/pi-coding-agent@latest\"]);\n },\n async auth() {\n await runInteractive(\"pi\", [\"login\"]);\n },\n};\n\nexport const PROVIDERS: ProviderSpec[] = [claude, codex, copilot, opencode, pi];\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["execa", "APPOSTLE_WEB_URL", "execa", "require", "s"]
|
|
7
7
|
}
|