@parall/daemon 1.30.0 → 1.32.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/bundle/manifest.json +17 -11
- package/bundle/package.json +1 -0
- package/bundle/parall-claude-agent.js +27671 -337
- package/bundle/parall-codex-agent.js +27715 -375
- package/bundle/parall-daemon.js +30421 -1355
- package/bundle/parall-openclaw-agent.js +51 -26
- package/dist/cli.d.ts +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +122 -72
- package/dist/clip-runtime/clip-installer.d.ts +44 -0
- package/dist/clip-runtime/clip-installer.d.ts.map +1 -0
- package/dist/clip-runtime/clip-installer.js +501 -0
- package/dist/clip-runtime/clip-provider.d.ts +76 -0
- package/dist/clip-runtime/clip-provider.d.ts.map +1 -0
- package/dist/clip-runtime/clip-provider.js +402 -0
- package/dist/clip-runtime/index.d.ts +7 -0
- package/dist/clip-runtime/index.d.ts.map +1 -0
- package/dist/clip-runtime/index.js +5 -0
- package/dist/clip-runtime/ipc.d.ts +94 -0
- package/dist/clip-runtime/ipc.d.ts.map +1 -0
- package/dist/clip-runtime/ipc.js +98 -0
- package/dist/clip-runtime/manifest.d.ts +74 -0
- package/dist/clip-runtime/manifest.d.ts.map +1 -0
- package/dist/clip-runtime/manifest.js +181 -0
- package/dist/clip-runtime/process-manager.d.ts +57 -0
- package/dist/clip-runtime/process-manager.d.ts.map +1 -0
- package/dist/clip-runtime/process-manager.js +354 -0
- package/dist/clip-runtime/process.d.ts +59 -0
- package/dist/clip-runtime/process.d.ts.map +1 -0
- package/dist/clip-runtime/process.js +350 -0
- package/dist/config.d.ts +13 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +36 -19
- package/dist/filesystem.d.ts +1 -1
- package/dist/filesystem.d.ts.map +1 -1
- package/dist/filesystem.js +51 -53
- package/dist/index.js +46 -14
- package/dist/runtimes.d.ts +10 -8
- package/dist/runtimes.d.ts.map +1 -1
- package/dist/runtimes.js +63 -95
- package/dist/supervisor.d.ts +12 -3
- package/dist/supervisor.d.ts.map +1 -1
- package/dist/supervisor.js +272 -71
- package/dist/updater-manifest.d.ts +41 -0
- package/dist/updater-manifest.d.ts.map +1 -0
- package/dist/updater-manifest.js +94 -0
- package/dist/updater.d.ts +60 -0
- package/dist/updater.d.ts.map +1 -0
- package/dist/updater.js +427 -0
- package/dist/workspace.d.ts +2 -2
- package/dist/workspace.d.ts.map +1 -1
- package/dist/workspace.js +112 -112
- package/package.json +6 -6
|
@@ -23,7 +23,7 @@ function env(name) {
|
|
|
23
23
|
var PRLL_API_URL = env("PRLL_API_URL");
|
|
24
24
|
var PRLL_API_KEY = env("PRLL_API_KEY");
|
|
25
25
|
var PRLL_ORG_ID = env("PRLL_ORG_ID");
|
|
26
|
-
var stateDir = env("
|
|
26
|
+
var stateDir = env("PRLL_STATE_DIR");
|
|
27
27
|
var PRLL_WS_URL = process.env.PRLL_WS_URL?.trim() || "";
|
|
28
28
|
var PRLL_SWIMLANE_NAME = process.env.PRLL_SWIMLANE_NAME?.trim() || "";
|
|
29
29
|
var gatewayPort = process.env.OPENCLAW_GATEWAY_PORT?.trim() || "0";
|
|
@@ -37,13 +37,7 @@ if (fs.existsSync(pluginArchive)) {
|
|
|
37
37
|
fs.rmSync(legacyExtDir, { recursive: true, force: true });
|
|
38
38
|
log.info(`Installing Parall plugin from ${pluginArchive}...`);
|
|
39
39
|
try {
|
|
40
|
-
execFileSync("openclaw", [
|
|
41
|
-
"plugins",
|
|
42
|
-
"install",
|
|
43
|
-
pluginArchive,
|
|
44
|
-
"--force",
|
|
45
|
-
"--dangerously-force-unsafe-install"
|
|
46
|
-
], {
|
|
40
|
+
execFileSync("openclaw", ["plugins", "install", pluginArchive, "--force", "--dangerously-force-unsafe-install"], {
|
|
47
41
|
env: { ...process.env, OPENCLAW_STATE_DIR: openclawStateDir },
|
|
48
42
|
stdio: "inherit",
|
|
49
43
|
timeout: 6e4
|
|
@@ -136,39 +130,70 @@ async function preseedPlatformConfig() {
|
|
|
136
130
|
}
|
|
137
131
|
const ALLOWED_DEFAULTS = /* @__PURE__ */ new Set(["model", "compaction", "memorySearch"]);
|
|
138
132
|
const platformDefaults = pc.agents?.defaults;
|
|
133
|
+
const agents = cfg.agents && typeof cfg.agents === "object" ? cfg.agents : {};
|
|
134
|
+
const existing = agents.defaults && typeof agents.defaults === "object" ? agents.defaults : {};
|
|
135
|
+
const hadModel = "model" in existing;
|
|
136
|
+
delete existing.model;
|
|
139
137
|
if (platformDefaults && typeof platformDefaults === "object") {
|
|
140
|
-
const agents = cfg.agents && typeof cfg.agents === "object" ? cfg.agents : {};
|
|
141
|
-
const existing = agents.defaults && typeof agents.defaults === "object" ? agents.defaults : {};
|
|
142
138
|
for (const [k, v] of Object.entries(platformDefaults)) {
|
|
143
139
|
if (ALLOWED_DEFAULTS.has(k))
|
|
144
140
|
existing[k] = v;
|
|
145
141
|
}
|
|
142
|
+
}
|
|
143
|
+
if (hadModel || platformDefaults && typeof platformDefaults === "object") {
|
|
146
144
|
agents.defaults = existing;
|
|
147
145
|
cfg.agents = agents;
|
|
148
146
|
}
|
|
149
147
|
const ALLOWED_MODEL_KEYS = /* @__PURE__ */ new Set(["id", "name", "contextWindow", "maxTokens"]);
|
|
150
148
|
const platformModels = pc.models?.providers;
|
|
151
|
-
|
|
152
|
-
if (platformParall && typeof platformParall === "object") {
|
|
149
|
+
if (platformModels && typeof platformModels === "object") {
|
|
153
150
|
const models = cfg.models && typeof cfg.models === "object" ? cfg.models : {};
|
|
154
151
|
const providers = models.providers && typeof models.providers === "object" ? models.providers : {};
|
|
155
|
-
const
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
152
|
+
for (const providerName of ["parall", "parall-anthropic"]) {
|
|
153
|
+
const platformProvider = platformModels[providerName];
|
|
154
|
+
if (!platformProvider || typeof platformProvider !== "object") {
|
|
155
|
+
if (providerName !== "parall")
|
|
156
|
+
delete providers[providerName];
|
|
157
|
+
continue;
|
|
158
|
+
}
|
|
159
|
+
const existing2 = providers[providerName] && typeof providers[providerName] === "object" ? providers[providerName] : {};
|
|
160
|
+
const merged = { ...existing2, ...platformProvider };
|
|
161
|
+
if (Array.isArray(merged.models)) {
|
|
162
|
+
merged.models = merged.models.filter((m) => m && typeof m === "object").map((m) => {
|
|
163
|
+
const clean = {};
|
|
164
|
+
for (const [k, v] of Object.entries(m)) {
|
|
165
|
+
if (ALLOWED_MODEL_KEYS.has(k))
|
|
166
|
+
clean[k] = v;
|
|
167
|
+
}
|
|
168
|
+
return clean;
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
merged.apiKey = PRLL_API_KEY;
|
|
172
|
+
providers[providerName] = merged;
|
|
166
173
|
}
|
|
167
|
-
merged.apiKey = PRLL_API_KEY;
|
|
168
|
-
providers.parall = merged;
|
|
169
174
|
models.providers = providers;
|
|
170
175
|
cfg.models = models;
|
|
171
176
|
}
|
|
177
|
+
const agentsCfg = cfg.agents && typeof cfg.agents === "object" ? cfg.agents : {};
|
|
178
|
+
const defaultsCfg = agentsCfg.defaults && typeof agentsCfg.defaults === "object" ? agentsCfg.defaults : {};
|
|
179
|
+
if (typeof defaultsCfg.model === "string") {
|
|
180
|
+
const modelStr = defaultsCfg.model;
|
|
181
|
+
if (platformModels?.["parall-anthropic"]) {
|
|
182
|
+
const fwd = modelStr.match(/^parall\/(anthropic\/.+)$/);
|
|
183
|
+
if (fwd) {
|
|
184
|
+
defaultsCfg.model = `parall-anthropic/${fwd[1]}`;
|
|
185
|
+
agentsCfg.defaults = defaultsCfg;
|
|
186
|
+
cfg.agents = agentsCfg;
|
|
187
|
+
}
|
|
188
|
+
} else {
|
|
189
|
+
const rev = modelStr.match(/^parall-anthropic\/(anthropic\/.+)$/);
|
|
190
|
+
if (rev) {
|
|
191
|
+
defaultsCfg.model = `parall/${rev[1]}`;
|
|
192
|
+
agentsCfg.defaults = defaultsCfg;
|
|
193
|
+
cfg.agents = agentsCfg;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
172
197
|
const tmp = configPath + ".tmp";
|
|
173
198
|
fs.writeFileSync(tmp, JSON.stringify(cfg, null, 2));
|
|
174
199
|
fs.renameSync(tmp, configPath);
|
|
@@ -187,7 +212,7 @@ try {
|
|
|
187
212
|
} catch {
|
|
188
213
|
}
|
|
189
214
|
log.info("Starting OpenClaw gateway...");
|
|
190
|
-
var workspaceDir = process.env.
|
|
215
|
+
var workspaceDir = process.env.PRLL_WORKSPACE_DIR?.trim() || "";
|
|
191
216
|
var gatewayEnv = {
|
|
192
217
|
...process.env,
|
|
193
218
|
OPENCLAW_STATE_DIR: openclawStateDir
|
package/dist/cli.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare function runCLI(args: string[]): Promise<
|
|
1
|
+
export declare function runCLI(args: string[]): Promise<'run-daemon' | 'handled'>;
|
|
2
2
|
//# sourceMappingURL=cli.d.ts.map
|
package/dist/cli.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AA0SA,wBAAsB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,YAAY,GAAG,SAAS,CAAC,CAuD9E"}
|
package/dist/cli.js
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import * as fs from
|
|
2
|
-
import * as path from
|
|
3
|
-
import * as os from
|
|
4
|
-
import * as readline from
|
|
5
|
-
import { spawn, execSync } from
|
|
6
|
-
import { daemonConfigDir, daemonConfigPath } from
|
|
1
|
+
import * as fs from 'node:fs';
|
|
2
|
+
import * as path from 'node:path';
|
|
3
|
+
import * as os from 'node:os';
|
|
4
|
+
import * as readline from 'node:readline';
|
|
5
|
+
import { spawn, execSync } from 'node:child_process';
|
|
6
|
+
import { daemonConfigDir, daemonConfigPath } from './config.js';
|
|
7
7
|
const CONFIG_DIR = daemonConfigDir();
|
|
8
8
|
const CONFIG_PATH = daemonConfigPath();
|
|
9
9
|
function readConfig() {
|
|
10
10
|
try {
|
|
11
|
-
return JSON.parse(fs.readFileSync(CONFIG_PATH,
|
|
11
|
+
return JSON.parse(fs.readFileSync(CONFIG_PATH, 'utf-8'));
|
|
12
12
|
}
|
|
13
13
|
catch {
|
|
14
14
|
return null;
|
|
@@ -29,28 +29,30 @@ function prompt(question) {
|
|
|
29
29
|
});
|
|
30
30
|
}
|
|
31
31
|
function isMacOS() {
|
|
32
|
-
return process.platform ===
|
|
32
|
+
return process.platform === 'darwin';
|
|
33
33
|
}
|
|
34
34
|
function isLinux() {
|
|
35
|
-
return process.platform ===
|
|
35
|
+
return process.platform === 'linux';
|
|
36
36
|
}
|
|
37
|
-
const PLIST_LABEL =
|
|
37
|
+
const PLIST_LABEL = 'com.parall.daemon';
|
|
38
38
|
function plistPath() {
|
|
39
|
-
return path.join(os.homedir(),
|
|
39
|
+
return path.join(os.homedir(), 'Library', 'LaunchAgents', `${PLIST_LABEL}.plist`);
|
|
40
40
|
}
|
|
41
41
|
function systemdUnitPath() {
|
|
42
|
-
return path.join(os.homedir(),
|
|
42
|
+
return path.join(os.homedir(), '.config', 'systemd', 'user', 'parall-daemon.service');
|
|
43
43
|
}
|
|
44
44
|
function getDaemonBin() {
|
|
45
45
|
try {
|
|
46
|
-
return execSync(
|
|
46
|
+
return execSync('which parall-daemon', { encoding: 'utf-8', stdio: 'pipe' }).trim();
|
|
47
47
|
}
|
|
48
48
|
catch {
|
|
49
|
-
return process.argv[1] ??
|
|
49
|
+
return process.argv[1] ?? 'parall-daemon';
|
|
50
50
|
}
|
|
51
51
|
}
|
|
52
52
|
function generatePlist(daemonBin) {
|
|
53
|
-
const logPath = path.join(os.homedir(),
|
|
53
|
+
const logPath = path.join(os.homedir(), 'Library', 'Logs', 'parall-daemon.log');
|
|
54
|
+
// Use a shell wrapper so the service manager loads the self-updated overlay
|
|
55
|
+
// bundle when it exists, falling back to the original npm-installed binary.
|
|
54
56
|
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
55
57
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
56
58
|
<plist version="1.0">
|
|
@@ -59,7 +61,9 @@ function generatePlist(daemonBin) {
|
|
|
59
61
|
<string>${PLIST_LABEL}</string>
|
|
60
62
|
<key>ProgramArguments</key>
|
|
61
63
|
<array>
|
|
62
|
-
<string
|
|
64
|
+
<string>/bin/sh</string>
|
|
65
|
+
<string>-c</string>
|
|
66
|
+
<string>OVERLAY="$HOME/.parall-daemon/bundle/current/parall-daemon.js"; if [ -f "$OVERLAY" ]; then exec node "$OVERLAY"; else exec ${daemonBin}; fi</string>
|
|
63
67
|
</array>
|
|
64
68
|
<key>RunAtLoad</key>
|
|
65
69
|
<true/>
|
|
@@ -75,6 +79,8 @@ function generatePlist(daemonBin) {
|
|
|
75
79
|
</plist>`;
|
|
76
80
|
}
|
|
77
81
|
function generateSystemdUnit(daemonBin) {
|
|
82
|
+
// Use a shell wrapper so the service manager loads the self-updated overlay
|
|
83
|
+
// bundle when it exists, falling back to the original npm-installed binary.
|
|
78
84
|
return `[Unit]
|
|
79
85
|
Description=Parall Daemon
|
|
80
86
|
After=network-online.target
|
|
@@ -82,7 +88,7 @@ Wants=network-online.target
|
|
|
82
88
|
|
|
83
89
|
[Service]
|
|
84
90
|
Type=simple
|
|
85
|
-
ExecStart
|
|
91
|
+
ExecStart=/bin/sh -c 'OVERLAY="$HOME/.parall-daemon/bundle/current/parall-daemon.js"; if [ -f "$OVERLAY" ]; then exec node "$OVERLAY"; else exec ${daemonBin}; fi'
|
|
86
92
|
Restart=always
|
|
87
93
|
RestartSec=5
|
|
88
94
|
|
|
@@ -92,7 +98,7 @@ WantedBy=default.target`;
|
|
|
92
98
|
function installService() {
|
|
93
99
|
const config = readConfig();
|
|
94
100
|
if (!config) {
|
|
95
|
-
console.error(
|
|
101
|
+
console.error('No config found. Run `parall-daemon init` first.');
|
|
96
102
|
process.exit(1);
|
|
97
103
|
}
|
|
98
104
|
const bin = getDaemonBin();
|
|
@@ -108,102 +114,142 @@ function installService() {
|
|
|
108
114
|
const dir = path.dirname(systemdUnitPath());
|
|
109
115
|
fs.mkdirSync(dir, { recursive: true });
|
|
110
116
|
fs.writeFileSync(systemdUnitPath(), generateSystemdUnit(bin));
|
|
111
|
-
execSync(
|
|
112
|
-
execSync(
|
|
117
|
+
execSync('systemctl --user daemon-reload');
|
|
118
|
+
execSync('systemctl --user enable --now parall-daemon');
|
|
113
119
|
console.log(`systemd service installed: ${systemdUnitPath()}`);
|
|
114
120
|
}
|
|
115
121
|
else {
|
|
116
|
-
console.log(
|
|
122
|
+
console.log('Unsupported platform. Run `parall-daemon` manually.');
|
|
117
123
|
}
|
|
118
124
|
}
|
|
119
125
|
async function cmdInit() {
|
|
120
126
|
const existing = readConfig();
|
|
121
|
-
const defaultUrl = existing?.api_url ||
|
|
127
|
+
const defaultUrl = existing?.api_url || 'https://api.parall.com';
|
|
122
128
|
const apiUrl = (await prompt(`API URL [${defaultUrl}]: `)) || defaultUrl;
|
|
123
|
-
const apiKey = await prompt(
|
|
124
|
-
if (!apiKey.startsWith(
|
|
129
|
+
const apiKey = await prompt('Machine key (mck_...): ');
|
|
130
|
+
if (!apiKey.startsWith('mck_')) {
|
|
125
131
|
console.error('Error: Machine key must start with "mck_"');
|
|
126
132
|
process.exit(1);
|
|
127
133
|
}
|
|
128
134
|
writeConfig({ api_url: apiUrl, api_key: apiKey });
|
|
129
135
|
console.log(`Config written to ${CONFIG_PATH}`);
|
|
130
|
-
const install = await prompt(
|
|
131
|
-
if (install.toLowerCase() !==
|
|
136
|
+
const install = await prompt('Install as background service? (Y/n): ');
|
|
137
|
+
if (install.toLowerCase() !== 'n') {
|
|
132
138
|
installService();
|
|
133
139
|
}
|
|
134
140
|
}
|
|
135
141
|
function cmdStatus() {
|
|
136
142
|
const config = readConfig();
|
|
137
|
-
console.log(`Config: ${config ? CONFIG_PATH :
|
|
143
|
+
console.log(`Config: ${config ? CONFIG_PATH : 'not configured'}`);
|
|
138
144
|
if (isMacOS()) {
|
|
139
145
|
try {
|
|
140
146
|
const output = execSync(`launchctl print gui/$(id -u)/${PLIST_LABEL} 2>&1`, {
|
|
141
|
-
encoding:
|
|
147
|
+
encoding: 'utf-8',
|
|
142
148
|
});
|
|
143
|
-
const running = output.includes(
|
|
144
|
-
console.log(`Service: ${running ?
|
|
149
|
+
const running = output.includes('state = running');
|
|
150
|
+
console.log(`Service: ${running ? 'running' : 'stopped'}`);
|
|
145
151
|
const pidMatch = output.match(/pid\s*=\s*(\d+)/);
|
|
146
152
|
if (pidMatch)
|
|
147
153
|
console.log(`PID: ${pidMatch[1]}`);
|
|
148
154
|
}
|
|
149
155
|
catch {
|
|
150
|
-
console.log(
|
|
156
|
+
console.log('Service: not installed');
|
|
151
157
|
}
|
|
152
158
|
}
|
|
153
159
|
else if (isLinux()) {
|
|
154
160
|
try {
|
|
155
|
-
execSync(
|
|
156
|
-
console.log(
|
|
161
|
+
execSync('systemctl --user is-active parall-daemon', { encoding: 'utf-8', stdio: 'pipe' });
|
|
162
|
+
console.log('Service: running');
|
|
157
163
|
}
|
|
158
164
|
catch {
|
|
159
|
-
console.log(
|
|
165
|
+
console.log('Service: stopped or not installed');
|
|
160
166
|
}
|
|
161
167
|
}
|
|
162
168
|
}
|
|
163
169
|
function cmdStop() {
|
|
164
170
|
if (isMacOS()) {
|
|
165
171
|
execSync(`launchctl bootout gui/$(id -u) ${plistPath()} 2>/dev/null || true`, {
|
|
166
|
-
stdio:
|
|
172
|
+
stdio: 'inherit',
|
|
167
173
|
});
|
|
168
174
|
}
|
|
169
175
|
else if (isLinux()) {
|
|
170
|
-
execSync(
|
|
176
|
+
execSync('systemctl --user stop parall-daemon', { stdio: 'inherit' });
|
|
171
177
|
}
|
|
172
|
-
console.log(
|
|
178
|
+
console.log('Daemon stopped.');
|
|
173
179
|
}
|
|
174
180
|
function cmdLogs(lines) {
|
|
175
181
|
if (isLinux()) {
|
|
176
|
-
const child = spawn(
|
|
177
|
-
stdio:
|
|
182
|
+
const child = spawn('journalctl', ['--user-unit', 'parall-daemon', '-n', lines, '-f'], {
|
|
183
|
+
stdio: 'inherit',
|
|
178
184
|
});
|
|
179
|
-
child.on(
|
|
185
|
+
child.on('exit', (code) => process.exit(code ?? 0));
|
|
180
186
|
return;
|
|
181
187
|
}
|
|
182
|
-
const logPath = path.join(os.homedir(),
|
|
188
|
+
const logPath = path.join(os.homedir(), 'Library', 'Logs', 'parall-daemon.log');
|
|
183
189
|
if (!fs.existsSync(logPath)) {
|
|
184
|
-
console.log(
|
|
190
|
+
console.log('No log file found at', logPath);
|
|
185
191
|
return;
|
|
186
192
|
}
|
|
187
|
-
const child = spawn(
|
|
188
|
-
child.on(
|
|
193
|
+
const child = spawn('tail', ['-n', lines, '-f', logPath], { stdio: 'inherit' });
|
|
194
|
+
child.on('exit', (code) => process.exit(code ?? 0));
|
|
189
195
|
}
|
|
190
196
|
function cmdServiceUninstall() {
|
|
191
197
|
if (isMacOS()) {
|
|
192
198
|
execSync(`launchctl bootout gui/$(id -u) ${plistPath()} 2>/dev/null || true`);
|
|
193
199
|
if (fs.existsSync(plistPath()))
|
|
194
200
|
fs.unlinkSync(plistPath());
|
|
195
|
-
console.log(
|
|
201
|
+
console.log('launchd agent uninstalled.');
|
|
196
202
|
}
|
|
197
203
|
else if (isLinux()) {
|
|
198
|
-
execSync(
|
|
199
|
-
execSync(
|
|
204
|
+
execSync('systemctl --user stop parall-daemon 2>/dev/null || true');
|
|
205
|
+
execSync('systemctl --user disable parall-daemon 2>/dev/null || true');
|
|
200
206
|
if (fs.existsSync(systemdUnitPath()))
|
|
201
207
|
fs.unlinkSync(systemdUnitPath());
|
|
202
|
-
execSync(
|
|
203
|
-
console.log(
|
|
208
|
+
execSync('systemctl --user daemon-reload');
|
|
209
|
+
console.log('systemd service uninstalled.');
|
|
204
210
|
}
|
|
205
211
|
else {
|
|
206
|
-
console.log(
|
|
212
|
+
console.log('Unsupported platform.');
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
async function cmdUpdate(checkOnly) {
|
|
216
|
+
const { resolveClaudeDaemonConfig, resolveBundleDir } = await import('./config.js');
|
|
217
|
+
const { DaemonUpdater } = await import('./updater.js');
|
|
218
|
+
const config = resolveClaudeDaemonConfig(process.env);
|
|
219
|
+
const bundleDir = resolveBundleDir(process.env);
|
|
220
|
+
const signingEnabled = process.env.PRLL_DAEMON_SIGNING_DISABLED !== '1';
|
|
221
|
+
const updater = new DaemonUpdater(bundleDir, config.updateCdnUrl, {
|
|
222
|
+
info: (msg) => console.log(msg),
|
|
223
|
+
warn: (msg) => console.warn(msg),
|
|
224
|
+
error: (msg) => console.error(msg),
|
|
225
|
+
}, signingEnabled);
|
|
226
|
+
const local = updater.getLocalVersion();
|
|
227
|
+
console.log(`Current version: ${local ?? 'unknown'}`);
|
|
228
|
+
console.log(`CDN: ${config.updateCdnUrl}`);
|
|
229
|
+
console.log(`Bundle dir: ${bundleDir}`);
|
|
230
|
+
if (checkOnly) {
|
|
231
|
+
console.log('\nChecking for updates...');
|
|
232
|
+
const result = await updater.checkAvailable();
|
|
233
|
+
if (result.available) {
|
|
234
|
+
console.log(`Update available: ${result.currentVersion ?? 'unknown'} → ${result.remoteVersion}`);
|
|
235
|
+
}
|
|
236
|
+
else if (result.remoteVersion) {
|
|
237
|
+
console.log(`Already up to date (${result.currentVersion}).`);
|
|
238
|
+
}
|
|
239
|
+
else {
|
|
240
|
+
console.log('Could not check for updates.');
|
|
241
|
+
}
|
|
242
|
+
return;
|
|
243
|
+
}
|
|
244
|
+
else {
|
|
245
|
+
console.log('\nChecking and applying updates...');
|
|
246
|
+
}
|
|
247
|
+
const applied = await updater.checkAndApply();
|
|
248
|
+
if (applied) {
|
|
249
|
+
console.log('Update applied. Restart the daemon to use the new version.');
|
|
250
|
+
}
|
|
251
|
+
else {
|
|
252
|
+
console.log('Already up to date.');
|
|
207
253
|
}
|
|
208
254
|
}
|
|
209
255
|
function printUsage() {
|
|
@@ -215,6 +261,7 @@ Usage:
|
|
|
215
261
|
parall-daemon init Configure the daemon (interactive)
|
|
216
262
|
parall-daemon status Show daemon service status
|
|
217
263
|
parall-daemon stop Stop the background service
|
|
264
|
+
parall-daemon update [--check] Check for / apply daemon updates
|
|
218
265
|
parall-daemon logs [-n LINES] Tail daemon logs
|
|
219
266
|
parall-daemon service install Install as background service (launchd/systemd)
|
|
220
267
|
parall-daemon service uninstall Uninstall background service
|
|
@@ -224,54 +271,57 @@ Usage:
|
|
|
224
271
|
export async function runCLI(args) {
|
|
225
272
|
const cmd = args[0];
|
|
226
273
|
switch (cmd) {
|
|
227
|
-
case
|
|
274
|
+
case 'init':
|
|
228
275
|
await cmdInit();
|
|
229
|
-
return
|
|
230
|
-
case
|
|
276
|
+
return 'handled';
|
|
277
|
+
case 'status':
|
|
231
278
|
cmdStatus();
|
|
232
|
-
return
|
|
233
|
-
case
|
|
279
|
+
return 'handled';
|
|
280
|
+
case 'stop':
|
|
234
281
|
cmdStop();
|
|
235
|
-
return
|
|
236
|
-
case
|
|
237
|
-
let lines =
|
|
238
|
-
if (args[1] ===
|
|
282
|
+
return 'handled';
|
|
283
|
+
case 'logs': {
|
|
284
|
+
let lines = '50';
|
|
285
|
+
if (args[1] === '-n') {
|
|
239
286
|
const n = Number(args[2]);
|
|
240
287
|
if (!Number.isInteger(n) || n <= 0) {
|
|
241
|
-
console.error(
|
|
288
|
+
console.error('Error: -n requires a positive integer');
|
|
242
289
|
process.exit(1);
|
|
243
290
|
}
|
|
244
291
|
lines = String(n);
|
|
245
292
|
}
|
|
246
293
|
cmdLogs(lines);
|
|
247
|
-
return
|
|
294
|
+
return 'handled';
|
|
248
295
|
}
|
|
249
|
-
case
|
|
296
|
+
case 'update':
|
|
297
|
+
await cmdUpdate(args.includes('--check'));
|
|
298
|
+
return 'handled';
|
|
299
|
+
case 'service': {
|
|
250
300
|
const sub = args[1];
|
|
251
|
-
if (sub ===
|
|
301
|
+
if (sub === 'install') {
|
|
252
302
|
installService();
|
|
253
303
|
}
|
|
254
|
-
else if (sub ===
|
|
304
|
+
else if (sub === 'uninstall') {
|
|
255
305
|
cmdServiceUninstall();
|
|
256
306
|
}
|
|
257
307
|
else {
|
|
258
|
-
console.error(`Unknown service command: ${sub ??
|
|
259
|
-
console.log(
|
|
308
|
+
console.error(`Unknown service command: ${sub ?? '(none)'}`);
|
|
309
|
+
console.log('Usage: parall-daemon service [install|uninstall]');
|
|
260
310
|
process.exit(1);
|
|
261
311
|
}
|
|
262
|
-
return
|
|
312
|
+
return 'handled';
|
|
263
313
|
}
|
|
264
|
-
case
|
|
265
|
-
case
|
|
266
|
-
case
|
|
314
|
+
case 'help':
|
|
315
|
+
case '--help':
|
|
316
|
+
case '-h':
|
|
267
317
|
printUsage();
|
|
268
|
-
return
|
|
318
|
+
return 'handled';
|
|
269
319
|
default:
|
|
270
320
|
if (cmd) {
|
|
271
321
|
console.error(`Unknown command: ${cmd}`);
|
|
272
322
|
printUsage();
|
|
273
323
|
process.exit(1);
|
|
274
324
|
}
|
|
275
|
-
return
|
|
325
|
+
return 'run-daemon';
|
|
276
326
|
}
|
|
277
327
|
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ClipInstaller — Downloads and installs clips from the Pinix registry.
|
|
3
|
+
*
|
|
4
|
+
* Flow: parse source → resolve version → download tarball → verify checksum →
|
|
5
|
+
* extract to clipsDir/{alias}/ → install deps → return result.
|
|
6
|
+
*
|
|
7
|
+
* Uses only Node.js built-ins (no external npm packages).
|
|
8
|
+
*/
|
|
9
|
+
export interface InstallOptions {
|
|
10
|
+
/** e.g., "@pinix/github-tools" or "@pinix/github-tools@1.0.0" */
|
|
11
|
+
source: string;
|
|
12
|
+
/** Override alias (default: derived from package name) */
|
|
13
|
+
alias?: string;
|
|
14
|
+
/** Directory to install clips into */
|
|
15
|
+
clipsDir: string;
|
|
16
|
+
/** Pinix registry REST base (package metadata + tarballs). Default: https://api.pinixai.com (env: PRLL_PINIX_REGISTRY_URL) */
|
|
17
|
+
registryUrl?: string;
|
|
18
|
+
}
|
|
19
|
+
export interface InstallResult {
|
|
20
|
+
alias: string;
|
|
21
|
+
name: string;
|
|
22
|
+
version: string;
|
|
23
|
+
/** Filesystem path of the installed clip */
|
|
24
|
+
path: string;
|
|
25
|
+
}
|
|
26
|
+
interface ParsedSource {
|
|
27
|
+
scope: string | null;
|
|
28
|
+
name: string;
|
|
29
|
+
/** Full package name including scope, e.g. "@pinix/github-tools" */
|
|
30
|
+
fullName: string;
|
|
31
|
+
version: string | null;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Parse a source string into scope, name, and optional version.
|
|
35
|
+
* "@scope/name" → scope="scope", name="name", version=null
|
|
36
|
+
* "@scope/name@1.0.0" → scope="scope", name="name", version="1.0.0"
|
|
37
|
+
* "name" → scope=null, name="name", version=null
|
|
38
|
+
* "name@1.0.0" → scope=null, name="name", version="1.0.0"
|
|
39
|
+
*/
|
|
40
|
+
export declare function parseSource(source: string): ParsedSource;
|
|
41
|
+
export declare function installClip(opts: InstallOptions): Promise<InstallResult>;
|
|
42
|
+
export declare function removeClip(clipsDir: string, alias: string): Promise<void>;
|
|
43
|
+
export {};
|
|
44
|
+
//# sourceMappingURL=clip-installer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clip-installer.d.ts","sourceRoot":"","sources":["../../src/clip-runtime/clip-installer.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAcH,MAAM,WAAW,cAAc;IAC7B,iEAAiE;IACjE,MAAM,EAAE,MAAM,CAAC;IACf,0DAA0D;IAC1D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,sCAAsC;IACtC,QAAQ,EAAE,MAAM,CAAC;IACjB,8HAA8H;IAC9H,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,4CAA4C;IAC5C,IAAI,EAAE,MAAM,CAAC;CACd;AAMD,UAAU,YAAY;IACpB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,oEAAoE;IACpE,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CACxB;AAcD;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,YAAY,CAgCxD;AAicD,wBAAsB,WAAW,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC,CAiE9E;AAED,wBAAsB,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAM/E"}
|