@intutic/cli 0.1.0 ā 0.2.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/dist/cli.js +309 -0
- package/dist/cli.js.map +1 -1
- package/dist/commands/benchmark.d.ts +31 -0
- package/dist/commands/benchmark.d.ts.map +1 -0
- package/dist/commands/benchmark.js +211 -0
- package/dist/commands/benchmark.js.map +1 -0
- package/dist/commands/connect.d.ts +8 -6
- package/dist/commands/connect.d.ts.map +1 -1
- package/dist/commands/connect.js +322 -82
- package/dist/commands/connect.js.map +1 -1
- package/dist/commands/enterprise-install.d.ts +36 -0
- package/dist/commands/enterprise-install.d.ts.map +1 -0
- package/dist/commands/enterprise-install.js +289 -0
- package/dist/commands/enterprise-install.js.map +1 -0
- package/dist/commands/eval.d.ts +13 -0
- package/dist/commands/eval.d.ts.map +1 -0
- package/dist/commands/eval.js +67 -0
- package/dist/commands/eval.js.map +1 -0
- package/dist/commands/exec.d.ts +34 -0
- package/dist/commands/exec.d.ts.map +1 -0
- package/dist/commands/exec.js +114 -0
- package/dist/commands/exec.js.map +1 -0
- package/dist/commands/exec.test.d.ts +2 -0
- package/dist/commands/exec.test.d.ts.map +1 -0
- package/dist/commands/exec.test.js +29 -0
- package/dist/commands/exec.test.js.map +1 -0
- package/dist/commands/export.d.ts +21 -0
- package/dist/commands/export.d.ts.map +1 -0
- package/dist/commands/export.js +116 -0
- package/dist/commands/export.js.map +1 -0
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +28 -2
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/install-daemon.d.ts +61 -0
- package/dist/commands/install-daemon.d.ts.map +1 -0
- package/dist/commands/install-daemon.js +691 -0
- package/dist/commands/install-daemon.js.map +1 -0
- package/dist/commands/install-daemon.test.d.ts +2 -0
- package/dist/commands/install-daemon.test.d.ts.map +1 -0
- package/dist/commands/install-daemon.test.js +93 -0
- package/dist/commands/install-daemon.test.js.map +1 -0
- package/dist/commands/login.js +2 -2
- package/dist/commands/login.js.map +1 -1
- package/dist/commands/logout.js +1 -1
- package/dist/commands/logout.js.map +1 -1
- package/dist/commands/mdm.d.ts +23 -0
- package/dist/commands/mdm.d.ts.map +1 -0
- package/dist/commands/mdm.js +134 -0
- package/dist/commands/mdm.js.map +1 -0
- package/dist/commands/sop-audit.d.ts +17 -0
- package/dist/commands/sop-audit.d.ts.map +1 -0
- package/dist/commands/sop-audit.js +136 -0
- package/dist/commands/sop-audit.js.map +1 -0
- package/dist/commands/status.d.ts.map +1 -1
- package/dist/commands/status.js +53 -1
- package/dist/commands/status.js.map +1 -1
- package/dist/commands/syncContext.d.ts +18 -0
- package/dist/commands/syncContext.d.ts.map +1 -0
- package/dist/commands/syncContext.js +37 -0
- package/dist/commands/syncContext.js.map +1 -0
- package/dist/commands/traces.d.ts +13 -0
- package/dist/commands/traces.d.ts.map +1 -1
- package/dist/commands/traces.js +104 -10
- package/dist/commands/traces.js.map +1 -1
- package/dist/commands/whoami.js +1 -1
- package/dist/commands/whoami.js.map +1 -1
- package/dist/config/keychain.d.ts +28 -0
- package/dist/config/keychain.d.ts.map +1 -0
- package/dist/config/keychain.js +99 -0
- package/dist/config/keychain.js.map +1 -0
- package/dist/config/store.d.ts +3 -3
- package/dist/config/store.d.ts.map +1 -1
- package/dist/config/store.js +30 -6
- package/dist/config/store.js.map +1 -1
- package/dist/harness/aider.d.ts +4 -3
- package/dist/harness/aider.d.ts.map +1 -1
- package/dist/harness/aider.js +13 -27
- package/dist/harness/aider.js.map +1 -1
- package/dist/harness/claudeDesktop.d.ts +18 -0
- package/dist/harness/claudeDesktop.d.ts.map +1 -0
- package/dist/harness/claudeDesktop.js +69 -0
- package/dist/harness/claudeDesktop.js.map +1 -0
- package/dist/harness/cline.d.ts +13 -0
- package/dist/harness/cline.d.ts.map +1 -0
- package/dist/harness/cline.js +75 -0
- package/dist/harness/cline.js.map +1 -0
- package/dist/harness/codex.d.ts +4 -4
- package/dist/harness/codex.d.ts.map +1 -1
- package/dist/harness/codex.js +33 -21
- package/dist/harness/codex.js.map +1 -1
- package/dist/harness/continue.d.ts +14 -0
- package/dist/harness/continue.d.ts.map +1 -0
- package/dist/harness/continue.js +97 -0
- package/dist/harness/continue.js.map +1 -0
- package/dist/harness/cursor.d.ts +13 -1
- package/dist/harness/cursor.d.ts.map +1 -1
- package/dist/harness/cursor.js +59 -3
- package/dist/harness/cursor.js.map +1 -1
- package/dist/harness/detector.d.ts +1 -1
- package/dist/harness/detector.d.ts.map +1 -1
- package/dist/harness/detector.js +13 -1
- package/dist/harness/detector.js.map +1 -1
- package/dist/harness/goose.d.ts +13 -0
- package/dist/harness/goose.d.ts.map +1 -0
- package/dist/harness/goose.js +45 -0
- package/dist/harness/goose.js.map +1 -0
- package/dist/harness/n8n.d.ts +8 -4
- package/dist/harness/n8n.d.ts.map +1 -1
- package/dist/harness/n8n.js +108 -13
- package/dist/harness/n8n.js.map +1 -1
- package/dist/harness/openWebUI.d.ts +13 -0
- package/dist/harness/openWebUI.d.ts.map +1 -0
- package/dist/harness/openWebUI.js +25 -0
- package/dist/harness/openWebUI.js.map +1 -0
- package/dist/harness/openhands.d.ts +3 -3
- package/dist/harness/openhands.d.ts.map +1 -1
- package/dist/harness/openhands.js +13 -9
- package/dist/harness/openhands.js.map +1 -1
- package/dist/harness/rooCode.d.ts +14 -0
- package/dist/harness/rooCode.d.ts.map +1 -0
- package/dist/harness/rooCode.js +77 -0
- package/dist/harness/rooCode.js.map +1 -0
- package/dist/harness/types.d.ts.map +1 -1
- package/dist/harness/types.js +6 -0
- package/dist/harness/types.js.map +1 -1
- package/dist/harness/vscodeSettingsWriter.d.ts +40 -0
- package/dist/harness/vscodeSettingsWriter.d.ts.map +1 -0
- package/dist/harness/vscodeSettingsWriter.js +116 -0
- package/dist/harness/vscodeSettingsWriter.js.map +1 -0
- package/dist/harness/windsurf.d.ts +13 -1
- package/dist/harness/windsurf.d.ts.map +1 -1
- package/dist/harness/windsurf.js +58 -3
- package/dist/harness/windsurf.js.map +1 -1
- package/dist/lib/api.d.ts +2 -0
- package/dist/lib/api.d.ts.map +1 -1
- package/dist/lib/api.js +3 -0
- package/dist/lib/api.js.map +1 -1
- package/dist/lib/envInjector.d.ts +24 -0
- package/dist/lib/envInjector.d.ts.map +1 -0
- package/dist/lib/envInjector.js +146 -0
- package/dist/lib/envInjector.js.map +1 -0
- package/dist/lib/envInjector.test.d.ts +2 -0
- package/dist/lib/envInjector.test.d.ts.map +1 -0
- package/dist/lib/envInjector.test.js +32 -0
- package/dist/lib/envInjector.test.js.map +1 -0
- package/dist/lib/gitHooks.d.ts +19 -0
- package/dist/lib/gitHooks.d.ts.map +1 -0
- package/dist/lib/gitHooks.js +58 -0
- package/dist/lib/gitHooks.js.map +1 -0
- package/dist/lib/onboarding.d.ts +17 -0
- package/dist/lib/onboarding.d.ts.map +1 -0
- package/dist/lib/onboarding.js +164 -0
- package/dist/lib/onboarding.js.map +1 -0
- package/dist/lib/process.d.ts +53 -0
- package/dist/lib/process.d.ts.map +1 -0
- package/dist/lib/process.js +181 -0
- package/dist/lib/process.js.map +1 -0
- package/dist/lib/process.test.d.ts +2 -0
- package/dist/lib/process.test.d.ts.map +1 -0
- package/dist/lib/process.test.js +44 -0
- package/dist/lib/process.test.js.map +1 -0
- package/package.json +39 -17
|
@@ -0,0 +1,691 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* install-daemon.ts ā System-level sync-daemon & mcp-daemon persistence installer.
|
|
3
|
+
*
|
|
4
|
+
* Registers the Intutic sync-daemon or mcp-daemon as system-level services so they
|
|
5
|
+
* auto-start on login/boot and restart automatically on any exit.
|
|
6
|
+
*
|
|
7
|
+
* Platform support:
|
|
8
|
+
* - macOS : LaunchAgent/LaunchDaemon (LaunchDaemon requires root/system flag)
|
|
9
|
+
* - Linux : systemd user/system service (system service requires root/system flag)
|
|
10
|
+
*
|
|
11
|
+
* WS-5 ā Q3 Layer 4 (LaunchAgent / systemd persistence) & WS-5MCP
|
|
12
|
+
*
|
|
13
|
+
* @module
|
|
14
|
+
*/
|
|
15
|
+
import * as fs from 'node:fs/promises';
|
|
16
|
+
import * as path from 'node:path';
|
|
17
|
+
import * as os from 'node:os';
|
|
18
|
+
import { execFileSync } from 'node:child_process';
|
|
19
|
+
import { createLogger } from '@intutic/logger';
|
|
20
|
+
import { loadConfig } from '../config/store.js';
|
|
21
|
+
const log = createLogger('cli-install-daemon');
|
|
22
|
+
// āā Error definitions āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
23
|
+
export class ElevationRequiredError extends Error {
|
|
24
|
+
constructor(targetPath) {
|
|
25
|
+
super(`System-level operation requires root privileges to access ${targetPath}. Try running with sudo.`);
|
|
26
|
+
this.name = 'ElevationRequiredError';
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
// āā Helpers āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
30
|
+
export function checkRootPrivileges(system, targetPath = '/Library/LaunchDaemons/ or /etc/systemd/system/') {
|
|
31
|
+
if (system && typeof process.getuid === 'function' && process.getuid() !== 0) {
|
|
32
|
+
throw new ElevationRequiredError(targetPath);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
export function getPaths(system, isMcp, platform = process.platform) {
|
|
36
|
+
const label = isMcp ? 'ai.intutic.mcp-daemon' : 'ai.intutic.sync-daemon';
|
|
37
|
+
const unitName = isMcp ? 'intutic-mcp-daemon.service' : 'intutic-sync-daemon.service';
|
|
38
|
+
if (platform === 'darwin') {
|
|
39
|
+
const dir = system ? '/Library/LaunchDaemons' : path.join(os.homedir(), 'Library', 'LaunchAgents');
|
|
40
|
+
const plistPath = path.join(dir, `${label}.plist`);
|
|
41
|
+
const logsDir = system ? '/Library/Logs/Intutic' : path.join(os.homedir(), '.intutic', 'logs');
|
|
42
|
+
return {
|
|
43
|
+
label,
|
|
44
|
+
targetDir: dir,
|
|
45
|
+
targetPath: plistPath,
|
|
46
|
+
logsDir,
|
|
47
|
+
logPath: path.join(logsDir, isMcp ? 'mcp-daemon.log' : 'sync-daemon.log'),
|
|
48
|
+
errPath: path.join(logsDir, isMcp ? 'mcp-daemon.err' : 'sync-daemon.err'),
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
const dir = system ? '/etc/systemd/system' : path.join(os.homedir(), '.config', 'systemd', 'user');
|
|
53
|
+
const unitPath = path.join(dir, unitName);
|
|
54
|
+
const logsDir = system ? '/var/log/intutic' : path.join(os.homedir(), '.intutic', 'logs');
|
|
55
|
+
return {
|
|
56
|
+
label,
|
|
57
|
+
unitName,
|
|
58
|
+
targetDir: dir,
|
|
59
|
+
targetPath: unitPath,
|
|
60
|
+
logsDir,
|
|
61
|
+
logPath: path.join(logsDir, isMcp ? 'mcp-daemon.log' : 'sync-daemon.log'),
|
|
62
|
+
errPath: path.join(logsDir, isMcp ? 'mcp-daemon.err' : 'sync-daemon.err'),
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
// āā macOS LaunchAgent & LaunchDaemon āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
67
|
+
export function buildPlist(opts, system = false) {
|
|
68
|
+
const paths = getPaths(system, false, 'darwin');
|
|
69
|
+
const argStrings = [];
|
|
70
|
+
if (opts.binaryPath.endsWith('.js') || opts.binaryPath.endsWith('.ts')) {
|
|
71
|
+
argStrings.push(` <string>${process.execPath}</string>`);
|
|
72
|
+
argStrings.push(` <string>${opts.binaryPath}</string>`);
|
|
73
|
+
}
|
|
74
|
+
else if (opts.binaryPath.includes('node') && !opts.binaryPath.endsWith('intutic')) {
|
|
75
|
+
const scriptPath = process.argv[1];
|
|
76
|
+
argStrings.push(` <string>${opts.binaryPath}</string>`);
|
|
77
|
+
argStrings.push(` <string>${scriptPath}</string>`);
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
argStrings.push(` <string>${opts.binaryPath}</string>`);
|
|
81
|
+
}
|
|
82
|
+
const runAtLoad = system ? '' : '\n <key>RunAtLoad</key>\n <true/>';
|
|
83
|
+
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
84
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
85
|
+
<plist version="1.0">
|
|
86
|
+
<dict>
|
|
87
|
+
<key>Label</key>
|
|
88
|
+
<string>${paths.label}</string>
|
|
89
|
+
|
|
90
|
+
<key>ProgramArguments</key>
|
|
91
|
+
<array>
|
|
92
|
+
${argStrings.join('\n')}
|
|
93
|
+
<string>connect</string>
|
|
94
|
+
<string>--workspace-id</string>
|
|
95
|
+
<string>${opts.workspaceId}</string>
|
|
96
|
+
<string>--api-key</string>
|
|
97
|
+
<string>${opts.apiKey}</string>
|
|
98
|
+
<string>--control-plane-url</string>
|
|
99
|
+
<string>${opts.controlPlaneUrl}</string>
|
|
100
|
+
</array>
|
|
101
|
+
|
|
102
|
+
<key>KeepAlive</key>
|
|
103
|
+
<true/>
|
|
104
|
+
<key>ThrottleInterval</key>
|
|
105
|
+
<integer>5</integer>${runAtLoad}
|
|
106
|
+
|
|
107
|
+
<key>StandardOutPath</key>
|
|
108
|
+
<string>${paths.logPath}</string>
|
|
109
|
+
<key>StandardErrorPath</key>
|
|
110
|
+
<string>${paths.errPath}</string>
|
|
111
|
+
|
|
112
|
+
<key>EnvironmentVariables</key>
|
|
113
|
+
<dict>
|
|
114
|
+
<key>INTUTIC_WORKSPACE_ID</key>
|
|
115
|
+
<string>${opts.workspaceId}</string>
|
|
116
|
+
<key>INTUTIC_API_KEY</key>
|
|
117
|
+
<string>${opts.apiKey}</string>
|
|
118
|
+
<key>INTUTIC_CONTROL_PLANE_URL</key>
|
|
119
|
+
<string>${opts.controlPlaneUrl}</string>
|
|
120
|
+
</dict>
|
|
121
|
+
</dict>
|
|
122
|
+
</plist>
|
|
123
|
+
`;
|
|
124
|
+
}
|
|
125
|
+
export function buildMcpPlist(opts, system = false) {
|
|
126
|
+
const paths = getPaths(system, true, 'darwin');
|
|
127
|
+
const config = loadConfig();
|
|
128
|
+
const workspaceRoot = config?.workspaceRoot ?? process.cwd();
|
|
129
|
+
const daemonPath = path.join(workspaceRoot, 'packages', 'mcp-proxy', 'dist', 'daemon', 'index.js');
|
|
130
|
+
let execArgs = [];
|
|
131
|
+
try {
|
|
132
|
+
execFileSync('which', ['intutic-mcp-daemon'], { stdio: 'ignore' });
|
|
133
|
+
execArgs = ['intutic-mcp-daemon'];
|
|
134
|
+
}
|
|
135
|
+
catch {
|
|
136
|
+
execArgs = [process.execPath, daemonPath];
|
|
137
|
+
}
|
|
138
|
+
const programArgsXml = execArgs.map(arg => ` <string>${arg}</string>`).join('\n');
|
|
139
|
+
const runAtLoad = system ? '' : '\n <key>RunAtLoad</key>\n <true/>';
|
|
140
|
+
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
141
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
142
|
+
<plist version="1.0">
|
|
143
|
+
<dict>
|
|
144
|
+
<key>Label</key>
|
|
145
|
+
<string>${paths.label}</string>
|
|
146
|
+
|
|
147
|
+
<key>ProgramArguments</key>
|
|
148
|
+
<array>
|
|
149
|
+
${programArgsXml}
|
|
150
|
+
</array>
|
|
151
|
+
|
|
152
|
+
<key>KeepAlive</key>
|
|
153
|
+
<true/>
|
|
154
|
+
<key>ThrottleInterval</key>
|
|
155
|
+
<integer>5</integer>${runAtLoad}
|
|
156
|
+
|
|
157
|
+
<key>StandardOutPath</key>
|
|
158
|
+
<string>${paths.logPath}</string>
|
|
159
|
+
<key>StandardErrorPath</key>
|
|
160
|
+
<string>${paths.errPath}</string>
|
|
161
|
+
|
|
162
|
+
<key>EnvironmentVariables</key>
|
|
163
|
+
<dict>
|
|
164
|
+
<key>INTUTIC_WORKSPACE_ID</key>
|
|
165
|
+
<string>${opts.workspaceId}</string>
|
|
166
|
+
<key>INTUTIC_API_KEY</key>
|
|
167
|
+
<string>${opts.apiKey}</string>
|
|
168
|
+
<key>INTUTIC_CONTROL_PLANE_URL</key>
|
|
169
|
+
<string>${opts.controlPlaneUrl}</string>
|
|
170
|
+
<key>CONTROL_PLANE_URL</key>
|
|
171
|
+
<string>${opts.controlPlaneUrl}</string>
|
|
172
|
+
</dict>
|
|
173
|
+
</dict>
|
|
174
|
+
</plist>
|
|
175
|
+
`;
|
|
176
|
+
}
|
|
177
|
+
async function installMacos(opts, system = false, dryRun = false) {
|
|
178
|
+
const paths = getPaths(system, false, 'darwin');
|
|
179
|
+
if (!dryRun) {
|
|
180
|
+
checkRootPrivileges(system, paths.targetPath);
|
|
181
|
+
}
|
|
182
|
+
const plist = buildPlist(opts, system);
|
|
183
|
+
console.log(`\nš¦ Installing macOS Launch${system ? 'Daemon' : 'Agent'}: ${paths.targetPath}`);
|
|
184
|
+
console.log(` Binary : ${opts.binaryPath}`);
|
|
185
|
+
console.log(` Workspace: ${opts.workspaceId}`);
|
|
186
|
+
if (dryRun) {
|
|
187
|
+
console.log('\n[dry-run] Would write plist:');
|
|
188
|
+
console.log(plist);
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
await fs.mkdir(paths.targetDir, { recursive: true });
|
|
192
|
+
await fs.mkdir(paths.logsDir, { recursive: true });
|
|
193
|
+
try {
|
|
194
|
+
execFileSync('launchctl', ['unload', '-w', paths.targetPath], { stdio: 'ignore' });
|
|
195
|
+
}
|
|
196
|
+
catch { }
|
|
197
|
+
await fs.writeFile(paths.targetPath, plist, 'utf-8');
|
|
198
|
+
execFileSync('launchctl', ['load', '-w', paths.targetPath]);
|
|
199
|
+
console.log(`\nā
Launch${system ? 'Daemon' : 'Agent'} installed and started.`);
|
|
200
|
+
}
|
|
201
|
+
// āā Linux systemd āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
202
|
+
export function buildUnit(opts, system = false) {
|
|
203
|
+
const paths = getPaths(system, false, 'linux');
|
|
204
|
+
let execStart = '';
|
|
205
|
+
if (opts.binaryPath.endsWith('.js') || opts.binaryPath.endsWith('.ts')) {
|
|
206
|
+
execStart = `${process.execPath} ${opts.binaryPath}`;
|
|
207
|
+
}
|
|
208
|
+
else if (opts.binaryPath.includes('node') && !opts.binaryPath.endsWith('intutic')) {
|
|
209
|
+
const scriptPath = process.argv[1];
|
|
210
|
+
execStart = `${opts.binaryPath} ${scriptPath}`;
|
|
211
|
+
}
|
|
212
|
+
else {
|
|
213
|
+
execStart = opts.binaryPath;
|
|
214
|
+
}
|
|
215
|
+
return `[Unit]
|
|
216
|
+
Description=Intutic Sync Daemon ā Governance enforcement for AI agent harnesses
|
|
217
|
+
Documentation=https://docs.intutic.ai/daemon
|
|
218
|
+
After=network-online.target
|
|
219
|
+
Wants=network-online.target
|
|
220
|
+
|
|
221
|
+
[Service]
|
|
222
|
+
Type=simple
|
|
223
|
+
ExecStart=${execStart} connect \\
|
|
224
|
+
--workspace-id ${opts.workspaceId} \\
|
|
225
|
+
--api-key ${opts.apiKey} \\
|
|
226
|
+
--control-plane-url ${opts.controlPlaneUrl}
|
|
227
|
+
|
|
228
|
+
Restart=always
|
|
229
|
+
RestartSec=5
|
|
230
|
+
|
|
231
|
+
Environment=INTUTIC_WORKSPACE_ID=${opts.workspaceId}
|
|
232
|
+
Environment=INTUTIC_API_KEY=${opts.apiKey}
|
|
233
|
+
Environment=INTUTIC_CONTROL_PLANE_URL=${opts.controlPlaneUrl}
|
|
234
|
+
|
|
235
|
+
StandardOutput=append:${paths.logPath}
|
|
236
|
+
StandardError=append:${paths.errPath}
|
|
237
|
+
|
|
238
|
+
[Install]
|
|
239
|
+
WantedBy=${system ? 'multi-user.target' : 'default.target'}
|
|
240
|
+
`;
|
|
241
|
+
}
|
|
242
|
+
export function buildMcpUnit(opts, system = false) {
|
|
243
|
+
const paths = getPaths(system, true, 'linux');
|
|
244
|
+
const config = loadConfig();
|
|
245
|
+
const workspaceRoot = config?.workspaceRoot ?? process.cwd();
|
|
246
|
+
const daemonPath = path.join(workspaceRoot, 'packages', 'mcp-proxy', 'dist', 'daemon', 'index.js');
|
|
247
|
+
let execStart = '';
|
|
248
|
+
try {
|
|
249
|
+
execFileSync('which', ['intutic-mcp-daemon'], { stdio: 'ignore' });
|
|
250
|
+
execStart = 'intutic-mcp-daemon';
|
|
251
|
+
}
|
|
252
|
+
catch {
|
|
253
|
+
execStart = `${process.execPath} ${daemonPath}`;
|
|
254
|
+
}
|
|
255
|
+
return `[Unit]
|
|
256
|
+
Description=Intutic MCP Daemon ā Persistent policy and telemetry cache for MCP harnesses
|
|
257
|
+
Documentation=https://docs.intutic.ai/daemon
|
|
258
|
+
After=network-online.target
|
|
259
|
+
Wants=network-online.target
|
|
260
|
+
|
|
261
|
+
[Service]
|
|
262
|
+
Type=simple
|
|
263
|
+
ExecStart=${execStart}
|
|
264
|
+
|
|
265
|
+
Restart=always
|
|
266
|
+
RestartSec=5
|
|
267
|
+
|
|
268
|
+
Environment=INTUTIC_WORKSPACE_ID=${opts.workspaceId}
|
|
269
|
+
Environment=INTUTIC_API_KEY=${opts.apiKey}
|
|
270
|
+
Environment=INTUTIC_CONTROL_PLANE_URL=${opts.controlPlaneUrl}
|
|
271
|
+
Environment=CONTROL_PLANE_URL=${opts.controlPlaneUrl}
|
|
272
|
+
|
|
273
|
+
StandardOutput=append:${paths.logPath}
|
|
274
|
+
StandardError=append:${paths.errPath}
|
|
275
|
+
|
|
276
|
+
[Install]
|
|
277
|
+
WantedBy=${system ? 'multi-user.target' : 'default.target'}
|
|
278
|
+
`;
|
|
279
|
+
}
|
|
280
|
+
async function installLinux(opts, system = false, dryRun = false) {
|
|
281
|
+
const paths = getPaths(system, false, 'linux');
|
|
282
|
+
if (!dryRun) {
|
|
283
|
+
checkRootPrivileges(system, paths.targetPath);
|
|
284
|
+
}
|
|
285
|
+
const unit = buildUnit(opts, system);
|
|
286
|
+
console.log(`\nš¦ Installing systemd ${system ? 'system' : 'user'} unit: ${paths.targetPath}`);
|
|
287
|
+
console.log(` Binary : ${opts.binaryPath}`);
|
|
288
|
+
console.log(` Workspace: ${opts.workspaceId}`);
|
|
289
|
+
if (dryRun) {
|
|
290
|
+
console.log('\n[dry-run] Would write unit:');
|
|
291
|
+
console.log(unit);
|
|
292
|
+
return;
|
|
293
|
+
}
|
|
294
|
+
await fs.mkdir(paths.targetDir, { recursive: true });
|
|
295
|
+
await fs.mkdir(paths.logsDir, { recursive: true });
|
|
296
|
+
await fs.writeFile(paths.targetPath, unit, 'utf-8');
|
|
297
|
+
const cmdArgs = system ? [] : ['--user'];
|
|
298
|
+
execFileSync('systemctl', [...cmdArgs, 'daemon-reload']);
|
|
299
|
+
execFileSync('systemctl', [...cmdArgs, 'enable', '--now', paths.unitName]);
|
|
300
|
+
console.log(`\nā
systemd ${system ? 'system' : 'user'} unit installed and started.`);
|
|
301
|
+
}
|
|
302
|
+
// āā Public API (sync-daemon) āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
303
|
+
export async function installDaemon(opts) {
|
|
304
|
+
const resolved = {
|
|
305
|
+
workspaceId: opts.workspaceId,
|
|
306
|
+
apiKey: opts.apiKey,
|
|
307
|
+
binaryPath: opts.binaryPath ?? process.execPath,
|
|
308
|
+
controlPlaneUrl: opts.controlPlaneUrl ?? 'https://api.intutic.ai',
|
|
309
|
+
};
|
|
310
|
+
const system = !!opts.system;
|
|
311
|
+
switch (process.platform) {
|
|
312
|
+
case 'darwin':
|
|
313
|
+
await installMacos(resolved, system, opts.dryRun);
|
|
314
|
+
break;
|
|
315
|
+
case 'linux':
|
|
316
|
+
await installLinux(resolved, system, opts.dryRun);
|
|
317
|
+
break;
|
|
318
|
+
default:
|
|
319
|
+
console.log(`\nā ļø Platform '${process.platform}' is not supported by install-daemon.`);
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
export async function uninstallDaemon(opts = {}) {
|
|
323
|
+
const system = !!opts.system;
|
|
324
|
+
const paths = getPaths(system, false);
|
|
325
|
+
if (!opts.dryRun) {
|
|
326
|
+
checkRootPrivileges(system, paths.targetPath);
|
|
327
|
+
}
|
|
328
|
+
switch (process.platform) {
|
|
329
|
+
case 'darwin': {
|
|
330
|
+
console.log(`\nš Removing Launch${system ? 'Daemon' : 'Agent'}: ${paths.targetPath}`);
|
|
331
|
+
if (!opts.dryRun) {
|
|
332
|
+
try {
|
|
333
|
+
execFileSync('launchctl', ['unload', '-w', paths.targetPath], { stdio: 'ignore' });
|
|
334
|
+
}
|
|
335
|
+
catch { }
|
|
336
|
+
try {
|
|
337
|
+
await fs.unlink(paths.targetPath);
|
|
338
|
+
}
|
|
339
|
+
catch { }
|
|
340
|
+
}
|
|
341
|
+
console.log(`ā
Launch${system ? 'Daemon' : 'Agent'} removed.`);
|
|
342
|
+
break;
|
|
343
|
+
}
|
|
344
|
+
case 'linux': {
|
|
345
|
+
console.log(`\nš Removing systemd ${system ? 'system' : 'user'} unit: ${paths.targetPath}`);
|
|
346
|
+
if (!opts.dryRun) {
|
|
347
|
+
const cmdArgs = system ? [] : ['--user'];
|
|
348
|
+
try {
|
|
349
|
+
execFileSync('systemctl', [...cmdArgs, 'disable', '--now', paths.unitName], { stdio: 'ignore' });
|
|
350
|
+
}
|
|
351
|
+
catch { }
|
|
352
|
+
try {
|
|
353
|
+
await fs.unlink(paths.targetPath);
|
|
354
|
+
execFileSync('systemctl', [...cmdArgs, 'daemon-reload'], { stdio: 'ignore' });
|
|
355
|
+
}
|
|
356
|
+
catch { }
|
|
357
|
+
}
|
|
358
|
+
console.log(`ā
systemd ${system ? 'system' : 'user'} unit removed.`);
|
|
359
|
+
break;
|
|
360
|
+
}
|
|
361
|
+
default:
|
|
362
|
+
console.log(`\nā ļø Platform '${process.platform}' is not supported.`);
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
export async function daemonStatus() {
|
|
366
|
+
switch (process.platform) {
|
|
367
|
+
case 'darwin': {
|
|
368
|
+
for (const system of [false, true]) {
|
|
369
|
+
const paths = getPaths(system, false, 'darwin');
|
|
370
|
+
const plistExists = await fs.access(paths.targetPath).then(() => true).catch(() => false);
|
|
371
|
+
const scopeStr = system ? 'System-level (LaunchDaemon)' : 'User-level (LaunchAgent)';
|
|
372
|
+
if (plistExists) {
|
|
373
|
+
console.log(`ā
Daemon: ${scopeStr} installed at ${paths.targetPath}`);
|
|
374
|
+
try {
|
|
375
|
+
execFileSync('launchctl', ['list', paths.label], { stdio: 'inherit' });
|
|
376
|
+
}
|
|
377
|
+
catch {
|
|
378
|
+
console.log(` ā ļø ${scopeStr} plist file exists but is not loaded.`);
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
else {
|
|
382
|
+
console.log(`⬠Daemon: ${scopeStr} not installed`);
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
break;
|
|
386
|
+
}
|
|
387
|
+
case 'linux': {
|
|
388
|
+
for (const system of [false, true]) {
|
|
389
|
+
const paths = getPaths(system, false, 'linux');
|
|
390
|
+
const scopeStr = system ? 'System-level' : 'User-level';
|
|
391
|
+
const cmdArgs = system ? [] : ['--user'];
|
|
392
|
+
try {
|
|
393
|
+
console.log(`\n--- ${scopeStr} Status ---`);
|
|
394
|
+
execFileSync('systemctl', [...cmdArgs, 'status', paths.unitName], { stdio: 'inherit' });
|
|
395
|
+
}
|
|
396
|
+
catch {
|
|
397
|
+
console.log(`⬠Daemon: ${scopeStr} not running`);
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
break;
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
export async function daemonStop() {
|
|
405
|
+
switch (process.platform) {
|
|
406
|
+
case 'darwin': {
|
|
407
|
+
for (const system of [false, true]) {
|
|
408
|
+
const paths = getPaths(system, false, 'darwin');
|
|
409
|
+
const plistExists = await fs.access(paths.targetPath).then(() => true).catch(() => false);
|
|
410
|
+
if (plistExists) {
|
|
411
|
+
console.log(`\nš Stopping Launch${system ? 'Daemon' : 'Agent'}: ${paths.label}`);
|
|
412
|
+
try {
|
|
413
|
+
execFileSync('launchctl', ['unload', paths.targetPath], { stdio: 'ignore' });
|
|
414
|
+
console.log(`ā
Successfully stopped ${system ? 'system' : 'user'} sync-daemon.`);
|
|
415
|
+
}
|
|
416
|
+
catch (e) {
|
|
417
|
+
console.log(`ā Failed to stop ${system ? 'system' : 'user'} sync-daemon: ${e.message}`);
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
break;
|
|
422
|
+
}
|
|
423
|
+
case 'linux': {
|
|
424
|
+
for (const system of [false, true]) {
|
|
425
|
+
const paths = getPaths(system, false, 'linux');
|
|
426
|
+
const unitExists = await fs.access(paths.targetPath).then(() => true).catch(() => false);
|
|
427
|
+
if (unitExists) {
|
|
428
|
+
try {
|
|
429
|
+
const cmdArgs = system ? [] : ['--user'];
|
|
430
|
+
execFileSync('systemctl', [...cmdArgs, 'stop', paths.unitName], { stdio: 'ignore' });
|
|
431
|
+
console.log(`ā
Successfully stopped ${system ? 'system' : 'user'} sync-daemon unit.`);
|
|
432
|
+
}
|
|
433
|
+
catch (e) {
|
|
434
|
+
console.log(`ā Failed to stop ${system ? 'system' : 'user'} sync-daemon unit: ${e.message}`);
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
break;
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
export async function daemonStart() {
|
|
443
|
+
switch (process.platform) {
|
|
444
|
+
case 'darwin': {
|
|
445
|
+
for (const system of [false, true]) {
|
|
446
|
+
const paths = getPaths(system, false, 'darwin');
|
|
447
|
+
const plistExists = await fs.access(paths.targetPath).then(() => true).catch(() => false);
|
|
448
|
+
if (plistExists) {
|
|
449
|
+
try {
|
|
450
|
+
execFileSync('launchctl', ['load', '-w', paths.targetPath], { stdio: 'ignore' });
|
|
451
|
+
console.log(`ā
Successfully started ${system ? 'system' : 'user'} sync-daemon.`);
|
|
452
|
+
}
|
|
453
|
+
catch (e) {
|
|
454
|
+
console.log(`ā Failed to start ${system ? 'system' : 'user'} sync-daemon: ${e.message}`);
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
break;
|
|
459
|
+
}
|
|
460
|
+
case 'linux': {
|
|
461
|
+
for (const system of [false, true]) {
|
|
462
|
+
const paths = getPaths(system, false, 'linux');
|
|
463
|
+
const unitExists = await fs.access(paths.targetPath).then(() => true).catch(() => false);
|
|
464
|
+
if (unitExists) {
|
|
465
|
+
try {
|
|
466
|
+
const cmdArgs = system ? [] : ['--user'];
|
|
467
|
+
execFileSync('systemctl', [...cmdArgs, 'start', paths.unitName], { stdio: 'ignore' });
|
|
468
|
+
console.log(`ā
Successfully started ${system ? 'system' : 'user'} sync-daemon unit.`);
|
|
469
|
+
}
|
|
470
|
+
catch (e) {
|
|
471
|
+
console.log(`ā Failed to start ${system ? 'system' : 'user'} sync-daemon unit: ${e.message}`);
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
break;
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
// āā Public API (mcp-daemon) āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
480
|
+
export async function installMcpDaemon(opts) {
|
|
481
|
+
const resolved = {
|
|
482
|
+
workspaceId: opts.workspaceId,
|
|
483
|
+
apiKey: opts.apiKey,
|
|
484
|
+
controlPlaneUrl: opts.controlPlaneUrl ?? 'https://api.intutic.ai',
|
|
485
|
+
};
|
|
486
|
+
const system = !!opts.system;
|
|
487
|
+
switch (process.platform) {
|
|
488
|
+
case 'darwin': {
|
|
489
|
+
const paths = getPaths(system, true, 'darwin');
|
|
490
|
+
if (!opts.dryRun) {
|
|
491
|
+
checkRootPrivileges(system, paths.targetPath);
|
|
492
|
+
}
|
|
493
|
+
const plist = buildMcpPlist(resolved, system);
|
|
494
|
+
console.log(`\nš¦ Installing MCP macOS Launch${system ? 'Daemon' : 'Agent'}: ${paths.targetPath}`);
|
|
495
|
+
if (opts.dryRun) {
|
|
496
|
+
console.log('\n[dry-run] Would write plist:');
|
|
497
|
+
console.log(plist);
|
|
498
|
+
return;
|
|
499
|
+
}
|
|
500
|
+
await fs.mkdir(paths.targetDir, { recursive: true });
|
|
501
|
+
await fs.mkdir(paths.logsDir, { recursive: true });
|
|
502
|
+
try {
|
|
503
|
+
execFileSync('launchctl', ['unload', '-w', paths.targetPath], { stdio: 'ignore' });
|
|
504
|
+
}
|
|
505
|
+
catch { }
|
|
506
|
+
await fs.writeFile(paths.targetPath, plist, 'utf-8');
|
|
507
|
+
execFileSync('launchctl', ['load', '-w', paths.targetPath]);
|
|
508
|
+
console.log(`\nā
MCP Launch${system ? 'Daemon' : 'Agent'} installed and started.`);
|
|
509
|
+
break;
|
|
510
|
+
}
|
|
511
|
+
case 'linux': {
|
|
512
|
+
const paths = getPaths(system, true, 'linux');
|
|
513
|
+
if (!opts.dryRun) {
|
|
514
|
+
checkRootPrivileges(system, paths.targetPath);
|
|
515
|
+
}
|
|
516
|
+
const unit = buildMcpUnit(resolved, system);
|
|
517
|
+
console.log(`\nš¦ Installing MCP systemd ${system ? 'system' : 'user'} unit: ${paths.targetPath}`);
|
|
518
|
+
if (opts.dryRun) {
|
|
519
|
+
console.log('\n[dry-run] Would write unit:');
|
|
520
|
+
console.log(unit);
|
|
521
|
+
return;
|
|
522
|
+
}
|
|
523
|
+
await fs.mkdir(paths.targetDir, { recursive: true });
|
|
524
|
+
await fs.mkdir(paths.logsDir, { recursive: true });
|
|
525
|
+
await fs.writeFile(paths.targetPath, unit, 'utf-8');
|
|
526
|
+
const cmdArgs = system ? [] : ['--user'];
|
|
527
|
+
execFileSync('systemctl', [...cmdArgs, 'daemon-reload']);
|
|
528
|
+
execFileSync('systemctl', [...cmdArgs, 'enable', '--now', paths.unitName]);
|
|
529
|
+
console.log(`\nā
MCP systemd ${system ? 'system' : 'user'} unit installed and started.`);
|
|
530
|
+
break;
|
|
531
|
+
}
|
|
532
|
+
default:
|
|
533
|
+
console.log(`\nā ļø Platform '${process.platform}' not supported.`);
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
export async function uninstallMcpDaemon(opts = {}) {
|
|
537
|
+
const system = !!opts.system;
|
|
538
|
+
const paths = getPaths(system, true);
|
|
539
|
+
if (!opts.dryRun) {
|
|
540
|
+
checkRootPrivileges(system, paths.targetPath);
|
|
541
|
+
}
|
|
542
|
+
switch (process.platform) {
|
|
543
|
+
case 'darwin': {
|
|
544
|
+
console.log(`\nš Removing MCP Launch${system ? 'Daemon' : 'Agent'}: ${paths.targetPath}`);
|
|
545
|
+
if (!opts.dryRun) {
|
|
546
|
+
try {
|
|
547
|
+
execFileSync('launchctl', ['unload', '-w', paths.targetPath], { stdio: 'ignore' });
|
|
548
|
+
}
|
|
549
|
+
catch { }
|
|
550
|
+
try {
|
|
551
|
+
await fs.unlink(paths.targetPath);
|
|
552
|
+
}
|
|
553
|
+
catch { }
|
|
554
|
+
}
|
|
555
|
+
console.log(`ā
MCP Launch${system ? 'Daemon' : 'Agent'} removed.`);
|
|
556
|
+
break;
|
|
557
|
+
}
|
|
558
|
+
case 'linux': {
|
|
559
|
+
console.log(`\nš Removing MCP systemd ${system ? 'system' : 'user'} unit: ${paths.targetPath}`);
|
|
560
|
+
if (!opts.dryRun) {
|
|
561
|
+
const cmdArgs = system ? [] : ['--user'];
|
|
562
|
+
try {
|
|
563
|
+
execFileSync('systemctl', [...cmdArgs, 'disable', '--now', paths.unitName], { stdio: 'ignore' });
|
|
564
|
+
}
|
|
565
|
+
catch { }
|
|
566
|
+
try {
|
|
567
|
+
await fs.unlink(paths.targetPath);
|
|
568
|
+
execFileSync('systemctl', [...cmdArgs, 'daemon-reload'], { stdio: 'ignore' });
|
|
569
|
+
}
|
|
570
|
+
catch { }
|
|
571
|
+
}
|
|
572
|
+
console.log(`ā
MCP systemd ${system ? 'system' : 'user'} unit removed.`);
|
|
573
|
+
break;
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
export async function mcpDaemonStatus() {
|
|
578
|
+
switch (process.platform) {
|
|
579
|
+
case 'darwin': {
|
|
580
|
+
for (const system of [false, true]) {
|
|
581
|
+
const paths = getPaths(system, true, 'darwin');
|
|
582
|
+
const plistExists = await fs.access(paths.targetPath).then(() => true).catch(() => false);
|
|
583
|
+
const scopeStr = system ? 'System-level (LaunchDaemon)' : 'User-level (LaunchAgent)';
|
|
584
|
+
if (plistExists) {
|
|
585
|
+
console.log(`ā
MCP Daemon: ${scopeStr} installed at ${paths.targetPath}`);
|
|
586
|
+
try {
|
|
587
|
+
execFileSync('launchctl', ['list', paths.label], { stdio: 'inherit' });
|
|
588
|
+
}
|
|
589
|
+
catch {
|
|
590
|
+
console.log(` ā ļø MCP ${scopeStr} plist exists but is not loaded.`);
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
else {
|
|
594
|
+
console.log(`⬠MCP Daemon: ${scopeStr} not installed`);
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
break;
|
|
598
|
+
}
|
|
599
|
+
case 'linux': {
|
|
600
|
+
for (const system of [false, true]) {
|
|
601
|
+
const paths = getPaths(system, true, 'linux');
|
|
602
|
+
const scopeStr = system ? 'System-level' : 'User-level';
|
|
603
|
+
const cmdArgs = system ? [] : ['--user'];
|
|
604
|
+
try {
|
|
605
|
+
console.log(`\n--- MCP ${scopeStr} Status ---`);
|
|
606
|
+
execFileSync('systemctl', [...cmdArgs, 'status', paths.unitName], { stdio: 'inherit' });
|
|
607
|
+
}
|
|
608
|
+
catch {
|
|
609
|
+
console.log(`⬠MCP Daemon: ${scopeStr} not running`);
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
break;
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
}
|
|
616
|
+
export async function mcpDaemonStop() {
|
|
617
|
+
switch (process.platform) {
|
|
618
|
+
case 'darwin': {
|
|
619
|
+
for (const system of [false, true]) {
|
|
620
|
+
const paths = getPaths(system, true, 'darwin');
|
|
621
|
+
const plistExists = await fs.access(paths.targetPath).then(() => true).catch(() => false);
|
|
622
|
+
if (plistExists) {
|
|
623
|
+
console.log(`\nš Stopping MCP Launch${system ? 'Daemon' : 'Agent'}: ${paths.label}`);
|
|
624
|
+
try {
|
|
625
|
+
execFileSync('launchctl', ['unload', paths.targetPath], { stdio: 'ignore' });
|
|
626
|
+
console.log(`ā
Successfully stopped MCP Launch${system ? 'Daemon' : 'Agent'}.`);
|
|
627
|
+
}
|
|
628
|
+
catch (e) {
|
|
629
|
+
console.log(`ā Failed to stop MCP Launch${system ? 'Daemon' : 'Agent'}: ${e.message}`);
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
}
|
|
633
|
+
break;
|
|
634
|
+
}
|
|
635
|
+
case 'linux': {
|
|
636
|
+
for (const system of [false, true]) {
|
|
637
|
+
const paths = getPaths(system, true, 'linux');
|
|
638
|
+
const unitExists = await fs.access(paths.targetPath).then(() => true).catch(() => false);
|
|
639
|
+
if (unitExists) {
|
|
640
|
+
try {
|
|
641
|
+
const cmdArgs = system ? [] : ['--user'];
|
|
642
|
+
execFileSync('systemctl', [...cmdArgs, 'stop', paths.unitName], { stdio: 'ignore' });
|
|
643
|
+
console.log(`ā
Successfully stopped MCP ${system ? 'system' : 'user'} unit.`);
|
|
644
|
+
}
|
|
645
|
+
catch (e) {
|
|
646
|
+
console.log(`ā Failed to stop MCP ${system ? 'system' : 'user'} unit: ${e.message}`);
|
|
647
|
+
}
|
|
648
|
+
}
|
|
649
|
+
}
|
|
650
|
+
break;
|
|
651
|
+
}
|
|
652
|
+
}
|
|
653
|
+
}
|
|
654
|
+
export async function mcpDaemonStart() {
|
|
655
|
+
switch (process.platform) {
|
|
656
|
+
case 'darwin': {
|
|
657
|
+
for (const system of [false, true]) {
|
|
658
|
+
const paths = getPaths(system, true, 'darwin');
|
|
659
|
+
const plistExists = await fs.access(paths.targetPath).then(() => true).catch(() => false);
|
|
660
|
+
if (plistExists) {
|
|
661
|
+
try {
|
|
662
|
+
execFileSync('launchctl', ['load', '-w', paths.targetPath], { stdio: 'ignore' });
|
|
663
|
+
console.log(`ā
Successfully started MCP Launch${system ? 'Daemon' : 'Agent'}.`);
|
|
664
|
+
}
|
|
665
|
+
catch (e) {
|
|
666
|
+
console.log(`ā Failed to start MCP Launch${system ? 'Daemon' : 'Agent'}: ${e.message}`);
|
|
667
|
+
}
|
|
668
|
+
}
|
|
669
|
+
}
|
|
670
|
+
break;
|
|
671
|
+
}
|
|
672
|
+
case 'linux': {
|
|
673
|
+
for (const system of [false, true]) {
|
|
674
|
+
const paths = getPaths(system, true, 'linux');
|
|
675
|
+
const unitExists = await fs.access(paths.targetPath).then(() => true).catch(() => false);
|
|
676
|
+
if (unitExists) {
|
|
677
|
+
try {
|
|
678
|
+
const cmdArgs = system ? [] : ['--user'];
|
|
679
|
+
execFileSync('systemctl', [...cmdArgs, 'start', paths.unitName], { stdio: 'ignore' });
|
|
680
|
+
console.log(`ā
Successfully started MCP ${system ? 'system' : 'user'} unit.`);
|
|
681
|
+
}
|
|
682
|
+
catch (e) {
|
|
683
|
+
console.log(`ā Failed to start MCP ${system ? 'system' : 'user'} unit: ${e.message}`);
|
|
684
|
+
}
|
|
685
|
+
}
|
|
686
|
+
}
|
|
687
|
+
break;
|
|
688
|
+
}
|
|
689
|
+
}
|
|
690
|
+
}
|
|
691
|
+
//# sourceMappingURL=install-daemon.js.map
|