@ccpocket-base-auth/bridge 1.26.0 → 1.27.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/README.md CHANGED
@@ -12,6 +12,10 @@ npx @ccpocket/bridge@latest
12
12
 
13
13
  A QR code will appear in your terminal. Scan it with the ccpocket mobile app to connect.
14
14
 
15
+ > Warning
16
+ > Versions older than `1.25.0` are deprecated and should not be used for new installs due to potential Anthropic policy concerns around OAuth-based usage.
17
+ > Upgrade to `>=1.25.0` and use `ANTHROPIC_API_KEY` instead of OAuth.
18
+
15
19
  ## Installation
16
20
 
17
21
  ```bash
@@ -69,6 +69,7 @@ export declare class CodexProcess extends EventEmitter<CodexProcessEvents> {
69
69
  private _pendingPlanInput;
70
70
  get status(): ProcessStatus;
71
71
  get isWaitingForInput(): boolean;
72
+ private getMessageModel;
72
73
  get sessionId(): string | null;
73
74
  get agentNickname(): string | null;
74
75
  get agentRole(): string | null;
@@ -42,6 +42,9 @@ export class CodexProcess extends EventEmitter {
42
42
  get isWaitingForInput() {
43
43
  return this.inputResolve !== null;
44
44
  }
45
+ getMessageModel() {
46
+ return sanitizeCodexModel(this.startModel) ?? "";
47
+ }
45
48
  get sessionId() {
46
49
  return this._threadId;
47
50
  }
@@ -98,14 +101,14 @@ export class CodexProcess extends EventEmitter {
98
101
  await this.request("thread/archive", { threadId });
99
102
  }
100
103
  async listThreads(params = {}) {
101
- const result = await this.request("thread/list", {
104
+ const result = (await this.request("thread/list", {
102
105
  sortKey: "updated_at",
103
106
  archived: false,
104
107
  ...(params.limit != null ? { limit: params.limit } : {}),
105
108
  ...(params.cursor !== undefined ? { cursor: params.cursor } : {}),
106
109
  ...(params.cwd ? { cwd: params.cwd } : {}),
107
110
  ...(params.searchTerm ? { searchTerm: params.searchTerm } : {}),
108
- });
111
+ }));
109
112
  const data = Array.isArray(result.data)
110
113
  ? result.data.map((entry) => toCodexThreadSummary(entry))
111
114
  : [];
@@ -157,7 +160,7 @@ export class CodexProcess extends EventEmitter {
157
160
  this.pendingApprovals.clear();
158
161
  this.pendingUserInputs.clear();
159
162
  this.lastTokenUsage = null;
160
- this.startModel = options?.model;
163
+ this.startModel = sanitizeCodexModel(options?.model);
161
164
  this._approvalPolicy = options?.approvalPolicy ?? "never";
162
165
  this._collaborationMode = options?.collaborationMode ?? "default";
163
166
  this.lastPlanItemText = null;
@@ -188,7 +191,10 @@ export class CodexProcess extends EventEmitter {
188
191
  if (this.stopped)
189
192
  return;
190
193
  console.error("[codex-process] app-server process error:", err);
191
- this.emitMessage({ type: "error", message: `Failed to start codex app-server: ${err.message}` });
194
+ this.emitMessage({
195
+ type: "error",
196
+ message: `Failed to start codex app-server: ${err.message}`,
197
+ });
192
198
  this.setStatus("idle");
193
199
  this.emit("exit", 1);
194
200
  });
@@ -197,7 +203,10 @@ export class CodexProcess extends EventEmitter {
197
203
  this.child = null;
198
204
  this.rejectAllPending(new Error("codex app-server exited"));
199
205
  if (!this.stopped && exitCode !== 0) {
200
- this.emitMessage({ type: "error", message: `codex app-server exited with code ${exitCode}` });
206
+ this.emitMessage({
207
+ type: "error",
208
+ message: `codex app-server exited with code ${exitCode}`,
209
+ });
201
210
  }
202
211
  this.setStatus("idle");
203
212
  this.emit("exit", code);
@@ -244,7 +253,8 @@ export class CodexProcess extends EventEmitter {
244
253
  }
245
254
  approve(toolUseId, _updatedInput) {
246
255
  // Check if this is a plan completion approval
247
- if (this.pendingPlanCompletion && toolUseId === this.pendingPlanCompletion.toolUseId) {
256
+ if (this.pendingPlanCompletion &&
257
+ toolUseId === this.pendingPlanCompletion.toolUseId) {
248
258
  this.handlePlanApproved(_updatedInput);
249
259
  return;
250
260
  }
@@ -275,7 +285,8 @@ export class CodexProcess extends EventEmitter {
275
285
  }
276
286
  reject(toolUseId, _message) {
277
287
  // Check if this is a plan completion rejection
278
- if (this.pendingPlanCompletion && toolUseId === this.pendingPlanCompletion.toolUseId) {
288
+ if (this.pendingPlanCompletion &&
289
+ toolUseId === this.pendingPlanCompletion.toolUseId) {
279
290
  this.handlePlanRejected(_message);
280
291
  return;
281
292
  }
@@ -359,7 +370,9 @@ export class CodexProcess extends EventEmitter {
359
370
  * Plan approved → switch to Default mode and auto-start execution.
360
371
  */
361
372
  handlePlanApproved(updatedInput) {
362
- const planText = updatedInput?.plan ?? this.pendingPlanCompletion?.planText ?? "";
373
+ const planText = updatedInput?.plan ??
374
+ this.pendingPlanCompletion?.planText ??
375
+ "";
363
376
  const resolvedToolUseId = this.pendingPlanCompletion?.toolUseId;
364
377
  this.pendingPlanCompletion = null;
365
378
  this._collaborationMode = "default";
@@ -418,8 +431,9 @@ export class CodexProcess extends EventEmitter {
418
431
  experimentalRawEvents: false,
419
432
  persistExtendedHistory: true,
420
433
  };
421
- if (options?.model)
422
- threadParams.model = options.model;
434
+ const requestedModel = sanitizeCodexModel(options?.model);
435
+ if (requestedModel)
436
+ threadParams.model = requestedModel;
423
437
  if (options?.modelReasoningEffort) {
424
438
  threadParams.effort = normalizeReasoningEffort(options.modelReasoningEffort);
425
439
  }
@@ -442,11 +456,9 @@ export class CodexProcess extends EventEmitter {
442
456
  if (options?.threadId) {
443
457
  threadParams.persistExtendedHistory = true;
444
458
  }
445
- const response = await this.request(method, threadParams);
459
+ const response = (await this.request(method, threadParams));
446
460
  const thread = response.thread;
447
- const threadId = typeof thread?.id === "string"
448
- ? thread.id
449
- : options?.threadId;
461
+ const threadId = typeof thread?.id === "string" ? thread.id : options?.threadId;
450
462
  if (!threadId) {
451
463
  throw new Error(`${method} returned no thread id`);
452
464
  }
@@ -454,12 +466,34 @@ export class CodexProcess extends EventEmitter {
454
466
  if (typeof thread?.model === "string" && thread.model) {
455
467
  this.startModel = thread.model;
456
468
  }
469
+ const resolvedSettings = extractResolvedSettingsFromThreadResponse(response);
470
+ if (resolvedSettings.model) {
471
+ this.startModel = resolvedSettings.model;
472
+ }
457
473
  this._threadId = threadId;
458
474
  this.emitMessage({
459
475
  type: "system",
460
476
  subtype: "init",
461
477
  sessionId: threadId,
462
- model: this.startModel ?? "codex",
478
+ provider: "codex",
479
+ ...(sanitizeCodexModel(this.startModel)
480
+ ? { model: sanitizeCodexModel(this.startModel) }
481
+ : {}),
482
+ ...(resolvedSettings.approvalPolicy
483
+ ? { approvalPolicy: resolvedSettings.approvalPolicy }
484
+ : {}),
485
+ ...(resolvedSettings.sandboxMode
486
+ ? { sandboxMode: resolvedSettings.sandboxMode }
487
+ : {}),
488
+ ...(resolvedSettings.modelReasoningEffort
489
+ ? { modelReasoningEffort: resolvedSettings.modelReasoningEffort }
490
+ : {}),
491
+ ...(resolvedSettings.networkAccessEnabled !== undefined
492
+ ? { networkAccessEnabled: resolvedSettings.networkAccessEnabled }
493
+ : {}),
494
+ ...(resolvedSettings.webSearchMode
495
+ ? { webSearchMode: resolvedSettings.webSearchMode }
496
+ : {}),
463
497
  });
464
498
  this.setStatus("idle");
465
499
  // Fetch skills in background (non-blocking)
@@ -472,7 +506,12 @@ export class CodexProcess extends EventEmitter {
472
506
  const message = err instanceof Error ? err.message : String(err);
473
507
  console.error("[codex-process] bootstrap error:", err);
474
508
  this.emitMessage({ type: "error", message: `Codex error: ${message}` });
475
- this.emitMessage({ type: "result", subtype: "error", error: message, sessionId: this._threadId ?? undefined });
509
+ this.emitMessage({
510
+ type: "result",
511
+ subtype: "error",
512
+ error: message,
513
+ sessionId: this._threadId ?? undefined,
514
+ });
476
515
  }
477
516
  this.setStatus("idle");
478
517
  this.emit("exit", 1);
@@ -499,10 +538,10 @@ export class CodexProcess extends EventEmitter {
499
538
  async fetchSkills(projectPath) {
500
539
  const TIMEOUT_MS = 10_000;
501
540
  try {
502
- const result = await Promise.race([
541
+ const result = (await Promise.race([
503
542
  this.request("skills/list", { cwds: [projectPath] }),
504
543
  new Promise((resolve) => setTimeout(() => resolve(null), TIMEOUT_MS)),
505
- ]);
544
+ ]));
506
545
  if (this.stopped || !result?.data)
507
546
  return;
508
547
  const skills = [];
@@ -517,7 +556,9 @@ export class CodexProcess extends EventEmitter {
517
556
  name: skill.name,
518
557
  path: skill.path,
519
558
  description: skill.description,
520
- shortDescription: skill.shortDescription ?? skill.interface?.shortDescription ?? undefined,
559
+ shortDescription: skill.shortDescription ??
560
+ skill.interface?.shortDescription ??
561
+ undefined,
521
562
  enabled: skill.enabled,
522
563
  scope: skill.scope,
523
564
  displayName: skill.interface?.displayName ?? undefined,
@@ -558,7 +599,10 @@ export class CodexProcess extends EventEmitter {
558
599
  if (this.stopped || !pendingInput.text)
559
600
  break;
560
601
  if (!this._threadId) {
561
- this.emitMessage({ type: "error", message: "Codex thread is not initialized" });
602
+ this.emitMessage({
603
+ type: "error",
604
+ message: "Codex thread is not initialized",
605
+ });
562
606
  continue;
563
607
  }
564
608
  const { input, tempPaths } = await this.toRpcInput(pendingInput);
@@ -574,15 +618,18 @@ export class CodexProcess extends EventEmitter {
574
618
  input,
575
619
  approvalPolicy: normalizeApprovalPolicy(this._approvalPolicy),
576
620
  };
577
- if (options?.model)
578
- params.model = options.model;
621
+ const requestedModel = sanitizeCodexModel(options?.model);
622
+ if (requestedModel)
623
+ params.model = requestedModel;
579
624
  if (options?.modelReasoningEffort) {
580
625
  params.effort = normalizeReasoningEffort(options.modelReasoningEffort);
581
626
  }
582
627
  // Always send collaborationMode so the server switches modes correctly.
583
628
  // Omitting it causes the server to persist the previous turn's mode.
584
629
  const modeSettings = {
585
- model: options?.model || this.startModel || "gpt-5.4",
630
+ model: requestedModel
631
+ || sanitizeCodexModel(this.startModel)
632
+ || "gpt-5.4",
586
633
  };
587
634
  if (this._collaborationMode === "plan") {
588
635
  modeSettings.reasoning_effort = "medium";
@@ -646,11 +693,15 @@ export class CodexProcess extends EventEmitter {
646
693
  }
647
694
  }
648
695
  handleRpcEnvelope(envelope) {
649
- if (envelope.id != null && envelope.method && envelope.result === undefined && envelope.error === undefined) {
696
+ if (envelope.id != null &&
697
+ envelope.method &&
698
+ envelope.result === undefined &&
699
+ envelope.error === undefined) {
650
700
  this.handleServerRequest(envelope.id, envelope.method, envelope.params ?? {});
651
701
  return;
652
702
  }
653
- if (envelope.id != null && (envelope.result !== undefined || envelope.error)) {
703
+ if (envelope.id != null &&
704
+ (envelope.result !== undefined || envelope.error)) {
654
705
  this.handleRpcResponse(envelope);
655
706
  return;
656
707
  }
@@ -678,16 +729,38 @@ export class CodexProcess extends EventEmitter {
678
729
  case "item/commandExecution/requestApproval": {
679
730
  const toolUseId = this.extractToolUseId(params, id);
680
731
  const input = {
681
- ...(typeof params.command === "string" ? { command: params.command } : {}),
732
+ ...(typeof params.command === "string"
733
+ ? { command: params.command }
734
+ : {}),
682
735
  ...(typeof params.cwd === "string" ? { cwd: params.cwd } : {}),
683
- ...(params.commandActions ? { commandActions: params.commandActions } : {}),
684
- ...(params.networkApprovalContext ? { networkApprovalContext: params.networkApprovalContext } : {}),
685
- ...(params.additionalPermissions ? { additionalPermissions: params.additionalPermissions } : {}),
686
- ...(params.skillMetadata ? { skillMetadata: params.skillMetadata } : {}),
687
- ...(params.proposedExecpolicyAmendment ? { proposedExecpolicyAmendment: params.proposedExecpolicyAmendment } : {}),
688
- ...(params.proposedNetworkPolicyAmendments ? { proposedNetworkPolicyAmendments: params.proposedNetworkPolicyAmendments } : {}),
689
- ...(params.availableDecisions ? { availableDecisions: params.availableDecisions } : {}),
690
- ...(typeof params.reason === "string" ? { reason: params.reason } : {}),
736
+ ...(params.commandActions
737
+ ? { commandActions: params.commandActions }
738
+ : {}),
739
+ ...(params.networkApprovalContext
740
+ ? { networkApprovalContext: params.networkApprovalContext }
741
+ : {}),
742
+ ...(params.additionalPermissions
743
+ ? { additionalPermissions: params.additionalPermissions }
744
+ : {}),
745
+ ...(params.skillMetadata
746
+ ? { skillMetadata: params.skillMetadata }
747
+ : {}),
748
+ ...(params.proposedExecpolicyAmendment
749
+ ? {
750
+ proposedExecpolicyAmendment: params.proposedExecpolicyAmendment,
751
+ }
752
+ : {}),
753
+ ...(params.proposedNetworkPolicyAmendments
754
+ ? {
755
+ proposedNetworkPolicyAmendments: params.proposedNetworkPolicyAmendments,
756
+ }
757
+ : {}),
758
+ ...(params.availableDecisions
759
+ ? { availableDecisions: params.availableDecisions }
760
+ : {}),
761
+ ...(typeof params.reason === "string"
762
+ ? { reason: params.reason }
763
+ : {}),
691
764
  };
692
765
  this.pendingApprovals.set(toolUseId, {
693
766
  requestId: id,
@@ -709,8 +782,12 @@ export class CodexProcess extends EventEmitter {
709
782
  const toolUseId = this.extractToolUseId(params, id);
710
783
  const input = {
711
784
  ...(Array.isArray(params.changes) ? { changes: params.changes } : {}),
712
- ...(typeof params.grantRoot === "string" ? { grantRoot: params.grantRoot } : {}),
713
- ...(typeof params.reason === "string" ? { reason: params.reason } : {}),
785
+ ...(typeof params.grantRoot === "string"
786
+ ? { grantRoot: params.grantRoot }
787
+ : {}),
788
+ ...(typeof params.reason === "string"
789
+ ? { reason: params.reason }
790
+ : {}),
714
791
  };
715
792
  this.pendingApprovals.set(toolUseId, {
716
793
  requestId: id,
@@ -767,7 +844,9 @@ export class CodexProcess extends EventEmitter {
767
844
  const requestedPermissions = asRecord(params.permissions) ?? {};
768
845
  const input = {
769
846
  permissions: requestedPermissions,
770
- ...(typeof params.reason === "string" ? { reason: params.reason } : {}),
847
+ ...(typeof params.reason === "string"
848
+ ? { reason: params.reason }
849
+ : {}),
771
850
  };
772
851
  this.pendingApprovals.set(toolUseId, {
773
852
  requestId: id,
@@ -905,7 +984,7 @@ export class CodexProcess extends EventEmitter {
905
984
  id: randomUUID(),
906
985
  role: "assistant",
907
986
  content: [{ type: "text", text }],
908
- model: "codex",
987
+ model: this.getMessageModel(),
909
988
  },
910
989
  });
911
990
  break;
@@ -947,7 +1026,9 @@ export class CodexProcess extends EventEmitter {
947
1026
  subtype: "success",
948
1027
  sessionId: this._threadId ?? undefined,
949
1028
  ...(usage?.input != null ? { inputTokens: usage.input } : {}),
950
- ...(usage?.cachedInput != null ? { cachedInputTokens: usage.cachedInput } : {}),
1029
+ ...(usage?.cachedInput != null
1030
+ ? { cachedInputTokens: usage.cachedInput }
1031
+ : {}),
951
1032
  ...(usage?.output != null ? { outputTokens: usage.output } : {}),
952
1033
  });
953
1034
  }
@@ -971,7 +1052,8 @@ export class CodexProcess extends EventEmitter {
971
1052
  }
972
1053
  else {
973
1054
  this.lastPlanItemText = null;
974
- if (this.pendingApprovals.size === 0 && this.pendingUserInputs.size === 0) {
1055
+ if (this.pendingApprovals.size === 0 &&
1056
+ this.pendingUserInputs.size === 0) {
975
1057
  this.setStatus("idle");
976
1058
  }
977
1059
  }
@@ -1005,7 +1087,7 @@ export class CodexProcess extends EventEmitter {
1005
1087
  input: { command: commandText },
1006
1088
  },
1007
1089
  ],
1008
- model: "codex",
1090
+ model: this.getMessageModel(),
1009
1091
  },
1010
1092
  });
1011
1093
  break;
@@ -1026,7 +1108,7 @@ export class CodexProcess extends EventEmitter {
1026
1108
  },
1027
1109
  },
1028
1110
  ],
1029
- model: "codex",
1111
+ model: this.getMessageModel(),
1030
1112
  },
1031
1113
  });
1032
1114
  break;
@@ -1046,7 +1128,7 @@ export class CodexProcess extends EventEmitter {
1046
1128
  input: toToolUseInput(item.arguments),
1047
1129
  },
1048
1130
  ],
1049
- model: "codex",
1131
+ model: this.getMessageModel(),
1050
1132
  },
1051
1133
  });
1052
1134
  break;
@@ -1057,10 +1139,16 @@ export class CodexProcess extends EventEmitter {
1057
1139
  const input = {
1058
1140
  tool,
1059
1141
  ...(typeof item.prompt === "string" ? { prompt: item.prompt } : {}),
1060
- ...(typeof item.senderThreadId === "string" ? { senderThreadId: item.senderThreadId } : {}),
1061
- ...(Array.isArray(item.receiverThreadIds) ? { receiverThreadIds: item.receiverThreadIds } : {}),
1142
+ ...(typeof item.senderThreadId === "string"
1143
+ ? { senderThreadId: item.senderThreadId }
1144
+ : {}),
1145
+ ...(Array.isArray(item.receiverThreadIds)
1146
+ ? { receiverThreadIds: item.receiverThreadIds }
1147
+ : {}),
1062
1148
  ...(typeof item.model === "string" ? { model: item.model } : {}),
1063
- ...(typeof item.reasoningEffort === "string" ? { reasoningEffort: item.reasoningEffort } : {}),
1149
+ ...(typeof item.reasoningEffort === "string"
1150
+ ? { reasoningEffort: item.reasoningEffort }
1151
+ : {}),
1064
1152
  ...(item.agentsStates ? { agentsStates: item.agentsStates } : {}),
1065
1153
  };
1066
1154
  this.emitMessage({
@@ -1076,7 +1164,7 @@ export class CodexProcess extends EventEmitter {
1076
1164
  input,
1077
1165
  },
1078
1166
  ],
1079
- model: "codex",
1167
+ model: this.getMessageModel(),
1080
1168
  },
1081
1169
  });
1082
1170
  break;
@@ -1101,7 +1189,7 @@ export class CodexProcess extends EventEmitter {
1101
1189
  id: itemId,
1102
1190
  role: "assistant",
1103
1191
  content: [{ type: "text", text }],
1104
- model: "codex",
1192
+ model: this.getMessageModel(),
1105
1193
  },
1106
1194
  });
1107
1195
  break;
@@ -1157,7 +1245,7 @@ export class CodexProcess extends EventEmitter {
1157
1245
  input: item.arguments ?? {},
1158
1246
  },
1159
1247
  ],
1160
- model: "codex",
1248
+ model: this.getMessageModel(),
1161
1249
  },
1162
1250
  });
1163
1251
  this.emitMessage({
@@ -1197,7 +1285,7 @@ export class CodexProcess extends EventEmitter {
1197
1285
  input: { query },
1198
1286
  },
1199
1287
  ],
1200
- model: "codex",
1288
+ model: this.getMessageModel(),
1201
1289
  },
1202
1290
  });
1203
1291
  this.emitMessage({
@@ -1249,7 +1337,11 @@ export class CodexProcess extends EventEmitter {
1249
1337
  const tempPaths = [];
1250
1338
  // Prepend SkillUserInput if a skill reference is attached
1251
1339
  if (pendingInput.skill) {
1252
- input.push({ type: "skill", name: pendingInput.skill.name, path: pendingInput.skill.path });
1340
+ input.push({
1341
+ type: "skill",
1342
+ name: pendingInput.skill.name,
1343
+ path: pendingInput.skill.path,
1344
+ });
1253
1345
  }
1254
1346
  input.push({ type: "text", text: pendingInput.text });
1255
1347
  if (!pendingInput.images || pendingInput.images.length === 0) {
@@ -1354,14 +1446,22 @@ export class CodexProcess extends EventEmitter {
1354
1446
  const approval = [...this.pendingApprovals.values()].find((entry) => entry.requestId === requestId);
1355
1447
  if (approval) {
1356
1448
  this.pendingApprovals.delete(approval.toolUseId);
1357
- this.emitMessage({ type: "permission_resolved", toolUseId: approval.toolUseId });
1449
+ this.emitMessage({
1450
+ type: "permission_resolved",
1451
+ toolUseId: approval.toolUseId,
1452
+ });
1358
1453
  }
1359
1454
  const inputRequest = [...this.pendingUserInputs.values()].find((entry) => entry.requestId === requestId);
1360
1455
  if (inputRequest) {
1361
1456
  this.pendingUserInputs.delete(inputRequest.toolUseId);
1362
- this.emitMessage({ type: "permission_resolved", toolUseId: inputRequest.toolUseId });
1457
+ this.emitMessage({
1458
+ type: "permission_resolved",
1459
+ toolUseId: inputRequest.toolUseId,
1460
+ });
1363
1461
  }
1364
- if (!this.pendingPlanCompletion && this.pendingApprovals.size === 0 && this.pendingUserInputs.size === 0) {
1462
+ if (!this.pendingPlanCompletion &&
1463
+ this.pendingApprovals.size === 0 &&
1464
+ this.pendingUserInputs.size === 0) {
1365
1465
  this.setStatus(this.pendingTurnId ? "running" : "idle");
1366
1466
  }
1367
1467
  }
@@ -1417,13 +1517,56 @@ function normalizeReasoningEffort(value) {
1417
1517
  return value;
1418
1518
  }
1419
1519
  }
1520
+ function sanitizeCodexModel(value) {
1521
+ if (typeof value !== "string")
1522
+ return undefined;
1523
+ const normalized = value.trim();
1524
+ if (!normalized || normalized === "codex")
1525
+ return undefined;
1526
+ return normalized;
1527
+ }
1528
+ function extractResolvedSettingsFromThreadResponse(response) {
1529
+ const thread = response.thread;
1530
+ const sandbox = response.sandbox;
1531
+ return {
1532
+ model: sanitizeCodexModel(response.model)
1533
+ ?? sanitizeCodexModel(thread?.model),
1534
+ approvalPolicy: typeof response.approvalPolicy === "string"
1535
+ ? response.approvalPolicy
1536
+ : undefined,
1537
+ sandboxMode: normalizeSandboxModeFromRpc(sandbox?.type),
1538
+ modelReasoningEffort: typeof response.reasoningEffort === "string"
1539
+ ? response.reasoningEffort
1540
+ : undefined,
1541
+ networkAccessEnabled: typeof sandbox?.networkAccess === "boolean"
1542
+ ? sandbox.networkAccess
1543
+ : undefined,
1544
+ webSearchMode: typeof response.webSearchMode === "string"
1545
+ ? response.webSearchMode
1546
+ : undefined,
1547
+ };
1548
+ }
1549
+ function normalizeSandboxModeFromRpc(value) {
1550
+ switch (value) {
1551
+ case "dangerFullAccess":
1552
+ return "danger-full-access";
1553
+ case "workspaceWrite":
1554
+ return "workspace-write";
1555
+ case "readOnly":
1556
+ return "read-only";
1557
+ default:
1558
+ return typeof value === "string" && value.length > 0 ? value : undefined;
1559
+ }
1560
+ }
1420
1561
  function normalizeItemType(raw) {
1421
1562
  if (typeof raw !== "string")
1422
1563
  return "";
1423
1564
  return raw.replace(/[_\s-]/g, "").toLowerCase();
1424
1565
  }
1425
1566
  function numberOrUndefined(value) {
1426
- return typeof value === "number" && Number.isFinite(value) ? value : undefined;
1567
+ return typeof value === "number" && Number.isFinite(value)
1568
+ ? value
1569
+ : undefined;
1427
1570
  }
1428
1571
  function stringOrNull(value) {
1429
1572
  return typeof value === "string" && value.trim().length > 0 ? value : null;
@@ -1458,7 +1601,9 @@ function toToolUseInput(value) {
1458
1601
  function formatDynamicToolResult(item) {
1459
1602
  const status = typeof item.status === "string" ? item.status : "completed";
1460
1603
  const success = typeof item.success === "boolean" ? item.success : null;
1461
- const contentItems = Array.isArray(item.contentItems) ? item.contentItems : null;
1604
+ const contentItems = Array.isArray(item.contentItems)
1605
+ ? item.contentItems
1606
+ : null;
1462
1607
  const parts = [
1463
1608
  `status: ${status}`,
1464
1609
  ...(success != null ? [`success: ${success}`] : []),
@@ -1536,7 +1681,9 @@ function normalizeMcpToolResult(result) {
1536
1681
  const imageCount = rawContentBlocks.filter((entry) => entry.type === "image").length;
1537
1682
  if (imageCount > 0) {
1538
1683
  return {
1539
- content: imageCount === 1 ? "Generated 1 image" : `Generated ${imageCount} images`,
1684
+ content: imageCount === 1
1685
+ ? "Generated 1 image"
1686
+ : `Generated ${imageCount} images`,
1540
1687
  rawContentBlocks,
1541
1688
  };
1542
1689
  }
@@ -1639,7 +1786,9 @@ function normalizeUserInputQuestions(raw) {
1639
1786
  .map((entry, index) => {
1640
1787
  const id = typeof entry.id === "string" ? entry.id : `question_${index + 1}`;
1641
1788
  const question = typeof entry.question === "string" ? entry.question : "";
1642
- const header = typeof entry.header === "string" ? entry.header : `Question ${index + 1}`;
1789
+ const header = typeof entry.header === "string"
1790
+ ? entry.header
1791
+ : `Question ${index + 1}`;
1643
1792
  const optionsRaw = Array.isArray(entry.options) ? entry.options : [];
1644
1793
  const options = optionsRaw
1645
1794
  .filter((option) => !!option && typeof option === "object")
@@ -1821,7 +1970,9 @@ function createElicitationInput(params) {
1821
1970
  const field = value;
1822
1971
  const title = typeof field.title === "string" ? field.title : key;
1823
1972
  const description = typeof field.description === "string" ? field.description : message;
1824
- const enumValues = Array.isArray(field.enum) ? field.enum.map((entry) => String(entry)) : [];
1973
+ const enumValues = Array.isArray(field.enum)
1974
+ ? field.enum.map((entry) => String(entry))
1975
+ : [];
1825
1976
  const type = typeof field.type === "string" ? field.type : "";
1826
1977
  const options = enumValues.length > 0
1827
1978
  ? enumValues.map((entry, index) => ({