@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.
Files changed (53) hide show
  1. package/bundle/manifest.json +17 -11
  2. package/bundle/package.json +1 -0
  3. package/bundle/parall-claude-agent.js +27671 -337
  4. package/bundle/parall-codex-agent.js +27715 -375
  5. package/bundle/parall-daemon.js +30421 -1355
  6. package/bundle/parall-openclaw-agent.js +51 -26
  7. package/dist/cli.d.ts +1 -1
  8. package/dist/cli.d.ts.map +1 -1
  9. package/dist/cli.js +122 -72
  10. package/dist/clip-runtime/clip-installer.d.ts +44 -0
  11. package/dist/clip-runtime/clip-installer.d.ts.map +1 -0
  12. package/dist/clip-runtime/clip-installer.js +501 -0
  13. package/dist/clip-runtime/clip-provider.d.ts +76 -0
  14. package/dist/clip-runtime/clip-provider.d.ts.map +1 -0
  15. package/dist/clip-runtime/clip-provider.js +402 -0
  16. package/dist/clip-runtime/index.d.ts +7 -0
  17. package/dist/clip-runtime/index.d.ts.map +1 -0
  18. package/dist/clip-runtime/index.js +5 -0
  19. package/dist/clip-runtime/ipc.d.ts +94 -0
  20. package/dist/clip-runtime/ipc.d.ts.map +1 -0
  21. package/dist/clip-runtime/ipc.js +98 -0
  22. package/dist/clip-runtime/manifest.d.ts +74 -0
  23. package/dist/clip-runtime/manifest.d.ts.map +1 -0
  24. package/dist/clip-runtime/manifest.js +181 -0
  25. package/dist/clip-runtime/process-manager.d.ts +57 -0
  26. package/dist/clip-runtime/process-manager.d.ts.map +1 -0
  27. package/dist/clip-runtime/process-manager.js +354 -0
  28. package/dist/clip-runtime/process.d.ts +59 -0
  29. package/dist/clip-runtime/process.d.ts.map +1 -0
  30. package/dist/clip-runtime/process.js +350 -0
  31. package/dist/config.d.ts +13 -0
  32. package/dist/config.d.ts.map +1 -1
  33. package/dist/config.js +36 -19
  34. package/dist/filesystem.d.ts +1 -1
  35. package/dist/filesystem.d.ts.map +1 -1
  36. package/dist/filesystem.js +51 -53
  37. package/dist/index.js +46 -14
  38. package/dist/runtimes.d.ts +10 -8
  39. package/dist/runtimes.d.ts.map +1 -1
  40. package/dist/runtimes.js +63 -95
  41. package/dist/supervisor.d.ts +12 -3
  42. package/dist/supervisor.d.ts.map +1 -1
  43. package/dist/supervisor.js +272 -71
  44. package/dist/updater-manifest.d.ts +41 -0
  45. package/dist/updater-manifest.d.ts.map +1 -0
  46. package/dist/updater-manifest.js +94 -0
  47. package/dist/updater.d.ts +60 -0
  48. package/dist/updater.d.ts.map +1 -0
  49. package/dist/updater.js +427 -0
  50. package/dist/workspace.d.ts +2 -2
  51. package/dist/workspace.d.ts.map +1 -1
  52. package/dist/workspace.js +112 -112
  53. package/package.json +6 -6
@@ -1,65 +1,63 @@
1
- import * as fs from "fs";
2
- import * as path from "path";
3
- import * as os from "os";
1
+ import * as fs from 'fs';
2
+ import * as path from 'path';
3
+ import * as os from 'os';
4
4
  const MAX_ENTRIES = 200;
5
5
  const SYSTEM_DIR_PREFIXES = [
6
- "/Applications",
7
- "/bin",
8
- "/boot",
9
- "/dev",
10
- "/etc",
11
- "/Library",
12
- "/private",
13
- "/proc",
14
- "/root",
15
- "/run",
16
- "/sbin",
17
- "/System",
18
- "/sys",
19
- "/usr",
20
- "/var",
6
+ '/Applications',
7
+ '/bin',
8
+ '/boot',
9
+ '/dev',
10
+ '/etc',
11
+ '/Library',
12
+ '/private',
13
+ '/proc',
14
+ '/root',
15
+ '/run',
16
+ '/sbin',
17
+ '/System',
18
+ '/sys',
19
+ '/usr',
20
+ '/var',
21
21
  ];
