@parall/codex-agent 1.18.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/package.json ADDED
@@ -0,0 +1,41 @@
1
+ {
2
+ "name": "@parall/codex-agent",
3
+ "version": "1.18.0",
4
+ "description": "Codex CLI bridge runtime for self-hosted Parall agents",
5
+ "license": "MIT",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "https://github.com/parall-hq/parall-mono",
9
+ "directory": "ts/codex-agent"
10
+ },
11
+ "type": "module",
12
+ "main": "./dist/index.js",
13
+ "types": "./dist/index.d.ts",
14
+ "bin": {
15
+ "parall-codex-agent": "./dist/index.js"
16
+ },
17
+ "exports": {
18
+ ".": {
19
+ "types": "./dist/index.d.ts",
20
+ "import": "./dist/index.js"
21
+ }
22
+ },
23
+ "files": [
24
+ "dist",
25
+ "src"
26
+ ],
27
+ "dependencies": {
28
+ "@parall/agent-core": "1.18.0",
29
+ "@parall/cli": "1.18.0",
30
+ "@parall/sdk": "1.18.0"
31
+ },
32
+ "devDependencies": {
33
+ "@types/node": "^22.0.0",
34
+ "typescript": "^5.7.0"
35
+ },
36
+ "scripts": {
37
+ "build": "tsc -b",
38
+ "start": "node dist/index.js",
39
+ "test": "pnpm run build && node --test test/*.test.mjs"
40
+ }
41
+ }
package/src/config.ts ADDED
@@ -0,0 +1,118 @@
1
+ import * as os from "node:os";
2
+ import * as path from "node:path";
3
+
4
+ export type CodexAgentConfig = {
5
+ apiUrl: string;
6
+ apiKey: string;
7
+ orgId: string;
8
+ wsUrl?: string;
9
+ swimlaneName?: string;
10
+ codexBin: string;
11
+ codexHome: string;
12
+ stateDir: string;
13
+ workspaceDir: string;
14
+ model?: string;
15
+ reasoningEffort?: string;
16
+ sandbox: string;
17
+ approvalPolicy: string;
18
+ runtimeKey?: string;
19
+ };
20
+
21
+ function requireEnv(env: NodeJS.ProcessEnv, name: string): string {
22
+ const value = env[name]?.trim();
23
+ if (!value) {
24
+ throw new Error(`Missing required env var: ${name}`);
25
+ }
26
+ return value;
27
+ }
28
+
29
+ function resolvePath(value: string): string {
30
+ return path.isAbsolute(value) ? value : path.resolve(process.cwd(), value);
31
+ }
32
+
33
+ export function resolveCodexAgentConfig(env: NodeJS.ProcessEnv = process.env): CodexAgentConfig {
34
+ const apiUrl = requireEnv(env, "PRLL_API_URL");
35
+ const apiKey = requireEnv(env, "PRLL_API_KEY");
36
+ const orgId = requireEnv(env, "PRLL_ORG_ID");
37
+ const codexHome = resolvePath(
38
+ env.PRLL_CODEX_HOME?.trim()
39
+ || env.CODEX_HOME?.trim()
40
+ || env.HOME
41
+ || os.homedir(),
42
+ );
43
+ const stateDir = resolvePath(env.PRLL_CODEX_STATE_DIR?.trim() || path.join(codexHome, ".parall-agent"));
44
+ const workspaceDir = resolvePath(env.PRLL_CODEX_WORKSPACE_DIR?.trim() || path.join(stateDir, "workspace"));
45
+
46
+ return {
47
+ apiUrl,
48
+ apiKey,
49
+ orgId,
50
+ wsUrl: env.PRLL_WS_URL?.trim() || undefined,
51
+ swimlaneName: env.PRLL_SWIMLANE_NAME?.trim() || undefined,
52
+ codexBin: env.PRLL_CODEX_BIN?.trim() || "codex",
53
+ codexHome,
54
+ stateDir,
55
+ workspaceDir,
56
+ model: env.PRLL_CODEX_MODEL?.trim() || undefined,
57
+ reasoningEffort: env.PRLL_CODEX_REASONING_EFFORT?.trim() || undefined,
58
+ sandbox: env.PRLL_CODEX_SANDBOX?.trim() || "workspace-write",
59
+ approvalPolicy: env.PRLL_CODEX_APPROVAL?.trim() || "never",
60
+ runtimeKey: env.PRLL_CODEX_RUNTIME_KEY?.trim() || undefined,
61
+ };
62
+ }
63
+
64
+ /**
65
+ * Normalise a sandbox value (CLI docs use kebab-case like `workspace-write`,
66
+ * but the app-server JSON-RPC protocol uses camelCase like `workspaceWrite`).
67
+ * Accept both forms and emit the canonical protocol form.
68
+ */
69
+ export function normalizeSandbox(value: string): string {
70
+ const map: Record<string, string> = {
71
+ "workspace-write": "workspaceWrite",
72
+ "workspacewrite": "workspaceWrite",
73
+ "danger-full-access": "dangerFullAccess",
74
+ "dangerfullaccess": "dangerFullAccess",
75
+ "read-only": "readOnly",
76
+ "readonly": "readOnly",
77
+ };
78
+ return map[value.toLowerCase()] ?? value;
79
+ }
80
+
81
+ /**
82
+ * Normalise an approval policy string to the camelCase form the app-server
83
+ * JSON-RPC protocol uses (`never` / `onRequest` / `unlessTrusted`).
84
+ */
85
+ export function normalizeApprovalPolicy(value: string): string {
86
+ const map: Record<string, string> = {
87
+ "never": "never",
88
+ "on-request": "onRequest",
89
+ "onrequest": "onRequest",
90
+ "unless-trusted": "unlessTrusted",
91
+ "unlesstrusted": "unlessTrusted",
92
+ "on-failure": "onFailure",
93
+ "onfailure": "onFailure",
94
+ };
95
+ return map[value.toLowerCase()] ?? value;
96
+ }
97
+
98
+ export function resolveWsUrl(apiUrl: string, explicitWsUrl?: string, swimlaneName?: string): string {
99
+ const base = explicitWsUrl || `${apiUrl.replace(/\/$/, "").replace(/^http/, "ws")}/ws`;
100
+ if (!swimlaneName) return base;
101
+ const url = new URL(base);
102
+ url.searchParams.set("swimlane", swimlaneName);
103
+ return url.toString();
104
+ }
105
+
106
+ export function buildCodexRuntimeKey(agentUserId: string): string {
107
+ return `agent:main:codex:${agentUserId}:orchestrator`;
108
+ }
109
+
110
+ export function sessionStateFilePathForRuntime(stateDir: string, runtimeKey: string): string {
111
+ const fileName = Buffer.from(runtimeKey).toString("base64url");
112
+ return path.join(stateDir, "threads", `${fileName}.json`);
113
+ }
114
+
115
+ export function stepIdFilePathForSession(stateDir: string, sessionKey: string): string {
116
+ const fileName = Buffer.from(sessionKey).toString("base64url");
117
+ return path.join(stateDir, "step-ids", `${fileName}.txt`);
118
+ }