@lovenyberg/ove 0.4.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lovenyberg/ove",
3
- "version": "0.4.0",
3
+ "version": "0.5.0",
4
4
  "description": "Your grumpy but meticulous dev companion. AI coding agent for Slack, WhatsApp, Telegram, Discord, GitHub, HTTP API, and CLI.",
5
5
  "type": "module",
6
6
  "bin": {
package/src/setup.ts CHANGED
@@ -1,4 +1,7 @@
1
1
  import { existsSync, readFileSync, writeFileSync } from "node:fs";
2
+ import { execFileSync } from "node:child_process";
3
+ import { resolve } from "node:path";
4
+ import { userInfo } from "node:os";
2
5
  import { createInterface } from "node:readline/promises";
3
6
  import type { Config } from "./config";
4
7
 
@@ -363,6 +366,14 @@ export async function runSetup(opts?: { fixOnly?: string[] }): Promise<void> {
363
366
  process.stdout.write(" Wrote config.json\n");
364
367
  }
365
368
 
369
+ // Systemd service setup
370
+ if (!fixing) {
371
+ const installService = await ask(rl, "Install as systemd service? (y/n)");
372
+ if (installService.toLowerCase() === "y") {
373
+ await installSystemdService(rl);
374
+ }
375
+ }
376
+
366
377
  if (!fixing) {
367
378
  process.stdout.write("\n Nåväl. Run 'ove start' when you're ready.\n\n");
368
379
  } else {
@@ -372,3 +383,63 @@ export async function runSetup(opts?: { fixOnly?: string[] }): Promise<void> {
372
383
  rl.close();
373
384
  }
374
385
  }
386
+
387
+ async function installSystemdService(rl: ReturnType<typeof createInterface>): Promise<void> {
388
+ const detectedUser = userInfo().username;
389
+ const detectedDir = resolve(".");
390
+ let detectedBun = "";
391
+ try {
392
+ detectedBun = execFileSync("which", ["bun"]).toString().trim();
393
+ } catch {
394
+ // bun not in PATH
395
+ }
396
+
397
+ const user = (await ask(rl, `User [${detectedUser}]`)) || detectedUser;
398
+ const workDir = (await ask(rl, `Working directory [${detectedDir}]`)) || detectedDir;
399
+ const bunPath = (await ask(rl, `Bun path [${detectedBun}]`)) || detectedBun;
400
+
401
+ if (!bunPath) {
402
+ process.stdout.write(" Could not find bun. Skipping service install.\n");
403
+ return;
404
+ }
405
+
406
+ const envPath = resolve(workDir, ".env");
407
+ const service = `[Unit]
408
+ Description=Ove - Personal AI coding assistant
409
+ After=network.target
410
+
411
+ [Service]
412
+ Type=simple
413
+ User=${user}
414
+ WorkingDirectory=${workDir}
415
+ ExecStart=${bunPath} run src/index.ts
416
+ Restart=always
417
+ RestartSec=5
418
+ EnvironmentFile=${envPath}
419
+
420
+ [Install]
421
+ WantedBy=multi-user.target
422
+ `;
423
+
424
+ const servicePath = resolve(workDir, "ove.service");
425
+ writeFileSync(servicePath, service);
426
+ process.stdout.write(` Wrote ${servicePath}\n`);
427
+
428
+ const install = await ask(rl, "Install and enable now? Requires sudo (y/n)");
429
+ if (install.toLowerCase() === "y") {
430
+ try {
431
+ execFileSync("sudo", ["cp", servicePath, "/etc/systemd/system/ove.service"]);
432
+ execFileSync("sudo", ["systemctl", "daemon-reload"]);
433
+ execFileSync("sudo", ["systemctl", "enable", "ove"]);
434
+ process.stdout.write(" Service installed and enabled.\n");
435
+
436
+ const startNow = await ask(rl, "Start service now? (y/n)");
437
+ if (startNow.toLowerCase() === "y") {
438
+ execFileSync("sudo", ["systemctl", "start", "ove"]);
439
+ process.stdout.write(" Service started.\n");
440
+ }
441
+ } catch (err) {
442
+ process.stdout.write(` Failed to install service: ${err}\n`);
443
+ }
444
+ }
445
+ }
@@ -1,15 +0,0 @@
1
- [Unit]
2
- Description=Ove - Personal AI coding assistant
3
- After=network.target
4
-
5
- [Service]
6
- Type=simple
7
- User=YOUR_USER
8
- WorkingDirectory=/path/to/ove
9
- ExecStart=/path/to/bun run src/index.ts
10
- Restart=always
11
- RestartSec=5
12
- EnvironmentFile=/path/to/ove/.env
13
-
14
- [Install]
15
- WantedBy=multi-user.target