@opengeni/config 0.22.5 → 1.0.0-canary.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 +724 -23
- package/dist/index.js +1048 -134
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
- package/src/index.ts +1330 -165
package/dist/index.js
CHANGED
|
@@ -45,6 +45,10 @@ import { createHash } from "crypto";
|
|
|
45
45
|
import { z } from "zod";
|
|
46
46
|
var envName = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
47
47
|
var registryId = /^[A-Za-z0-9_-]+$/;
|
|
48
|
+
var DEFAULT_OPENROUTER_MODEL_ID = "openrouter/nvidia/nemotron-3-super-120b-a12b:free";
|
|
49
|
+
var DEFAULT_MODEL_COST_POLICY_JSON = JSON.stringify({
|
|
50
|
+
[DEFAULT_OPENROUTER_MODEL_ID]: "free"
|
|
51
|
+
});
|
|
48
52
|
var SANDBOX_ARCHIVE_CAPTURE_MAX_TIMEOUT_MS = 60 * 6e4;
|
|
49
53
|
var SANDBOX_ARCHIVE_CAPTURE_SETTLEMENT_GRACE_MS = 1e4;
|
|
50
54
|
var SANDBOX_SNAPSHOT_MAX_TIMEOUT_MS = SANDBOX_ARCHIVE_CAPTURE_MAX_TIMEOUT_MS - SANDBOX_ARCHIVE_CAPTURE_SETTLEMENT_GRACE_MS;
|
|
@@ -177,8 +181,16 @@ var McpServerConnectionRefSchema = z.object({
|
|
|
177
181
|
seen.add(key);
|
|
178
182
|
}
|
|
179
183
|
}).optional(),
|
|
184
|
+
authoritySource: z.literal("host").optional(),
|
|
180
185
|
subjectScope: z.enum(["workspace", "subject"]).optional()
|
|
181
186
|
}).strict().superRefine((reference, context) => {
|
|
187
|
+
if (reference.authoritySource === "host" && !reference.connectionId) {
|
|
188
|
+
context.addIssue({
|
|
189
|
+
code: "custom",
|
|
190
|
+
message: "host authority requires connectionId",
|
|
191
|
+
path: ["connectionId"]
|
|
192
|
+
});
|
|
193
|
+
}
|
|
182
194
|
if (!reference.selectedResources) return;
|
|
183
195
|
if (!reference.connectionId) {
|
|
184
196
|
context.addIssue({
|
|
@@ -195,6 +207,7 @@ var McpServerConnectionRefSchema = z.object({
|
|
|
195
207
|
});
|
|
196
208
|
}
|
|
197
209
|
});
|
|
210
|
+
var DEFAULT_MODAL_IMAGE_REF = "opengenipublicneuacr.azurecr.io/opengeni-desktop@sha256:c3bd17b8841de1bff9bb2777aad422cf8c75de78e2c30f9ac81d0cd6810a1b78";
|
|
198
211
|
var SettingsSchema = z.object({
|
|
199
212
|
serviceName: z.string().default("opengeni"),
|
|
200
213
|
environment: z.string().default("local"),
|
|
@@ -251,6 +264,12 @@ var SettingsSchema = z.object({
|
|
|
251
264
|
analyticsPosthogHost: z.string().url().max(2048).optional(),
|
|
252
265
|
analyticsGa4MeasurementId: z.string().max(32).regex(/^G-[A-Z0-9]+$/u).optional(),
|
|
253
266
|
publicBaseUrl: z.string().url().optional(),
|
|
267
|
+
// Standards-based OAuth authorization server for external workspace MCP
|
|
268
|
+
// clients. Opt-in because it creates a new public authentication surface.
|
|
269
|
+
mcpOauthEnabled: EnvBoolean.default(false),
|
|
270
|
+
// Forwarded client addresses are ignored by default. Operators may trust an
|
|
271
|
+
// exact number of proxy hops only when direct access to the API is blocked.
|
|
272
|
+
mcpOauthTrustedProxyHops: z.coerce.number().int().min(0).max(16).default(0),
|
|
254
273
|
// Browser origin when the web app and API use separate origins in local
|
|
255
274
|
// development. Production normally leaves this unset and uses publicBaseUrl.
|
|
256
275
|
webBaseUrl: z.string().url().optional(),
|
|
@@ -384,6 +403,13 @@ var SettingsSchema = z.object({
|
|
|
384
403
|
// into @opengeni/db once at boot.
|
|
385
404
|
// Env: OPENGENI_CHILD_LIFECYCLE_NOTICES_ENABLED.
|
|
386
405
|
childLifecycleNoticesEnabled: EnvBoolean.default(false),
|
|
406
|
+
// Explicit host-owned MCP connection authority is a rolling protocol
|
|
407
|
+
// activation. Keep it off while any API, worker, or browser bundle predates
|
|
408
|
+
// the authority discriminator; enable it only after the whole fleet runs an
|
|
409
|
+
// image that understands host refs. Legacy markerless non-UUID refs remain a
|
|
410
|
+
// separate compatibility lane for already-persisted embedding integrations.
|
|
411
|
+
// Env: OPENGENI_HOST_MCP_AUTHORITY_SOURCE_ADMISSION_ENABLED.
|
|
412
|
+
hostMcpAuthoritySourceAdmissionEnabled: EnvBoolean.default(false),
|
|
387
413
|
// Per-channel and per-DM Slack workspace routing. Default ON. A channel does
|
|
388
414
|
// not count a personal workspace as a candidate, so an organization with one
|
|
389
415
|
// shared workspace resolves it as the sole candidate and never asks; the
|
|
@@ -511,6 +537,24 @@ var SettingsSchema = z.object({
|
|
|
511
537
|
// keep subscription model routing while disabling Codex voice input.
|
|
512
538
|
voiceInputCodexExperimentalEnabled: EnvBoolean.default(false),
|
|
513
539
|
modelPricingJson: z.string().default("{}"),
|
|
540
|
+
// Supported-model membership source. Database mode is resolved by the async
|
|
541
|
+
// core overlay; getSettings remains synchronous and env-only.
|
|
542
|
+
modelCatalogSource: z.enum(["code", "database"]).default("code"),
|
|
543
|
+
// Deployment-owned workspace-facing price policy. This is deliberately
|
|
544
|
+
// separate from catalog membership and upstream credential ownership.
|
|
545
|
+
// Shape: { "product/model-id": "free" | "credits" }.
|
|
546
|
+
modelCostPolicyJson: z.string().default("{}"),
|
|
547
|
+
// Optional per-product agent guidance. Database mode replaces this with the
|
|
548
|
+
// singleton document's validated modelNotes map.
|
|
549
|
+
modelNotesJson: z.string().default("{}"),
|
|
550
|
+
// Managed OpenRouter credential. The curated model table is injected in
|
|
551
|
+
// code/catalog-document resolution and never read from host provider JSON.
|
|
552
|
+
openrouterApiKey: z.string().optional(),
|
|
553
|
+
// Internal, secret-free catalog overlays populated only by
|
|
554
|
+
// applyModelCatalogDocument. They intentionally have no OPENGENI_* env
|
|
555
|
+
// binding so database mode cannot be bypassed with a second source.
|
|
556
|
+
resolvedGatewayModelsJson: z.string().optional(),
|
|
557
|
+
resolvedOpenRouterModelsJson: z.string().optional(),
|
|
514
558
|
// Extra (non-built-in) model providers, declared by the host as a JSON
|
|
515
559
|
// provider registry. Each entry carries its own base URL, API key, wire API
|
|
516
560
|
// ("responses" | "chat") and the models it exposes. The models a client may
|
|
@@ -552,11 +596,6 @@ var SettingsSchema = z.object({
|
|
|
552
596
|
// the Codex rollout so an emergency Codex opt-out cannot disable every model.
|
|
553
597
|
// OPENGENI_LAZY_TOOL_SEARCH_ENABLED
|
|
554
598
|
lazyToolSearchEnabled: EnvBoolean.default(true),
|
|
555
|
-
// credential allocator atomic, workspace-local credential allocation. Default OFF is a
|
|
556
|
-
// deliberate rolling-deploy fence: migrate + roll every worker first, then
|
|
557
|
-
// enable. Turning it off restores the legacy sticky selector without a schema
|
|
558
|
-
// rollback; the additive lease table/cursor columns become inert.
|
|
559
|
-
codexCredentialLeasingEnabled: EnvBoolean.default(false),
|
|
560
599
|
// Decision-observability fence. When enabled, the worker emits one
|
|
561
600
|
// bounded, metadata-only adaptive-policy replay record alongside the unchanged
|
|
562
601
|
// sticky-sharded decision. It never changes placement/admission/failover.
|
|
@@ -956,6 +995,13 @@ var SettingsSchema = z.object({
|
|
|
956
995
|
// treated exactly like a failed best-effort snapshot. Knob:
|
|
957
996
|
// OPENGENI_SANDBOX_SNAPSHOT_TIMEOUT_MS. Default 60s.
|
|
958
997
|
sandboxSnapshotTimeoutMs: z.coerce.number().int().positive().max(SANDBOX_SNAPSHOT_MAX_TIMEOUT_MS).default(6e4),
|
|
998
|
+
// A zero-holder drain may need substantially longer than a best-effort
|
|
999
|
+
// mid-turn/turn-end snapshot for a very large workspace. Keep that provider
|
|
1000
|
+
// budget independent so increasing drain recovery headroom cannot pin an
|
|
1001
|
+
// ordinary turn finalizer for the same duration. Unset preserves the legacy
|
|
1002
|
+
// single-budget behavior. Knob:
|
|
1003
|
+
// OPENGENI_SANDBOX_DRAIN_SNAPSHOT_TIMEOUT_MS.
|
|
1004
|
+
sandboxDrainSnapshotTimeoutMs: z.coerce.number().int().positive().max(SANDBOX_SNAPSHOT_MAX_TIMEOUT_MS).optional(),
|
|
959
1005
|
// Begin a controlled snapshot/quiesce/drain/rematerialize transition this far
|
|
960
1006
|
// ahead of a finite provider deadline. Modal's 24h creation clock cannot be
|
|
961
1007
|
// extended; the logical sandbox outlives it by moving to one successor box.
|
|
@@ -1073,6 +1119,15 @@ var SettingsSchema = z.object({
|
|
|
1073
1119
|
// Rolling browser login-slot compatibility. Repository/deployment default is
|
|
1074
1120
|
// deliberately legacy; changing to broker is an operator-authorized rollout.
|
|
1075
1121
|
managedAuthSessionSetMode: z.enum(["legacy", "dual", "broker"]).default("legacy"),
|
|
1122
|
+
// Query transport is an explicit second-stage rollout. A pre-compatibility
|
|
1123
|
+
// web image understands only fragment bearers, so API replicas must keep
|
|
1124
|
+
// generating fragment links until the compatible web fleet has converged.
|
|
1125
|
+
organizationUserSetupEmailTokenTransport: z.enum(["fragment", "query"]).default("fragment"),
|
|
1126
|
+
// Query-bearing setup links may appear in controller/edge error logs even
|
|
1127
|
+
// when access logs and request tracing are disabled. This explicit operator
|
|
1128
|
+
// confirmation keeps query transport fail closed until that separate sink is
|
|
1129
|
+
// proven sanitized.
|
|
1130
|
+
organizationUserSetupQueryEdgeSanitizationConfirmed: EnvBoolean.default(false),
|
|
1076
1131
|
resendApiKey: z.string().optional(),
|
|
1077
1132
|
emailFrom: z.string().default("OpenGeni <auth@mail.opengeni.ai>"),
|
|
1078
1133
|
stripeSecretKey: z.string().optional(),
|
|
@@ -1227,6 +1282,7 @@ function voiceInputDeploymentConfigured(settings) {
|
|
|
1227
1282
|
var ModelPricingSchema = z.object({
|
|
1228
1283
|
inputMicrosPerMillionTokens: z.number().int().nonnegative(),
|
|
1229
1284
|
cachedInputMicrosPerMillionTokens: z.number().int().nonnegative().optional(),
|
|
1285
|
+
cacheWriteMicrosPerMillionTokens: z.number().int().nonnegative().optional(),
|
|
1230
1286
|
outputMicrosPerMillionTokens: z.number().int().nonnegative(),
|
|
1231
1287
|
marginBps: z.number().int().min(0).max(1e5).optional()
|
|
1232
1288
|
});
|
|
@@ -1362,7 +1418,10 @@ var RegistryProviderKind = z.enum([
|
|
|
1362
1418
|
"codex-subscription",
|
|
1363
1419
|
"xai-subscription",
|
|
1364
1420
|
"vercel-gateway-managed",
|
|
1365
|
-
"vercel-gateway-workspace"
|
|
1421
|
+
"vercel-gateway-workspace",
|
|
1422
|
+
"vercel-gateway-organization",
|
|
1423
|
+
"openrouter-workspace",
|
|
1424
|
+
"openrouter-organization"
|
|
1366
1425
|
]);
|
|
1367
1426
|
var RegistryModelSchema = z.object({
|
|
1368
1427
|
id: z.string().min(1),
|
|
@@ -1475,6 +1534,297 @@ var RegistryProviderSchema = z.object({
|
|
|
1475
1534
|
});
|
|
1476
1535
|
}
|
|
1477
1536
|
});
|
|
1537
|
+
var OPENGENI_GATEWAY_PROVIDER_ID = "opengeni-gateway";
|
|
1538
|
+
var WORKSPACE_GATEWAY_PROVIDER_ID = "workspace-gateway";
|
|
1539
|
+
var WORKSPACE_GATEWAY_MODEL_ID_PREFIX = "workspace-gateway/";
|
|
1540
|
+
var ORGANIZATION_GATEWAY_PROVIDER_ID = "organization-gateway";
|
|
1541
|
+
var ORGANIZATION_GATEWAY_MODEL_ID_PREFIX = "organization-gateway/";
|
|
1542
|
+
var OPENROUTER_PROVIDER_ID = "openrouter";
|
|
1543
|
+
var OPENROUTER_MODEL_ID_PREFIX = "openrouter/";
|
|
1544
|
+
var WORKSPACE_OPENROUTER_PROVIDER_ID = "workspace-openrouter";
|
|
1545
|
+
var WORKSPACE_OPENROUTER_MODEL_ID_PREFIX = "workspace-openrouter/";
|
|
1546
|
+
var ORGANIZATION_OPENROUTER_PROVIDER_ID = "organization-openrouter";
|
|
1547
|
+
var ORGANIZATION_OPENROUTER_MODEL_ID_PREFIX = "organization-openrouter/";
|
|
1548
|
+
var OPENROUTER_BASE_URL = "https://openrouter.ai/api/v1";
|
|
1549
|
+
var RESERVED_MODEL_PROVIDER_IDS = /* @__PURE__ */ new Set([
|
|
1550
|
+
"openai",
|
|
1551
|
+
"azure",
|
|
1552
|
+
CODEX_PROVIDER_ID,
|
|
1553
|
+
XAI_SUBSCRIPTION_PROVIDER_ID,
|
|
1554
|
+
OPENGENI_GATEWAY_PROVIDER_ID,
|
|
1555
|
+
WORKSPACE_GATEWAY_PROVIDER_ID,
|
|
1556
|
+
ORGANIZATION_GATEWAY_PROVIDER_ID,
|
|
1557
|
+
OPENROUTER_PROVIDER_ID,
|
|
1558
|
+
WORKSPACE_OPENROUTER_PROVIDER_ID,
|
|
1559
|
+
ORGANIZATION_OPENROUTER_PROVIDER_ID
|
|
1560
|
+
]);
|
|
1561
|
+
var ModelCostClass = z.enum(["free", "credits"]);
|
|
1562
|
+
var ConfiguredModelCostClass = z.enum([
|
|
1563
|
+
"free",
|
|
1564
|
+
"credits",
|
|
1565
|
+
"subscription",
|
|
1566
|
+
"workspace",
|
|
1567
|
+
"organization"
|
|
1568
|
+
]);
|
|
1569
|
+
var ModelNote = z.string().max(500).refine((value) => !/[\r\n|]/u.test(value), {
|
|
1570
|
+
message: "model notes must not contain newlines or the | field separator"
|
|
1571
|
+
});
|
|
1572
|
+
function parseModelCostPolicyJson(raw) {
|
|
1573
|
+
let parsed;
|
|
1574
|
+
try {
|
|
1575
|
+
parsed = JSON.parse(raw);
|
|
1576
|
+
} catch (error) {
|
|
1577
|
+
throw new Error(
|
|
1578
|
+
`OPENGENI_MODEL_COST_POLICY_JSON must be valid JSON: ${error instanceof Error ? error.message : String(error)}`,
|
|
1579
|
+
{ cause: error }
|
|
1580
|
+
);
|
|
1581
|
+
}
|
|
1582
|
+
return z.record(z.string().min(1), ModelCostClass).parse(parsed);
|
|
1583
|
+
}
|
|
1584
|
+
function parseModelNotesJson(raw) {
|
|
1585
|
+
let parsed;
|
|
1586
|
+
try {
|
|
1587
|
+
parsed = JSON.parse(raw);
|
|
1588
|
+
} catch (error) {
|
|
1589
|
+
throw new Error(
|
|
1590
|
+
`OPENGENI_MODEL_NOTES_JSON must be valid JSON: ${error instanceof Error ? error.message : String(error)}`,
|
|
1591
|
+
{ cause: error }
|
|
1592
|
+
);
|
|
1593
|
+
}
|
|
1594
|
+
return z.record(z.string().min(1), ModelNote).parse(parsed);
|
|
1595
|
+
}
|
|
1596
|
+
function configuredModelNotes(settings) {
|
|
1597
|
+
return parseModelNotesJson(settings.modelNotesJson);
|
|
1598
|
+
}
|
|
1599
|
+
var GatewayCatalogModel = z.object({
|
|
1600
|
+
productId: z.string().min(1),
|
|
1601
|
+
workspaceProductId: z.string().min(1).startsWith(WORKSPACE_GATEWAY_MODEL_ID_PREFIX),
|
|
1602
|
+
upstreamModelId: z.string().min(1),
|
|
1603
|
+
label: z.string().min(1),
|
|
1604
|
+
shortLabel: z.string().min(1).max(64).optional(),
|
|
1605
|
+
providers: z.array(z.string().min(1)).min(1),
|
|
1606
|
+
implicitCaching: z.boolean().default(false),
|
|
1607
|
+
vision: z.boolean().default(false),
|
|
1608
|
+
inputFileMediaTypes: z.array(z.string().min(1)).default([]),
|
|
1609
|
+
contextWindowTokens: z.number().int().positive().default(1e6),
|
|
1610
|
+
effectiveContextWindowTokens: z.number().int().positive().default(9e5),
|
|
1611
|
+
autoCompactTokenLimit: z.number().int().positive().default(85e4),
|
|
1612
|
+
pricing: z.union([ModelPricingSchema, ModelPricingScheduleSchema]).optional(),
|
|
1613
|
+
credentialSource: z.never().optional(),
|
|
1614
|
+
billing: z.never().optional(),
|
|
1615
|
+
apiKey: z.never().optional()
|
|
1616
|
+
}).strict();
|
|
1617
|
+
var OpenRouterCatalogModel = z.object({
|
|
1618
|
+
upstreamModelId: z.string().min(1).endsWith(":free"),
|
|
1619
|
+
label: z.string().min(1),
|
|
1620
|
+
shortLabel: z.string().min(1).max(64).optional(),
|
|
1621
|
+
aliases: z.array(z.string().min(1)).default([]),
|
|
1622
|
+
capabilities: ModelCapabilitiesV1Schema,
|
|
1623
|
+
contextWindowTokens: z.number().int().positive().optional(),
|
|
1624
|
+
effectiveContextWindowTokens: z.number().int().positive().optional(),
|
|
1625
|
+
autoCompactTokenLimit: z.number().int().positive().optional(),
|
|
1626
|
+
toolOutputTruncationTokens: z.number().int().positive().optional(),
|
|
1627
|
+
credentialSource: z.never().optional(),
|
|
1628
|
+
billing: z.never().optional(),
|
|
1629
|
+
pricing: z.never().optional(),
|
|
1630
|
+
apiKey: z.never().optional()
|
|
1631
|
+
}).strict();
|
|
1632
|
+
var DeploymentRegistryBaseUrl = z.string().url().superRefine((value, context) => {
|
|
1633
|
+
const url = new URL(value);
|
|
1634
|
+
if (url.username || url.password) {
|
|
1635
|
+
context.addIssue({
|
|
1636
|
+
code: "custom",
|
|
1637
|
+
message: "database catalog provider baseUrl must not contain userinfo"
|
|
1638
|
+
});
|
|
1639
|
+
}
|
|
1640
|
+
if (url.search) {
|
|
1641
|
+
context.addIssue({
|
|
1642
|
+
code: "custom",
|
|
1643
|
+
message: "database catalog provider baseUrl must not contain a query"
|
|
1644
|
+
});
|
|
1645
|
+
}
|
|
1646
|
+
if (url.hash) {
|
|
1647
|
+
context.addIssue({
|
|
1648
|
+
code: "custom",
|
|
1649
|
+
message: "database catalog provider baseUrl must not contain a fragment"
|
|
1650
|
+
});
|
|
1651
|
+
}
|
|
1652
|
+
});
|
|
1653
|
+
var DeploymentRegistryProviderKind = z.enum(["api-key", "anonymous"]);
|
|
1654
|
+
var DeploymentRegistryModelSchema = RegistryModelSchema.safeExtend({
|
|
1655
|
+
pricing: z.never().optional()
|
|
1656
|
+
}).strict();
|
|
1657
|
+
var DeploymentRegistryProviderSchema = RegistryProviderSchema.safeExtend({
|
|
1658
|
+
kind: DeploymentRegistryProviderKind.default("api-key"),
|
|
1659
|
+
baseUrl: DeploymentRegistryBaseUrl,
|
|
1660
|
+
models: z.array(DeploymentRegistryModelSchema).min(1),
|
|
1661
|
+
apiKey: z.never().optional(),
|
|
1662
|
+
apiKeyEnv: z.never().optional(),
|
|
1663
|
+
defaultHeaders: z.never().optional(),
|
|
1664
|
+
defaultQuery: z.never().optional(),
|
|
1665
|
+
publicDefaultHeaderNames: z.never().optional(),
|
|
1666
|
+
publicDefaultQueryNames: z.never().optional()
|
|
1667
|
+
}).strict();
|
|
1668
|
+
var DeploymentGatewayCatalogModelSchema = GatewayCatalogModel.safeExtend({
|
|
1669
|
+
pricing: z.never().optional()
|
|
1670
|
+
}).strict();
|
|
1671
|
+
var ModelCatalogDocument = z.object({
|
|
1672
|
+
schemaVersion: z.literal(1),
|
|
1673
|
+
/** Canonical deployment default. Omission preserves the V1 first-built-in
|
|
1674
|
+
* fallback for existing documents; operators should set this explicitly
|
|
1675
|
+
* when cutting over a registry or connected-subscription default. */
|
|
1676
|
+
defaultModel: z.string().min(1).optional(),
|
|
1677
|
+
builtInModels: z.array(z.string().min(1)).min(1),
|
|
1678
|
+
registryProviders: z.array(DeploymentRegistryProviderSchema).default([]),
|
|
1679
|
+
gatewayModels: z.array(DeploymentGatewayCatalogModelSchema).default([]),
|
|
1680
|
+
openrouterModels: z.array(OpenRouterCatalogModel).default([]),
|
|
1681
|
+
modelNotes: z.record(z.string().min(1), ModelNote).default({}),
|
|
1682
|
+
billing: z.never().optional(),
|
|
1683
|
+
enabled: z.never().optional(),
|
|
1684
|
+
apiKey: z.never().optional(),
|
|
1685
|
+
bands: z.never().optional()
|
|
1686
|
+
}).strict().superRefine((document, context) => {
|
|
1687
|
+
const productIds = /* @__PURE__ */ new Set();
|
|
1688
|
+
const providerIds = /* @__PURE__ */ new Set();
|
|
1689
|
+
const gatewayUpstreamIds = /* @__PURE__ */ new Set();
|
|
1690
|
+
const add = (id, path) => {
|
|
1691
|
+
if (/[\u000A\u000D|]/u.test(id)) {
|
|
1692
|
+
context.addIssue({
|
|
1693
|
+
code: "custom",
|
|
1694
|
+
path,
|
|
1695
|
+
message: "catalog product ids must not contain newlines or the | field separator"
|
|
1696
|
+
});
|
|
1697
|
+
}
|
|
1698
|
+
if (productIds.has(id)) {
|
|
1699
|
+
context.addIssue({
|
|
1700
|
+
code: "custom",
|
|
1701
|
+
path,
|
|
1702
|
+
message: `duplicate product id ${id}`
|
|
1703
|
+
});
|
|
1704
|
+
}
|
|
1705
|
+
productIds.add(id);
|
|
1706
|
+
};
|
|
1707
|
+
document.builtInModels.forEach((id, index) => add(id, ["builtInModels", index]));
|
|
1708
|
+
document.registryProviders.forEach((provider, providerIndex) => {
|
|
1709
|
+
if (RESERVED_MODEL_PROVIDER_IDS.has(provider.id)) {
|
|
1710
|
+
context.addIssue({
|
|
1711
|
+
code: "custom",
|
|
1712
|
+
path: ["registryProviders", providerIndex, "id"],
|
|
1713
|
+
message: `provider id ${provider.id} is reserved for a reviewed OpenGeni provider`
|
|
1714
|
+
});
|
|
1715
|
+
}
|
|
1716
|
+
if (providerIds.has(provider.id)) {
|
|
1717
|
+
context.addIssue({
|
|
1718
|
+
code: "custom",
|
|
1719
|
+
path: ["registryProviders", providerIndex, "id"],
|
|
1720
|
+
message: `duplicate provider id ${provider.id}`
|
|
1721
|
+
});
|
|
1722
|
+
}
|
|
1723
|
+
providerIds.add(provider.id);
|
|
1724
|
+
provider.models.forEach(
|
|
1725
|
+
(model, modelIndex) => add(model.id, ["registryProviders", providerIndex, "models", modelIndex, "id"])
|
|
1726
|
+
);
|
|
1727
|
+
});
|
|
1728
|
+
document.gatewayModels.forEach((model, index) => {
|
|
1729
|
+
if (gatewayUpstreamIds.has(model.upstreamModelId)) {
|
|
1730
|
+
context.addIssue({
|
|
1731
|
+
code: "custom",
|
|
1732
|
+
path: ["gatewayModels", index, "upstreamModelId"],
|
|
1733
|
+
message: `duplicate Gateway upstream model id ${model.upstreamModelId}`
|
|
1734
|
+
});
|
|
1735
|
+
}
|
|
1736
|
+
gatewayUpstreamIds.add(model.upstreamModelId);
|
|
1737
|
+
add(model.productId, ["gatewayModels", index, "productId"]);
|
|
1738
|
+
add(model.workspaceProductId, ["gatewayModels", index, "workspaceProductId"]);
|
|
1739
|
+
});
|
|
1740
|
+
document.openrouterModels.forEach(
|
|
1741
|
+
(model, index) => add(`${OPENROUTER_MODEL_ID_PREFIX}${model.upstreamModelId}`, [
|
|
1742
|
+
"openrouterModels",
|
|
1743
|
+
index,
|
|
1744
|
+
"upstreamModelId"
|
|
1745
|
+
])
|
|
1746
|
+
);
|
|
1747
|
+
if (document.defaultModel && /[\u000A\u000D|]/u.test(document.defaultModel)) {
|
|
1748
|
+
context.addIssue({
|
|
1749
|
+
code: "custom",
|
|
1750
|
+
path: ["defaultModel"],
|
|
1751
|
+
message: "catalog default model must not contain newlines or the | field separator"
|
|
1752
|
+
});
|
|
1753
|
+
}
|
|
1754
|
+
if (document.defaultModel && !productIds.has(document.defaultModel) && !document.defaultModel.startsWith(CODEX_MODEL_ID_PREFIX) && !document.defaultModel.startsWith(XAI_SUBSCRIPTION_MODEL_ID_PREFIX)) {
|
|
1755
|
+
context.addIssue({
|
|
1756
|
+
code: "custom",
|
|
1757
|
+
path: ["defaultModel"],
|
|
1758
|
+
message: "catalog default model must reference deployment catalog membership or a connected-subscription product"
|
|
1759
|
+
});
|
|
1760
|
+
}
|
|
1761
|
+
for (const productId of Object.keys(document.modelNotes)) {
|
|
1762
|
+
if (!productIds.has(productId)) {
|
|
1763
|
+
context.addIssue({
|
|
1764
|
+
code: "custom",
|
|
1765
|
+
path: ["modelNotes", productId],
|
|
1766
|
+
message: "model note references a product id outside the deployment catalog"
|
|
1767
|
+
});
|
|
1768
|
+
}
|
|
1769
|
+
}
|
|
1770
|
+
});
|
|
1771
|
+
function parseModelCatalogDocument(value) {
|
|
1772
|
+
return ModelCatalogDocument.parse(value);
|
|
1773
|
+
}
|
|
1774
|
+
function deploymentRegistryProvidersWithHostCredentials(settings, providers) {
|
|
1775
|
+
const hostProviders = new Map(
|
|
1776
|
+
parseModelProvidersJson(settings.modelProvidersJson).map((provider) => [provider.id, provider])
|
|
1777
|
+
);
|
|
1778
|
+
return providers.map((provider) => {
|
|
1779
|
+
if (provider.kind !== "api-key") return provider;
|
|
1780
|
+
const host = hostProviders.get(provider.id);
|
|
1781
|
+
if (!host || host.kind !== "api-key") {
|
|
1782
|
+
throw new Error(
|
|
1783
|
+
`database model catalog provider ${provider.id} has no matching host-authorized api-key transport`
|
|
1784
|
+
);
|
|
1785
|
+
}
|
|
1786
|
+
const transportIdentity = (candidate) => ({
|
|
1787
|
+
kind: candidate.kind,
|
|
1788
|
+
baseUrl: candidate.baseUrl,
|
|
1789
|
+
api: candidate.api,
|
|
1790
|
+
wireProfile: candidate.wireProfile
|
|
1791
|
+
});
|
|
1792
|
+
if (canonicalJson(transportIdentity(provider)) !== canonicalJson(transportIdentity(host))) {
|
|
1793
|
+
throw new Error(
|
|
1794
|
+
`database model catalog provider ${provider.id} does not match its host-authorized transport`
|
|
1795
|
+
);
|
|
1796
|
+
}
|
|
1797
|
+
return {
|
|
1798
|
+
...provider,
|
|
1799
|
+
...host.defaultHeaders === void 0 ? {} : { defaultHeaders: host.defaultHeaders },
|
|
1800
|
+
...host.defaultQuery === void 0 ? {} : { defaultQuery: host.defaultQuery },
|
|
1801
|
+
...host.publicDefaultHeaderNames === void 0 ? {} : { publicDefaultHeaderNames: host.publicDefaultHeaderNames },
|
|
1802
|
+
...host.publicDefaultQueryNames === void 0 ? {} : { publicDefaultQueryNames: host.publicDefaultQueryNames },
|
|
1803
|
+
...host.apiKey === void 0 ? {} : { apiKey: host.apiKey },
|
|
1804
|
+
...host.apiKeyEnv === void 0 ? {} : { apiKeyEnv: host.apiKeyEnv }
|
|
1805
|
+
};
|
|
1806
|
+
});
|
|
1807
|
+
}
|
|
1808
|
+
function applyModelCatalogDocument(settings, rawDocument) {
|
|
1809
|
+
const document = parseModelCatalogDocument(rawDocument);
|
|
1810
|
+
const defaultModel = document.defaultModel ?? document.builtInModels[0];
|
|
1811
|
+
const resolved = {
|
|
1812
|
+
...settings,
|
|
1813
|
+
openaiModel: defaultModel,
|
|
1814
|
+
// Keep the complete built-in membership, including the default. The worker
|
|
1815
|
+
// replaces openaiModel with the exact turn model; the run-scoped router
|
|
1816
|
+
// needs one stable built-in id in this allow-list so a bare provider model
|
|
1817
|
+
// is not temporarily claimed by OpenAI/Azure during name re-resolution.
|
|
1818
|
+
openaiAllowedModels: document.builtInModels.join(","),
|
|
1819
|
+
modelProvidersJson: JSON.stringify(
|
|
1820
|
+
deploymentRegistryProvidersWithHostCredentials(settings, document.registryProviders)
|
|
1821
|
+
),
|
|
1822
|
+
resolvedGatewayModelsJson: JSON.stringify(document.gatewayModels),
|
|
1823
|
+
resolvedOpenRouterModelsJson: JSON.stringify(document.openrouterModels),
|
|
1824
|
+
modelNotesJson: JSON.stringify(document.modelNotes)
|
|
1825
|
+
};
|
|
1826
|
+
return resolved;
|
|
1827
|
+
}
|
|
1478
1828
|
var IntegrationOAuthClientConfigSchema = z.object({
|
|
1479
1829
|
clientId: z.string().min(1),
|
|
1480
1830
|
clientSecret: z.string().min(1).optional(),
|
|
@@ -1482,11 +1832,10 @@ var IntegrationOAuthClientConfigSchema = z.object({
|
|
|
1482
1832
|
});
|
|
1483
1833
|
var VERCEL_AI_GATEWAY_BASE_URL = "https://ai-gateway.vercel.sh/v1";
|
|
1484
1834
|
var VERCEL_AI_GATEWAY_AI_SDK_BASE_URL = "https://ai-gateway.vercel.sh/v4/ai";
|
|
1485
|
-
var OPENGENI_GATEWAY_PROVIDER_ID = "opengeni-gateway";
|
|
1486
|
-
var WORKSPACE_GATEWAY_PROVIDER_ID = "workspace-gateway";
|
|
1487
|
-
var WORKSPACE_GATEWAY_MODEL_ID_PREFIX = "workspace-gateway/";
|
|
1488
1835
|
var VERCEL_AI_GATEWAY_CONNECTION_DOMAIN = "ai-gateway.vercel.sh";
|
|
1489
1836
|
var VERCEL_AI_GATEWAY_CONNECTION_ROLE = "vercel_ai_gateway";
|
|
1837
|
+
var WORKSPACE_OPENROUTER_CONNECTION_DOMAIN = "openrouter.ai";
|
|
1838
|
+
var WORKSPACE_OPENROUTER_CONNECTION_ROLE = "openrouter";
|
|
1490
1839
|
var CODEX_REALTIME_MODEL_ID = "gpt-live-1-boulder-alpha";
|
|
1491
1840
|
var SUPERGROK_REALTIME_MODEL_ID = "supergrok/grok-voice-think-fast-2.0";
|
|
1492
1841
|
var OPENGENI_REALTIME_MODEL_ID_PREFIX = "opengeni-gateway/";
|
|
@@ -1545,23 +1894,126 @@ var OPENGENI_GATEWAY_MODELS = {
|
|
|
1545
1894
|
implicitCaching: true
|
|
1546
1895
|
}
|
|
1547
1896
|
};
|
|
1897
|
+
var OPENGENI_OPENROUTER_MODELS = [
|
|
1898
|
+
OpenRouterCatalogModel.parse({
|
|
1899
|
+
upstreamModelId: "nvidia/nemotron-3-super-120b-a12b:free",
|
|
1900
|
+
label: "Nemotron 3 Super 120B",
|
|
1901
|
+
shortLabel: "Nemotron 3 Super",
|
|
1902
|
+
aliases: [],
|
|
1903
|
+
capabilities: {
|
|
1904
|
+
reasoning: {
|
|
1905
|
+
upstream: "supported",
|
|
1906
|
+
// OpenRouter advertises the reasoning controls, but the catalogue does
|
|
1907
|
+
// not publish this model's accepted effort vocabulary. Preserve that
|
|
1908
|
+
// upstream fact without exposing an unverified runnable selector.
|
|
1909
|
+
runnable: false,
|
|
1910
|
+
efforts: [],
|
|
1911
|
+
defaultEffort: null,
|
|
1912
|
+
required: false
|
|
1913
|
+
},
|
|
1914
|
+
functionCalling: { upstream: "supported", runnable: true },
|
|
1915
|
+
structuredOutput: { upstream: "supported", runnable: true },
|
|
1916
|
+
hostedTools: {
|
|
1917
|
+
webSearch: { upstream: "unknown", runnable: false },
|
|
1918
|
+
xSearch: { upstream: "unknown", runnable: false },
|
|
1919
|
+
codeExecution: { upstream: "unknown", runnable: false },
|
|
1920
|
+
imageGeneration: { upstream: "unknown", runnable: false }
|
|
1921
|
+
},
|
|
1922
|
+
inputModalities: ["text"],
|
|
1923
|
+
inputFileMediaTypes: [],
|
|
1924
|
+
outputModalities: ["text"],
|
|
1925
|
+
transports: {
|
|
1926
|
+
sse: { upstream: "supported", runnable: true },
|
|
1927
|
+
responsesWebSocket: { upstream: "unknown", runnable: false },
|
|
1928
|
+
realtimeAudio: { upstream: "unsupported", runnable: false }
|
|
1929
|
+
},
|
|
1930
|
+
latencyModes: [{ id: "standard", upstream: "unknown", runnable: true }]
|
|
1931
|
+
},
|
|
1932
|
+
contextWindowTokens: 262144,
|
|
1933
|
+
effectiveContextWindowTokens: 235929,
|
|
1934
|
+
autoCompactTokenLimit: 22e4
|
|
1935
|
+
})
|
|
1936
|
+
];
|
|
1937
|
+
function defaultGatewayCatalogModels() {
|
|
1938
|
+
return [
|
|
1939
|
+
{
|
|
1940
|
+
...OPENGENI_GATEWAY_MODELS.deepseek,
|
|
1941
|
+
vision: false,
|
|
1942
|
+
inputFileMediaTypes: [],
|
|
1943
|
+
contextWindowTokens: 1e6,
|
|
1944
|
+
effectiveContextWindowTokens: 9e5,
|
|
1945
|
+
autoCompactTokenLimit: 85e4
|
|
1946
|
+
},
|
|
1947
|
+
{
|
|
1948
|
+
...OPENGENI_GATEWAY_MODELS.kimi,
|
|
1949
|
+
vision: true,
|
|
1950
|
+
inputFileMediaTypes: ["application/pdf"],
|
|
1951
|
+
contextWindowTokens: 1e6,
|
|
1952
|
+
effectiveContextWindowTokens: 9e5,
|
|
1953
|
+
autoCompactTokenLimit: 85e4
|
|
1954
|
+
}
|
|
1955
|
+
].map((model) => GatewayCatalogModel.parse(model));
|
|
1956
|
+
}
|
|
1957
|
+
function configuredGatewayCatalogModels(settings) {
|
|
1958
|
+
if (settings.resolvedGatewayModelsJson === void 0) {
|
|
1959
|
+
return defaultGatewayCatalogModels();
|
|
1960
|
+
}
|
|
1961
|
+
return z.array(GatewayCatalogModel).parse(JSON.parse(settings.resolvedGatewayModelsJson));
|
|
1962
|
+
}
|
|
1963
|
+
function configuredGatewayUpstreamModelIds(settings) {
|
|
1964
|
+
return configuredGatewayCatalogModels(settings).map((model) => model.upstreamModelId);
|
|
1965
|
+
}
|
|
1966
|
+
function configuredGatewayWorkspaceProductModelIds(settings) {
|
|
1967
|
+
return configuredGatewayCatalogModels(settings).map((model) => model.workspaceProductId);
|
|
1968
|
+
}
|
|
1969
|
+
function configuredGatewayOrganizationProductModelIds(settings) {
|
|
1970
|
+
void settings;
|
|
1971
|
+
return [];
|
|
1972
|
+
}
|
|
1973
|
+
function configuredModelInputIdentities(settings) {
|
|
1974
|
+
return configuredModels(settings).flatMap((model) => [model.id, ...model.aliases]);
|
|
1975
|
+
}
|
|
1976
|
+
function configuredOpenRouterCatalogModels(settings) {
|
|
1977
|
+
if (settings.resolvedOpenRouterModelsJson === void 0) {
|
|
1978
|
+
return [...OPENGENI_OPENROUTER_MODELS];
|
|
1979
|
+
}
|
|
1980
|
+
return z.array(OpenRouterCatalogModel).parse(JSON.parse(settings.resolvedOpenRouterModelsJson));
|
|
1981
|
+
}
|
|
1982
|
+
function configuredOpenRouterUpstreamModelIds(settings) {
|
|
1983
|
+
return configuredOpenRouterCatalogModels(settings).map((model) => model.upstreamModelId);
|
|
1984
|
+
}
|
|
1985
|
+
function workspaceOpenRouterProductId(modelId) {
|
|
1986
|
+
return `${WORKSPACE_OPENROUTER_MODEL_ID_PREFIX}${modelId.startsWith(OPENROUTER_MODEL_ID_PREFIX) ? modelId.slice(OPENROUTER_MODEL_ID_PREFIX.length) : modelId}`;
|
|
1987
|
+
}
|
|
1988
|
+
function configuredOpenRouterWorkspaceProductModelIds(settings) {
|
|
1989
|
+
return configuredOpenRouterCatalogModels(settings).flatMap(
|
|
1990
|
+
(model) => [model.upstreamModelId, ...model.aliases].map(workspaceOpenRouterProductId)
|
|
1991
|
+
);
|
|
1992
|
+
}
|
|
1993
|
+
function configuredOpenRouterOrganizationProductModelIds(settings) {
|
|
1994
|
+
void settings;
|
|
1995
|
+
return [];
|
|
1996
|
+
}
|
|
1548
1997
|
var defaultModelPricing = {
|
|
1549
1998
|
"gpt-5.6-sol": {
|
|
1550
1999
|
default: {
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
2000
|
+
// Promotional OpenAI pricing, guaranteed through at least 2026-11-21.
|
|
2001
|
+
inputMicrosPerMillionTokens: 4e6,
|
|
2002
|
+
cachedInputMicrosPerMillionTokens: 4e5,
|
|
2003
|
+
cacheWriteMicrosPerMillionTokens: 5e6,
|
|
2004
|
+
outputMicrosPerMillionTokens: 2e7,
|
|
2005
|
+
marginBps: 500
|
|
1555
2006
|
},
|
|
1556
2007
|
inputTokenTiers: [
|
|
1557
2008
|
{
|
|
1558
2009
|
// OpenAI: prompts with >272K input tokens use the long-context rate.
|
|
1559
2010
|
minimumInputTokens: 272001,
|
|
1560
2011
|
pricing: {
|
|
1561
|
-
inputMicrosPerMillionTokens:
|
|
1562
|
-
cachedInputMicrosPerMillionTokens:
|
|
1563
|
-
|
|
1564
|
-
|
|
2012
|
+
inputMicrosPerMillionTokens: 8e6,
|
|
2013
|
+
cachedInputMicrosPerMillionTokens: 8e5,
|
|
2014
|
+
cacheWriteMicrosPerMillionTokens: 1e7,
|
|
2015
|
+
outputMicrosPerMillionTokens: 3e7,
|
|
2016
|
+
marginBps: 500
|
|
1565
2017
|
}
|
|
1566
2018
|
}
|
|
1567
2019
|
]
|
|
@@ -1570,8 +2022,9 @@ var defaultModelPricing = {
|
|
|
1570
2022
|
default: {
|
|
1571
2023
|
inputMicrosPerMillionTokens: 2e6,
|
|
1572
2024
|
cachedInputMicrosPerMillionTokens: 2e5,
|
|
2025
|
+
cacheWriteMicrosPerMillionTokens: 25e5,
|
|
1573
2026
|
outputMicrosPerMillionTokens: 12e6,
|
|
1574
|
-
marginBps:
|
|
2027
|
+
marginBps: 500
|
|
1575
2028
|
},
|
|
1576
2029
|
inputTokenTiers: [
|
|
1577
2030
|
{
|
|
@@ -1579,8 +2032,9 @@ var defaultModelPricing = {
|
|
|
1579
2032
|
pricing: {
|
|
1580
2033
|
inputMicrosPerMillionTokens: 4e6,
|
|
1581
2034
|
cachedInputMicrosPerMillionTokens: 4e5,
|
|
2035
|
+
cacheWriteMicrosPerMillionTokens: 5e6,
|
|
1582
2036
|
outputMicrosPerMillionTokens: 18e6,
|
|
1583
|
-
marginBps:
|
|
2037
|
+
marginBps: 500
|
|
1584
2038
|
}
|
|
1585
2039
|
}
|
|
1586
2040
|
]
|
|
@@ -1589,8 +2043,9 @@ var defaultModelPricing = {
|
|
|
1589
2043
|
default: {
|
|
1590
2044
|
inputMicrosPerMillionTokens: 2e5,
|
|
1591
2045
|
cachedInputMicrosPerMillionTokens: 2e4,
|
|
2046
|
+
cacheWriteMicrosPerMillionTokens: 25e4,
|
|
1592
2047
|
outputMicrosPerMillionTokens: 12e5,
|
|
1593
|
-
marginBps:
|
|
2048
|
+
marginBps: 500
|
|
1594
2049
|
},
|
|
1595
2050
|
inputTokenTiers: [
|
|
1596
2051
|
{
|
|
@@ -1598,8 +2053,9 @@ var defaultModelPricing = {
|
|
|
1598
2053
|
pricing: {
|
|
1599
2054
|
inputMicrosPerMillionTokens: 4e5,
|
|
1600
2055
|
cachedInputMicrosPerMillionTokens: 4e4,
|
|
2056
|
+
cacheWriteMicrosPerMillionTokens: 5e5,
|
|
1601
2057
|
outputMicrosPerMillionTokens: 18e5,
|
|
1602
|
-
marginBps:
|
|
2058
|
+
marginBps: 500
|
|
1603
2059
|
}
|
|
1604
2060
|
}
|
|
1605
2061
|
]
|
|
@@ -1614,7 +2070,7 @@ var defaultModelPricing = {
|
|
|
1614
2070
|
inputMicrosPerMillionTokens: 14e4,
|
|
1615
2071
|
cachedInputMicrosPerMillionTokens: 28e3,
|
|
1616
2072
|
outputMicrosPerMillionTokens: 28e4,
|
|
1617
|
-
marginBps:
|
|
2073
|
+
marginBps: 500
|
|
1618
2074
|
}
|
|
1619
2075
|
},
|
|
1620
2076
|
[OPENGENI_GATEWAY_MODELS.kimi.productId]: {
|
|
@@ -1622,7 +2078,7 @@ var defaultModelPricing = {
|
|
|
1622
2078
|
inputMicrosPerMillionTokens: 3e6,
|
|
1623
2079
|
cachedInputMicrosPerMillionTokens: 3e5,
|
|
1624
2080
|
outputMicrosPerMillionTokens: 15e6,
|
|
1625
|
-
marginBps:
|
|
2081
|
+
marginBps: 500
|
|
1626
2082
|
}
|
|
1627
2083
|
},
|
|
1628
2084
|
// Fireworks AI / GLM 5.2 — the first shipped non-OpenAI registry model. A
|
|
@@ -1634,7 +2090,7 @@ var defaultModelPricing = {
|
|
|
1634
2090
|
inputMicrosPerMillionTokens: 14e5,
|
|
1635
2091
|
cachedInputMicrosPerMillionTokens: 14e4,
|
|
1636
2092
|
outputMicrosPerMillionTokens: 44e5,
|
|
1637
|
-
marginBps:
|
|
2093
|
+
marginBps: 500
|
|
1638
2094
|
}
|
|
1639
2095
|
}
|
|
1640
2096
|
};
|
|
@@ -1693,11 +2149,14 @@ function objectStorageConfiguredForWorkspaceArchives(settings) {
|
|
|
1693
2149
|
}
|
|
1694
2150
|
}
|
|
1695
2151
|
}
|
|
1696
|
-
function
|
|
1697
|
-
const value =
|
|
2152
|
+
function optionalEnvironmentValue(name, source) {
|
|
2153
|
+
const value = source[name];
|
|
1698
2154
|
return value && value.trim().length > 0 ? value : void 0;
|
|
1699
2155
|
}
|
|
1700
|
-
function getSettings() {
|
|
2156
|
+
function getSettings(source = process.env) {
|
|
2157
|
+
const optional = (name) => optionalEnvironmentValue(name, source);
|
|
2158
|
+
const modelCatalogSource = optional("OPENGENI_MODEL_CATALOG_SOURCE");
|
|
2159
|
+
const modelCostPolicyJson = optional("OPENGENI_MODEL_COST_POLICY_JSON") ?? (modelCatalogSource === "database" ? "{}" : DEFAULT_MODEL_COST_POLICY_JSON);
|
|
1701
2160
|
const raw = {
|
|
1702
2161
|
serviceName: optional("OPENGENI_SERVICE_NAME"),
|
|
1703
2162
|
environment: optional("OPENGENI_ENVIRONMENT"),
|
|
@@ -1742,6 +2201,8 @@ function getSettings() {
|
|
|
1742
2201
|
analyticsPosthogHost: optional("OPENGENI_ANALYTICS_POSTHOG_HOST"),
|
|
1743
2202
|
analyticsGa4MeasurementId: optional("OPENGENI_ANALYTICS_GA4_MEASUREMENT_ID"),
|
|
1744
2203
|
publicBaseUrl: optional("OPENGENI_PUBLIC_BASE_URL"),
|
|
2204
|
+
mcpOauthEnabled: optional("OPENGENI_MCP_OAUTH_ENABLED"),
|
|
2205
|
+
mcpOauthTrustedProxyHops: optional("OPENGENI_MCP_OAUTH_TRUSTED_PROXY_HOPS"),
|
|
1745
2206
|
webBaseUrl: optional("OPENGENI_WEB_BASE_URL"),
|
|
1746
2207
|
agentReleasesBaseUrl: optional("OPENGENI_AGENT_RELEASES_BASE_URL"),
|
|
1747
2208
|
agentStableVersion: optional("OPENGENI_AGENT_STABLE_VERSION"),
|
|
@@ -1813,6 +2274,9 @@ function getSettings() {
|
|
|
1813
2274
|
goalIdleBackoffMs: optional("OPENGENI_GOAL_IDLE_BACKOFF_MS"),
|
|
1814
2275
|
goalIdleBackoffMaxMs: optional("OPENGENI_GOAL_IDLE_BACKOFF_MAX_MS"),
|
|
1815
2276
|
childLifecycleNoticesEnabled: optional("OPENGENI_CHILD_LIFECYCLE_NOTICES_ENABLED"),
|
|
2277
|
+
hostMcpAuthoritySourceAdmissionEnabled: optional(
|
|
2278
|
+
"OPENGENI_HOST_MCP_AUTHORITY_SOURCE_ADMISSION_ENABLED"
|
|
2279
|
+
),
|
|
1816
2280
|
slackWorkspaceRoutingEnabled: optional("OPENGENI_SLACK_WORKSPACE_ROUTING_ENABLED"),
|
|
1817
2281
|
agentMaxModelCallsPerTurn: optional("OPENGENI_AGENT_MAX_MODEL_CALLS_PER_TURN"),
|
|
1818
2282
|
contextWindowTokens: optional("OPENGENI_CONTEXT_WINDOW_TOKENS"),
|
|
@@ -1882,6 +2346,10 @@ function getSettings() {
|
|
|
1882
2346
|
voiceInputAzureAdToken: optional("OPENGENI_VOICE_INPUT_AZURE_AD_TOKEN"),
|
|
1883
2347
|
voiceInputCodexExperimentalEnabled: optional("OPENGENI_VOICE_INPUT_CODEX_EXPERIMENTAL"),
|
|
1884
2348
|
modelPricingJson: optional("OPENGENI_MODEL_PRICING_JSON"),
|
|
2349
|
+
modelCatalogSource,
|
|
2350
|
+
modelCostPolicyJson,
|
|
2351
|
+
modelNotesJson: optional("OPENGENI_MODEL_NOTES_JSON"),
|
|
2352
|
+
openrouterApiKey: optional("OPENGENI_OPENROUTER_API_KEY"),
|
|
1885
2353
|
modelProvidersJson: optional("OPENGENI_MODEL_PROVIDERS_JSON"),
|
|
1886
2354
|
codexSubscriptionEnabled: optional("OPENGENI_CODEX_SUBSCRIPTION_ENABLED"),
|
|
1887
2355
|
supergrokSubscriptionEnabled: optional("OPENGENI_SUPERGROK_SUBSCRIPTION_ENABLED"),
|
|
@@ -1891,7 +2359,6 @@ function getSettings() {
|
|
|
1891
2359
|
codexConnectedAppsEnabled: optional("OPENGENI_CODEX_CONNECTED_APPS_ENABLED"),
|
|
1892
2360
|
codexToolSearchEnabled: optional("OPENGENI_CODEX_TOOL_SEARCH_ENABLED"),
|
|
1893
2361
|
lazyToolSearchEnabled: optional("OPENGENI_LAZY_TOOL_SEARCH_ENABLED"),
|
|
1894
|
-
codexCredentialLeasingEnabled: optional("OPENGENI_CODEX_CREDENTIAL_LEASING_ENABLED"),
|
|
1895
2362
|
codexFleetPolicyShadowEnabled: optional("OPENGENI_CODEX_FLEET_POLICY_SHADOW_ENABLED"),
|
|
1896
2363
|
codexProductSku: optional("OPENGENI_CODEX_PRODUCT_SKU"),
|
|
1897
2364
|
openaiReasoningEffort: optional("OPENGENI_OPENAI_REASONING_EFFORT"),
|
|
@@ -1916,7 +2383,7 @@ function getSettings() {
|
|
|
1916
2383
|
dockerNetwork: optional("OPENGENI_DOCKER_NETWORK"),
|
|
1917
2384
|
dockerWorkspaceBaseDir: optional("OPENGENI_DOCKER_WORKSPACE_BASE_DIR"),
|
|
1918
2385
|
modalAppName: optional("OPENGENI_MODAL_APP_NAME"),
|
|
1919
|
-
modalImageRef: optional("OPENGENI_MODAL_IMAGE_REF"),
|
|
2386
|
+
modalImageRef: optional("OPENGENI_MODAL_IMAGE_REF") ?? DEFAULT_MODAL_IMAGE_REF,
|
|
1920
2387
|
modalImageId: optional("OPENGENI_MODAL_IMAGE_ID"),
|
|
1921
2388
|
modalImageRegistrySecret: optional("OPENGENI_MODAL_IMAGE_REGISTRY_SECRET"),
|
|
1922
2389
|
modalTimeoutSeconds: optional("OPENGENI_MODAL_TIMEOUT_SECONDS"),
|
|
@@ -2018,6 +2485,7 @@ function getSettings() {
|
|
|
2018
2485
|
sandboxIdleGraceMs: optional("OPENGENI_SANDBOX_IDLE_GRACE_MS"),
|
|
2019
2486
|
sandboxSnapshotIntervalMs: optional("OPENGENI_SANDBOX_SNAPSHOT_INTERVAL_MS"),
|
|
2020
2487
|
sandboxSnapshotTimeoutMs: optional("OPENGENI_SANDBOX_SNAPSHOT_TIMEOUT_MS"),
|
|
2488
|
+
sandboxDrainSnapshotTimeoutMs: optional("OPENGENI_SANDBOX_DRAIN_SNAPSHOT_TIMEOUT_MS"),
|
|
2021
2489
|
sandboxRotationLeadMs: optional("OPENGENI_SANDBOX_ROTATION_LEAD_MS"),
|
|
2022
2490
|
sandboxRotationBatchSize: optional("OPENGENI_SANDBOX_ROTATION_BATCH_SIZE"),
|
|
2023
2491
|
sandboxLeaseTtlMs: optional("OPENGENI_SANDBOX_LEASE_TTL_MS"),
|
|
@@ -2092,6 +2560,12 @@ function getSettings() {
|
|
|
2092
2560
|
managedAuthGithubClientId: optional("OPENGENI_MANAGED_AUTH_GITHUB_CLIENT_ID"),
|
|
2093
2561
|
managedAuthGithubClientSecret: optional("OPENGENI_MANAGED_AUTH_GITHUB_CLIENT_SECRET"),
|
|
2094
2562
|
managedAuthSessionSetMode: optional("OPENGENI_MANAGED_AUTH_SESSION_SET_MODE"),
|
|
2563
|
+
organizationUserSetupEmailTokenTransport: optional(
|
|
2564
|
+
"OPENGENI_ORGANIZATION_USER_SETUP_EMAIL_TOKEN_TRANSPORT"
|
|
2565
|
+
),
|
|
2566
|
+
organizationUserSetupQueryEdgeSanitizationConfirmed: optional(
|
|
2567
|
+
"OPENGENI_ORGANIZATION_USER_SETUP_QUERY_EDGE_SANITIZATION_CONFIRMED"
|
|
2568
|
+
),
|
|
2095
2569
|
resendApiKey: optional("OPENGENI_RESEND_API_KEY"),
|
|
2096
2570
|
emailFrom: optional("OPENGENI_EMAIL_FROM"),
|
|
2097
2571
|
stripeSecretKey: optional("OPENGENI_STRIPE_SECRET_KEY"),
|
|
@@ -2107,7 +2581,7 @@ function getSettings() {
|
|
|
2107
2581
|
sandboxRotationLeadMs: raw.sandboxRotationLeadMs === void 0 && parsed.sandboxBackend === "modal" ? Math.min(36e5, Math.floor(parsed.modalTimeoutSeconds * 1e3 / 2)) : parsed.sandboxRotationLeadMs,
|
|
2108
2582
|
mcpServers: ensureBuiltInMcpServers(parsed)
|
|
2109
2583
|
};
|
|
2110
|
-
validateSettings(settings);
|
|
2584
|
+
validateSettings(settings, source);
|
|
2111
2585
|
return settings;
|
|
2112
2586
|
}
|
|
2113
2587
|
var LOCAL_FIRST_PARTY_DELEGATION_SECRET = "opengeni-local-first-party-delegation-secret-v1";
|
|
@@ -2167,8 +2641,13 @@ function sandboxArchiveCaptureTimeoutMs(settings) {
|
|
|
2167
2641
|
settings.sandboxSnapshotTimeoutMs + SANDBOX_ARCHIVE_CAPTURE_SETTLEMENT_GRACE_MS
|
|
2168
2642
|
);
|
|
2169
2643
|
}
|
|
2644
|
+
function effectiveSandboxDrainSnapshotTimeoutMs(settings) {
|
|
2645
|
+
return settings.sandboxDrainSnapshotTimeoutMs ?? settings.sandboxSnapshotTimeoutMs;
|
|
2646
|
+
}
|
|
2170
2647
|
function sandboxLifecycleTransitionWaitMs(settings) {
|
|
2171
|
-
const captureTimeoutMs = sandboxArchiveCaptureTimeoutMs(
|
|
2648
|
+
const captureTimeoutMs = sandboxArchiveCaptureTimeoutMs({
|
|
2649
|
+
sandboxSnapshotTimeoutMs: effectiveSandboxDrainSnapshotTimeoutMs(settings)
|
|
2650
|
+
});
|
|
2172
2651
|
return Math.min(
|
|
2173
2652
|
SANDBOX_LIFECYCLE_TRANSITION_MAX_WAIT_MS,
|
|
2174
2653
|
settings.sandboxLeaseReaperPeriodMs + captureTimeoutMs + SANDBOX_LIFECYCLE_RETRY_HANDOFF_GRACE_MS
|
|
@@ -2422,10 +2901,8 @@ function legacyModelCapabilities(settings, input) {
|
|
|
2422
2901
|
latencyModes: [{ id: "standard", upstream: "unknown", runnable: true }]
|
|
2423
2902
|
});
|
|
2424
2903
|
}
|
|
2425
|
-
function gatewayRequestPolicyForUpstreamModel(upstreamModelId) {
|
|
2426
|
-
const model =
|
|
2427
|
-
(candidate) => candidate.upstreamModelId === upstreamModelId
|
|
2428
|
-
);
|
|
2904
|
+
function gatewayRequestPolicyForUpstreamModel(upstreamModelId, models = defaultGatewayCatalogModels()) {
|
|
2905
|
+
const model = models.find((candidate) => candidate.upstreamModelId === upstreamModelId);
|
|
2429
2906
|
if (!model) {
|
|
2430
2907
|
return void 0;
|
|
2431
2908
|
}
|
|
@@ -2456,30 +2933,83 @@ function gatewayModelCapabilities(settings, input) {
|
|
|
2456
2933
|
latencyModes: [{ id: "standard", upstream: "supported", runnable: true }]
|
|
2457
2934
|
});
|
|
2458
2935
|
}
|
|
2936
|
+
function openRouterCustomModelCapabilities(settings) {
|
|
2937
|
+
const legacy = legacyModelCapabilities(settings, {
|
|
2938
|
+
reasoningEffort: false,
|
|
2939
|
+
hostedWebSearch: false
|
|
2940
|
+
});
|
|
2941
|
+
return normalizeCapabilities({
|
|
2942
|
+
...legacy,
|
|
2943
|
+
functionCalling: { upstream: "supported", runnable: true },
|
|
2944
|
+
inputModalities: ["text"],
|
|
2945
|
+
inputFileMediaTypes: [],
|
|
2946
|
+
transports: {
|
|
2947
|
+
...legacy.transports,
|
|
2948
|
+
sse: { upstream: "supported", runnable: true }
|
|
2949
|
+
},
|
|
2950
|
+
promptCaching: { upstream: "unsupported", runnable: false, mode: "none" },
|
|
2951
|
+
latencyModes: [{ id: "standard", upstream: "supported", runnable: true }]
|
|
2952
|
+
});
|
|
2953
|
+
}
|
|
2459
2954
|
function gatewayRegistryProvider(settings, input) {
|
|
2460
2955
|
const workspace = input.kind === "vercel-gateway-workspace";
|
|
2461
|
-
const
|
|
2462
|
-
|
|
2956
|
+
const organization = input.kind === "vercel-gateway-organization";
|
|
2957
|
+
const scoped = workspace || organization;
|
|
2958
|
+
const curated = organization ? [] : configuredGatewayCatalogModels(settings);
|
|
2959
|
+
const upstreamIds = new Set(curated.map((model) => model.upstreamModelId));
|
|
2960
|
+
const productIds = new Set(
|
|
2961
|
+
parseModelProvidersJson(settings.modelProvidersJson).filter(
|
|
2962
|
+
(provider) => provider.id !== WORKSPACE_GATEWAY_PROVIDER_ID && provider.id !== ORGANIZATION_GATEWAY_PROVIDER_ID
|
|
2963
|
+
).flatMap(
|
|
2964
|
+
(provider) => provider.models.flatMap((model) => [model.id, ...model.aliases ?? []])
|
|
2965
|
+
)
|
|
2966
|
+
);
|
|
2967
|
+
const models = curated.map((model) => {
|
|
2968
|
+
const id = workspace ? model.workspaceProductId : organization ? `${ORGANIZATION_GATEWAY_MODEL_ID_PREFIX}${model.upstreamModelId}` : model.productId;
|
|
2969
|
+
productIds.add(id);
|
|
2463
2970
|
return {
|
|
2464
|
-
id
|
|
2971
|
+
id,
|
|
2465
2972
|
upstreamModelId: model.upstreamModelId,
|
|
2466
2973
|
label: model.label,
|
|
2467
|
-
shortLabel: model.shortLabel,
|
|
2974
|
+
...model.shortLabel ? { shortLabel: model.shortLabel } : {},
|
|
2468
2975
|
capabilities: gatewayModelCapabilities(settings, {
|
|
2469
2976
|
implicitCaching: model.implicitCaching,
|
|
2470
|
-
vision:
|
|
2471
|
-
inputFileMediaTypes:
|
|
2977
|
+
vision: model.vision,
|
|
2978
|
+
inputFileMediaTypes: model.inputFileMediaTypes
|
|
2472
2979
|
}),
|
|
2473
|
-
contextWindowTokens:
|
|
2474
|
-
effectiveContextWindowTokens:
|
|
2475
|
-
autoCompactTokenLimit:
|
|
2476
|
-
toolOutputTruncationTokens: settings.modelToolOutputTruncationTokens
|
|
2980
|
+
contextWindowTokens: model.contextWindowTokens,
|
|
2981
|
+
effectiveContextWindowTokens: model.effectiveContextWindowTokens,
|
|
2982
|
+
autoCompactTokenLimit: model.autoCompactTokenLimit,
|
|
2983
|
+
toolOutputTruncationTokens: settings.modelToolOutputTruncationTokens,
|
|
2984
|
+
...model.pricing === void 0 ? {} : { pricing: model.pricing }
|
|
2477
2985
|
};
|
|
2478
2986
|
});
|
|
2987
|
+
if (scoped) {
|
|
2988
|
+
for (const custom of input.customModels ?? []) {
|
|
2989
|
+
const productId = `${workspace ? WORKSPACE_GATEWAY_MODEL_ID_PREFIX : ORGANIZATION_GATEWAY_MODEL_ID_PREFIX}${custom.upstreamModelId}`;
|
|
2990
|
+
if (upstreamIds.has(custom.upstreamModelId) || productIds.has(productId)) continue;
|
|
2991
|
+
upstreamIds.add(custom.upstreamModelId);
|
|
2992
|
+
productIds.add(productId);
|
|
2993
|
+
models.push({
|
|
2994
|
+
id: productId,
|
|
2995
|
+
upstreamModelId: custom.upstreamModelId,
|
|
2996
|
+
label: custom.label?.trim() || custom.upstreamModelId,
|
|
2997
|
+
capabilities: gatewayModelCapabilities(settings, {
|
|
2998
|
+
implicitCaching: false,
|
|
2999
|
+
vision: false,
|
|
3000
|
+
inputFileMediaTypes: []
|
|
3001
|
+
}),
|
|
3002
|
+
contextWindowTokens: 1e6,
|
|
3003
|
+
effectiveContextWindowTokens: 9e5,
|
|
3004
|
+
autoCompactTokenLimit: 85e4,
|
|
3005
|
+
toolOutputTruncationTokens: settings.modelToolOutputTruncationTokens
|
|
3006
|
+
});
|
|
3007
|
+
}
|
|
3008
|
+
}
|
|
2479
3009
|
return {
|
|
2480
3010
|
kind: input.kind,
|
|
2481
|
-
id: workspace ? WORKSPACE_GATEWAY_PROVIDER_ID : OPENGENI_GATEWAY_PROVIDER_ID,
|
|
2482
|
-
label: workspace ? "Your Gateway" : "OpenGeni",
|
|
3011
|
+
id: workspace ? WORKSPACE_GATEWAY_PROVIDER_ID : organization ? ORGANIZATION_GATEWAY_PROVIDER_ID : OPENGENI_GATEWAY_PROVIDER_ID,
|
|
3012
|
+
label: workspace ? "Your Gateway" : organization ? "Organization Gateway" : "OpenGeni",
|
|
2483
3013
|
// Responses preserves vision, reasoning items, and provider-native usage.
|
|
2484
3014
|
// Model-specific compatibility stays at the reviewed request fence rather
|
|
2485
3015
|
// than downgrading the whole provider wire.
|
|
@@ -2490,47 +3020,179 @@ function gatewayRegistryProvider(settings, input) {
|
|
|
2490
3020
|
models
|
|
2491
3021
|
};
|
|
2492
3022
|
}
|
|
3023
|
+
function openRouterRegistryProvider(settings, input) {
|
|
3024
|
+
const workspace = input.kind === "openrouter-workspace";
|
|
3025
|
+
const organization = input.kind === "openrouter-organization";
|
|
3026
|
+
const scoped = workspace || organization;
|
|
3027
|
+
const curated = organization ? [] : configuredOpenRouterCatalogModels(settings);
|
|
3028
|
+
const upstreamIds = new Set(curated.map((model) => model.upstreamModelId));
|
|
3029
|
+
const productIds = new Set(
|
|
3030
|
+
parseModelProvidersJson(settings.modelProvidersJson).filter(
|
|
3031
|
+
(provider) => provider.id !== WORKSPACE_OPENROUTER_PROVIDER_ID && provider.id !== ORGANIZATION_OPENROUTER_PROVIDER_ID
|
|
3032
|
+
).flatMap(
|
|
3033
|
+
(provider) => provider.models.flatMap((model) => [model.id, ...model.aliases ?? []])
|
|
3034
|
+
)
|
|
3035
|
+
);
|
|
3036
|
+
const models = curated.map((model) => {
|
|
3037
|
+
const id = workspace ? workspaceOpenRouterProductId(model.upstreamModelId) : organization ? `${ORGANIZATION_OPENROUTER_MODEL_ID_PREFIX}${model.upstreamModelId}` : `${OPENROUTER_MODEL_ID_PREFIX}${model.upstreamModelId}`;
|
|
3038
|
+
const aliases = workspace ? model.aliases.map(workspaceOpenRouterProductId) : organization ? model.aliases.map((alias) => `${ORGANIZATION_OPENROUTER_MODEL_ID_PREFIX}${alias}`) : model.aliases;
|
|
3039
|
+
productIds.add(id);
|
|
3040
|
+
for (const alias of aliases) productIds.add(alias);
|
|
3041
|
+
return {
|
|
3042
|
+
id,
|
|
3043
|
+
upstreamModelId: model.upstreamModelId,
|
|
3044
|
+
aliases,
|
|
3045
|
+
label: model.label,
|
|
3046
|
+
...model.shortLabel ? { shortLabel: model.shortLabel } : {},
|
|
3047
|
+
capabilities: model.capabilities,
|
|
3048
|
+
...model.contextWindowTokens === void 0 ? {} : { contextWindowTokens: model.contextWindowTokens },
|
|
3049
|
+
...model.effectiveContextWindowTokens === void 0 ? {} : { effectiveContextWindowTokens: model.effectiveContextWindowTokens },
|
|
3050
|
+
...model.autoCompactTokenLimit === void 0 ? {} : { autoCompactTokenLimit: model.autoCompactTokenLimit },
|
|
3051
|
+
toolOutputTruncationTokens: model.toolOutputTruncationTokens ?? settings.modelToolOutputTruncationTokens
|
|
3052
|
+
};
|
|
3053
|
+
});
|
|
3054
|
+
if (scoped) {
|
|
3055
|
+
for (const custom of input.customModels ?? []) {
|
|
3056
|
+
const productId = `${workspace ? WORKSPACE_OPENROUTER_MODEL_ID_PREFIX : ORGANIZATION_OPENROUTER_MODEL_ID_PREFIX}${custom.upstreamModelId}`;
|
|
3057
|
+
if (upstreamIds.has(custom.upstreamModelId) || productIds.has(productId)) continue;
|
|
3058
|
+
upstreamIds.add(custom.upstreamModelId);
|
|
3059
|
+
productIds.add(productId);
|
|
3060
|
+
models.push({
|
|
3061
|
+
id: productId,
|
|
3062
|
+
upstreamModelId: custom.upstreamModelId,
|
|
3063
|
+
aliases: [],
|
|
3064
|
+
label: custom.label?.trim() || custom.upstreamModelId,
|
|
3065
|
+
capabilities: openRouterCustomModelCapabilities(settings),
|
|
3066
|
+
toolOutputTruncationTokens: settings.modelToolOutputTruncationTokens
|
|
3067
|
+
});
|
|
3068
|
+
}
|
|
3069
|
+
}
|
|
3070
|
+
if (models.length === 0) return null;
|
|
3071
|
+
const defaultHeaders = {
|
|
3072
|
+
"x-title": "OpenGeni",
|
|
3073
|
+
...settings.publicBaseUrl ? { "http-referer": settings.publicBaseUrl } : {}
|
|
3074
|
+
};
|
|
3075
|
+
return {
|
|
3076
|
+
kind: input.kind,
|
|
3077
|
+
id: workspace ? WORKSPACE_OPENROUTER_PROVIDER_ID : organization ? ORGANIZATION_OPENROUTER_PROVIDER_ID : OPENROUTER_PROVIDER_ID,
|
|
3078
|
+
label: workspace ? "Your OpenRouter" : organization ? "Organization OpenRouter" : "OpenRouter",
|
|
3079
|
+
api: "chat",
|
|
3080
|
+
wireProfile: "openai",
|
|
3081
|
+
baseUrl: OPENROUTER_BASE_URL,
|
|
3082
|
+
...input.apiKey ? { apiKey: input.apiKey } : {},
|
|
3083
|
+
defaultHeaders,
|
|
3084
|
+
publicDefaultHeaderNames: Object.keys(defaultHeaders),
|
|
3085
|
+
models
|
|
3086
|
+
};
|
|
3087
|
+
}
|
|
2493
3088
|
function configuredRegistryProviders(settings) {
|
|
2494
3089
|
const providers = parseModelProvidersJson(settings.modelProvidersJson);
|
|
2495
|
-
|
|
2496
|
-
|
|
2497
|
-
|
|
2498
|
-
|
|
2499
|
-
|
|
2500
|
-
|
|
3090
|
+
const injected = [...providers];
|
|
3091
|
+
if (settings.vercelAiGatewayApiKey && configuredGatewayCatalogModels(settings).length > 0) {
|
|
3092
|
+
injected.push(
|
|
3093
|
+
gatewayRegistryProvider(settings, {
|
|
3094
|
+
kind: "vercel-gateway-managed",
|
|
3095
|
+
apiKey: settings.vercelAiGatewayApiKey
|
|
3096
|
+
})
|
|
2501
3097
|
);
|
|
2502
3098
|
}
|
|
2503
|
-
|
|
2504
|
-
|
|
2505
|
-
|
|
2506
|
-
|
|
2507
|
-
|
|
2508
|
-
|
|
2509
|
-
];
|
|
3099
|
+
const openrouter = settings.openrouterApiKey ? openRouterRegistryProvider(settings, {
|
|
3100
|
+
kind: "openrouter-managed",
|
|
3101
|
+
apiKey: settings.openrouterApiKey
|
|
3102
|
+
}) : null;
|
|
3103
|
+
if (openrouter) injected.push(openrouter);
|
|
3104
|
+
return injected;
|
|
2510
3105
|
}
|
|
2511
|
-
function withWorkspaceGatewayCatalogProvider(settings) {
|
|
3106
|
+
function withWorkspaceGatewayCatalogProvider(settings, customModels = []) {
|
|
2512
3107
|
const providers = parseModelProvidersJson(settings.modelProvidersJson);
|
|
2513
|
-
|
|
2514
|
-
|
|
2515
|
-
|
|
3108
|
+
const withoutWorkspace = providers.filter(
|
|
3109
|
+
(provider) => provider.id !== WORKSPACE_GATEWAY_PROVIDER_ID
|
|
3110
|
+
);
|
|
3111
|
+
const curatedCount = configuredGatewayCatalogModels(settings).length;
|
|
3112
|
+
if (curatedCount === 0 && customModels.length === 0) return settings;
|
|
2516
3113
|
return {
|
|
2517
3114
|
...settings,
|
|
2518
3115
|
modelProvidersJson: JSON.stringify([
|
|
2519
|
-
...
|
|
2520
|
-
gatewayRegistryProvider(settings, {
|
|
3116
|
+
...withoutWorkspace,
|
|
3117
|
+
gatewayRegistryProvider(settings, {
|
|
3118
|
+
kind: "vercel-gateway-workspace",
|
|
3119
|
+
customModels
|
|
3120
|
+
})
|
|
2521
3121
|
])
|
|
2522
3122
|
};
|
|
2523
3123
|
}
|
|
2524
|
-
function withWorkspaceGatewayCredential(settings, apiKey) {
|
|
3124
|
+
function withWorkspaceGatewayCredential(settings, apiKey, customModels = []) {
|
|
2525
3125
|
if (!apiKey.trim()) {
|
|
2526
3126
|
throw new Error("workspace AI Gateway credential is empty");
|
|
2527
3127
|
}
|
|
2528
|
-
const catalogSettings = withWorkspaceGatewayCatalogProvider(settings);
|
|
3128
|
+
const catalogSettings = withWorkspaceGatewayCatalogProvider(settings, customModels);
|
|
2529
3129
|
const providers = parseModelProvidersJson(catalogSettings.modelProvidersJson).map(
|
|
2530
3130
|
(provider) => provider.id === WORKSPACE_GATEWAY_PROVIDER_ID ? { ...provider, apiKey } : provider
|
|
2531
3131
|
);
|
|
2532
3132
|
return { ...catalogSettings, modelProvidersJson: JSON.stringify(providers) };
|
|
2533
3133
|
}
|
|
3134
|
+
function withWorkspaceOpenRouterCatalogProvider(settings, customModels = []) {
|
|
3135
|
+
const providers = parseModelProvidersJson(settings.modelProvidersJson);
|
|
3136
|
+
const withoutWorkspace = providers.filter(
|
|
3137
|
+
(provider2) => provider2.id !== WORKSPACE_OPENROUTER_PROVIDER_ID
|
|
3138
|
+
);
|
|
3139
|
+
const provider = openRouterRegistryProvider(settings, {
|
|
3140
|
+
kind: "openrouter-workspace",
|
|
3141
|
+
customModels
|
|
3142
|
+
});
|
|
3143
|
+
if (!provider) return settings;
|
|
3144
|
+
return {
|
|
3145
|
+
...settings,
|
|
3146
|
+
modelProvidersJson: JSON.stringify([...withoutWorkspace, provider])
|
|
3147
|
+
};
|
|
3148
|
+
}
|
|
3149
|
+
function withWorkspaceOpenRouterCredential(settings, apiKey, customModels = []) {
|
|
3150
|
+
if (!apiKey.trim()) {
|
|
3151
|
+
throw new Error("workspace OpenRouter credential is empty");
|
|
3152
|
+
}
|
|
3153
|
+
const catalogSettings = withWorkspaceOpenRouterCatalogProvider(settings, customModels);
|
|
3154
|
+
const providers = parseModelProvidersJson(catalogSettings.modelProvidersJson).map(
|
|
3155
|
+
(provider) => provider.id === WORKSPACE_OPENROUTER_PROVIDER_ID ? { ...provider, apiKey } : provider
|
|
3156
|
+
);
|
|
3157
|
+
return { ...catalogSettings, modelProvidersJson: JSON.stringify(providers) };
|
|
3158
|
+
}
|
|
3159
|
+
function withOrganizationGatewayCatalogProvider(settings, customModels = []) {
|
|
3160
|
+
if (customModels.length === 0) return settings;
|
|
3161
|
+
const providers = parseModelProvidersJson(settings.modelProvidersJson).filter(
|
|
3162
|
+
(provider2) => provider2.id !== ORGANIZATION_GATEWAY_PROVIDER_ID
|
|
3163
|
+
);
|
|
3164
|
+
const provider = gatewayRegistryProvider(settings, {
|
|
3165
|
+
kind: "vercel-gateway-organization",
|
|
3166
|
+
customModels
|
|
3167
|
+
});
|
|
3168
|
+
return { ...settings, modelProvidersJson: JSON.stringify([...providers, provider]) };
|
|
3169
|
+
}
|
|
3170
|
+
function withOrganizationGatewayCredential(settings, apiKey, customModels = []) {
|
|
3171
|
+
if (!apiKey.trim()) throw new Error("organization AI Gateway credential is empty");
|
|
3172
|
+
const catalog = withOrganizationGatewayCatalogProvider(settings, customModels);
|
|
3173
|
+
const providers = parseModelProvidersJson(catalog.modelProvidersJson).map(
|
|
3174
|
+
(provider) => provider.id === ORGANIZATION_GATEWAY_PROVIDER_ID ? { ...provider, apiKey } : provider
|
|
3175
|
+
);
|
|
3176
|
+
return { ...catalog, modelProvidersJson: JSON.stringify(providers) };
|
|
3177
|
+
}
|
|
3178
|
+
function withOrganizationOpenRouterCatalogProvider(settings, customModels = []) {
|
|
3179
|
+
const providers = parseModelProvidersJson(settings.modelProvidersJson).filter(
|
|
3180
|
+
(provider2) => provider2.id !== ORGANIZATION_OPENROUTER_PROVIDER_ID
|
|
3181
|
+
);
|
|
3182
|
+
const provider = openRouterRegistryProvider(settings, {
|
|
3183
|
+
kind: "openrouter-organization",
|
|
3184
|
+
customModels
|
|
3185
|
+
});
|
|
3186
|
+
return provider ? { ...settings, modelProvidersJson: JSON.stringify([...providers, provider]) } : settings;
|
|
3187
|
+
}
|
|
3188
|
+
function withOrganizationOpenRouterCredential(settings, apiKey, customModels = []) {
|
|
3189
|
+
if (!apiKey.trim()) throw new Error("organization OpenRouter credential is empty");
|
|
3190
|
+
const catalog = withOrganizationOpenRouterCatalogProvider(settings, customModels);
|
|
3191
|
+
const providers = parseModelProvidersJson(catalog.modelProvidersJson).map(
|
|
3192
|
+
(provider) => provider.id === ORGANIZATION_OPENROUTER_PROVIDER_ID ? { ...provider, apiKey } : provider
|
|
3193
|
+
);
|
|
3194
|
+
return { ...catalog, modelProvidersJson: JSON.stringify(providers) };
|
|
3195
|
+
}
|
|
2534
3196
|
var GPT56_FAST_BILLING_MULTIPLIER_BPS = 2e4;
|
|
2535
3197
|
function productLabelForModelId(modelId) {
|
|
2536
3198
|
const slug = modelId.startsWith(CODEX_MODEL_ID_PREFIX) ? modelId.slice(CODEX_MODEL_ID_PREFIX.length) : modelId;
|
|
@@ -2561,6 +3223,8 @@ function productShortLabelForModelId(modelId) {
|
|
|
2561
3223
|
return "5.6 Terra";
|
|
2562
3224
|
case "gpt-5.6-luna":
|
|
2563
3225
|
return "5.6 Luna";
|
|
3226
|
+
case "gpt-6-astra":
|
|
3227
|
+
return "6 Astra";
|
|
2564
3228
|
default:
|
|
2565
3229
|
return null;
|
|
2566
3230
|
}
|
|
@@ -2580,7 +3244,7 @@ function builtinContextLimitsForModel(settings, modelId) {
|
|
|
2580
3244
|
return { contextWindowTokens: settings.contextWindowTokens };
|
|
2581
3245
|
}
|
|
2582
3246
|
function builtinLatencyModesForModel(modelId) {
|
|
2583
|
-
if (isBuiltinGpt56ModelId(modelId) || modelId.startsWith("codex/gpt-5.6-")) {
|
|
3247
|
+
if (isBuiltinGpt56ModelId(modelId) || modelId.startsWith("codex/gpt-5.6-") || modelId === "codex/gpt-6-astra") {
|
|
2584
3248
|
return [
|
|
2585
3249
|
{ id: "standard", upstream: "supported", runnable: true },
|
|
2586
3250
|
{
|
|
@@ -2643,31 +3307,60 @@ function assertLatencyModeRunnable(settings, modelId, latencyMode) {
|
|
|
2643
3307
|
}
|
|
2644
3308
|
}
|
|
2645
3309
|
function registryCredentialSource(provider) {
|
|
2646
|
-
|
|
2647
|
-
|
|
2648
|
-
|
|
2649
|
-
|
|
2650
|
-
|
|
2651
|
-
|
|
2652
|
-
|
|
2653
|
-
|
|
2654
|
-
|
|
2655
|
-
|
|
2656
|
-
|
|
3310
|
+
switch (provider.kind) {
|
|
3311
|
+
case "anonymous":
|
|
3312
|
+
return { kind: "deployment", mechanism: "none" };
|
|
3313
|
+
case "codex-subscription":
|
|
3314
|
+
return { kind: "connected_subscription", provider: "codex" };
|
|
3315
|
+
case "xai-subscription":
|
|
3316
|
+
return { kind: "connected_subscription", provider: "xai" };
|
|
3317
|
+
case "vercel-gateway-workspace":
|
|
3318
|
+
case "openrouter-workspace":
|
|
3319
|
+
return { kind: "workspace_connection", mechanism: "api_key" };
|
|
3320
|
+
case "vercel-gateway-organization":
|
|
3321
|
+
case "openrouter-organization":
|
|
3322
|
+
return { kind: "organization_connection", mechanism: "api_key" };
|
|
3323
|
+
case "api-key":
|
|
3324
|
+
case "vercel-gateway-managed":
|
|
3325
|
+
case "openrouter-managed":
|
|
3326
|
+
return { kind: "deployment", mechanism: "api_key" };
|
|
3327
|
+
default: {
|
|
3328
|
+
const _exhaustive = provider.kind;
|
|
3329
|
+
return _exhaustive;
|
|
3330
|
+
}
|
|
2657
3331
|
}
|
|
2658
|
-
return { kind: "deployment", mechanism: "api_key" };
|
|
2659
3332
|
}
|
|
2660
3333
|
function registryBilling(provider) {
|
|
2661
|
-
|
|
2662
|
-
|
|
2663
|
-
|
|
2664
|
-
|
|
2665
|
-
|
|
2666
|
-
|
|
2667
|
-
|
|
2668
|
-
|
|
3334
|
+
switch (provider.kind) {
|
|
3335
|
+
case "anonymous":
|
|
3336
|
+
case "openrouter-managed":
|
|
3337
|
+
return { upstreamPayer: "deployment", metering: "external" };
|
|
3338
|
+
case "codex-subscription":
|
|
3339
|
+
case "xai-subscription":
|
|
3340
|
+
return { upstreamPayer: "connected_subscription", metering: "external" };
|
|
3341
|
+
case "vercel-gateway-workspace":
|
|
3342
|
+
case "openrouter-workspace":
|
|
3343
|
+
return { upstreamPayer: "workspace", metering: "external" };
|
|
3344
|
+
case "vercel-gateway-organization":
|
|
3345
|
+
case "openrouter-organization":
|
|
3346
|
+
return { upstreamPayer: "organization", metering: "external" };
|
|
3347
|
+
case "api-key":
|
|
3348
|
+
case "vercel-gateway-managed":
|
|
3349
|
+
return { upstreamPayer: "deployment", metering: "opengeni_credits" };
|
|
3350
|
+
default: {
|
|
3351
|
+
const _exhaustive = provider.kind;
|
|
3352
|
+
return _exhaustive;
|
|
3353
|
+
}
|
|
2669
3354
|
}
|
|
2670
|
-
|
|
3355
|
+
}
|
|
3356
|
+
function configuredCostForModel(settings, productModelId, credentialSource) {
|
|
3357
|
+
if (credentialSource.kind === "workspace_connection") return "workspace";
|
|
3358
|
+
if (credentialSource.kind === "organization_connection") return "organization";
|
|
3359
|
+
if (credentialSource.kind === "connected_subscription") return "subscription";
|
|
3360
|
+
return parseModelCostPolicyJson(settings.modelCostPolicyJson)[productModelId] ?? "credits";
|
|
3361
|
+
}
|
|
3362
|
+
function modelCostClassForConfiguredModel(_settings, model) {
|
|
3363
|
+
return model.cost;
|
|
2671
3364
|
}
|
|
2672
3365
|
function builtinCredentialSource(settings) {
|
|
2673
3366
|
if (settings.openaiProvider === "azure" && !settings.azureOpenaiApiKey) {
|
|
@@ -2726,6 +3419,10 @@ function definitionVersionFor(model, provider, options = {}) {
|
|
|
2726
3419
|
billing: model.billing,
|
|
2727
3420
|
executionLimits: model.executionLimits,
|
|
2728
3421
|
capabilities: model.capabilities,
|
|
3422
|
+
// Workspace-facing free/credits classification is a separate live
|
|
3423
|
+
// deployment policy. Operators must drain/fence accepted turns before
|
|
3424
|
+
// changing it; it is intentionally not a second executable-definition
|
|
3425
|
+
// freeze inside TurnExecutionPolicyV1.
|
|
2729
3426
|
...model.requestPolicy ? { requestPolicy: model.requestPolicy } : {},
|
|
2730
3427
|
pricing: model.pricing ?? null
|
|
2731
3428
|
});
|
|
@@ -2734,7 +3431,9 @@ function definitionVersionFor(model, provider, options = {}) {
|
|
|
2734
3431
|
function legacyImplicitOpenAiDefinitionVersionFor(model, provider) {
|
|
2735
3432
|
if (provider.wireProfile !== "openai") return null;
|
|
2736
3433
|
const { definitionVersion: _definitionVersion, ...modelWithoutVersion } = model;
|
|
2737
|
-
return definitionVersionFor(modelWithoutVersion, provider, {
|
|
3434
|
+
return definitionVersionFor(modelWithoutVersion, provider, {
|
|
3435
|
+
includeWireProfile: false
|
|
3436
|
+
});
|
|
2738
3437
|
}
|
|
2739
3438
|
function builtinProviderId(settings) {
|
|
2740
3439
|
return settings.openaiProvider === "azure" ? "azure" : "openai";
|
|
@@ -2742,7 +3441,7 @@ function builtinProviderId(settings) {
|
|
|
2742
3441
|
function builtinProviderLabel(settings) {
|
|
2743
3442
|
return settings.openaiProvider === "azure" ? "Azure OpenAI" : "OpenAI";
|
|
2744
3443
|
}
|
|
2745
|
-
function configuredProviders(settings) {
|
|
3444
|
+
function configuredProviders(settings, source = process.env) {
|
|
2746
3445
|
const credentialSource = builtinCredentialSource(settings);
|
|
2747
3446
|
const builtin = {
|
|
2748
3447
|
id: builtinProviderId(settings),
|
|
@@ -2771,7 +3470,7 @@ function configuredProviders(settings) {
|
|
|
2771
3470
|
wireProfile: provider.wireProfile,
|
|
2772
3471
|
builtin: false,
|
|
2773
3472
|
baseUrl: provider.baseUrl,
|
|
2774
|
-
apiKey: resolveProviderApiKey(provider),
|
|
3473
|
+
apiKey: resolveProviderApiKey(provider, source),
|
|
2775
3474
|
defaultQuery: provider.defaultQuery,
|
|
2776
3475
|
defaultHeaders: provider.defaultHeaders,
|
|
2777
3476
|
publicDefaultQueryNames: provider.publicDefaultQueryNames,
|
|
@@ -2799,7 +3498,7 @@ function withCodexCatalogProvider(settings) {
|
|
|
2799
3498
|
...legacyModelCapabilities(settings, {
|
|
2800
3499
|
reasoningEffort: true,
|
|
2801
3500
|
hostedWebSearch: true,
|
|
2802
|
-
vision: slug.startsWith("gpt-5.6-")
|
|
3501
|
+
vision: slug.startsWith("gpt-5.6-") || slug === "gpt-6-astra"
|
|
2803
3502
|
}),
|
|
2804
3503
|
...builtinPromptCachingForModel(`${CODEX_MODEL_ID_PREFIX}${slug}`) ? {
|
|
2805
3504
|
promptCaching: builtinPromptCachingForModel(`${CODEX_MODEL_ID_PREFIX}${slug}`)
|
|
@@ -2854,8 +3553,14 @@ function withXaiSubscriptionCatalogProvider(settings) {
|
|
|
2854
3553
|
{ id: "standard", upstream: "supported", runnable: true },
|
|
2855
3554
|
{ id: "fast", upstream: "supported", runnable: true }
|
|
2856
3555
|
];
|
|
2857
|
-
capabilities.hostedTools.xSearch = {
|
|
2858
|
-
|
|
3556
|
+
capabilities.hostedTools.xSearch = {
|
|
3557
|
+
upstream: "supported",
|
|
3558
|
+
runnable: true
|
|
3559
|
+
};
|
|
3560
|
+
capabilities.hostedTools.imageGeneration = {
|
|
3561
|
+
upstream: "supported",
|
|
3562
|
+
runnable: true
|
|
3563
|
+
};
|
|
2859
3564
|
return {
|
|
2860
3565
|
id: `${XAI_SUBSCRIPTION_MODEL_ID_PREFIX}${slug}`,
|
|
2861
3566
|
upstreamModelId: slug,
|
|
@@ -2871,7 +3576,10 @@ function withXaiSubscriptionCatalogProvider(settings) {
|
|
|
2871
3576
|
};
|
|
2872
3577
|
})
|
|
2873
3578
|
};
|
|
2874
|
-
return {
|
|
3579
|
+
return {
|
|
3580
|
+
...settings,
|
|
3581
|
+
modelProvidersJson: JSON.stringify([...providers, provider])
|
|
3582
|
+
};
|
|
2875
3583
|
}
|
|
2876
3584
|
function policyProviderIdForModel(settings, modelId) {
|
|
2877
3585
|
const canonicalModelId = canonicalizeConfiguredModelId(settings, modelId);
|
|
@@ -2884,6 +3592,9 @@ function policyProviderIdForModel(settings, modelId) {
|
|
|
2884
3592
|
if (canonicalModelId.startsWith(WORKSPACE_GATEWAY_MODEL_ID_PREFIX)) {
|
|
2885
3593
|
return WORKSPACE_GATEWAY_PROVIDER_ID;
|
|
2886
3594
|
}
|
|
3595
|
+
if (canonicalModelId.startsWith(WORKSPACE_OPENROUTER_MODEL_ID_PREFIX)) {
|
|
3596
|
+
return WORKSPACE_OPENROUTER_PROVIDER_ID;
|
|
3597
|
+
}
|
|
2887
3598
|
const configured = configuredModels(settings).find((model) => model.id === canonicalModelId);
|
|
2888
3599
|
return configured?.providerId ?? builtinProviderId(settings);
|
|
2889
3600
|
}
|
|
@@ -2896,10 +3607,14 @@ function resolvedExecutionLimits(settings, model) {
|
|
|
2896
3607
|
};
|
|
2897
3608
|
}
|
|
2898
3609
|
function finalizeConfiguredModel(settings, provider, input) {
|
|
2899
|
-
const requestPolicy = provider.kind === "vercel-gateway-managed" || provider.kind === "vercel-gateway-workspace"
|
|
3610
|
+
const requestPolicy = provider.kind === "vercel-gateway-managed" || provider.kind === "vercel-gateway-workspace" || provider.kind === "vercel-gateway-organization" ? gatewayRequestPolicyForUpstreamModel(
|
|
3611
|
+
input.upstreamModelId,
|
|
3612
|
+
configuredGatewayCatalogModels(settings)
|
|
3613
|
+
) : void 0;
|
|
2900
3614
|
const modelWithoutVersion = {
|
|
2901
3615
|
schemaVersion: 1,
|
|
2902
3616
|
...input,
|
|
3617
|
+
cost: configuredCostForModel(settings, input.id, input.credentialSource),
|
|
2903
3618
|
...requestPolicy ? { requestPolicy } : {},
|
|
2904
3619
|
executionLimits: resolvedExecutionLimits(settings, input)
|
|
2905
3620
|
};
|
|
@@ -2939,10 +3654,10 @@ function assertUniqueModelIdentities(models) {
|
|
|
2939
3654
|
}
|
|
2940
3655
|
}
|
|
2941
3656
|
}
|
|
2942
|
-
function configuredModels(settings) {
|
|
3657
|
+
function configuredModels(settings, source = process.env) {
|
|
2943
3658
|
const builtinId = builtinProviderId(settings);
|
|
2944
3659
|
const builtinLabel = builtinProviderLabel(settings);
|
|
2945
|
-
const providers = configuredProviders(settings);
|
|
3660
|
+
const providers = configuredProviders(settings, source);
|
|
2946
3661
|
const providerById = new Map(providers.map((provider) => [provider.id, provider]));
|
|
2947
3662
|
const pricingSchedules = configuredModelPricingSchedules(settings);
|
|
2948
3663
|
const parsedRegistry = configuredRegistryProviders(settings);
|
|
@@ -3031,7 +3746,10 @@ function configuredModels(settings) {
|
|
|
3031
3746
|
}
|
|
3032
3747
|
}
|
|
3033
3748
|
assertUniqueModelIdentities(out);
|
|
3034
|
-
|
|
3749
|
+
const defaultIndex = out.findIndex(
|
|
3750
|
+
(model) => model.id === settings.openaiModel || model.aliases.includes(settings.openaiModel)
|
|
3751
|
+
);
|
|
3752
|
+
return defaultIndex > 0 ? [out[defaultIndex], ...out.slice(0, defaultIndex), ...out.slice(defaultIndex + 1)] : out;
|
|
3035
3753
|
}
|
|
3036
3754
|
function canonicalizeConfiguredModelId(settings, modelId) {
|
|
3037
3755
|
const models = configuredModels(settings);
|
|
@@ -3066,10 +3784,32 @@ function settingsForTurnExecutionPolicy(settings, modelId) {
|
|
|
3066
3784
|
return withXaiSubscriptionCatalogProvider(settings);
|
|
3067
3785
|
}
|
|
3068
3786
|
if (modelId.startsWith(WORKSPACE_GATEWAY_MODEL_ID_PREFIX)) {
|
|
3787
|
+
if (resolveModelProvider(settings, modelId)) {
|
|
3788
|
+
return settings;
|
|
3789
|
+
}
|
|
3069
3790
|
return withWorkspaceGatewayCatalogProvider(settings);
|
|
3070
3791
|
}
|
|
3792
|
+
if (modelId.startsWith(WORKSPACE_OPENROUTER_MODEL_ID_PREFIX)) {
|
|
3793
|
+
if (resolveModelProvider(settings, modelId)) {
|
|
3794
|
+
return settings;
|
|
3795
|
+
}
|
|
3796
|
+
return withWorkspaceOpenRouterCatalogProvider(settings);
|
|
3797
|
+
}
|
|
3798
|
+
if (modelId.startsWith(ORGANIZATION_GATEWAY_MODEL_ID_PREFIX)) {
|
|
3799
|
+
return resolveModelProvider(settings, modelId) ? settings : withOrganizationGatewayCatalogProvider(settings);
|
|
3800
|
+
}
|
|
3801
|
+
if (modelId.startsWith(ORGANIZATION_OPENROUTER_MODEL_ID_PREFIX)) {
|
|
3802
|
+
return resolveModelProvider(settings, modelId) ? settings : withOrganizationOpenRouterCatalogProvider(settings);
|
|
3803
|
+
}
|
|
3071
3804
|
return settings;
|
|
3072
3805
|
}
|
|
3806
|
+
function resolveModelProviderForTurn(settings, modelId) {
|
|
3807
|
+
const catalogSettings = settingsForTurnExecutionPolicy(settings, modelId);
|
|
3808
|
+
return resolveModelProvider(
|
|
3809
|
+
catalogSettings,
|
|
3810
|
+
canonicalizeConfiguredModelId(catalogSettings, modelId)
|
|
3811
|
+
);
|
|
3812
|
+
}
|
|
3073
3813
|
function resolveTurnExecutionPolicyV1(settings, input) {
|
|
3074
3814
|
const catalogSettings = settingsForTurnExecutionPolicy(settings, input.modelId);
|
|
3075
3815
|
const productModelId = canonicalizeConfiguredModelId(catalogSettings, input.modelId);
|
|
@@ -3147,7 +3887,7 @@ function configuredModelPricingSchedules(settings) {
|
|
|
3147
3887
|
const configured = Object.fromEntries(
|
|
3148
3888
|
Object.entries(parseModelPricingJson(settings.modelPricingJson)).map(([model, pricing]) => [
|
|
3149
3889
|
model,
|
|
3150
|
-
|
|
3890
|
+
normalizeModelPricingSchedule(pricing)
|
|
3151
3891
|
])
|
|
3152
3892
|
);
|
|
3153
3893
|
return {
|
|
@@ -3260,12 +4000,7 @@ function calculateModelUsageCostBreakdown(settings, model, usage, options) {
|
|
|
3260
4000
|
function calculateGatewayReportedCostMicros(settings, model, inferenceCostUsd, options) {
|
|
3261
4001
|
return calculateGatewayReportedCostBreakdown(settings, model, inferenceCostUsd, options).creditCostMicros;
|
|
3262
4002
|
}
|
|
3263
|
-
function
|
|
3264
|
-
const schedule = configuredModelPricingSchedules(settings)[model];
|
|
3265
|
-
if (!schedule) {
|
|
3266
|
-
throw new Error(`Missing model pricing for ${model}`);
|
|
3267
|
-
}
|
|
3268
|
-
const pricing = selectModelPricing(schedule, positiveInt(options?.inputTokens));
|
|
4003
|
+
function parseGatewayReportedCostDecimal(inferenceCostUsd) {
|
|
3269
4004
|
const match = /^(0|[1-9]\d*)(?:\.(\d{1,18}))?$/.exec(inferenceCostUsd);
|
|
3270
4005
|
if (!match) {
|
|
3271
4006
|
throw new Error("Invalid AI Gateway inference cost");
|
|
@@ -3274,16 +4009,35 @@ function calculateGatewayReportedCostBreakdown(settings, model, inferenceCostUsd
|
|
|
3274
4009
|
const decimalDigits = BigInt(`${match[1]}${fraction}`);
|
|
3275
4010
|
const decimalScale = 10n ** BigInt(fraction.length);
|
|
3276
4011
|
const providerNumerator = decimalDigits * 1000000n;
|
|
3277
|
-
const
|
|
4012
|
+
const providerCostMicros = (providerNumerator + decimalScale - 1n) / decimalScale;
|
|
4013
|
+
if (providerCostMicros > BigInt(Number.MAX_SAFE_INTEGER)) {
|
|
4014
|
+
throw new Error("AI Gateway inference cost exceeds the supported billing range");
|
|
4015
|
+
}
|
|
4016
|
+
return {
|
|
4017
|
+
providerNumerator,
|
|
4018
|
+
decimalScale,
|
|
4019
|
+
providerCostMicros: Number(providerCostMicros)
|
|
4020
|
+
};
|
|
4021
|
+
}
|
|
4022
|
+
function calculateGatewayReportedProviderCostMicros(inferenceCostUsd) {
|
|
4023
|
+
return parseGatewayReportedCostDecimal(inferenceCostUsd).providerCostMicros;
|
|
4024
|
+
}
|
|
4025
|
+
function calculateGatewayReportedCostBreakdown(settings, model, inferenceCostUsd, options) {
|
|
4026
|
+
const schedule = configuredModelPricingSchedules(settings)[model];
|
|
4027
|
+
if (!schedule) {
|
|
4028
|
+
throw new Error(`Missing model pricing for ${model}`);
|
|
4029
|
+
}
|
|
4030
|
+
const pricing = selectModelPricing(schedule, positiveInt(options?.inputTokens));
|
|
4031
|
+
const { providerNumerator, decimalScale, providerCostMicros } = parseGatewayReportedCostDecimal(inferenceCostUsd);
|
|
3278
4032
|
const marginBps = BigInt(1e4 + (pricing.marginBps ?? 0));
|
|
3279
4033
|
const numerator = providerNumerator * marginBps;
|
|
3280
4034
|
const denominator = decimalScale * 10000n;
|
|
3281
4035
|
const creditMicros = (numerator + denominator - 1n) / denominator;
|
|
3282
|
-
if (
|
|
4036
|
+
if (creditMicros > BigInt(Number.MAX_SAFE_INTEGER)) {
|
|
3283
4037
|
throw new Error("AI Gateway inference cost exceeds the supported billing range");
|
|
3284
4038
|
}
|
|
3285
4039
|
return {
|
|
3286
|
-
providerCostMicros
|
|
4040
|
+
providerCostMicros,
|
|
3287
4041
|
creditCostMicros: Number(creditMicros)
|
|
3288
4042
|
};
|
|
3289
4043
|
}
|
|
@@ -3555,7 +4309,7 @@ function parseModelPricingJson(raw) {
|
|
|
3555
4309
|
if (!model.trim()) {
|
|
3556
4310
|
throw new Error("OPENGENI_MODEL_PRICING_JSON contains an empty model name");
|
|
3557
4311
|
}
|
|
3558
|
-
out[model] = ModelPricingSchema.parse(value);
|
|
4312
|
+
out[model] = z.union([ModelPricingSchema, ModelPricingScheduleSchema]).parse(value);
|
|
3559
4313
|
}
|
|
3560
4314
|
return out;
|
|
3561
4315
|
}
|
|
@@ -3739,9 +4493,14 @@ function calculateEntryCostMicros(pricing, entry) {
|
|
|
3739
4493
|
const inputTokens = positiveInt(entry.inputTokens);
|
|
3740
4494
|
const outputTokens = positiveInt(entry.outputTokens);
|
|
3741
4495
|
const cachedTokens = Math.min(inputTokens, cachedInputTokens(entry));
|
|
3742
|
-
const
|
|
4496
|
+
const cacheWriteTokens = Math.min(
|
|
4497
|
+
Math.max(0, inputTokens - cachedTokens),
|
|
4498
|
+
cacheWriteInputTokens(entry)
|
|
4499
|
+
);
|
|
4500
|
+
const uncachedInputTokens = Math.max(0, inputTokens - cachedTokens - cacheWriteTokens);
|
|
3743
4501
|
const cachedInputRate = pricing.cachedInputMicrosPerMillionTokens ?? pricing.inputMicrosPerMillionTokens;
|
|
3744
|
-
|
|
4502
|
+
const cacheWriteRate = pricing.cacheWriteMicrosPerMillionTokens ?? pricing.inputMicrosPerMillionTokens;
|
|
4503
|
+
return Math.ceil(uncachedInputTokens * pricing.inputMicrosPerMillionTokens / 1e6) + Math.ceil(cachedTokens * cachedInputRate / 1e6) + Math.ceil(cacheWriteTokens * cacheWriteRate / 1e6) + Math.ceil(outputTokens * pricing.outputMicrosPerMillionTokens / 1e6);
|
|
3745
4504
|
}
|
|
3746
4505
|
function cachedInputTokens(entry) {
|
|
3747
4506
|
const details = Array.isArray(entry.inputTokensDetails) ? entry.inputTokensDetails : entry.inputTokensDetails ? [entry.inputTokensDetails] : [];
|
|
@@ -3751,6 +4510,14 @@ function cachedInputTokens(entry) {
|
|
|
3751
4510
|
}
|
|
3752
4511
|
return total;
|
|
3753
4512
|
}
|
|
4513
|
+
function cacheWriteInputTokens(entry) {
|
|
4514
|
+
const details = Array.isArray(entry.inputTokensDetails) ? entry.inputTokensDetails : entry.inputTokensDetails ? [entry.inputTokensDetails] : [];
|
|
4515
|
+
let total = 0;
|
|
4516
|
+
for (const detail of details) {
|
|
4517
|
+
total += positiveInt(detail.cache_write_tokens ?? detail.cacheWriteTokens);
|
|
4518
|
+
}
|
|
4519
|
+
return total;
|
|
4520
|
+
}
|
|
3754
4521
|
function positiveInt(value) {
|
|
3755
4522
|
return typeof value === "number" && Number.isFinite(value) && value > 0 ? Math.floor(value) : 0;
|
|
3756
4523
|
}
|
|
@@ -3863,8 +4630,13 @@ function isDigestPinnedModalDesktopImage(settings) {
|
|
|
3863
4630
|
if (settings.modalImageId) return true;
|
|
3864
4631
|
return typeof settings.modalImageRef === "string" && MODAL_DESKTOP_IMAGE_DIGEST_REF.test(settings.modalImageRef);
|
|
3865
4632
|
}
|
|
3866
|
-
function validateSettings(settings) {
|
|
4633
|
+
function validateSettings(settings, source = process.env) {
|
|
3867
4634
|
temporalConnectionOptions(settings);
|
|
4635
|
+
if (settings.organizationUserSetupEmailTokenTransport === "query" && !settings.organizationUserSetupQueryEdgeSanitizationConfirmed) {
|
|
4636
|
+
throw new Error(
|
|
4637
|
+
"OPENGENI_ORGANIZATION_USER_SETUP_QUERY_EDGE_SANITIZATION_CONFIRMED=true is required when OPENGENI_ORGANIZATION_USER_SETUP_EMAIL_TOKEN_TRANSPORT=query"
|
|
4638
|
+
);
|
|
4639
|
+
}
|
|
3868
4640
|
if (settings.goalIdleBackoffMs.some((delayMs) => delayMs > settings.goalIdleBackoffMaxMs)) {
|
|
3869
4641
|
throw new Error(
|
|
3870
4642
|
`OPENGENI_GOAL_IDLE_BACKOFF_MS entries must not exceed OPENGENI_GOAL_IDLE_BACKOFF_MAX_MS (${settings.goalIdleBackoffMaxMs})`
|
|
@@ -3942,6 +4714,24 @@ function validateSettings(settings) {
|
|
|
3942
4714
|
);
|
|
3943
4715
|
}
|
|
3944
4716
|
}
|
|
4717
|
+
if (settings.mcpOauthEnabled) {
|
|
4718
|
+
if (settings.productAccessMode === "configured") {
|
|
4719
|
+
throw new Error(
|
|
4720
|
+
"OPENGENI_MCP_OAUTH_ENABLED=true requires managed or local product access mode"
|
|
4721
|
+
);
|
|
4722
|
+
}
|
|
4723
|
+
const publicOrigin = canonicalPublicOrigin(settings.publicBaseUrl);
|
|
4724
|
+
if (!publicOrigin) {
|
|
4725
|
+
throw new Error(
|
|
4726
|
+
"OPENGENI_PUBLIC_BASE_URL must be a credential-free HTTP(S) origin when OPENGENI_MCP_OAUTH_ENABLED=true"
|
|
4727
|
+
);
|
|
4728
|
+
}
|
|
4729
|
+
if (!publicOrigin.startsWith("https://") && !["local", "test"].includes(settings.environment)) {
|
|
4730
|
+
throw new Error(
|
|
4731
|
+
"OPENGENI_PUBLIC_BASE_URL must use https when OPENGENI_MCP_OAUTH_ENABLED=true outside local/test"
|
|
4732
|
+
);
|
|
4733
|
+
}
|
|
4734
|
+
}
|
|
3945
4735
|
environmentsEncryptionKeyBytes(settings);
|
|
3946
4736
|
if (settings.integrationsEnabled) {
|
|
3947
4737
|
if (settings.productAccessMode === "managed" && !settings.publicBaseUrl) {
|
|
@@ -4132,15 +4922,6 @@ function validateSettings(settings) {
|
|
|
4132
4922
|
if (settings.productAccessMode !== "managed" && settings.billingMode === "stripe") {
|
|
4133
4923
|
throw new Error("OPENGENI_BILLING_MODE=stripe requires OPENGENI_PRODUCT_ACCESS_MODE=managed");
|
|
4134
4924
|
}
|
|
4135
|
-
if (settings.billingMode === "stripe" || settings.usageLimitsMode === "managed") {
|
|
4136
|
-
const pricing = configuredModelPricing(settings);
|
|
4137
|
-
const missing = configuredAllowedModels(settings).filter((model) => !pricing[model]);
|
|
4138
|
-
if (missing.length > 0) {
|
|
4139
|
-
throw new Error(
|
|
4140
|
-
`Missing model pricing for managed billing model(s): ${missing.join(", ")}. Set OPENGENI_MODEL_PRICING_JSON.`
|
|
4141
|
-
);
|
|
4142
|
-
}
|
|
4143
|
-
}
|
|
4144
4925
|
if (settings.usageLimitsMode === "static") {
|
|
4145
4926
|
const limits = configuredStaticUsageLimits(settings);
|
|
4146
4927
|
if (Object.keys(limits).length === 0) {
|
|
@@ -4274,6 +5055,11 @@ function validateSettings(settings) {
|
|
|
4274
5055
|
throw new Error(`OPENGENI_MCP_SERVERS contains duplicate id ${server.id}`);
|
|
4275
5056
|
}
|
|
4276
5057
|
serverIds.add(server.id);
|
|
5058
|
+
if (server.connectionRef?.authoritySource === "host" && !settings.hostMcpAuthoritySourceAdmissionEnabled) {
|
|
5059
|
+
throw new Error(
|
|
5060
|
+
"OPENGENI_MCP_SERVERS host-owned connection refs require OPENGENI_HOST_MCP_AUTHORITY_SOURCE_ADMISSION_ENABLED=true after the whole API/worker fleet is upgraded"
|
|
5061
|
+
);
|
|
5062
|
+
}
|
|
4277
5063
|
}
|
|
4278
5064
|
{
|
|
4279
5065
|
const reaperPeriod = settings.sandboxLeaseReaperPeriodMs;
|
|
@@ -4289,11 +5075,35 @@ function validateSettings(settings) {
|
|
|
4289
5075
|
`OPENGENI_SANDBOX_LEASE_REAPER_PERIOD_MS (${reaperPeriod}) must be strictly less than OPENGENI_SANDBOX_INTERACTION_HOLDER_TTL_MS (${interactionTtl}): the reaper must run more often than the controller-heartbeat horizon.`
|
|
4290
5076
|
);
|
|
4291
5077
|
}
|
|
5078
|
+
if (settings.sandboxDrainSnapshotTimeoutMs !== void 0) {
|
|
5079
|
+
const drainCaptureTimeoutMs2 = sandboxArchiveCaptureTimeoutMs({
|
|
5080
|
+
sandboxSnapshotTimeoutMs: effectiveSandboxDrainSnapshotTimeoutMs(settings)
|
|
5081
|
+
});
|
|
5082
|
+
const requiredTransitionWaitMs = reaperPeriod + drainCaptureTimeoutMs2 + SANDBOX_LIFECYCLE_RETRY_HANDOFF_GRACE_MS;
|
|
5083
|
+
if (requiredTransitionWaitMs > SANDBOX_LIFECYCLE_TRANSITION_MAX_WAIT_MS) {
|
|
5084
|
+
throw new Error(
|
|
5085
|
+
`OPENGENI_SANDBOX_DRAIN_SNAPSHOT_TIMEOUT_MS (${settings.sandboxDrainSnapshotTimeoutMs}) requires a sandbox lifecycle transition wait of ${requiredTransitionWaitMs}ms after one reaper period and provider settlement, exceeding the ${SANDBOX_LIFECYCLE_TRANSITION_MAX_WAIT_MS}ms limit. Lower the drain snapshot timeout or OPENGENI_SANDBOX_LEASE_REAPER_PERIOD_MS.`
|
|
5086
|
+
);
|
|
5087
|
+
}
|
|
5088
|
+
}
|
|
5089
|
+
const rotationLeadMs = settings.sandboxRotationLeadMs;
|
|
5090
|
+
const ordinaryCaptureTimeoutMs = sandboxArchiveCaptureTimeoutMs(settings);
|
|
5091
|
+
const drainCaptureTimeoutMs = sandboxArchiveCaptureTimeoutMs({
|
|
5092
|
+
sandboxSnapshotTimeoutMs: effectiveSandboxDrainSnapshotTimeoutMs(settings)
|
|
5093
|
+
});
|
|
5094
|
+
const providerDeadlineCaptureTimeoutMs = Math.max(
|
|
5095
|
+
ordinaryCaptureTimeoutMs,
|
|
5096
|
+
drainCaptureTimeoutMs
|
|
5097
|
+
);
|
|
5098
|
+
if (!(rotationLeadMs > providerDeadlineCaptureTimeoutMs + reaperPeriod)) {
|
|
5099
|
+
throw new Error(
|
|
5100
|
+
`OPENGENI_SANDBOX_ROTATION_LEAD_MS (${rotationLeadMs}) must exceed the largest durable snapshot or drain capture timeout plus one reaper period (${providerDeadlineCaptureTimeoutMs + reaperPeriod}), including for persisted Modal leases after a default-backend rollout.`
|
|
5101
|
+
);
|
|
5102
|
+
}
|
|
4292
5103
|
if (settings.sandboxBackend === "modal") {
|
|
4293
5104
|
const idleGraceMs = settings.sandboxIdleGraceMs;
|
|
4294
5105
|
const lifecycle = effectiveSandboxLifecycle(settings, "modal");
|
|
4295
5106
|
const providerLifetimeMs = lifecycle.hardLifetimeMs;
|
|
4296
|
-
const rotationLeadMs = lifecycle.rotationLeadMs;
|
|
4297
5107
|
const idleTimeoutMs = lifecycle.providerIdleTimeoutMs;
|
|
4298
5108
|
if (!(idleTimeoutMs <= providerLifetimeMs)) {
|
|
4299
5109
|
throw new Error(
|
|
@@ -4305,12 +5115,6 @@ function validateSettings(settings) {
|
|
|
4305
5115
|
`OPENGENI_SANDBOX_ROTATION_LEAD_MS (${rotationLeadMs}) must be strictly less than OPENGENI_MODAL_TIMEOUT_SECONDS*1000 (${providerLifetimeMs}).`
|
|
4306
5116
|
);
|
|
4307
5117
|
}
|
|
4308
|
-
const captureTimeoutMs = sandboxArchiveCaptureTimeoutMs(settings);
|
|
4309
|
-
if (!(rotationLeadMs > captureTimeoutMs + reaperPeriod)) {
|
|
4310
|
-
throw new Error(
|
|
4311
|
-
`OPENGENI_SANDBOX_ROTATION_LEAD_MS (${rotationLeadMs}) must exceed the durable capture timeout plus one reaper period (${captureTimeoutMs + reaperPeriod}).`
|
|
4312
|
-
);
|
|
4313
|
-
}
|
|
4314
5118
|
if (!(viewerTtl < idleTimeoutMs)) {
|
|
4315
5119
|
throw new Error(
|
|
4316
5120
|
`OPENGENI_SANDBOX_VIEWER_HOLDER_TTL_MS (${viewerTtl}) must be strictly less than the effective box idle timeout (${idleTimeoutMs}): a viewer holder must be reapable before the box idles out from under it (the provider idle-timeout is the backstop).`
|
|
@@ -4340,15 +5144,29 @@ function validateSettings(settings) {
|
|
|
4340
5144
|
"[opengeni] OPENGENI_SANDBOX_DESKTOP_ENABLED=true but neither OPENGENI_STREAM_TOKEN_SECRET nor OPENGENI_DELEGATION_SECRET is set: the desktop pixel plane will GRACEFULLY DEGRADE (DesktopStream.transport=null \u2014 no scoped stream tokens can be minted). Set OPENGENI_STREAM_TOKEN_SECRET to enable the live desktop stream."
|
|
4341
5145
|
);
|
|
4342
5146
|
}
|
|
5147
|
+
if (settings.modelCatalogSource === "code") {
|
|
5148
|
+
validateModelCatalogSettings(settings, source);
|
|
5149
|
+
} else {
|
|
5150
|
+
parseModelCostPolicyJson(settings.modelCostPolicyJson);
|
|
5151
|
+
}
|
|
5152
|
+
}
|
|
5153
|
+
function validateModelCatalogSettings(settings, source = process.env) {
|
|
5154
|
+
const costPolicy = parseModelCostPolicyJson(settings.modelCostPolicyJson);
|
|
5155
|
+
const notes = parseModelNotesJson(settings.modelNotesJson);
|
|
4343
5156
|
const registryProviders = parseModelProvidersJson(settings.modelProvidersJson);
|
|
4344
5157
|
const builtinId = builtinProviderId(settings);
|
|
4345
5158
|
const providerIds = /* @__PURE__ */ new Set();
|
|
4346
5159
|
for (const provider of registryProviders) {
|
|
4347
|
-
if (provider.kind === "vercel-gateway-managed" || provider.kind === "vercel-gateway-workspace" || provider.kind === "xai-subscription") {
|
|
5160
|
+
if (provider.kind === "vercel-gateway-managed" || provider.kind === "vercel-gateway-workspace" || provider.kind === "vercel-gateway-organization" || provider.kind === "openrouter-workspace" || provider.kind === "openrouter-organization" || provider.kind === "xai-subscription") {
|
|
4348
5161
|
throw new Error(
|
|
4349
5162
|
`OPENGENI_MODEL_PROVIDERS_JSON provider kind ${provider.kind} is reserved for a reviewed OpenGeni credential broker`
|
|
4350
5163
|
);
|
|
4351
5164
|
}
|
|
5165
|
+
if (RESERVED_MODEL_PROVIDER_IDS.has(provider.id)) {
|
|
5166
|
+
throw new Error(
|
|
5167
|
+
`OPENGENI_MODEL_PROVIDERS_JSON provider id ${provider.id} is reserved for a reviewed OpenGeni provider`
|
|
5168
|
+
);
|
|
5169
|
+
}
|
|
4352
5170
|
if (provider.id === builtinId) {
|
|
4353
5171
|
throw new Error(
|
|
4354
5172
|
`OPENGENI_MODEL_PROVIDERS_JSON provider id ${provider.id} collides with the built-in provider id`
|
|
@@ -4360,13 +5178,66 @@ function validateSettings(settings) {
|
|
|
4360
5178
|
);
|
|
4361
5179
|
}
|
|
4362
5180
|
providerIds.add(provider.id);
|
|
4363
|
-
if (provider.kind !== "codex-subscription" && provider.kind !== "anonymous" && !resolveProviderApiKey(provider)) {
|
|
5181
|
+
if (provider.kind !== "codex-subscription" && provider.kind !== "anonymous" && !resolveProviderApiKey(provider, source)) {
|
|
4364
5182
|
throw new Error(
|
|
4365
5183
|
`OPENGENI_MODEL_PROVIDERS_JSON provider ${provider.id} requires a resolvable API key (set apiKey or apiKeyEnv)`
|
|
4366
5184
|
);
|
|
4367
5185
|
}
|
|
4368
5186
|
}
|
|
4369
|
-
configuredModels(settings);
|
|
5187
|
+
const models = configuredModels(settings, source);
|
|
5188
|
+
const defaultCatalogSettings = settingsForTurnExecutionPolicy(settings, settings.openaiModel);
|
|
5189
|
+
const defaultCatalogModels = defaultCatalogSettings === settings ? models : configuredModels(defaultCatalogSettings, source);
|
|
5190
|
+
if (models.length === 0 && defaultCatalogModels.length === 0) {
|
|
5191
|
+
throw new Error("The resolved model catalog contains no executable models");
|
|
5192
|
+
}
|
|
5193
|
+
const defaultModelId = canonicalizeConfiguredModelId(
|
|
5194
|
+
defaultCatalogSettings,
|
|
5195
|
+
settings.openaiModel
|
|
5196
|
+
);
|
|
5197
|
+
if (!defaultCatalogModels.some((model) => model.id === defaultModelId)) {
|
|
5198
|
+
throw new Error(
|
|
5199
|
+
`The default model ${settings.openaiModel} is not executable in the resolved model catalog`
|
|
5200
|
+
);
|
|
5201
|
+
}
|
|
5202
|
+
const deploymentProductIds = new Set(
|
|
5203
|
+
models.filter((model) => model.credentialSource.kind === "deployment").map((model) => model.id)
|
|
5204
|
+
);
|
|
5205
|
+
const noteProductIds = new Set(models.map((model) => model.id));
|
|
5206
|
+
for (const model of configuredGatewayCatalogModels(settings)) {
|
|
5207
|
+
deploymentProductIds.add(model.productId);
|
|
5208
|
+
noteProductIds.add(model.productId);
|
|
5209
|
+
noteProductIds.add(model.workspaceProductId);
|
|
5210
|
+
}
|
|
5211
|
+
for (const model of configuredOpenRouterCatalogModels(settings)) {
|
|
5212
|
+
const productId = `${OPENROUTER_MODEL_ID_PREFIX}${model.upstreamModelId}`;
|
|
5213
|
+
deploymentProductIds.add(productId);
|
|
5214
|
+
noteProductIds.add(productId);
|
|
5215
|
+
noteProductIds.add(`${WORKSPACE_OPENROUTER_MODEL_ID_PREFIX}${model.upstreamModelId}`);
|
|
5216
|
+
}
|
|
5217
|
+
if (settings.modelCatalogSource === "code") {
|
|
5218
|
+
for (const productId of Object.keys(costPolicy)) {
|
|
5219
|
+
if (!deploymentProductIds.has(productId)) {
|
|
5220
|
+
throw new Error(
|
|
5221
|
+
`OPENGENI_MODEL_COST_POLICY_JSON references unknown deployment model ${productId}`
|
|
5222
|
+
);
|
|
5223
|
+
}
|
|
5224
|
+
}
|
|
5225
|
+
}
|
|
5226
|
+
for (const productId of Object.keys(notes)) {
|
|
5227
|
+
if (!noteProductIds.has(productId)) {
|
|
5228
|
+
throw new Error(`OPENGENI_MODEL_NOTES_JSON references unknown catalog model ${productId}`);
|
|
5229
|
+
}
|
|
5230
|
+
}
|
|
5231
|
+
if (settings.billingMode === "stripe" || settings.usageLimitsMode === "managed") {
|
|
5232
|
+
const pricing = configuredModelPricing(settings);
|
|
5233
|
+
const missing = models.filter((model) => model.cost === "credits" && !pricing[model.id]).map((model) => model.id);
|
|
5234
|
+
if (missing.length > 0) {
|
|
5235
|
+
throw new Error(
|
|
5236
|
+
`Missing model pricing for managed billing model(s): ${missing.join(", ")}. Set OPENGENI_MODEL_PRICING_JSON.`
|
|
5237
|
+
);
|
|
5238
|
+
}
|
|
5239
|
+
}
|
|
5240
|
+
return models;
|
|
4370
5241
|
}
|
|
4371
5242
|
function resolveStreamTokenSecret(settings) {
|
|
4372
5243
|
const explicit = settings.streamTokenSecret?.trim();
|
|
@@ -4456,19 +5327,35 @@ export {
|
|
|
4456
5327
|
CODEX_REALTIME_MODEL_ID,
|
|
4457
5328
|
CapabilityStateV1Schema,
|
|
4458
5329
|
CapabilitySupportV1,
|
|
5330
|
+
ConfiguredModelCostClass,
|
|
4459
5331
|
DEFAULT_AGENT_INSTRUCTIONS,
|
|
4460
5332
|
DEFAULT_GOAL_IDLE_BACKOFF_MAX_MS,
|
|
4461
5333
|
DEFAULT_GOAL_IDLE_BACKOFF_MS,
|
|
5334
|
+
DEFAULT_MODAL_IMAGE_REF,
|
|
5335
|
+
DEFAULT_MODEL_COST_POLICY_JSON,
|
|
5336
|
+
DEFAULT_OPENROUTER_MODEL_ID,
|
|
4462
5337
|
GOOGLE_DRIVE_PROVIDER_REQUEST_TIMEOUT_MAX_MS,
|
|
4463
5338
|
GOOGLE_DRIVE_PROVIDER_RETRY_DELAY_MAX_MS,
|
|
5339
|
+
GatewayCatalogModel,
|
|
4464
5340
|
IntegrationOAuthClientConfigSchema,
|
|
4465
5341
|
McpServerConnectionRefSchema,
|
|
4466
5342
|
ModelCapabilitiesV1Schema,
|
|
5343
|
+
ModelCatalogDocument,
|
|
5344
|
+
ModelCostClass,
|
|
4467
5345
|
ModelProviderApi,
|
|
4468
5346
|
ModelProviderWireProfile,
|
|
4469
5347
|
OPENGENI_GATEWAY_MODELS,
|
|
4470
5348
|
OPENGENI_GATEWAY_PROVIDER_ID,
|
|
5349
|
+
OPENGENI_OPENROUTER_MODELS,
|
|
4471
5350
|
OPENGENI_REALTIME_MODEL_ID_PREFIX,
|
|
5351
|
+
OPENROUTER_BASE_URL,
|
|
5352
|
+
OPENROUTER_MODEL_ID_PREFIX,
|
|
5353
|
+
OPENROUTER_PROVIDER_ID,
|
|
5354
|
+
ORGANIZATION_GATEWAY_MODEL_ID_PREFIX,
|
|
5355
|
+
ORGANIZATION_GATEWAY_PROVIDER_ID,
|
|
5356
|
+
ORGANIZATION_OPENROUTER_MODEL_ID_PREFIX,
|
|
5357
|
+
ORGANIZATION_OPENROUTER_PROVIDER_ID,
|
|
5358
|
+
OpenRouterCatalogModel,
|
|
4472
5359
|
RegistryProviderKind,
|
|
4473
5360
|
SANDBOX_ARCHIVE_CAPTURE_MAX_TIMEOUT_MS,
|
|
4474
5361
|
SANDBOX_ARCHIVE_CAPTURE_SETTLEMENT_GRACE_MS,
|
|
@@ -4484,14 +5371,20 @@ export {
|
|
|
4484
5371
|
VERCEL_AI_GATEWAY_CONNECTION_ROLE,
|
|
4485
5372
|
WORKSPACE_GATEWAY_MODEL_ID_PREFIX,
|
|
4486
5373
|
WORKSPACE_GATEWAY_PROVIDER_ID,
|
|
5374
|
+
WORKSPACE_OPENROUTER_CONNECTION_DOMAIN,
|
|
5375
|
+
WORKSPACE_OPENROUTER_CONNECTION_ROLE,
|
|
5376
|
+
WORKSPACE_OPENROUTER_MODEL_ID_PREFIX,
|
|
5377
|
+
WORKSPACE_OPENROUTER_PROVIDER_ID,
|
|
4487
5378
|
WORKSPACE_REALTIME_MODEL_ID_PREFIX,
|
|
4488
5379
|
XAI_SUBSCRIPTION_MODEL_ID_PREFIX2 as XAI_SUBSCRIPTION_MODEL_ID_PREFIX,
|
|
4489
5380
|
allowedFirstPartyMcpToolsForSession,
|
|
4490
5381
|
applyGitAuthPointerEnvironment,
|
|
5382
|
+
applyModelCatalogDocument,
|
|
4491
5383
|
assertTurnExecutionPolicyMatchesConfigV1,
|
|
4492
5384
|
builtinProviderId,
|
|
4493
5385
|
calculateGatewayReportedCostBreakdown,
|
|
4494
5386
|
calculateGatewayReportedCostMicros,
|
|
5387
|
+
calculateGatewayReportedProviderCostMicros,
|
|
4495
5388
|
calculateModelUsageCostBreakdown,
|
|
4496
5389
|
calculateModelUsageCostMicros,
|
|
4497
5390
|
calculateVideoGenerationCreditCostMicros,
|
|
@@ -4503,16 +5396,25 @@ export {
|
|
|
4503
5396
|
configuredAllowedModels,
|
|
4504
5397
|
configuredAllowedReasoningEfforts,
|
|
4505
5398
|
configuredEntitlements,
|
|
5399
|
+
configuredGatewayOrganizationProductModelIds,
|
|
5400
|
+
configuredGatewayUpstreamModelIds,
|
|
5401
|
+
configuredGatewayWorkspaceProductModelIds,
|
|
4506
5402
|
configuredGoogleDriveSyncLimits,
|
|
5403
|
+
configuredModelInputIdentities,
|
|
5404
|
+
configuredModelNotes,
|
|
4507
5405
|
configuredModelPricing,
|
|
4508
5406
|
configuredModelPricingSchedules,
|
|
4509
5407
|
configuredModels,
|
|
5408
|
+
configuredOpenRouterOrganizationProductModelIds,
|
|
5409
|
+
configuredOpenRouterUpstreamModelIds,
|
|
5410
|
+
configuredOpenRouterWorkspaceProductModelIds,
|
|
4510
5411
|
configuredProviders,
|
|
4511
5412
|
configuredStaticUsageLimits,
|
|
4512
5413
|
contextInputBudgetTokens,
|
|
4513
5414
|
dbSearchPath,
|
|
4514
5415
|
defaultModelPricing,
|
|
4515
5416
|
effectiveModalIdleTimeoutSeconds,
|
|
5417
|
+
effectiveSandboxDrainSnapshotTimeoutMs,
|
|
4516
5418
|
effectiveSandboxLifecycle,
|
|
4517
5419
|
environmentsEncryptionKeyBytes,
|
|
4518
5420
|
firstPartyMcpBaseUrl,
|
|
@@ -4527,9 +5429,13 @@ export {
|
|
|
4527
5429
|
hasGitHubRepositorySelection,
|
|
4528
5430
|
isDirectOpenAiApiBaseUrl,
|
|
4529
5431
|
isUsableVoiceInputSecret,
|
|
5432
|
+
modelCostClassForConfiguredModel,
|
|
4530
5433
|
parseExposedPorts,
|
|
4531
5434
|
parseIntegrationsOauthClientsJson,
|
|
4532
5435
|
parseMcpServers,
|
|
5436
|
+
parseModelCatalogDocument,
|
|
5437
|
+
parseModelCostPolicyJson,
|
|
5438
|
+
parseModelNotesJson,
|
|
4533
5439
|
parseModelPricingJson,
|
|
4534
5440
|
parseModelProvidersJson,
|
|
4535
5441
|
parseSandboxWarmRateJson,
|
|
@@ -4546,6 +5452,7 @@ export {
|
|
|
4546
5452
|
resolveFirstPartyDelegationSecret,
|
|
4547
5453
|
resolveFirstPartyMcpToolPolicy,
|
|
4548
5454
|
resolveModelProvider,
|
|
5455
|
+
resolveModelProviderForTurn,
|
|
4549
5456
|
resolveNatsCalloutConfig,
|
|
4550
5457
|
resolveNatsControlPlaneAuth,
|
|
4551
5458
|
resolveProviderApiKey,
|
|
@@ -4569,10 +5476,17 @@ export {
|
|
|
4569
5476
|
startupRetryOptions,
|
|
4570
5477
|
streamTokenDegraded,
|
|
4571
5478
|
temporalConnectionOptions,
|
|
5479
|
+
validateModelCatalogSettings,
|
|
4572
5480
|
voiceInputDeploymentConfigured,
|
|
4573
5481
|
withCodexCatalogProvider,
|
|
5482
|
+
withOrganizationGatewayCatalogProvider,
|
|
5483
|
+
withOrganizationGatewayCredential,
|
|
5484
|
+
withOrganizationOpenRouterCatalogProvider,
|
|
5485
|
+
withOrganizationOpenRouterCredential,
|
|
4574
5486
|
withWorkspaceGatewayCatalogProvider,
|
|
4575
5487
|
withWorkspaceGatewayCredential,
|
|
5488
|
+
withWorkspaceOpenRouterCatalogProvider,
|
|
5489
|
+
withWorkspaceOpenRouterCredential,
|
|
4576
5490
|
withXaiSubscriptionCatalogProvider
|
|
4577
5491
|
};
|
|
4578
5492
|
//# sourceMappingURL=index.js.map
|