@ccpocket/bridge 1.58.1 → 1.59.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/websocket.js CHANGED
@@ -192,6 +192,59 @@ function normalizeCodexApprovalPolicy(value) {
192
192
  return "on-request";
193
193
  }
194
194
  }
195
+ function normalizeCodexPermissionsMode(value) {
196
+ switch (value) {
197
+ case "default":
198
+ case "autoReview":
199
+ case "fullAccess":
200
+ case "custom":
201
+ return value;
202
+ default:
203
+ return undefined;
204
+ }
205
+ }
206
+ function codexSettingsFromPermissionsMode(mode) {
207
+ switch (mode) {
208
+ case "default":
209
+ return {
210
+ codexPermissionsMode: mode,
211
+ approvalPolicy: "on-request",
212
+ approvalsReviewer: "user",
213
+ sandboxMode: "workspace-write",
214
+ };
215
+ case "autoReview":
216
+ return {
217
+ codexPermissionsMode: mode,
218
+ approvalPolicy: "on-request",
219
+ approvalsReviewer: "auto_review",
220
+ sandboxMode: "workspace-write",
221
+ };
222
+ case "fullAccess":
223
+ return {
224
+ codexPermissionsMode: mode,
225
+ approvalPolicy: "never",
226
+ approvalsReviewer: "user",
227
+ sandboxMode: "danger-full-access",
228
+ };
229
+ case "custom":
230
+ return { codexPermissionsMode: mode };
231
+ }
232
+ }
233
+ function inferCodexPermissionsMode(params) {
234
+ const approvalPolicy = params.approvalPolicy;
235
+ const approvalsReviewer = params.approvalsReviewer ?? "user";
236
+ const sandboxMode = params.sandboxMode;
237
+ if (approvalPolicy === "never" && sandboxMode === "danger-full-access") {
238
+ return "fullAccess";
239
+ }
240
+ if (approvalPolicy === "on-request" && sandboxMode === "workspace-write") {
241
+ return approvalsReviewer === "auto_review" ||
242
+ approvalsReviewer === "guardian_subagent"
243
+ ? "autoReview"
244
+ : "default";
245
+ }
246
+ return undefined;
247
+ }
195
248
  function errorMessageOf(err) {
196
249
  return err instanceof Error ? err.message : String(err);
197
250
  }
@@ -417,7 +470,7 @@ export class BridgeWebSocketServer {
417
470
  return { roots: [...normalized.values()] };
418
471
  }
