@questionbase/deskfree 0.4.5 → 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.
@@ -1,28 +1,134 @@
1
1
  import { createRequire } from 'node:module';
2
2
  import { execSync } from 'child_process';
3
- import { writeFileSync, chmodSync } from 'fs';
3
+ import { mkdirSync, writeFileSync, chmodSync } from 'fs';
4
+ import { homedir } from 'os';
5
+ import { dirname, join } from 'path';
4
6
 
5
7
  createRequire(import.meta.url);
6
8
  var SERVICE_NAME = "deskfree-agent";
7
- var SERVICE_FILE = `/etc/systemd/system/${SERVICE_NAME}.service`;
8
- var ENV_FILE = `/etc/${SERVICE_NAME}.env`;
9
9
  var PACKAGE = "@questionbase/deskfree@latest";
10
- function install(token) {
10
+ var PLIST_LABEL = "com.deskfree.agent";
11
+ function getMacPaths() {
12
+ const home = homedir();
13
+ const deskfreeDir = join(home, ".deskfree");
14
+ return {
15
+ deskfreeDir,
16
+ envFile: join(deskfreeDir, ".env"),
17
+ launcher: join(deskfreeDir, "launcher.sh"),
18
+ logDir: join(deskfreeDir, "logs"),
19
+ plist: join(home, "Library", "LaunchAgents", `${PLIST_LABEL}.plist`)
20
+ };
21
+ }
22
+ function installMac(token) {
23
+ const paths = getMacPaths();
24
+ let nodeBinDir;
25
+ try {
26
+ const nodePath = execSync("which node", { encoding: "utf8" }).trim();
27
+ nodeBinDir = dirname(nodePath);
28
+ } catch {
29
+ console.error("Error: node not found in PATH");
30
+ process.exit(1);
31
+ }
32
+ mkdirSync(paths.deskfreeDir, { recursive: true });
33
+ mkdirSync(paths.logDir, { recursive: true });
34
+ mkdirSync(dirname(paths.plist), { recursive: true });
35
+ writeFileSync(paths.envFile, `DESKFREE_LAUNCH=${token}
36
+ `, { mode: 384 });
37
+ chmodSync(paths.envFile, 384);
38
+ console.log(`Wrote ${paths.envFile}`);
39
+ const launcher = `#!/bin/bash
40
+ set -euo pipefail
41
+
42
+ export PATH="${nodeBinDir}:$PATH"
43
+
44
+ # Update to latest version before starting
45
+ npm install -g ${PACKAGE} 2>/dev/null || true
46
+
47
+ # Source env
48
+ set -a
49
+ source "${paths.envFile}"
50
+ set +a
51
+
52
+ exec deskfree-agent start
53
+ `;
54
+ writeFileSync(paths.launcher, launcher, { mode: 493 });
55
+ chmodSync(paths.launcher, 493);
56
+ console.log(`Wrote ${paths.launcher}`);
57
+ const plist = `<?xml version="1.0" encoding="UTF-8"?>
58
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
59
+ <plist version="1.0">
60
+ <dict>
61
+ <key>Label</key>
62
+ <string>${PLIST_LABEL}</string>
63
+ <key>ProgramArguments</key>
64
+ <array>
65
+ <string>${paths.launcher}</string>
66
+ </array>
67
+ <key>KeepAlive</key>
68
+ <true/>
69
+ <key>RunAtLoad</key>
70
+ <true/>
71
+ <key>StandardOutPath</key>
72
+ <string>${join(paths.logDir, "stdout.log")}</string>
73
+ <key>StandardErrorPath</key>
74
+ <string>${join(paths.logDir, "stderr.log")}</string>
75
+ <key>ThrottleInterval</key>
76
+ <integer>10</integer>
77
+ </dict>
78
+ </plist>
79
+ `;
80
+ writeFileSync(paths.plist, plist);
81
+ console.log(`Wrote ${paths.plist}`);
82
+ try {
83
+ execSync(`launchctl bootout gui/$(id -u) ${paths.plist}`, {
84
+ stdio: "ignore"
85
+ });
86
+ } catch {
87
+ }
88
+ execSync(`launchctl bootstrap gui/$(id -u) ${paths.plist}`);
89
+ console.log(`
90
+ Service ${PLIST_LABEL} installed and started.`);
91
+ console.log(`Check status: launchctl print gui/$(id -u)/${PLIST_LABEL}`);
92
+ console.log(`Logs: tail -f ${join(paths.logDir, "stdout.log")}`);
93
+ }
94
+ var SYSTEMD_SERVICE_FILE = `/etc/systemd/system/${SERVICE_NAME}.service`;
95
+ var SYSTEMD_ENV_FILE = `/etc/${SERVICE_NAME}.env`;
96
+ var LINUX_STATE_DIR = "/var/lib/deskfree-agent";
97
+ var LINUX_LOG_DIR = "/var/log/deskfree-agent";
98
+ function installLinux(token) {
11
99
  if (process.getuid?.() !== 0) {
12
100
  console.error("Error: install must be run as root (use sudo)");
13
101
  process.exit(1);
14
102
  }
15
- let npxPath;
103
+ let npmPath;
104
+ let nodeBinDir;
16
105
  try {
17
- npxPath = execSync("which npx", { encoding: "utf8" }).trim();
106
+ npmPath = execSync("which npm", { encoding: "utf8" }).trim();
107
+ nodeBinDir = dirname(npmPath);
18
108
  } catch {
19
- console.error("Error: npx not found in PATH");
109
+ console.error("Error: npm not found in PATH");
20
110
  process.exit(1);
21
111
  }
22
- writeFileSync(ENV_FILE, `DESKFREE_LAUNCH=${token}
23
- `, { mode: 384 });
24
- chmodSync(ENV_FILE, 384);
25
- console.log(`Wrote ${ENV_FILE}`);
112
+ try {
113
+ execSync("id deskfree-agent", { stdio: "ignore" });
114
+ } catch {
115
+ execSync(
116
+ "useradd --system --no-create-home --shell /usr/sbin/nologin deskfree-agent"
117
+ );
118
+ console.log("Created system user: deskfree-agent");
119
+ }
120
+ mkdirSync(LINUX_STATE_DIR, { recursive: true });
121
+ mkdirSync(LINUX_LOG_DIR, { recursive: true });
122
+ execSync(
123
+ `chown deskfree-agent:deskfree-agent ${LINUX_STATE_DIR} ${LINUX_LOG_DIR}`
124
+ );
125
+ console.log(`Created ${LINUX_STATE_DIR} and ${LINUX_LOG_DIR}`);
126
+ writeFileSync(SYSTEMD_ENV_FILE, `DESKFREE_LAUNCH=${token}
127
+ `, {
128
+ mode: 384
129
+ });
130
+ chmodSync(SYSTEMD_ENV_FILE, 384);
131
+ console.log(`Wrote ${SYSTEMD_ENV_FILE}`);
26
132
  const unit = `[Unit]
27
133
  Description=DeskFree Agent
28
134
  After=network-online.target
@@ -30,22 +136,43 @@ Wants=network-online.target
30
136
 
31
137
  [Service]
32
138
  Type=simple
33
- ExecStart=${npxPath} ${PACKAGE} start
34
- EnvironmentFile=${ENV_FILE}
139
+ User=deskfree-agent
140
+ Group=deskfree-agent
141
+ WorkingDirectory=${LINUX_STATE_DIR}
142
+ Environment=PATH=${nodeBinDir}:/usr/local/bin:/usr/bin:/bin
143
+ ExecStartPre=+${npmPath} install -g ${PACKAGE}
144
+ ExecStart=${nodeBinDir}/deskfree-agent start
145
+ EnvironmentFile=${SYSTEMD_ENV_FILE}
35
146
  Environment=NODE_ENV=production
147
+ Environment=DESKFREE_STATE_DIR=${LINUX_STATE_DIR}
148
+ Environment=DESKFREE_TOOLS_DIR=${LINUX_STATE_DIR}/tools
36
149
  Restart=always
37
150
  RestartSec=10
151
+ StandardOutput=append:${LINUX_LOG_DIR}/stdout.log
152
+ StandardError=append:${LINUX_LOG_DIR}/stderr.log
38
153
 
39
154
  [Install]
40
155
  WantedBy=multi-user.target
41
156
  `;
42
- writeFileSync(SERVICE_FILE, unit);
43
- console.log(`Wrote ${SERVICE_FILE}`);
157
+ writeFileSync(SYSTEMD_SERVICE_FILE, unit);
158
+ console.log(`Wrote ${SYSTEMD_SERVICE_FILE}`);
44
159
  execSync("systemctl daemon-reload");
45
160
  execSync(`systemctl enable ${SERVICE_NAME}`);
46
161
  execSync(`systemctl start ${SERVICE_NAME}`);
47
- console.log(`Service ${SERVICE_NAME} installed and started.`);
162
+ console.log(`
163
+ Service ${SERVICE_NAME} installed and started.`);
48
164
  console.log(`Check status: systemctl status ${SERVICE_NAME}`);
165
+ console.log(`Logs: tail -f ${LINUX_LOG_DIR}/stdout.log`);
166
+ }
167
+ function install(token) {
168
+ if (process.platform === "darwin") {
169
+ installMac(token);
170
+ } else if (process.platform === "linux") {
171
+ installLinux(token);
172
+ } else {
173
+ console.error(`Unsupported platform: ${process.platform}`);
174
+ process.exit(1);
175
+ }
49
176
  }
50
177
 
51
178
  export { install };
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/cli/install.ts"],"names":[],"mappings":";;;;;AAGA,IAAM,YAAA,GAAe,gBAAA;AACrB,IAAM,YAAA,GAAe,uBAAuB,YAAY,CAAA,QAAA,CAAA;AACxD,IAAM,QAAA,GAAW,QAAQ,YAAY,CAAA,IAAA,CAAA;AACrC,IAAM,OAAA,GAAU,+BAAA;AAET,SAAS,QAAQ,KAAA,EAAqB;AAC3C,EAAA,IAAI,OAAA,CAAQ,MAAA,IAAS,KAAM,CAAA,EAAG;AAC5B,IAAA,OAAA,CAAQ,MAAM,+CAA+C,CAAA;AAC7D,IAAA,OAAA,CAAQ,KAAK,CAAC,CAAA;AAAA,EAChB;AAGA,EAAA,IAAI,OAAA;AACJ,EAAA,IAAI;AACF,IAAA,OAAA,GAAU,SAAS,WAAA,EAAa,EAAE,UAAU,MAAA,EAAQ,EAAE,IAAA,EAAK;AAAA,EAC7D,CAAA,CAAA,MAAQ;AACN,IAAA,OAAA,CAAQ,MAAM,8BAA8B,CAAA;AAC5C,IAAA,OAAA,CAAQ,KAAK,CAAC,CAAA;AAAA,EAChB;AAGA,EAAA,aAAA,CAAc,QAAA,EAAU,mBAAmB,KAAK;AAAA,CAAA,EAAM,EAAE,IAAA,EAAM,GAAA,EAAO,CAAA;AACrE,EAAA,SAAA,CAAU,UAAU,GAAK,CAAA;AACzB,EAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,MAAA,EAAS,QAAQ,CAAA,CAAE,CAAA;AAG/B,EAAA,MAAM,IAAA,GAAO,CAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA,UAAA,EAOH,OAAO,IAAI,OAAO,CAAA;AAAA,gBAAA,EACZ,QAAQ;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA,CAAA;AASxB,EAAA,aAAA,CAAc,cAAc,IAAI,CAAA;AAChC,EAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,MAAA,EAAS,YAAY,CAAA,CAAE,CAAA;AAGnC,EAAA,QAAA,CAAS,yBAAyB,CAAA;AAClC,EAAA,QAAA,CAAS,CAAA,iBAAA,EAAoB,YAAY,CAAA,CAAE,CAAA;AAC3C,EAAA,QAAA,CAAS,CAAA,gBAAA,EAAmB,YAAY,CAAA,CAAE,CAAA;AAE1C,EAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,QAAA,EAAW,YAAY,CAAA,uBAAA,CAAyB,CAAA;AAC5D,EAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,+BAAA,EAAkC,YAAY,CAAA,CAAE,CAAA;AAC9D","file":"install.js","sourcesContent":["import { execSync } from 'node:child_process';\nimport { chmodSync, writeFileSync } from 'node:fs';\n\nconst SERVICE_NAME = 'deskfree-agent';\nconst SERVICE_FILE = `/etc/systemd/system/${SERVICE_NAME}.service`;\nconst ENV_FILE = `/etc/${SERVICE_NAME}.env`;\nconst PACKAGE = '@questionbase/deskfree@latest';\n\nexport function install(token: string): void {\n if (process.getuid?.() !== 0) {\n console.error('Error: install must be run as root (use sudo)');\n process.exit(1);\n }\n\n // Resolve full npx path so systemd doesn't depend on PATH\n let npxPath: string;\n try {\n npxPath = execSync('which npx', { encoding: 'utf8' }).trim();\n } catch {\n console.error('Error: npx not found in PATH');\n process.exit(1);\n }\n\n // Write env file with token (chmod 600 — only root can read)\n writeFileSync(ENV_FILE, `DESKFREE_LAUNCH=${token}\\n`, { mode: 0o600 });\n chmodSync(ENV_FILE, 0o600);\n console.log(`Wrote ${ENV_FILE}`);\n\n // Write systemd unit file\n const unit = `[Unit]\nDescription=DeskFree Agent\nAfter=network-online.target\nWants=network-online.target\n\n[Service]\nType=simple\nExecStart=${npxPath} ${PACKAGE} start\nEnvironmentFile=${ENV_FILE}\nEnvironment=NODE_ENV=production\nRestart=always\nRestartSec=10\n\n[Install]\nWantedBy=multi-user.target\n`;\n\n writeFileSync(SERVICE_FILE, unit);\n console.log(`Wrote ${SERVICE_FILE}`);\n\n // Enable and start\n execSync('systemctl daemon-reload');\n execSync(`systemctl enable ${SERVICE_NAME}`);\n execSync(`systemctl start ${SERVICE_NAME}`);\n\n console.log(`Service ${SERVICE_NAME} installed and started.`);\n console.log(`Check status: systemctl status ${SERVICE_NAME}`);\n}\n"]}
1
+ {"version":3,"sources":["../../src/cli/install.ts"],"names":[],"mappings":"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","file":"install.js","sourcesContent":["import { execSync } from 'node:child_process';\nimport { chmodSync, mkdirSync, writeFileSync } from 'node:fs';\nimport { homedir } from 'node:os';\nimport { dirname, join } from 'node:path';\n\nconst SERVICE_NAME = 'deskfree-agent';\nconst PACKAGE = '@questionbase/deskfree@latest';\n\n// ── macOS (launchd) ─────────────────────────────────────────────────────────\n\nconst PLIST_LABEL = 'com.deskfree.agent';\n\nfunction getMacPaths() {\n const home = homedir();\n const deskfreeDir = join(home, '.deskfree');\n return {\n deskfreeDir,\n envFile: join(deskfreeDir, '.env'),\n launcher: join(deskfreeDir, 'launcher.sh'),\n logDir: join(deskfreeDir, 'logs'),\n plist: join(home, 'Library', 'LaunchAgents', `${PLIST_LABEL}.plist`),\n };\n}\n\nfunction installMac(token: string): void {\n const paths = getMacPaths();\n\n // Resolve full path to node's bin directory (survives nvm/fnm across sessions)\n let nodeBinDir: string;\n try {\n const nodePath = execSync('which node', { encoding: 'utf8' }).trim();\n nodeBinDir = dirname(nodePath);\n } catch {\n console.error('Error: node not found in PATH');\n process.exit(1);\n }\n\n // Create directories\n mkdirSync(paths.deskfreeDir, { recursive: true });\n mkdirSync(paths.logDir, { recursive: true });\n mkdirSync(dirname(paths.plist), { recursive: true });\n\n // Write env file (chmod 600)\n writeFileSync(paths.envFile, `DESKFREE_LAUNCH=${token}\\n`, { mode: 0o600 });\n chmodSync(paths.envFile, 0o600);\n console.log(`Wrote ${paths.envFile}`);\n\n // Write launcher script\n const launcher = `#!/bin/bash\nset -euo pipefail\n\nexport PATH=\"${nodeBinDir}:$PATH\"\n\n# Update to latest version before starting\nnpm install -g ${PACKAGE} 2>/dev/null || true\n\n# Source env\nset -a\nsource \"${paths.envFile}\"\nset +a\n\nexec deskfree-agent start\n`;\n\n writeFileSync(paths.launcher, launcher, { mode: 0o755 });\n chmodSync(paths.launcher, 0o755);\n console.log(`Wrote ${paths.launcher}`);\n\n // Write LaunchAgent plist\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>\n <string>${PLIST_LABEL}</string>\n <key>ProgramArguments</key>\n <array>\n <string>${paths.launcher}</string>\n </array>\n <key>KeepAlive</key>\n <true/>\n <key>RunAtLoad</key>\n <true/>\n <key>StandardOutPath</key>\n <string>${join(paths.logDir, 'stdout.log')}</string>\n <key>StandardErrorPath</key>\n <string>${join(paths.logDir, 'stderr.log')}</string>\n <key>ThrottleInterval</key>\n <integer>10</integer>\n</dict>\n</plist>\n`;\n\n writeFileSync(paths.plist, plist);\n console.log(`Wrote ${paths.plist}`);\n\n // Unload if already loaded (ignore errors)\n try {\n execSync(`launchctl bootout gui/$(id -u) ${paths.plist}`, {\n stdio: 'ignore',\n });\n } catch {\n // not loaded — fine\n }\n\n // Load the service\n execSync(`launchctl bootstrap gui/$(id -u) ${paths.plist}`);\n\n console.log(`\\nService ${PLIST_LABEL} installed and started.`);\n console.log(`Check status: launchctl print gui/$(id -u)/${PLIST_LABEL}`);\n console.log(`Logs: tail -f ${join(paths.logDir, 'stdout.log')}`);\n}\n\n// ── Linux (systemd) ─────────────────────────────────────────────────────────\n\nconst SYSTEMD_SERVICE_FILE = `/etc/systemd/system/${SERVICE_NAME}.service`;\nconst SYSTEMD_ENV_FILE = `/etc/${SERVICE_NAME}.env`;\n\nconst LINUX_STATE_DIR = '/var/lib/deskfree-agent';\nconst LINUX_LOG_DIR = '/var/log/deskfree-agent';\n\nfunction installLinux(token: string): void {\n if (process.getuid?.() !== 0) {\n console.error('Error: install must be run as root (use sudo)');\n process.exit(1);\n }\n\n // Resolve full npm/node bin dir so systemd doesn't depend on PATH\n let npmPath: string;\n let nodeBinDir: string;\n try {\n npmPath = execSync('which npm', { encoding: 'utf8' }).trim();\n nodeBinDir = dirname(npmPath);\n } catch {\n console.error('Error: npm not found in PATH');\n process.exit(1);\n }\n\n // Create dedicated system user (no login shell, no home dir)\n try {\n execSync('id deskfree-agent', { stdio: 'ignore' });\n } catch {\n execSync(\n 'useradd --system --no-create-home --shell /usr/sbin/nologin deskfree-agent',\n );\n console.log('Created system user: deskfree-agent');\n }\n\n // Create state and log directories owned by the service user\n mkdirSync(LINUX_STATE_DIR, { recursive: true });\n mkdirSync(LINUX_LOG_DIR, { recursive: true });\n execSync(\n `chown deskfree-agent:deskfree-agent ${LINUX_STATE_DIR} ${LINUX_LOG_DIR}`,\n );\n console.log(`Created ${LINUX_STATE_DIR} and ${LINUX_LOG_DIR}`);\n\n // Write env file with token (chmod 600 — only root can read)\n writeFileSync(SYSTEMD_ENV_FILE, `DESKFREE_LAUNCH=${token}\\n`, {\n mode: 0o600,\n });\n chmodSync(SYSTEMD_ENV_FILE, 0o600);\n console.log(`Wrote ${SYSTEMD_ENV_FILE}`);\n\n // Write systemd unit file\n // ExecStartPre updates to latest version before each start (same as macOS launcher)\n const unit = `[Unit]\nDescription=DeskFree Agent\nAfter=network-online.target\nWants=network-online.target\n\n[Service]\nType=simple\nUser=deskfree-agent\nGroup=deskfree-agent\nWorkingDirectory=${LINUX_STATE_DIR}\nEnvironment=PATH=${nodeBinDir}:/usr/local/bin:/usr/bin:/bin\nExecStartPre=+${npmPath} install -g ${PACKAGE}\nExecStart=${nodeBinDir}/deskfree-agent start\nEnvironmentFile=${SYSTEMD_ENV_FILE}\nEnvironment=NODE_ENV=production\nEnvironment=DESKFREE_STATE_DIR=${LINUX_STATE_DIR}\nEnvironment=DESKFREE_TOOLS_DIR=${LINUX_STATE_DIR}/tools\nRestart=always\nRestartSec=10\nStandardOutput=append:${LINUX_LOG_DIR}/stdout.log\nStandardError=append:${LINUX_LOG_DIR}/stderr.log\n\n[Install]\nWantedBy=multi-user.target\n`;\n\n writeFileSync(SYSTEMD_SERVICE_FILE, unit);\n console.log(`Wrote ${SYSTEMD_SERVICE_FILE}`);\n\n // Enable and start\n execSync('systemctl daemon-reload');\n execSync(`systemctl enable ${SERVICE_NAME}`);\n execSync(`systemctl start ${SERVICE_NAME}`);\n\n console.log(`\\nService ${SERVICE_NAME} installed and started.`);\n console.log(`Check status: systemctl status ${SERVICE_NAME}`);\n console.log(`Logs: tail -f ${LINUX_LOG_DIR}/stdout.log`);\n}\n\n// ── Public API ──────────────────────────────────────────────────────────────\n\nexport function install(token: string): void {\n if (process.platform === 'darwin') {\n installMac(token);\n } else if (process.platform === 'linux') {\n installLinux(token);\n } else {\n console.error(`Unsupported platform: ${process.platform}`);\n process.exit(1);\n }\n}\n"]}
@@ -1,12 +1,36 @@
1
1
  import { createRequire } from 'node:module';
2
2
  import { execSync } from 'child_process';
3
3
  import { existsSync, unlinkSync } from 'fs';
4
+ import { homedir } from 'os';
5
+ import { join } from 'path';
4
6
 
5
7
  createRequire(import.meta.url);
6
8
  var SERVICE_NAME = "deskfree-agent";
7
- var SERVICE_FILE = `/etc/systemd/system/${SERVICE_NAME}.service`;
8
- var ENV_FILE = `/etc/${SERVICE_NAME}.env`;
9
- function uninstall() {
9
+ var PLIST_LABEL = "com.deskfree.agent";
10
+ function uninstallMac() {
11
+ const home = homedir();
12
+ const plist = join(home, "Library", "LaunchAgents", `${PLIST_LABEL}.plist`);
13
+ const deskfreeDir = join(home, ".deskfree");
14
+ const envFile = join(deskfreeDir, ".env");
15
+ const launcher = join(deskfreeDir, "launcher.sh");
16
+ try {
17
+ execSync(`launchctl bootout gui/$(id -u) ${plist}`, { stdio: "ignore" });
18
+ } catch {
19
+ }
20
+ for (const file of [plist, envFile, launcher]) {
21
+ if (existsSync(file)) {
22
+ unlinkSync(file);
23
+ console.log(`Removed ${file}`);
24
+ }
25
+ }
26
+ console.log(`Service ${PLIST_LABEL} uninstalled.`);
27
+ console.log(
28
+ `Note: logs and state in ${deskfreeDir} were preserved. Remove manually if desired.`
29
+ );
30
+ }
31
+ var SYSTEMD_SERVICE_FILE = `/etc/systemd/system/${SERVICE_NAME}.service`;
32
+ var SYSTEMD_ENV_FILE = `/etc/${SERVICE_NAME}.env`;
33
+ function uninstallLinux() {
10
34
  if (process.getuid?.() !== 0) {
11
35
  console.error("Error: uninstall must be run as root (use sudo)");
12
36
  process.exit(1);
@@ -19,17 +43,27 @@ function uninstall() {
19
43
  execSync(`systemctl disable ${SERVICE_NAME}`, { stdio: "ignore" });
20
44
  } catch {
21
45
  }
22
- if (existsSync(SERVICE_FILE)) {
23
- unlinkSync(SERVICE_FILE);
24
- console.log(`Removed ${SERVICE_FILE}`);
46
+ if (existsSync(SYSTEMD_SERVICE_FILE)) {
47
+ unlinkSync(SYSTEMD_SERVICE_FILE);
48
+ console.log(`Removed ${SYSTEMD_SERVICE_FILE}`);
25
49
  }
26
- if (existsSync(ENV_FILE)) {
27
- unlinkSync(ENV_FILE);
28
- console.log(`Removed ${ENV_FILE}`);
50
+ if (existsSync(SYSTEMD_ENV_FILE)) {
51
+ unlinkSync(SYSTEMD_ENV_FILE);
52
+ console.log(`Removed ${SYSTEMD_ENV_FILE}`);
29
53
  }
30
54
  execSync("systemctl daemon-reload");
31
55
  console.log(`Service ${SERVICE_NAME} uninstalled.`);
32
56
  }
57
+ function uninstall() {
58
+ if (process.platform === "darwin") {
59
+ uninstallMac();
60
+ } else if (process.platform === "linux") {
61
+ uninstallLinux();
62
+ } else {
63
+ console.error(`Unsupported platform: ${process.platform}`);
64
+ process.exit(1);
65
+ }
66
+ }
33
67
 
34
68
  export { uninstall };
35
69
  //# sourceMappingURL=uninstall.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/cli/uninstall.ts"],"names":[],"mappings":";;;;;AAGA,IAAM,YAAA,GAAe,gBAAA;AACrB,IAAM,YAAA,GAAe,uBAAuB,YAAY,CAAA,QAAA,CAAA;AACxD,IAAM,QAAA,GAAW,QAAQ,YAAY,CAAA,IAAA,CAAA;AAE9B,SAAS,SAAA,GAAkB;AAChC,EAAA,IAAI,OAAA,CAAQ,MAAA,IAAS,KAAM,CAAA,EAAG;AAC5B,IAAA,OAAA,CAAQ,MAAM,iDAAiD,CAAA;AAC/D,IAAA,OAAA,CAAQ,KAAK,CAAC,CAAA;AAAA,EAChB;AAGA,EAAA,IAAI;AACF,IAAA,QAAA,CAAS,kBAAkB,YAAY,CAAA,CAAA,EAAI,EAAE,KAAA,EAAO,UAAU,CAAA;AAAA,EAChE,CAAA,CAAA,MAAQ;AAAA,EAER;AACA,EAAA,IAAI;AACF,IAAA,QAAA,CAAS,qBAAqB,YAAY,CAAA,CAAA,EAAI,EAAE,KAAA,EAAO,UAAU,CAAA;AAAA,EACnE,CAAA,CAAA,MAAQ;AAAA,EAER;AAGA,EAAA,IAAI,UAAA,CAAW,YAAY,CAAA,EAAG;AAC5B,IAAA,UAAA,CAAW,YAAY,CAAA;AACvB,IAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,QAAA,EAAW,YAAY,CAAA,CAAE,CAAA;AAAA,EACvC;AACA,EAAA,IAAI,UAAA,CAAW,QAAQ,CAAA,EAAG;AACxB,IAAA,UAAA,CAAW,QAAQ,CAAA;AACnB,IAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,QAAA,EAAW,QAAQ,CAAA,CAAE,CAAA;AAAA,EACnC;AAEA,EAAA,QAAA,CAAS,yBAAyB,CAAA;AAClC,EAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,QAAA,EAAW,YAAY,CAAA,aAAA,CAAe,CAAA;AACpD","file":"uninstall.js","sourcesContent":["import { execSync } from 'node:child_process';\nimport { existsSync, unlinkSync } from 'node:fs';\n\nconst SERVICE_NAME = 'deskfree-agent';\nconst SERVICE_FILE = `/etc/systemd/system/${SERVICE_NAME}.service`;\nconst ENV_FILE = `/etc/${SERVICE_NAME}.env`;\n\nexport function uninstall(): void {\n if (process.getuid?.() !== 0) {\n console.error('Error: uninstall must be run as root (use sudo)');\n process.exit(1);\n }\n\n // Stop and disable (ignore errors if not running/enabled)\n try {\n execSync(`systemctl stop ${SERVICE_NAME}`, { stdio: 'ignore' });\n } catch {\n // not running — fine\n }\n try {\n execSync(`systemctl disable ${SERVICE_NAME}`, { stdio: 'ignore' });\n } catch {\n // not enabled — fine\n }\n\n // Remove files\n if (existsSync(SERVICE_FILE)) {\n unlinkSync(SERVICE_FILE);\n console.log(`Removed ${SERVICE_FILE}`);\n }\n if (existsSync(ENV_FILE)) {\n unlinkSync(ENV_FILE);\n console.log(`Removed ${ENV_FILE}`);\n }\n\n execSync('systemctl daemon-reload');\n console.log(`Service ${SERVICE_NAME} uninstalled.`);\n}\n"]}
1
+ {"version":3,"sources":["../../src/cli/uninstall.ts"],"names":[],"mappings":"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","file":"uninstall.js","sourcesContent":["import { execSync } from 'node:child_process';\nimport { existsSync, unlinkSync } from 'node:fs';\nimport { homedir } from 'node:os';\nimport { join } from 'node:path';\n\nconst SERVICE_NAME = 'deskfree-agent';\n\n// ── macOS (launchd) ─────────────────────────────────────────────────────────\n\nconst PLIST_LABEL = 'com.deskfree.agent';\n\nfunction uninstallMac(): void {\n const home = homedir();\n const plist = join(home, 'Library', 'LaunchAgents', `${PLIST_LABEL}.plist`);\n const deskfreeDir = join(home, '.deskfree');\n const envFile = join(deskfreeDir, '.env');\n const launcher = join(deskfreeDir, 'launcher.sh');\n\n // Unload (ignore errors if not loaded)\n try {\n execSync(`launchctl bootout gui/$(id -u) ${plist}`, { stdio: 'ignore' });\n } catch {\n // not loaded — fine\n }\n\n // Remove files\n for (const file of [plist, envFile, launcher]) {\n if (existsSync(file)) {\n unlinkSync(file);\n console.log(`Removed ${file}`);\n }\n }\n\n console.log(`Service ${PLIST_LABEL} uninstalled.`);\n console.log(\n `Note: logs and state in ${deskfreeDir} were preserved. Remove manually if desired.`,\n );\n}\n\n// ── Linux (systemd) ─────────────────────────────────────────────────────────\n\nconst SYSTEMD_SERVICE_FILE = `/etc/systemd/system/${SERVICE_NAME}.service`;\nconst SYSTEMD_ENV_FILE = `/etc/${SERVICE_NAME}.env`;\n\nfunction uninstallLinux(): void {\n if (process.getuid?.() !== 0) {\n console.error('Error: uninstall must be run as root (use sudo)');\n process.exit(1);\n }\n\n // Stop and disable (ignore errors if not running/enabled)\n try {\n execSync(`systemctl stop ${SERVICE_NAME}`, { stdio: 'ignore' });\n } catch {\n // not running — fine\n }\n try {\n execSync(`systemctl disable ${SERVICE_NAME}`, { stdio: 'ignore' });\n } catch {\n // not enabled — fine\n }\n\n // Remove files\n if (existsSync(SYSTEMD_SERVICE_FILE)) {\n unlinkSync(SYSTEMD_SERVICE_FILE);\n console.log(`Removed ${SYSTEMD_SERVICE_FILE}`);\n }\n if (existsSync(SYSTEMD_ENV_FILE)) {\n unlinkSync(SYSTEMD_ENV_FILE);\n console.log(`Removed ${SYSTEMD_ENV_FILE}`);\n }\n\n execSync('systemctl daemon-reload');\n console.log(`Service ${SERVICE_NAME} uninstalled.`);\n}\n\n// ── Public API ──────────────────────────────────────────────────────────────\n\nexport function uninstall(): void {\n if (process.platform === 'darwin') {\n uninstallMac();\n } else if (process.platform === 'linux') {\n uninstallLinux();\n } else {\n console.error(`Unsupported platform: ${process.platform}`);\n process.exit(1);\n }\n}\n"]}
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { PluginLogger, DeskFreeClient, DeskFreeTool, ChatMessage, RuntimeBootstrapConfig } from '@deskfree/core';
1
+ import { PluginLogger, AgentContext, DeskFreeClient, DeskFreeTool, ChatMessage, RuntimeBootstrapConfig } from '@deskfree/core';
2
2
  import * as _anthropic_ai_claude_agent_sdk from '@anthropic-ai/claude-agent-sdk';
3
3
  import { McpSdkServerConfigWithInstance, SDKMessage, SDKUserMessage, Query, tool } from '@anthropic-ai/claude-agent-sdk';
4
4
 
@@ -28,6 +28,8 @@ interface OrchestratorQueryOptions {
28
28
  sessionId?: string;
29
29
  /** Path to user's Claude Code executable (uses bundled CLI if omitted). */
30
30
  claudeCodePath?: string;
31
+ /** Runtime context for templated system prompt. Falls back to static directive if omitted. */
32
+ agentContext?: AgentContext;
31
33
  }
32
34
  /**
33
35
  * Run the orchestrator agent. Returns an async iterable of SDKMessage events.
@@ -44,6 +46,8 @@ interface HeartbeatOptions {
44
46
  model: string;
45
47
  /** Path to user's Claude Code executable (uses bundled CLI if omitted). */
46
48
  claudeCodePath?: string;
49
+ /** Runtime context for templated system prompt. Falls back to static directive if omitted. */
50
+ agentContext?: AgentContext;
47
51
  }
48
52
  /**
49
53
  * Run a one-shot heartbeat query (no session persistence).
@@ -56,6 +60,8 @@ interface WorkerQueryOptions {
56
60
  model: string;
57
61
  /** Agent SDK session ID to resume (for multi-turn task conversations). */
58
62
  sessionId?: string;
63
+ /** Runtime context for templated system prompt. Falls back to static directive if omitted. */
64
+ agentContext?: AgentContext;
59
65
  }
60
66
  /**
61
67
  * Run the worker agent directly. Returns a Query (async iterable of
@@ -111,6 +117,8 @@ interface WorkerManagerDeps {
111
117
  dailyLogCharBudget?: number;
112
118
  /** Path to persist session history JSON (taskId → sessionId). */
113
119
  sessionHistoryPath?: string;
120
+ /** Runtime context for templated system prompts. */
121
+ agentContext?: AgentContext;
114
122
  }
115
123
  declare class WorkerManager {
116
124
  private workers;
@@ -386,6 +394,10 @@ interface RuntimeConfig extends LocalConfig {
386
394
  baseUrl?: string;
387
395
  /** Bot ID for this runtime instance */
388
396
  botId: string;
397
+ /** Bot's display name (e.g. "Sofia") */
398
+ botName: string;
399
+ /** Deployment type (aws, docker, local) */
400
+ deploymentType: 'aws' | 'docker' | 'local' | null;
389
401
  /** File ID for the bot's Memory file (null if not created yet) */
390
402
  memoryFileId: string | null;
391
403
  /** Hour of day (0-23) in local time for the nightly sleep cycle (null = disabled) */