@foxden-app/foxclaw 0.3.10 → 0.3.11

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/main.js CHANGED
@@ -8,6 +8,7 @@ import { fileURLToPath } from 'node:url';
8
8
  import { APP_HOME, DEFAULT_ENV_PATH, DEFAULT_LOG_PATH, DEFAULT_STATUS_PATH, getLoadedEnvPath, loadConfig, loadEnv, } from './config.js';
9
9
  import { acquireProcessLock, LockHeldError } from './lock.js';
10
10
  import { readRuntimeStatus, writeRuntimeStatus } from './runtime.js';
11
+ import { refreshFoxclawExecStartDropIns } from './systemd.js';
11
12
  const rawCommand = process.argv[2];
12
13
  const command = rawCommand || 'serve';
13
14
  loadEnv();
@@ -553,6 +554,7 @@ function installSystemd() {
553
554
  fs.mkdirSync(userSystemdDir, { recursive: true });
554
555
  fs.mkdirSync(configDir, { recursive: true });
555
556
  fs.mkdirSync(path.join(APP_HOME, 'logs'), { recursive: true });
557
+ const escapedEntryPoint = systemdEscape(entryPoint);
556
558
  fs.writeFileSync(unitPath, `[Unit]
557
559
  Description=FoxClaw local Codex execution bridge
558
560
  Documentation=https://github.com/foxden-app/foxclaw
@@ -569,7 +571,7 @@ Environment=USER=${systemdEscape(process.env.USER || '')}
569
571
  Environment=LOGNAME=${systemdEscape(process.env.LOGNAME || process.env.USER || '')}
570
572
  Environment=PATH=${systemdEscape(pathValue)}
571
573
  Environment=FOXCLAW_ENV=${systemdEscape(envPath)}
572
- ExecStart=${systemdEscape(nodeBin)} ${systemdEscape(entryPoint)} serve
574
+ ExecStart=${systemdEscape(nodeBin)} ${escapedEntryPoint} serve
573
575
  Restart=always
574
576
  RestartSec=10
575
577
  TimeoutStopSec=45
@@ -578,6 +580,10 @@ KillMode=process
578
580
  [Install]
579
581
  WantedBy=default.target
580
582
  `);
583
+ const dropInUpdates = refreshFoxclawExecStartDropIns(userSystemdDir, unitName, escapedEntryPoint);
584
+ for (const update of dropInUpdates) {
585
+ console.log(`[OK] updated FoxClaw ExecStart override: ${update.path}`);
586
+ }
581
587
  spawnChecked('systemctl', ['--user', 'daemon-reload']);
582
588
  spawnChecked('systemctl', ['--user', 'enable', unitName]);
583
589
  const restarted = spawnSync('systemctl', ['--user', 'restart', unitName], { stdio: 'inherit' });
@@ -0,0 +1,9 @@
1
+ export interface SystemdDropInUpdate {
2
+ path: string;
3
+ replacements: number;
4
+ }
5
+ export declare function refreshFoxclawExecStartDropIns(userSystemdDir: string, unitName: string, escapedEntryPoint: string): SystemdDropInUpdate[];
6
+ export declare function refreshFoxclawExecStartText(text: string, escapedEntryPoint: string): {
7
+ text: string;
8
+ replacements: number;
9
+ };
@@ -0,0 +1,45 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ const FOXCLAW_MAIN_PATH_RE = /\S*(?:\.pnpm\/@foxden-app\+foxclaw@[^/\s]+\/node_modules\/@foxden-app\/foxclaw|node_modules\/@foxden-app\/foxclaw)\/dist\/main\.js/g;
4
+ export function refreshFoxclawExecStartDropIns(userSystemdDir, unitName, escapedEntryPoint) {
5
+ const dropInDir = path.join(userSystemdDir, `${unitName}.d`);
6
+ let names;
7
+ try {
8
+ names = fs.readdirSync(dropInDir).filter((name) => name.endsWith('.conf')).sort();
9
+ }
10
+ catch {
11
+ return [];
12
+ }
13
+ const updates = [];
14
+ for (const name of names) {
15
+ const filePath = path.join(dropInDir, name);
16
+ let before = '';
17
+ try {
18
+ before = fs.readFileSync(filePath, 'utf8');
19
+ }
20
+ catch {
21
+ continue;
22
+ }
23
+ const { text, replacements } = refreshFoxclawExecStartText(before, escapedEntryPoint);
24
+ if (replacements === 0 || text === before) {
25
+ continue;
26
+ }
27
+ fs.writeFileSync(filePath, text, 'utf8');
28
+ updates.push({ path: filePath, replacements });
29
+ }
30
+ return updates;
31
+ }
32
+ export function refreshFoxclawExecStartText(text, escapedEntryPoint) {
33
+ let replacements = 0;
34
+ const lines = text.split(/(\r?\n)/);
35
+ const refreshed = lines.map((part) => {
36
+ if (!part.startsWith('ExecStart=') || part.trim() === 'ExecStart=') {
37
+ return part;
38
+ }
39
+ return part.replace(FOXCLAW_MAIN_PATH_RE, () => {
40
+ replacements += 1;
41
+ return escapedEntryPoint;
42
+ });
43
+ });
44
+ return { text: refreshed.join(''), replacements };
45
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@foxden-app/foxclaw",
3
- "version": "0.3.10",
3
+ "version": "0.3.11",
4
4
  "description": "Foxden local execution claw for controlling Codex from trusted chat interfaces.",
5
5
  "type": "module",
6
6
  "main": "dist/main.js",