appostle-installer 0.0.14 → 0.0.16
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 +122 -10
- package/dist/appostle-installer.js.map +3 -3
- package/dist/appostle.js +1371 -672
- package/dist/appostle.js.map +4 -4
- package/dist/schema-templates/layout.md +8 -0
- package/dist/worker.js +21612 -20682
- package/dist/worker.js.map +4 -4
- package/package.json +1 -1
- package/dist/schema-templates/art-direction.md +0 -90
|
@@ -44,6 +44,7 @@ import chalk from "chalk";
|
|
|
44
44
|
|
|
45
45
|
// src/daemon-setup.ts
|
|
46
46
|
init_config();
|
|
47
|
+
import { execa as execa2 } from "execa";
|
|
47
48
|
|
|
48
49
|
// src/util.ts
|
|
49
50
|
import { execa } from "execa";
|
|
@@ -102,11 +103,103 @@ async function npmInstallGlobal(packages) {
|
|
|
102
103
|
async function installAppostleGlobal() {
|
|
103
104
|
await npmInstallGlobal([`${INSTALLER_PACKAGE}@latest`]);
|
|
104
105
|
}
|
|
106
|
+
async function appostleHome() {
|
|
107
|
+
const path = await import("node:path");
|
|
108
|
+
const os = await import("node:os");
|
|
109
|
+
return path.join(os.homedir(), ".appostle");
|
|
110
|
+
}
|
|
111
|
+
async function readDaemonPid() {
|
|
112
|
+
const fs = await import("node:fs/promises");
|
|
113
|
+
const path = await import("node:path");
|
|
114
|
+
try {
|
|
115
|
+
const raw = await fs.readFile(path.join(await appostleHome(), "appostle.pid"), "utf8");
|
|
116
|
+
const data = JSON.parse(raw);
|
|
117
|
+
const pid = typeof data.pid === "number" ? data.pid : null;
|
|
118
|
+
return pid && pid > 0 ? pid : null;
|
|
119
|
+
} catch {
|
|
120
|
+
return null;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
function processAlive(pid) {
|
|
124
|
+
try {
|
|
125
|
+
process.kill(pid, 0);
|
|
126
|
+
return true;
|
|
127
|
+
} catch {
|
|
128
|
+
return false;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
async function isAppostleProcess(pid) {
|
|
132
|
+
try {
|
|
133
|
+
if (currentPlatform() === "win32") {
|
|
134
|
+
const { stdout: stdout2 } = await execa2("wmic", [
|
|
135
|
+
"process",
|
|
136
|
+
"where",
|
|
137
|
+
`ProcessId=${pid}`,
|
|
138
|
+
"get",
|
|
139
|
+
"CommandLine",
|
|
140
|
+
"/value"
|
|
141
|
+
]);
|
|
142
|
+
return /appostle/i.test(stdout2);
|
|
143
|
+
}
|
|
144
|
+
const { stdout } = await execa2("ps", ["-p", String(pid), "-o", "command="]);
|
|
145
|
+
return /appostle/i.test(stdout);
|
|
146
|
+
} catch {
|
|
147
|
+
return true;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
async function sleep(ms) {
|
|
151
|
+
await new Promise((resolve) => setTimeout(resolve, ms));
|
|
152
|
+
}
|
|
153
|
+
async function stopRunningDaemon() {
|
|
154
|
+
const pid = await readDaemonPid();
|
|
155
|
+
if (pid === null || !processAlive(pid)) return null;
|
|
156
|
+
if (!await isAppostleProcess(pid)) return null;
|
|
157
|
+
if (currentPlatform() === "win32") {
|
|
158
|
+
await runInteractive("taskkill", ["/F", "/PID", String(pid)], {
|
|
159
|
+
reject: false,
|
|
160
|
+
stdio: "ignore"
|
|
161
|
+
});
|
|
162
|
+
await sleep(500);
|
|
163
|
+
return pid;
|
|
164
|
+
}
|
|
165
|
+
try {
|
|
166
|
+
process.kill(pid, "SIGTERM");
|
|
167
|
+
} catch {
|
|
168
|
+
return null;
|
|
169
|
+
}
|
|
170
|
+
const deadline = Date.now() + 5e3;
|
|
171
|
+
while (Date.now() < deadline) {
|
|
172
|
+
if (!processAlive(pid)) return pid;
|
|
173
|
+
await sleep(100);
|
|
174
|
+
}
|
|
175
|
+
try {
|
|
176
|
+
process.kill(pid, "SIGKILL");
|
|
177
|
+
} catch {
|
|
178
|
+
}
|
|
179
|
+
await sleep(300);
|
|
180
|
+
return pid;
|
|
181
|
+
}
|
|
182
|
+
async function verifyDaemonRestarted(prevPid) {
|
|
183
|
+
const deadline = Date.now() + 15e3;
|
|
184
|
+
let lastSeen = null;
|
|
185
|
+
while (Date.now() < deadline) {
|
|
186
|
+
const pid = await readDaemonPid();
|
|
187
|
+
if (pid !== null && pid !== prevPid && processAlive(pid)) return pid;
|
|
188
|
+
lastSeen = pid;
|
|
189
|
+
await sleep(250);
|
|
190
|
+
}
|
|
191
|
+
throw new Error(
|
|
192
|
+
`Daemon restart did not complete within 15s (prevPid=${prevPid ?? "none"}, lastSeenPid=${lastSeen ?? "none"}). Check the daemon log under ~/.appostle/daemon.log or the supervisor's log.`
|
|
193
|
+
);
|
|
194
|
+
}
|
|
105
195
|
async function installAutostart() {
|
|
106
196
|
const os = currentPlatform();
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
if (os === "
|
|
197
|
+
const prevPid = await readDaemonPid();
|
|
198
|
+
await stopRunningDaemon();
|
|
199
|
+
if (os === "darwin") await installLaunchd();
|
|
200
|
+
else if (os === "linux") await installSystemdSystem();
|
|
201
|
+
else if (os === "win32") await installWindowsStartup();
|
|
202
|
+
await verifyDaemonRestarted(prevPid);
|
|
110
203
|
}
|
|
111
204
|
async function installLaunchd() {
|
|
112
205
|
const fs = await import("node:fs/promises");
|
|
@@ -144,11 +237,29 @@ async function installLaunchd() {
|
|
|
144
237
|
await fs.mkdir(path.dirname(plistPath), { recursive: true });
|
|
145
238
|
await fs.writeFile(plistPath, plist);
|
|
146
239
|
await writeAppostleConfig(osHome);
|
|
240
|
+
const uid = process.getuid?.() ?? 501;
|
|
241
|
+
const domain = `gui/${uid}`;
|
|
242
|
+
const label = `${domain}/agency.ohlord.appostle`;
|
|
243
|
+
let modernPathWorked = false;
|
|
147
244
|
try {
|
|
148
|
-
await runInteractive("launchctl", ["
|
|
245
|
+
await runInteractive("launchctl", ["bootout", label], {
|
|
246
|
+
reject: false,
|
|
247
|
+
stdio: "ignore"
|
|
248
|
+
});
|
|
249
|
+
await runInteractive("launchctl", ["bootstrap", domain, plistPath]);
|
|
250
|
+
modernPathWorked = true;
|
|
149
251
|
} catch {
|
|
150
252
|
}
|
|
151
|
-
|
|
253
|
+
if (!modernPathWorked) {
|
|
254
|
+
try {
|
|
255
|
+
await runInteractive("launchctl", ["unload", plistPath], {
|
|
256
|
+
reject: false,
|
|
257
|
+
stdio: "ignore"
|
|
258
|
+
});
|
|
259
|
+
} catch {
|
|
260
|
+
}
|
|
261
|
+
await runInteractive("launchctl", ["load", plistPath]);
|
|
262
|
+
}
|
|
152
263
|
}
|
|
153
264
|
async function writeAppostleConfig(osHome) {
|
|
154
265
|
const fs = await import("node:fs/promises");
|
|
@@ -218,7 +329,8 @@ WantedBy=multi-user.target
|
|
|
218
329
|
);
|
|
219
330
|
await runInteractive("sudo", ["cp", tempUnitPath, unitPath]);
|
|
220
331
|
await runInteractive("sudo", ["systemctl", "daemon-reload"]);
|
|
221
|
-
await runInteractive("sudo", ["systemctl", "enable", "
|
|
332
|
+
await runInteractive("sudo", ["systemctl", "enable", "appostle.service"]);
|
|
333
|
+
await runInteractive("sudo", ["systemctl", "restart", "appostle.service"]);
|
|
222
334
|
}
|
|
223
335
|
async function installWindowsStartup() {
|
|
224
336
|
const fs = await import("node:fs/promises");
|
|
@@ -255,9 +367,9 @@ WshShell.Run """${batPath}""", 0, False
|
|
|
255
367
|
await runInteractive("wscript", [vbsPath]);
|
|
256
368
|
}
|
|
257
369
|
async function printPairingLink() {
|
|
258
|
-
const { execa:
|
|
370
|
+
const { execa: execa4 } = await import("execa");
|
|
259
371
|
const { APPOSTLE_WEB_URL: APPOSTLE_WEB_URL2 } = await Promise.resolve().then(() => (init_config(), config_exports));
|
|
260
|
-
const result = await
|
|
372
|
+
const result = await execa4("appostle", ["daemon", "pair"], { reject: false });
|
|
261
373
|
const raw = (typeof result.stdout === "string" ? result.stdout : "") + (typeof result.stderr === "string" ? result.stderr : "");
|
|
262
374
|
const rewritten = raw.replace(/https?:\/\/[^/]+\/#offer=/g, `${APPOSTLE_WEB_URL2}/#offer=`);
|
|
263
375
|
process.stdout.write(rewritten);
|
|
@@ -337,7 +449,7 @@ var pi = {
|
|
|
337
449
|
var PROVIDERS = [claude, codex, copilot, opencode, pi];
|
|
338
450
|
|
|
339
451
|
// src/index.ts
|
|
340
|
-
import { execa as
|
|
452
|
+
import { execa as execa3 } from "execa";
|
|
341
453
|
import { createRequire } from "node:module";
|
|
342
454
|
function parseArgs() {
|
|
343
455
|
const args = process.argv.slice(2);
|
|
@@ -354,7 +466,7 @@ async function shouldReinstallInstallerPackage() {
|
|
|
354
466
|
const packageVersion = require2("../package.json")?.version;
|
|
355
467
|
if (!packageVersion) return true;
|
|
356
468
|
try {
|
|
357
|
-
const { stdout } = await
|
|
469
|
+
const { stdout } = await execa3("npm", ["view", "appostle-installer", "dist-tags.latest"]);
|
|
358
470
|
const latest = stdout.trim();
|
|
359
471
|
if (!latest) return true;
|
|
360
472
|
return latest !== packageVersion;
|
|
@@ -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 // ---------------------------------------------------------------------\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
|
-
"names": ["execa", "APPOSTLE_WEB_URL", "execa", "require", "s"]
|
|
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 { execa } from \"execa\";\nimport { 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// Daemon lifecycle helpers \u2014 guarantee singleton + verify restart on every OS.\n// Background: appostle-installer historically wrote a fresh unit/plist/vbs and\n// asked the supervisor to start, but never explicitly killed any pre-existing\n// daemon process. On systemd `enable --now` is a no-op if the service is\n// already running (old PID survives \u2014 Linux symptom). On Windows wscript\n// happily spawns a second daemon alongside the running one (duplicate PIDs).\n// See https://gitlab.com/ohlord-suite/appostle/-/work_items/23.\n//\n// The fix is OS-agnostic at the contract layer:\n// 1. Snapshot the running daemon's PID (from `~/.appostle/appostle.pid`).\n// 2. Kill it cleanly (SIGTERM \u2192 wait \u2192 SIGKILL on POSIX; taskkill on Win).\n// 3. Run the OS-specific supervisor bring-up.\n// 4. Confirm a new PID appears in the PID file and is alive, within 15s.\n// 5. Fail loudly if not \u2014 never silently report \"service restarted\".\n// -----------------------------------------------------------------------------\n\nasync function appostleHome(): Promise<string> {\n const path = await import(\"node:path\");\n const os = await import(\"node:os\");\n return path.join(os.homedir(), \".appostle\");\n}\n\nasync function readDaemonPid(): Promise<number | null> {\n const fs = await import(\"node:fs/promises\");\n const path = await import(\"node:path\");\n try {\n const raw = await fs.readFile(path.join(await appostleHome(), \"appostle.pid\"), \"utf8\");\n const data = JSON.parse(raw) as { pid?: unknown };\n const pid = typeof data.pid === \"number\" ? data.pid : null;\n return pid && pid > 0 ? pid : null;\n } catch {\n return null;\n }\n}\n\n/**\n * POSIX-portable \"is this PID alive?\". Signal 0 doesn't deliver anything,\n * it just checks the kernel knows about the PID and we may signal it.\n */\nfunction processAlive(pid: number): boolean {\n try {\n process.kill(pid, 0);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Confirm the given PID is actually an appostle daemon (not some unrelated\n * process that inherited the PID after the daemon died). Best-effort: returns\n * `true` if the process command line mentions \"appostle\", `false` if it\n * doesn't, and `true` (optimistic) if we can't tell.\n */\nasync function isAppostleProcess(pid: number): Promise<boolean> {\n try {\n if (currentPlatform() === \"win32\") {\n const { stdout } = await execa(\"wmic\", [\n \"process\",\n \"where\",\n `ProcessId=${pid}`,\n \"get\",\n \"CommandLine\",\n \"/value\",\n ]);\n return /appostle/i.test(stdout);\n }\n const { stdout } = await execa(\"ps\", [\"-p\", String(pid), \"-o\", \"command=\"]);\n return /appostle/i.test(stdout);\n } catch {\n return true; // can't verify \u2014 assume it's ours rather than leak a duplicate\n }\n}\n\nasync function sleep(ms: number): Promise<void> {\n await new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/**\n * Stop any running daemon for this user. Idempotent: returns null when there\n * was nothing to stop. Returns the PID that was killed otherwise.\n */\nasync function stopRunningDaemon(): Promise<number | null> {\n const pid = await readDaemonPid();\n if (pid === null || !processAlive(pid)) return null;\n if (!(await isAppostleProcess(pid))) return null;\n\n if (currentPlatform() === \"win32\") {\n await runInteractive(\"taskkill\", [\"/F\", \"/PID\", String(pid)], {\n reject: false,\n stdio: \"ignore\",\n });\n // brief settle so the next start doesn't race the port bind\n await sleep(500);\n return pid;\n }\n\n try {\n process.kill(pid, \"SIGTERM\");\n } catch {\n return null;\n }\n // Up to 5s for graceful exit\n const deadline = Date.now() + 5000;\n while (Date.now() < deadline) {\n if (!processAlive(pid)) return pid;\n await sleep(100);\n }\n // Stubborn \u2014 force kill\n try {\n process.kill(pid, \"SIGKILL\");\n } catch {\n // already gone\n }\n await sleep(300);\n return pid;\n}\n\n/**\n * Poll the PID file for up to 15s waiting for a new daemon PID that differs\n * from `prevPid` (or any non-null PID when `prevPid` is null). Throws when no\n * fresh PID appears \u2014 that signal is what makes the installer fail loud\n * instead of falsely claiming success.\n */\nasync function verifyDaemonRestarted(prevPid: number | null): Promise<number> {\n const deadline = Date.now() + 15_000;\n let lastSeen: number | null = null;\n while (Date.now() < deadline) {\n const pid = await readDaemonPid();\n if (pid !== null && pid !== prevPid && processAlive(pid)) return pid;\n lastSeen = pid;\n await sleep(250);\n }\n throw new Error(\n `Daemon restart did not complete within 15s ` +\n `(prevPid=${prevPid ?? \"none\"}, lastSeenPid=${lastSeen ?? \"none\"}). ` +\n `Check the daemon log under ~/.appostle/daemon.log or the supervisor's log.`,\n );\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//\n// Every OS path follows the same shape:\n// 1. Snapshot prev PID.\n// 2. Stop the running daemon (no-op if none).\n// 3. Write the unit/plist/vbs and ask the supervisor to bring the daemon up.\n// 4. Verify a new PID is alive.\n// -----------------------------------------------------------------------------\nexport async function installAutostart(): Promise<void> {\n const os = currentPlatform();\n const prevPid = await readDaemonPid();\n await stopRunningDaemon();\n if (os === \"darwin\") await installLaunchd();\n else if (os === \"linux\") await installSystemdSystem();\n else if (os === \"win32\") await installWindowsStartup();\n await verifyDaemonRestarted(prevPid);\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 // Modern launchctl API (macOS 10.10+). Fall back to legacy unload/load on\n // older systems or if bootout reports an error other than \"not bootstrapped\".\n // bootout-then-bootstrap is the supported way to re-load a plist whose\n // contents changed.\n const uid = process.getuid?.() ?? 501;\n const domain = `gui/${uid}`;\n const label = `${domain}/agency.ohlord.appostle`;\n let modernPathWorked = false;\n try {\n await runInteractive(\"launchctl\", [\"bootout\", label], {\n reject: false,\n stdio: \"ignore\",\n });\n await runInteractive(\"launchctl\", [\"bootstrap\", domain, plistPath]);\n modernPathWorked = true;\n } catch {\n /* fall through to legacy */\n }\n if (!modernPathWorked) {\n try {\n await runInteractive(\"launchctl\", [\"unload\", plistPath], {\n reject: false,\n stdio: \"ignore\",\n });\n } catch {\n /* not loaded yet */\n }\n await runInteractive(\"launchctl\", [\"load\", plistPath]);\n }\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 // `enable` makes the unit start on boot. `--now` would also start it, but\n // ONLY if it's not already running \u2014 that's the bug that left old PIDs\n // alive across updates. We explicitly restart after enable so an existing\n // daemon process is torn down and replaced regardless of state.\n await runInteractive(\"sudo\", [\"systemctl\", \"enable\", \"appostle.service\"]);\n await runInteractive(\"sudo\", [\"systemctl\", \"restart\", \"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 // Kick it off now so we don't wait for next login. The pre-step\n // `stopRunningDaemon()` in `installAutostart` already killed any prior\n // daemon by PID, so this won't double-spawn (the historic Windows bug).\n // The post-step `verifyDaemonRestarted` confirms a fresh PID landed.\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
|
+
"names": ["execa", "stdout", "execa", "APPOSTLE_WEB_URL", "execa", "require", "s"]
|
|
7
7
|
}
|