22
22
  const CREDENTIAL_DIR_NAMES = new Set([
23
- ".aws",
24
- ".azure",
25
- ".claude",
26
- ".codex",
27
- ".config",
28
- ".docker",
29
- ".gnupg",
30
- ".kube",
31
- ".npm",
32
- ".ssh",
33
- ".parall-agent",
34
- ".parall-daemon",
23
+ '.aws',
24
+ '.azure',
25
+ '.claude',
26
+ '.codex',
27
+ '.config',
28
+ '.docker',
29
+ '.gnupg',
30
+ '.kube',
31
+ '.npm',
32
+ '.ssh',
33
+ '.parall-agent',
34
+ '.parall-daemon',
35
35
  ]);
36
36
  export function browseDenyReason(value) {
37
- const normalized = path.resolve(value).split(path.sep).join("/");
38
- if (normalized === "/")
39
- return "";
37
+ const normalized = path.resolve(value).split(path.sep).join('/');
38
+ if (normalized === '/')
39
+ return '';
40
40
  for (const prefix of SYSTEM_DIR_PREFIXES) {
41
41
  if (normalized === prefix || normalized.startsWith(`${prefix}/`)) {
42
- return "a system directory";
42
+ return 'a system directory';
43
43
  }
44
44
  }
45
- const parts = normalized.split("/").filter(Boolean);
45
+ const parts = normalized.split('/').filter(Boolean);
46
46
  for (const part of parts) {
47
47
  if (CREDENTIAL_DIR_NAMES.has(part)) {
48
- return "a credential or application state directory";
48
+ return 'a credential or application state directory';
49
49
  }
50
50
  }
51
- return "";
51
+ return '';
52
52
  }
