@parall/daemon 1.28.1 → 1.29.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/index.js CHANGED
@@ -1,15 +1,10 @@
1
1
  #!/usr/bin/env node
2
+ import { createLogger } from "@parall/agent-core";
2
3
  import { ParallClient } from "@parall/sdk";
3
4
  import { resolveClaudeDaemonConfig, resolveWsUrl } from "./config.js";
4
5
  import { DaemonSupervisor, sleepCancellable } from "./supervisor.js";
5
6
  import { runCLI } from "./cli.js";
6
- function createLogger(prefix) {
7
- return {
8
- info: (msg) => console.log(`[${prefix}] ${msg}`),
9
- warn: (msg) => console.warn(`[${prefix}] ${msg}`),
10
- error: (msg) => console.error(`[${prefix}] ${msg}`),
11
- };
12
- }
7
+ const log = createLogger("daemon");
13
8
  function formatError(reason) {
14
9
  if (reason instanceof Error) {
15
10
  return reason.stack ?? reason.message;
@@ -73,7 +68,6 @@ async function runForever(config, client, log, signal) {
73
68
  }
74
69
  async function main() {
75
70
  const config = resolveClaudeDaemonConfig(process.env);
76
- const log = createLogger("daemon");
77
71
  log.info(`boot: api=${config.apiUrl} pollMs=${config.pollIntervalMs} heartbeatMs=${config.heartbeatIntervalMs} agentBin=${config.agentBin}`);
78
72
  log.info(`keepalive: bootstrapBackoffMs=${config.bootstrapBackoffMs} supervisorRestartBackoffMs=${config.supervisorRestartBackoffMs}`);
79
73
  // The daemon talks to the API as a Machine — the bearer is mck_*.
@@ -110,11 +104,11 @@ runCLI(cliArgs)
110
104
  if (result === "handled")
111
105
  return;
112
106
  main().catch((err) => {
113
- console.error(`[daemon] fatal: ${formatError(err)}`);
107
+ log.error(`fatal: ${formatError(err)}`);
114
108
  process.exitCode = 1;
115
109
  });
116
110
  })
117
111
  .catch((err) => {
118
- console.error(`[daemon] fatal: ${formatError(err)}`);
112
+ log.error(`fatal: ${formatError(err)}`);
119
113
  process.exitCode = 1;
120
114
  });
@@ -1,6 +1,13 @@
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
8
  export interface RuntimeAdapter {
2
9
  bin: string;
3
- buildEnv(baseEnv: NodeJS.ProcessEnv, agentId: string, orgId: string, apiKey: string, dirs: AgentDirs): NodeJS.ProcessEnv;
10
+ buildEnv(baseEnv: NodeJS.ProcessEnv, agentId: string, orgId: string, apiKey: string, dirs: AgentDirs, pc?: ProviderConfig): NodeJS.ProcessEnv;
4
11
  }
5
12
  export interface AgentDirs {
6
13
  stateDir: string;
@@ -1 +1 @@
1
- {"version":3,"file":"runtimes.d.ts","sourceRoot":"","sources":["../src/runtimes.ts"],"names":[],"mappings":"AAAA,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,GAAG,MAAM,CAAC,UAAU,CAAC;CAC1H;AAED,MAAM,WAAW,SAAS;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;CACpB;AAyED,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,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;AAsHD,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,7 +1,28 @@
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
+ 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;
20
+ }
1
21
  const claudeCodeAdapter = {
2
22
  bin: "parall-claude-agent",
3
- buildEnv(baseEnv, agentId, orgId, apiKey, dirs) {
23
+ buildEnv(baseEnv, agentId, orgId, apiKey, dirs, pc) {
4
24
  const env = { ...baseEnv };
25
+ clearAllProviderCreds(env);
5
26
  env.PRLL_API_KEY = apiKey;
6
27
  env.PRLL_ORG_ID = orgId;
7
28
  env.AGENT_ID = agentId;
@@ -9,8 +30,19 @@ const claudeCodeAdapter = {
9
30
  env.PRLL_CLAUDE_HOME = dirs.claudeHome;
10
31
  env.PRLL_CLAUDE_STATE_DIR = dirs.stateDir;
11
32
  env.PRLL_CLAUDE_WORKSPACE_DIR = dirs.workspaceDir;
12
- if ("ANTHROPIC_AUTH_TOKEN" in env) {
33
+ const source = llmSource(pc);
34
+ if (source === "parall") {
13
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;
14
46
  }
15
47
  delete env.PRLL_DAEMON_MODE;
16
48
  return env;
@@ -18,14 +50,27 @@ const claudeCodeAdapter = {
18
50
  };
19
51
  const codexAdapter = {
20
52
  bin: "parall-codex-agent",
21
- buildEnv(baseEnv, agentId, orgId, apiKey, dirs) {
53
+ buildEnv(baseEnv, agentId, orgId, apiKey, dirs, pc) {
22
54
  const env = { ...baseEnv };
55
+ clearAllProviderCreds(env);
23
56
  env.PRLL_API_KEY = apiKey;
24
57
  env.PRLL_ORG_ID = orgId;
25
58
  env.AGENT_ID = agentId;
26
59
  env.PRLL_AGENT_ID = agentId;
27
60
  env.PRLL_CODEX_STATE_DIR = dirs.stateDir;
28
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
+ }
29
74
  delete env.PRLL_DAEMON_MODE;
30
75
  return env;
31
76
  },
@@ -48,6 +93,7 @@ const openclawAdapter = {
48
93
  bin: "parall-openclaw-agent",
49
94
  buildEnv(baseEnv, agentId, orgId, apiKey, dirs) {
50
95
  const env = { ...baseEnv };
96
+ clearAllProviderCreds(env);
51
97
  env.PRLL_API_KEY = apiKey;
52
98
  env.PRLL_ORG_ID = orgId;
53
99
  env.AGENT_ID = agentId;
@@ -1,10 +1,6 @@
1
+ import type { GatewayLogger } from "@parall/agent-core";
1
2
  import { ParallClient } from "@parall/sdk";
2
3
  import { type ClaudeDaemonConfig } from "./config.js";
3
- export interface DaemonLogger {
4
- info(msg: string): void;
5
- warn(msg: string): void;
6
- error(msg: string): void;
7
- }
8
4
  /**
9
5
  * Sleep that wakes early on abort. Returns true if the full delay elapsed,
10
6
  * false if aborted. Used by bootstrap retry and the outer keepalive in
@@ -31,8 +27,9 @@ export declare class DaemonSupervisor {
31
27
  private ws;
32
28
  private running;
33
29
  private machineOrgId;
30
+ private machineLlmSource;
34
31
  private stopResolve;
35
- constructor(config: ClaudeDaemonConfig, client: ParallClient, log: DaemonLogger);
32
+ constructor(config: ClaudeDaemonConfig, client: ParallClient, log: GatewayLogger);
36
33
  /** Start the supervisor. Returns a promise that resolves on `stop()`. */
37
34
  run(signal: AbortSignal): Promise<void>;
38
35
  /** Disconnect WS, cancel timers, SIGTERM all children, await exit. */
@@ -47,6 +44,8 @@ export declare class DaemonSupervisor {
47
44
  private migrateFlatLayout;
48
45
  private handleAgentAttached;
49
46
  private handleAgentDetached;
47
+ private refreshMachineConfig;
48
+ private respawnAllChildren;
50
49
  private restartChildNow;
51
50
  private spawnAgent;
52
51
  private startChild;
@@ -1 +1 @@
1
- {"version":3,"file":"supervisor.d.ts","sourceRoot":"","sources":["../src/supervisor.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,YAAY,EAAmJ,MAAM,aAAa,CAAC;AAC5L,OAAO,EACL,KAAK,kBAAkB,EAMxB,MAAM,aAAa,CAAC;AASrB,MAAM,WAAW,YAAY;IAC3B,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAED;;;;GAIG;AACH,iBAAS,gBAAgB,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC,CAa3E;AAED,OAAO,EAAE,gBAAgB,EAAE,CAAC;AAuB5B;;;;;;;;;;GAUG;AACH,qBAAa,gBAAgB;IAQzB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,GAAG;IATtB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAiC;IAC1D,OAAO,CAAC,EAAE,CAAyB;IACnC,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,YAAY,CAAuB;IAC3C,OAAO,CAAC,WAAW,CAA6B;gBAG7B,MAAM,EAAE,kBAAkB,EAC1B,MAAM,EAAE,YAAY,EACpB,GAAG,EAAE,YAAY;IAGpC,yEAAyE;IACnE,GAAG,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAgE7C,sEAAsE;IAChE,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;YA6Bb,kBAAkB;YAoClB,aAAa;IAqD3B;;;;OAIG;IACH,OAAO,CAAC,iBAAiB;YA6CX,mBAAmB;YA6BnB,mBAAmB;YAgBnB,eAAe;YAcf,UAAU;IA+CxB,OAAO,CAAC,UAAU;YAwEJ,cAAc;IAyB5B,OAAO,CAAC,0BAA0B;CA8BnC"}
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,EAAkL,MAAM,aAAa,CAAC;AAC3N,OAAO,EACL,KAAK,kBAAkB,EAMxB,MAAM,aAAa,CAAC;AASrB;;;;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;IASzB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,GAAG;IAVtB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAiC;IAC1D,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;IA4E7C,sEAAsE;IAChE,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;YA6Bb,kBAAkB;YAqClB,aAAa;IAqD3B;;;;OAIG;IACH,OAAO,CAAC,iBAAiB;YA6CX,mBAAmB;YA6BnB,mBAAmB;YAgBnB,oBAAoB;YAcpB,kBAAkB;YAYlB,eAAe;YAcf,UAAU;IAgDxB,OAAO,CAAC,UAAU;YAyEJ,cAAc;IAyB5B,OAAO,CAAC,0BAA0B;CA8BnC"}
@@ -49,6 +49,7 @@ export class DaemonSupervisor {
49
49
  ws = null;
50
50
  running = false;
51
51
  machineOrgId = null;
52
+ machineLlmSource = "parall";
52
53
  stopResolve = null;
53
54
  constructor(config, client, log) {
54
55
  this.config = config;
@@ -85,7 +86,10 @@ export class DaemonSupervisor {
85
86
  });
86
87
  this.ws.on("machine.hello", (_data) => {
87
88
  this.log.info("machine WS connected (machine.hello)");
88
- void this.fullReconcile();
89
+ void (async () => {
90
+ await this.refreshMachineConfig();
91
+ await this.fullReconcile();
92
+ })();
89
93
  });
90
94
  this.ws.on("machine.agent.attached", (data) => {
91
95
  this.log.info(`WS: agent ${data.agent_id} attached`);
@@ -95,6 +99,14 @@ export class DaemonSupervisor {
95
99
  this.log.info(`WS: agent ${data.agent_id} detached`);
96
100
  void this.handleAgentDetached(data.agent_id);
97
101
  });
102
+ this.ws.on("machine.config.updated", (data) => {
103
+ const newSource = data.llm_source ?? "parall";
104
+ if (newSource !== this.machineLlmSource) {
105
+ this.log.info(`WS: llm_source changed ${this.machineLlmSource} → ${newSource}, respawning all agents`);
106
+ this.machineLlmSource = newSource;
107
+ void this.respawnAllChildren();
108
+ }
109
+ });
98
110
  this.ws.on("machine.stop", (data) => {
99
111
  this.log.info(`WS: machine.stop received (reason=${data.reason ?? "none"})`);
100
112
  void this.stop();
@@ -143,6 +155,7 @@ export class DaemonSupervisor {
143
155
  try {
144
156
  const machine = await this.client.getMachineSelf();
145
157
  this.machineOrgId = machine.org_id;
158
+ this.machineLlmSource = machine.llm_source ?? "parall";
146
159
  this.log.info(`daemon online — machine_id=${machine.id} org=${machine.org_id} label=${machine.label}`);
147
160
  return true;
148
161
  }
@@ -305,6 +318,31 @@ export class DaemonSupervisor {
305
318
  this.children.delete(agentId);
306
319
  }
307
320
  // ---- Spawn / restart ----
321
+ async refreshMachineConfig() {
322
+ try {
323
+ const machine = await this.client.getMachineSelf();
324
+ const newSource = machine.llm_source ?? "parall";
325
+ if (newSource !== this.machineLlmSource) {
326
+ this.log.info(`machine config refreshed: llm_source ${this.machineLlmSource} → ${newSource}`);
327
+ this.machineLlmSource = newSource;
328
+ await this.respawnAllChildren();
329
+ }
330
+ }
331
+ catch (err) {
332
+ this.log.warn(`refreshMachineConfig failed: ${String(err)}`);
333
+ }
334
+ }
335
+ async respawnAllChildren() {
336
+ const states = [...this.children.values()];
337
+ for (const state of states) {
338
+ await this.terminateChild(state);
339
+ }
340
+ for (const state of states) {
341
+ if (!state.shuttingDown && this.running) {
342
+ await this.restartChildNow(state, "llm_source changed");
343
+ }
344
+ }
345
+ }
308
346
  async restartChildNow(state, reason) {
309
347
  if (!this.running || state.shuttingDown || state.child || state.restartTimer) {
310
348
  return;
@@ -357,6 +395,7 @@ export class DaemonSupervisor {
357
395
  runtimeType,
358
396
  workspacePath: workspaceDir,
359
397
  claudeHome,
398
+ providerConfig: attached.provider_config ?? { llm_source: this.machineLlmSource },
360
399
  child: null,
361
400
  credential,
362
401
  restartAttempts: 0,
@@ -380,7 +419,7 @@ export class DaemonSupervisor {
380
419
  workspaceDir: state.workspacePath,
381
420
  claudeHome: state.claudeHome,
382
421
  };
383
- const env = adapter.buildEnv({ ...process.env, PRLL_API_URL: this.config.apiUrl }, state.agentId, state.orgId, state.credential.api_key, dirs);
422
+ const env = adapter.buildEnv({ ...process.env, PRLL_API_URL: this.config.apiUrl }, state.agentId, state.orgId, state.credential.api_key, dirs, state.providerConfig);
384
423
  this.log.info(`spawning agent ${state.agentId} runtime=${state.runtimeType} bin=${adapter.bin} (attempt ${state.restartAttempts + 1})`);
385
424
  const child = spawn(adapter.bin, [], {
386
425
  env,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@parall/daemon",
3
- "version": "1.28.1",
3
+ "version": "1.29.0",
4
4
  "description": "Parall local agent runtime — daemon supervisor + bridge runtimes, bundled as standalone JS files",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -12,6 +12,7 @@
12
12
  "main": "./bundle/parall-daemon.js",
13
13
  "types": "./dist/index.d.ts",
14
14
  "bin": {
15
+ "daemon": "./bundle/parall-daemon.js",
15
16
  "parall-daemon": "./bundle/parall-daemon.js",
16
17
  "parall-claude-agent": "./bundle/parall-claude-agent.js",
17
18
  "parall-codex-agent": "./bundle/parall-codex-agent.js",
@@ -28,10 +29,11 @@
28
29
  "dist"
29
30
  ],
30
31
  "dependencies": {
31
- "@parall/sdk": "1.28.1",
32
- "@parall/claude-agent": "1.28.1",
33
- "@parall/codex-agent": "1.28.1",
34
- "@parall/openclaw-agent": "1.28.1"
32
+ "@parall/agent-core": "1.29.0",
33
+ "@parall/sdk": "1.29.0",
34
+ "@parall/claude-agent": "1.29.0",
35
+ "@parall/codex-agent": "1.29.0",
36
+ "@parall/openclaw-agent": "1.29.0"
35
37
  },
36
38
  "devDependencies": {
37
39
  "@types/node": "^22.0.0",