@parall/claude-agent 1.20.2 → 1.22.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/config.d.ts +1 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +1 -0
- package/dist/dispatch.d.ts +4 -1
- package/dist/dispatch.d.ts.map +1 -1
- package/dist/dispatch.js +27 -12
- package/dist/index.js +9 -1
- package/dist/workspace.d.ts +2 -1
- package/dist/workspace.d.ts.map +1 -1
- package/dist/workspace.js +8 -12
- package/package.json +4 -4
- package/src/config.ts +2 -0
- package/src/dispatch.ts +34 -12
- package/src/index.ts +14 -1
- package/src/workspace.ts +9 -12
package/dist/config.d.ts
CHANGED
|
@@ -15,6 +15,7 @@ export type ClaudeAgentConfig = {
|
|
|
15
15
|
additionalDirs: string[];
|
|
16
16
|
appendSystemPrompt?: string;
|
|
17
17
|
runtimeKey?: string;
|
|
18
|
+
allowApiKey: boolean;
|
|
18
19
|
};
|
|
19
20
|
export declare function resolveClaudeAgentConfig(env?: NodeJS.ProcessEnv): ClaudeAgentConfig;
|
|
20
21
|
export declare function resolveWsUrl(apiUrl: string, explicitWsUrl?: string, swimlaneName?: string): string;
|
package/dist/config.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,iBAAiB,GAAG;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,UAAU,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,iBAAiB,GAAG;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,OAAO,CAAC;CACtB,CAAC;AAsBF,wBAAgB,wBAAwB,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,iBAAiB,CA4BhG;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,aAAa,CAAC,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,MAAM,GAAG,MAAM,CAMlG;AAED,wBAAgB,qBAAqB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAEjE;AAED,wBAAgB,8BAA8B,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAG3F;AAED,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAGrF"}
|
package/dist/config.js
CHANGED
|
@@ -43,6 +43,7 @@ export function resolveClaudeAgentConfig(env = process.env) {
|
|
|
43
43
|
additionalDirs,
|
|
44
44
|
appendSystemPrompt: env.PRLL_CLAUDE_APPEND_SYSTEM_PROMPT?.trim() || undefined,
|
|
45
45
|
runtimeKey: env.PRLL_CLAUDE_RUNTIME_KEY?.trim() || undefined,
|
|
46
|
+
allowApiKey: env.PRLL_CLAUDE_ALLOW_API_KEY?.trim() === "1",
|
|
46
47
|
};
|
|
47
48
|
}
|
|
48
49
|
export function resolveWsUrl(apiUrl, explicitWsUrl, swimlaneName) {
|
package/dist/dispatch.d.ts
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import type { CleanupForkOpts, DispatchAdapter, DispatchOpts, ForkOpts, RuntimeEvent } from "@parall/agent-core";
|
|
2
2
|
import type { ClaudeAgentConfig } from "./config.js";
|
|
3
3
|
import { ClaudeSessionManager } from "./session-manager.js";
|
|
4
|
-
type ClaudeCodeAdapterOptions = Pick<ClaudeAgentConfig, "additionalDirs" | "allowedTools" | "appendSystemPrompt" | "claudeBin" | "claudeHome" | "disallowedTools" | "model" | "permissionMode" | "workspaceDir"> & {
|
|
4
|
+
type ClaudeCodeAdapterOptions = Pick<ClaudeAgentConfig, "additionalDirs" | "allowApiKey" | "allowedTools" | "appendSystemPrompt" | "claudeBin" | "claudeHome" | "disallowedTools" | "model" | "permissionMode" | "workspaceDir"> & {
|
|
5
5
|
sessionManager: ClaudeSessionManager;
|
|
6
6
|
};
|
|
7
|
+
export declare function buildSpawnEnv(parentEnv: NodeJS.ProcessEnv, claudeHome: string, context: DispatchOpts["context"], opts: {
|
|
8
|
+
allowApiKey: boolean;
|
|
9
|
+
}): NodeJS.ProcessEnv;
|
|
7
10
|
export declare class ClaudeCodeAdapter implements DispatchAdapter {
|
|
8
11
|
private readonly opts;
|
|
9
12
|
constructor(opts: ClaudeCodeAdapterOptions);
|
package/dist/dispatch.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dispatch.d.ts","sourceRoot":"","sources":["../src/dispatch.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,eAAe,EACf,eAAe,EACf,YAAY,EACZ,QAAQ,EACR,YAAY,EACb,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAErD,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAE5D,KAAK,wBAAwB,GAAG,IAAI,CAClC,iBAAiB,EACf,gBAAgB,GAChB,cAAc,GACd,oBAAoB,GACpB,WAAW,GACX,YAAY,GACZ,iBAAiB,GACjB,OAAO,GACP,gBAAgB,GAChB,cAAc,CACjB,GAAG;IACF,cAAc,EAAE,oBAAoB,CAAC;CACtC,CAAC;AAEF,qBAAa,iBAAkB,YAAW,eAAe;IAC3C,OAAO,CAAC,QAAQ,CAAC,IAAI;gBAAJ,IAAI,EAAE,wBAAwB;IAEpD,QAAQ,CAAC,EAAE,YAAY,EAAE,UAAU,EAAE,OAAO,EAAE,EAAE,YAAY,GAAG,aAAa,CAAC,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"dispatch.d.ts","sourceRoot":"","sources":["../src/dispatch.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,eAAe,EACf,eAAe,EACf,YAAY,EACZ,QAAQ,EACR,YAAY,EACb,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAErD,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAE5D,KAAK,wBAAwB,GAAG,IAAI,CAClC,iBAAiB,EACf,gBAAgB,GAChB,aAAa,GACb,cAAc,GACd,oBAAoB,GACpB,WAAW,GACX,YAAY,GACZ,iBAAiB,GACjB,OAAO,GACP,gBAAgB,GAChB,cAAc,CACjB,GAAG;IACF,cAAc,EAAE,oBAAoB,CAAC;CACtC,CAAC;AAEF,wBAAgB,aAAa,CAC3B,SAAS,EAAE,MAAM,CAAC,UAAU,EAC5B,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,YAAY,CAAC,SAAS,CAAC,EAChC,IAAI,EAAE;IAAE,WAAW,EAAE,OAAO,CAAA;CAAE,GAC7B,MAAM,CAAC,UAAU,CAuBnB;AAED,qBAAa,iBAAkB,YAAW,eAAe;IAC3C,OAAO,CAAC,QAAQ,CAAC,IAAI;gBAAJ,IAAI,EAAE,wBAAwB;IAEpD,QAAQ,CAAC,EAAE,YAAY,EAAE,UAAU,EAAE,OAAO,EAAE,EAAE,YAAY,GAAG,aAAa,CAAC,YAAY,CAAC;IA+EjG,WAAW,CAAC,EAAE,UAAU,EAAE,EAAE,QAAQ;IAIpC,WAAW,CAAC,EAAE,IAAI,EAAE,EAAE,eAAe;IAIrC,OAAO,CAAC,SAAS;CAkClB"}
|
package/dist/dispatch.js
CHANGED
|
@@ -1,6 +1,30 @@
|
|
|
1
1
|
import { randomUUID } from "node:crypto";
|
|
2
2
|
import { spawn } from "node:child_process";
|
|
3
3
|
import { parseClaudeStreamJson } from "./output-parser.js";
|
|
4
|
+
export function buildSpawnEnv(parentEnv, claudeHome, context, opts) {
|
|
5
|
+
const env = { ...parentEnv };
|
|
6
|
+
// Default: behave like the hosted Claude container — OAuth via
|
|
7
|
+
// ~/.claude/.credentials.json only. Inheriting the operator's
|
|
8
|
+
// ANTHROPIC_API_KEY would silently divert billing to Anthropic API
|
|
9
|
+
// pay-per-use instead of the connected Claude.ai subscription.
|
|
10
|
+
// Opt back in with PRLL_CLAUDE_ALLOW_API_KEY=1.
|
|
11
|
+
if (!opts.allowApiKey) {
|
|
12
|
+
delete env.ANTHROPIC_API_KEY;
|
|
13
|
+
delete env.ANTHROPIC_AUTH_TOKEN;
|
|
14
|
+
}
|
|
15
|
+
return {
|
|
16
|
+
...env,
|
|
17
|
+
HOME: claudeHome,
|
|
18
|
+
PRLL_API_URL: context.apiUrl,
|
|
19
|
+
PRLL_API_KEY: context.apiKey,
|
|
20
|
+
PRLL_ORG_ID: context.orgId,
|
|
21
|
+
PRLL_SESSION_ID: context.sessionId ?? "",
|
|
22
|
+
PRLL_CHAT_ID: context.chatId ?? "",
|
|
23
|
+
PRLL_TRIGGER_MESSAGE_ID: context.triggerMessageId ?? "",
|
|
24
|
+
PRLL_NO_REPLY: context.noReply ? "1" : "",
|
|
25
|
+
PRLL_STEP_ID_FILE: context.stepIdFilePath ?? "",
|
|
26
|
+
};
|
|
27
|
+
}
|
|
4
28
|
export class ClaudeCodeAdapter {
|
|
5
29
|
opts;
|
|
6
30
|
constructor(opts) {
|
|
@@ -8,18 +32,9 @@ export class ClaudeCodeAdapter {
|
|
|
8
32
|
}
|
|
9
33
|
async *dispatch({ bodyForAgent, sessionKey, context }) {
|
|
10
34
|
const args = this.buildArgs(sessionKey, bodyForAgent);
|
|
11
|
-
const env = {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
PRLL_API_URL: context.apiUrl,
|
|
15
|
-
PRLL_API_KEY: context.apiKey,
|
|
16
|
-
PRLL_ORG_ID: context.orgId,
|
|
17
|
-
PRLL_SESSION_ID: context.sessionId ?? "",
|
|
18
|
-
PRLL_CHAT_ID: context.chatId ?? "",
|
|
19
|
-
PRLL_TRIGGER_MESSAGE_ID: context.triggerMessageId ?? "",
|
|
20
|
-
PRLL_NO_REPLY: context.noReply ? "1" : "",
|
|
21
|
-
PRLL_STEP_ID_FILE: context.stepIdFilePath ?? "",
|
|
22
|
-
};
|
|
35
|
+
const env = buildSpawnEnv(process.env, this.opts.claudeHome, context, {
|
|
36
|
+
allowApiKey: this.opts.allowApiKey,
|
|
37
|
+
});
|
|
23
38
|
context.log?.info(`claude-agent[${context.accountId}]: spawn ${this.opts.claudeBin} ${args.slice(0, -1).join(" ")}`);
|
|
24
39
|
const proc = spawn(this.opts.claudeBin, args, {
|
|
25
40
|
cwd: this.opts.workspaceDir,
|
package/dist/index.js
CHANGED
|
@@ -16,7 +16,13 @@ function createLogger(prefix) {
|
|
|
16
16
|
async function main() {
|
|
17
17
|
const config = resolveClaudeAgentConfig(process.env);
|
|
18
18
|
const log = createLogger("claude-agent");
|
|
19
|
-
|
|
19
|
+
if (config.allowApiKey &&
|
|
20
|
+
(process.env.ANTHROPIC_API_KEY || process.env.ANTHROPIC_AUTH_TOKEN)) {
|
|
21
|
+
// Surface the billing path: default is OAuth (Claude.ai subscription); this
|
|
22
|
+
// branch means the operator opted into Anthropic API pay-per-use, and the
|
|
23
|
+
// whole point of the strip default is that "silent" is the bad state.
|
|
24
|
+
log.warn("PRLL_CLAUDE_ALLOW_API_KEY=1 — ANTHROPIC_API_KEY/ANTHROPIC_AUTH_TOKEN will reach the Claude CLI; billing routes through Anthropic API pay-per-use instead of Claude.ai OAuth.");
|
|
25
|
+
}
|
|
20
26
|
const client = new ParallClient({
|
|
21
27
|
baseUrl: config.apiUrl,
|
|
22
28
|
token: config.apiKey,
|
|
@@ -24,6 +30,7 @@ async function main() {
|
|
|
24
30
|
});
|
|
25
31
|
const me = await client.getMe();
|
|
26
32
|
const agentUserId = me.id;
|
|
33
|
+
ensureClaudeWorkspace(config.workspaceDir, log, { userId: agentUserId, displayName: me.display_name });
|
|
27
34
|
const runtimeKey = config.runtimeKey || buildClaudeRuntimeKey(agentUserId);
|
|
28
35
|
const sessionStateFilePath = sessionStateFilePathForRuntime(config.stateDir, runtimeKey);
|
|
29
36
|
const sessionManager = new ClaudeSessionManager(runtimeKey, sessionStateFilePath, log);
|
|
@@ -42,6 +49,7 @@ async function main() {
|
|
|
42
49
|
disallowedTools: config.disallowedTools,
|
|
43
50
|
additionalDirs: config.additionalDirs,
|
|
44
51
|
appendSystemPrompt: config.appendSystemPrompt,
|
|
52
|
+
allowApiKey: config.allowApiKey,
|
|
45
53
|
sessionManager,
|
|
46
54
|
});
|
|
47
55
|
const gateway = new ParallAgentGateway({
|
package/dist/workspace.d.ts
CHANGED
package/dist/workspace.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workspace.d.ts","sourceRoot":"","sources":["../src/workspace.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"workspace.d.ts","sourceRoot":"","sources":["../src/workspace.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAExD,wBAAgB,qBAAqB,CACnC,YAAY,EAAE,MAAM,EACpB,GAAG,CAAC,EAAE;IAAE,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAA;CAAE,EACrC,aAAa,CAAC,EAAE,aAAa,QAgC9B"}
|
package/dist/workspace.js
CHANGED
|
@@ -1,17 +1,13 @@
|
|
|
1
1
|
import * as fs from "node:fs";
|
|
2
2
|
import * as path from "node:path";
|
|
3
|
-
import { BRIDGE_WORKSPACE_INSTRUCTIONS, PRLL_BEHAVIOR,
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
PRLL_BEHAVIOR,
|
|
12
|
-
PRLL_REFERENCE_GUIDE,
|
|
13
|
-
].join("\n\n");
|
|
14
|
-
export function ensureClaudeWorkspace(workspaceDir, log) {
|
|
3
|
+
import { BRIDGE_WORKSPACE_INSTRUCTIONS, PRLL_BEHAVIOR, PRLL_REFERENCE_GUIDE, buildIdentity, } from "@parall/agent-core";
|
|
4
|
+
export function ensureClaudeWorkspace(workspaceDir, log, agentIdentity) {
|
|
5
|
+
const CLAUDE_MD = [
|
|
6
|
+
buildIdentity(agentIdentity),
|
|
7
|
+
BRIDGE_WORKSPACE_INSTRUCTIONS,
|
|
8
|
+
PRLL_BEHAVIOR,
|
|
9
|
+
PRLL_REFERENCE_GUIDE,
|
|
10
|
+
].join("\n\n");
|
|
15
11
|
fs.mkdirSync(workspaceDir, { recursive: true });
|
|
16
12
|
fs.mkdirSync(path.join(workspaceDir, ".claude"), { recursive: true });
|
|
17
13
|
// CLAUDE.md is bridge-managed: always overwrite so a hosted PVC keeps the
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@parall/claude-agent",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.22.0",
|
|
4
4
|
"description": "Claude Code bridge runtime for self-hosted Parall agents",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -25,9 +25,9 @@
|
|
|
25
25
|
"src"
|
|
26
26
|
],
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@parall/cli": "1.
|
|
29
|
-
"@parall/
|
|
30
|
-
"@parall/
|
|
28
|
+
"@parall/cli": "1.22.0",
|
|
29
|
+
"@parall/sdk": "1.22.0",
|
|
30
|
+
"@parall/agent-core": "1.22.0"
|
|
31
31
|
},
|
|
32
32
|
"devDependencies": {
|
|
33
33
|
"@types/node": "^22.0.0",
|
package/src/config.ts
CHANGED
|
@@ -18,6 +18,7 @@ export type ClaudeAgentConfig = {
|
|
|
18
18
|
additionalDirs: string[];
|
|
19
19
|
appendSystemPrompt?: string;
|
|
20
20
|
runtimeKey?: string;
|
|
21
|
+
allowApiKey: boolean;
|
|
21
22
|
};
|
|
22
23
|
|
|
23
24
|
function requireEnv(env: NodeJS.ProcessEnv, name: string): string {
|
|
@@ -66,6 +67,7 @@ export function resolveClaudeAgentConfig(env: NodeJS.ProcessEnv = process.env):
|
|
|
66
67
|
additionalDirs,
|
|
67
68
|
appendSystemPrompt: env.PRLL_CLAUDE_APPEND_SYSTEM_PROMPT?.trim() || undefined,
|
|
68
69
|
runtimeKey: env.PRLL_CLAUDE_RUNTIME_KEY?.trim() || undefined,
|
|
70
|
+
allowApiKey: env.PRLL_CLAUDE_ALLOW_API_KEY?.trim() === "1",
|
|
69
71
|
};
|
|
70
72
|
}
|
|
71
73
|
|
package/src/dispatch.ts
CHANGED
|
@@ -14,6 +14,7 @@ import { ClaudeSessionManager } from "./session-manager.js";
|
|
|
14
14
|
type ClaudeCodeAdapterOptions = Pick<
|
|
15
15
|
ClaudeAgentConfig,
|
|
16
16
|
| "additionalDirs"
|
|
17
|
+
| "allowApiKey"
|
|
17
18
|
| "allowedTools"
|
|
18
19
|
| "appendSystemPrompt"
|
|
19
20
|
| "claudeBin"
|
|
@@ -26,23 +27,44 @@ type ClaudeCodeAdapterOptions = Pick<
|
|
|
26
27
|
sessionManager: ClaudeSessionManager;
|
|
27
28
|
};
|
|
28
29
|
|
|
30
|
+
export function buildSpawnEnv(
|
|
31
|
+
parentEnv: NodeJS.ProcessEnv,
|
|
32
|
+
claudeHome: string,
|
|
33
|
+
context: DispatchOpts["context"],
|
|
34
|
+
opts: { allowApiKey: boolean },
|
|
35
|
+
): NodeJS.ProcessEnv {
|
|
36
|
+
const env: NodeJS.ProcessEnv = { ...parentEnv };
|
|
37
|
+
// Default: behave like the hosted Claude container — OAuth via
|
|
38
|
+
// ~/.claude/.credentials.json only. Inheriting the operator's
|
|
39
|
+
// ANTHROPIC_API_KEY would silently divert billing to Anthropic API
|
|
40
|
+
// pay-per-use instead of the connected Claude.ai subscription.
|
|
41
|
+
// Opt back in with PRLL_CLAUDE_ALLOW_API_KEY=1.
|
|
42
|
+
if (!opts.allowApiKey) {
|
|
43
|
+
delete env.ANTHROPIC_API_KEY;
|
|
44
|
+
delete env.ANTHROPIC_AUTH_TOKEN;
|
|
45
|
+
}
|
|
46
|
+
return {
|
|
47
|
+
...env,
|
|
48
|
+
HOME: claudeHome,
|
|
49
|
+
PRLL_API_URL: context.apiUrl,
|
|
50
|
+
PRLL_API_KEY: context.apiKey,
|
|
51
|
+
PRLL_ORG_ID: context.orgId,
|
|
52
|
+
PRLL_SESSION_ID: context.sessionId ?? "",
|
|
53
|
+
PRLL_CHAT_ID: context.chatId ?? "",
|
|
54
|
+
PRLL_TRIGGER_MESSAGE_ID: context.triggerMessageId ?? "",
|
|
55
|
+
PRLL_NO_REPLY: context.noReply ? "1" : "",
|
|
56
|
+
PRLL_STEP_ID_FILE: context.stepIdFilePath ?? "",
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
|
|
29
60
|
export class ClaudeCodeAdapter implements DispatchAdapter {
|
|
30
61
|
constructor(private readonly opts: ClaudeCodeAdapterOptions) {}
|
|
31
62
|
|
|
32
63
|
async *dispatch({ bodyForAgent, sessionKey, context }: DispatchOpts): AsyncIterable<RuntimeEvent> {
|
|
33
64
|
const args = this.buildArgs(sessionKey, bodyForAgent);
|
|
34
|
-
const env = {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
PRLL_API_URL: context.apiUrl,
|
|
38
|
-
PRLL_API_KEY: context.apiKey,
|
|
39
|
-
PRLL_ORG_ID: context.orgId,
|
|
40
|
-
PRLL_SESSION_ID: context.sessionId ?? "",
|
|
41
|
-
PRLL_CHAT_ID: context.chatId ?? "",
|
|
42
|
-
PRLL_TRIGGER_MESSAGE_ID: context.triggerMessageId ?? "",
|
|
43
|
-
PRLL_NO_REPLY: context.noReply ? "1" : "",
|
|
44
|
-
PRLL_STEP_ID_FILE: context.stepIdFilePath ?? "",
|
|
45
|
-
};
|
|
65
|
+
const env = buildSpawnEnv(process.env, this.opts.claudeHome, context, {
|
|
66
|
+
allowApiKey: this.opts.allowApiKey,
|
|
67
|
+
});
|
|
46
68
|
|
|
47
69
|
context.log?.info(`claude-agent[${context.accountId}]: spawn ${this.opts.claudeBin} ${args.slice(0, -1).join(" ")}`);
|
|
48
70
|
|
package/src/index.ts
CHANGED
|
@@ -25,7 +25,18 @@ function createLogger(prefix: string) {
|
|
|
25
25
|
async function main() {
|
|
26
26
|
const config = resolveClaudeAgentConfig(process.env);
|
|
27
27
|
const log = createLogger("claude-agent");
|
|
28
|
-
|
|
28
|
+
|
|
29
|
+
if (
|
|
30
|
+
config.allowApiKey &&
|
|
31
|
+
(process.env.ANTHROPIC_API_KEY || process.env.ANTHROPIC_AUTH_TOKEN)
|
|
32
|
+
) {
|
|
33
|
+
// Surface the billing path: default is OAuth (Claude.ai subscription); this
|
|
34
|
+
// branch means the operator opted into Anthropic API pay-per-use, and the
|
|
35
|
+
// whole point of the strip default is that "silent" is the bad state.
|
|
36
|
+
log.warn(
|
|
37
|
+
"PRLL_CLAUDE_ALLOW_API_KEY=1 — ANTHROPIC_API_KEY/ANTHROPIC_AUTH_TOKEN will reach the Claude CLI; billing routes through Anthropic API pay-per-use instead of Claude.ai OAuth.",
|
|
38
|
+
);
|
|
39
|
+
}
|
|
29
40
|
|
|
30
41
|
const client = new ParallClient({
|
|
31
42
|
baseUrl: config.apiUrl,
|
|
@@ -35,6 +46,7 @@ async function main() {
|
|
|
35
46
|
|
|
36
47
|
const me = await client.getMe();
|
|
37
48
|
const agentUserId = me.id;
|
|
49
|
+
ensureClaudeWorkspace(config.workspaceDir, log, { userId: agentUserId, displayName: me.display_name });
|
|
38
50
|
const runtimeKey = config.runtimeKey || buildClaudeRuntimeKey(agentUserId);
|
|
39
51
|
const sessionStateFilePath = sessionStateFilePathForRuntime(config.stateDir, runtimeKey);
|
|
40
52
|
const sessionManager = new ClaudeSessionManager(
|
|
@@ -59,6 +71,7 @@ async function main() {
|
|
|
59
71
|
disallowedTools: config.disallowedTools,
|
|
60
72
|
additionalDirs: config.additionalDirs,
|
|
61
73
|
appendSystemPrompt: config.appendSystemPrompt,
|
|
74
|
+
allowApiKey: config.allowApiKey,
|
|
62
75
|
sessionManager,
|
|
63
76
|
});
|
|
64
77
|
|
package/src/workspace.ts
CHANGED
|
@@ -3,25 +3,22 @@ import * as path from "node:path";
|
|
|
3
3
|
import {
|
|
4
4
|
BRIDGE_WORKSPACE_INSTRUCTIONS,
|
|
5
5
|
PRLL_BEHAVIOR,
|
|
6
|
-
PRLL_IDENTITY,
|
|
7
6
|
PRLL_REFERENCE_GUIDE,
|
|
7
|
+
buildIdentity,
|
|
8
8
|
} from "@parall/agent-core";
|
|
9
|
-
|
|
10
|
-
// Same slot order as OpenClaw / Hermes: identity → channel-context
|
|
11
|
-
// (BRIDGE_WORKSPACE_INSTRUCTIONS plays that role for bridge runtimes) →
|
|
12
|
-
// behavior → reference guide. Keeps the agent-facing prompt schema strictly
|
|
13
|
-
// unified across runtimes.
|
|
14
|
-
const CLAUDE_MD = [
|
|
15
|
-
PRLL_IDENTITY,
|
|
16
|
-
BRIDGE_WORKSPACE_INSTRUCTIONS,
|
|
17
|
-
PRLL_BEHAVIOR,
|
|
18
|
-
PRLL_REFERENCE_GUIDE,
|
|
19
|
-
].join("\n\n");
|
|
9
|
+
import type { AgentIdentity } from "@parall/agent-core";
|
|
20
10
|
|
|
21
11
|
export function ensureClaudeWorkspace(
|
|
22
12
|
workspaceDir: string,
|
|
23
13
|
log?: { warn: (msg: string) => void },
|
|
14
|
+
agentIdentity?: AgentIdentity,
|
|
24
15
|
) {
|
|
16
|
+
const CLAUDE_MD = [
|
|
17
|
+
buildIdentity(agentIdentity),
|
|
18
|
+
BRIDGE_WORKSPACE_INSTRUCTIONS,
|
|
19
|
+
PRLL_BEHAVIOR,
|
|
20
|
+
PRLL_REFERENCE_GUIDE,
|
|
21
|
+
].join("\n\n");
|
|
25
22
|
fs.mkdirSync(workspaceDir, { recursive: true });
|
|
26
23
|
fs.mkdirSync(path.join(workspaceDir, ".claude"), { recursive: true });
|
|
27
24
|
|