@iam-brain/opencode-codex-auth 1.1.0 → 1.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (122) hide show
  1. package/README.md +16 -14
  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 -11
  28. package/dist/lib/codex-native/chat-hooks.js.map +1 -1
  29. package/dist/lib/codex-native/collaboration.d.ts +2 -4
  30. package/dist/lib/codex-native/collaboration.d.ts.map +1 -1
  31. package/dist/lib/codex-native/collaboration.js +21 -35
  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 +67 -12
  38. package/dist/lib/codex-native/oauth-server.js.map +1 -1
  39. package/dist/lib/codex-native/oauth-utils.js +1 -1
  40. package/dist/lib/codex-native/oauth-utils.js.map +1 -1
  41. package/dist/lib/codex-native/openai-loader-fetch.d.ts.map +1 -1
  42. package/dist/lib/codex-native/openai-loader-fetch.js +109 -78
  43. package/dist/lib/codex-native/openai-loader-fetch.js.map +1 -1
  44. package/dist/lib/codex-native/request-routing.d.ts.map +1 -1
  45. package/dist/lib/codex-native/request-routing.js +19 -4
  46. package/dist/lib/codex-native/request-routing.js.map +1 -1
  47. package/dist/lib/codex-native/request-transform-pipeline.d.ts +9 -2
  48. package/dist/lib/codex-native/request-transform-pipeline.d.ts.map +1 -1
  49. package/dist/lib/codex-native/request-transform-pipeline.js +11 -7
  50. package/dist/lib/codex-native/request-transform-pipeline.js.map +1 -1
  51. package/dist/lib/codex-native/request-transform.d.ts +39 -0
  52. package/dist/lib/codex-native/request-transform.d.ts.map +1 -1
  53. package/dist/lib/codex-native/request-transform.js +321 -276
  54. package/dist/lib/codex-native/request-transform.js.map +1 -1
  55. package/dist/lib/codex-native.d.ts +0 -2
  56. package/dist/lib/codex-native.d.ts.map +1 -1
  57. package/dist/lib/codex-native.js +5 -6
  58. package/dist/lib/codex-native.js.map +1 -1
  59. package/dist/lib/codex-status-storage.d.ts.map +1 -1
  60. package/dist/lib/codex-status-storage.js +3 -0
  61. package/dist/lib/codex-status-storage.js.map +1 -1
  62. package/dist/lib/config-dir-gitignore.d.ts +1 -1
  63. package/dist/lib/config-dir-gitignore.d.ts.map +1 -1
  64. package/dist/lib/config-dir-gitignore.js +2 -0
  65. package/dist/lib/config-dir-gitignore.js.map +1 -1
  66. package/dist/lib/config.d.ts +0 -3
  67. package/dist/lib/config.d.ts.map +1 -1
  68. package/dist/lib/config.js +9 -31
  69. package/dist/lib/config.js.map +1 -1
  70. package/dist/lib/fetch-orchestrator.d.ts +3 -0
  71. package/dist/lib/fetch-orchestrator.d.ts.map +1 -1
  72. package/dist/lib/fetch-orchestrator.js +33 -3
  73. package/dist/lib/fetch-orchestrator.js.map +1 -1
  74. package/dist/lib/installer-cli.js +1 -1
  75. package/dist/lib/installer-cli.js.map +1 -1
  76. package/dist/lib/model-catalog.d.ts.map +1 -1
  77. package/dist/lib/model-catalog.js +44 -27
  78. package/dist/lib/model-catalog.js.map +1 -1
  79. package/dist/lib/oauth-pages.d.ts +1 -1
  80. package/dist/lib/oauth-pages.d.ts.map +1 -1
  81. package/dist/lib/oauth-pages.js +6 -1
  82. package/dist/lib/oauth-pages.js.map +1 -1
  83. package/dist/lib/orchestrator-agent.d.ts.map +1 -1
  84. package/dist/lib/orchestrator-agent.js +3 -1
  85. package/dist/lib/orchestrator-agent.js.map +1 -1
  86. package/dist/lib/paths.d.ts +4 -1
  87. package/dist/lib/paths.d.ts.map +1 -1
  88. package/dist/lib/paths.js +11 -2
  89. package/dist/lib/paths.js.map +1 -1
  90. package/dist/lib/quarantine.d.ts.map +1 -1
  91. package/dist/lib/quarantine.js +27 -5
  92. package/dist/lib/quarantine.js.map +1 -1
  93. package/dist/lib/request-snapshots.d.ts.map +1 -1
  94. package/dist/lib/request-snapshots.js +177 -13
  95. package/dist/lib/request-snapshots.js.map +1 -1
  96. package/dist/lib/rotation.d.ts.map +1 -1
  97. package/dist/lib/rotation.js +9 -9
  98. package/dist/lib/rotation.js.map +1 -1
  99. package/dist/lib/storage.d.ts.map +1 -1
  100. package/dist/lib/storage.js +47 -31
  101. package/dist/lib/storage.js.map +1 -1
  102. package/dist/lib/toast.d.ts.map +1 -1
  103. package/dist/lib/toast.js +7 -1
  104. package/dist/lib/toast.js.map +1 -1
  105. package/dist/lib/ui/auth-menu.d.ts.map +1 -1
  106. package/dist/lib/ui/auth-menu.js +4 -17
  107. package/dist/lib/ui/auth-menu.js.map +1 -1
  108. package/package.json +1 -1
  109. package/schemas/codex-accounts.schema.json +1 -1
  110. package/schemas/codex-config.schema.json +0 -4
  111. package/dist/lib/auth-refresh.d.ts +0 -2
  112. package/dist/lib/auth-refresh.d.ts.map +0 -1
  113. package/dist/lib/auth-refresh.js +0 -2
  114. package/dist/lib/auth-refresh.js.map +0 -1
  115. package/dist/lib/constants.d.ts +0 -2
  116. package/dist/lib/constants.d.ts.map +0 -1
  117. package/dist/lib/constants.js +0 -2
  118. package/dist/lib/constants.js.map +0 -1
  119. package/dist/lib/tools-output.d.ts +0 -6
  120. package/dist/lib/tools-output.d.ts.map +0 -1
  121. package/dist/lib/tools-output.js +0 -6
  122. 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 { ensureOpenCodeToolingCompatibility, 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;
355
+ }
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;
336
379
  }
