File size: 3,306 Bytes
df23150
 
 
 
 
 
 
 
 
 
e772221
 
 
c2a5120
 
 
 
 
 
 
 
 
 
e772221
 
 
 
 
 
 
 
 
 
c2a5120
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
df23150
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
e772221
 
 
 
df23150
 
 
 
e772221
 
 
 
 
 
 
 
df23150
e772221
 
 
 
 
 
 
 
 
 
df23150
 
e772221
 
c2a5120
e772221
 
 
 
 
 
 
df23150
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
import {
  PROVIDER_BINDING_KEY,
  SUPPORTED_ADAPTER_TYPES,
} from "../constants.js";
import type { GlobalProviderRecord } from "../types.js";

type EnvBinding =
  | { type: "plain"; value: string }
  | { type: "secret_ref"; secretId: string; version?: number | "latest" };

function buildCodexBaseUrlOverrides(baseUrl: string): string[] {
  const encodedBaseUrl = JSON.stringify(baseUrl);
  return [
    "-c",
    'model_provider="custom"',
    "-c",
    'model_providers.custom.name="custom"',
    "-c",
    'model_providers.custom.wire_api="responses"',
    "-c",
    "model_providers.custom.requires_openai_auth=true",
    "-c",
    `model_providers.custom.base_url=${encodedBaseUrl}`,
    "-c",
    `openai_base_url=${encodedBaseUrl}`,
  ];
}

function readStringArray(value: unknown): string[] {
  if (!Array.isArray(value)) return [];
  return value.filter((entry): entry is string => typeof entry === "string" && entry.trim().length > 0);
}

function stripManagedCodexProviderArgs(args: string[]): string[] {
  const managedPatterns = [
    /^model_provider=/,
    /^model_providers\.custom\./,
    /^openai_base_url=/,
  ];

  const next: string[] = [];
  for (let index = 0; index < args.length; index += 1) {
    const current = args[index]?.trim();
    const following = args[index + 1]?.trim();
    if (current === "-c" && following && managedPatterns.some((pattern) => pattern.test(following))) {
      index += 1;
      continue;
    }
    next.push(args[index]!);
  }
  return next;
}

function asEnvRecord(value: unknown): Record<string, EnvBinding> {
  if (!value || typeof value !== "object" || Array.isArray(value)) return {};
  return value as Record<string, EnvBinding>;
}

export function isSupportedAdapterType(adapterType: string): boolean {
  return SUPPORTED_ADAPTER_TYPES.includes(adapterType as (typeof SUPPORTED_ADAPTER_TYPES)[number]);
}

export function buildOpenAiAgentPatch(input: {
  adapterType: string;
  currentAdapterConfig?: Record<string, unknown> | null;
  provider: Pick<GlobalProviderRecord, "id" | "name" | "baseUrl">;
  apiKey: string;
  model: string;
  syncedAt: string;
}) {
  const current = { ...(input.currentAdapterConfig ?? {}) };
  const env = { ...asEnvRecord(current.env) };
  env.OPENAI_API_KEY = {
    type: "plain",
    value: input.apiKey,
  };
  env.CODEX_API_KEY = {
    type: "plain",
    value: input.apiKey,
  };
  env.OPENAI_BASE_URL = {
    type: "plain",
    value: input.provider.baseUrl,
  };
  env.OPENAI_API_BASE = {
    type: "plain",
    value: input.provider.baseUrl,
  };
  env.OPENAI_API_BASE_URL = {
    type: "plain",
    value: input.provider.baseUrl,
  };

  const nextConfig: Record<string, unknown> = {
    ...current,
    model: input.model,
    env,
    [PROVIDER_BINDING_KEY]: {
      providerId: input.provider.id,
      providerName: input.provider.name,
      providerBaseUrl: input.provider.baseUrl,
      managedByPlugin: true,
      syncedAt: input.syncedAt,
    },
  };

  if (input.adapterType === "codex_local") {
    const existingExtraArgs = stripManagedCodexProviderArgs(readStringArray(current.extraArgs));
    const overrideArgs = buildCodexBaseUrlOverrides(input.provider.baseUrl);
    nextConfig.extraArgs = [...existingExtraArgs, ...overrideArgs];
  }

  return {
    adapterConfig: nextConfig,
  };
}