53
53
  function syntheticRoots() {
54
54
  const roots = [];
55
55
  const platform = os.platform();
56
- const candidates = platform === "darwin"
57
- ? ["/Users", os.homedir()]
58
- : ["/home", os.homedir()];
56
+ const candidates = platform === 'darwin' ? ['/Users', os.homedir()] : ['/home', os.homedir()];
59
57
  for (const dir of [...new Set(candidates)]) {
60
58
  try {
61
59
  fs.accessSync(dir, fs.constants.R_OK);
62
- roots.push({ name: dir, type: "dir" });
60
+ roots.push({ name: dir, type: 'dir' });
63
61
  }
64
62
  catch {
65
63
  // not accessible
@@ -69,8 +67,8 @@ function syntheticRoots() {
69
67
  }
70
68
  export async function listDirectory(dirPath) {
71
69
  const resolved = path.resolve(dirPath);
72
- const normalized = resolved.split(path.sep).join("/");
73
- if (normalized === "/") {
70
+ const normalized = resolved.split(path.sep).join('/');
71
+ if (normalized === '/') {
74
72
  return { entries: syntheticRoots() };
75
73
  }
76
74
  const deny = browseDenyReason(normalized);
@@ -83,11 +81,11 @@ export async function listDirectory(dirPath) {
83
81
  }
84
82
  catch (err) {
85
83
  const code = err.code;
86
- if (code === "ENOENT")
87
- return { entries: [], error: "Directory not found" };
88
- return { entries: [], error: "Permission denied" };
84
+ if (code === 'ENOENT')
85
+ return { entries: [], error: 'Directory not found' };
86
+ return { entries: [], error: 'Permission denied' };
89
87
  }
90
- const realDeny = browseDenyReason(realPath.split(path.sep).join("/"));
88
+ const realDeny = browseDenyReason(realPath.split(path.sep).join('/'));
91
89
  if (realDeny) {
92
90
  return { entries: [], error: `Access denied: ${realDeny}` };
93
91
  }
@@ -97,19 +95,19 @@ export async function listDirectory(dirPath) {
97
95
  }
98
96
  catch (err) {
99
97
  const code = err.code;
100
- if (code === "ENOENT")
101
- return { entries: [], error: "Directory not found" };
102
- if (code === "EACCES" || code === "EPERM")
103
- return { entries: [], error: "Permission denied" };
98
+ if (code === 'ENOENT')
99
+ return { entries: [], error: 'Directory not found' };
100
+ if (code === 'EACCES' || code === 'EPERM')
101
+ return { entries: [], error: 'Permission denied' };
104
102
  return { entries: [], error: `Failed to read directory: ${code ?? String(err)}` };
105
103
  }
106
104
  const entries = [];
107
105
  for (const d of dirents) {
108
106
  if (!d.isDirectory())
109
107
  continue;
110
- if (d.name.startsWith("."))
108
+ if (d.name.startsWith('.'))
111
109
  continue;
112
- entries.push({ name: d.name, type: "dir" });
110
+ entries.push({ name: d.name, type: 'dir' });
113
111
  if (entries.length >= MAX_ENTRIES)
114
112
  break;
115
113
  }
package/dist/index.js CHANGED
@@ -1,10 +1,12 @@
1
1
  #!/usr/bin/env node
2
- import { createLogger } from "@parall/agent-core";
3
- import { ParallClient } from "@parall/sdk";
4
- import { resolveClaudeDaemonConfig, resolveWsUrl } from "./config.js";
5
- import { DaemonSupervisor, sleepCancellable } from "./supervisor.js";
6
- import { runCLI } from "./cli.js";
7
- const log = createLogger("daemon");
2
+ import { createLogger, createOtelLogger, initAgentTelemetry, } from '@parall/agent-core';
3
+ import { ParallClient } from '@parall/sdk';
4
+ import { resolveClaudeDaemonConfig, resolveBundleDir, resolveWsUrl, } from './config.js';
5
+ import { DaemonSupervisor, sleepCancellable } from './supervisor.js';
6
+ import { DaemonUpdater } from './updater.js';
7
+ import { runCLI } from './cli.js';
8
+ const UPDATE_EXIT_CODE = 42;
9
+ let log = createLogger('daemon');
8
10
  function formatError(reason) {
9
11
  if (reason instanceof Error) {
10
12
  return reason.stack ?? reason.message;
@@ -30,10 +32,12 @@ function formatError(reason) {
30
32
  * any supervisor.run() rejection and rely entirely on the shell wrapper +
31
33
  * K8s for restart.
32
34
  */
33
- async function runForever(config, client, log, signal) {
35
+ async function runForever(config, client, log, signal, updater) {
34
36
  let attempt = 0;
35
37
  while (!signal.aborted) {
36
38
  const supervisor = new DaemonSupervisor(config, client, log);
39
+ if (updater)
40
+ supervisor.setUpdater(updater);
37
41
  try {
38
42
  await supervisor.run(signal);
39
43
  // Clean exit (signal aborted) — done.
@@ -54,7 +58,7 @@ async function runForever(config, client, log, signal) {
54
58
  log.warn(`supervisor.stop() after crash threw: ${String(stopErr)}`);
55
59
  }
56
60
  if (config.supervisorRestartBackoffMs === 0) {
57
- log.error("supervisor keepalive disabled (PRLL_DAEMON_SUPERVISOR_RESTART_BACKOFF_MS=0) — exiting");
61
+ log.error('supervisor keepalive disabled (PRLL_DAEMON_SUPERVISOR_RESTART_BACKOFF_MS=0) — exiting');
58
62
  throw err;
59
63
  }
60
64
  const delay = Math.min(config.supervisorRestartBackoffMs * Math.pow(2, attempt), config.supervisorRestartBackoffMaxMs);
@@ -68,8 +72,22 @@ async function runForever(config, client, log, signal) {
68
72
  }
69
73
  async function main() {
70
74
  const config = resolveClaudeDaemonConfig(process.env);
75
+ const telemetry = await initAgentTelemetry('parall-daemon', 'daemon');
76
+ log = createOtelLogger('daemon', 'daemon');
71
77
  log.info(`boot: api=${config.apiUrl} pollMs=${config.pollIntervalMs} heartbeatMs=${config.heartbeatIntervalMs} agentBin=${config.agentBin}`);
72
78
  log.info(`keepalive: bootstrapBackoffMs=${config.bootstrapBackoffMs} supervisorRestartBackoffMs=${config.supervisorRestartBackoffMs}`);
79
+ // --- Self-update: rollback check (before any network calls) ---
80
+ let updater = null;
81
+ if (!config.updateDisabled) {
82
+ const bundleDir = resolveBundleDir(process.env);
83
+ updater = new DaemonUpdater(bundleDir, config.updateCdnUrl, log, true);
84
+ if (updater.checkRollback()) {
85
+ log.info('rollback applied — exiting for service manager restart');
86
+ await telemetry.shutdown();
87
+ process.exit(UPDATE_EXIT_CODE);
88
+ }
89
+ log.info(`update: bundleDir=${bundleDir} cdn=${config.updateCdnUrl} interval=${config.updateIntervalMs}ms`);
90
+ }
73
91
  // The daemon talks to the API as a Machine — the bearer is mck_*.
74
92
  // No orgId is configured here; per-agent subprocesses get their
75
93
  // own org_id via the spawn env.
@@ -83,26 +101,40 @@ async function main() {
83
101
  log.info(`received ${sig} — initiating shutdown`);
84
102
  abortController.abort();
85
103
  };
86
- process.on("SIGINT", () => onSignal("SIGINT"));
87
- process.on("SIGTERM", () => onSignal("SIGTERM"));
104
+ process.on('SIGINT', () => onSignal('SIGINT'));
105
+ process.on('SIGTERM', () => onSignal('SIGTERM'));
88
106
  // Defensive: unexpected async failures are logged explicitly. Rejections
89
107
  // stay in-process so the supervisor loop can recover; uncaught exceptions
90
108
  // exit so entrypoint.sh's shell-level keepalive restarts from a clean VM.
91
- process.on("unhandledRejection", (reason) => {
109
+ process.on('unhandledRejection', (reason) => {
92
110
  log.error(`unhandledRejection: ${formatError(reason)}`);
93
111
  });
94
- process.on("uncaughtException", (err) => {
112
+ process.on('uncaughtException', (err) => {
95
113
  log.error(`uncaughtException: ${formatError(err)}`);
96
114
  process.exitCode = 1;
97
115
  process.exit(1);
98
116
  });
99
117
  config.wsUrl = resolveWsUrl(config.apiUrl, config.wsUrl, config.swimlaneName);
100
- await runForever(config, client, log, abortController.signal);
118
+ // --- Self-update: boot check + periodic timer ---
119
+ if (updater) {
120
+ const applied = await updater.checkAndApply().catch((err) => {
121
+ log.warn(`boot update check failed: ${String(err)}`);
122
+ return false;
123
+ });
124
+ if (applied) {
125
+ log.info('boot update applied — exiting for restart');
126
+ await telemetry.shutdown();
127
+ process.exit(UPDATE_EXIT_CODE);
128
+ }
129
+ updater.startPeriodicCheck(config.updateIntervalMs);
130
+ }
131
+ await runForever(config, client, log, abortController.signal, updater);
132
+ await telemetry.shutdown();
101
133
  }
102
134
  const cliArgs = process.argv.slice(2);
103
135
  runCLI(cliArgs)
104
136
  .then((result) => {
105
- if (result === "handled")
137
+ if (result === 'handled')
106
138
  return;
107
139
  main().catch((err) => {
108
140
  log.error(`fatal: ${formatError(err)}`);
@@ -1,12 +1,10 @@
1
- export interface ProviderConfig {
2
- llm_source?: string;
3
- openai_api_key?: string;
4
- openai_base_url?: string;
5
- anthropic_auth_token?: string;
6
- anthropic_base_url?: string;
7
- }
1
+ import { clearAllProviderCreds } from '@parall/agent-core';
2
+ import type { ProviderConfig } from '@parall/agent-core';
3
+ export type { ProviderConfig };
4
+ export { clearAllProviderCreds };
8
5
  export interface RuntimeAdapter {
9
6
  bin: string;
7
+ args: string[];
10
8
  buildEnv(baseEnv: NodeJS.ProcessEnv, agentId: string, orgId: string, apiKey: string, dirs: AgentDirs, pc?: ProviderConfig): NodeJS.ProcessEnv;
11
9
  }
12
10
  export interface AgentDirs {
@@ -14,7 +12,11 @@ export interface AgentDirs {
14
12
  workspaceDir: string;
15
13
  claudeHome: string;
16
14
  }
17
- export declare function clearAllProviderCreds(env: NodeJS.ProcessEnv): void;
15
+ /**
16
+ * Resolve a runtime adapter, preferring overlay bundle paths when available.
17
+ * When the daemon has self-updated into ~/.parall-daemon/bundle/, bridge
18
+ * binaries should also load from overlay to keep versions in sync.
19
+ */
18
20
  export declare function getRuntimeAdapter(runtimeType: string): RuntimeAdapter;
19
21
  export declare function assertAgentKey(apiKey: string): void;
20
22
  //# sourceMappingURL=runtimes.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"runtimes.d.ts","sourceRoot":"","sources":["../src/runtimes.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,cAAc;IAC7B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,MAAM,WAAW,cAAc;IAC7B,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,UAAU,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,CAAC,EAAE,cAAc,GAAG,MAAM,CAAC,UAAU,CAAC;CAC/I;AAED,MAAM,WAAW,SAAS;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;CACpB;AAeD,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,CAAC,UAAU,GAAG,IAAI,CAOlE;AAgGD,wBAAgB,iBAAiB,CAAC,WAAW,EAAE,MAAM,GAAG,cAAc,CAErE;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAInD"}
1
+ {"version":3,"file":"runtimes.d.ts","sourceRoot":"","sources":["../src/runtimes.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAC3D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAGzD,YAAY,EAAE,cAAc,EAAE,CAAC;AAC/B,OAAO,EAAE,qBAAqB,EAAE,CAAC;AAEjC,MAAM,WAAW,cAAc;IAC7B,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,QAAQ,CACN,OAAO,EAAE,MAAM,CAAC,UAAU,EAC1B,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,SAAS,EACf,EAAE,CAAC,EAAE,cAAc,GAClB,MAAM,CAAC,UAAU,CAAC;CACtB;AAED,MAAM,WAAW,SAAS;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;CACpB;AAuED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,WAAW,EAAE,MAAM,GAAG,cAAc,CAerE;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAInD"}
package/dist/runtimes.js CHANGED
@@ -1,120 +1,88 @@
1
- import * as path from "node:path";
2
- function llmSource(pc) {
3
- if (pc?.llm_source)
4
- return pc.llm_source;
5
- if (pc?.openai_api_key ||
6
- pc?.openai_base_url ||
7
- pc?.anthropic_auth_token ||
8
- pc?.anthropic_base_url) {
9
- return "custom";
10
- }
11
- return "parall";
12
- }
13
- export function clearAllProviderCreds(env) {
14
- delete env.ANTHROPIC_AUTH_TOKEN;
15
- delete env.ANTHROPIC_BASE_URL;
16
- delete env.ANTHROPIC_API_KEY;
17
- delete env.OPENAI_API_KEY;
18
- delete env.OPENAI_BASE_URL;
19
- delete env.PRLL_CLAUDE_ALLOW_API_KEY;
1
+ import * as fs from 'node:fs';
2
+ import * as path from 'node:path';
3
+ import { clearAllProviderCreds } from '@parall/agent-core';
4
+ import { resolveBundleDir } from './config.js';
5
+ export { clearAllProviderCreds };
6
+ function buildStandardEnv(baseEnv, agentId, orgId, apiKey, dirs, pc) {
7
+ const env = { ...baseEnv };
8
+ clearAllProviderCreds(env);
9
+ env.PRLL_API_KEY = apiKey;
10
+ env.PRLL_ORG_ID = orgId;
11
+ env.AGENT_ID = agentId;
12
+ env.PRLL_AGENT_ID = agentId;
13
+ env.PRLL_STATE_DIR = dirs.stateDir;
14
+ env.PRLL_WORKSPACE_DIR = dirs.workspaceDir;
15
+ if (pc)
16
+ env.PRLL_PROVIDER_CONFIG = JSON.stringify(pc);
17
+ delete env.PRLL_DAEMON_MODE;
18
+ return env;
20
19
  }
21
20
  const claudeCodeAdapter = {
22
- bin: "parall-claude-agent",
21
+ bin: 'parall-claude-agent',
22
+ args: [],
23
23
  buildEnv(baseEnv, agentId, orgId, apiKey, dirs, pc) {
24
- const env = { ...baseEnv };
25
- clearAllProviderCreds(env);
26
- env.PRLL_API_KEY = apiKey;
27
- env.PRLL_ORG_ID = orgId;
28
- env.AGENT_ID = agentId;
29
- env.PRLL_AGENT_ID = agentId;
24
+ const env = buildStandardEnv(baseEnv, agentId, orgId, apiKey, dirs, pc);
30
25
  env.PRLL_CLAUDE_HOME = dirs.claudeHome;
31
- env.PRLL_CLAUDE_STATE_DIR = dirs.stateDir;
32
- env.PRLL_CLAUDE_WORKSPACE_DIR = dirs.workspaceDir;
33
- const source = llmSource(pc);
34
- if (source === "parall") {
35
- env.ANTHROPIC_AUTH_TOKEN = apiKey;
36
- env.ANTHROPIC_BASE_URL = `${baseEnv.PRLL_API_URL}/api/llm`;
37
- env.PRLL_CLAUDE_ALLOW_API_KEY = "1";
38
- }
39
- else if (source === "custom") {
40
- if (pc?.anthropic_auth_token) {
41
- env.ANTHROPIC_AUTH_TOKEN = pc.anthropic_auth_token;
42
- env.PRLL_CLAUDE_ALLOW_API_KEY = "1";
43
- }
44
- if (pc?.anthropic_base_url)
45
- env.ANTHROPIC_BASE_URL = pc.anthropic_base_url;
46
- }
47
- delete env.PRLL_DAEMON_MODE;
48
26
  return env;
49
27
  },
50
28
  };
51
29
  const codexAdapter = {
52
- bin: "parall-codex-agent",
30
+ bin: 'parall-codex-agent',
31
+ args: [],
53
32
  buildEnv(baseEnv, agentId, orgId, apiKey, dirs, pc) {
54
- const env = { ...baseEnv };
55
- clearAllProviderCreds(env);
56
- env.PRLL_API_KEY = apiKey;
57
- env.PRLL_ORG_ID = orgId;
58
- env.AGENT_ID = agentId;
59
- env.PRLL_AGENT_ID = agentId;
60
- env.PRLL_CODEX_STATE_DIR = dirs.stateDir;
61
- env.PRLL_CODEX_WORKSPACE_DIR = dirs.workspaceDir;
62
- env.PRLL_CODEX_HOME = path.join(dirs.stateDir, ".codex");
63
- const source = llmSource(pc);
64
- if (source === "parall") {
65
- env.OPENAI_API_KEY = apiKey;
66
- env.OPENAI_BASE_URL = `${baseEnv.PRLL_API_URL}/api/llm/v1`;
67
- }
68
- else if (source === "custom") {
69
- if (pc?.openai_api_key)
70
- env.OPENAI_API_KEY = pc.openai_api_key;
71
- if (pc?.openai_base_url)
72
- env.OPENAI_BASE_URL = pc.openai_base_url;
73
- }
74
- delete env.PRLL_DAEMON_MODE;
33
+ const env = buildStandardEnv(baseEnv, agentId, orgId, apiKey, dirs, pc);
34
+ env.PRLL_CODEX_HOME = path.join(dirs.stateDir, '.codex');
75
35
  return env;
76
36
  },
77
37
  };
78
38
  const defaultAdapter = {
79
- bin: "parall-agent",
80
- buildEnv(baseEnv, agentId, orgId, apiKey, dirs) {
81
- const env = { ...baseEnv };
82
- env.PRLL_API_KEY = apiKey;
83
- env.PRLL_ORG_ID = orgId;
84
- env.AGENT_ID = agentId;
85
- env.PRLL_AGENT_ID = agentId;
86
- env.PRLL_STATE_DIR = dirs.stateDir;
87
- env.PRLL_WORKSPACE_DIR = dirs.workspaceDir;
88
- delete env.PRLL_DAEMON_MODE;
89
- return env;
90
- },
39
+ bin: 'parall-agent',
40
+ args: [],
41
+ buildEnv: buildStandardEnv,
91
42
  };
92
43
  const openclawAdapter = {
93
- bin: "parall-openclaw-agent",
94
- buildEnv(baseEnv, agentId, orgId, apiKey, dirs) {
95
- const env = { ...baseEnv };
96
- clearAllProviderCreds(env);
97
- env.PRLL_API_KEY = apiKey;
98
- env.PRLL_ORG_ID = orgId;
99
- env.AGENT_ID = agentId;
100
- env.PRLL_AGENT_ID = agentId;
101
- env.PRLL_OPENCLAW_STATE_DIR = dirs.stateDir;
102
- env.PRLL_OPENCLAW_WORKSPACE_DIR = dirs.workspaceDir;
103
- env.OPENCLAW_GATEWAY_PORT = env.OPENCLAW_GATEWAY_PORT || "0";
104
- delete env.PRLL_DAEMON_MODE;
44
+ bin: 'parall-openclaw-agent',
45
+ args: [],
46
+ buildEnv(baseEnv, agentId, orgId, apiKey, dirs, pc) {
47
+ const env = buildStandardEnv(baseEnv, agentId, orgId, apiKey, dirs, pc);
48
+ env.OPENCLAW_GATEWAY_PORT = env.OPENCLAW_GATEWAY_PORT || '0';
105
49
  return env;
106
50
  },
107
51
  };
108
52
  const RUNTIME_ADAPTERS = {
109
- "claude-code": claudeCodeAdapter,
110
- "codex": codexAdapter,
111
- "openclaw": openclawAdapter,
53
+ 'claude-code': claudeCodeAdapter,
54
+ codex: codexAdapter,
55
+ openclaw: openclawAdapter,
56
+ };
57
+ const OVERLAY_BIN_NAMES = {
58
+ 'claude-code': 'parall-claude-agent.js',
59
+ codex: 'parall-codex-agent.js',
60
+ openclaw: 'parall-openclaw-agent.js',
112
61
  };
62
+ /**
63
+ * Resolve a runtime adapter, preferring overlay bundle paths when available.
64
+ * When the daemon has self-updated into ~/.parall-daemon/bundle/, bridge
65
+ * binaries should also load from overlay to keep versions in sync.
66
+ */
113
67
  export function getRuntimeAdapter(runtimeType) {
114
- return RUNTIME_ADAPTERS[runtimeType] ?? defaultAdapter;
68
+ const base = RUNTIME_ADAPTERS[runtimeType] ?? defaultAdapter;
69
+ const overlayName = OVERLAY_BIN_NAMES[runtimeType];
70
+ if (!overlayName)
71
+ return base;
72
+ try {
73
+ const bundleDir = resolveBundleDir();
74
+ const overlayBin = path.join(bundleDir, 'current', overlayName);
75
+ if (fs.existsSync(overlayBin)) {
76
+ return { ...base, bin: process.execPath, args: [overlayBin] };
77
+ }
78
+ }
79
+ catch {
80
+ // resolveBundleDir may fail in unusual setups; fall through
81
+ }
82
+ return base;
115
83
  }
116
84
  export function assertAgentKey(apiKey) {
117
- if (apiKey.startsWith("mck_")) {
118
- throw new Error("BUG: machine key leaked to child process — expected agk_, got mck_");
85
+ if (apiKey.startsWith('mck_')) {
86
+ throw new Error('BUG: machine key leaked to child process — expected agk_, got mck_');
119
87
  }
120
88
  }
@@ -1,6 +1,7 @@
1
- import type { GatewayLogger } from "@parall/agent-core";
2
- import { ParallClient } from "@parall/sdk";
3
- import { type ClaudeDaemonConfig } from "./config.js";
1
+ import { type GatewayLogger } from '@parall/agent-core';
2
+ import { ParallClient } from '@parall/sdk';
3
+ import type { DaemonUpdater } from './updater.js';
4
+ import { type ClaudeDaemonConfig } from './config.js';
4
5
  /**
5
6
  * Sleep that wakes early on abort. Returns true if the full delay elapsed,
6
7
  * false if aborted. Used by bootstrap retry and the outer keepalive in
@@ -30,10 +31,16 @@ export declare class DaemonSupervisor {
30
31
  private readonly cancelledSpawns;
31
32
  private ws;
32
33
  private running;
34
+ private machineId;
33
35
  private machineOrgId;
34
36
  private machineLlmSource;
35
37
  private stopResolve;
38
+ private updater;
39
+ private healthConfirmed;
40
+ private clipManager;
41
+ private clipProvider;
36
42
  constructor(config: ClaudeDaemonConfig, client: ParallClient, log: GatewayLogger);
43
+ setUpdater(updater: DaemonUpdater): void;
37
44
  /** Start the supervisor. Returns a promise that resolves on `stop()`. */
38
45
  run(signal: AbortSignal): Promise<void>;
39
46
  /** Disconnect WS, cancel timers, SIGTERM all children, await exit. */
@@ -50,6 +57,8 @@ export declare class DaemonSupervisor {
50
57
  private handleAgentAttached;
51
58
  private handleAgentDetached;
52
59
  private handleFilesystemBrowse;
60
+ private handleClipInstall;
61
+ private reconcileClipInstalls;
53
62
  private handleWorkspaceSetupRequested;
54
63
  private scheduleWorkspaceSetupRetry;
55
64
  private clearWorkspaceSetupRetry;
@@ -1 +1 @@
1
- {"version":3,"file":"supervisor.d.ts","sourceRoot":"","sources":["../src/supervisor.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,EAAE,YAAY,EAA6P,MAAM,aAAa,CAAC;AAEtS,OAAO,EACL,KAAK,kBAAkB,EAMxB,MAAM,aAAa,CAAC;AAiBrB;;;;GAIG;AACH,iBAAS,gBAAgB,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC,CAa3E;AAED,OAAO,EAAE,gBAAgB,EAAE,CAAC;AAyB5B;;;;;;;;;;GAUG;AACH,qBAAa,gBAAgB;IAazB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,GAAG;IAdtB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAiC;IAC1D,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAqB;IACpD,OAAO,CAAC,QAAQ,CAAC,qBAAqB,CAAqB;IAC3D,OAAO,CAAC,QAAQ,CAAC,yBAAyB,CAAqC;IAC/E,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAqB;IACrD,OAAO,CAAC,EAAE,CAAyB;IACnC,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,YAAY,CAAuB;IAC3C,OAAO,CAAC,gBAAgB,CAAoB;IAC5C,OAAO,CAAC,WAAW,CAA6B;gBAG7B,MAAM,EAAE,kBAAkB,EAC1B,MAAM,EAAE,YAAY,EACpB,GAAG,EAAE,aAAa;IAGrC,yEAAyE;IACnE,GAAG,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAsF7C,sEAAsE;IAChE,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;YAiCb,kBAAkB;YAqClB,aAAa;IAqD3B;;;;OAIG;IACH,OAAO,CAAC,iBAAiB;YA6CX,kBAAkB;YAqBlB,mBAAmB;YAgBnB,mBAAmB;YAmBnB,sBAAsB;YAwBtB,6BAA6B;IAqC3C,OAAO,CAAC,2BAA2B;IAYnC,OAAO,CAAC,wBAAwB;YAUlB,oBAAoB;YAcpB,kBAAkB;YAYlB,eAAe;YAcf,UAAU;YAoBV,cAAc;IA2D5B,OAAO,CAAC,UAAU;YA0EJ,cAAc;IAyB5B,OAAO,CAAC,0BAA0B;CA8BnC"}
1
+ {"version":3,"file":"supervisor.d.ts","sourceRoot":"","sources":["../src/supervisor.ts"],"names":[],"mappings":"AAGA,OAAO,EAA8B,KAAK,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACpF,OAAO,EACL,YAAY,EAab,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAElD,OAAO,EACL,KAAK,kBAAkB,EAMxB,MAAM,aAAa,CAAC;AAmBrB;;;;GAIG;AACH,iBAAS,gBAAgB,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC,CAa3E;AAED,OAAO,EAAE,gBAAgB,EAAE,CAAC;AAyB5B;;;;;;;;;;GAUG;AACH,qBAAa,gBAAgB;IAkBzB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,GAAG;IAnBtB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAiC;IAC1D,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAqB;IACpD,OAAO,CAAC,QAAQ,CAAC,qBAAqB,CAAqB;IAC3D,OAAO,CAAC,QAAQ,CAAC,yBAAyB,CAAqC;IAC/E,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAqB;IACrD,OAAO,CAAC,EAAE,CAAyB;IACnC,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,SAAS,CAAuB;IACxC,OAAO,CAAC,YAAY,CAAuB;IAC3C,OAAO,CAAC,gBAAgB,CAAoB;IAC5C,OAAO,CAAC,WAAW,CAA6B;IAChD,OAAO,CAAC,OAAO,CAA8B;IAC7C,OAAO,CAAC,eAAe,CAAS;IAChC,OAAO,CAAC,WAAW,CAAmC;IACtD,OAAO,CAAC,YAAY,CAA6B;gBAG9B,MAAM,EAAE,kBAAkB,EAC1B,MAAM,EAAE,YAAY,EACpB,GAAG,EAAE,aAAa;IAGrC,UAAU,CAAC,OAAO,EAAE,aAAa,GAAG,IAAI;IAIxC,yEAAyE;IACnE,GAAG,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IA+J7C,sEAAsE;IAChE,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;YAyCb,kBAAkB;YAsClB,aAAa;IA2D3B;;;;OAIG;IACH,OAAO,CAAC,iBAAiB;YA6CX,kBAAkB;YAqBlB,mBAAmB;YAgBnB,mBAAmB;YAmBnB,sBAAsB;YAwBtB,iBAAiB;YAmEjB,qBAAqB;YAqBrB,6BAA6B;IAqC3C,OAAO,CAAC,2BAA2B;IAYnC,OAAO,CAAC,wBAAwB;YAUlB,oBAAoB;YAgBpB,kBAAkB;YAYlB,eAAe;YAcf,UAAU;YAoBV,cAAc;IAkE5B,OAAO,CAAC,UAAU;YA2GJ,cAAc;IAyB5B,OAAO,CAAC,0BAA0B;CAkCnC"}