419
472
  buildSessionCreatedMessage(params) {
420
- const { sessionId, provider, projectPath, session, permissionMode, executionMode, planMode, approvalsReviewer, sandboxMode, slashCommands, skills, skillMetadata, apps, appMetadata, plugins, pluginMetadata, sourceSessionId, } = params;
473
+ const { sessionId, provider, projectPath, session, permissionMode, executionMode, planMode, approvalsReviewer, codexPermissionsMode, sandboxMode, slashCommands, skills, skillMetadata, apps, appMetadata, plugins, pluginMetadata, sourceSessionId, } = params;
421
474
  const msg = {
422
475
  type: "system",
423
476
  subtype: "session_created",
@@ -434,6 +487,12 @@ export class BridgeWebSocketServer {
434
487
  approvalsReviewer: approvalsReviewer ?? session?.codexSettings?.approvalsReviewer,
435
488
  }
436
489
  : {}),
490
+ ...((codexPermissionsMode ?? session?.codexSettings?.codexPermissionsMode)
491
+ ? {
492
+ codexPermissionsMode: (codexPermissionsMode ??
493
+ session?.codexSettings?.codexPermissionsMode),
494
+ }
495
+ : {}),
437
496
  ...((executionMode ??
438
497
  (session?.process instanceof SdkProcess
439
498
  ? session.process.permissionMode === "bypassPermissions"
@@ -511,6 +570,9 @@ export class BridgeWebSocketServer {
511
570
  if (session.codexSettings.approvalPolicy !== undefined) {
512
571
  msg.approvalPolicy = session.codexSettings.approvalPolicy;
513
572
  }
573
+ if (session.codexSettings.codexPermissionsMode !== undefined) {
574
+ msg.codexPermissionsMode = session.codexSettings.codexPermissionsMode;
575
+ }
514
576
  if (session.codexSettings.modelReasoningEffort !== undefined) {
515
577
  msg.modelReasoningEffort = session.codexSettings.modelReasoningEffort;
516
578
  }
@@ -991,13 +1053,21 @@ export class BridgeWebSocketServer {
991
1053
  }
992
1054
  try {
993
1055
  const provider = msg.provider ?? "claude";
1056
+ const requestedCodexPermissionsMode = provider === "codex"
1057
+ ? normalizeCodexPermissionsMode(msg.codexPermissionsMode)
1058
+ : undefined;
1059
+ const codexPermissionSettings = requestedCodexPermissionsMode
1060
+ ? codexSettingsFromPermissionsMode(requestedCodexPermissionsMode)
1061
+ : undefined;
994
1062
  const codexApprovalPolicy = provider === "codex"
995
- ? normalizeCodexApprovalPolicy(msg.approvalPolicy ??
996
- (msg.executionMode == null
997
- ? undefined
998
- : msg.executionMode === "fullAccess"
999
- ? "never"
1000
- : "on-request"))
1063
+ ? requestedCodexPermissionsMode
1064
+ ? codexPermissionSettings?.approvalPolicy
1065
+ : normalizeCodexApprovalPolicy(msg.approvalPolicy ??
1066
+ (msg.executionMode == null
1067
+ ? undefined
1068
+ : msg.executionMode === "fullAccess"
1069
+ ? "never"
1070
+ : "on-request"))
1001
1071
  : undefined;
1002
1072
  const executionMode = deriveExecutionMode({
1003
1073
  provider,
@@ -1066,12 +1136,19 @@ export class BridgeWebSocketServer {
1066
1136
  existingWorktreePath: msg.existingWorktreePath,
1067
1137
  }, provider, {
1068
1138
  profile: msg.profile,
1069
- approvalPolicy: codexApprovalPolicy ??
1070
- normalizeCodexApprovalPolicy(executionMode === "fullAccess"
1071
- ? "never"
1072
- : "on-request"),
1073
- approvalsReviewer: msg.approvalsReviewer,
1074
- sandboxMode: sandboxModeToInternal(msg.sandboxMode),
1139
+ approvalPolicy: codexPermissionSettings
1140
+ ? codexPermissionSettings.approvalPolicy
1141
+ : (codexApprovalPolicy ??
1142
+ normalizeCodexApprovalPolicy(executionMode === "fullAccess"
1143
+ ? "never"
1144
+ : "on-request")),
1145
+ approvalsReviewer: codexPermissionSettings
1146
+ ? codexPermissionSettings.approvalsReviewer
1147
+ : msg.approvalsReviewer,
1148
+ codexPermissionsMode: codexPermissionSettings?.codexPermissionsMode,
1149
+ sandboxMode: codexPermissionSettings
1150
+ ? codexPermissionSettings.sandboxMode
1151
+ : sandboxModeToInternal(msg.sandboxMode),
1075
1152
  model: msg.model,
1076
1153
  modelReasoningEffort: msg.modelReasoningEffort ?? undefined,
1077
1154
  networkAccessEnabled: msg.networkAccessEnabled,
@@ -1103,7 +1180,10 @@ export class BridgeWebSocketServer {
1103
1180
  ? effectiveExecutionMode
1104
1181
  : executionMode,
1105
1182
  planMode: provider === "claude" ? effectivePlanMode : planMode,
1106
- sandboxMode: msg.sandboxMode,
1183
+ sandboxMode: createdSession?.codexSettings?.sandboxMode
1184
+ ? sandboxModeToExternal(createdSession.codexSettings.sandboxMode)
1185
+ : msg.sandboxMode,
1186
+ codexPermissionsMode: createdSession?.codexSettings?.codexPermissionsMode,
1107
1187
  approvalsReviewer: createdSession?.codexSettings?.approvalsReviewer,
1108
1188
  ...(cached
1109
1189
  ? {
@@ -1558,12 +1638,18 @@ export class BridgeWebSocketServer {
1558
1638
  // Permission mode for Codex requires a session restart (like sandbox mode).
1559
1639
  // approvalPolicy and collaborationMode are thread-level settings that
1560
1640
  // only take effect reliably at thread/start or thread/resume time.
1561
- const explicitApproval = normalizeCodexApprovalPolicy(msg.approvalPolicy ??
1562
- (msg.executionMode == null
1563
- ? undefined
1564
- : msg.executionMode === "fullAccess"
1565
- ? "never"
1566
- : "on-request"));
1641
+ const requestedCodexPermissionsMode = normalizeCodexPermissionsMode(msg.codexPermissionsMode);
1642
+ const codexPermissionSettings = requestedCodexPermissionsMode
1643
+ ? codexSettingsFromPermissionsMode(requestedCodexPermissionsMode)
1644
+ : undefined;
1645
+ const explicitApproval = requestedCodexPermissionsMode
1646
+ ? codexPermissionSettings?.approvalPolicy
1647
+ : normalizeCodexApprovalPolicy(msg.approvalPolicy ??
1648
+ (msg.executionMode == null
1649
+ ? undefined
1650
+ : msg.executionMode === "fullAccess"
1651
+ ? "never"
1652
+ : "on-request"));
1567
1653
  const executionMode = deriveExecutionMode({
1568
1654
  provider: "codex",
1569
1655
  permissionMode: msg.mode,
@@ -1576,6 +1662,13 @@ export class BridgeWebSocketServer {
1576
1662
  });
1577
1663
  const legacyPermissionMode = modesToLegacyPermissionMode("codex", executionMode, planMode);
1578
1664
  const newApproval = explicitApproval;
1665
+ const newPermissionsMode = codexPermissionSettings?.codexPermissionsMode ??
1666
+ inferCodexPermissionsMode({
1667
+ approvalPolicy: newApproval,
1668
+ approvalsReviewer: codexPermissionSettings?.approvalsReviewer ??
1669
+ msg.approvalsReviewer,
1670
+ sandboxMode: session.codexSettings?.sandboxMode,
1671
+ });
1579
1672
  const newCollaboration = planMode
1580
1673
  ? "plan"
1581
1674
  : "default";
@@ -1583,21 +1676,34 @@ export class BridgeWebSocketServer {
1583
1676
  .approvalPolicy;
1584
1677
  const currentReviewer = session.process
1585
1678
  .approvalsReviewer;
1586
- const newReviewer = msg.approvalsReviewer ?? currentReviewer;
1679
+ const newReviewer = requestedCodexPermissionsMode === "custom"
1680
+ ? undefined
1681
+ : (codexPermissionSettings?.approvalsReviewer ??
1682
+ msg.approvalsReviewer ??
1683
+ currentReviewer);
1684
+ const currentSandboxMode = session.codexSettings?.sandboxMode;
1685
+ const newSandboxMode = codexPermissionSettings
1686
+ ? codexPermissionSettings.sandboxMode
1687
+ : currentSandboxMode;
1587
1688
  const currentCollaboration = session.process
1588
1689
  .collaborationMode;
1690
+ const currentPermissionsMode = session.codexSettings?.codexPermissionsMode;
1589
1691
  if (newApproval === currentApproval &&
1590
1692
  newReviewer === currentReviewer &&
1693
+ newSandboxMode === currentSandboxMode &&
1694
+ newPermissionsMode === currentPermissionsMode &&
1591
1695
  newCollaboration === currentCollaboration) {
1592
1696
  break; // No change needed
1593
1697
  }
1594
- const canApplyModeInPlace = session.status === "idle";
1698
+ const canApplyModeInPlace = session.status === "idle" &&
1699
+ requestedCodexPermissionsMode !== "custom" &&
1700
+ newSandboxMode === currentSandboxMode;
1595
1701
  if (canApplyModeInPlace) {
1596
1702
  const process = session.process;
1597
- if (newApproval !== currentApproval) {
1703
+ if (newApproval && newApproval !== currentApproval) {
1598
1704
  process.setApprovalPolicy(newApproval);
1599
1705
  }
1600
- if (newReviewer !== currentReviewer) {
1706
+ if (newReviewer && newReviewer !== currentReviewer) {
1601
1707
  process.setApprovalsReviewer(newReviewer);
1602
1708
  }
1603
1709
  if (newCollaboration !== currentCollaboration) {
@@ -1607,6 +1713,8 @@ export class BridgeWebSocketServer {
1607
1713
  ...(session.codexSettings ?? {}),
1608
1714
  approvalPolicy: newApproval,
1609
1715
  approvalsReviewer: newReviewer,
1716
+ codexPermissionsMode: newPermissionsMode,
1717
+ sandboxMode: newSandboxMode,
1610
1718
  };
1611
1719
  session.lastActivityAt = new Date();
1612
1720
  this.broadcast({
@@ -1617,6 +1725,7 @@ export class BridgeWebSocketServer {
1617
1725
  executionMode,
1618
1726
  approvalPolicy: newApproval,
1619
1727
  approvalsReviewer: newReviewer,
1728
+ codexPermissionsMode: newPermissionsMode,
1620
1729
  planMode,
1621
1730
  });
1622
1731
  this.broadcastSessionList();
@@ -1647,7 +1756,8 @@ export class BridgeWebSocketServer {
1647
1756
  : undefined, "codex", {
1648
1757
  approvalPolicy: newApproval,
1649
1758
  approvalsReviewer: newReviewer,
1650
- sandboxMode: oldSettings.sandboxMode,
1759
+ codexPermissionsMode: newPermissionsMode,
1760
+ sandboxMode: newSandboxMode,
1651
1761
  model: oldSettings.model,
1652
1762
  modelReasoningEffort: oldSettings.modelReasoningEffort,
1653
1763
  networkAccessEnabled: oldSettings.networkAccessEnabled,
@@ -1665,10 +1775,11 @@ export class BridgeWebSocketServer {
1665
1775
  permissionMode: legacyPermissionMode,
1666
1776
  executionMode,
1667
1777
  planMode,
1668
- sandboxMode: oldSettings.sandboxMode
1669
- ? sandboxModeToExternal(oldSettings.sandboxMode)
1778
+ sandboxMode: newSandboxMode
1779
+ ? sandboxModeToExternal(newSandboxMode)
1670
1780
  : undefined,
1671
1781
  approvalsReviewer: newReviewer,
1782
+ codexPermissionsMode: newPermissionsMode,
1672
1783
  sourceSessionId: oldSessionId,
1673
1784
  }));
1674
1785
  this.broadcastSessionList();
@@ -1705,7 +1816,8 @@ export class BridgeWebSocketServer {
1705
1816
  threadId,
1706
1817
  approvalPolicy: newApproval,
1707
1818
  approvalsReviewer: newReviewer,
1708
- sandboxMode: oldSettings.sandboxMode,
1819
+ codexPermissionsMode: newPermissionsMode,
1820
+ sandboxMode: newSandboxMode,
1709
1821
  model: oldSettings.model,
1710
1822
  modelReasoningEffort: oldSettings.modelReasoningEffort,
1711
1823
  networkAccessEnabled: oldSettings.networkAccessEnabled,
@@ -1725,10 +1837,11 @@ export class BridgeWebSocketServer {
1725
1837
  permissionMode: legacyPermissionMode,
1726
1838
  executionMode,
1727
1839
  planMode,
1728
- sandboxMode: oldSettings.sandboxMode
1729
- ? sandboxModeToExternal(oldSettings.sandboxMode)
1840
+ sandboxMode: newSandboxMode
1841
+ ? sandboxModeToExternal(newSandboxMode)
1730
1842
  : undefined,
1731
1843
  approvalsReviewer: newReviewer,
1844
+ codexPermissionsMode: newPermissionsMode,
1732
1845
  sourceSessionId: oldSessionId,
1733
1846
  }));
1734
1847
  this.broadcastSessionList();
@@ -2410,13 +2523,21 @@ export class BridgeWebSocketServer {
2410
2523
  break;
2411
2524
  }
2412
2525
  const provider = msg.provider ?? "claude";
2526
+ const requestedCodexPermissionsMode = provider === "codex"
2527
+ ? normalizeCodexPermissionsMode(msg.codexPermissionsMode)
2528
+ : undefined;
2529
+ const codexPermissionSettings = requestedCodexPermissionsMode
2530
+ ? codexSettingsFromPermissionsMode(requestedCodexPermissionsMode)
2531
+ : undefined;
2413
2532
  const codexApprovalPolicy = provider === "codex"
2414
- ? normalizeCodexApprovalPolicy(msg.approvalPolicy ??
2415
- (msg.executionMode == null
2416
- ? undefined
2417
- : msg.executionMode === "fullAccess"
2418
- ? "never"
2419
- : "on-request"))
2533
+ ? requestedCodexPermissionsMode
2534
+ ? codexPermissionSettings?.approvalPolicy
2535
+ : normalizeCodexApprovalPolicy(msg.approvalPolicy ??
2536
+ (msg.executionMode == null
2537
+ ? undefined
2538
+ : msg.executionMode === "fullAccess"
2539
+ ? "never"
2540
+ : "on-request"))
2420
2541
  : undefined;
2421
2542
  const executionMode = deriveExecutionMode({
2422
2543
  provider,
@@ -2466,10 +2587,17 @@ export class BridgeWebSocketServer {
2466
2587
  const sessionId = this.sessionManager.create(effectiveProjectPath, undefined, pastMessages, worktreeOpts, "codex", {
2467
2588
  threadId: sessionRefId,
2468
2589
  profile: effectiveProfile,
2469
- approvalPolicy: codexApprovalPolicy ??
2470
- normalizeCodexApprovalPolicy(executionMode === "fullAccess" ? "never" : "on-request"),
2471
- approvalsReviewer: msg.approvalsReviewer,
2472
- sandboxMode: sandboxModeToInternal(msg.sandboxMode),
2590
+ approvalPolicy: codexPermissionSettings
2591
+ ? codexPermissionSettings.approvalPolicy
2592
+ : (codexApprovalPolicy ??
2593
+ normalizeCodexApprovalPolicy(executionMode === "fullAccess" ? "never" : "on-request")),
2594
+ approvalsReviewer: codexPermissionSettings
2595
+ ? codexPermissionSettings.approvalsReviewer
2596
+ : msg.approvalsReviewer,
2597
+ codexPermissionsMode: codexPermissionSettings?.codexPermissionsMode,
2598
+ sandboxMode: codexPermissionSettings
2599
+ ? codexPermissionSettings.sandboxMode
2600
+ : sandboxModeToInternal(msg.sandboxMode),
2473
2601
  model: msg.model,
2474
2602
  modelReasoningEffort: msg.modelReasoningEffort ?? undefined,
2475
2603
  networkAccessEnabled: msg.networkAccessEnabled,
@@ -2491,6 +2619,7 @@ export class BridgeWebSocketServer {
2491
2619
  ? sandboxModeToExternal(createdSession.codexSettings.sandboxMode)
2492
2620
  : undefined,
2493
2621
  approvalsReviewer: createdSession?.codexSettings?.approvalsReviewer,
2622
+ codexPermissionsMode: createdSession?.codexSettings?.codexPermissionsMode,
2494
2623
  permissionMode: legacyPermissionMode,
2495
2624
  executionMode,
2496
2625
  planMode,