@centerforagenticai/pi-multi-account 0.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.
- package/LICENSE +21 -0
- package/NOTICE +29 -0
- package/README.md +999 -0
- package/config/models/pi-multi-account.v1.json +32 -0
- package/config/subscription-plans.v1.json +122 -0
- package/package.json +76 -0
- package/packages/pi-anthropic-oauth/LICENSE +21 -0
- package/packages/pi-anthropic-oauth/package.json +54 -0
- package/packages/pi-anthropic-oauth/src/auth.ts +396 -0
- package/packages/pi-anthropic-oauth/src/context.ts +116 -0
- package/packages/pi-anthropic-oauth/src/convert.ts +303 -0
- package/packages/pi-anthropic-oauth/src/index.ts +37 -0
- package/packages/pi-anthropic-oauth/src/prompt.ts +137 -0
- package/packages/pi-anthropic-oauth/src/stream.ts +476 -0
- package/packages/pi-antigravity/LICENSE +21 -0
- package/packages/pi-antigravity/package.json +77 -0
- package/packages/pi-antigravity/src/auth/index.ts +14 -0
- package/packages/pi-antigravity/src/auth/oauth.ts +442 -0
- package/packages/pi-antigravity/src/client/client.ts +561 -0
- package/packages/pi-antigravity/src/client/index.ts +1 -0
- package/packages/pi-antigravity/src/context.ts +110 -0
- package/packages/pi-antigravity/src/diagnostics/diagnostics.ts +96 -0
- package/packages/pi-antigravity/src/diagnostics/index.ts +1 -0
- package/packages/pi-antigravity/src/image/image.ts +336 -0
- package/packages/pi-antigravity/src/image/index.ts +1 -0
- package/packages/pi-antigravity/src/index.ts +280 -0
- package/packages/pi-antigravity/src/models/discovery.ts +154 -0
- package/packages/pi-antigravity/src/models/grouping.ts +424 -0
- package/packages/pi-antigravity/src/models/index.ts +3 -0
- package/packages/pi-antigravity/src/models/models.ts +500 -0
- package/packages/pi-antigravity/src/stream/index.ts +1 -0
- package/packages/pi-antigravity/src/stream/stream.ts +1478 -0
- package/packages/pi-antigravity/src/types/enums.ts +42 -0
- package/packages/pi-antigravity/src/types/index.ts +2 -0
- package/packages/pi-antigravity/src/types/types.ts +292 -0
- package/packages/pi-antigravity/src/usage/index.ts +1 -0
- package/packages/pi-antigravity/src/usage/usage.ts +416 -0
- package/packages/pi-antigravity/src/utils/http.ts +91 -0
- package/packages/pi-antigravity/src/utils/index.ts +3 -0
- package/packages/pi-antigravity/src/utils/security.ts +73 -0
- package/packages/pi-antigravity/src/utils/util.ts +132 -0
- package/scripts/multi-account.mjs +44 -0
- package/src/account-labels.ts +223 -0
- package/src/account-plan-assignment.ts +340 -0
- package/src/account-rate-history.ts +372 -0
- package/src/anthropic-adaptive-stream.ts +531 -0
- package/src/anthropic-alias-stream.ts +140 -0
- package/src/anthropic-context-compat.ts +80 -0
- package/src/api-pricing.ts +579 -0
- package/src/bounded-file-lines.ts +97 -0
- package/src/catalog-rebinding.ts +177 -0
- package/src/catalog-registration-probe.ts +111 -0
- package/src/codex-adapter.ts +345 -0
- package/src/codex-model-defaults.ts +785 -0
- package/src/command-completions.ts +404 -0
- package/src/commands.ts +2000 -0
- package/src/compaction.ts +14 -0
- package/src/config.ts +1317 -0
- package/src/continuation.ts +569 -0
- package/src/cooldowns.ts +110 -0
- package/src/cost-digest-store.ts +332 -0
- package/src/cost-digest.ts +1044 -0
- package/src/cost-history.ts +251 -0
- package/src/cost-period-closer.ts +160 -0
- package/src/cost-report-json.ts +318 -0
- package/src/cost-report-reader.ts +368 -0
- package/src/cost-report-render.ts +207 -0
- package/src/cost-report.ts +1104 -0
- package/src/coverage-attestation.ts +397 -0
- package/src/credential-lifecycle.ts +169 -0
- package/src/credential-refresh.ts +248 -0
- package/src/declaration-notice-marker.ts +238 -0
- package/src/diagnostic-store.ts +276 -0
- package/src/diagnostics.ts +309 -0
- package/src/discovery.ts +471 -0
- package/src/duration.ts +13 -0
- package/src/error-classification.ts +256 -0
- package/src/fuzzy.ts +15 -0
- package/src/group-policy.ts +81 -0
- package/src/history-store.ts +897 -0
- package/src/index.ts +5572 -0
- package/src/lifecycle.ts +378 -0
- package/src/logical-dispatch.ts +279 -0
- package/src/logical-model-selector.ts +254 -0
- package/src/logical-model-switcher.ts +430 -0
- package/src/logical-provider-attribution.ts +544 -0
- package/src/logical-provider.ts +1237 -0
- package/src/logical-route-indicator.ts +215 -0
- package/src/machine-lease.ts +445 -0
- package/src/model-support.ts +66 -0
- package/src/models-declaration.ts +1091 -0
- package/src/openai-adapter.ts +117 -0
- package/src/openrouter-budget.ts +304 -0
- package/src/openrouter-fallback.ts +146 -0
- package/src/period-boundaries.ts +376 -0
- package/src/pi-anthropic-oauth.d.ts +6 -0
- package/src/preflight.ts +253 -0
- package/src/pricing-cache.ts +235 -0
- package/src/project-identity.ts +100 -0
- package/src/provider-registration.ts +942 -0
- package/src/rate-formula.ts +163 -0
- package/src/recovery-engine.ts +853 -0
- package/src/recovery-output.ts +837 -0
- package/src/recovery-plan.ts +239 -0
- package/src/report-range.ts +203 -0
- package/src/route-resolver.ts +789 -0
- package/src/routing-config-transaction.ts +232 -0
- package/src/routing.ts +1163 -0
- package/src/runtime-state.ts +630 -0
- package/src/session-account-groups.ts +284 -0
- package/src/session-restore.ts +287 -0
- package/src/shared-usage.ts +1392 -0
- package/src/standalone-cli.ts +720 -0
- package/src/status-view.ts +578 -0
- package/src/subscription-plan-catalog.ts +346 -0
- package/src/tier-model-resolver.ts +46 -0
- package/src/upstream-anthropic.ts +315 -0
- package/src/upstream-antigravity.ts +327 -0
- package/src/usage-fetch.ts +1634 -0
- package/src/usage.ts +1026 -0
- package/src/vendor.ts +87 -0
- package/src/warmer.ts +231 -0
- package/src/watchdog.ts +219 -0
- package/src/window-history.ts +270 -0
|
@@ -0,0 +1,345 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Codex base and alias provider registration via Pi's maintained
|
|
3
|
+
* openai-codex-responses stream and OAuth callbacks (REQ-CODEX-1).
|
|
4
|
+
*
|
|
5
|
+
* No local transport or refresh flow is implemented. Alias handling is a
|
|
6
|
+
* bounded identity adapter: Pi resolves the alias credential first, then the
|
|
7
|
+
* adapter presents base Codex identity to the maintained stream, normalizes
|
|
8
|
+
* same-alias history for reasoning/tool continuation, and restores alias
|
|
9
|
+
* attribution on emitted events and callbacks.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import type {
|
|
13
|
+
ExtensionAPI,
|
|
14
|
+
ProviderConfig,
|
|
15
|
+
ProviderModelConfig,
|
|
16
|
+
} from "@earendil-works/pi-coding-agent";
|
|
17
|
+
import {
|
|
18
|
+
createAssistantMessageEventStream,
|
|
19
|
+
type Api,
|
|
20
|
+
type AssistantMessage,
|
|
21
|
+
type AssistantMessageEvent,
|
|
22
|
+
type AssistantMessageEventStream,
|
|
23
|
+
type Context,
|
|
24
|
+
type Model,
|
|
25
|
+
type ProviderResponse,
|
|
26
|
+
type SimpleStreamOptions,
|
|
27
|
+
} from "@earendil-works/pi-ai";
|
|
28
|
+
import { cloneProviderModelCatalog } from "./catalog-rebinding.js";
|
|
29
|
+
import {
|
|
30
|
+
sanitizeDiagnosticText,
|
|
31
|
+
sanitizeHeaderValue,
|
|
32
|
+
} from "./diagnostics.js";
|
|
33
|
+
|
|
34
|
+
const CODEX_BASE_API = "openai-codex-responses" as const;
|
|
35
|
+
/**
|
|
36
|
+
* Keep alias models on Pi's host-known API id. The provider-scoped
|
|
37
|
+
* `streamSimple` adapter still wins normal dispatch, while direct helpers such
|
|
38
|
+
* as compaction and delegate startup can resolve the built-in handler before
|
|
39
|
+
* extension composition is available.
|
|
40
|
+
*/
|
|
41
|
+
export const CODEX_ALIAS_API = CODEX_BASE_API;
|
|
42
|
+
const CODEX_BASE_PROVIDER = "openai-codex" as const;
|
|
43
|
+
|
|
44
|
+
export interface CapturedCodexProvider {
|
|
45
|
+
readonly name: "openai-codex";
|
|
46
|
+
readonly baseUrl: string;
|
|
47
|
+
readonly oauth: NonNullable<ProviderConfig["oauth"]>;
|
|
48
|
+
readonly streamSimple: NonNullable<ProviderConfig["streamSimple"]>;
|
|
49
|
+
readonly models: readonly ProviderModelConfig[];
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export class CodexContractError extends Error {
|
|
53
|
+
constructor(message: string) {
|
|
54
|
+
super(
|
|
55
|
+
`[openai-codex contract] ${message} ` +
|
|
56
|
+
"Run npm run upstream:check and review UPSTREAM.md before release.",
|
|
57
|
+
);
|
|
58
|
+
this.name = "CodexContractError";
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/** Reads a lossless, deeply isolated live Codex catalog. */
|
|
63
|
+
function extractCodexModels(registry: unknown): readonly ProviderModelConfig[] {
|
|
64
|
+
let models: ProviderModelConfig[];
|
|
65
|
+
try {
|
|
66
|
+
models = cloneProviderModelCatalog(registry, CODEX_BASE_PROVIDER);
|
|
67
|
+
} catch (error) {
|
|
68
|
+
const detail = error instanceof Error ? error.message : String(error);
|
|
69
|
+
throw new CodexContractError(detail);
|
|
70
|
+
}
|
|
71
|
+
if (models.length === 0) {
|
|
72
|
+
throw new CodexContractError(
|
|
73
|
+
"No built-in openai-codex models found in the live registry.",
|
|
74
|
+
);
|
|
75
|
+
}
|
|
76
|
+
return models;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
type CaptureProxyRegistrations = Array<{ name: string; config: ProviderConfig }>;
|
|
80
|
+
|
|
81
|
+
function createCaptureProxy(
|
|
82
|
+
pi: ExtensionAPI,
|
|
83
|
+
registrations: CaptureProxyRegistrations,
|
|
84
|
+
): ExtensionAPI {
|
|
85
|
+
return new Proxy(pi, {
|
|
86
|
+
get(target, property, receiver) {
|
|
87
|
+
if (property === "registerProvider") {
|
|
88
|
+
return (name: string, config: ProviderConfig): void => {
|
|
89
|
+
registrations.push({ name, config });
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
const value = Reflect.get(target, property, receiver) as unknown;
|
|
93
|
+
return typeof value === "function" ? value.bind(target) : value;
|
|
94
|
+
},
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/** Captures and validates a maintained Codex provider registration. */
|
|
99
|
+
export async function captureCodexProviderViaCaptureProxy(
|
|
100
|
+
pi: ExtensionAPI,
|
|
101
|
+
extension: (pi: ExtensionAPI) => void | Promise<void>,
|
|
102
|
+
): Promise<CapturedCodexProvider> {
|
|
103
|
+
const registrations: CaptureProxyRegistrations = [];
|
|
104
|
+
await extension(createCaptureProxy(pi, registrations));
|
|
105
|
+
|
|
106
|
+
const matches = registrations.filter(({ name }) => name === CODEX_BASE_PROVIDER);
|
|
107
|
+
if (matches.length !== 1) {
|
|
108
|
+
throw new CodexContractError(
|
|
109
|
+
`Expected exactly one registerProvider('openai-codex', ...) call but found ${matches.length}.`,
|
|
110
|
+
);
|
|
111
|
+
}
|
|
112
|
+
const config = matches[0]?.config;
|
|
113
|
+
if (!config?.oauth) {
|
|
114
|
+
throw new CodexContractError("Captured openai-codex config has no OAuth callbacks.");
|
|
115
|
+
}
|
|
116
|
+
if (typeof config.oauth.login !== "function") {
|
|
117
|
+
throw new CodexContractError("Captured openai-codex OAuth login is missing.");
|
|
118
|
+
}
|
|
119
|
+
if (typeof config.oauth.refreshToken !== "function") {
|
|
120
|
+
throw new CodexContractError("Captured openai-codex OAuth refreshToken is missing.");
|
|
121
|
+
}
|
|
122
|
+
if (typeof config.oauth.getApiKey !== "function") {
|
|
123
|
+
throw new CodexContractError("Captured openai-codex OAuth getApiKey is missing.");
|
|
124
|
+
}
|
|
125
|
+
if (typeof config.streamSimple !== "function") {
|
|
126
|
+
throw new CodexContractError("Captured openai-codex config has no streamSimple.");
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
return {
|
|
130
|
+
name: CODEX_BASE_PROVIDER,
|
|
131
|
+
baseUrl: config.baseUrl ?? "https://chatgpt.com/backend-api",
|
|
132
|
+
oauth: config.oauth,
|
|
133
|
+
streamSimple: config.streamSimple,
|
|
134
|
+
models: config.models ?? [],
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
type CodexUpstreamStream = (
|
|
139
|
+
model: Model<Api>,
|
|
140
|
+
context: Context,
|
|
141
|
+
options?: SimpleStreamOptions,
|
|
142
|
+
) => AssistantMessageEventStream;
|
|
143
|
+
|
|
144
|
+
function withAliasAttribution(
|
|
145
|
+
message: AssistantMessage,
|
|
146
|
+
aliasModel: Model<Api>,
|
|
147
|
+
): AssistantMessage {
|
|
148
|
+
return {
|
|
149
|
+
...message,
|
|
150
|
+
api: aliasModel.api,
|
|
151
|
+
provider: aliasModel.provider,
|
|
152
|
+
model: aliasModel.id,
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
function sanitizeUpstreamError(message: AssistantMessage): AssistantMessage {
|
|
157
|
+
if (message.errorMessage === undefined) return message;
|
|
158
|
+
return {
|
|
159
|
+
...message,
|
|
160
|
+
errorMessage: sanitizeDiagnosticText(message.errorMessage),
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
function sanitizeProviderResponse(response: ProviderResponse): ProviderResponse {
|
|
165
|
+
return {
|
|
166
|
+
status: response.status,
|
|
167
|
+
headers: Object.fromEntries(
|
|
168
|
+
Object.entries(response.headers).map(([name, value]) => [
|
|
169
|
+
sanitizeDiagnosticText(name),
|
|
170
|
+
sanitizeHeaderValue(name, value),
|
|
171
|
+
]),
|
|
172
|
+
),
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
function withAliasEvent(
|
|
177
|
+
event: AssistantMessageEvent,
|
|
178
|
+
aliasModel: Model<Api>,
|
|
179
|
+
): AssistantMessageEvent {
|
|
180
|
+
switch (event.type) {
|
|
181
|
+
case "done":
|
|
182
|
+
return { ...event, message: withAliasAttribution(event.message, aliasModel) };
|
|
183
|
+
case "error":
|
|
184
|
+
return {
|
|
185
|
+
...event,
|
|
186
|
+
error: withAliasAttribution(
|
|
187
|
+
sanitizeUpstreamError(event.error),
|
|
188
|
+
aliasModel,
|
|
189
|
+
),
|
|
190
|
+
};
|
|
191
|
+
default:
|
|
192
|
+
return { ...event, partial: withAliasAttribution(event.partial, aliasModel) };
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
function reattributeStream(
|
|
197
|
+
upstream: AssistantMessageEventStream,
|
|
198
|
+
aliasModel: Model<Api>,
|
|
199
|
+
): AssistantMessageEventStream {
|
|
200
|
+
const attributed = createAssistantMessageEventStream();
|
|
201
|
+
void (async () => {
|
|
202
|
+
for await (const event of upstream) {
|
|
203
|
+
attributed.push(withAliasEvent(event, aliasModel));
|
|
204
|
+
}
|
|
205
|
+
})();
|
|
206
|
+
return attributed;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* Converts only assistant history emitted by this alias back to maintained base
|
|
211
|
+
* identity before request conversion. Reasoning signatures and tool-call IDs
|
|
212
|
+
* remain byte-for-byte unchanged, so same-model continuation stays native.
|
|
213
|
+
*/
|
|
214
|
+
function normalizeAliasContext(
|
|
215
|
+
context: Context,
|
|
216
|
+
aliasModel: Model<Api>,
|
|
217
|
+
): Context {
|
|
218
|
+
return {
|
|
219
|
+
...context,
|
|
220
|
+
messages: context.messages.map((message) => {
|
|
221
|
+
if (
|
|
222
|
+
message.role !== "assistant" ||
|
|
223
|
+
message.provider !== aliasModel.provider ||
|
|
224
|
+
message.api !== aliasModel.api
|
|
225
|
+
) {
|
|
226
|
+
return message;
|
|
227
|
+
}
|
|
228
|
+
return {
|
|
229
|
+
...message,
|
|
230
|
+
provider: CODEX_BASE_PROVIDER,
|
|
231
|
+
api: CODEX_BASE_API,
|
|
232
|
+
};
|
|
233
|
+
}),
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
/**
|
|
238
|
+
* Wraps the exact maintained stream without replacing transport or OAuth. Pi's
|
|
239
|
+
* alias-resolved apiKey and every other option field are forwarded unchanged;
|
|
240
|
+
* only model/context identity and callback attribution are adapted.
|
|
241
|
+
*/
|
|
242
|
+
export function createCodexAliasStream(
|
|
243
|
+
maintainedStream: NonNullable<ProviderConfig["streamSimple"]>,
|
|
244
|
+
): NonNullable<ProviderConfig["streamSimple"]> {
|
|
245
|
+
const upstream = maintainedStream as unknown as CodexUpstreamStream;
|
|
246
|
+
const aliasStream: CodexUpstreamStream = (aliasModel, context, options) => {
|
|
247
|
+
const upstreamModel: Model<Api> = {
|
|
248
|
+
...aliasModel,
|
|
249
|
+
provider: CODEX_BASE_PROVIDER,
|
|
250
|
+
api: CODEX_BASE_API,
|
|
251
|
+
};
|
|
252
|
+
const upstreamContext = normalizeAliasContext(context, aliasModel);
|
|
253
|
+
|
|
254
|
+
let upstreamOptions = options;
|
|
255
|
+
if (options?.onPayload || options?.onResponse) {
|
|
256
|
+
const aliasOnPayload = options.onPayload;
|
|
257
|
+
const aliasOnResponse = options.onResponse;
|
|
258
|
+
upstreamOptions = {
|
|
259
|
+
...options,
|
|
260
|
+
...(aliasOnPayload
|
|
261
|
+
? {
|
|
262
|
+
onPayload: (payload: unknown) =>
|
|
263
|
+
aliasOnPayload(payload, aliasModel),
|
|
264
|
+
}
|
|
265
|
+
: {}),
|
|
266
|
+
...(aliasOnResponse
|
|
267
|
+
? {
|
|
268
|
+
onResponse: (response: Parameters<NonNullable<SimpleStreamOptions["onResponse"]>>[0]) =>
|
|
269
|
+
aliasOnResponse(sanitizeProviderResponse(response), aliasModel),
|
|
270
|
+
}
|
|
271
|
+
: {}),
|
|
272
|
+
};
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
return reattributeStream(
|
|
276
|
+
upstream(upstreamModel, upstreamContext, upstreamOptions),
|
|
277
|
+
aliasModel,
|
|
278
|
+
);
|
|
279
|
+
};
|
|
280
|
+
return aliasStream as unknown as NonNullable<ProviderConfig["streamSimple"]>;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
function createAliasModels(
|
|
284
|
+
sourceModels: readonly ProviderModelConfig[],
|
|
285
|
+
aliasDisplayLabel: string,
|
|
286
|
+
): ProviderModelConfig[] {
|
|
287
|
+
try {
|
|
288
|
+
return sourceModels.map((source) => {
|
|
289
|
+
const model = structuredClone(source);
|
|
290
|
+
model.api = CODEX_ALIAS_API;
|
|
291
|
+
model.name = `${source.name} (${aliasDisplayLabel})`;
|
|
292
|
+
return model;
|
|
293
|
+
});
|
|
294
|
+
} catch (error) {
|
|
295
|
+
const detail = error instanceof Error ? error.message : String(error);
|
|
296
|
+
throw new CodexContractError(
|
|
297
|
+
`Codex live catalog could not be losslessly cloned: ${detail}`,
|
|
298
|
+
);
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
function buildAliasConfig(
|
|
303
|
+
captured: Pick<CapturedCodexProvider, "oauth" | "streamSimple" | "baseUrl">,
|
|
304
|
+
sourceModels: readonly ProviderModelConfig[],
|
|
305
|
+
aliasDisplayLabel: string,
|
|
306
|
+
): ProviderConfig {
|
|
307
|
+
if (sourceModels.length === 0) {
|
|
308
|
+
throw new CodexContractError("Cannot register a Codex alias with an empty model catalog.");
|
|
309
|
+
}
|
|
310
|
+
return {
|
|
311
|
+
api: CODEX_ALIAS_API,
|
|
312
|
+
baseUrl: captured.baseUrl,
|
|
313
|
+
oauth: captured.oauth,
|
|
314
|
+
streamSimple: createCodexAliasStream(captured.streamSimple),
|
|
315
|
+
models: createAliasModels(sourceModels, aliasDisplayLabel),
|
|
316
|
+
};
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
/** Builds a Codex alias from captured maintained behavior. */
|
|
320
|
+
export function createCodexAliasProviderConfig(
|
|
321
|
+
captured: CapturedCodexProvider,
|
|
322
|
+
aliasDisplayLabel: string,
|
|
323
|
+
registryModels?: readonly ProviderModelConfig[],
|
|
324
|
+
): ProviderConfig {
|
|
325
|
+
return buildAliasConfig(
|
|
326
|
+
captured,
|
|
327
|
+
registryModels ?? captured.models,
|
|
328
|
+
aliasDisplayLabel,
|
|
329
|
+
);
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
/** Builds a Codex alias from maintained base behavior and a live catalog. */
|
|
333
|
+
export function buildCodexAliasFromBaseConfig(
|
|
334
|
+
baseCaptured: Pick<CapturedCodexProvider, "oauth" | "streamSimple" | "baseUrl">,
|
|
335
|
+
liveRegistryModels: readonly ProviderModelConfig[],
|
|
336
|
+
aliasDisplayLabel: string,
|
|
337
|
+
): ProviderConfig {
|
|
338
|
+
return buildAliasConfig(baseCaptured, liveRegistryModels, aliasDisplayLabel);
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
export function getCodexModelsFromRegistry(
|
|
342
|
+
registry: unknown,
|
|
343
|
+
): readonly ProviderModelConfig[] {
|
|
344
|
+
return extractCodexModels(registry);
|
|
345
|
+
}
|