@iam-brain/opencode-codex-auth 1.0.0 → 1.1.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.
Files changed (111) hide show
  1. package/README.md +26 -24
  2. package/dist/index.d.ts.map +1 -1
  3. package/dist/index.js +17 -12
  4. package/dist/index.js.map +1 -1
  5. package/dist/lib/account-auth-types.d.ts +3 -0
  6. package/dist/lib/account-auth-types.d.ts.map +1 -0
  7. package/dist/lib/account-auth-types.js +18 -0
  8. package/dist/lib/account-auth-types.js.map +1 -0
  9. package/dist/lib/auth-messages.d.ts +16 -0
  10. package/dist/lib/auth-messages.d.ts.map +1 -0
  11. package/dist/lib/auth-messages.js +15 -0
  12. package/dist/lib/auth-messages.js.map +1 -0
  13. package/dist/lib/cache-io.d.ts.map +1 -1
  14. package/dist/lib/cache-io.js +26 -2
  15. package/dist/lib/cache-io.js.map +1 -1
  16. package/dist/lib/codex-native/accounts.d.ts +1 -4
  17. package/dist/lib/codex-native/accounts.d.ts.map +1 -1
  18. package/dist/lib/codex-native/accounts.js +1 -24
  19. package/dist/lib/codex-native/accounts.js.map +1 -1
  20. package/dist/lib/codex-native/acquire-auth.d.ts.map +1 -1
  21. package/dist/lib/codex-native/acquire-auth.js +9 -2
  22. package/dist/lib/codex-native/acquire-auth.js.map +1 -1
  23. package/dist/lib/codex-native/auth-menu-flow.js +2 -2
  24. package/dist/lib/codex-native/auth-menu-flow.js.map +1 -1
  25. package/dist/lib/codex-native/chat-hooks.d.ts +0 -2
  26. package/dist/lib/codex-native/chat-hooks.d.ts.map +1 -1
  27. package/dist/lib/codex-native/chat-hooks.js +16 -10
  28. package/dist/lib/codex-native/chat-hooks.js.map +1 -1
  29. package/dist/lib/codex-native/collaboration.d.ts +3 -2
  30. package/dist/lib/codex-native/collaboration.d.ts.map +1 -1
  31. package/dist/lib/codex-native/collaboration.js +32 -20
  32. package/dist/lib/codex-native/collaboration.js.map +1 -1
  33. package/dist/lib/codex-native/oauth-auth-methods.d.ts.map +1 -1
  34. package/dist/lib/codex-native/oauth-auth-methods.js +5 -1
  35. package/dist/lib/codex-native/oauth-auth-methods.js.map +1 -1
  36. package/dist/lib/codex-native/oauth-server.d.ts.map +1 -1
  37. package/dist/lib/codex-native/oauth-server.js +52 -9
  38. package/dist/lib/codex-native/oauth-server.js.map +1 -1
  39. package/dist/lib/codex-native/openai-loader-fetch.d.ts.map +1 -1
  40. package/dist/lib/codex-native/openai-loader-fetch.js +105 -78
  41. package/dist/lib/codex-native/openai-loader-fetch.js.map +1 -1
  42. package/dist/lib/codex-native/request-routing.d.ts.map +1 -1
  43. package/dist/lib/codex-native/request-routing.js +18 -1
  44. package/dist/lib/codex-native/request-routing.js.map +1 -1
  45. package/dist/lib/codex-native/request-transform-pipeline.d.ts +9 -2
  46. package/dist/lib/codex-native/request-transform-pipeline.d.ts.map +1 -1
  47. package/dist/lib/codex-native/request-transform-pipeline.js +11 -7
  48. package/dist/lib/codex-native/request-transform-pipeline.js.map +1 -1
  49. package/dist/lib/codex-native/request-transform.d.ts +39 -0
  50. package/dist/lib/codex-native/request-transform.d.ts.map +1 -1
  51. package/dist/lib/codex-native/request-transform.js +321 -269
  52. package/dist/lib/codex-native/request-transform.js.map +1 -1
  53. package/dist/lib/codex-native.d.ts +0 -2
  54. package/dist/lib/codex-native.d.ts.map +1 -1
  55. package/dist/lib/codex-native.js +5 -6
  56. package/dist/lib/codex-native.js.map +1 -1
  57. package/dist/lib/codex-status-storage.d.ts.map +1 -1
  58. package/dist/lib/codex-status-storage.js +3 -0
  59. package/dist/lib/codex-status-storage.js.map +1 -1
  60. package/dist/lib/config-dir-gitignore.d.ts +1 -1
  61. package/dist/lib/config-dir-gitignore.d.ts.map +1 -1
  62. package/dist/lib/config-dir-gitignore.js +2 -0
  63. package/dist/lib/config-dir-gitignore.js.map +1 -1
  64. package/dist/lib/config.d.ts +0 -3
  65. package/dist/lib/config.d.ts.map +1 -1
  66. package/dist/lib/config.js +9 -31
  67. package/dist/lib/config.js.map +1 -1
  68. package/dist/lib/fetch-orchestrator.js +2 -2
  69. package/dist/lib/fetch-orchestrator.js.map +1 -1
  70. package/dist/lib/model-catalog.d.ts.map +1 -1
  71. package/dist/lib/model-catalog.js +44 -27
  72. package/dist/lib/model-catalog.js.map +1 -1
  73. package/dist/lib/oauth-pages.d.ts +1 -1
  74. package/dist/lib/oauth-pages.d.ts.map +1 -1
  75. package/dist/lib/oauth-pages.js +6 -1
  76. package/dist/lib/oauth-pages.js.map +1 -1
  77. package/dist/lib/orchestrator-agent.d.ts.map +1 -1
  78. package/dist/lib/orchestrator-agent.js +3 -1
  79. package/dist/lib/orchestrator-agent.js.map +1 -1
  80. package/dist/lib/quarantine.d.ts.map +1 -1
  81. package/dist/lib/quarantine.js +27 -5
  82. package/dist/lib/quarantine.js.map +1 -1
  83. package/dist/lib/request-snapshots.d.ts.map +1 -1
  84. package/dist/lib/request-snapshots.js +72 -9
  85. package/dist/lib/request-snapshots.js.map +1 -1
  86. package/dist/lib/rotation.d.ts.map +1 -1
  87. package/dist/lib/rotation.js +9 -9
  88. package/dist/lib/rotation.js.map +1 -1
  89. package/dist/lib/storage.d.ts.map +1 -1
  90. package/dist/lib/storage.js +38 -29
  91. package/dist/lib/storage.js.map +1 -1
  92. package/dist/lib/toast.d.ts.map +1 -1
  93. package/dist/lib/toast.js +7 -1
  94. package/dist/lib/toast.js.map +1 -1
  95. package/dist/lib/ui/auth-menu.d.ts.map +1 -1
  96. package/dist/lib/ui/auth-menu.js +4 -17
  97. package/dist/lib/ui/auth-menu.js.map +1 -1
  98. package/package.json +1 -1
  99. package/schemas/codex-config.schema.json +0 -4
  100. package/dist/lib/auth-refresh.d.ts +0 -2
  101. package/dist/lib/auth-refresh.d.ts.map +0 -1
  102. package/dist/lib/auth-refresh.js +0 -2
  103. package/dist/lib/auth-refresh.js.map +0 -1
  104. package/dist/lib/constants.d.ts +0 -2
  105. package/dist/lib/constants.d.ts.map +0 -1
  106. package/dist/lib/constants.js +0 -2
  107. package/dist/lib/constants.js.map +0 -1
  108. package/dist/lib/tools-output.d.ts +0 -6
  109. package/dist/lib/tools-output.d.ts.map +0 -1
  110. package/dist/lib/tools-output.js +0 -6
  111. package/dist/lib/tools-output.js.map +0 -1