337
- return { request, changed: false };
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
+ };
350
406
  }
351
- const promptCacheKey = asString(input.promptCacheKey);
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
+ };
437
+ }
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" };
354
449
  }
450
+ const current = asString(payload.prompt_cache_key);
451
+ if (current === promptCacheKey) {
452
+ return { changed: false, reason: "already_matches" };
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,26 +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
- const compatible = ensureOpenCodeToolingCompatibility(currentInstructions);
775
- if (compatible && compatible.trim() !== (currentInstructions?.trim() ?? "")) {
776
- payload.instructions = compatible;
777
- const updatedRequest = rebuildRequestWithJsonBody(input.request, payload);
778
- return { request: updatedRequest, changed: true, reason: "tooling_compatibility_added" };
779
- }
780
825
  return { request: input.request, changed: false, reason: "orchestrator_instructions_preserved" };
781
826
  }
782
- if (currentInstructions === rendered) {
827
+ if (currentInstructions === renderedForRequest) {
783
828
  return { request: input.request, changed: false, reason: "already_matches" };
784
829
  }
785
- if (currentInstructions && currentInstructions.includes(rendered)) {
830
+ if (currentInstructions && currentInstructions.includes(renderedForRequest)) {
786
831
  return { request: input.request, changed: false, reason: "already_contains_rendered" };
787
832
  }
788
833
  const collaborationTail = currentInstructions ? extractCollaborationInstructionTail(currentInstructions) : undefined;
789
- const nextInstructionsBase = collaborationTail ? `${rendered}\n\n${collaborationTail}` : rendered;
790
- const nextInstructions = ensureOpenCodeToolingCompatibility(nextInstructionsBase) ?? nextInstructionsBase;
834
+ const nextInstructionsBase = collaborationTail ? `${renderedForRequest}\n\n${collaborationTail}` : renderedForRequest;
835
+ const nextInstructions = nextInstructionsBase;
791
836
  if (currentInstructions === nextInstructions) {
792
837
  return { request: input.request, changed: false, reason: "already_matches" };
793
838
  }