@opengeni/config 0.6.2 → 0.7.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/dist/index.d.ts +379 -8
- package/dist/index.js +756 -65
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
- package/src/index.ts +1016 -86
package/dist/index.js
CHANGED
|
@@ -4,13 +4,26 @@ import {
|
|
|
4
4
|
CAPABILITY_DESCRIPTORS,
|
|
5
5
|
Entitlements,
|
|
6
6
|
EntitlementsMode,
|
|
7
|
+
MAX_NESTED_AGENT_DEPTH,
|
|
7
8
|
ProductAccessMode,
|
|
8
9
|
ReasoningEffort,
|
|
9
10
|
SandboxBackend,
|
|
11
|
+
SessionMcpApprovalPolicy,
|
|
10
12
|
StaticUsageLimits,
|
|
13
|
+
TurnExecutionPolicyV1,
|
|
11
14
|
UsageLimitsMode
|
|
12
15
|
} from "@opengeni/contracts";
|
|
13
|
-
import {
|
|
16
|
+
import { CODEX_MODEL_TOOL_OUTPUT_TRUNCATION_TOKENS } from "@opengeni/codex";
|
|
17
|
+
import {
|
|
18
|
+
CODEX_FALLBACK_MODEL_SLUGS,
|
|
19
|
+
CODEX_MODEL_AUTO_COMPACT_TOKEN_LIMIT,
|
|
20
|
+
CODEX_MODEL_CONTEXT_WINDOW_TOKENS,
|
|
21
|
+
CODEX_MODEL_EFFECTIVE_CONTEXT_WINDOW_TOKENS,
|
|
22
|
+
CODEX_MODEL_ID_PREFIX,
|
|
23
|
+
CODEX_PROVIDER_BASE_URL,
|
|
24
|
+
CODEX_PROVIDER_ID
|
|
25
|
+
} from "@opengeni/codex/constants";
|
|
26
|
+
import { createHash } from "crypto";
|
|
14
27
|
import { z } from "zod";
|
|
15
28
|
var envName = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
16
29
|
var registryId = /^[A-Za-z0-9_-]+$/;
|
|
@@ -175,6 +188,9 @@ var SettingsSchema = z.object({
|
|
|
175
188
|
// holder of stream:control gets 403 until this flips. Keeps stream:control a
|
|
176
189
|
// declared-but-inert permission so later hardening is a flag flip.
|
|
177
190
|
streamControlEnabled: EnvBoolean.default(false),
|
|
191
|
+
// Existing-session explicit tool replacement is gated until every API and
|
|
192
|
+
// worker instance understands durable tools_provided provenance.
|
|
193
|
+
sessionTurnToolReplacementEnabled: EnvBoolean.default(false),
|
|
178
194
|
toolspaceEnabled: EnvBoolean.default(false),
|
|
179
195
|
toolspaceMaxCallsPerTurn: z.coerce.number().int().positive().default(200),
|
|
180
196
|
// Optional release-coherent bootstrap hint for custom rigs/connected machines
|
|
@@ -186,6 +202,9 @@ var SettingsSchema = z.object({
|
|
|
186
202
|
integrationsStateSecret: z.string().optional(),
|
|
187
203
|
integrationsAllowPrivateNetworkTargets: EnvBoolean.default(false),
|
|
188
204
|
integrationsOauthClientsJson: z.string().default("{}"),
|
|
205
|
+
// Undefined is meaningful: the migration boundary persists the product
|
|
206
|
+
// default of 3 when no deployment override is supplied.
|
|
207
|
+
maxNestedAgentDepth: z.coerce.number().int().nonnegative().max(MAX_NESTED_AGENT_DEPTH).optional(),
|
|
189
208
|
// Session goal guard rails. Goals are designed for runs that legitimately
|
|
190
209
|
// span days, so length is bounded by pathology detection (no-progress
|
|
191
210
|
// streaks, budget exhaustion), never by count. goalMaxAutoContinuations is
|
|
@@ -269,6 +288,14 @@ var SettingsSchema = z.object({
|
|
|
269
288
|
// enable. Turning it off restores the legacy sticky selector without a schema
|
|
270
289
|
// rollback; the additive lease table/cursor columns become inert.
|
|
271
290
|
codexCredentialLeasingEnabled: EnvBoolean.default(false),
|
|
291
|
+
// Decision-observability fence. When enabled, the worker emits one
|
|
292
|
+
// bounded, metadata-only adaptive-policy replay record alongside the unchanged
|
|
293
|
+
// sticky-sharded decision. It never changes placement/admission/failover.
|
|
294
|
+
codexFleetPolicyShadowEnabled: EnvBoolean.default(false),
|
|
295
|
+
// Multi-account P3 (auto-rotation): an account is "near exhaustion" — ineligible to be
|
|
296
|
+
// rotated TO — when EITHER usage window (5h/weekly) is at/over this percent. Default 90 to
|
|
297
|
+
// match the UI danger flip (UsageBar danger at pct >= 90). OPENGENI_CODEX_ROTATION_NEAR_EXHAUSTION_PCT.
|
|
298
|
+
codexRotationNearExhaustionPct: z.coerce.number().int().min(1).max(100).default(90),
|
|
272
299
|
openaiReasoningEffort: ReasoningEffort.default("low"),
|
|
273
300
|
openaiAllowedReasoningEfforts: z.string().default("low,medium,high,xhigh"),
|
|
274
301
|
openaiResponsesTransport: z.enum(["http", "websocket"]).default("http"),
|
|
@@ -470,6 +497,15 @@ var SettingsSchema = z.object({
|
|
|
470
497
|
// EnvBoolean (NOT z.coerce.boolean(), which would coerce "false" -> true and
|
|
471
498
|
// turn the flag ON the moment anyone set the env var to disable it).
|
|
472
499
|
sandboxOwnershipEnabled: EnvBoolean.default(false),
|
|
500
|
+
// --- standalone rig-verifier ownership rollout flag, default OFF ---
|
|
501
|
+
// Rig verification creates a throwaway provider sandbox outside the normal
|
|
502
|
+
// session-turn path. When enabled, that sandbox must first acquire the same
|
|
503
|
+
// durable lease lifecycle used by session boxes so the global orphan sweep
|
|
504
|
+
// recognizes its exact provider instance. Keep this separate from the general
|
|
505
|
+
// sandboxOwnershipEnabled rollout: every reaper worker must understand verifier
|
|
506
|
+
// leases before dispatch is enabled. When false the verifier fails closed before
|
|
507
|
+
// provider create; it never falls back to the legacy unowned path.
|
|
508
|
+
rigVerificationLeaseOwnershipEnabled: EnvBoolean.default(false),
|
|
473
509
|
// --- lazy sandbox provisioning rollout flag, default OFF ---
|
|
474
510
|
// Only effective when sandboxOwnershipEnabled is ALSO on (lazy provisioning is a
|
|
475
511
|
// property of the owned path — the SDK never creates/resumes an injected session,
|
|
@@ -687,14 +723,8 @@ var SettingsSchema = z.object({
|
|
|
687
723
|
allowedTools: z.array(z.string().min(1)).optional(),
|
|
688
724
|
timeoutMs: z.number().int().positive().optional(),
|
|
689
725
|
cacheToolsList: z.boolean().default(false),
|
|
690
|
-
/**
|
|
691
|
-
|
|
692
|
-
* session MCP server row (never from OPENGENI_MCP_SERVERS). `true` = all
|
|
693
|
-
* tools require approval; a string[] = only the listed UNPREFIXED tool
|
|
694
|
-
* names do; absent = auto-run (the historical default). Enforced in the
|
|
695
|
-
* runtime by attaching `needsApproval` to the matching MCP tools.
|
|
696
|
-
*/
|
|
697
|
-
requireApproval: z.union([z.boolean(), z.array(z.string().min(1))]).optional(),
|
|
726
|
+
/** Runtime approval policy, overlaid from an attempt-frozen session snapshot. */
|
|
727
|
+
requireApproval: SessionMcpApprovalPolicy.optional(),
|
|
698
728
|
/**
|
|
699
729
|
* Extra request headers sent to this MCP server (credential injection
|
|
700
730
|
* for workspace-enabled capability MCPs). Populated at runtime from
|
|
@@ -712,11 +742,130 @@ var ModelPricingSchema = z.object({
|
|
|
712
742
|
outputMicrosPerMillionTokens: z.number().int().nonnegative(),
|
|
713
743
|
marginBps: z.number().int().min(0).max(1e5).optional()
|
|
714
744
|
});
|
|
745
|
+
var ModelPricingScheduleSchema = z.object({
|
|
746
|
+
default: ModelPricingSchema,
|
|
747
|
+
inputTokenTiers: z.array(
|
|
748
|
+
z.object({
|
|
749
|
+
minimumInputTokens: z.number().int().nonnegative(),
|
|
750
|
+
pricing: ModelPricingSchema
|
|
751
|
+
})
|
|
752
|
+
).optional()
|
|
753
|
+
}).superRefine((schedule, ctx) => {
|
|
754
|
+
let previous = -1;
|
|
755
|
+
for (const [index, tier] of (schedule.inputTokenTiers ?? []).entries()) {
|
|
756
|
+
if (tier.minimumInputTokens <= previous) {
|
|
757
|
+
ctx.addIssue({
|
|
758
|
+
code: "custom",
|
|
759
|
+
path: ["inputTokenTiers", index, "minimumInputTokens"],
|
|
760
|
+
message: "input-token tier thresholds must be strictly increasing"
|
|
761
|
+
});
|
|
762
|
+
}
|
|
763
|
+
previous = tier.minimumInputTokens;
|
|
764
|
+
}
|
|
765
|
+
});
|
|
766
|
+
var CapabilitySupportV1 = z.enum(["supported", "unsupported", "unknown"]);
|
|
767
|
+
var CapabilityStateV1Schema = z.object({
|
|
768
|
+
upstream: CapabilitySupportV1,
|
|
769
|
+
runnable: z.boolean()
|
|
770
|
+
}).superRefine((state, ctx) => {
|
|
771
|
+
if (state.upstream === "unsupported" && state.runnable) {
|
|
772
|
+
ctx.addIssue({
|
|
773
|
+
code: "custom",
|
|
774
|
+
path: ["runnable"],
|
|
775
|
+
message: "an upstream-unsupported capability cannot be runnable"
|
|
776
|
+
});
|
|
777
|
+
}
|
|
778
|
+
});
|
|
779
|
+
var ModelModalityV1 = z.enum(["text", "image", "audio"]);
|
|
780
|
+
var ModelLatencyModeV1 = z.enum(["standard", "priority", "fast"]);
|
|
781
|
+
var ModelCapabilitiesV1Schema = z.object({
|
|
782
|
+
reasoning: CapabilityStateV1Schema.extend({
|
|
783
|
+
efforts: z.array(ReasoningEffort),
|
|
784
|
+
defaultEffort: ReasoningEffort.nullable(),
|
|
785
|
+
required: z.boolean()
|
|
786
|
+
}),
|
|
787
|
+
functionCalling: CapabilityStateV1Schema,
|
|
788
|
+
structuredOutput: CapabilityStateV1Schema,
|
|
789
|
+
hostedTools: z.object({
|
|
790
|
+
webSearch: CapabilityStateV1Schema,
|
|
791
|
+
xSearch: CapabilityStateV1Schema,
|
|
792
|
+
codeExecution: CapabilityStateV1Schema
|
|
793
|
+
}),
|
|
794
|
+
inputModalities: z.array(ModelModalityV1).min(1),
|
|
795
|
+
outputModalities: z.array(ModelModalityV1).min(1),
|
|
796
|
+
transports: z.object({
|
|
797
|
+
sse: CapabilityStateV1Schema,
|
|
798
|
+
responsesWebSocket: CapabilityStateV1Schema,
|
|
799
|
+
realtimeAudio: CapabilityStateV1Schema
|
|
800
|
+
}),
|
|
801
|
+
latencyModes: z.array(
|
|
802
|
+
z.object({
|
|
803
|
+
id: ModelLatencyModeV1,
|
|
804
|
+
upstream: CapabilitySupportV1,
|
|
805
|
+
runnable: z.boolean(),
|
|
806
|
+
billingMultiplierBps: z.number().int().positive().optional()
|
|
807
|
+
})
|
|
808
|
+
).min(1)
|
|
809
|
+
}).superRefine((capabilities, ctx) => {
|
|
810
|
+
const efforts = new Set(capabilities.reasoning.efforts);
|
|
811
|
+
if (efforts.size !== capabilities.reasoning.efforts.length) {
|
|
812
|
+
ctx.addIssue({
|
|
813
|
+
code: "custom",
|
|
814
|
+
path: ["reasoning", "efforts"],
|
|
815
|
+
message: "reasoning efforts must be unique"
|
|
816
|
+
});
|
|
817
|
+
}
|
|
818
|
+
if (capabilities.reasoning.defaultEffort !== null && !efforts.has(capabilities.reasoning.defaultEffort)) {
|
|
819
|
+
ctx.addIssue({
|
|
820
|
+
code: "custom",
|
|
821
|
+
path: ["reasoning", "defaultEffort"],
|
|
822
|
+
message: "the default reasoning effort must be one of the supported efforts"
|
|
823
|
+
});
|
|
824
|
+
}
|
|
825
|
+
if (capabilities.reasoning.runnable && capabilities.reasoning.efforts.length === 0) {
|
|
826
|
+
ctx.addIssue({
|
|
827
|
+
code: "custom",
|
|
828
|
+
path: ["reasoning", "efforts"],
|
|
829
|
+
message: "a runnable reasoning capability must declare at least one effort"
|
|
830
|
+
});
|
|
831
|
+
}
|
|
832
|
+
for (const field of ["inputModalities", "outputModalities"]) {
|
|
833
|
+
if (new Set(capabilities[field]).size !== capabilities[field].length) {
|
|
834
|
+
ctx.addIssue({
|
|
835
|
+
code: "custom",
|
|
836
|
+
path: [field],
|
|
837
|
+
message: `${field} must be unique`
|
|
838
|
+
});
|
|
839
|
+
}
|
|
840
|
+
}
|
|
841
|
+
const latencyIds = /* @__PURE__ */ new Set();
|
|
842
|
+
for (const [index, mode] of capabilities.latencyModes.entries()) {
|
|
843
|
+
if (latencyIds.has(mode.id)) {
|
|
844
|
+
ctx.addIssue({
|
|
845
|
+
code: "custom",
|
|
846
|
+
path: ["latencyModes", index, "id"],
|
|
847
|
+
message: "latency mode ids must be unique"
|
|
848
|
+
});
|
|
849
|
+
}
|
|
850
|
+
latencyIds.add(mode.id);
|
|
851
|
+
if (mode.upstream === "unsupported" && mode.runnable) {
|
|
852
|
+
ctx.addIssue({
|
|
853
|
+
code: "custom",
|
|
854
|
+
path: ["latencyModes", index, "runnable"],
|
|
855
|
+
message: "an upstream-unsupported latency mode cannot be runnable"
|
|
856
|
+
});
|
|
857
|
+
}
|
|
858
|
+
}
|
|
859
|
+
});
|
|
715
860
|
var ModelProviderApi = z.enum(["responses", "chat"]);
|
|
716
861
|
var RegistryProviderKind = z.enum(["api-key", "codex-subscription"]);
|
|
717
862
|
var RegistryModelSchema = z.object({
|
|
718
863
|
id: z.string().min(1),
|
|
719
|
-
//
|
|
864
|
+
// canonical OpenGeni product id
|
|
865
|
+
upstreamModelId: z.string().min(1).optional(),
|
|
866
|
+
// exact provider slug; defaults to id
|
|
867
|
+
aliases: z.array(z.string().min(1)).optional(),
|
|
868
|
+
// accepted input only; never sent upstream
|
|
720
869
|
label: z.string().min(1).optional(),
|
|
721
870
|
// display name; defaults to id
|
|
722
871
|
contextWindowTokens: z.number().int().positive().optional(),
|
|
@@ -726,10 +875,30 @@ var RegistryModelSchema = z.object({
|
|
|
726
875
|
// the same 1.2x serialization allowance as Codex when materializing output.
|
|
727
876
|
toolOutputTruncationTokens: z.number().int().positive().optional(),
|
|
728
877
|
reasoningEffort: z.boolean().optional(),
|
|
729
|
-
//
|
|
878
|
+
// legacy compatibility input/projection
|
|
730
879
|
hostedWebSearch: z.boolean().optional(),
|
|
731
|
-
//
|
|
732
|
-
|
|
880
|
+
// legacy compatibility input/projection
|
|
881
|
+
capabilities: ModelCapabilitiesV1Schema.optional(),
|
|
882
|
+
pricing: z.union([ModelPricingSchema, ModelPricingScheduleSchema]).optional(),
|
|
883
|
+
// Reserved normalized contracts are derived by OpenGeni in V1. Generic
|
|
884
|
+
// registry JSON must not opt itself into workspace BYOK or reattribute cost.
|
|
885
|
+
credentialSource: z.never().optional(),
|
|
886
|
+
billing: z.never().optional()
|
|
887
|
+
}).superRefine((model, ctx) => {
|
|
888
|
+
if (model.capabilities && model.reasoningEffort !== void 0 && model.reasoningEffort !== model.capabilities.reasoning.runnable) {
|
|
889
|
+
ctx.addIssue({
|
|
890
|
+
code: "custom",
|
|
891
|
+
path: ["reasoningEffort"],
|
|
892
|
+
message: "legacy reasoningEffort must agree with capabilities.reasoning.runnable"
|
|
893
|
+
});
|
|
894
|
+
}
|
|
895
|
+
if (model.capabilities && model.hostedWebSearch !== void 0 && model.hostedWebSearch !== model.capabilities.hostedTools.webSearch.runnable) {
|
|
896
|
+
ctx.addIssue({
|
|
897
|
+
code: "custom",
|
|
898
|
+
path: ["hostedWebSearch"],
|
|
899
|
+
message: "legacy hostedWebSearch must agree with capabilities.hostedTools.webSearch.runnable"
|
|
900
|
+
});
|
|
901
|
+
}
|
|
733
902
|
});
|
|
734
903
|
var RegistryProviderSchema = z.object({
|
|
735
904
|
kind: RegistryProviderKind.default("api-key"),
|
|
@@ -745,6 +914,12 @@ var RegistryProviderSchema = z.object({
|
|
|
745
914
|
// ... OR name of the env var holding the key (preferred)
|
|
746
915
|
defaultQuery: z.record(z.string(), z.string()).optional(),
|
|
747
916
|
defaultHeaders: z.record(z.string(), z.string()).optional(),
|
|
917
|
+
publicDefaultQueryNames: z.array(z.string().min(1)).optional(),
|
|
918
|
+
publicDefaultHeaderNames: z.array(z.string().min(1)).optional(),
|
|
919
|
+
// V1 derives these from provider kind. Workspace BYOK is deliberately not a
|
|
920
|
+
// registry switch and requires a separately reviewed encrypted broker.
|
|
921
|
+
credentialSource: z.never().optional(),
|
|
922
|
+
billing: z.never().optional(),
|
|
748
923
|
models: z.array(RegistryModelSchema).min(1)
|
|
749
924
|
});
|
|
750
925
|
var IntegrationOAuthClientConfigSchema = z.object({
|
|
@@ -909,6 +1084,7 @@ function getSettings() {
|
|
|
909
1084
|
delegationSecret: optional("OPENGENI_DELEGATION_SECRET"),
|
|
910
1085
|
streamTokenSecret: optional("OPENGENI_STREAM_TOKEN_SECRET"),
|
|
911
1086
|
streamControlEnabled: optional("OPENGENI_STREAM_CONTROL_ENABLED"),
|
|
1087
|
+
sessionTurnToolReplacementEnabled: optional("OPENGENI_SESSION_TURN_TOOL_REPLACEMENT_ENABLED"),
|
|
912
1088
|
toolspaceEnabled: optional("OPENGENI_TOOLSPACE_ENABLED"),
|
|
913
1089
|
toolspaceMaxCallsPerTurn: optional("OPENGENI_TOOLSPACE_MAX_CALLS_PER_TURN"),
|
|
914
1090
|
ogtoolPackageSpec: optional("OPENGENI_OGTOOL_PACKAGE_SPEC"),
|
|
@@ -919,6 +1095,7 @@ function getSettings() {
|
|
|
919
1095
|
"OPENGENI_INTEGRATIONS_ALLOW_PRIVATE_NETWORK_TARGETS"
|
|
920
1096
|
),
|
|
921
1097
|
integrationsOauthClientsJson: optional("OPENGENI_INTEGRATIONS_OAUTH_CLIENTS_JSON"),
|
|
1098
|
+
maxNestedAgentDepth: optional("OPENGENI_MAX_NESTED_AGENT_DEPTH"),
|
|
922
1099
|
goalMaxAutoContinuations: optional("OPENGENI_GOAL_MAX_AUTO_CONTINUATIONS"),
|
|
923
1100
|
goalNoProgressLimit: optional("OPENGENI_GOAL_NO_PROGRESS_LIMIT"),
|
|
924
1101
|
agentMaxModelCallsPerTurn: optional("OPENGENI_AGENT_MAX_MODEL_CALLS_PER_TURN"),
|
|
@@ -947,6 +1124,7 @@ function getSettings() {
|
|
|
947
1124
|
codexSubscriptionEnabled: optional("OPENGENI_CODEX_SUBSCRIPTION_ENABLED"),
|
|
948
1125
|
codexToolSearchEnabled: optional("OPENGENI_CODEX_TOOL_SEARCH_ENABLED"),
|
|
949
1126
|
codexCredentialLeasingEnabled: optional("OPENGENI_CODEX_CREDENTIAL_LEASING_ENABLED"),
|
|
1127
|
+
codexFleetPolicyShadowEnabled: optional("OPENGENI_CODEX_FLEET_POLICY_SHADOW_ENABLED"),
|
|
950
1128
|
codexProductSku: optional("OPENGENI_CODEX_PRODUCT_SKU"),
|
|
951
1129
|
openaiReasoningEffort: optional("OPENGENI_OPENAI_REASONING_EFFORT"),
|
|
952
1130
|
openaiAllowedReasoningEfforts: optional("OPENGENI_OPENAI_ALLOWED_REASONING_EFFORTS"),
|
|
@@ -1025,6 +1203,9 @@ function getSettings() {
|
|
|
1025
1203
|
vercelTeamId: optional("OPENGENI_VERCEL_TEAM_ID"),
|
|
1026
1204
|
vercelRuntime: optional("OPENGENI_VERCEL_RUNTIME"),
|
|
1027
1205
|
sandboxOwnershipEnabled: optional("OPENGENI_SANDBOX_OWNERSHIP_ENABLED"),
|
|
1206
|
+
rigVerificationLeaseOwnershipEnabled: optional(
|
|
1207
|
+
"OPENGENI_RIG_VERIFICATION_LEASE_OWNERSHIP_ENABLED"
|
|
1208
|
+
),
|
|
1028
1209
|
sandboxLazyProvisionEnabled: optional("OPENGENI_SANDBOX_LAZY_PROVISION"),
|
|
1029
1210
|
sandboxSelfhostedEnabled: optional("OPENGENI_SANDBOX_SELFHOSTED_ENABLED"),
|
|
1030
1211
|
agentOpStreamEnabled: optional("OPENGENI_AGENT_OP_STREAM_ENABLED"),
|
|
@@ -1136,6 +1317,287 @@ function resolveProviderApiKey(provider, source = process.env) {
|
|
|
1136
1317
|
}
|
|
1137
1318
|
return void 0;
|
|
1138
1319
|
}
|
|
1320
|
+
var HTTP_FIELD_NAME = /^[!#$%&'*+\-.^_`|~0-9A-Za-z]+$/;
|
|
1321
|
+
var CREDENTIAL_LIKE_NAME_PARTS = /* @__PURE__ */ new Set([
|
|
1322
|
+
"apikey",
|
|
1323
|
+
"auth",
|
|
1324
|
+
"authorization",
|
|
1325
|
+
"bearer",
|
|
1326
|
+
"credential",
|
|
1327
|
+
"cookie",
|
|
1328
|
+
"key",
|
|
1329
|
+
"password",
|
|
1330
|
+
"secret",
|
|
1331
|
+
"session",
|
|
1332
|
+
"signature",
|
|
1333
|
+
"token"
|
|
1334
|
+
]);
|
|
1335
|
+
var REASONING_EFFORT_ORDER = new Map(
|
|
1336
|
+
ReasoningEffort.options.map((effort, index) => [effort, index])
|
|
1337
|
+
);
|
|
1338
|
+
var MODALITY_ORDER = new Map(["text", "image", "audio"].map((value, index) => [value, index]));
|
|
1339
|
+
var LATENCY_MODE_ORDER = new Map(
|
|
1340
|
+
["standard", "priority", "fast"].map((value, index) => [value, index])
|
|
1341
|
+
);
|
|
1342
|
+
function normalizeRegistryBaseUrl(value, providerId) {
|
|
1343
|
+
const url = new URL(value);
|
|
1344
|
+
if (url.username || url.password) {
|
|
1345
|
+
throw new Error(`provider ${providerId} baseUrl must not contain userinfo`);
|
|
1346
|
+
}
|
|
1347
|
+
if (url.search) {
|
|
1348
|
+
throw new Error(
|
|
1349
|
+
`provider ${providerId} baseUrl must not contain a query; move query entries to defaultQuery`
|
|
1350
|
+
);
|
|
1351
|
+
}
|
|
1352
|
+
if (url.hash) {
|
|
1353
|
+
throw new Error(`provider ${providerId} baseUrl must not contain a fragment`);
|
|
1354
|
+
}
|
|
1355
|
+
return url.toString();
|
|
1356
|
+
}
|
|
1357
|
+
function isCredentialLikeMetadataName(name) {
|
|
1358
|
+
return name.toLowerCase().split(/[-_.]/u).some((part) => CREDENTIAL_LIKE_NAME_PARTS.has(part));
|
|
1359
|
+
}
|
|
1360
|
+
function normalizeHeaderMap(providerId, headers) {
|
|
1361
|
+
if (!headers) {
|
|
1362
|
+
return void 0;
|
|
1363
|
+
}
|
|
1364
|
+
const normalized = {};
|
|
1365
|
+
const rawByNormalized = /* @__PURE__ */ new Map();
|
|
1366
|
+
for (const [rawName, value] of Object.entries(headers)) {
|
|
1367
|
+
if (!HTTP_FIELD_NAME.test(rawName)) {
|
|
1368
|
+
throw new Error(
|
|
1369
|
+
`provider ${providerId} defaultHeaders contains invalid HTTP field name ${JSON.stringify(rawName)}`
|
|
1370
|
+
);
|
|
1371
|
+
}
|
|
1372
|
+
const name = rawName.toLowerCase();
|
|
1373
|
+
const previous = rawByNormalized.get(name);
|
|
1374
|
+
if (previous !== void 0) {
|
|
1375
|
+
throw new Error(
|
|
1376
|
+
`provider ${providerId} defaultHeaders names ${JSON.stringify(previous)} and ${JSON.stringify(rawName)} collide after lowercase normalization`
|
|
1377
|
+
);
|
|
1378
|
+
}
|
|
1379
|
+
if (name === "authorization") {
|
|
1380
|
+
throw new Error(
|
|
1381
|
+
`provider ${providerId} defaultHeaders must not override SDK-managed Authorization`
|
|
1382
|
+
);
|
|
1383
|
+
}
|
|
1384
|
+
rawByNormalized.set(name, rawName);
|
|
1385
|
+
normalized[name] = value;
|
|
1386
|
+
}
|
|
1387
|
+
return normalized;
|
|
1388
|
+
}
|
|
1389
|
+
function normalizePublicHeaderNames(providerId, names, headers) {
|
|
1390
|
+
if (!names) {
|
|
1391
|
+
return void 0;
|
|
1392
|
+
}
|
|
1393
|
+
const normalized = [];
|
|
1394
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1395
|
+
for (const rawName of names) {
|
|
1396
|
+
if (!HTTP_FIELD_NAME.test(rawName)) {
|
|
1397
|
+
throw new Error(
|
|
1398
|
+
`provider ${providerId} publicDefaultHeaderNames contains invalid HTTP field name ${JSON.stringify(rawName)}`
|
|
1399
|
+
);
|
|
1400
|
+
}
|
|
1401
|
+
const name = rawName.toLowerCase();
|
|
1402
|
+
if (seen.has(name)) {
|
|
1403
|
+
throw new Error(
|
|
1404
|
+
`provider ${providerId} publicDefaultHeaderNames contains duplicate normalized name ${JSON.stringify(name)}`
|
|
1405
|
+
);
|
|
1406
|
+
}
|
|
1407
|
+
if (!(name in (headers ?? {}))) {
|
|
1408
|
+
throw new Error(
|
|
1409
|
+
`provider ${providerId} publicDefaultHeaderNames declares absent defaultHeaders entry ${JSON.stringify(name)}`
|
|
1410
|
+
);
|
|
1411
|
+
}
|
|
1412
|
+
if (isCredentialLikeMetadataName(name)) {
|
|
1413
|
+
throw new Error(
|
|
1414
|
+
`provider ${providerId} publicDefaultHeaderNames cannot classify credential-like name ${JSON.stringify(name)} as public`
|
|
1415
|
+
);
|
|
1416
|
+
}
|
|
1417
|
+
seen.add(name);
|
|
1418
|
+
normalized.push(name);
|
|
1419
|
+
}
|
|
1420
|
+
return normalized;
|
|
1421
|
+
}
|
|
1422
|
+
function normalizeQueryMap(providerId, query) {
|
|
1423
|
+
if (!query) {
|
|
1424
|
+
return void 0;
|
|
1425
|
+
}
|
|
1426
|
+
for (const name of Object.keys(query)) {
|
|
1427
|
+
if (!name) {
|
|
1428
|
+
throw new Error(`provider ${providerId} defaultQuery contains an empty name`);
|
|
1429
|
+
}
|
|
1430
|
+
}
|
|
1431
|
+
return { ...query };
|
|
1432
|
+
}
|
|
1433
|
+
function normalizePublicQueryNames(providerId, names, query) {
|
|
1434
|
+
if (!names) {
|
|
1435
|
+
return void 0;
|
|
1436
|
+
}
|
|
1437
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1438
|
+
for (const name of names) {
|
|
1439
|
+
if (seen.has(name)) {
|
|
1440
|
+
throw new Error(
|
|
1441
|
+
`provider ${providerId} publicDefaultQueryNames contains duplicate name ${JSON.stringify(name)}`
|
|
1442
|
+
);
|
|
1443
|
+
}
|
|
1444
|
+
if (!(name in (query ?? {}))) {
|
|
1445
|
+
throw new Error(
|
|
1446
|
+
`provider ${providerId} publicDefaultQueryNames declares absent defaultQuery entry ${JSON.stringify(name)}`
|
|
1447
|
+
);
|
|
1448
|
+
}
|
|
1449
|
+
if (isCredentialLikeMetadataName(name)) {
|
|
1450
|
+
throw new Error(
|
|
1451
|
+
`provider ${providerId} publicDefaultQueryNames cannot classify credential-like name ${JSON.stringify(name)} as public`
|
|
1452
|
+
);
|
|
1453
|
+
}
|
|
1454
|
+
seen.add(name);
|
|
1455
|
+
}
|
|
1456
|
+
return [...names];
|
|
1457
|
+
}
|
|
1458
|
+
function normalizeRegistryProvider(provider) {
|
|
1459
|
+
const defaultHeaders = normalizeHeaderMap(provider.id, provider.defaultHeaders);
|
|
1460
|
+
const defaultQuery = normalizeQueryMap(provider.id, provider.defaultQuery);
|
|
1461
|
+
return {
|
|
1462
|
+
...provider,
|
|
1463
|
+
baseUrl: normalizeRegistryBaseUrl(provider.baseUrl, provider.id),
|
|
1464
|
+
...defaultHeaders === void 0 ? {} : { defaultHeaders },
|
|
1465
|
+
...defaultQuery === void 0 ? {} : { defaultQuery },
|
|
1466
|
+
...provider.publicDefaultHeaderNames === void 0 ? {} : {
|
|
1467
|
+
publicDefaultHeaderNames: normalizePublicHeaderNames(
|
|
1468
|
+
provider.id,
|
|
1469
|
+
provider.publicDefaultHeaderNames,
|
|
1470
|
+
defaultHeaders
|
|
1471
|
+
)
|
|
1472
|
+
},
|
|
1473
|
+
...provider.publicDefaultQueryNames === void 0 ? {} : {
|
|
1474
|
+
publicDefaultQueryNames: normalizePublicQueryNames(
|
|
1475
|
+
provider.id,
|
|
1476
|
+
provider.publicDefaultQueryNames,
|
|
1477
|
+
defaultQuery
|
|
1478
|
+
)
|
|
1479
|
+
}
|
|
1480
|
+
};
|
|
1481
|
+
}
|
|
1482
|
+
function normalizeModelPricingSchedule(pricing) {
|
|
1483
|
+
return "default" in pricing ? pricing : { default: pricing };
|
|
1484
|
+
}
|
|
1485
|
+
function normalizeCapabilities(capabilities) {
|
|
1486
|
+
const parsed = ModelCapabilitiesV1Schema.parse(capabilities);
|
|
1487
|
+
return {
|
|
1488
|
+
...parsed,
|
|
1489
|
+
reasoning: {
|
|
1490
|
+
...parsed.reasoning,
|
|
1491
|
+
efforts: [...parsed.reasoning.efforts].sort(
|
|
1492
|
+
(left, right) => (REASONING_EFFORT_ORDER.get(left) ?? 0) - (REASONING_EFFORT_ORDER.get(right) ?? 0)
|
|
1493
|
+
)
|
|
1494
|
+
},
|
|
1495
|
+
inputModalities: [...parsed.inputModalities].sort(
|
|
1496
|
+
(left, right) => (MODALITY_ORDER.get(left) ?? 0) - (MODALITY_ORDER.get(right) ?? 0)
|
|
1497
|
+
),
|
|
1498
|
+
outputModalities: [...parsed.outputModalities].sort(
|
|
1499
|
+
(left, right) => (MODALITY_ORDER.get(left) ?? 0) - (MODALITY_ORDER.get(right) ?? 0)
|
|
1500
|
+
),
|
|
1501
|
+
latencyModes: [...parsed.latencyModes].sort(
|
|
1502
|
+
(left, right) => (LATENCY_MODE_ORDER.get(left.id) ?? 0) - (LATENCY_MODE_ORDER.get(right.id) ?? 0)
|
|
1503
|
+
)
|
|
1504
|
+
};
|
|
1505
|
+
}
|
|
1506
|
+
function legacyModelCapabilities(settings, input) {
|
|
1507
|
+
const reasoningEfforts = input.reasoningEffort ? configuredAllowedReasoningEfforts(settings) : [];
|
|
1508
|
+
return normalizeCapabilities({
|
|
1509
|
+
reasoning: {
|
|
1510
|
+
upstream: input.reasoningEffort ? "supported" : "unknown",
|
|
1511
|
+
runnable: input.reasoningEffort,
|
|
1512
|
+
efforts: reasoningEfforts,
|
|
1513
|
+
defaultEffort: input.reasoningEffort ? settings.openaiReasoningEffort : null,
|
|
1514
|
+
required: false
|
|
1515
|
+
},
|
|
1516
|
+
functionCalling: { upstream: "unknown", runnable: true },
|
|
1517
|
+
structuredOutput: { upstream: "unknown", runnable: false },
|
|
1518
|
+
hostedTools: {
|
|
1519
|
+
webSearch: {
|
|
1520
|
+
upstream: input.hostedWebSearch ? "supported" : "unknown",
|
|
1521
|
+
runnable: input.hostedWebSearch
|
|
1522
|
+
},
|
|
1523
|
+
xSearch: { upstream: "unknown", runnable: false },
|
|
1524
|
+
codeExecution: { upstream: "unknown", runnable: false }
|
|
1525
|
+
},
|
|
1526
|
+
inputModalities: ["text"],
|
|
1527
|
+
outputModalities: ["text"],
|
|
1528
|
+
transports: {
|
|
1529
|
+
sse: { upstream: "unknown", runnable: true },
|
|
1530
|
+
responsesWebSocket: { upstream: "unknown", runnable: false },
|
|
1531
|
+
realtimeAudio: { upstream: "unknown", runnable: false }
|
|
1532
|
+
},
|
|
1533
|
+
latencyModes: [{ id: "standard", upstream: "unknown", runnable: true }]
|
|
1534
|
+
});
|
|
1535
|
+
}
|
|
1536
|
+
function registryCredentialSource(provider) {
|
|
1537
|
+
return provider.kind === "codex-subscription" ? { kind: "connected_subscription", provider: "codex" } : { kind: "deployment", mechanism: "api_key" };
|
|
1538
|
+
}
|
|
1539
|
+
function registryBilling(provider) {
|
|
1540
|
+
return provider.kind === "codex-subscription" ? { upstreamPayer: "connected_subscription", metering: "external" } : { upstreamPayer: "deployment", metering: "opengeni_credits" };
|
|
1541
|
+
}
|
|
1542
|
+
function builtinCredentialSource(settings) {
|
|
1543
|
+
if (settings.openaiProvider === "azure" && !settings.azureOpenaiApiKey) {
|
|
1544
|
+
return { kind: "deployment", mechanism: "azure_ad_bearer" };
|
|
1545
|
+
}
|
|
1546
|
+
return { kind: "deployment", mechanism: "api_key" };
|
|
1547
|
+
}
|
|
1548
|
+
function staticRequestMetadataForDigest(provider) {
|
|
1549
|
+
const publicHeaders = new Set(provider.publicDefaultHeaderNames ?? []);
|
|
1550
|
+
const publicQuery = new Set(provider.publicDefaultQueryNames ?? []);
|
|
1551
|
+
return {
|
|
1552
|
+
headers: Object.entries(provider.defaultHeaders ?? {}).sort(([left], [right]) => left.localeCompare(right)).map(
|
|
1553
|
+
([name, value]) => publicHeaders.has(name) ? { name, classification: "public", value } : { name, classification: "secret" }
|
|
1554
|
+
),
|
|
1555
|
+
query: Object.entries(provider.defaultQuery ?? {}).sort(([left], [right]) => left.localeCompare(right)).map(
|
|
1556
|
+
([name, value]) => publicQuery.has(name) ? { name, classification: "public", value } : { name, classification: "secret" }
|
|
1557
|
+
)
|
|
1558
|
+
};
|
|
1559
|
+
}
|
|
1560
|
+
function canonicalJson(value) {
|
|
1561
|
+
const normalize = (input) => {
|
|
1562
|
+
if (Array.isArray(input)) {
|
|
1563
|
+
return input.map((entry) => normalize(entry));
|
|
1564
|
+
}
|
|
1565
|
+
if (input && typeof input === "object") {
|
|
1566
|
+
const out = {};
|
|
1567
|
+
for (const key of Object.keys(input).sort()) {
|
|
1568
|
+
const child = input[key];
|
|
1569
|
+
if (child !== void 0) {
|
|
1570
|
+
out[key] = normalize(child);
|
|
1571
|
+
}
|
|
1572
|
+
}
|
|
1573
|
+
return out;
|
|
1574
|
+
}
|
|
1575
|
+
return input;
|
|
1576
|
+
};
|
|
1577
|
+
return JSON.stringify(normalize(value));
|
|
1578
|
+
}
|
|
1579
|
+
function definitionVersionFor(model, provider) {
|
|
1580
|
+
const requestMetadata = staticRequestMetadataForDigest(provider);
|
|
1581
|
+
const digestInput = canonicalJson({
|
|
1582
|
+
schemaVersion: model.schemaVersion,
|
|
1583
|
+
id: model.id,
|
|
1584
|
+
providerId: model.providerId,
|
|
1585
|
+
deployment: model.deployment,
|
|
1586
|
+
provider: {
|
|
1587
|
+
adapterKind: provider.kind,
|
|
1588
|
+
wireApi: provider.api,
|
|
1589
|
+
baseUrl: provider.baseUrl ?? null,
|
|
1590
|
+
defaultHeaders: requestMetadata.headers,
|
|
1591
|
+
defaultQuery: requestMetadata.query
|
|
1592
|
+
},
|
|
1593
|
+
credentialSource: model.credentialSource,
|
|
1594
|
+
billing: model.billing,
|
|
1595
|
+
executionLimits: model.executionLimits,
|
|
1596
|
+
capabilities: model.capabilities,
|
|
1597
|
+
pricing: model.pricing ?? null
|
|
1598
|
+
});
|
|
1599
|
+
return `sha256:${createHash("sha256").update("opengeni:model-definition:v1\n", "utf8").update(digestInput, "utf8").digest("hex")}`;
|
|
1600
|
+
}
|
|
1139
1601
|
function builtinProviderId(settings) {
|
|
1140
1602
|
return settings.openaiProvider === "azure" ? "azure" : "openai";
|
|
1141
1603
|
}
|
|
@@ -1143,18 +1605,22 @@ function builtinProviderLabel(settings) {
|
|
|
1143
1605
|
return settings.openaiProvider === "azure" ? "Azure OpenAI" : "OpenAI";
|
|
1144
1606
|
}
|
|
1145
1607
|
function configuredProviders(settings) {
|
|
1608
|
+
const credentialSource = builtinCredentialSource(settings);
|
|
1146
1609
|
const builtin = {
|
|
1147
1610
|
id: builtinProviderId(settings),
|
|
1148
1611
|
label: builtinProviderLabel(settings),
|
|
1149
1612
|
kind: "api-key",
|
|
1150
1613
|
api: "responses",
|
|
1151
|
-
builtin: true
|
|
1614
|
+
builtin: true,
|
|
1615
|
+
credentialSource,
|
|
1616
|
+
billing: { upstreamPayer: "deployment", metering: "opengeni_credits" }
|
|
1152
1617
|
};
|
|
1153
1618
|
if (settings.openaiProvider === "azure") {
|
|
1154
|
-
|
|
1619
|
+
const baseUrl = settings.azureOpenaiBaseUrl ?? settings.azureOpenaiEndpoint;
|
|
1620
|
+
builtin.baseUrl = baseUrl ? normalizeRegistryBaseUrl(baseUrl, builtin.id) : void 0;
|
|
1155
1621
|
builtin.apiKey = settings.azureOpenaiApiKey ?? settings.azureOpenaiAdToken;
|
|
1156
1622
|
} else {
|
|
1157
|
-
builtin.baseUrl = settings.openaiBaseUrl;
|
|
1623
|
+
builtin.baseUrl = settings.openaiBaseUrl ? normalizeRegistryBaseUrl(settings.openaiBaseUrl, builtin.id) : void 0;
|
|
1158
1624
|
builtin.apiKey = settings.openaiApiKey;
|
|
1159
1625
|
}
|
|
1160
1626
|
const registry = parseModelProvidersJson(settings.modelProvidersJson).map(
|
|
@@ -1167,73 +1633,195 @@ function configuredProviders(settings) {
|
|
|
1167
1633
|
baseUrl: provider.baseUrl,
|
|
1168
1634
|
apiKey: resolveProviderApiKey(provider),
|
|
1169
1635
|
defaultQuery: provider.defaultQuery,
|
|
1170
|
-
defaultHeaders: provider.defaultHeaders
|
|
1636
|
+
defaultHeaders: provider.defaultHeaders,
|
|
1637
|
+
publicDefaultQueryNames: provider.publicDefaultQueryNames,
|
|
1638
|
+
publicDefaultHeaderNames: provider.publicDefaultHeaderNames,
|
|
1639
|
+
credentialSource: registryCredentialSource(provider),
|
|
1640
|
+
billing: registryBilling(provider)
|
|
1171
1641
|
})
|
|
1172
1642
|
);
|
|
1173
1643
|
return [builtin, ...registry];
|
|
1174
1644
|
}
|
|
1645
|
+
function withCodexCatalogProvider(settings) {
|
|
1646
|
+
const providers = parseModelProvidersJson(settings.modelProvidersJson);
|
|
1647
|
+
if (providers.some((provider2) => provider2.id === CODEX_PROVIDER_ID)) {
|
|
1648
|
+
return settings;
|
|
1649
|
+
}
|
|
1650
|
+
const provider = {
|
|
1651
|
+
kind: "codex-subscription",
|
|
1652
|
+
id: CODEX_PROVIDER_ID,
|
|
1653
|
+
label: "Codex (ChatGPT subscription)",
|
|
1654
|
+
api: "responses",
|
|
1655
|
+
baseUrl: CODEX_PROVIDER_BASE_URL,
|
|
1656
|
+
models: CODEX_FALLBACK_MODEL_SLUGS.map((slug) => ({
|
|
1657
|
+
id: `${CODEX_MODEL_ID_PREFIX}${slug}`,
|
|
1658
|
+
upstreamModelId: slug,
|
|
1659
|
+
label: slug,
|
|
1660
|
+
reasoningEffort: true,
|
|
1661
|
+
contextWindowTokens: CODEX_MODEL_CONTEXT_WINDOW_TOKENS,
|
|
1662
|
+
effectiveContextWindowTokens: CODEX_MODEL_EFFECTIVE_CONTEXT_WINDOW_TOKENS,
|
|
1663
|
+
autoCompactTokenLimit: CODEX_MODEL_AUTO_COMPACT_TOKEN_LIMIT,
|
|
1664
|
+
toolOutputTruncationTokens: CODEX_MODEL_TOOL_OUTPUT_TRUNCATION_TOKENS
|
|
1665
|
+
}))
|
|
1666
|
+
};
|
|
1667
|
+
return { ...settings, modelProvidersJson: JSON.stringify([...providers, provider]) };
|
|
1668
|
+
}
|
|
1175
1669
|
function policyProviderIdForModel(settings, modelId) {
|
|
1176
|
-
|
|
1670
|
+
const canonicalModelId = canonicalizeConfiguredModelId(settings, modelId);
|
|
1671
|
+
if (canonicalModelId.startsWith(CODEX_MODEL_ID_PREFIX)) {
|
|
1177
1672
|
return CODEX_PROVIDER_ID;
|
|
1178
1673
|
}
|
|
1179
|
-
const configured = configuredModels(settings).find((model) => model.id ===
|
|
1674
|
+
const configured = configuredModels(settings).find((model) => model.id === canonicalModelId);
|
|
1180
1675
|
return configured?.providerId ?? builtinProviderId(settings);
|
|
1181
1676
|
}
|
|
1677
|
+
function resolvedExecutionLimits(settings, model) {
|
|
1678
|
+
return {
|
|
1679
|
+
contextWindowTokens: model.contextWindowTokens ?? settings.contextWindowTokens,
|
|
1680
|
+
effectiveContextWindowTokens: model.effectiveContextWindowTokens ?? settings.contextEffectiveWindowTokens ?? null,
|
|
1681
|
+
autoCompactTokenLimit: model.autoCompactTokenLimit ?? settings.contextAutoCompactThresholdTokens ?? null,
|
|
1682
|
+
toolOutputTruncationTokens: model.toolOutputTruncationTokens ?? settings.modelToolOutputTruncationTokens ?? null
|
|
1683
|
+
};
|
|
1684
|
+
}
|
|
1685
|
+
function finalizeConfiguredModel(settings, provider, input) {
|
|
1686
|
+
const modelWithoutVersion = {
|
|
1687
|
+
schemaVersion: 1,
|
|
1688
|
+
...input,
|
|
1689
|
+
executionLimits: resolvedExecutionLimits(settings, input)
|
|
1690
|
+
};
|
|
1691
|
+
return {
|
|
1692
|
+
...modelWithoutVersion,
|
|
1693
|
+
definitionVersion: definitionVersionFor(modelWithoutVersion, provider)
|
|
1694
|
+
};
|
|
1695
|
+
}
|
|
1696
|
+
function assertUniqueModelIdentities(models) {
|
|
1697
|
+
const canonicalOwners = /* @__PURE__ */ new Map();
|
|
1698
|
+
for (const model of models) {
|
|
1699
|
+
const previous = canonicalOwners.get(model.id);
|
|
1700
|
+
if (previous !== void 0) {
|
|
1701
|
+
throw new Error(
|
|
1702
|
+
`OPENGENI_MODEL_PROVIDERS_JSON model id ${JSON.stringify(model.id)} is declared by both ${previous} and ${model.providerId}`
|
|
1703
|
+
);
|
|
1704
|
+
}
|
|
1705
|
+
canonicalOwners.set(model.id, model.providerId);
|
|
1706
|
+
}
|
|
1707
|
+
const acceptedInputs = new Map(canonicalOwners);
|
|
1708
|
+
for (const model of models) {
|
|
1709
|
+
const ownAliases = /* @__PURE__ */ new Set();
|
|
1710
|
+
for (const alias of model.aliases) {
|
|
1711
|
+
if (ownAliases.has(alias)) {
|
|
1712
|
+
throw new Error(
|
|
1713
|
+
`OPENGENI_MODEL_PROVIDERS_JSON model ${JSON.stringify(model.id)} contains duplicate alias ${JSON.stringify(alias)}`
|
|
1714
|
+
);
|
|
1715
|
+
}
|
|
1716
|
+
ownAliases.add(alias);
|
|
1717
|
+
const previous = acceptedInputs.get(alias);
|
|
1718
|
+
if (previous !== void 0) {
|
|
1719
|
+
throw new Error(
|
|
1720
|
+
`OPENGENI_MODEL_PROVIDERS_JSON alias ${JSON.stringify(alias)} for model ${JSON.stringify(model.id)} collides with model/provider ${previous}`
|
|
1721
|
+
);
|
|
1722
|
+
}
|
|
1723
|
+
acceptedInputs.set(alias, model.id);
|
|
1724
|
+
}
|
|
1725
|
+
}
|
|
1726
|
+
}
|
|
1182
1727
|
function configuredModels(settings) {
|
|
1183
1728
|
const builtinId = builtinProviderId(settings);
|
|
1184
1729
|
const builtinLabel = builtinProviderLabel(settings);
|
|
1730
|
+
const providers = configuredProviders(settings);
|
|
1731
|
+
const providerById = new Map(providers.map((provider) => [provider.id, provider]));
|
|
1732
|
+
const pricingSchedules = configuredModelPricingSchedules(settings);
|
|
1733
|
+
const parsedRegistry = parseModelProvidersJson(settings.modelProvidersJson);
|
|
1185
1734
|
const registryOwnedIds = new Set(
|
|
1186
|
-
|
|
1187
|
-
(provider) => provider.models.map((model) => model.id)
|
|
1188
|
-
)
|
|
1735
|
+
parsedRegistry.flatMap((provider) => provider.models.map((model) => model.id))
|
|
1189
1736
|
);
|
|
1190
|
-
const
|
|
1737
|
+
const registryAliases = new Set(
|
|
1738
|
+
parsedRegistry.flatMap((provider) => provider.models.flatMap((model) => model.aliases ?? []))
|
|
1739
|
+
);
|
|
1740
|
+
const isRegistryNamespaced = (id) => id.startsWith(CODEX_MODEL_ID_PREFIX) || registryAliases.has(id) || id.includes("/") && registryOwnedIds.has(id);
|
|
1741
|
+
const builtinProvider = providerById.get(builtinId);
|
|
1742
|
+
if (!builtinProvider) {
|
|
1743
|
+
throw new Error(`Built-in model provider ${builtinId} is not configured`);
|
|
1744
|
+
}
|
|
1191
1745
|
const out = uniqueValues([
|
|
1192
1746
|
settings.openaiModel,
|
|
1193
1747
|
...splitCsv(settings.openaiAllowedModels)
|
|
1194
|
-
]).filter((id) => !isRegistryNamespaced(id)).map((id) =>
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1748
|
+
]).filter((id) => !isRegistryNamespaced(id)).map((id) => {
|
|
1749
|
+
const capabilities = legacyModelCapabilities(settings, {
|
|
1750
|
+
reasoningEffort: true,
|
|
1751
|
+
hostedWebSearch: settings.webSearchEnabled
|
|
1752
|
+
});
|
|
1753
|
+
return finalizeConfiguredModel(settings, builtinProvider, {
|
|
1754
|
+
id,
|
|
1755
|
+
aliases: [],
|
|
1756
|
+
label: id,
|
|
1757
|
+
providerId: builtinId,
|
|
1758
|
+
providerLabel: builtinLabel,
|
|
1759
|
+
api: "responses",
|
|
1760
|
+
upstreamModelId: id,
|
|
1761
|
+
deployment: { upstreamModelId: id, wireApi: "responses" },
|
|
1762
|
+
credentialSource: builtinProvider.credentialSource,
|
|
1763
|
+
billing: builtinProvider.billing,
|
|
1764
|
+
capabilities,
|
|
1765
|
+
...pricingSchedules[id] === void 0 ? {} : { pricing: pricingSchedules[id] },
|
|
1766
|
+
contextWindowTokens: settings.contextWindowTokens,
|
|
1767
|
+
toolOutputTruncationTokens: settings.modelToolOutputTruncationTokens,
|
|
1768
|
+
reasoningEffort: capabilities.reasoning.runnable,
|
|
1769
|
+
hostedWebSearch: capabilities.hostedTools.webSearch.runnable
|
|
1770
|
+
});
|
|
1771
|
+
});
|
|
1772
|
+
for (const provider of parsedRegistry) {
|
|
1206
1773
|
const providerLabel = provider.label ?? provider.id;
|
|
1774
|
+
const resolvedProvider = providerById.get(provider.id);
|
|
1775
|
+
if (!resolvedProvider) {
|
|
1776
|
+
throw new Error(`Registry model provider ${provider.id} is not configured`);
|
|
1777
|
+
}
|
|
1207
1778
|
for (const model of provider.models) {
|
|
1208
|
-
|
|
1209
|
-
id: model.id,
|
|
1210
|
-
label: model.label ?? model.id,
|
|
1211
|
-
providerId: provider.id,
|
|
1212
|
-
providerLabel,
|
|
1213
|
-
api: provider.api,
|
|
1214
|
-
...model.contextWindowTokens === void 0 ? {} : { contextWindowTokens: model.contextWindowTokens },
|
|
1215
|
-
...model.effectiveContextWindowTokens === void 0 ? {} : { effectiveContextWindowTokens: model.effectiveContextWindowTokens },
|
|
1216
|
-
...model.autoCompactTokenLimit === void 0 ? {} : { autoCompactTokenLimit: model.autoCompactTokenLimit },
|
|
1217
|
-
...model.toolOutputTruncationTokens === void 0 ? {} : { toolOutputTruncationTokens: model.toolOutputTruncationTokens },
|
|
1779
|
+
const capabilities = model.capabilities ? normalizeCapabilities(model.capabilities) : legacyModelCapabilities(settings, {
|
|
1218
1780
|
reasoningEffort: model.reasoningEffort ?? false,
|
|
1219
1781
|
hostedWebSearch: model.hostedWebSearch ?? false
|
|
1220
1782
|
});
|
|
1783
|
+
const upstreamModelId = model.upstreamModelId ?? model.id;
|
|
1784
|
+
out.push(
|
|
1785
|
+
finalizeConfiguredModel(settings, resolvedProvider, {
|
|
1786
|
+
id: model.id,
|
|
1787
|
+
aliases: [...model.aliases ?? []],
|
|
1788
|
+
label: model.label ?? model.id,
|
|
1789
|
+
providerId: provider.id,
|
|
1790
|
+
providerLabel,
|
|
1791
|
+
api: provider.api,
|
|
1792
|
+
upstreamModelId,
|
|
1793
|
+
deployment: { upstreamModelId, wireApi: provider.api },
|
|
1794
|
+
credentialSource: resolvedProvider.credentialSource,
|
|
1795
|
+
billing: resolvedProvider.billing,
|
|
1796
|
+
capabilities,
|
|
1797
|
+
...pricingSchedules[model.id] === void 0 ? {} : { pricing: pricingSchedules[model.id] },
|
|
1798
|
+
...model.contextWindowTokens === void 0 ? {} : { contextWindowTokens: model.contextWindowTokens },
|
|
1799
|
+
...model.effectiveContextWindowTokens === void 0 ? {} : { effectiveContextWindowTokens: model.effectiveContextWindowTokens },
|
|
1800
|
+
...model.autoCompactTokenLimit === void 0 ? {} : { autoCompactTokenLimit: model.autoCompactTokenLimit },
|
|
1801
|
+
...model.toolOutputTruncationTokens === void 0 ? {} : { toolOutputTruncationTokens: model.toolOutputTruncationTokens },
|
|
1802
|
+
reasoningEffort: capabilities.reasoning.runnable,
|
|
1803
|
+
hostedWebSearch: capabilities.hostedTools.webSearch.runnable
|
|
1804
|
+
})
|
|
1805
|
+
);
|
|
1221
1806
|
}
|
|
1222
1807
|
}
|
|
1223
|
-
|
|
1224
|
-
return out
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1808
|
+
assertUniqueModelIdentities(out);
|
|
1809
|
+
return out;
|
|
1810
|
+
}
|
|
1811
|
+
function canonicalizeConfiguredModelId(settings, modelId) {
|
|
1812
|
+
const models = configuredModels(settings);
|
|
1813
|
+
const canonical = models.find((model) => model.id === modelId);
|
|
1814
|
+
if (canonical) {
|
|
1815
|
+
return canonical.id;
|
|
1816
|
+
}
|
|
1817
|
+
return models.find((model) => model.aliases.includes(modelId))?.id ?? modelId;
|
|
1231
1818
|
}
|
|
1232
1819
|
function configuredAllowedModels(settings) {
|
|
1233
1820
|
return configuredModels(settings).map((model) => model.id);
|
|
1234
1821
|
}
|
|
1235
1822
|
function resolveModelProvider(settings, modelId) {
|
|
1236
|
-
const
|
|
1823
|
+
const canonicalModelId = canonicalizeConfiguredModelId(settings, modelId);
|
|
1824
|
+
const model = configuredModels(settings).find((candidate) => candidate.id === canonicalModelId);
|
|
1237
1825
|
if (!model) {
|
|
1238
1826
|
return void 0;
|
|
1239
1827
|
}
|
|
@@ -1245,22 +1833,97 @@ function resolveModelProvider(settings, modelId) {
|
|
|
1245
1833
|
}
|
|
1246
1834
|
return { provider, model };
|
|
1247
1835
|
}
|
|
1248
|
-
function
|
|
1836
|
+
function settingsForTurnExecutionPolicy(settings, modelId) {
|
|
1837
|
+
return settings.codexSubscriptionEnabled && modelId.startsWith(CODEX_MODEL_ID_PREFIX) ? withCodexCatalogProvider(settings) : settings;
|
|
1838
|
+
}
|
|
1839
|
+
function resolveTurnExecutionPolicyV1(settings, input) {
|
|
1840
|
+
const catalogSettings = settingsForTurnExecutionPolicy(settings, input.modelId);
|
|
1841
|
+
const productModelId = canonicalizeConfiguredModelId(catalogSettings, input.modelId);
|
|
1842
|
+
const resolved = resolveModelProvider(catalogSettings, productModelId);
|
|
1843
|
+
if (!resolved) {
|
|
1844
|
+
throw new Error("Turn execution policy model is not present in the configured catalog");
|
|
1845
|
+
}
|
|
1846
|
+
if (input.requestedModelId !== null && canonicalizeConfiguredModelId(catalogSettings, input.requestedModelId) !== productModelId) {
|
|
1847
|
+
throw new Error("Turn execution policy requested model does not canonicalize to its product");
|
|
1848
|
+
}
|
|
1849
|
+
return TurnExecutionPolicyV1.parse({
|
|
1850
|
+
schemaVersion: 1,
|
|
1851
|
+
productModelId,
|
|
1852
|
+
requestedModelId: input.requestedModelId,
|
|
1853
|
+
modelSource: input.modelSource,
|
|
1854
|
+
reasoningEffort: input.reasoningEffort,
|
|
1855
|
+
reasoningSource: input.reasoningSource,
|
|
1856
|
+
providerId: resolved.provider.id,
|
|
1857
|
+
upstreamModelId: resolved.model.upstreamModelId,
|
|
1858
|
+
wireApi: resolved.model.api,
|
|
1859
|
+
credentialSource: resolved.model.credentialSource,
|
|
1860
|
+
billing: resolved.model.billing,
|
|
1861
|
+
definitionVersion: resolved.model.definitionVersion
|
|
1862
|
+
});
|
|
1863
|
+
}
|
|
1864
|
+
function assertTurnExecutionPolicyMatchesConfigV1(settings, policy, expected) {
|
|
1865
|
+
const parsed = TurnExecutionPolicyV1.parse(policy);
|
|
1866
|
+
const catalogSettings = settingsForTurnExecutionPolicy(settings, parsed.productModelId);
|
|
1867
|
+
const canonicalExpectedModel = canonicalizeConfiguredModelId(catalogSettings, expected.modelId);
|
|
1868
|
+
if (parsed.productModelId !== canonicalExpectedModel || parsed.reasoningEffort !== expected.reasoningEffort) {
|
|
1869
|
+
throw new Error("Turn execution policy does not match the accepted turn model/reasoning");
|
|
1870
|
+
}
|
|
1871
|
+
if (parsed.requestedModelId !== null && canonicalizeConfiguredModelId(catalogSettings, parsed.requestedModelId) !== parsed.productModelId) {
|
|
1872
|
+
throw new Error("Turn execution policy requested model does not match its product model");
|
|
1873
|
+
}
|
|
1874
|
+
const resolved = resolveModelProvider(catalogSettings, parsed.productModelId);
|
|
1875
|
+
if (!resolved) {
|
|
1876
|
+
throw new Error("Turn execution policy model is no longer configured");
|
|
1877
|
+
}
|
|
1878
|
+
const mismatched = parsed.providerId !== resolved.provider.id || parsed.upstreamModelId !== resolved.model.upstreamModelId || parsed.wireApi !== resolved.model.api || parsed.definitionVersion !== resolved.model.definitionVersion || canonicalJson(parsed.credentialSource) !== canonicalJson(resolved.model.credentialSource) || canonicalJson(parsed.billing) !== canonicalJson(resolved.model.billing);
|
|
1879
|
+
if (mismatched) {
|
|
1880
|
+
throw new Error("Turn execution policy does not match the current provider definition");
|
|
1881
|
+
}
|
|
1882
|
+
return { policy: parsed, provider: resolved.provider, model: resolved.model };
|
|
1883
|
+
}
|
|
1884
|
+
function configuredModelPricingSchedules(settings) {
|
|
1885
|
+
const defaults = Object.fromEntries(
|
|
1886
|
+
Object.entries(defaultModelPricing).map(([model, pricing]) => [model, { default: pricing }])
|
|
1887
|
+
);
|
|
1249
1888
|
const registry = {};
|
|
1250
1889
|
for (const provider of parseModelProvidersJson(settings.modelProvidersJson)) {
|
|
1251
1890
|
for (const model of provider.models) {
|
|
1252
1891
|
if (model.pricing) {
|
|
1253
|
-
registry[model.id] = model.pricing;
|
|
1892
|
+
registry[model.id] = normalizeModelPricingSchedule(model.pricing);
|
|
1254
1893
|
}
|
|
1255
1894
|
}
|
|
1256
1895
|
}
|
|
1257
|
-
const configured =
|
|
1896
|
+
const configured = Object.fromEntries(
|
|
1897
|
+
Object.entries(parseModelPricingJson(settings.modelPricingJson)).map(([model, pricing]) => [
|
|
1898
|
+
model,
|
|
1899
|
+
{ default: pricing }
|
|
1900
|
+
])
|
|
1901
|
+
);
|
|
1258
1902
|
return {
|
|
1259
|
-
...
|
|
1903
|
+
...defaults,
|
|
1260
1904
|
...registry,
|
|
1261
1905
|
...configured
|
|
1262
1906
|
};
|
|
1263
1907
|
}
|
|
1908
|
+
function configuredModelPricing(settings) {
|
|
1909
|
+
return Object.fromEntries(
|
|
1910
|
+
Object.entries(configuredModelPricingSchedules(settings)).map(([model, schedule]) => [
|
|
1911
|
+
model,
|
|
1912
|
+
schedule.default
|
|
1913
|
+
])
|
|
1914
|
+
);
|
|
1915
|
+
}
|
|
1916
|
+
function selectModelPricing(schedule, inputTokens) {
|
|
1917
|
+
const normalizedInputTokens = Math.max(0, Math.floor(inputTokens));
|
|
1918
|
+
let selected = schedule.default;
|
|
1919
|
+
for (const tier of schedule.inputTokenTiers ?? []) {
|
|
1920
|
+
if (normalizedInputTokens < tier.minimumInputTokens) {
|
|
1921
|
+
break;
|
|
1922
|
+
}
|
|
1923
|
+
selected = tier.pricing;
|
|
1924
|
+
}
|
|
1925
|
+
return selected;
|
|
1926
|
+
}
|
|
1264
1927
|
function contextInputBudgetTokens(settings) {
|
|
1265
1928
|
if (settings.contextEffectiveWindowTokens !== void 0) {
|
|
1266
1929
|
return Math.min(settings.contextWindowTokens, settings.contextEffectiveWindowTokens);
|
|
@@ -1303,14 +1966,25 @@ function configuredEntitlements(settings) {
|
|
|
1303
1966
|
};
|
|
1304
1967
|
}
|
|
1305
1968
|
function calculateModelUsageCostMicros(settings, model, usage) {
|
|
1306
|
-
const
|
|
1307
|
-
if (!
|
|
1969
|
+
const schedule = configuredModelPricingSchedules(settings)[model];
|
|
1970
|
+
if (!schedule) {
|
|
1308
1971
|
throw new Error(`Missing model pricing for ${model}`);
|
|
1309
1972
|
}
|
|
1310
1973
|
const entries = usage.requestUsageEntries && usage.requestUsageEntries.length > 0 ? usage.requestUsageEntries : [usage];
|
|
1311
|
-
const
|
|
1312
|
-
const
|
|
1313
|
-
|
|
1974
|
+
const rawCostByPricing = /* @__PURE__ */ new Map();
|
|
1975
|
+
for (const entry of entries) {
|
|
1976
|
+
const pricing = selectModelPricing(schedule, positiveInt(entry.inputTokens));
|
|
1977
|
+
rawCostByPricing.set(
|
|
1978
|
+
pricing,
|
|
1979
|
+
(rawCostByPricing.get(pricing) ?? 0) + calculateEntryCostMicros(pricing, entry)
|
|
1980
|
+
);
|
|
1981
|
+
}
|
|
1982
|
+
let total = 0;
|
|
1983
|
+
for (const [pricing, rawCost] of rawCostByPricing) {
|
|
1984
|
+
const marginBps = pricing.marginBps ?? 0;
|
|
1985
|
+
total += Math.ceil(rawCost * (1e4 + marginBps) / 1e4);
|
|
1986
|
+
}
|
|
1987
|
+
return total;
|
|
1314
1988
|
}
|
|
1315
1989
|
function configuredAllowedReasoningEfforts(settings) {
|
|
1316
1990
|
return uniqueValues([
|
|
@@ -1634,7 +2308,14 @@ function parseModelProvidersJson(raw) {
|
|
|
1634
2308
|
`OPENGENI_MODEL_PROVIDERS_JSON provider[${index}] is invalid: ${result.error.message}`
|
|
1635
2309
|
);
|
|
1636
2310
|
}
|
|
1637
|
-
|
|
2311
|
+
try {
|
|
2312
|
+
return normalizeRegistryProvider(result.data);
|
|
2313
|
+
} catch (error) {
|
|
2314
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
2315
|
+
throw new Error(`OPENGENI_MODEL_PROVIDERS_JSON provider[${index}] is invalid: ${message}`, {
|
|
2316
|
+
cause: error
|
|
2317
|
+
});
|
|
2318
|
+
}
|
|
1638
2319
|
});
|
|
1639
2320
|
}
|
|
1640
2321
|
function parseIntegrationsOauthClientsJson(raw) {
|
|
@@ -2040,6 +2721,7 @@ function validateSettings(settings) {
|
|
|
2040
2721
|
);
|
|
2041
2722
|
}
|
|
2042
2723
|
}
|
|
2724
|
+
configuredModels(settings);
|
|
2043
2725
|
}
|
|
2044
2726
|
function resolveStreamTokenSecret(settings) {
|
|
2045
2727
|
const explicit = settings.streamTokenSecret?.trim();
|
|
@@ -2125,21 +2807,27 @@ function delay(ms) {
|
|
|
2125
2807
|
}
|
|
2126
2808
|
export {
|
|
2127
2809
|
AGENT_INSTRUCTIONS_CORE_PLACEHOLDER,
|
|
2810
|
+
CapabilityStateV1Schema,
|
|
2811
|
+
CapabilitySupportV1,
|
|
2128
2812
|
DEFAULT_AGENT_INSTRUCTIONS,
|
|
2129
2813
|
IntegrationOAuthClientConfigSchema,
|
|
2130
2814
|
McpServerConnectionRefSchema,
|
|
2815
|
+
ModelCapabilitiesV1Schema,
|
|
2131
2816
|
ModelProviderApi,
|
|
2132
2817
|
RegistryProviderKind,
|
|
2133
2818
|
SANDBOX_REQUIRED_ENV,
|
|
2134
2819
|
applyGitAuthPointerEnvironment,
|
|
2820
|
+
assertTurnExecutionPolicyMatchesConfigV1,
|
|
2135
2821
|
builtinProviderId,
|
|
2136
2822
|
calculateModelUsageCostMicros,
|
|
2823
|
+
canonicalizeConfiguredModelId,
|
|
2137
2824
|
collectGitIdentityEnvironment,
|
|
2138
2825
|
collectSandboxEnvironment,
|
|
2139
2826
|
configuredAllowedModels,
|
|
2140
2827
|
configuredAllowedReasoningEfforts,
|
|
2141
2828
|
configuredEntitlements,
|
|
2142
2829
|
configuredModelPricing,
|
|
2830
|
+
configuredModelPricingSchedules,
|
|
2143
2831
|
configuredModels,
|
|
2144
2832
|
configuredProviders,
|
|
2145
2833
|
configuredStaticUsageLimits,
|
|
@@ -2170,15 +2858,18 @@ export {
|
|
|
2170
2858
|
resolveProviderApiKey,
|
|
2171
2859
|
resolveRelayTokenSecret,
|
|
2172
2860
|
resolveStreamTokenSecret,
|
|
2861
|
+
resolveTurnExecutionPolicyV1,
|
|
2173
2862
|
retryStartupDependency,
|
|
2174
2863
|
sandboxEnvironmentVariableNames,
|
|
2175
2864
|
sandboxLifecycleHookIds,
|
|
2176
2865
|
sandboxPreparationProfiles,
|
|
2177
2866
|
sandboxWarmRateMicrosPerSecond,
|
|
2867
|
+
selectModelPricing,
|
|
2178
2868
|
settingsWithResolvedModelContext,
|
|
2179
2869
|
stableSandboxEnvironmentForRun,
|
|
2180
2870
|
startupRetryOptions,
|
|
2181
2871
|
streamTokenDegraded,
|
|
2182
|
-
temporalConnectionOptions
|
|
2872
|
+
temporalConnectionOptions,
|
|
2873
|
+
withCodexCatalogProvider
|
|
2183
2874
|
};
|
|
2184
2875
|
//# sourceMappingURL=index.js.map
|