@opengeni/config 0.22.5 → 0.23.2-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.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({
@@ -384,6 +396,13 @@ var SettingsSchema = z.object({
384
396
  // into @opengeni/db once at boot.
385
397
  // Env: OPENGENI_CHILD_LIFECYCLE_NOTICES_ENABLED.
386
398
  childLifecycleNoticesEnabled: EnvBoolean.default(false),
399
+ // Explicit host-owned MCP connection authority is a rolling protocol
400
+ // activation. Keep it off while any API, worker, or browser bundle predates
401
+ // the authority discriminator; enable it only after the whole fleet runs an
402
+ // image that understands host refs. Legacy markerless non-UUID refs remain a
403
+ // separate compatibility lane for already-persisted embedding integrations.
404
+ // Env: OPENGENI_HOST_MCP_AUTHORITY_SOURCE_ADMISSION_ENABLED.
405
+ hostMcpAuthoritySourceAdmissionEnabled: EnvBoolean.default(false),
387
406
  // Per-channel and per-DM Slack workspace routing. Default ON. A channel does
388
407
  // not count a personal workspace as a candidate, so an organization with one
389
408
  // shared workspace resolves it as the sole candidate and never asks; the
@@ -511,6 +530,24 @@ var SettingsSchema = z.object({
511
530
  // keep subscription model routing while disabling Codex voice input.
512
531
  voiceInputCodexExperimentalEnabled: EnvBoolean.default(false),
513
532
  modelPricingJson: z.string().default("{}"),
533
+ // Supported-model membership source. Database mode is resolved by the async
534
+ // core overlay; getSettings remains synchronous and env-only.
535
+ modelCatalogSource: z.enum(["code", "database"]).default("code"),
536
+ // Deployment-owned workspace-facing price policy. This is deliberately
537
+ // separate from catalog membership and upstream credential ownership.
538
+ // Shape: { "product/model-id": "free" | "credits" }.
539
+ modelCostPolicyJson: z.string().default("{}"),
540
+ // Optional per-product agent guidance. Database mode replaces this with the
541
+ // singleton document's validated modelNotes map.
542
+ modelNotesJson: z.string().default("{}"),
543
+ // Managed OpenRouter credential. The curated model table is injected in
544
+ // code/catalog-document resolution and never read from host provider JSON.
545
+ openrouterApiKey: z.string().optional(),
546
+ // Internal, secret-free catalog overlays populated only by
547
+ // applyModelCatalogDocument. They intentionally have no OPENGENI_* env
548
+ // binding so database mode cannot be bypassed with a second source.
549
+ resolvedGatewayModelsJson: z.string().optional(),
550
+ resolvedOpenRouterModelsJson: z.string().optional(),
514
551
  // Extra (non-built-in) model providers, declared by the host as a JSON
515
552
  // provider registry. Each entry carries its own base URL, API key, wire API
516
553
  // ("responses" | "chat") and the models it exposes. The models a client may
@@ -956,6 +993,13 @@ var SettingsSchema = z.object({
956
993
  // treated exactly like a failed best-effort snapshot. Knob:
957
994
  // OPENGENI_SANDBOX_SNAPSHOT_TIMEOUT_MS. Default 60s.
958
995
  sandboxSnapshotTimeoutMs: z.coerce.number().int().positive().max(SANDBOX_SNAPSHOT_MAX_TIMEOUT_MS).default(6e4),
996
+ // A zero-holder drain may need substantially longer than a best-effort
997
+ // mid-turn/turn-end snapshot for a very large workspace. Keep that provider
998
+ // budget independent so increasing drain recovery headroom cannot pin an
999
+ // ordinary turn finalizer for the same duration. Unset preserves the legacy
1000
+ // single-budget behavior. Knob:
1001
+ // OPENGENI_SANDBOX_DRAIN_SNAPSHOT_TIMEOUT_MS.
1002
+ sandboxDrainSnapshotTimeoutMs: z.coerce.number().int().positive().max(SANDBOX_SNAPSHOT_MAX_TIMEOUT_MS).optional(),
959
1003
  // Begin a controlled snapshot/quiesce/drain/rematerialize transition this far
960
1004
  // ahead of a finite provider deadline. Modal's 24h creation clock cannot be
961
1005
  // extended; the logical sandbox outlives it by moving to one successor box.
@@ -1227,6 +1271,7 @@ function voiceInputDeploymentConfigured(settings) {
1227
1271
  var ModelPricingSchema = z.object({
1228
1272
  inputMicrosPerMillionTokens: z.number().int().nonnegative(),
1229
1273
  cachedInputMicrosPerMillionTokens: z.number().int().nonnegative().optional(),
1274
+ cacheWriteMicrosPerMillionTokens: z.number().int().nonnegative().optional(),
1230
1275
  outputMicrosPerMillionTokens: z.number().int().nonnegative(),
1231
1276
  marginBps: z.number().int().min(0).max(1e5).optional()
1232
1277
  });
@@ -1362,7 +1407,10 @@ var RegistryProviderKind = z.enum([
1362
1407
  "codex-subscription",
1363
1408
  "xai-subscription",
1364
1409
  "vercel-gateway-managed",
1365
- "vercel-gateway-workspace"
1410
+ "vercel-gateway-workspace",
1411
+ "vercel-gateway-organization",
1412
+ "openrouter-workspace",
1413
+ "openrouter-organization"
1366
1414
  ]);
1367
1415
  var RegistryModelSchema = z.object({
1368
1416
  id: z.string().min(1),
@@ -1475,6 +1523,297 @@ var RegistryProviderSchema = z.object({
1475
1523
  });
1476
1524
  }
1477
1525
  });
1526
+ var OPENGENI_GATEWAY_PROVIDER_ID = "opengeni-gateway";
1527
+ var WORKSPACE_GATEWAY_PROVIDER_ID = "workspace-gateway";
1528
+ var WORKSPACE_GATEWAY_MODEL_ID_PREFIX = "workspace-gateway/";
1529
+ var ORGANIZATION_GATEWAY_PROVIDER_ID = "organization-gateway";
1530
+ var ORGANIZATION_GATEWAY_MODEL_ID_PREFIX = "organization-gateway/";
1531
+ var OPENROUTER_PROVIDER_ID = "openrouter";
1532
+ var OPENROUTER_MODEL_ID_PREFIX = "openrouter/";
1533
+ var WORKSPACE_OPENROUTER_PROVIDER_ID = "workspace-openrouter";
1534
+ var WORKSPACE_OPENROUTER_MODEL_ID_PREFIX = "workspace-openrouter/";
1535
+ var ORGANIZATION_OPENROUTER_PROVIDER_ID = "organization-openrouter";
1536
+ var ORGANIZATION_OPENROUTER_MODEL_ID_PREFIX = "organization-openrouter/";
1537
+ var OPENROUTER_BASE_URL = "https://openrouter.ai/api/v1";
1538
+ var RESERVED_MODEL_PROVIDER_IDS = /* @__PURE__ */ new Set([
1539
+ "openai",
1540
+ "azure",
1541
+ CODEX_PROVIDER_ID,
1542
+ XAI_SUBSCRIPTION_PROVIDER_ID,
1543
+ OPENGENI_GATEWAY_PROVIDER_ID,
1544
+ WORKSPACE_GATEWAY_PROVIDER_ID,
1545
+ ORGANIZATION_GATEWAY_PROVIDER_ID,
1546
+ OPENROUTER_PROVIDER_ID,
1547
+ WORKSPACE_OPENROUTER_PROVIDER_ID,
1548
+ ORGANIZATION_OPENROUTER_PROVIDER_ID
1549
+ ]);
1550
+ var ModelCostClass = z.enum(["free", "credits"]);
1551
+ var ConfiguredModelCostClass = z.enum([
1552
+ "free",
1553
+ "credits",
1554
+ "subscription",
1555
+ "workspace",
1556
+ "organization"
1557
+ ]);
1558
+ var ModelNote = z.string().max(500).refine((value) => !/[\r\n|]/u.test(value), {
1559
+ message: "model notes must not contain newlines or the | field separator"
1560
+ });
1561
+ function parseModelCostPolicyJson(raw) {
1562
+ let parsed;
1563
+ try {
1564
+ parsed = JSON.parse(raw);
1565
+ } catch (error) {
1566
+ throw new Error(
1567
+ `OPENGENI_MODEL_COST_POLICY_JSON must be valid JSON: ${error instanceof Error ? error.message : String(error)}`,
1568
+ { cause: error }
1569
+ );
1570
+ }
1571
+ return z.record(z.string().min(1), ModelCostClass).parse(parsed);
1572
+ }
1573
+ function parseModelNotesJson(raw) {
1574
+ let parsed;
1575
+ try {
1576
+ parsed = JSON.parse(raw);
1577
+ } catch (error) {
1578
+ throw new Error(
1579
+ `OPENGENI_MODEL_NOTES_JSON must be valid JSON: ${error instanceof Error ? error.message : String(error)}`,
1580
+ { cause: error }
1581
+ );
1582
+ }
1583
+ return z.record(z.string().min(1), ModelNote).parse(parsed);
1584
+ }
1585
+ function configuredModelNotes(settings) {
1586
+ return parseModelNotesJson(settings.modelNotesJson);
1587
+ }
1588
+ var GatewayCatalogModel = z.object({
1589
+ productId: z.string().min(1),
1590
+ workspaceProductId: z.string().min(1).startsWith(WORKSPACE_GATEWAY_MODEL_ID_PREFIX),
1591
+ upstreamModelId: z.string().min(1),
1592
+ label: z.string().min(1),
1593
+ shortLabel: z.string().min(1).max(64).optional(),
1594
+ providers: z.array(z.string().min(1)).min(1),
1595
+ implicitCaching: z.boolean().default(false),
1596
+ vision: z.boolean().default(false),
1597
+ inputFileMediaTypes: z.array(z.string().min(1)).default([]),
1598
+ contextWindowTokens: z.number().int().positive().default(1e6),
1599
+ effectiveContextWindowTokens: z.number().int().positive().default(9e5),
1600
+ autoCompactTokenLimit: z.number().int().positive().default(85e4),
1601
+ pricing: z.union([ModelPricingSchema, ModelPricingScheduleSchema]).optional(),
1602
+ credentialSource: z.never().optional(),
1603
+ billing: z.never().optional(),
1604
+ apiKey: z.never().optional()
1605
+ }).strict();
1606
+ var OpenRouterCatalogModel = z.object({
1607
+ upstreamModelId: z.string().min(1).endsWith(":free"),
1608
+ label: z.string().min(1),
1609
+ shortLabel: z.string().min(1).max(64).optional(),
1610
+ aliases: z.array(z.string().min(1)).default([]),
1611
+ capabilities: ModelCapabilitiesV1Schema,
1612
+ contextWindowTokens: z.number().int().positive().optional(),
1613
+ effectiveContextWindowTokens: z.number().int().positive().optional(),
1614
+ autoCompactTokenLimit: z.number().int().positive().optional(),
1615
+ toolOutputTruncationTokens: z.number().int().positive().optional(),
1616
+ credentialSource: z.never().optional(),
1617
+ billing: z.never().optional(),
1618
+ pricing: z.never().optional(),
1619
+ apiKey: z.never().optional()
1620
+ }).strict();
1621
+ var DeploymentRegistryBaseUrl = z.string().url().superRefine((value, context) => {
1622
+ const url = new URL(value);
1623
+ if (url.username || url.password) {
1624
+ context.addIssue({
1625
+ code: "custom",
1626
+ message: "database catalog provider baseUrl must not contain userinfo"
1627
+ });
1628
+ }
1629
+ if (url.search) {
1630
+ context.addIssue({
1631
+ code: "custom",
1632
+ message: "database catalog provider baseUrl must not contain a query"
1633
+ });
1634
+ }
1635
+ if (url.hash) {
1636
+ context.addIssue({
1637
+ code: "custom",
1638
+ message: "database catalog provider baseUrl must not contain a fragment"
1639
+ });
1640
+ }
1641
+ });
1642
+ var DeploymentRegistryProviderKind = z.enum(["api-key", "anonymous"]);
1643
+ var DeploymentRegistryModelSchema = RegistryModelSchema.safeExtend({
1644
+ pricing: z.never().optional()
1645
+ }).strict();
1646
+ var DeploymentRegistryProviderSchema = RegistryProviderSchema.safeExtend({
1647
+ kind: DeploymentRegistryProviderKind.default("api-key"),
1648
+ baseUrl: DeploymentRegistryBaseUrl,
1649
+ models: z.array(DeploymentRegistryModelSchema).min(1),
1650
+ apiKey: z.never().optional(),
1651
+ apiKeyEnv: z.never().optional(),
1652
+ defaultHeaders: z.never().optional(),
1653
+ defaultQuery: z.never().optional(),
1654
+ publicDefaultHeaderNames: z.never().optional(),
1655
+ publicDefaultQueryNames: z.never().optional()
1656
+ }).strict();
1657
+ var DeploymentGatewayCatalogModelSchema = GatewayCatalogModel.safeExtend({
1658
+ pricing: z.never().optional()
1659
+ }).strict();
1660
+ var ModelCatalogDocument = z.object({
1661
+ schemaVersion: z.literal(1),
1662
+ /** Canonical deployment default. Omission preserves the V1 first-built-in
1663
+ * fallback for existing documents; operators should set this explicitly
1664
+ * when cutting over a registry or connected-subscription default. */
1665
+ defaultModel: z.string().min(1).optional(),
1666
+ builtInModels: z.array(z.string().min(1)).min(1),
1667
+ registryProviders: z.array(DeploymentRegistryProviderSchema).default([]),
1668
+ gatewayModels: z.array(DeploymentGatewayCatalogModelSchema).default([]),
1669
+ openrouterModels: z.array(OpenRouterCatalogModel).default([]),
1670
+ modelNotes: z.record(z.string().min(1), ModelNote).default({}),
1671
+ billing: z.never().optional(),
1672
+ enabled: z.never().optional(),
1673
+ apiKey: z.never().optional(),
1674
+ bands: z.never().optional()
1675
+ }).strict().superRefine((document, context) => {
1676
+ const productIds = /* @__PURE__ */ new Set();
1677
+ const providerIds = /* @__PURE__ */ new Set();
1678
+ const gatewayUpstreamIds = /* @__PURE__ */ new Set();
1679
+ const add = (id, path) => {
1680
+ if (/[\u000A\u000D|]/u.test(id)) {
1681
+ context.addIssue({
1682
+ code: "custom",
1683
+ path,
1684
+ message: "catalog product ids must not contain newlines or the | field separator"
1685
+ });
1686
+ }
1687
+ if (productIds.has(id)) {
1688
+ context.addIssue({
1689
+ code: "custom",
1690
+ path,
1691
+ message: `duplicate product id ${id}`
1692
+ });
1693
+ }
1694
+ productIds.add(id);
1695
+ };
1696
+ document.builtInModels.forEach((id, index) => add(id, ["builtInModels", index]));
1697
+ document.registryProviders.forEach((provider, providerIndex) => {
1698
+ if (RESERVED_MODEL_PROVIDER_IDS.has(provider.id)) {
1699
+ context.addIssue({
1700
+ code: "custom",
1701
+ path: ["registryProviders", providerIndex, "id"],
1702
+ message: `provider id ${provider.id} is reserved for a reviewed OpenGeni provider`
1703
+ });
1704
+ }
1705
+ if (providerIds.has(provider.id)) {
1706
+ context.addIssue({
1707
+ code: "custom",
1708
+ path: ["registryProviders", providerIndex, "id"],
1709
+ message: `duplicate provider id ${provider.id}`
1710
+ });
1711
+ }
1712
+ providerIds.add(provider.id);
1713
+ provider.models.forEach(
1714
+ (model, modelIndex) => add(model.id, ["registryProviders", providerIndex, "models", modelIndex, "id"])
1715
+ );
1716
+ });
1717
+ document.gatewayModels.forEach((model, index) => {
1718
+ if (gatewayUpstreamIds.has(model.upstreamModelId)) {
1719
+ context.addIssue({
1720
+ code: "custom",
1721
+ path: ["gatewayModels", index, "upstreamModelId"],
1722
+ message: `duplicate Gateway upstream model id ${model.upstreamModelId}`
1723
+ });
1724
+ }
1725
+ gatewayUpstreamIds.add(model.upstreamModelId);
1726
+ add(model.productId, ["gatewayModels", index, "productId"]);
1727
+ add(model.workspaceProductId, ["gatewayModels", index, "workspaceProductId"]);
1728
+ });
1729
+ document.openrouterModels.forEach(
1730
+ (model, index) => add(`${OPENROUTER_MODEL_ID_PREFIX}${model.upstreamModelId}`, [
1731
+ "openrouterModels",
1732
+ index,
1733
+ "upstreamModelId"
1734
+ ])
1735
+ );
1736
+ if (document.defaultModel && /[\u000A\u000D|]/u.test(document.defaultModel)) {
1737
+ context.addIssue({
1738
+ code: "custom",
1739
+ path: ["defaultModel"],
1740
+ message: "catalog default model must not contain newlines or the | field separator"
1741
+ });
1742
+ }
1743
+ if (document.defaultModel && !productIds.has(document.defaultModel) && !document.defaultModel.startsWith(CODEX_MODEL_ID_PREFIX) && !document.defaultModel.startsWith(XAI_SUBSCRIPTION_MODEL_ID_PREFIX)) {
1744
+ context.addIssue({
1745
+ code: "custom",
1746
+ path: ["defaultModel"],
1747
+ message: "catalog default model must reference deployment catalog membership or a connected-subscription product"
1748
+ });
1749
+ }
1750
+ for (const productId of Object.keys(document.modelNotes)) {
1751
+ if (!productIds.has(productId)) {
1752
+ context.addIssue({
1753
+ code: "custom",
1754
+ path: ["modelNotes", productId],
1755
+ message: "model note references a product id outside the deployment catalog"
1756
+ });
1757
+ }
1758
+ }
1759
+ });
1760
+ function parseModelCatalogDocument(value) {
1761
+ return ModelCatalogDocument.parse(value);
1762
+ }
1763
+ function deploymentRegistryProvidersWithHostCredentials(settings, providers) {
1764
+ const hostProviders = new Map(
1765
+ parseModelProvidersJson(settings.modelProvidersJson).map((provider) => [provider.id, provider])
1766
+ );
1767
+ return providers.map((provider) => {
1768
+ if (provider.kind !== "api-key") return provider;
1769
+ const host = hostProviders.get(provider.id);
1770
+ if (!host || host.kind !== "api-key") {
1771
+ throw new Error(
1772
+ `database model catalog provider ${provider.id} has no matching host-authorized api-key transport`
1773
+ );
1774
+ }
1775
+ const transportIdentity = (candidate) => ({
1776
+ kind: candidate.kind,
1777
+ baseUrl: candidate.baseUrl,
1778
+ api: candidate.api,
1779
+ wireProfile: candidate.wireProfile
1780
+ });
1781
+ if (canonicalJson(transportIdentity(provider)) !== canonicalJson(transportIdentity(host))) {
1782
+ throw new Error(
1783
+ `database model catalog provider ${provider.id} does not match its host-authorized transport`
1784
+ );
1785
+ }
1786
+ return {
1787
+ ...provider,
1788
+ ...host.defaultHeaders === void 0 ? {} : { defaultHeaders: host.defaultHeaders },
1789
+ ...host.defaultQuery === void 0 ? {} : { defaultQuery: host.defaultQuery },
1790
+ ...host.publicDefaultHeaderNames === void 0 ? {} : { publicDefaultHeaderNames: host.publicDefaultHeaderNames },
1791
+ ...host.publicDefaultQueryNames === void 0 ? {} : { publicDefaultQueryNames: host.publicDefaultQueryNames },
1792
+ ...host.apiKey === void 0 ? {} : { apiKey: host.apiKey },
1793
+ ...host.apiKeyEnv === void 0 ? {} : { apiKeyEnv: host.apiKeyEnv }
1794
+ };
1795
+ });
1796
+ }
1797
+ function applyModelCatalogDocument(settings, rawDocument) {
1798
+ const document = parseModelCatalogDocument(rawDocument);
1799
+ const defaultModel = document.defaultModel ?? document.builtInModels[0];
1800
+ const resolved = {
1801
+ ...settings,
1802
+ openaiModel: defaultModel,
1803
+ // Keep the complete built-in membership, including the default. The worker
1804
+ // replaces openaiModel with the exact turn model; the run-scoped router
1805
+ // needs one stable built-in id in this allow-list so a bare provider model
1806
+ // is not temporarily claimed by OpenAI/Azure during name re-resolution.
1807
+ openaiAllowedModels: document.builtInModels.join(","),
1808
+ modelProvidersJson: JSON.stringify(
1809
+ deploymentRegistryProvidersWithHostCredentials(settings, document.registryProviders)
1810
+ ),
1811
+ resolvedGatewayModelsJson: JSON.stringify(document.gatewayModels),
1812
+ resolvedOpenRouterModelsJson: JSON.stringify(document.openrouterModels),
1813
+ modelNotesJson: JSON.stringify(document.modelNotes)
1814
+ };
1815
+ return resolved;
1816
+ }
1478
1817
  var IntegrationOAuthClientConfigSchema = z.object({
1479
1818
  clientId: z.string().min(1),
1480
1819
  clientSecret: z.string().min(1).optional(),
@@ -1482,11 +1821,10 @@ var IntegrationOAuthClientConfigSchema = z.object({
1482
1821
  });
1483
1822
  var VERCEL_AI_GATEWAY_BASE_URL = "https://ai-gateway.vercel.sh/v1";
1484
1823
  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
1824
  var VERCEL_AI_GATEWAY_CONNECTION_DOMAIN = "ai-gateway.vercel.sh";
1489
1825
  var VERCEL_AI_GATEWAY_CONNECTION_ROLE = "vercel_ai_gateway";
1826
+ var WORKSPACE_OPENROUTER_CONNECTION_DOMAIN = "openrouter.ai";
1827
+ var WORKSPACE_OPENROUTER_CONNECTION_ROLE = "openrouter";
1490
1828
  var CODEX_REALTIME_MODEL_ID = "gpt-live-1-boulder-alpha";
1491
1829
  var SUPERGROK_REALTIME_MODEL_ID = "supergrok/grok-voice-think-fast-2.0";
1492
1830
  var OPENGENI_REALTIME_MODEL_ID_PREFIX = "opengeni-gateway/";
@@ -1545,23 +1883,126 @@ var OPENGENI_GATEWAY_MODELS = {
1545
1883
  implicitCaching: true
1546
1884
  }
1547
1885
  };
1886
+ var OPENGENI_OPENROUTER_MODELS = [
1887
+ OpenRouterCatalogModel.parse({
1888
+ upstreamModelId: "nvidia/nemotron-3-super-120b-a12b:free",
1889
+ label: "Nemotron 3 Super 120B",
1890
+ shortLabel: "Nemotron 3 Super",
1891
+ aliases: [],
1892
+ capabilities: {
1893
+ reasoning: {
1894
+ upstream: "supported",
1895
+ // OpenRouter advertises the reasoning controls, but the catalogue does
1896
+ // not publish this model's accepted effort vocabulary. Preserve that
1897
+ // upstream fact without exposing an unverified runnable selector.
1898
+ runnable: false,
1899
+ efforts: [],
1900
+ defaultEffort: null,
1901
+ required: false
1902
+ },
1903
+ functionCalling: { upstream: "supported", runnable: true },
1904
+ structuredOutput: { upstream: "supported", runnable: true },
1905
+ hostedTools: {
1906
+ webSearch: { upstream: "unknown", runnable: false },
1907
+ xSearch: { upstream: "unknown", runnable: false },
1908
+ codeExecution: { upstream: "unknown", runnable: false },
1909
+ imageGeneration: { upstream: "unknown", runnable: false }
1910
+ },
1911
+ inputModalities: ["text"],
1912
+ inputFileMediaTypes: [],
1913
+ outputModalities: ["text"],
1914
+ transports: {
1915
+ sse: { upstream: "supported", runnable: true },
1916
+ responsesWebSocket: { upstream: "unknown", runnable: false },
1917
+ realtimeAudio: { upstream: "unsupported", runnable: false }
1918
+ },
1919
+ latencyModes: [{ id: "standard", upstream: "unknown", runnable: true }]
1920
+ },
1921
+ contextWindowTokens: 262144,
1922
+ effectiveContextWindowTokens: 235929,
1923
+ autoCompactTokenLimit: 22e4
1924
+ })
1925
+ ];
1926
+ function defaultGatewayCatalogModels() {
1927
+ return [
1928
+ {
1929
+ ...OPENGENI_GATEWAY_MODELS.deepseek,
1930
+ vision: false,
1931
+ inputFileMediaTypes: [],
1932
+ contextWindowTokens: 1e6,
1933
+ effectiveContextWindowTokens: 9e5,
1934
+ autoCompactTokenLimit: 85e4
1935
+ },
1936
+ {
1937
+ ...OPENGENI_GATEWAY_MODELS.kimi,
1938
+ vision: true,
1939
+ inputFileMediaTypes: ["application/pdf"],
1940
+ contextWindowTokens: 1e6,
1941
+ effectiveContextWindowTokens: 9e5,
1942
+ autoCompactTokenLimit: 85e4
1943
+ }
1944
+ ].map((model) => GatewayCatalogModel.parse(model));
1945
+ }
1946
+ function configuredGatewayCatalogModels(settings) {
1947
+ if (settings.resolvedGatewayModelsJson === void 0) {
1948
+ return defaultGatewayCatalogModels();
1949
+ }
1950
+ return z.array(GatewayCatalogModel).parse(JSON.parse(settings.resolvedGatewayModelsJson));
1951
+ }
1952
+ function configuredGatewayUpstreamModelIds(settings) {
1953
+ return configuredGatewayCatalogModels(settings).map((model) => model.upstreamModelId);
1954
+ }
1955
+ function configuredGatewayWorkspaceProductModelIds(settings) {
1956
+ return configuredGatewayCatalogModels(settings).map((model) => model.workspaceProductId);
1957
+ }
1958
+ function configuredGatewayOrganizationProductModelIds(settings) {
1959
+ void settings;
1960
+ return [];
1961
+ }
1962
+ function configuredModelInputIdentities(settings) {
1963
+ return configuredModels(settings).flatMap((model) => [model.id, ...model.aliases]);
1964
+ }
1965
+ function configuredOpenRouterCatalogModels(settings) {
1966
+ if (settings.resolvedOpenRouterModelsJson === void 0) {
1967
+ return [...OPENGENI_OPENROUTER_MODELS];
1968
+ }
1969
+ return z.array(OpenRouterCatalogModel).parse(JSON.parse(settings.resolvedOpenRouterModelsJson));
1970
+ }
1971
+ function configuredOpenRouterUpstreamModelIds(settings) {
1972
+ return configuredOpenRouterCatalogModels(settings).map((model) => model.upstreamModelId);
1973
+ }
1974
+ function workspaceOpenRouterProductId(modelId) {
1975
+ return `${WORKSPACE_OPENROUTER_MODEL_ID_PREFIX}${modelId.startsWith(OPENROUTER_MODEL_ID_PREFIX) ? modelId.slice(OPENROUTER_MODEL_ID_PREFIX.length) : modelId}`;
1976
+ }
1977
+ function configuredOpenRouterWorkspaceProductModelIds(settings) {
1978
+ return configuredOpenRouterCatalogModels(settings).flatMap(
1979
+ (model) => [model.upstreamModelId, ...model.aliases].map(workspaceOpenRouterProductId)
1980
+ );
1981
+ }
1982
+ function configuredOpenRouterOrganizationProductModelIds(settings) {
1983
+ void settings;
1984
+ return [];
1985
+ }
1548
1986
  var defaultModelPricing = {
1549
1987
  "gpt-5.6-sol": {
1550
1988
  default: {
1551
- inputMicrosPerMillionTokens: 5e6,
1552
- cachedInputMicrosPerMillionTokens: 5e5,
1553
- outputMicrosPerMillionTokens: 3e7,
1554
- marginBps: 2500
1989
+ // Promotional OpenAI pricing, guaranteed through at least 2026-11-21.
1990
+ inputMicrosPerMillionTokens: 4e6,
1991
+ cachedInputMicrosPerMillionTokens: 4e5,
1992
+ cacheWriteMicrosPerMillionTokens: 5e6,
1993
+ outputMicrosPerMillionTokens: 2e7,
1994
+ marginBps: 500
1555
1995
  },
1556
1996
  inputTokenTiers: [
1557
1997
  {
1558
1998
  // OpenAI: prompts with >272K input tokens use the long-context rate.
1559
1999
  minimumInputTokens: 272001,
1560
2000
  pricing: {
1561
- inputMicrosPerMillionTokens: 1e7,
1562
- cachedInputMicrosPerMillionTokens: 1e6,
1563
- outputMicrosPerMillionTokens: 45e6,
1564
- marginBps: 2500
2001
+ inputMicrosPerMillionTokens: 8e6,
2002
+ cachedInputMicrosPerMillionTokens: 8e5,
2003
+ cacheWriteMicrosPerMillionTokens: 1e7,
2004
+ outputMicrosPerMillionTokens: 3e7,
2005
+ marginBps: 500
1565
2006
  }
1566
2007
  }
1567
2008
  ]
@@ -1570,8 +2011,9 @@ var defaultModelPricing = {
1570
2011
  default: {
1571
2012
  inputMicrosPerMillionTokens: 2e6,
1572
2013
  cachedInputMicrosPerMillionTokens: 2e5,
2014
+ cacheWriteMicrosPerMillionTokens: 25e5,
1573
2015
  outputMicrosPerMillionTokens: 12e6,
1574
- marginBps: 2500
2016
+ marginBps: 500
1575
2017
  },
1576
2018
  inputTokenTiers: [
1577
2019
  {
@@ -1579,8 +2021,9 @@ var defaultModelPricing = {
1579
2021
  pricing: {
1580
2022
  inputMicrosPerMillionTokens: 4e6,
1581
2023
  cachedInputMicrosPerMillionTokens: 4e5,
2024
+ cacheWriteMicrosPerMillionTokens: 5e6,
1582
2025
  outputMicrosPerMillionTokens: 18e6,
1583
- marginBps: 2500
2026
+ marginBps: 500
1584
2027
  }
1585
2028
  }
1586
2029
  ]
@@ -1589,8 +2032,9 @@ var defaultModelPricing = {
1589
2032
  default: {
1590
2033
  inputMicrosPerMillionTokens: 2e5,
1591
2034
  cachedInputMicrosPerMillionTokens: 2e4,
2035
+ cacheWriteMicrosPerMillionTokens: 25e4,
1592
2036
  outputMicrosPerMillionTokens: 12e5,
1593
- marginBps: 2500
2037
+ marginBps: 500
1594
2038
  },
1595
2039
  inputTokenTiers: [
1596
2040
  {
@@ -1598,8 +2042,9 @@ var defaultModelPricing = {
1598
2042
  pricing: {
1599
2043
  inputMicrosPerMillionTokens: 4e5,
1600
2044
  cachedInputMicrosPerMillionTokens: 4e4,
2045
+ cacheWriteMicrosPerMillionTokens: 5e5,
1601
2046
  outputMicrosPerMillionTokens: 18e5,
1602
- marginBps: 2500
2047
+ marginBps: 500
1603
2048
  }
1604
2049
  }
1605
2050
  ]
@@ -1614,7 +2059,7 @@ var defaultModelPricing = {
1614
2059
  inputMicrosPerMillionTokens: 14e4,
1615
2060
  cachedInputMicrosPerMillionTokens: 28e3,
1616
2061
  outputMicrosPerMillionTokens: 28e4,
1617
- marginBps: 2500
2062
+ marginBps: 500
1618
2063
  }
1619
2064
  },
1620
2065
  [OPENGENI_GATEWAY_MODELS.kimi.productId]: {
@@ -1622,7 +2067,7 @@ var defaultModelPricing = {
1622
2067
  inputMicrosPerMillionTokens: 3e6,
1623
2068
  cachedInputMicrosPerMillionTokens: 3e5,
1624
2069
  outputMicrosPerMillionTokens: 15e6,
1625
- marginBps: 2500
2070
+ marginBps: 500
1626
2071
  }
1627
2072
  },
1628
2073
  // Fireworks AI / GLM 5.2 — the first shipped non-OpenAI registry model. A
@@ -1634,7 +2079,7 @@ var defaultModelPricing = {
1634
2079
  inputMicrosPerMillionTokens: 14e5,
1635
2080
  cachedInputMicrosPerMillionTokens: 14e4,
1636
2081
  outputMicrosPerMillionTokens: 44e5,
1637
- marginBps: 2500
2082
+ marginBps: 500
1638
2083
  }
1639
2084
  }
1640
2085
  };
@@ -1693,11 +2138,14 @@ function objectStorageConfiguredForWorkspaceArchives(settings) {
1693
2138
  }
1694
2139
  }
1695
2140
  }
1696
- function optional(name) {
1697
- const value = process.env[name];
2141
+ function optionalEnvironmentValue(name, source) {
2142
+ const value = source[name];
1698
2143
  return value && value.trim().length > 0 ? value : void 0;
1699
2144
  }
1700
- function getSettings() {
2145
+ function getSettings(source = process.env) {
2146
+ const optional = (name) => optionalEnvironmentValue(name, source);
2147
+ const modelCatalogSource = optional("OPENGENI_MODEL_CATALOG_SOURCE");
2148
+ const modelCostPolicyJson = optional("OPENGENI_MODEL_COST_POLICY_JSON") ?? (modelCatalogSource === "database" ? "{}" : DEFAULT_MODEL_COST_POLICY_JSON);
1701
2149
  const raw = {
1702
2150
  serviceName: optional("OPENGENI_SERVICE_NAME"),
1703
2151
  environment: optional("OPENGENI_ENVIRONMENT"),
@@ -1813,6 +2261,9 @@ function getSettings() {
1813
2261
  goalIdleBackoffMs: optional("OPENGENI_GOAL_IDLE_BACKOFF_MS"),
1814
2262
  goalIdleBackoffMaxMs: optional("OPENGENI_GOAL_IDLE_BACKOFF_MAX_MS"),
1815
2263
  childLifecycleNoticesEnabled: optional("OPENGENI_CHILD_LIFECYCLE_NOTICES_ENABLED"),
2264
+ hostMcpAuthoritySourceAdmissionEnabled: optional(
2265
+ "OPENGENI_HOST_MCP_AUTHORITY_SOURCE_ADMISSION_ENABLED"
2266
+ ),
1816
2267
  slackWorkspaceRoutingEnabled: optional("OPENGENI_SLACK_WORKSPACE_ROUTING_ENABLED"),
1817
2268
  agentMaxModelCallsPerTurn: optional("OPENGENI_AGENT_MAX_MODEL_CALLS_PER_TURN"),
1818
2269
  contextWindowTokens: optional("OPENGENI_CONTEXT_WINDOW_TOKENS"),
@@ -1882,6 +2333,10 @@ function getSettings() {
1882
2333
  voiceInputAzureAdToken: optional("OPENGENI_VOICE_INPUT_AZURE_AD_TOKEN"),
1883
2334
  voiceInputCodexExperimentalEnabled: optional("OPENGENI_VOICE_INPUT_CODEX_EXPERIMENTAL"),
1884
2335
  modelPricingJson: optional("OPENGENI_MODEL_PRICING_JSON"),
2336
+ modelCatalogSource,
2337
+ modelCostPolicyJson,
2338
+ modelNotesJson: optional("OPENGENI_MODEL_NOTES_JSON"),
2339
+ openrouterApiKey: optional("OPENGENI_OPENROUTER_API_KEY"),
1885
2340
  modelProvidersJson: optional("OPENGENI_MODEL_PROVIDERS_JSON"),
1886
2341
  codexSubscriptionEnabled: optional("OPENGENI_CODEX_SUBSCRIPTION_ENABLED"),
1887
2342
  supergrokSubscriptionEnabled: optional("OPENGENI_SUPERGROK_SUBSCRIPTION_ENABLED"),
@@ -2018,6 +2473,7 @@ function getSettings() {
2018
2473
  sandboxIdleGraceMs: optional("OPENGENI_SANDBOX_IDLE_GRACE_MS"),
2019
2474
  sandboxSnapshotIntervalMs: optional("OPENGENI_SANDBOX_SNAPSHOT_INTERVAL_MS"),
2020
2475
  sandboxSnapshotTimeoutMs: optional("OPENGENI_SANDBOX_SNAPSHOT_TIMEOUT_MS"),
2476
+ sandboxDrainSnapshotTimeoutMs: optional("OPENGENI_SANDBOX_DRAIN_SNAPSHOT_TIMEOUT_MS"),
2021
2477
  sandboxRotationLeadMs: optional("OPENGENI_SANDBOX_ROTATION_LEAD_MS"),
2022
2478
  sandboxRotationBatchSize: optional("OPENGENI_SANDBOX_ROTATION_BATCH_SIZE"),
2023
2479
  sandboxLeaseTtlMs: optional("OPENGENI_SANDBOX_LEASE_TTL_MS"),
@@ -2107,7 +2563,7 @@ function getSettings() {
2107
2563
  sandboxRotationLeadMs: raw.sandboxRotationLeadMs === void 0 && parsed.sandboxBackend === "modal" ? Math.min(36e5, Math.floor(parsed.modalTimeoutSeconds * 1e3 / 2)) : parsed.sandboxRotationLeadMs,
2108
2564
  mcpServers: ensureBuiltInMcpServers(parsed)
2109
2565
  };
2110
- validateSettings(settings);
2566
+ validateSettings(settings, source);
2111
2567
  return settings;
2112
2568
  }
2113
2569
  var LOCAL_FIRST_PARTY_DELEGATION_SECRET = "opengeni-local-first-party-delegation-secret-v1";
@@ -2167,8 +2623,13 @@ function sandboxArchiveCaptureTimeoutMs(settings) {
2167
2623
  settings.sandboxSnapshotTimeoutMs + SANDBOX_ARCHIVE_CAPTURE_SETTLEMENT_GRACE_MS
2168
2624
  );
2169
2625
  }
2626
+ function effectiveSandboxDrainSnapshotTimeoutMs(settings) {
2627
+ return settings.sandboxDrainSnapshotTimeoutMs ?? settings.sandboxSnapshotTimeoutMs;
2628
+ }
2170
2629
  function sandboxLifecycleTransitionWaitMs(settings) {
2171
- const captureTimeoutMs = sandboxArchiveCaptureTimeoutMs(settings);
2630
+ const captureTimeoutMs = sandboxArchiveCaptureTimeoutMs({
2631
+ sandboxSnapshotTimeoutMs: effectiveSandboxDrainSnapshotTimeoutMs(settings)
2632
+ });
2172
2633
  return Math.min(
2173
2634
  SANDBOX_LIFECYCLE_TRANSITION_MAX_WAIT_MS,
2174
2635
  settings.sandboxLeaseReaperPeriodMs + captureTimeoutMs + SANDBOX_LIFECYCLE_RETRY_HANDOFF_GRACE_MS
@@ -2422,10 +2883,8 @@ function legacyModelCapabilities(settings, input) {
2422
2883
  latencyModes: [{ id: "standard", upstream: "unknown", runnable: true }]
2423
2884
  });
2424
2885
  }
2425
- function gatewayRequestPolicyForUpstreamModel(upstreamModelId) {
2426
- const model = Object.values(OPENGENI_GATEWAY_MODELS).find(
2427
- (candidate) => candidate.upstreamModelId === upstreamModelId
2428
- );
2886
+ function gatewayRequestPolicyForUpstreamModel(upstreamModelId, models = defaultGatewayCatalogModels()) {
2887
+ const model = models.find((candidate) => candidate.upstreamModelId === upstreamModelId);
2429
2888
  if (!model) {
2430
2889
  return void 0;
2431
2890
  }
@@ -2456,30 +2915,83 @@ function gatewayModelCapabilities(settings, input) {
2456
2915
  latencyModes: [{ id: "standard", upstream: "supported", runnable: true }]
2457
2916
  });
2458
2917
  }
2918
+ function openRouterCustomModelCapabilities(settings) {
2919
+ const legacy = legacyModelCapabilities(settings, {
2920
+ reasoningEffort: false,
2921
+ hostedWebSearch: false
2922
+ });
2923
+ return normalizeCapabilities({
2924
+ ...legacy,
2925
+ functionCalling: { upstream: "supported", runnable: true },
2926
+ inputModalities: ["text"],
2927
+ inputFileMediaTypes: [],
2928
+ transports: {
2929
+ ...legacy.transports,
2930
+ sse: { upstream: "supported", runnable: true }
2931
+ },
2932
+ promptCaching: { upstream: "unsupported", runnable: false, mode: "none" },
2933
+ latencyModes: [{ id: "standard", upstream: "supported", runnable: true }]
2934
+ });
2935
+ }
2459
2936
  function gatewayRegistryProvider(settings, input) {
2460
2937
  const workspace = input.kind === "vercel-gateway-workspace";
2461
- const models = [OPENGENI_GATEWAY_MODELS.deepseek, OPENGENI_GATEWAY_MODELS.kimi].map((model) => {
2462
- const kimi = model === OPENGENI_GATEWAY_MODELS.kimi;
2938
+ const organization = input.kind === "vercel-gateway-organization";
2939
+ const scoped = workspace || organization;
2940
+ const curated = organization ? [] : configuredGatewayCatalogModels(settings);
2941
+ const upstreamIds = new Set(curated.map((model) => model.upstreamModelId));
2942
+ const productIds = new Set(
2943
+ parseModelProvidersJson(settings.modelProvidersJson).filter(
2944
+ (provider) => provider.id !== WORKSPACE_GATEWAY_PROVIDER_ID && provider.id !== ORGANIZATION_GATEWAY_PROVIDER_ID
2945
+ ).flatMap(
2946
+ (provider) => provider.models.flatMap((model) => [model.id, ...model.aliases ?? []])
2947
+ )
2948
+ );
2949
+ const models = curated.map((model) => {
2950
+ const id = workspace ? model.workspaceProductId : organization ? `${ORGANIZATION_GATEWAY_MODEL_ID_PREFIX}${model.upstreamModelId}` : model.productId;
2951
+ productIds.add(id);
2463
2952
  return {
2464
- id: workspace ? model.workspaceProductId : model.productId,
2953
+ id,
2465
2954
  upstreamModelId: model.upstreamModelId,
2466
2955
  label: model.label,
2467
- shortLabel: model.shortLabel,
2956
+ ...model.shortLabel ? { shortLabel: model.shortLabel } : {},
2468
2957
  capabilities: gatewayModelCapabilities(settings, {
2469
2958
  implicitCaching: model.implicitCaching,
2470
- vision: kimi,
2471
- inputFileMediaTypes: kimi ? ["application/pdf"] : []
2959
+ vision: model.vision,
2960
+ inputFileMediaTypes: model.inputFileMediaTypes
2472
2961
  }),
2473
- contextWindowTokens: 1e6,
2474
- effectiveContextWindowTokens: 9e5,
2475
- autoCompactTokenLimit: 85e4,
2476
- toolOutputTruncationTokens: settings.modelToolOutputTruncationTokens
2962
+ contextWindowTokens: model.contextWindowTokens,
2963
+ effectiveContextWindowTokens: model.effectiveContextWindowTokens,
2964
+ autoCompactTokenLimit: model.autoCompactTokenLimit,
2965
+ toolOutputTruncationTokens: settings.modelToolOutputTruncationTokens,
2966
+ ...model.pricing === void 0 ? {} : { pricing: model.pricing }
2477
2967
  };
2478
2968
  });
2969
+ if (scoped) {
2970
+ for (const custom of input.customModels ?? []) {
2971
+ const productId = `${workspace ? WORKSPACE_GATEWAY_MODEL_ID_PREFIX : ORGANIZATION_GATEWAY_MODEL_ID_PREFIX}${custom.upstreamModelId}`;
2972
+ if (upstreamIds.has(custom.upstreamModelId) || productIds.has(productId)) continue;
2973
+ upstreamIds.add(custom.upstreamModelId);
2974
+ productIds.add(productId);
2975
+ models.push({
2976
+ id: productId,
2977
+ upstreamModelId: custom.upstreamModelId,
2978
+ label: custom.label?.trim() || custom.upstreamModelId,
2979
+ capabilities: gatewayModelCapabilities(settings, {
2980
+ implicitCaching: false,
2981
+ vision: false,
2982
+ inputFileMediaTypes: []
2983
+ }),
2984
+ contextWindowTokens: 1e6,
2985
+ effectiveContextWindowTokens: 9e5,
2986
+ autoCompactTokenLimit: 85e4,
2987
+ toolOutputTruncationTokens: settings.modelToolOutputTruncationTokens
2988
+ });
2989
+ }
2990
+ }
2479
2991
  return {
2480
2992
  kind: input.kind,
2481
- id: workspace ? WORKSPACE_GATEWAY_PROVIDER_ID : OPENGENI_GATEWAY_PROVIDER_ID,
2482
- label: workspace ? "Your Gateway" : "OpenGeni",
2993
+ id: workspace ? WORKSPACE_GATEWAY_PROVIDER_ID : organization ? ORGANIZATION_GATEWAY_PROVIDER_ID : OPENGENI_GATEWAY_PROVIDER_ID,
2994
+ label: workspace ? "Your Gateway" : organization ? "Organization Gateway" : "OpenGeni",
2483
2995
  // Responses preserves vision, reasoning items, and provider-native usage.
2484
2996
  // Model-specific compatibility stays at the reviewed request fence rather
2485
2997
  // than downgrading the whole provider wire.
@@ -2490,47 +3002,179 @@ function gatewayRegistryProvider(settings, input) {
2490
3002
  models
2491
3003
  };
2492
3004
  }
3005
+ function openRouterRegistryProvider(settings, input) {
3006
+ const workspace = input.kind === "openrouter-workspace";
3007
+ const organization = input.kind === "openrouter-organization";
3008
+ const scoped = workspace || organization;
3009
+ const curated = organization ? [] : configuredOpenRouterCatalogModels(settings);
3010
+ const upstreamIds = new Set(curated.map((model) => model.upstreamModelId));
3011
+ const productIds = new Set(
3012
+ parseModelProvidersJson(settings.modelProvidersJson).filter(
3013
+ (provider) => provider.id !== WORKSPACE_OPENROUTER_PROVIDER_ID && provider.id !== ORGANIZATION_OPENROUTER_PROVIDER_ID
3014
+ ).flatMap(
3015
+ (provider) => provider.models.flatMap((model) => [model.id, ...model.aliases ?? []])
3016
+ )
3017
+ );
3018
+ const models = curated.map((model) => {
3019
+ const id = workspace ? workspaceOpenRouterProductId(model.upstreamModelId) : organization ? `${ORGANIZATION_OPENROUTER_MODEL_ID_PREFIX}${model.upstreamModelId}` : `${OPENROUTER_MODEL_ID_PREFIX}${model.upstreamModelId}`;
3020
+ const aliases = workspace ? model.aliases.map(workspaceOpenRouterProductId) : organization ? model.aliases.map((alias) => `${ORGANIZATION_OPENROUTER_MODEL_ID_PREFIX}${alias}`) : model.aliases;
3021
+ productIds.add(id);
3022
+ for (const alias of aliases) productIds.add(alias);
3023
+ return {
3024
+ id,
3025
+ upstreamModelId: model.upstreamModelId,
3026
+ aliases,
3027
+ label: model.label,
3028
+ ...model.shortLabel ? { shortLabel: model.shortLabel } : {},
3029
+ capabilities: model.capabilities,
3030
+ ...model.contextWindowTokens === void 0 ? {} : { contextWindowTokens: model.contextWindowTokens },
3031
+ ...model.effectiveContextWindowTokens === void 0 ? {} : { effectiveContextWindowTokens: model.effectiveContextWindowTokens },
3032
+ ...model.autoCompactTokenLimit === void 0 ? {} : { autoCompactTokenLimit: model.autoCompactTokenLimit },
3033
+ toolOutputTruncationTokens: model.toolOutputTruncationTokens ?? settings.modelToolOutputTruncationTokens
3034
+ };
3035
+ });
3036
+ if (scoped) {
3037
+ for (const custom of input.customModels ?? []) {
3038
+ const productId = `${workspace ? WORKSPACE_OPENROUTER_MODEL_ID_PREFIX : ORGANIZATION_OPENROUTER_MODEL_ID_PREFIX}${custom.upstreamModelId}`;
3039
+ if (upstreamIds.has(custom.upstreamModelId) || productIds.has(productId)) continue;
3040
+ upstreamIds.add(custom.upstreamModelId);
3041
+ productIds.add(productId);
3042
+ models.push({
3043
+ id: productId,
3044
+ upstreamModelId: custom.upstreamModelId,
3045
+ aliases: [],
3046
+ label: custom.label?.trim() || custom.upstreamModelId,
3047
+ capabilities: openRouterCustomModelCapabilities(settings),
3048
+ toolOutputTruncationTokens: settings.modelToolOutputTruncationTokens
3049
+ });
3050
+ }
3051
+ }
3052
+ if (models.length === 0) return null;
3053
+ const defaultHeaders = {
3054
+ "x-title": "OpenGeni",
3055
+ ...settings.publicBaseUrl ? { "http-referer": settings.publicBaseUrl } : {}
3056
+ };
3057
+ return {
3058
+ kind: input.kind,
3059
+ id: workspace ? WORKSPACE_OPENROUTER_PROVIDER_ID : organization ? ORGANIZATION_OPENROUTER_PROVIDER_ID : OPENROUTER_PROVIDER_ID,
3060
+ label: workspace ? "Your OpenRouter" : organization ? "Organization OpenRouter" : "OpenRouter",
3061
+ api: "chat",
3062
+ wireProfile: "openai",
3063
+ baseUrl: OPENROUTER_BASE_URL,
3064
+ ...input.apiKey ? { apiKey: input.apiKey } : {},
3065
+ defaultHeaders,
3066
+ publicDefaultHeaderNames: Object.keys(defaultHeaders),
3067
+ models
3068
+ };
3069
+ }
2493
3070
  function configuredRegistryProviders(settings) {
2494
3071
  const providers = parseModelProvidersJson(settings.modelProvidersJson);
2495
- if (!settings.vercelAiGatewayApiKey) {
2496
- return providers;
2497
- }
2498
- if (providers.some((provider) => provider.id === OPENGENI_GATEWAY_PROVIDER_ID)) {
2499
- throw new Error(
2500
- `${OPENGENI_GATEWAY_PROVIDER_ID} is reserved for OPENGENI_VERCEL_AI_GATEWAY_API_KEY`
3072
+ const injected = [...providers];
3073
+ if (settings.vercelAiGatewayApiKey && configuredGatewayCatalogModels(settings).length > 0) {
3074
+ injected.push(
3075
+ gatewayRegistryProvider(settings, {
3076
+ kind: "vercel-gateway-managed",
3077
+ apiKey: settings.vercelAiGatewayApiKey
3078
+ })
2501
3079
  );
2502
3080
  }
2503
- return [
2504
- ...providers,
2505
- gatewayRegistryProvider(settings, {
2506
- kind: "vercel-gateway-managed",
2507
- apiKey: settings.vercelAiGatewayApiKey
2508
- })
2509
- ];
3081
+ const openrouter = settings.openrouterApiKey ? openRouterRegistryProvider(settings, {
3082
+ kind: "openrouter-managed",
3083
+ apiKey: settings.openrouterApiKey
3084
+ }) : null;
3085
+ if (openrouter) injected.push(openrouter);
3086
+ return injected;
2510
3087
  }
2511
- function withWorkspaceGatewayCatalogProvider(settings) {
3088
+ function withWorkspaceGatewayCatalogProvider(settings, customModels = []) {
2512
3089
  const providers = parseModelProvidersJson(settings.modelProvidersJson);
2513
- if (providers.some((provider) => provider.id === WORKSPACE_GATEWAY_PROVIDER_ID)) {
2514
- return settings;
2515
- }
3090
+ const withoutWorkspace = providers.filter(
3091
+ (provider) => provider.id !== WORKSPACE_GATEWAY_PROVIDER_ID
3092
+ );
3093
+ const curatedCount = configuredGatewayCatalogModels(settings).length;
3094
+ if (curatedCount === 0 && customModels.length === 0) return settings;
2516
3095
  return {
2517
3096
  ...settings,
2518
3097
  modelProvidersJson: JSON.stringify([
2519
- ...providers,
2520
- gatewayRegistryProvider(settings, { kind: "vercel-gateway-workspace" })
3098
+ ...withoutWorkspace,
3099
+ gatewayRegistryProvider(settings, {
3100
+ kind: "vercel-gateway-workspace",
3101
+ customModels
3102
+ })
2521
3103
  ])
2522
3104
  };
2523
3105
  }
2524
- function withWorkspaceGatewayCredential(settings, apiKey) {
3106
+ function withWorkspaceGatewayCredential(settings, apiKey, customModels = []) {
2525
3107
  if (!apiKey.trim()) {
2526
3108
  throw new Error("workspace AI Gateway credential is empty");
2527
3109
  }
2528
- const catalogSettings = withWorkspaceGatewayCatalogProvider(settings);
3110
+ const catalogSettings = withWorkspaceGatewayCatalogProvider(settings, customModels);
2529
3111
  const providers = parseModelProvidersJson(catalogSettings.modelProvidersJson).map(
2530
3112
  (provider) => provider.id === WORKSPACE_GATEWAY_PROVIDER_ID ? { ...provider, apiKey } : provider
2531
3113
  );
2532
3114
  return { ...catalogSettings, modelProvidersJson: JSON.stringify(providers) };
2533
3115
  }
3116
+ function withWorkspaceOpenRouterCatalogProvider(settings, customModels = []) {
3117
+ const providers = parseModelProvidersJson(settings.modelProvidersJson);
3118
+ const withoutWorkspace = providers.filter(
3119
+ (provider2) => provider2.id !== WORKSPACE_OPENROUTER_PROVIDER_ID
3120
+ );
3121
+ const provider = openRouterRegistryProvider(settings, {
3122
+ kind: "openrouter-workspace",
3123
+ customModels
3124
+ });
3125
+ if (!provider) return settings;
3126
+ return {
3127
+ ...settings,
3128
+ modelProvidersJson: JSON.stringify([...withoutWorkspace, provider])
3129
+ };
3130
+ }
3131
+ function withWorkspaceOpenRouterCredential(settings, apiKey, customModels = []) {
3132
+ if (!apiKey.trim()) {
3133
+ throw new Error("workspace OpenRouter credential is empty");
3134
+ }
3135
+ const catalogSettings = withWorkspaceOpenRouterCatalogProvider(settings, customModels);
3136
+ const providers = parseModelProvidersJson(catalogSettings.modelProvidersJson).map(
3137
+ (provider) => provider.id === WORKSPACE_OPENROUTER_PROVIDER_ID ? { ...provider, apiKey } : provider
3138
+ );
3139
+ return { ...catalogSettings, modelProvidersJson: JSON.stringify(providers) };
3140
+ }
3141
+ function withOrganizationGatewayCatalogProvider(settings, customModels = []) {
3142
+ if (customModels.length === 0) return settings;
3143
+ const providers = parseModelProvidersJson(settings.modelProvidersJson).filter(
3144
+ (provider2) => provider2.id !== ORGANIZATION_GATEWAY_PROVIDER_ID
3145
+ );
3146
+ const provider = gatewayRegistryProvider(settings, {
3147
+ kind: "vercel-gateway-organization",
3148
+ customModels
3149
+ });
3150
+ return { ...settings, modelProvidersJson: JSON.stringify([...providers, provider]) };
3151
+ }
3152
+ function withOrganizationGatewayCredential(settings, apiKey, customModels = []) {
3153
+ if (!apiKey.trim()) throw new Error("organization AI Gateway credential is empty");
3154
+ const catalog = withOrganizationGatewayCatalogProvider(settings, customModels);
3155
+ const providers = parseModelProvidersJson(catalog.modelProvidersJson).map(
3156
+ (provider) => provider.id === ORGANIZATION_GATEWAY_PROVIDER_ID ? { ...provider, apiKey } : provider
3157
+ );
3158
+ return { ...catalog, modelProvidersJson: JSON.stringify(providers) };
3159
+ }
3160
+ function withOrganizationOpenRouterCatalogProvider(settings, customModels = []) {
3161
+ const providers = parseModelProvidersJson(settings.modelProvidersJson).filter(
3162
+ (provider2) => provider2.id !== ORGANIZATION_OPENROUTER_PROVIDER_ID
3163
+ );
3164
+ const provider = openRouterRegistryProvider(settings, {
3165
+ kind: "openrouter-organization",
3166
+ customModels
3167
+ });
3168
+ return provider ? { ...settings, modelProvidersJson: JSON.stringify([...providers, provider]) } : settings;
3169
+ }
3170
+ function withOrganizationOpenRouterCredential(settings, apiKey, customModels = []) {
3171
+ if (!apiKey.trim()) throw new Error("organization OpenRouter credential is empty");
3172
+ const catalog = withOrganizationOpenRouterCatalogProvider(settings, customModels);
3173
+ const providers = parseModelProvidersJson(catalog.modelProvidersJson).map(
3174
+ (provider) => provider.id === ORGANIZATION_OPENROUTER_PROVIDER_ID ? { ...provider, apiKey } : provider
3175
+ );
3176
+ return { ...catalog, modelProvidersJson: JSON.stringify(providers) };
3177
+ }
2534
3178
  var GPT56_FAST_BILLING_MULTIPLIER_BPS = 2e4;
2535
3179
  function productLabelForModelId(modelId) {
2536
3180
  const slug = modelId.startsWith(CODEX_MODEL_ID_PREFIX) ? modelId.slice(CODEX_MODEL_ID_PREFIX.length) : modelId;
@@ -2643,31 +3287,60 @@ function assertLatencyModeRunnable(settings, modelId, latencyMode) {
2643
3287
  }
2644
3288
  }
2645
3289
  function registryCredentialSource(provider) {
2646
- if (provider.kind === "anonymous") {
2647
- return { kind: "deployment", mechanism: "none" };
2648
- }
2649
- if (provider.kind === "codex-subscription") {
2650
- return { kind: "connected_subscription", provider: "codex" };
2651
- }
2652
- if (provider.kind === "xai-subscription") {
2653
- return { kind: "connected_subscription", provider: "xai" };
2654
- }
2655
- if (provider.kind === "vercel-gateway-workspace") {
2656
- return { kind: "workspace_connection", mechanism: "api_key" };
3290
+ switch (provider.kind) {
3291
+ case "anonymous":
3292
+ return { kind: "deployment", mechanism: "none" };
3293
+ case "codex-subscription":
3294
+ return { kind: "connected_subscription", provider: "codex" };
3295
+ case "xai-subscription":
3296
+ return { kind: "connected_subscription", provider: "xai" };
3297
+ case "vercel-gateway-workspace":
3298
+ case "openrouter-workspace":
3299
+ return { kind: "workspace_connection", mechanism: "api_key" };
3300
+ case "vercel-gateway-organization":
3301
+ case "openrouter-organization":
3302
+ return { kind: "organization_connection", mechanism: "api_key" };
3303
+ case "api-key":
3304
+ case "vercel-gateway-managed":
3305
+ case "openrouter-managed":
3306
+ return { kind: "deployment", mechanism: "api_key" };
3307
+ default: {
3308
+ const _exhaustive = provider.kind;
3309
+ return _exhaustive;
3310
+ }
2657
3311
  }
2658
- return { kind: "deployment", mechanism: "api_key" };
2659
3312
  }
2660
3313
  function registryBilling(provider) {
2661
- if (provider.kind === "anonymous") {
2662
- return { upstreamPayer: "deployment", metering: "external" };
2663
- }
2664
- if (provider.kind === "codex-subscription" || provider.kind === "xai-subscription") {
2665
- return { upstreamPayer: "connected_subscription", metering: "external" };
2666
- }
2667
- if (provider.kind === "vercel-gateway-workspace") {
2668
- return { upstreamPayer: "workspace", metering: "external" };
3314
+ switch (provider.kind) {
3315
+ case "anonymous":
3316
+ case "openrouter-managed":
3317
+ return { upstreamPayer: "deployment", metering: "external" };
3318
+ case "codex-subscription":
3319
+ case "xai-subscription":
3320
+ return { upstreamPayer: "connected_subscription", metering: "external" };
3321
+ case "vercel-gateway-workspace":
3322
+ case "openrouter-workspace":
3323
+ return { upstreamPayer: "workspace", metering: "external" };
3324
+ case "vercel-gateway-organization":
3325
+ case "openrouter-organization":
3326
+ return { upstreamPayer: "organization", metering: "external" };
3327
+ case "api-key":
3328
+ case "vercel-gateway-managed":
3329
+ return { upstreamPayer: "deployment", metering: "opengeni_credits" };
3330
+ default: {
3331
+ const _exhaustive = provider.kind;
3332
+ return _exhaustive;
3333
+ }
2669
3334
  }
2670
- return { upstreamPayer: "deployment", metering: "opengeni_credits" };
3335
+ }
3336
+ function configuredCostForModel(settings, productModelId, credentialSource) {
3337
+ if (credentialSource.kind === "workspace_connection") return "workspace";
3338
+ if (credentialSource.kind === "organization_connection") return "organization";
3339
+ if (credentialSource.kind === "connected_subscription") return "subscription";
3340
+ return parseModelCostPolicyJson(settings.modelCostPolicyJson)[productModelId] ?? "credits";
3341
+ }
3342
+ function modelCostClassForConfiguredModel(_settings, model) {
3343
+ return model.cost;
2671
3344
  }
2672
3345
  function builtinCredentialSource(settings) {
2673
3346
  if (settings.openaiProvider === "azure" && !settings.azureOpenaiApiKey) {
@@ -2726,6 +3399,10 @@ function definitionVersionFor(model, provider, options = {}) {
2726
3399
  billing: model.billing,
2727
3400
  executionLimits: model.executionLimits,
2728
3401
  capabilities: model.capabilities,
3402
+ // Workspace-facing free/credits classification is a separate live
3403
+ // deployment policy. Operators must drain/fence accepted turns before
3404
+ // changing it; it is intentionally not a second executable-definition
3405
+ // freeze inside TurnExecutionPolicyV1.
2729
3406
  ...model.requestPolicy ? { requestPolicy: model.requestPolicy } : {},
2730
3407
  pricing: model.pricing ?? null
2731
3408
  });
@@ -2734,7 +3411,9 @@ function definitionVersionFor(model, provider, options = {}) {
2734
3411
  function legacyImplicitOpenAiDefinitionVersionFor(model, provider) {
2735
3412
  if (provider.wireProfile !== "openai") return null;
2736
3413
  const { definitionVersion: _definitionVersion, ...modelWithoutVersion } = model;
2737
- return definitionVersionFor(modelWithoutVersion, provider, { includeWireProfile: false });
3414
+ return definitionVersionFor(modelWithoutVersion, provider, {
3415
+ includeWireProfile: false
3416
+ });
2738
3417
  }
2739
3418
  function builtinProviderId(settings) {
2740
3419
  return settings.openaiProvider === "azure" ? "azure" : "openai";
@@ -2742,7 +3421,7 @@ function builtinProviderId(settings) {
2742
3421
  function builtinProviderLabel(settings) {
2743
3422
  return settings.openaiProvider === "azure" ? "Azure OpenAI" : "OpenAI";
2744
3423
  }
2745
- function configuredProviders(settings) {
3424
+ function configuredProviders(settings, source = process.env) {
2746
3425
  const credentialSource = builtinCredentialSource(settings);
2747
3426
  const builtin = {
2748
3427
  id: builtinProviderId(settings),
@@ -2771,7 +3450,7 @@ function configuredProviders(settings) {
2771
3450
  wireProfile: provider.wireProfile,
2772
3451
  builtin: false,
2773
3452
  baseUrl: provider.baseUrl,
2774
- apiKey: resolveProviderApiKey(provider),
3453
+ apiKey: resolveProviderApiKey(provider, source),
2775
3454
  defaultQuery: provider.defaultQuery,
2776
3455
  defaultHeaders: provider.defaultHeaders,
2777
3456
  publicDefaultQueryNames: provider.publicDefaultQueryNames,
@@ -2854,8 +3533,14 @@ function withXaiSubscriptionCatalogProvider(settings) {
2854
3533
  { id: "standard", upstream: "supported", runnable: true },
2855
3534
  { id: "fast", upstream: "supported", runnable: true }
2856
3535
  ];
2857
- capabilities.hostedTools.xSearch = { upstream: "supported", runnable: true };
2858
- capabilities.hostedTools.imageGeneration = { upstream: "supported", runnable: true };
3536
+ capabilities.hostedTools.xSearch = {
3537
+ upstream: "supported",
3538
+ runnable: true
3539
+ };
3540
+ capabilities.hostedTools.imageGeneration = {
3541
+ upstream: "supported",
3542
+ runnable: true
3543
+ };
2859
3544
  return {
2860
3545
  id: `${XAI_SUBSCRIPTION_MODEL_ID_PREFIX}${slug}`,
2861
3546
  upstreamModelId: slug,
@@ -2871,7 +3556,10 @@ function withXaiSubscriptionCatalogProvider(settings) {
2871
3556
  };
2872
3557
  })
2873
3558
  };
2874
- return { ...settings, modelProvidersJson: JSON.stringify([...providers, provider]) };
3559
+ return {
3560
+ ...settings,
3561
+ modelProvidersJson: JSON.stringify([...providers, provider])
3562
+ };
2875
3563
  }
2876
3564
  function policyProviderIdForModel(settings, modelId) {
2877
3565
  const canonicalModelId = canonicalizeConfiguredModelId(settings, modelId);
@@ -2884,6 +3572,9 @@ function policyProviderIdForModel(settings, modelId) {
2884
3572
  if (canonicalModelId.startsWith(WORKSPACE_GATEWAY_MODEL_ID_PREFIX)) {
2885
3573
  return WORKSPACE_GATEWAY_PROVIDER_ID;
2886
3574
  }
3575
+ if (canonicalModelId.startsWith(WORKSPACE_OPENROUTER_MODEL_ID_PREFIX)) {
3576
+ return WORKSPACE_OPENROUTER_PROVIDER_ID;
3577
+ }
2887
3578
  const configured = configuredModels(settings).find((model) => model.id === canonicalModelId);
2888
3579
  return configured?.providerId ?? builtinProviderId(settings);
2889
3580
  }
@@ -2896,10 +3587,14 @@ function resolvedExecutionLimits(settings, model) {
2896
3587
  };
2897
3588
  }
2898
3589
  function finalizeConfiguredModel(settings, provider, input) {
2899
- const requestPolicy = provider.kind === "vercel-gateway-managed" || provider.kind === "vercel-gateway-workspace" ? gatewayRequestPolicyForUpstreamModel(input.upstreamModelId) : void 0;
3590
+ const requestPolicy = provider.kind === "vercel-gateway-managed" || provider.kind === "vercel-gateway-workspace" || provider.kind === "vercel-gateway-organization" ? gatewayRequestPolicyForUpstreamModel(
3591
+ input.upstreamModelId,
3592
+ configuredGatewayCatalogModels(settings)
3593
+ ) : void 0;
2900
3594
  const modelWithoutVersion = {
2901
3595
  schemaVersion: 1,
2902
3596
  ...input,
3597
+ cost: configuredCostForModel(settings, input.id, input.credentialSource),
2903
3598
  ...requestPolicy ? { requestPolicy } : {},
2904
3599
  executionLimits: resolvedExecutionLimits(settings, input)
2905
3600
  };
@@ -2939,10 +3634,10 @@ function assertUniqueModelIdentities(models) {
2939
3634
  }
2940
3635
  }
2941
3636
  }
2942
- function configuredModels(settings) {
3637
+ function configuredModels(settings, source = process.env) {
2943
3638
  const builtinId = builtinProviderId(settings);
2944
3639
  const builtinLabel = builtinProviderLabel(settings);
2945
- const providers = configuredProviders(settings);
3640
+ const providers = configuredProviders(settings, source);
2946
3641
  const providerById = new Map(providers.map((provider) => [provider.id, provider]));
2947
3642
  const pricingSchedules = configuredModelPricingSchedules(settings);
2948
3643
  const parsedRegistry = configuredRegistryProviders(settings);
@@ -3031,7 +3726,10 @@ function configuredModels(settings) {
3031
3726
  }
3032
3727
  }
3033
3728
  assertUniqueModelIdentities(out);
3034
- return out;
3729
+ const defaultIndex = out.findIndex(
3730
+ (model) => model.id === settings.openaiModel || model.aliases.includes(settings.openaiModel)
3731
+ );
3732
+ return defaultIndex > 0 ? [out[defaultIndex], ...out.slice(0, defaultIndex), ...out.slice(defaultIndex + 1)] : out;
3035
3733
  }
3036
3734
  function canonicalizeConfiguredModelId(settings, modelId) {
3037
3735
  const models = configuredModels(settings);
@@ -3066,10 +3764,32 @@ function settingsForTurnExecutionPolicy(settings, modelId) {
3066
3764
  return withXaiSubscriptionCatalogProvider(settings);
3067
3765
  }
3068
3766
  if (modelId.startsWith(WORKSPACE_GATEWAY_MODEL_ID_PREFIX)) {
3767
+ if (resolveModelProvider(settings, modelId)) {
3768
+ return settings;
3769
+ }
3069
3770
  return withWorkspaceGatewayCatalogProvider(settings);
3070
3771
  }
3772
+ if (modelId.startsWith(WORKSPACE_OPENROUTER_MODEL_ID_PREFIX)) {
3773
+ if (resolveModelProvider(settings, modelId)) {
3774
+ return settings;
3775
+ }
3776
+ return withWorkspaceOpenRouterCatalogProvider(settings);
3777
+ }
3778
+ if (modelId.startsWith(ORGANIZATION_GATEWAY_MODEL_ID_PREFIX)) {
3779
+ return resolveModelProvider(settings, modelId) ? settings : withOrganizationGatewayCatalogProvider(settings);
3780
+ }
3781
+ if (modelId.startsWith(ORGANIZATION_OPENROUTER_MODEL_ID_PREFIX)) {
3782
+ return resolveModelProvider(settings, modelId) ? settings : withOrganizationOpenRouterCatalogProvider(settings);
3783
+ }
3071
3784
  return settings;
3072
3785
  }
3786
+ function resolveModelProviderForTurn(settings, modelId) {
3787
+ const catalogSettings = settingsForTurnExecutionPolicy(settings, modelId);
3788
+ return resolveModelProvider(
3789
+ catalogSettings,
3790
+ canonicalizeConfiguredModelId(catalogSettings, modelId)
3791
+ );
3792
+ }
3073
3793
  function resolveTurnExecutionPolicyV1(settings, input) {
3074
3794
  const catalogSettings = settingsForTurnExecutionPolicy(settings, input.modelId);
3075
3795
  const productModelId = canonicalizeConfiguredModelId(catalogSettings, input.modelId);
@@ -3147,7 +3867,7 @@ function configuredModelPricingSchedules(settings) {
3147
3867
  const configured = Object.fromEntries(
3148
3868
  Object.entries(parseModelPricingJson(settings.modelPricingJson)).map(([model, pricing]) => [
3149
3869
  model,
3150
- { default: pricing }
3870
+ normalizeModelPricingSchedule(pricing)
3151
3871
  ])
3152
3872
  );
3153
3873
  return {
@@ -3260,12 +3980,7 @@ function calculateModelUsageCostBreakdown(settings, model, usage, options) {
3260
3980
  function calculateGatewayReportedCostMicros(settings, model, inferenceCostUsd, options) {
3261
3981
  return calculateGatewayReportedCostBreakdown(settings, model, inferenceCostUsd, options).creditCostMicros;
3262
3982
  }
3263
- function calculateGatewayReportedCostBreakdown(settings, model, inferenceCostUsd, options) {
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));
3983
+ function parseGatewayReportedCostDecimal(inferenceCostUsd) {
3269
3984
  const match = /^(0|[1-9]\d*)(?:\.(\d{1,18}))?$/.exec(inferenceCostUsd);
3270
3985
  if (!match) {
3271
3986
  throw new Error("Invalid AI Gateway inference cost");
@@ -3274,16 +3989,35 @@ function calculateGatewayReportedCostBreakdown(settings, model, inferenceCostUsd
3274
3989
  const decimalDigits = BigInt(`${match[1]}${fraction}`);
3275
3990
  const decimalScale = 10n ** BigInt(fraction.length);
3276
3991
  const providerNumerator = decimalDigits * 1000000n;
3277
- const providerMicros = (providerNumerator + decimalScale - 1n) / decimalScale;
3992
+ const providerCostMicros = (providerNumerator + decimalScale - 1n) / decimalScale;
3993
+ if (providerCostMicros > BigInt(Number.MAX_SAFE_INTEGER)) {
3994
+ throw new Error("AI Gateway inference cost exceeds the supported billing range");
3995
+ }
3996
+ return {
3997
+ providerNumerator,
3998
+ decimalScale,
3999
+ providerCostMicros: Number(providerCostMicros)
4000
+ };
4001
+ }
4002
+ function calculateGatewayReportedProviderCostMicros(inferenceCostUsd) {
4003
+ return parseGatewayReportedCostDecimal(inferenceCostUsd).providerCostMicros;
4004
+ }
4005
+ function calculateGatewayReportedCostBreakdown(settings, model, inferenceCostUsd, options) {
4006
+ const schedule = configuredModelPricingSchedules(settings)[model];
4007
+ if (!schedule) {
4008
+ throw new Error(`Missing model pricing for ${model}`);
4009
+ }
4010
+ const pricing = selectModelPricing(schedule, positiveInt(options?.inputTokens));
4011
+ const { providerNumerator, decimalScale, providerCostMicros } = parseGatewayReportedCostDecimal(inferenceCostUsd);
3278
4012
  const marginBps = BigInt(1e4 + (pricing.marginBps ?? 0));
3279
4013
  const numerator = providerNumerator * marginBps;
3280
4014
  const denominator = decimalScale * 10000n;
3281
4015
  const creditMicros = (numerator + denominator - 1n) / denominator;
3282
- if (providerMicros > BigInt(Number.MAX_SAFE_INTEGER) || creditMicros > BigInt(Number.MAX_SAFE_INTEGER)) {
4016
+ if (creditMicros > BigInt(Number.MAX_SAFE_INTEGER)) {
3283
4017
  throw new Error("AI Gateway inference cost exceeds the supported billing range");
3284
4018
  }
3285
4019
  return {
3286
- providerCostMicros: Number(providerMicros),
4020
+ providerCostMicros,
3287
4021
  creditCostMicros: Number(creditMicros)
3288
4022
  };
3289
4023
  }
@@ -3555,7 +4289,7 @@ function parseModelPricingJson(raw) {
3555
4289
  if (!model.trim()) {
3556
4290
  throw new Error("OPENGENI_MODEL_PRICING_JSON contains an empty model name");
3557
4291
  }
3558
- out[model] = ModelPricingSchema.parse(value);
4292
+ out[model] = z.union([ModelPricingSchema, ModelPricingScheduleSchema]).parse(value);
3559
4293
  }
3560
4294
  return out;
3561
4295
  }
@@ -3739,9 +4473,14 @@ function calculateEntryCostMicros(pricing, entry) {
3739
4473
  const inputTokens = positiveInt(entry.inputTokens);
3740
4474
  const outputTokens = positiveInt(entry.outputTokens);
3741
4475
  const cachedTokens = Math.min(inputTokens, cachedInputTokens(entry));
3742
- const uncachedInputTokens = Math.max(0, inputTokens - cachedTokens);
4476
+ const cacheWriteTokens = Math.min(
4477
+ Math.max(0, inputTokens - cachedTokens),
4478
+ cacheWriteInputTokens(entry)
4479
+ );
4480
+ const uncachedInputTokens = Math.max(0, inputTokens - cachedTokens - cacheWriteTokens);
3743
4481
  const cachedInputRate = pricing.cachedInputMicrosPerMillionTokens ?? pricing.inputMicrosPerMillionTokens;
3744
- return Math.ceil(uncachedInputTokens * pricing.inputMicrosPerMillionTokens / 1e6) + Math.ceil(cachedTokens * cachedInputRate / 1e6) + Math.ceil(outputTokens * pricing.outputMicrosPerMillionTokens / 1e6);
4482
+ const cacheWriteRate = pricing.cacheWriteMicrosPerMillionTokens ?? pricing.inputMicrosPerMillionTokens;
4483
+ return Math.ceil(uncachedInputTokens * pricing.inputMicrosPerMillionTokens / 1e6) + Math.ceil(cachedTokens * cachedInputRate / 1e6) + Math.ceil(cacheWriteTokens * cacheWriteRate / 1e6) + Math.ceil(outputTokens * pricing.outputMicrosPerMillionTokens / 1e6);
3745
4484
  }
3746
4485
  function cachedInputTokens(entry) {
3747
4486
  const details = Array.isArray(entry.inputTokensDetails) ? entry.inputTokensDetails : entry.inputTokensDetails ? [entry.inputTokensDetails] : [];
@@ -3751,6 +4490,14 @@ function cachedInputTokens(entry) {
3751
4490
  }
3752
4491
  return total;
3753
4492
  }
4493
+ function cacheWriteInputTokens(entry) {
4494
+ const details = Array.isArray(entry.inputTokensDetails) ? entry.inputTokensDetails : entry.inputTokensDetails ? [entry.inputTokensDetails] : [];
4495
+ let total = 0;
4496
+ for (const detail of details) {
4497
+ total += positiveInt(detail.cache_write_tokens ?? detail.cacheWriteTokens);
4498
+ }
4499
+ return total;
4500
+ }
3754
4501
  function positiveInt(value) {
3755
4502
  return typeof value === "number" && Number.isFinite(value) && value > 0 ? Math.floor(value) : 0;
3756
4503
  }
@@ -3863,7 +4610,7 @@ function isDigestPinnedModalDesktopImage(settings) {
3863
4610
  if (settings.modalImageId) return true;
3864
4611
  return typeof settings.modalImageRef === "string" && MODAL_DESKTOP_IMAGE_DIGEST_REF.test(settings.modalImageRef);
3865
4612
  }
3866
- function validateSettings(settings) {
4613
+ function validateSettings(settings, source = process.env) {
3867
4614
  temporalConnectionOptions(settings);
3868
4615
  if (settings.goalIdleBackoffMs.some((delayMs) => delayMs > settings.goalIdleBackoffMaxMs)) {
3869
4616
  throw new Error(
@@ -4132,15 +4879,6 @@ function validateSettings(settings) {
4132
4879
  if (settings.productAccessMode !== "managed" && settings.billingMode === "stripe") {
4133
4880
  throw new Error("OPENGENI_BILLING_MODE=stripe requires OPENGENI_PRODUCT_ACCESS_MODE=managed");
4134
4881
  }
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
4882
  if (settings.usageLimitsMode === "static") {
4145
4883
  const limits = configuredStaticUsageLimits(settings);
4146
4884
  if (Object.keys(limits).length === 0) {
@@ -4274,6 +5012,11 @@ function validateSettings(settings) {
4274
5012
  throw new Error(`OPENGENI_MCP_SERVERS contains duplicate id ${server.id}`);
4275
5013
  }
4276
5014
  serverIds.add(server.id);
5015
+ if (server.connectionRef?.authoritySource === "host" && !settings.hostMcpAuthoritySourceAdmissionEnabled) {
5016
+ throw new Error(
5017
+ "OPENGENI_MCP_SERVERS host-owned connection refs require OPENGENI_HOST_MCP_AUTHORITY_SOURCE_ADMISSION_ENABLED=true after the whole API/worker fleet is upgraded"
5018
+ );
5019
+ }
4277
5020
  }
4278
5021
  {
4279
5022
  const reaperPeriod = settings.sandboxLeaseReaperPeriodMs;
@@ -4289,11 +5032,35 @@ function validateSettings(settings) {
4289
5032
  `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
5033
  );
4291
5034
  }
5035
+ if (settings.sandboxDrainSnapshotTimeoutMs !== void 0) {
5036
+ const drainCaptureTimeoutMs2 = sandboxArchiveCaptureTimeoutMs({
5037
+ sandboxSnapshotTimeoutMs: effectiveSandboxDrainSnapshotTimeoutMs(settings)
5038
+ });
5039
+ const requiredTransitionWaitMs = reaperPeriod + drainCaptureTimeoutMs2 + SANDBOX_LIFECYCLE_RETRY_HANDOFF_GRACE_MS;
5040
+ if (requiredTransitionWaitMs > SANDBOX_LIFECYCLE_TRANSITION_MAX_WAIT_MS) {
5041
+ throw new Error(
5042
+ `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.`
5043
+ );
5044
+ }
5045
+ }
5046
+ const rotationLeadMs = settings.sandboxRotationLeadMs;
5047
+ const ordinaryCaptureTimeoutMs = sandboxArchiveCaptureTimeoutMs(settings);
5048
+ const drainCaptureTimeoutMs = sandboxArchiveCaptureTimeoutMs({
5049
+ sandboxSnapshotTimeoutMs: effectiveSandboxDrainSnapshotTimeoutMs(settings)
5050
+ });
5051
+ const providerDeadlineCaptureTimeoutMs = Math.max(
5052
+ ordinaryCaptureTimeoutMs,
5053
+ drainCaptureTimeoutMs
5054
+ );
5055
+ if (!(rotationLeadMs > providerDeadlineCaptureTimeoutMs + reaperPeriod)) {
5056
+ throw new Error(
5057
+ `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.`
5058
+ );
5059
+ }
4292
5060
  if (settings.sandboxBackend === "modal") {
4293
5061
  const idleGraceMs = settings.sandboxIdleGraceMs;
4294
5062
  const lifecycle = effectiveSandboxLifecycle(settings, "modal");
4295
5063
  const providerLifetimeMs = lifecycle.hardLifetimeMs;
4296
- const rotationLeadMs = lifecycle.rotationLeadMs;
4297
5064
  const idleTimeoutMs = lifecycle.providerIdleTimeoutMs;
4298
5065
  if (!(idleTimeoutMs <= providerLifetimeMs)) {
4299
5066
  throw new Error(
@@ -4305,12 +5072,6 @@ function validateSettings(settings) {
4305
5072
  `OPENGENI_SANDBOX_ROTATION_LEAD_MS (${rotationLeadMs}) must be strictly less than OPENGENI_MODAL_TIMEOUT_SECONDS*1000 (${providerLifetimeMs}).`
4306
5073
  );
4307
5074
  }
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
5075
  if (!(viewerTtl < idleTimeoutMs)) {
4315
5076
  throw new Error(
4316
5077
  `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 +5101,29 @@ function validateSettings(settings) {
4340
5101
  "[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
5102
  );
4342
5103
  }
5104
+ if (settings.modelCatalogSource === "code") {
5105
+ validateModelCatalogSettings(settings, source);
5106
+ } else {
5107
+ parseModelCostPolicyJson(settings.modelCostPolicyJson);
5108
+ }
5109
+ }
5110
+ function validateModelCatalogSettings(settings, source = process.env) {
5111
+ const costPolicy = parseModelCostPolicyJson(settings.modelCostPolicyJson);
5112
+ const notes = parseModelNotesJson(settings.modelNotesJson);
4343
5113
  const registryProviders = parseModelProvidersJson(settings.modelProvidersJson);
4344
5114
  const builtinId = builtinProviderId(settings);
4345
5115
  const providerIds = /* @__PURE__ */ new Set();
4346
5116
  for (const provider of registryProviders) {
4347
- if (provider.kind === "vercel-gateway-managed" || provider.kind === "vercel-gateway-workspace" || provider.kind === "xai-subscription") {
5117
+ 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
5118
  throw new Error(
4349
5119
  `OPENGENI_MODEL_PROVIDERS_JSON provider kind ${provider.kind} is reserved for a reviewed OpenGeni credential broker`
4350
5120
  );
4351
5121
  }
5122
+ if (RESERVED_MODEL_PROVIDER_IDS.has(provider.id)) {
5123
+ throw new Error(
5124
+ `OPENGENI_MODEL_PROVIDERS_JSON provider id ${provider.id} is reserved for a reviewed OpenGeni provider`
5125
+ );
5126
+ }
4352
5127
  if (provider.id === builtinId) {
4353
5128
  throw new Error(
4354
5129
  `OPENGENI_MODEL_PROVIDERS_JSON provider id ${provider.id} collides with the built-in provider id`
@@ -4360,13 +5135,66 @@ function validateSettings(settings) {
4360
5135
  );
4361
5136
  }
4362
5137
  providerIds.add(provider.id);
4363
- if (provider.kind !== "codex-subscription" && provider.kind !== "anonymous" && !resolveProviderApiKey(provider)) {
5138
+ if (provider.kind !== "codex-subscription" && provider.kind !== "anonymous" && !resolveProviderApiKey(provider, source)) {
4364
5139
  throw new Error(
4365
5140
  `OPENGENI_MODEL_PROVIDERS_JSON provider ${provider.id} requires a resolvable API key (set apiKey or apiKeyEnv)`
4366
5141
  );
4367
5142
  }
4368
5143
  }
4369
- configuredModels(settings);
5144
+ const models = configuredModels(settings, source);
5145
+ const defaultCatalogSettings = settingsForTurnExecutionPolicy(settings, settings.openaiModel);
5146
+ const defaultCatalogModels = defaultCatalogSettings === settings ? models : configuredModels(defaultCatalogSettings, source);
5147
+ if (models.length === 0 && defaultCatalogModels.length === 0) {
5148
+ throw new Error("The resolved model catalog contains no executable models");
5149
+ }
5150
+ const defaultModelId = canonicalizeConfiguredModelId(
5151
+ defaultCatalogSettings,
5152
+ settings.openaiModel
5153
+ );
5154
+ if (!defaultCatalogModels.some((model) => model.id === defaultModelId)) {
5155
+ throw new Error(
5156
+ `The default model ${settings.openaiModel} is not executable in the resolved model catalog`
5157
+ );
5158
+ }
5159
+ const deploymentProductIds = new Set(
5160
+ models.filter((model) => model.credentialSource.kind === "deployment").map((model) => model.id)
5161
+ );
5162
+ const noteProductIds = new Set(models.map((model) => model.id));
5163
+ for (const model of configuredGatewayCatalogModels(settings)) {
5164
+ deploymentProductIds.add(model.productId);
5165
+ noteProductIds.add(model.productId);
5166
+ noteProductIds.add(model.workspaceProductId);
5167
+ }
5168
+ for (const model of configuredOpenRouterCatalogModels(settings)) {
5169
+ const productId = `${OPENROUTER_MODEL_ID_PREFIX}${model.upstreamModelId}`;
5170
+ deploymentProductIds.add(productId);
5171
+ noteProductIds.add(productId);
5172
+ noteProductIds.add(`${WORKSPACE_OPENROUTER_MODEL_ID_PREFIX}${model.upstreamModelId}`);
5173
+ }
5174
+ if (settings.modelCatalogSource === "code") {
5175
+ for (const productId of Object.keys(costPolicy)) {
5176
+ if (!deploymentProductIds.has(productId)) {
5177
+ throw new Error(
5178
+ `OPENGENI_MODEL_COST_POLICY_JSON references unknown deployment model ${productId}`
5179
+ );
5180
+ }
5181
+ }
5182
+ }
5183
+ for (const productId of Object.keys(notes)) {
5184
+ if (!noteProductIds.has(productId)) {
5185
+ throw new Error(`OPENGENI_MODEL_NOTES_JSON references unknown catalog model ${productId}`);
5186
+ }
5187
+ }
5188
+ if (settings.billingMode === "stripe" || settings.usageLimitsMode === "managed") {
5189
+ const pricing = configuredModelPricing(settings);
5190
+ const missing = models.filter((model) => model.cost === "credits" && !pricing[model.id]).map((model) => model.id);
5191
+ if (missing.length > 0) {
5192
+ throw new Error(
5193
+ `Missing model pricing for managed billing model(s): ${missing.join(", ")}. Set OPENGENI_MODEL_PRICING_JSON.`
5194
+ );
5195
+ }
5196
+ }
5197
+ return models;
4370
5198
  }
4371
5199
  function resolveStreamTokenSecret(settings) {
4372
5200
  const explicit = settings.streamTokenSecret?.trim();
@@ -4456,19 +5284,34 @@ export {
4456
5284
  CODEX_REALTIME_MODEL_ID,
4457
5285
  CapabilityStateV1Schema,
4458
5286
  CapabilitySupportV1,
5287
+ ConfiguredModelCostClass,
4459
5288
  DEFAULT_AGENT_INSTRUCTIONS,
4460
5289
  DEFAULT_GOAL_IDLE_BACKOFF_MAX_MS,
4461
5290
  DEFAULT_GOAL_IDLE_BACKOFF_MS,
5291
+ DEFAULT_MODEL_COST_POLICY_JSON,
5292
+ DEFAULT_OPENROUTER_MODEL_ID,
4462
5293
  GOOGLE_DRIVE_PROVIDER_REQUEST_TIMEOUT_MAX_MS,
4463
5294
  GOOGLE_DRIVE_PROVIDER_RETRY_DELAY_MAX_MS,
5295
+ GatewayCatalogModel,
4464
5296
  IntegrationOAuthClientConfigSchema,
4465
5297
  McpServerConnectionRefSchema,
4466
5298
  ModelCapabilitiesV1Schema,
5299
+ ModelCatalogDocument,
5300
+ ModelCostClass,
4467
5301
  ModelProviderApi,
4468
5302
  ModelProviderWireProfile,
4469
5303
  OPENGENI_GATEWAY_MODELS,
4470
5304
  OPENGENI_GATEWAY_PROVIDER_ID,
5305
+ OPENGENI_OPENROUTER_MODELS,
4471
5306
  OPENGENI_REALTIME_MODEL_ID_PREFIX,
5307
+ OPENROUTER_BASE_URL,
5308
+ OPENROUTER_MODEL_ID_PREFIX,
5309
+ OPENROUTER_PROVIDER_ID,
5310
+ ORGANIZATION_GATEWAY_MODEL_ID_PREFIX,
5311
+ ORGANIZATION_GATEWAY_PROVIDER_ID,
5312
+ ORGANIZATION_OPENROUTER_MODEL_ID_PREFIX,
5313
+ ORGANIZATION_OPENROUTER_PROVIDER_ID,
5314
+ OpenRouterCatalogModel,
4472
5315
  RegistryProviderKind,
4473
5316
  SANDBOX_ARCHIVE_CAPTURE_MAX_TIMEOUT_MS,
4474
5317
  SANDBOX_ARCHIVE_CAPTURE_SETTLEMENT_GRACE_MS,
@@ -4484,14 +5327,20 @@ export {
4484
5327
  VERCEL_AI_GATEWAY_CONNECTION_ROLE,
4485
5328
  WORKSPACE_GATEWAY_MODEL_ID_PREFIX,
4486
5329
  WORKSPACE_GATEWAY_PROVIDER_ID,
5330
+ WORKSPACE_OPENROUTER_CONNECTION_DOMAIN,
5331
+ WORKSPACE_OPENROUTER_CONNECTION_ROLE,
5332
+ WORKSPACE_OPENROUTER_MODEL_ID_PREFIX,
5333
+ WORKSPACE_OPENROUTER_PROVIDER_ID,
4487
5334
  WORKSPACE_REALTIME_MODEL_ID_PREFIX,
4488
5335
  XAI_SUBSCRIPTION_MODEL_ID_PREFIX2 as XAI_SUBSCRIPTION_MODEL_ID_PREFIX,
4489
5336
  allowedFirstPartyMcpToolsForSession,
4490
5337
  applyGitAuthPointerEnvironment,
5338
+ applyModelCatalogDocument,
4491
5339
  assertTurnExecutionPolicyMatchesConfigV1,
4492
5340
  builtinProviderId,
4493
5341
  calculateGatewayReportedCostBreakdown,
4494
5342
  calculateGatewayReportedCostMicros,
5343
+ calculateGatewayReportedProviderCostMicros,
4495
5344
  calculateModelUsageCostBreakdown,
4496
5345
  calculateModelUsageCostMicros,
4497
5346
  calculateVideoGenerationCreditCostMicros,
@@ -4503,16 +5352,25 @@ export {
4503
5352
  configuredAllowedModels,
4504
5353
  configuredAllowedReasoningEfforts,
4505
5354
  configuredEntitlements,
5355
+ configuredGatewayOrganizationProductModelIds,
5356
+ configuredGatewayUpstreamModelIds,
5357
+ configuredGatewayWorkspaceProductModelIds,
4506
5358
  configuredGoogleDriveSyncLimits,
5359
+ configuredModelInputIdentities,
5360
+ configuredModelNotes,
4507
5361
  configuredModelPricing,
4508
5362
  configuredModelPricingSchedules,
4509
5363
  configuredModels,
5364
+ configuredOpenRouterOrganizationProductModelIds,
5365
+ configuredOpenRouterUpstreamModelIds,
5366
+ configuredOpenRouterWorkspaceProductModelIds,
4510
5367
  configuredProviders,
4511
5368
  configuredStaticUsageLimits,
4512
5369
  contextInputBudgetTokens,
4513
5370
  dbSearchPath,
4514
5371
  defaultModelPricing,
4515
5372
  effectiveModalIdleTimeoutSeconds,
5373
+ effectiveSandboxDrainSnapshotTimeoutMs,
4516
5374
  effectiveSandboxLifecycle,
4517
5375
  environmentsEncryptionKeyBytes,
4518
5376
  firstPartyMcpBaseUrl,
@@ -4527,9 +5385,13 @@ export {
4527
5385
  hasGitHubRepositorySelection,
4528
5386
  isDirectOpenAiApiBaseUrl,
4529
5387
  isUsableVoiceInputSecret,
5388
+ modelCostClassForConfiguredModel,
4530
5389
  parseExposedPorts,
4531
5390
  parseIntegrationsOauthClientsJson,
4532
5391
  parseMcpServers,
5392
+ parseModelCatalogDocument,
5393
+ parseModelCostPolicyJson,
5394
+ parseModelNotesJson,
4533
5395
  parseModelPricingJson,
4534
5396
  parseModelProvidersJson,
4535
5397
  parseSandboxWarmRateJson,
@@ -4546,6 +5408,7 @@ export {
4546
5408
  resolveFirstPartyDelegationSecret,
4547
5409
  resolveFirstPartyMcpToolPolicy,
4548
5410
  resolveModelProvider,
5411
+ resolveModelProviderForTurn,
4549
5412
  resolveNatsCalloutConfig,
4550
5413
  resolveNatsControlPlaneAuth,
4551
5414
  resolveProviderApiKey,
@@ -4569,10 +5432,17 @@ export {
4569
5432
  startupRetryOptions,
4570
5433
  streamTokenDegraded,
4571
5434
  temporalConnectionOptions,
5435
+ validateModelCatalogSettings,
4572
5436
  voiceInputDeploymentConfigured,
4573
5437
  withCodexCatalogProvider,
5438
+ withOrganizationGatewayCatalogProvider,
5439
+ withOrganizationGatewayCredential,
5440
+ withOrganizationOpenRouterCatalogProvider,
5441
+ withOrganizationOpenRouterCredential,
4574
5442
  withWorkspaceGatewayCatalogProvider,
4575
5443
  withWorkspaceGatewayCredential,
5444
+ withWorkspaceOpenRouterCatalogProvider,
5445
+ withWorkspaceOpenRouterCredential,
4576
5446
  withXaiSubscriptionCatalogProvider
4577
5447
  };
4578
5448
  //# sourceMappingURL=index.js.map