@ccpocket/bridge 1.69.0 → 1.69.1

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/websocket.js CHANGED
@@ -7,7 +7,7 @@ import { promisify } from "node:util";
7
7
  import { WebSocketServer, WebSocket } from "ws";
8
8
  import { SessionManager, MAX_HISTORY_PER_SESSION, } from "./session.js";
9
9
  import { SdkProcess, listAvailableClaudeModels, } from "./sdk-process.js";
10
- import { CodexProcess, } from "./codex-process.js";
10
+ import { codexErrorMessage, CodexRpcError, CodexProcess, } from "./codex-process.js";
11
11
  import { stopManagedCodexAppServers } from "./codex-transport.js";
12
12
  import { parseClientMessage, } from "./parser.js";
13
13
  import { getAllRecentSessions, getCodexSessionHistory, getSessionHistory, codexUserTurnUuid, codexThreadToSessionHistory, findSessionsByClaudeIds, extractMessageImages, getClaudeSessionName, getCodexSessionIndexMetadata, loadCodexSessionNames, renameClaudeSession, renameCodexSession, saveCodexSessionProfile, } from "./sessions-index.js";
@@ -243,6 +243,9 @@ function normalizeCodexApprovalPolicy(value) {
243
243
  return "on-request";
244
244
  }
245
245
  }
246
+ function isCodexAutoReviewApprovalsReviewer(value) {
247
+ return value === "auto_review" || value === "guardian_subagent";
248
+ }
246
249
  function sanitizeCodexModel(model) {
247
250
  if (typeof model !== "string")
248
251
  return undefined;
@@ -457,6 +460,8 @@ export class BridgeWebSocketServer {
457
460
  archiveStore;
458
461
  codexProfiles = [];
459
462
  defaultCodexProfile;
463
+ codexAutoReviewDisabled = false;
464
+ codexAutoReviewPolicyLoaded = false;
460
465
  codexMetadataRequest = null;
461
466
  lastConnectMetadataRefreshAt = null;
462
467
  claudeModels = FALLBACK_CLAUDE_MODELS;
@@ -809,10 +814,10 @@ export class BridgeWebSocketServer {
809
814
  fallback: buildCodexHistoryPrefix(session, targetOrdinal - 1),
810
815
  });
811
816
  this.destroySession(sessionId);
812
- const newSessionId = this.sessionManager.create(projectPath, undefined, pastMessages, worktreeOpts, "codex", {
817
+ const newSessionId = this.sessionManager.create(projectPath, undefined, pastMessages, worktreeOpts, "codex", this.withCodexAutoReviewPolicy({
813
818
  ...(codexSettings ?? {}),
814
819
  threadId,
815
- });
820
+ }));
816
821
  const newSession = this.sessionManager.get(newSessionId);
817
822
  this.send(ws, {
818
823
  type: "rewind_result",
@@ -824,8 +829,8 @@ export class BridgeWebSocketServer {
824
829
  provider: "codex",
825
830
  projectPath,
826
831
  session: newSession,
827
- approvalsReviewer: codexSettings?.approvalsReviewer,
828
- sandboxMode: codexSettings?.sandboxMode,
832
+ approvalsReviewer: newSession?.codexSettings?.approvalsReviewer,
833
+ sandboxMode: newSession?.codexSettings?.sandboxMode,
829
834
  sourceSessionId: sessionId,
830
835
  }));
831
836
  this.sendSessionList(ws);
@@ -896,18 +901,18 @@ export class BridgeWebSocketServer {
896
901
  expectedUserTurns: targetOrdinal,
897
902
  fallback: buildCodexHistoryPrefix(session, targetOrdinal),
898
903
  });
899
- const newSessionId = this.sessionManager.create(projectPath, undefined, pastMessages, worktreeOpts, "codex", {
904
+ const newSessionId = this.sessionManager.create(projectPath, undefined, pastMessages, worktreeOpts, "codex", this.withCodexAutoReviewPolicy({
900
905
  ...(codexSettings ?? {}),
901
906
  threadId: forkedThreadId,
902
- });
907
+ }));
903
908
  const newSession = this.sessionManager.get(newSessionId);
904
909
  this.send(ws, this.buildSessionCreatedMessage({
905
910
  sessionId: newSessionId,
906
911
  provider: "codex",
907
912
  projectPath,
908
913
  session: newSession,
909
- approvalsReviewer: codexSettings?.approvalsReviewer,
910
- sandboxMode: codexSettings?.sandboxMode,
914
+ approvalsReviewer: newSession?.codexSettings?.approvalsReviewer,
915
+ sandboxMode: newSession?.codexSettings?.sandboxMode,
911
916
  sourceSessionId: sessionId,
912
917
  }));
