@parall/codex-agent 1.58.1 → 1.58.2

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.
@@ -104,6 +104,7 @@ export declare class CodexAppServerAdapter implements DispatchAdapter {
104
104
  reasoningEffort?: string | null;
105
105
  developerInstructions?: string | null;
106
106
  }): void;
107
+ private threadConfigOverrides;
107
108
  enqueueDuringDispatch(sessionKey: string, body: string): Promise<boolean>;
108
109
  abortDispatch(sessionKey: string): void;
109
110
  hasPendingInjections(sessionKey: string): boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"dispatch.d.ts","sourceRoot":"","sources":["../src/dispatch.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"dispatch.d.ts","sourceRoot":"","sources":["../src/dispatch.ts"],"names":[],"mappings":"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"}
package/dist/dispatch.js CHANGED
@@ -8,6 +8,7 @@ import { normalizeApprovalPolicy, normalizeSandbox } from './config.js';
8
8
  import { MainThreadInstructionsRefresher, } from './instructions-refresh.js';
9
9
  import { JsonRpcStdioClient } from './jsonrpc-client.js';
10
10
  import { answerServerRequest } from './server-requests.js';
11
+ import { buildThreadConfigOverrides } from './thread-config.js';
11
12
  import { TurnSink } from './turn-sink.js';
12
13
  /**
13
14
  * Bridge driver backed by `codex app-server --listen stdio://`.
@@ -104,6 +105,13 @@ export class CodexAppServerAdapter {
104
105
  if (config.developerInstructions !== undefined)
105
106
  this.opts.developerInstructions = config.developerInstructions ?? undefined;
106
107
  }
108
+ threadConfigOverrides() {
109
+ return buildThreadConfigOverrides({
110
+ reasoningEffort: this.opts.reasoningEffort,
111
+ capabilityBinDir: this.opts.capabilityBinDir,
112
+ inheritedPath: process.env.PATH,
113
+ });
114
+ }
107
115
  async enqueueDuringDispatch(sessionKey, body) {
108
116
  const client = this.client;
109
117
  if (!client || client.isDisposed())
@@ -596,10 +604,9 @@ export class CodexAppServerAdapter {
596
604
  }
597
605
  if (this.opts.model)
598
606
  forkParams.model = this.opts.model;
599
- if (this.opts.reasoningEffort) {
600
- // Raw config.toml key — see openThread for the snake_case rationale.
601
- forkParams.config = { model_reasoning_effort: this.opts.reasoningEffort };
602
- }
607
+ const threadConfig = this.threadConfigOverrides();
608
+ if (threadConfig)
609
+ forkParams.config = threadConfig;
603
610
  const result = await client.sendRequest('thread/fork', forkParams);
604
611
  const forkedThreadId = extractThreadId(result);
605
612
  if (!forkedThreadId) {
@@ -885,16 +892,14 @@ export class CodexAppServerAdapter {
885
892
  }
886
893
  if (this.opts.model)
887
894
  commonParams.model = this.opts.model;
888
- if (this.opts.reasoningEffort) {
889
- // The nested `config` object is raw config.toml overrides and keeps the
890
- // TOML key names `model_reasoning_effort` (snake_case) — unlike the
891
- // typed top-level params (`approvalPolicy` / `sandbox`), which are
892
- // camelCase. Empirically verified against both pinned CLI generations
893
- // (0.133.0 and 0.144.1): the camelCase key is silently ignored
894
- // (thread/start echoes reasoningEffort: null), the snake_case key is
895
- // applied and echoed back.
896
- commonParams.config = { model_reasoning_effort: this.opts.reasoningEffort };
897
- }
895
+ // The nested `config` object is raw config.toml overrides and keeps TOML
896
+ // key names (for example model_reasoning_effort, allow_login_shell, and
897
+ // shell_environment_policy), unlike the typed camelCase top-level params.
898
+ // The reasoning key's casing is verified against pinned CLI generations;
899
+ // the shell policy is the official Codex config surface.
900
+ const threadConfig = this.threadConfigOverrides();
901
+ if (threadConfig)
902
+ commonParams.config = threadConfig;
898
903
  const method = opts.resumeId ? 'thread/resume' : 'thread/start';
899
904
  const params = opts.resumeId
900
905
  ? {
@@ -0,0 +1,20 @@
1
+ export type ThreadConfigOverrideOptions = {
2
+ reasoningEffort?: string;
3
+ capabilityBinDir?: string;
4
+ inheritedPath?: string;
5
+ platform?: NodeJS.Platform;
6
+ };
7
+ /**
8
+ * Build the raw config.toml overrides shared by thread start/resume/fork.
9
+ *
10
+ * Codex normally allows POSIX tools to use a login shell. On macOS,
11
+ * /etc/zprofile's path_helper (and an operator's own profile) can reorder PATH
12
+ * after the app-server inherited it, moving a globally-installed vendor CLI
13
+ * ahead of Parall's credential-broker pointer. Force non-login execution,
14
+ * disable profile-based command translation, and pin the already-resolved
15
+ * daemon PATH with the capability directory first. The daemon resolves the
16
+ * operator's runtime/tool PATH before spawning this bridge, so commands keep
17
+ * the same executable search path without a per-command profile reload.
18
+ */
19
+ export declare function buildThreadConfigOverrides({ reasoningEffort, capabilityBinDir, inheritedPath, platform, }: ThreadConfigOverrideOptions): Record<string, unknown> | undefined;
20
+ //# sourceMappingURL=thread-config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"thread-config.d.ts","sourceRoot":"","sources":["../src/thread-config.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,2BAA2B,GAAG;IACxC,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAC;CAC5B,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,wBAAgB,0BAA0B,CAAC,EACzC,eAAe,EACf,gBAAgB,EAChB,aAAa,EACb,QAA2B,GAC5B,EAAE,2BAA2B,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAoBnE"}
@@ -0,0 +1,33 @@
1
+ import * as path from 'node:path';
2
+ /**
3
+ * Build the raw config.toml overrides shared by thread start/resume/fork.
4
+ *
5
+ * Codex normally allows POSIX tools to use a login shell. On macOS,
6
+ * /etc/zprofile's path_helper (and an operator's own profile) can reorder PATH
7
+ * after the app-server inherited it, moving a globally-installed vendor CLI
8
+ * ahead of Parall's credential-broker pointer. Force non-login execution,
9
+ * disable profile-based command translation, and pin the already-resolved
10
+ * daemon PATH with the capability directory first. The daemon resolves the
11
+ * operator's runtime/tool PATH before spawning this bridge, so commands keep
12
+ * the same executable search path without a per-command profile reload.
13
+ */
14
+ export function buildThreadConfigOverrides({ reasoningEffort, capabilityBinDir, inheritedPath, platform = process.platform, }) {
15
+ const config = {};
16
+ if (reasoningEffort)
17
+ config.model_reasoning_effort = reasoningEffort;
18
+ // Windows shells do not have the POSIX login-profile reorder that this
19
+ // override addresses; the app-server process PATH already carries the .cmd
20
+ // pointer directory there.
21
+ if (capabilityBinDir && platform !== 'win32') {
22
+ const pathEntries = (inheritedPath ?? '')
23
+ .split(path.delimiter)
24
+ .filter((entry) => entry && entry !== capabilityBinDir);
25
+ const effectivePath = [capabilityBinDir, ...pathEntries].join(path.delimiter);
26
+ config.allow_login_shell = false;
27
+ config.shell_environment_policy = {
28
+ experimental_use_profile: false,
29
+ set: { PATH: effectivePath },
30
+ };
31
+ }
32
+ return Object.keys(config).length > 0 ? config : undefined;
33
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@parall/codex-agent",
3
- "version": "1.58.1",
3
+ "version": "1.58.2",
4
4
  "description": "Codex CLI 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/agent-core": "1.58.1",
29
- "@parall/sdk": "1.58.1",
30
- "@parall/cli": "1.58.1"
28
+ "@parall/agent-core": "1.58.2",
29
+ "@parall/cli": "1.58.2",
30
+ "@parall/sdk": "1.58.2"
31
31
  },
32
32
  "devDependencies": {
33
33
  "@types/node": "^22.0.0",
package/src/dispatch.ts CHANGED
@@ -32,6 +32,7 @@ import {
32
32
  import { JsonRpcStdioClient } from './jsonrpc-client.js';
33
33
  import { answerServerRequest } from './server-requests.js';
34
34
  import type { CodexSessionManager } from './session-manager.js';
35
+ import { buildThreadConfigOverrides } from './thread-config.js';
35
36
  import { TurnSink } from './turn-sink.js';
36
37
 
37
38
  type CodexAppServerAdapterOptions = Pick<
@@ -185,6 +186,14 @@ export class CodexAppServerAdapter implements DispatchAdapter {
185
186
  this.opts.developerInstructions = config.developerInstructions ?? undefined;
186
187
  }
187
188
 
189
+ private threadConfigOverrides(): Record<string, unknown> | undefined {
190
+ return buildThreadConfigOverrides({
191
+ reasoningEffort: this.opts.reasoningEffort,
192
+ capabilityBinDir: this.opts.capabilityBinDir,
193
+ inheritedPath: process.env.PATH,
194
+ });
195
+ }
196
+
188
197
  async enqueueDuringDispatch(sessionKey: string, body: string): Promise<boolean> {
189
198
  const client = this.client;
190
199
  if (!client || client.isDisposed()) return false;
@@ -694,10 +703,8 @@ export class CodexAppServerAdapter implements DispatchAdapter {
694
703
  forkParams.developerInstructions = this.opts.developerInstructions;
695
704
  }
696
705
  if (this.opts.model) forkParams.model = this.opts.model;
697
- if (this.opts.reasoningEffort) {
698
- // Raw config.toml key — see openThread for the snake_case rationale.
699
- forkParams.config = { model_reasoning_effort: this.opts.reasoningEffort };
700
- }
706
+ const threadConfig = this.threadConfigOverrides();
707
+ if (threadConfig) forkParams.config = threadConfig;
701
708
  const result = await client.sendRequest('thread/fork', forkParams);
702
709
  const forkedThreadId = extractThreadId(result);
703
710
  if (!forkedThreadId) {
@@ -1009,16 +1016,13 @@ export class CodexAppServerAdapter implements DispatchAdapter {
1009
1016
  commonParams.developerInstructions = this.opts.developerInstructions;
1010
1017
  }
1011
1018
  if (this.opts.model) commonParams.model = this.opts.model;
1012
- if (this.opts.reasoningEffort) {
1013
- // The nested `config` object is raw config.toml overrides and keeps the
1014
- // TOML key names `model_reasoning_effort` (snake_case) — unlike the
1015
- // typed top-level params (`approvalPolicy` / `sandbox`), which are
1016
- // camelCase. Empirically verified against both pinned CLI generations
1017
- // (0.133.0 and 0.144.1): the camelCase key is silently ignored
1018
- // (thread/start echoes reasoningEffort: null), the snake_case key is
1019
- // applied and echoed back.
1020
- commonParams.config = { model_reasoning_effort: this.opts.reasoningEffort };
1021
- }
1019
+ // The nested `config` object is raw config.toml overrides and keeps TOML
1020
+ // key names (for example model_reasoning_effort, allow_login_shell, and
1021
+ // shell_environment_policy), unlike the typed camelCase top-level params.
1022
+ // The reasoning key's casing is verified against pinned CLI generations;
1023
+ // the shell policy is the official Codex config surface.
1024
+ const threadConfig = this.threadConfigOverrides();
1025
+ if (threadConfig) commonParams.config = threadConfig;
1022
1026
 
1023
1027
  const method = opts.resumeId ? 'thread/resume' : 'thread/start';
1024
1028
  const params: Record<string, unknown> = opts.resumeId
@@ -0,0 +1,47 @@
1
+ import * as path from 'node:path';
2
+
3
+ export type ThreadConfigOverrideOptions = {
4
+ reasoningEffort?: string;
5
+ capabilityBinDir?: string;
6
+ inheritedPath?: string;
7
+ platform?: NodeJS.Platform;
8
+ };
9
+
10
+ /**
11
+ * Build the raw config.toml overrides shared by thread start/resume/fork.
12
+ *
13
+ * Codex normally allows POSIX tools to use a login shell. On macOS,
14
+ * /etc/zprofile's path_helper (and an operator's own profile) can reorder PATH
15
+ * after the app-server inherited it, moving a globally-installed vendor CLI
16
+ * ahead of Parall's credential-broker pointer. Force non-login execution,
17
+ * disable profile-based command translation, and pin the already-resolved
18
+ * daemon PATH with the capability directory first. The daemon resolves the
19
+ * operator's runtime/tool PATH before spawning this bridge, so commands keep
20
+ * the same executable search path without a per-command profile reload.
21
+ */
22
+ export function buildThreadConfigOverrides({
23
+ reasoningEffort,
24
+ capabilityBinDir,
25
+ inheritedPath,
26
+ platform = process.platform,
27
+ }: ThreadConfigOverrideOptions): Record<string, unknown> | undefined {
28
+ const config: Record<string, unknown> = {};
29
+ if (reasoningEffort) config.model_reasoning_effort = reasoningEffort;
30
+
31
+ // Windows shells do not have the POSIX login-profile reorder that this
32
+ // override addresses; the app-server process PATH already carries the .cmd
33
+ // pointer directory there.
34
+ if (capabilityBinDir && platform !== 'win32') {
35
+ const pathEntries = (inheritedPath ?? '')
36
+ .split(path.delimiter)
37
+ .filter((entry) => entry && entry !== capabilityBinDir);
38
+ const effectivePath = [capabilityBinDir, ...pathEntries].join(path.delimiter);
39
+ config.allow_login_shell = false;
40
+ config.shell_environment_policy = {
41
+ experimental_use_profile: false,
42
+ set: { PATH: effectivePath },
43
+ };
44
+ }
45
+
46
+ return Object.keys(config).length > 0 ? config : undefined;
47
+ }