@@ -1,7 +1,7 @@
1
1
  import { resolveInstructionsForModel } from "../model-catalog";
2
2
  import { sanitizeRequestPayloadForCompat } from "../compat-sanitizer";
3
3
  import { isRecord } from "../util";
4
- import { isOrchestratorInstructions } from "./collaboration";
4
+ import { isOrchestratorInstructions, replaceCodexToolCallsForOpenCode } from "./collaboration";
5
5
  function asString(value) {
6
6
  if (typeof value !== "string")
7
7
  return undefined;
@@ -318,70 +318,317 @@ export function applyCodexRuntimeDefaultsToParams(input) {
318
318
  }
319
319
  }
320
320
  export async function sanitizeOutboundRequestIfNeeded(request, enabled) {
321
- if (!enabled)
322
- return { request, changed: false };
323
- const method = request.method.toUpperCase();
324
- if (method !== "POST")
325
- return { request, changed: false };
326
- let payload;
327
- try {
328
- const raw = await request.clone().text();
329
- if (!raw)
330
- return { request, changed: false };
331
- payload = JSON.parse(raw);
321
+ const transformed = await transformOutboundRequestPayload({
322
+ request,
323
+ stripReasoningReplayEnabled: false,
324
+ remapDeveloperMessagesToUserEnabled: false,
325
+ compatInputSanitizerEnabled: enabled,
326
+ promptCacheKeyOverrideEnabled: false
327
+ });
328
+ return {
329
+ request: transformed.request,
330
+ changed: transformed.compatSanitizer.changed
331
+ };
332
+ }
333
+ function stripReasoningReplayFromPayload(payload) {
334
+ if (!Array.isArray(payload.input)) {
335
+ return {
336
+ changed: false,
337
+ reason: "missing_input_array",
338
+ removedPartCount: 0,
339
+ removedFieldCount: 0
340
+ };
332
341
  }
333
- catch (error) {
334
- if (!(error instanceof SyntaxError)) {
335
- // fall through with unchanged request on non-JSON payload parsing issues
342
+ let changed = false;
343
+ let removedPartCount = 0;
344
+ let removedFieldCount = 0;
345
+ const nextInput = [];
346
+ for (const item of payload.input) {
347
+ if (isReasoningReplayPart(item)) {
348
+ changed = true;
349
+ removedPartCount += 1;
350
+ continue;
351
+ }
352
+ if (!isRecord(item)) {
353
+ nextInput.push(item);
354
+ continue;
336
355
  }
337
- return { request, changed: false };
356
+ const nextItem = { ...item };
357
+ const role = asString(nextItem.role)?.toLowerCase();
358
+ if (role === "assistant" && Array.isArray(nextItem.content)) {
359
+ const contentOut = [];
360
+ for (const entry of nextItem.content) {
361
+ if (isReasoningReplayPart(entry)) {
362
+ changed = true;
363
+ removedPartCount += 1;
364
+ continue;
365
+ }
366
+ const strippedEntry = stripReasoningReplayFields(entry);
367
+ if (strippedEntry.removed > 0) {
368
+ changed = true;
369
+ removedFieldCount += strippedEntry.removed;
370
+ }
371
+ contentOut.push(strippedEntry.value);
372
+ }
373
+ nextItem.content = contentOut;
374
+ }
375
+ const strippedItem = stripReasoningReplayFields(nextItem);
376
+ if (strippedItem.removed > 0) {
377
+ changed = true;
378
+ removedFieldCount += strippedItem.removed;
379
+ }
380
+ nextInput.push(strippedItem.value);
338
381
  }
339
- if (!isRecord(payload))
340
- return { request, changed: false };
341
- const sanitized = sanitizeRequestPayloadForCompat(payload);
342
- if (!sanitized.changed)
343
- return { request, changed: false };
344
- const sanitizedRequest = rebuildRequestWithJsonBody(request, sanitized.payload);
345
- return { request: sanitizedRequest, changed: true };
382
+ if (!changed) {
383
+ return {
384
+ changed: false,
385
+ reason: "no_reasoning_replay",
386
+ removedPartCount,
387
+ removedFieldCount
388
+ };
389
+ }
390
+ payload.input = nextInput;
391
+ return {
392
+ changed: true,
393
+ reason: "updated",
394
+ removedPartCount,
395
+ removedFieldCount
396
+ };
346
397
  }
347
- export async function applyPromptCacheKeyOverrideToRequest(input) {
348
- if (!input.enabled) {
349
- return { request: input.request, changed: false, reason: "disabled" };
398
+ function remapDeveloperMessagesToUserOnPayload(payload) {
399
+ if (!Array.isArray(payload.input)) {
400
+ return {
401
+ changed: false,
402
+ reason: "missing_input_array",
403
+ remappedCount: 0,
404
+ preservedCount: 0
405
+ };
406
+ }
407
+ let nextInput;
408
+ let remappedCount = 0;
409
+ let preservedCount = 0;
410
+ let developerCount = 0;
411
+ for (let index = 0; index < payload.input.length; index += 1) {
412
+ const item = payload.input[index];
413
+ if (!isRecord(item))
414
+ continue;
415
+ if (item.role !== "developer")
416
+ continue;
417
+ developerCount += 1;
418
+ if (shouldPreserveDeveloperRole(item)) {
419
+ preservedCount += 1;
420
+ continue;
421
+ }
422
+ if (!nextInput)
423
+ nextInput = payload.input.slice();
424
+ nextInput[index] = {
425
+ ...item,
426
+ role: "user"
427
+ };
428
+ remappedCount += 1;
429
+ }
430
+ if (!nextInput) {
431
+ return {
432
+ changed: false,
433
+ reason: developerCount === 0 ? "no_developer_messages" : "permissions_only",
434
+ remappedCount,
435
+ preservedCount
436
+ };
350
437
  }
351
- const promptCacheKey = asString(input.promptCacheKey);
438
+ payload.input = nextInput;
439
+ return {
440
+ changed: true,
441
+ reason: "updated",
442
+ remappedCount,
443
+ preservedCount
444
+ };
445
+ }
446
+ function applyPromptCacheKeyOverrideToPayload(payload, promptCacheKey) {
352
447
  if (!promptCacheKey) {
353
- return { request: input.request, changed: false, reason: "missing_key" };
448
+ return { changed: false, reason: "missing_key" };
449
+ }
450
+ const current = asString(payload.prompt_cache_key);
451
+ if (current === promptCacheKey) {
452
+ return { changed: false, reason: "already_matches" };
354
453
  }
454
+ payload.prompt_cache_key = promptCacheKey;
455
+ return {
456
+ changed: true,
457
+ reason: current ? "replaced" : "set"
458
+ };
459
+ }
460
+ export async function transformOutboundRequestPayload(input) {
461
+ const disabledReplay = {
462
+ changed: false,
463
+ reason: "disabled",
464
+ removedPartCount: 0,
465
+ removedFieldCount: 0
466
+ };
467
+ const disabledRoleRemap = {
468
+ changed: false,
469
+ reason: "disabled",
470
+ remappedCount: 0,
471
+ preservedCount: 0
472
+ };
473
+ const disabledPromptCacheKey = {
474
+ changed: false,
475
+ reason: "disabled"
476
+ };
477
+ const disabledCompatSanitizer = {
478
+ changed: false,
479
+ reason: "disabled"
480
+ };
355
481
  const method = input.request.method.toUpperCase();
356
482
  if (method !== "POST") {
357
- return { request: input.request, changed: false, reason: "non_post" };
483
+ return {
484
+ request: input.request,
485
+ changed: false,
486
+ replay: input.stripReasoningReplayEnabled
487
+ ? { ...disabledReplay, reason: "non_post" }
488
+ : disabledReplay,
489
+ developerRoleRemap: input.remapDeveloperMessagesToUserEnabled
490
+ ? { ...disabledRoleRemap, reason: "non_post" }
491
+ : disabledRoleRemap,
492
+ promptCacheKey: input.promptCacheKeyOverrideEnabled
493
+ ? { ...disabledPromptCacheKey, reason: "non_post" }
494
+ : disabledPromptCacheKey,
495
+ compatSanitizer: input.compatInputSanitizerEnabled
496
+ ? { ...disabledCompatSanitizer, reason: "non_post" }
497
+ : disabledCompatSanitizer
498
+ };
499
+ }
500
+ let raw;
501
+ try {
502
+ raw = await input.request.clone().text();
503
+ }
504
+ catch {
505
+ return {
506
+ request: input.request,
507
+ changed: false,
508
+ replay: input.stripReasoningReplayEnabled
509
+ ? { ...disabledReplay, reason: "invalid_json" }
510
+ : disabledReplay,
511
+ developerRoleRemap: input.remapDeveloperMessagesToUserEnabled
512
+ ? { ...disabledRoleRemap, reason: "invalid_json" }
513
+ : disabledRoleRemap,
514
+ promptCacheKey: input.promptCacheKeyOverrideEnabled
515
+ ? { ...disabledPromptCacheKey, reason: "invalid_json" }
516
+ : disabledPromptCacheKey,
517
+ compatSanitizer: input.compatInputSanitizerEnabled
518
+ ? { ...disabledCompatSanitizer, reason: "invalid_json" }
519
+ : disabledCompatSanitizer
520
+ };
521
+ }
522
+ if (!raw) {
523
+ return {
524
+ request: input.request,
525
+ changed: false,
526
+ replay: input.stripReasoningReplayEnabled ? { ...disabledReplay, reason: "empty_body" } : disabledReplay,
527
+ developerRoleRemap: input.remapDeveloperMessagesToUserEnabled
528
+ ? { ...disabledRoleRemap, reason: "empty_body" }
529
+ : disabledRoleRemap,
530
+ promptCacheKey: input.promptCacheKeyOverrideEnabled
531
+ ? { ...disabledPromptCacheKey, reason: "empty_body" }
532
+ : disabledPromptCacheKey,
533
+ compatSanitizer: input.compatInputSanitizerEnabled
534
+ ? { ...disabledCompatSanitizer, reason: "empty_body" }
535
+ : disabledCompatSanitizer
536
+ };
358
537
  }
359
538
  let payload;
360
539
  try {
361
- const raw = await input.request.clone().text();
362
- if (!raw)
363
- return { request: input.request, changed: false, reason: "empty_body" };
364
540
  payload = JSON.parse(raw);
365
541
  }
366
- catch (error) {
367
- if (!(error instanceof SyntaxError)) {
368
- // request body could not be parsed as JSON
369
- }
370
- return { request: input.request, changed: false, reason: "invalid_json" };
542
+ catch {
543
+ return {
544
+ request: input.request,
545
+ changed: false,
546
+ replay: input.stripReasoningReplayEnabled
547
+ ? { ...disabledReplay, reason: "invalid_json" }
548
+ : disabledReplay,
549
+ developerRoleRemap: input.remapDeveloperMessagesToUserEnabled
550
+ ? { ...disabledRoleRemap, reason: "invalid_json" }
551
+ : disabledRoleRemap,
552
+ promptCacheKey: input.promptCacheKeyOverrideEnabled
553
+ ? { ...disabledPromptCacheKey, reason: "invalid_json" }
554
+ : disabledPromptCacheKey,
555
+ compatSanitizer: input.compatInputSanitizerEnabled
556
+ ? { ...disabledCompatSanitizer, reason: "invalid_json" }
557
+ : disabledCompatSanitizer
558
+ };
371
559
  }
372
560
  if (!isRecord(payload)) {
373
- return { request: input.request, changed: false, reason: "non_object_body" };
561
+ return {
562
+ request: input.request,
563
+ changed: false,
564
+ replay: input.stripReasoningReplayEnabled
565
+ ? { ...disabledReplay, reason: "non_object_body" }
566
+ : disabledReplay,
567
+ developerRoleRemap: input.remapDeveloperMessagesToUserEnabled
568
+ ? { ...disabledRoleRemap, reason: "non_object_body" }
569
+ : disabledRoleRemap,
570
+ promptCacheKey: input.promptCacheKeyOverrideEnabled
571
+ ? { ...disabledPromptCacheKey, reason: "non_object_body" }
572
+ : disabledPromptCacheKey,
573
+ compatSanitizer: input.compatInputSanitizerEnabled
574
+ ? { ...disabledCompatSanitizer, reason: "non_object_body" }
575
+ : disabledCompatSanitizer
576
+ };
374
577
  }
375
- const current = asString(payload.prompt_cache_key);
376
- if (current === promptCacheKey) {
377
- return { request: input.request, changed: false, reason: "already_matches" };
578
+ let changed = false;
579
+ const replay = input.stripReasoningReplayEnabled
580
+ ? stripReasoningReplayFromPayload(payload)
581
+ : disabledReplay;
582
+ changed = changed || replay.changed;
583
+ const developerRoleRemap = input.remapDeveloperMessagesToUserEnabled
584
+ ? remapDeveloperMessagesToUserOnPayload(payload)
585
+ : disabledRoleRemap;
586
+ changed = changed || developerRoleRemap.changed;
587
+ const promptCacheKey = input.promptCacheKeyOverrideEnabled
588
+ ? applyPromptCacheKeyOverrideToPayload(payload, asString(input.promptCacheKeyOverride))
589
+ : disabledPromptCacheKey;
590
+ changed = changed || promptCacheKey.changed;
591
+ const compatSanitizedPayload = input.compatInputSanitizerEnabled ? sanitizeRequestPayloadForCompat(payload) : null;
592
+ const compatSanitizer = input.compatInputSanitizerEnabled
593
+ ? {
594
+ changed: compatSanitizedPayload?.changed === true,
595
+ reason: compatSanitizedPayload?.changed === true ? "updated" : "already_matches"
596
+ }
597
+ : disabledCompatSanitizer;
598
+ const finalPayload = compatSanitizedPayload?.payload ?? payload;
599
+ changed = changed || compatSanitizer.changed;
600
+ if (!changed) {
601
+ return {
602
+ request: input.request,
603
+ changed: false,
604
+ replay,
605
+ developerRoleRemap,
606
+ promptCacheKey,
607
+ compatSanitizer
608
+ };
378
609
  }
379
- payload.prompt_cache_key = promptCacheKey;
380
- const updatedRequest = rebuildRequestWithJsonBody(input.request, payload);
381
610
  return {
382
- request: updatedRequest,
611
+ request: rebuildRequestWithJsonBody(input.request, finalPayload),
383
612
  changed: true,
384
- reason: current ? "replaced" : "set"
613
+ replay,
614
+ developerRoleRemap,
615
+ promptCacheKey,
616
+ compatSanitizer
617
+ };
618
+ }
619
+ export async function applyPromptCacheKeyOverrideToRequest(input) {
620
+ const transformed = await transformOutboundRequestPayload({
621
+ request: input.request,
622
+ stripReasoningReplayEnabled: false,
623
+ remapDeveloperMessagesToUserEnabled: false,
624
+ compatInputSanitizerEnabled: false,
625
+ promptCacheKeyOverrideEnabled: input.enabled,
626
+ promptCacheKeyOverride: input.promptCacheKey
627
+ });
628
+ return {
629
+ request: transformed.request,
630
+ changed: transformed.promptCacheKey.changed,
631
+ reason: transformed.promptCacheKey.reason
385
632
  };
386
633
  }
387
634
  function rebuildRequestWithJsonBody(request, body) {
@@ -425,109 +672,19 @@ function shouldPreserveDeveloperRole(item) {
425
672
  text.includes("filesystem sandboxing defines which files can be read or written"));
426
673
  }
427
674
  export async function remapDeveloperMessagesToUserOnRequest(input) {
428
- if (!input.enabled) {
429
- return {
430
- request: input.request,
431
- changed: false,
432
- reason: "disabled",
433
- remappedCount: 0,
434
- preservedCount: 0
435
- };
436
- }
437
- const method = input.request.method.toUpperCase();
438
- if (method !== "POST") {
439
- return {
440
- request: input.request,
441
- changed: false,
442
- reason: "non_post",
443
- remappedCount: 0,
444
- preservedCount: 0
445
- };
446
- }
447
- let payload;
448
- try {
449
- const raw = await input.request.clone().text();
450
- if (!raw) {
451
- return {
452
- request: input.request,
453
- changed: false,
454
- reason: "empty_body",
455
- remappedCount: 0,
456
- preservedCount: 0
457
- };
458
- }
459
- payload = JSON.parse(raw);
460
- }
461
- catch (error) {
462
- if (!(error instanceof SyntaxError)) {
463
- // request body could not be parsed as JSON
464
- }
465
- return {
466
- request: input.request,
467
- changed: false,
468
- reason: "invalid_json",
469
- remappedCount: 0,
470
- preservedCount: 0
471
- };
472
- }
473
- if (!isRecord(payload)) {
474
- return {
475
- request: input.request,
476
- changed: false,
477
- reason: "non_object_body",
478
- remappedCount: 0,
479
- preservedCount: 0
480
- };
481
- }
482
- if (!Array.isArray(payload.input)) {
483
- return {
484
- request: input.request,
485
- changed: false,
486
- reason: "missing_input_array",
487
- remappedCount: 0,
488
- preservedCount: 0
489
- };
490
- }
491
- let nextInput;
492
- let remappedCount = 0;
493
- let preservedCount = 0;
494
- let developerCount = 0;
495
- for (let index = 0; index < payload.input.length; index += 1) {
496
- const item = payload.input[index];
497
- if (!isRecord(item))
498
- continue;
499
- if (item.role !== "developer")
500
- continue;
501
- developerCount += 1;
502
- if (shouldPreserveDeveloperRole(item)) {
503
- preservedCount += 1;
504
- continue;
505
- }
506
- if (!nextInput)
507
- nextInput = payload.input.slice();
508
- nextInput[index] = {
509
- ...item,
510
- role: "user"
511
- };
512
- remappedCount += 1;
513
- }
514
- if (!nextInput) {
515
- return {
516
- request: input.request,
517
- changed: false,
518
- reason: developerCount === 0 ? "no_developer_messages" : "permissions_only",
519
- remappedCount,
520
- preservedCount
521
- };
522
- }
523
- payload.input = nextInput;
524
- const updatedRequest = rebuildRequestWithJsonBody(input.request, payload);
675
+ const transformed = await transformOutboundRequestPayload({
676
+ request: input.request,
677
+ stripReasoningReplayEnabled: false,
678
+ remapDeveloperMessagesToUserEnabled: input.enabled,
679
+ compatInputSanitizerEnabled: false,
680
+ promptCacheKeyOverrideEnabled: false
681
+ });
525
682
  return {
526
- request: updatedRequest,
527
- changed: true,
528
- reason: "updated",
529
- remappedCount,
530
- preservedCount
683
+ request: transformed.request,
684
+ changed: transformed.developerRoleRemap.changed,
685
+ reason: transformed.developerRoleRemap.reason,
686
+ remappedCount: transformed.developerRoleRemap.remappedCount,
687
+ preservedCount: transformed.developerRoleRemap.preservedCount
531
688
  };
532
689
  }
533
690
  function stripReasoningReplayFields(value) {
@@ -565,126 +722,19 @@ function isReasoningReplayPart(entry) {
565
722
  return type.startsWith("reasoning");
566
723
  }
567
724
  export async function stripReasoningReplayFromRequest(input) {
568
- if (!input.enabled) {
569
- return {
570
- request: input.request,
571
- changed: false,
572
- reason: "disabled",
573
- removedPartCount: 0,
574
- removedFieldCount: 0
575
- };
576
- }
577
- const method = input.request.method.toUpperCase();
578
- if (method !== "POST") {
579
- return {
580
- request: input.request,
581
- changed: false,
582
- reason: "non_post",
583
- removedPartCount: 0,
584
- removedFieldCount: 0
585
- };
586
- }
587
- let payload;
588
- try {
589
- const raw = await input.request.clone().text();
590
- if (!raw) {
591
- return {
592
- request: input.request,
593
- changed: false,
594
- reason: "empty_body",
595
- removedPartCount: 0,
596
- removedFieldCount: 0
597
- };
598
- }
599
- payload = JSON.parse(raw);
600
- }
601
- catch (error) {
602
- if (!(error instanceof SyntaxError)) {
603
- // request body could not be parsed as JSON
604
- }
605
- return {
606
- request: input.request,
607
- changed: false,
608
- reason: "invalid_json",
609
- removedPartCount: 0,
610
- removedFieldCount: 0
611
- };
612
- }
613
- if (!isRecord(payload)) {
614
- return {
615
- request: input.request,
616
- changed: false,
617
- reason: "non_object_body",
618
- removedPartCount: 0,
619
- removedFieldCount: 0
620
- };
621
- }
622
- if (!Array.isArray(payload.input)) {
623
- return {
624
- request: input.request,
625
- changed: false,
626
- reason: "missing_input_array",
627
- removedPartCount: 0,
628
- removedFieldCount: 0
629
- };
630
- }
631
- let changed = false;
632
- let removedPartCount = 0;
633
- let removedFieldCount = 0;
634
- const nextInput = [];
635
- for (const item of payload.input) {
636
- if (isReasoningReplayPart(item)) {
637
- changed = true;
638
- removedPartCount += 1;
639
- continue;
640
- }
641
- if (!isRecord(item)) {
642
- nextInput.push(item);
643
- continue;
644
- }
645
- const nextItem = { ...item };
646
- const role = asString(nextItem.role)?.toLowerCase();
647
- if (role === "assistant" && Array.isArray(nextItem.content)) {
648
- const contentOut = [];
649
- for (const entry of nextItem.content) {
650
- if (isReasoningReplayPart(entry)) {
651
- changed = true;
652
- removedPartCount += 1;
653
- continue;
654
- }
655
- const strippedEntry = stripReasoningReplayFields(entry);
656
- if (strippedEntry.removed > 0) {
657
- changed = true;
658
- removedFieldCount += strippedEntry.removed;
659
- }
660
- contentOut.push(strippedEntry.value);
661
- }
662
- nextItem.content = contentOut;
663
- }
664
- const strippedItem = stripReasoningReplayFields(nextItem);
665
- if (strippedItem.removed > 0) {
666
- changed = true;
667
- removedFieldCount += strippedItem.removed;
668
- }
669
- nextInput.push(strippedItem.value);
670
- }
671
- if (!changed) {
672
- return {
673
- request: input.request,
674
- changed: false,
675
- reason: "no_reasoning_replay",
676
- removedPartCount,
677
- removedFieldCount
678
- };
679
- }
680
- payload.input = nextInput;
681
- const updatedRequest = rebuildRequestWithJsonBody(input.request, payload);
725
+ const transformed = await transformOutboundRequestPayload({
726
+ request: input.request,
727
+ stripReasoningReplayEnabled: input.enabled,
728
+ remapDeveloperMessagesToUserEnabled: false,
729
+ compatInputSanitizerEnabled: false,
730
+ promptCacheKeyOverrideEnabled: false
731
+ });
682
732
  return {
683
- request: updatedRequest,
684
- changed: true,
685
- reason: "updated",
686
- removedPartCount,
687
- removedFieldCount
733
+ request: transformed.request,
734
+ changed: transformed.replay.changed,
735
+ reason: transformed.replay.reason,
736
+ removedPartCount: transformed.replay.removedPartCount,
737
+ removedFieldCount: transformed.replay.removedFieldCount
688
738
  };
689
739
  }
690
740
  function getVariantCandidatesFromBody(input) {
@@ -768,19 +818,21 @@ export async function applyCatalogInstructionOverrideToRequest(input) {
768
818
  const rendered = resolveInstructionsForModel(catalogModel, effectivePersonality);
769
819
  if (!rendered)
770
820
  return { request: input.request, changed: false, reason: "rendered_empty_or_unsafe" };
821
+ const renderedForRequest = input.replaceCodexToolCalls === true ? replaceCodexToolCallsForOpenCode(rendered) ?? rendered : rendered;
771
822
  const currentInstructions = asString(payload.instructions);
772
823
  const preserveOrchestratorInstructions = input.preserveOrchestratorInstructions !== false;
773
824
  if (preserveOrchestratorInstructions && isOrchestratorInstructions(currentInstructions)) {
774
825
  return { request: input.request, changed: false, reason: "orchestrator_instructions_preserved" };
775
826
  }
776
- if (currentInstructions === rendered) {
827
+ if (currentInstructions === renderedForRequest) {
777
828
  return { request: input.request, changed: false, reason: "already_matches" };
778
829
  }
779
- if (currentInstructions && currentInstructions.includes(rendered)) {
830
+ if (currentInstructions && currentInstructions.includes(renderedForRequest)) {
780
831
  return { request: input.request, changed: false, reason: "already_contains_rendered" };
781
832
  }
782
833
  const collaborationTail = currentInstructions ? extractCollaborationInstructionTail(currentInstructions) : undefined;
783
- const nextInstructions = collaborationTail ? `${rendered}\n\n${collaborationTail}` : rendered;
834
+ const nextInstructionsBase = collaborationTail ? `${renderedForRequest}\n\n${collaborationTail}` : renderedForRequest;
835
+ const nextInstructions = nextInstructionsBase;
784
836
  if (currentInstructions === nextInstructions) {
785
837
  return { request: input.request, changed: false, reason: "already_matches" };
786
838
  }