913
918
  this.sendSessionList(ws);
@@ -1645,9 +1650,13 @@ export class BridgeWebSocketServer {
1645
1650
  }
1646
1651
  try {
1647
1652
  const provider = msg.provider ?? "claude";
1648
- const requestedCodexPermissionsMode = provider === "codex"
1653
+ const normalizedCodexPermissionsMode = provider === "codex"
1649
1654
  ? normalizeCodexPermissionsMode(msg.codexPermissionsMode)
1650
1655
  : undefined;
1656
+ const requestedCodexPermissionsMode = this.codexAutoReviewDisabled &&
1657
+ normalizedCodexPermissionsMode === "autoReview"
1658
+ ? "default"
1659
+ : normalizedCodexPermissionsMode;
1651
1660
  const codexPermissionSettings = requestedCodexPermissionsMode
1652
1661
  ? codexSettingsFromPermissionsMode(requestedCodexPermissionsMode)
1653
1662
  : undefined;
@@ -1723,7 +1732,7 @@ export class BridgeWebSocketServer {
1723
1732
  useWorktree: msg.useWorktree,
1724
1733
  worktreeBranch: msg.worktreeBranch,
1725
1734
  existingWorktreePath: msg.existingWorktreePath,
1726
- }, provider, {
1735
+ }, provider, this.withCodexAutoReviewPolicy({
1727
1736
  profile: msg.profile,
1728
1737
  approvalPolicy: codexPermissionSettings
1729
1738
  ? codexPermissionSettings.approvalPolicy
@@ -1731,9 +1740,8 @@ export class BridgeWebSocketServer {
1731
1740
  normalizeCodexApprovalPolicy(executionMode === "fullAccess"
1732
1741
  ? "never"
1733
1742
  : "on-request")),
1734
- approvalsReviewer: codexPermissionSettings
1735
- ? codexPermissionSettings.approvalsReviewer
1736
- : msg.approvalsReviewer,
1743
+ approvalsReviewer: codexPermissionSettings?.approvalsReviewer ??
1744
+ msg.approvalsReviewer,
1737
1745
  codexPermissionsMode: codexPermissionSettings?.codexPermissionsMode,
1738
1746
  sandboxMode: codexPermissionSettings
1739
1747
  ? codexPermissionSettings.sandboxMode
@@ -1750,7 +1758,7 @@ export class BridgeWebSocketServer {
1750
1758
  collaborationMode: planMode
1751
1759
  ? "plan"
1752
1760
  : "default",
1753
- }),
1761
+ })),
1754
1762
  permissionMode: claudePermissionMode,
1755
1763
  executionMode,
1756
1764
  planMode,
@@ -2290,7 +2298,15 @@ export class BridgeWebSocketServer {
2290
2298
  // Permission mode for Codex requires a session restart (like sandbox mode).
2291
2299
  // approvalPolicy and collaborationMode are thread-level settings that
2292
2300
  // only take effect reliably at thread/start or thread/resume time.
2293
- const requestedCodexPermissionsMode = normalizeCodexPermissionsMode(msg.codexPermissionsMode);
2301
+ const normalizedCodexPermissionsMode = normalizeCodexPermissionsMode(msg.codexPermissionsMode);
2302
+ const requestedCodexPermissionsMode = this.codexAutoReviewDisabled &&
2303
+ normalizedCodexPermissionsMode === "autoReview"
2304
+ ? "default"
2305
+ : normalizedCodexPermissionsMode;
2306
+ const requestedApprovalsReviewer = this.codexAutoReviewDisabled &&
2307
+ isCodexAutoReviewApprovalsReviewer(msg.approvalsReviewer)
2308
+ ? "user"
2309
+ : msg.approvalsReviewer;
2294
2310
  const codexPermissionSettings = requestedCodexPermissionsMode
2295
2311
  ? codexSettingsFromPermissionsMode(requestedCodexPermissionsMode)
2296
2312
  : undefined;
@@ -2328,23 +2344,28 @@ export class BridgeWebSocketServer {
2328
2344
  const newSandboxMode = codexPermissionSettings
2329
2345
  ? codexPermissionSettings.sandboxMode
2330
2346
  : currentSandboxMode;
2331
- const newPermissionsMode = codexPermissionSettings?.codexPermissionsMode ??
2347
+ const configuredReviewer = requestedCodexPermissionsMode === "custom"
2348
+ ? undefined
2349
+ : (codexPermissionSettings?.approvalsReviewer ??
2350
+ requestedApprovalsReviewer ??
2351
+ currentReviewer);
2352
+ const newReviewer = this.codexAutoReviewDisabled
2353
+ ? "user"
2354
+ : configuredReviewer;
2355
+ const derivedPermissionsMode = codexPermissionSettings?.codexPermissionsMode ??
2332
2356
  (collaborationOnlyChange ? currentPermissionsMode : undefined) ??
2333
2357
  deriveCodexPermissionsMode({
2334
2358
  approvalPolicy: newApproval,
2335
- approvalsReviewer: codexPermissionSettings?.approvalsReviewer ??
2336
- msg.approvalsReviewer ??
2337
- currentReviewer,
2359
+ approvalsReviewer: newReviewer,
2338
2360
  sandboxMode: newSandboxMode,
2339
2361
  });
2362
+ const newPermissionsMode = this.codexAutoReviewDisabled &&
2363
+ derivedPermissionsMode === "autoReview"
2364
+ ? "default"
2365
+ : derivedPermissionsMode;
2340
2366
  const newCollaboration = planMode
2341
2367
  ? "plan"
2342
2368
  : "default";
2343
- const newReviewer = requestedCodexPermissionsMode === "custom"
2344
- ? undefined
2345
- : (codexPermissionSettings?.approvalsReviewer ??
2346
- msg.approvalsReviewer ??
2347
- currentReviewer);
2348
2369
  const currentCollaboration = process.collaborationMode;
2349
2370
  if (newApproval === currentApproval &&
2350
2371
  newReviewer === currentReviewer &&
@@ -2355,7 +2376,9 @@ export class BridgeWebSocketServer {
2355
2376
  }
2356
2377
  const canApplyModeInPlace = session.status === "idle" &&
2357
2378
  requestedCodexPermissionsMode !== "custom" &&
2358
- newSandboxMode === currentSandboxMode;
2379
+ newSandboxMode === currentSandboxMode &&
2380
+ (this.codexAutoReviewPolicyLoaded ||
2381
+ !isCodexAutoReviewApprovalsReviewer(newReviewer));
2359
2382
  if (canApplyModeInPlace) {
2360
2383
  const process = session.process;
2361
2384
  if (newApproval && newApproval !== currentApproval) {
@@ -2411,7 +2434,7 @@ export class BridgeWebSocketServer {
2411
2434
  if (!threadId || !hasUserMessages) {
2412
2435
  const newId = this.sessionManager.create(projectPath, undefined, undefined, worktreePath
2413
2436
  ? { existingWorktreePath: worktreePath, worktreeBranch }
2414
- : undefined, "codex", {
2437
+ : undefined, "codex", this.withCodexAutoReviewPolicy({
2415
2438
  approvalPolicy: newApproval,
2416
2439
  approvalsReviewer: newReviewer,
2417
2440
  codexPermissionsMode: newPermissionsMode,
@@ -2422,7 +2445,7 @@ export class BridgeWebSocketServer {
2422
2445
  networkAccessEnabled: oldSettings.networkAccessEnabled,
2423
2446
  webSearchMode: oldSettings.webSearchMode,
2424
2447
  collaborationMode: newCollaboration,
2425
- });
2448
+ }));
2426
2449
  const newSession = this.sessionManager.get(newId);
2427
2450
  if (newSession && sessionName)
2428
2451
  newSession.name = sessionName;
@@ -2471,7 +2494,7 @@ export class BridgeWebSocketServer {
2471
2494
  }
2472
2495
  this.getCodexThreadHistory(threadId, effectiveProjectPath)
2473
2496
  .then((pastMessages) => {
2474
- const newId = this.sessionManager.create(effectiveProjectPath, undefined, pastMessages, worktreeOpts, "codex", {
2497
+ const newId = this.sessionManager.create(effectiveProjectPath, undefined, pastMessages, worktreeOpts, "codex", this.withCodexAutoReviewPolicy({
2475
2498
  threadId,
2476
2499
  approvalPolicy: newApproval,
2477
2500
  approvalsReviewer: newReviewer,
@@ -2483,7 +2506,7 @@ export class BridgeWebSocketServer {
2483
2506
  networkAccessEnabled: oldSettings.networkAccessEnabled,
2484
2507
  webSearchMode: oldSettings.webSearchMode,
2485
2508
  collaborationMode: newCollaboration,
2486
- });
2509
+ }));
2487
2510
  const newSession = this.sessionManager.get(newId);
2488
2511
  if (newSession && sessionName) {
2489
2512
  newSession.name = sessionName;
@@ -2822,8 +2845,10 @@ export class BridgeWebSocketServer {
2822
2845
  // "no rollout found for thread id".)
2823
2846
  const newId = this.sessionManager.create(projectPath, undefined, undefined, worktreePath
2824
2847
  ? { existingWorktreePath: worktreePath, worktreeBranch }
2825
- : undefined, "codex", {
2848
+ : undefined, "codex", this.withCodexAutoReviewPolicy({
2826
2849
  approvalPolicy: oldSettings.approvalPolicy,
2850
+ approvalsReviewer: oldSettings.approvalsReviewer,
2851
+ codexPermissionsMode: oldSettings.codexPermissionsMode,
2827
2852
  sandboxMode: newSandboxMode,
2828
2853
  model: oldSettings.model,
2829
2854
  modelReasoningEffort: oldSettings.modelReasoningEffort,
@@ -2831,7 +2856,7 @@ export class BridgeWebSocketServer {
2831
2856
  networkAccessEnabled: oldSettings.networkAccessEnabled,
2832
2857
  webSearchMode: oldSettings.webSearchMode,
2833
2858
  collaborationMode,
2834
- });
2859
+ }));
2835
2860
  const newSession = this.sessionManager.get(newId);
2836
2861
  if (newSession && sessionName)
2837
2862
  newSession.name = sessionName;
@@ -2873,9 +2898,11 @@ export class BridgeWebSocketServer {
2873
2898
  }
2874
2899
  this.getCodexThreadHistory(threadId, effectiveProjectPath)
2875
2900
  .then((pastMessages) => {
2876
- const newId = this.sessionManager.create(effectiveProjectPath, undefined, pastMessages, worktreeOpts, "codex", {
2901
+ const newId = this.sessionManager.create(effectiveProjectPath, undefined, pastMessages, worktreeOpts, "codex", this.withCodexAutoReviewPolicy({
2877
2902
  threadId,
2878
2903
  approvalPolicy: oldSettings.approvalPolicy,
2904
+ approvalsReviewer: oldSettings.approvalsReviewer,
2905
+ codexPermissionsMode: oldSettings.codexPermissionsMode,
2879
2906
  sandboxMode: newSandboxMode,
2880
2907
  model: oldSettings.model,
2881
2908
  modelReasoningEffort: oldSettings.modelReasoningEffort,
@@ -2883,7 +2910,7 @@ export class BridgeWebSocketServer {
2883
2910
  networkAccessEnabled: oldSettings.networkAccessEnabled,
2884
2911
  webSearchMode: oldSettings.webSearchMode,
2885
2912
  collaborationMode,
2886
- });
2913
+ }));
2887
2914
  // Restore session name
2888
2915
  const newSession = this.sessionManager.get(newId);
2889
2916
  if (newSession && sessionName) {
@@ -3320,25 +3347,39 @@ export class BridgeWebSocketServer {
3320
3347
  }
3321
3348
  case "archive_session": {
3322
3349
  const { sessionId, provider, projectPath } = msg;
3323
- this.archiveStore
3324
- .archive(sessionId, provider, projectPath)
3325
- .then(() => {
3326
- // For Codex sessions, also call thread/archive RPC (best-effort).
3327
- // Requires a running Codex app-server process; skip if none active.
3350
+ const archiveProjectPath = resolvePlatformPath(projectPath, this.platform);
3351
+ if (!this.isPathAllowed(archiveProjectPath)) {
3352
+ const pathError = this.buildPathNotAllowedError(projectPath);
3353
+ this.send(ws, {
3354
+ type: "archive_result",
3355
+ sessionId,
3356
+ success: false,
3357
+ error: pathError.message,
3358
+ });
3359
+ break;
3360
+ }
3361
+ void (async () => {
3328
3362
  if (provider === "codex") {
3329
- const activeSessions = this.sessionManager.list();
3330
- const codexSession = activeSessions.find((s) => s.provider === "codex");
3331
- if (codexSession) {
3332
- const session = this.sessionManager.get(codexSession.id);
3333
- if (session) {
3334
- session.process
3335
- .archiveThread(sessionId)
3336
- .catch((err) => {
3337
- console.warn(`[ws] Codex thread/archive failed (non-fatal): ${err}`);
3338
- });
3363
+ const activeProcess = this.getActiveCodexProcess();
3364
+ const codexProcess = activeProcess ??
3365
+ (await this.createStandaloneCodexProcess(archiveProjectPath));
3366
+ try {
3367
+ await codexProcess.archiveThread(sessionId);
3368
+ }
3369
+ catch (err) {
3370
+ if (!(err instanceof CodexRpcError && err.code === -32601)) {
3371
+ throw err;
3339
3372
  }
3373
+ console.warn("[ws] thread/archive unsupported; using local archive marker");
3374
+ }
3375
+ finally {
3376
+ if (!activeProcess)
3377
+ codexProcess.stop();
3340
3378
  }
3341
3379
  }
3380
+ await this.archiveStore.archive(sessionId, provider, archiveProjectPath);
3381
+ })()
3382
+ .then(() => {
3342
3383
  this.send(ws, {
3343
3384
  type: "archive_result",
3344
3385
  sessionId,
@@ -3350,7 +3391,7 @@ export class BridgeWebSocketServer {
3350
3391
  type: "archive_result",
3351
3392
  sessionId,
3352
3393
  success: false,
3353
- error: String(err),
3394
+ error: codexErrorMessage(err),
3354
3395
  });
3355
3396
  });
3356
3397
  break;
@@ -3363,9 +3404,13 @@ export class BridgeWebSocketServer {
3363
3404
  break;
3364
3405
  }
3365
3406
  const provider = msg.provider ?? "claude";
3366
- const requestedCodexPermissionsMode = provider === "codex"
3407
+ const normalizedCodexPermissionsMode = provider === "codex"
3367
3408
  ? normalizeCodexPermissionsMode(msg.codexPermissionsMode)
3368
3409
  : undefined;
3410
+ const requestedCodexPermissionsMode = this.codexAutoReviewDisabled &&
3411
+ normalizedCodexPermissionsMode === "autoReview"
3412
+ ? "default"
3413
+ : normalizedCodexPermissionsMode;
3369
3414
  const codexPermissionSettings = requestedCodexPermissionsMode
3370
3415
  ? codexSettingsFromPermissionsMode(requestedCodexPermissionsMode)
3371
3416
  : undefined;
@@ -3424,16 +3469,15 @@ export class BridgeWebSocketServer {
3424
3469
  }
3425
3470
  try {
3426
3471
  const pastMessages = await this.getCodexThreadHistory(sessionRefId, effectiveProjectPath);
3427
- const sessionId = this.sessionManager.create(effectiveProjectPath, undefined, pastMessages, worktreeOpts, "codex", {
3472
+ const sessionId = this.sessionManager.create(effectiveProjectPath, undefined, pastMessages, worktreeOpts, "codex", this.withCodexAutoReviewPolicy({
3428
3473
  threadId: sessionRefId,
3429
3474
  profile: effectiveProfile,
3430
3475
  approvalPolicy: codexPermissionSettings
3431
3476
  ? codexPermissionSettings.approvalPolicy
3432
3477
  : (codexApprovalPolicy ??
3433
3478
  normalizeCodexApprovalPolicy(executionMode === "fullAccess" ? "never" : "on-request")),
3434
- approvalsReviewer: codexPermissionSettings
3435
- ? codexPermissionSettings.approvalsReviewer
3436
- : msg.approvalsReviewer,
3479
+ approvalsReviewer: codexPermissionSettings?.approvalsReviewer ??
3480
+ msg.approvalsReviewer,
3437
3481
  codexPermissionsMode: codexPermissionSettings?.codexPermissionsMode,
3438
3482
  sandboxMode: codexPermissionSettings
3439
3483
  ? codexPermissionSettings.sandboxMode
@@ -3449,7 +3493,7 @@ export class BridgeWebSocketServer {
3449
3493
  collaborationMode: planMode
3450
3494
  ? "plan"
3451
3495
  : "default",
3452
- });
3496
+ }));
3453
3497
  const createdSession = this.sessionManager.get(sessionId);
3454
3498
  const cached = this.sessionManager.getCachedCommands("codex", createdSession?.worktreePath ?? effectiveProjectPath);
3455
3499
  await this.loadAndSetSessionName(createdSession, "codex", effectiveProjectPath, sessionRefId);
@@ -5033,6 +5077,7 @@ export class BridgeWebSocketServer {
5033
5077
  codexModelServiceTiers: this.codexModelServiceTiers,
5034
5078
  codexProfiles: this.codexProfiles,
5035
5079
  defaultCodexProfile: this.defaultCodexProfile,
5080
+ codexAutoReviewDisabled: this.codexAutoReviewDisabled,
5036
5081
  bridgeVersion: getPackageVersion(),
5037
5082
  });
5038
5083
  }
@@ -5064,6 +5109,7 @@ export class BridgeWebSocketServer {
5064
5109
  codexModelServiceTiers: this.codexModelServiceTiers,
5065
5110
  codexProfiles: this.codexProfiles,
5066
5111
  defaultCodexProfile: this.defaultCodexProfile,
5112
+ codexAutoReviewDisabled: this.codexAutoReviewDisabled,
5067
5113
  bridgeVersion: getPackageVersion(),
5068
5114
  });
5069
5115
  }
@@ -5312,6 +5358,7 @@ export class BridgeWebSocketServer {
5312
5358
  console.warn(`[ws] Failed to load Codex metadata: ${err}`);
5313
5359
  this.codexProfiles = [];
5314
5360
  this.defaultCodexProfile = undefined;
5361
+ this.codexAutoReviewPolicyLoaded = false;
5315
5362
  this.applyFallbackCodexModels();
5316
5363
  this.broadcastSessionList();
5317
5364
  })
@@ -5324,9 +5371,10 @@ export class BridgeWebSocketServer {
5324
5371
  const activeProcess = this.getActiveCodexProcess();
5325
5372
  const codexProcess = activeProcess ?? (await this.createStandaloneCodexProcess(projectPath));
5326
5373
  try {
5327
- const [profileResult, modelResult] = await Promise.allSettled([
5374
+ const [profileResult, modelResult, requirementsResult] = await Promise.allSettled([
5328
5375
  codexProcess.readProfileConfig(projectPath),
5329
5376
  this.readCodexModels(codexProcess),
5377
+ this.readCodexAutoReviewDisabled(codexProcess),
5330
5378
  ]);
5331
5379
  if (profileResult.status === "fulfilled") {
5332
5380
  this.codexProfiles = profileResult.value.profiles;
@@ -5346,6 +5394,14 @@ export class BridgeWebSocketServer {
5346
5394
  }
5347
5395
  this.applyFallbackCodexModels();
5348
5396
  }
5397
+ if (requirementsResult.status === "fulfilled") {
5398
+ this.codexAutoReviewDisabled = requirementsResult.value;
5399
+ this.codexAutoReviewPolicyLoaded = true;
5400
+ }
5401
+ else {
5402
+ console.warn(`[ws] Failed to load Codex config requirements: ${requirementsResult.reason}`);
5403
+ this.codexAutoReviewPolicyLoaded = false;
5404
+ }
5349
5405
  this.broadcastSessionList();
5350
5406
  }
5351
5407
  finally {
@@ -5409,6 +5465,14 @@ export class BridgeWebSocketServer {
5409
5465
  supportedServiceTiers: fallbackCodexServiceTiers(model),
5410
5466
  }));
5411
5467
  }
5468
+ async readCodexAutoReviewDisabled(codexProcess) {
5469
+ const requirementsSource = codexProcess;
5470
+ if (typeof requirementsSource.readConfigRequirements !== "function") {
5471
+ return false;
5472
+ }
5473
+ return (await requirementsSource.readConfigRequirements())
5474
+ .autoReviewDisabled;
5475
+ }
5412
5476
  applyCodexModels(models) {
5413
5477
  this.codexModels = models.map((model) => model.model);
5414
5478
  this.codexModelReasoningEfforts = Object.fromEntries(models.map((model) => [
@@ -5487,6 +5551,19 @@ export class BridgeWebSocketServer {
5487
5551
  ? session.process
5488
5552
  : null;
5489
5553
  }
5554
+ withCodexAutoReviewPolicy(options) {
5555
+ const disableAutoReview = this.codexAutoReviewDisabled;
5556
+ return {
5557
+ ...options,
5558
+ ...(disableAutoReview ? { approvalsReviewer: "user" } : {}),
5559
+ ...(disableAutoReview && options.codexPermissionsMode === "autoReview"
5560
+ ? { codexPermissionsMode: "default" }
5561
+ : {}),
5562
+ autoReviewDisabledByPolicy: this.codexAutoReviewPolicyLoaded
5563
+ ? disableAutoReview
5564
+ : null,
5565
+ };
5566
+ }
5490
5567
  getActiveClaudeProcess() {
5491
5568
  const summary = this.sessionManager
5492
5569
  .list()