@opengeni/core 4.0.0 → 4.0.1-canary.35916963870001

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
@@ -1378,8 +1378,257 @@ async function knowledgeContextForAccess(deps, access, permission) {
1378
1378
 
1379
1379
  // src/domain/knowledge-search.ts
1380
1380
  import { KnowledgeEntryListRequest } from "@opengeni/contracts";
1381
- import { listKnowledgeEntries } from "@opengeni/db";
1382
- async function searchKnowledgeEntries(db, context, input, embedder) {
1381
+ import {
1382
+ applyCreditDebitAfterUse,
1383
+ getBillingBalance as getBillingBalance2,
1384
+ listKnowledgeEntries,
1385
+ recordUsageEvent as recordUsageEvent2,
1386
+ sumUsageQuantity as sumUsageQuantity2,
1387
+ withKnowledgeQueryAccountLock
1388
+ } from "@opengeni/db";
1389
+
1390
+ // src/billing/limits.ts
1391
+ import {
1392
+ configuredStaticUsageLimits,
1393
+ resolveModelProviderForTurn
1394
+ } from "@opengeni/config";
1395
+ import {
1396
+ countActiveApiKeysForWorkspace,
1397
+ countActiveOrganizationApiKeysForAccount,
1398
+ countScheduledTasksForWorkspace,
1399
+ countWorkspacesForAccount,
1400
+ getBillingBalance,
1401
+ isCodexBilledTurn,
1402
+ recordUsageEvent,
1403
+ sumUsageQuantity
1404
+ } from "@opengeni/db";
1405
+ import { HTTPException as HTTPException4 } from "hono/http-exception";
1406
+ function paidDocumentEmbedding(settings) {
1407
+ return settings.documentEmbeddingBillingMode === "credits" && settings.documentEmbeddingProvider === "openai";
1408
+ }
1409
+ function documentEmbeddingCostMicros(settings, inputBytes) {
1410
+ if (!Number.isSafeInteger(inputBytes) || inputBytes < 0)
1411
+ throw new Error("invalid embedding bytes");
1412
+ const amount = (BigInt(inputBytes) * BigInt(settings.documentEmbeddingRateMicrosPerMillionBytes) + 999999n) / 1000000n;
1413
+ if (amount > BigInt(Number.MAX_SAFE_INTEGER))
1414
+ throw new Error("embedding cost exceeds safe integer");
1415
+ return Number(amount);
1416
+ }
1417
+ function modelFundingForAdmission(settings, model, codexBilled) {
1418
+ const resolvedModel = model ? resolveModelProviderForTurn(settings, model)?.model : null;
1419
+ const codexSubscriptionModel = resolvedModel?.credentialSource.kind === "connected_subscription" && resolvedModel.credentialSource.provider === "codex";
1420
+ return {
1421
+ // A Codex namespace/definition never bypasses credits by itself: the live
1422
+ // workspace credential predicate above remains authoritative. SuperGrok's
1423
+ // static overlay is likewise secret-free; its worker/provider admission
1424
+ // owns live account selection before any upstream request can occur.
1425
+ fundedWithoutCredits: codexBilled || resolvedModel != null && !codexSubscriptionModel && resolvedModel.cost !== "credits",
1426
+ countsTowardTokenCap: !codexBilled && resolvedModel != null && resolvedModel.billing.upstreamPayer === "deployment"
1427
+ };
1428
+ }
1429
+ async function requireLimit(deps, input) {
1430
+ const decision = await checkLimit(deps, input);
1431
+ if (decision.allowed) {
1432
+ return;
1433
+ }
1434
+ throw new HTTPException4(decision.code === "insufficient_credits" ? 402 : 429, {
1435
+ message: decision.message
1436
+ });
1437
+ }
1438
+ async function checkLimit(deps, input) {
1439
+ const codexBilled = input.workspaceId ? await isCodexBilledTurn({
1440
+ db: deps.db,
1441
+ settings: deps.settings,
1442
+ workspaceId: input.workspaceId,
1443
+ model: input.model
1444
+ }) : false;
1445
+ const { fundedWithoutCredits, countsTowardTokenCap } = modelFundingForAdmission(
1446
+ deps.settings,
1447
+ input.model,
1448
+ codexBilled
1449
+ );
1450
+ const creditDecision = await checkCreditBalance(deps, input, fundedWithoutCredits);
1451
+ if (!creditDecision.allowed) {
1452
+ return creditDecision;
1453
+ }
1454
+ if (deps.settings.usageLimitsMode !== "static" && deps.settings.usageLimitsMode !== "managed") {
1455
+ return { allowed: true };
1456
+ }
1457
+ return await checkStaticCaps(deps, input, {
1458
+ fundedWithoutCredits,
1459
+ countsTowardTokenCap
1460
+ });
1461
+ }
1462
+ async function checkCreditBalance(deps, input, externallyBilled) {
1463
+ if (externallyBilled) {
1464
+ return { allowed: true };
1465
+ }
1466
+ if (!usesCreditLimits(deps) || !isCostlyAction(input.action)) {
1467
+ return { allowed: true };
1468
+ }
1469
+ const balance = await getBillingBalance(deps.db, input.accountId);
1470
+ if (balance.balanceMicros > 0) {
1471
+ return { allowed: true };
1472
+ }
1473
+ return { allowed: false, code: "insufficient_credits", message: "insufficient OpenGeni credits" };
1474
+ }
1475
+ async function checkStaticCaps(deps, input, funding) {
1476
+ const limits = configuredStaticUsageLimits(deps.settings);
1477
+ if (limits.maxMonthlyCostMicrosPerAccount && isCostlyAction(input.action) && !funding.fundedWithoutCredits) {
1478
+ const used = await sumUsageQuantity(deps.db, {
1479
+ accountId: input.accountId,
1480
+ eventType: "model.cost",
1481
+ since: startOfUtcMonth()
1482
+ });
1483
+ if (used >= limits.maxMonthlyCostMicrosPerAccount) {
1484
+ return blocked(
1485
+ "max_monthly_cost_micros_per_account",
1486
+ `monthly model cost limit reached (${limits.maxMonthlyCostMicrosPerAccount} micros)`
1487
+ );
1488
+ }
1489
+ }
1490
+ switch (input.action) {
1491
+ case "workspace:create": {
1492
+ if (!limits.maxWorkspacesPerAccount) {
1493
+ return { allowed: true };
1494
+ }
1495
+ const count = await countWorkspacesForAccount(deps.db, input.accountId);
1496
+ return count < limits.maxWorkspacesPerAccount ? { allowed: true } : blocked(
1497
+ "max_workspaces_per_account",
1498
+ `workspace limit reached (${limits.maxWorkspacesPerAccount})`
1499
+ );
1500
+ }
1501
+ case "api_key:create": {
1502
+ if (!limits.maxApiKeysPerWorkspace) {
1503
+ return { allowed: true };
1504
+ }
1505
+ const count = input.workspaceId ? await countActiveApiKeysForWorkspace(deps.db, input.workspaceId) : await countActiveOrganizationApiKeysForAccount(deps.db, input.accountId);
1506
+ return count < limits.maxApiKeysPerWorkspace ? { allowed: true } : blocked(
1507
+ "max_api_keys_per_workspace",
1508
+ `API key limit reached (${limits.maxApiKeysPerWorkspace})`
1509
+ );
1510
+ }
1511
+ case "schedule:create": {
1512
+ if (!limits.maxSchedulesPerWorkspace || !input.workspaceId) {
1513
+ return { allowed: true };
1514
+ }
1515
+ const count = await countScheduledTasksForWorkspace(deps.db, input.workspaceId);
1516
+ return count < limits.maxSchedulesPerWorkspace ? { allowed: true } : blocked(
1517
+ "max_schedules_per_workspace",
1518
+ `scheduled task limit reached (${limits.maxSchedulesPerWorkspace})`
1519
+ );
1520
+ }
1521
+ case "file:upload": {
1522
+ if (!limits.maxFileUploadBytes || !input.quantity) {
1523
+ return { allowed: true };
1524
+ }
1525
+ return input.quantity <= limits.maxFileUploadBytes ? { allowed: true } : blocked(
1526
+ "max_file_upload_bytes",
1527
+ `file upload exceeds static limit of ${limits.maxFileUploadBytes} bytes`
1528
+ );
1529
+ }
1530
+ case "agent_run:create": {
1531
+ if (!limits.maxMonthlyAgentRunsPerWorkspace || !input.workspaceId) {
1532
+ return { allowed: true };
1533
+ }
1534
+ const used = await sumUsageQuantity(deps.db, {
1535
+ workspaceId: input.workspaceId,
1536
+ eventType: "agent_run.created",
1537
+ since: startOfUtcMonth()
1538
+ });
1539
+ const requested = input.quantity ?? 0;
1540
+ return used + requested <= limits.maxMonthlyAgentRunsPerWorkspace ? { allowed: true } : blocked(
1541
+ "max_monthly_agent_runs_per_workspace",
1542
+ `monthly agent run limit reached (${limits.maxMonthlyAgentRunsPerWorkspace})`
1543
+ );
1544
+ }
1545
+ case "tokens:consume": {
1546
+ if (!funding.countsTowardTokenCap || !limits.maxMonthlyTokensPerWorkspace || !input.workspaceId) {
1547
+ return { allowed: true };
1548
+ }
1549
+ const used = await sumUsageQuantity(deps.db, {
1550
+ workspaceId: input.workspaceId,
1551
+ eventType: "model.tokens",
1552
+ since: startOfUtcMonth()
1553
+ });
1554
+ const requested = input.quantity ?? 0;
1555
+ return used + requested <= limits.maxMonthlyTokensPerWorkspace ? { allowed: true } : blocked(
1556
+ "max_monthly_tokens_per_workspace",
1557
+ `monthly token limit reached (${limits.maxMonthlyTokensPerWorkspace})`
1558
+ );
1559
+ }
1560
+ case "document:index": {
1561
+ if (!limits.maxDocumentIndexedChunksPerWorkspace || !input.workspaceId) {
1562
+ return { allowed: true };
1563
+ }
1564
+ const used = await sumUsageQuantity(deps.db, {
1565
+ workspaceId: input.workspaceId,
1566
+ eventType: "document.indexed",
1567
+ since: startOfUtcMonth()
1568
+ });
1569
+ const requested = input.quantity ?? 0;
1570
+ return used + requested <= limits.maxDocumentIndexedChunksPerWorkspace ? { allowed: true } : blocked(
1571
+ "max_document_indexed_chunks_per_workspace",
1572
+ `monthly document indexing limit reached (${limits.maxDocumentIndexedChunksPerWorkspace} chunks)`
1573
+ );
1574
+ }
1575
+ }
1576
+ }
1577
+ async function recordWorkspaceUsage(deps, input) {
1578
+ await recordUsageEvent(deps.db, {
1579
+ accountId: input.accountId,
1580
+ workspaceId: input.workspaceId,
1581
+ subjectId: input.subjectId ?? null,
1582
+ eventType: input.eventType,
1583
+ quantity: input.quantity,
1584
+ unit: input.unit,
1585
+ sourceResourceType: input.sourceResourceType,
1586
+ sourceResourceId: input.sourceResourceId,
1587
+ sessionId: input.sessionId ?? null,
1588
+ turnId: input.turnId ?? null,
1589
+ turnAttemptId: input.turnAttemptId ?? null,
1590
+ initiator: input.initiator ?? (input.subjectId ? { kind: "subject", subjectId: input.subjectId } : null),
1591
+ ...input.initiatorContext ? { initiatorContext: input.initiatorContext } : {},
1592
+ origin: input.origin ?? null,
1593
+ idempotencyKey: input.idempotencyKey
1594
+ });
1595
+ }
1596
+ function usesCreditLimits(deps) {
1597
+ return deps.settings.billingMode === "stripe" || deps.settings.usageLimitsMode === "managed";
1598
+ }
1599
+ function isCostlyAction(action) {
1600
+ return action === "agent_run:create" || action === "tokens:consume";
1601
+ }
1602
+ function blocked(code, message) {
1603
+ return { allowed: false, code, message };
1604
+ }
1605
+ function startOfUtcMonth() {
1606
+ const now = /* @__PURE__ */ new Date();
1607
+ return new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), 1));
1608
+ }
1609
+
1610
+ // src/domain/knowledge-search.ts
1611
+ var MAX_PAID_QUERY_BYTES = 4096;
1612
+ var MAX_PAID_QUERY_MICROS = 1e3;
1613
+ var MAX_PAID_QUERY_BYTES_PER_MINUTE = 64 * 1024;
1614
+ var MAX_PAID_QUERY_BYTES_PER_MONTH = 8 * 1024 * 1024;
1615
+ var MAX_PAID_QUERY_MICROS_PER_MINUTE = 1e4;
1616
+ var MAX_PAID_QUERY_MICROS_PER_MONTH = 1e6;
1617
+ var KnowledgeVectorFundingError = class extends Error {
1618
+ code = "knowledge_vector_funding_required";
1619
+ constructor() {
1620
+ super("Knowledge vector search needs OpenGeni credits; keyword search remains available.");
1621
+ this.name = "KnowledgeVectorFundingError";
1622
+ }
1623
+ };
1624
+ var KnowledgeVectorQueryRejectedError = class extends Error {
1625
+ constructor(code, message) {
1626
+ super(message);
1627
+ this.code = code;
1628
+ this.name = "KnowledgeVectorQueryRejectedError";
1629
+ }
1630
+ };
1631
+ async function searchKnowledgeEntries(db, context, input, embedder, settings) {
1383
1632
  const request = KnowledgeEntryListRequest.parse(input);
1384
1633
  if (!request.query || request.mode === "keyword") {
1385
1634
  return {
@@ -1390,25 +1639,119 @@ async function searchKnowledgeEntries(db, context, input, embedder) {
1390
1639
  const lexicalQuery = /^[\p{L}\p{N}\s]+$/u.test(request.query) && !/\bOR\b/i.test(request.query) ? [...new Set(request.query.trim().split(/\s+/u))].map((term) => `"${term}"`).join(" OR ") : request.query;
1391
1640
  const lexicalRequest = KnowledgeEntryListRequest.safeParse({ ...request, query: lexicalQuery });
1392
1641
  const retrievalRequest = request.mode === "hybrid" && lexicalRequest.success ? lexicalRequest.data : request;
1393
- let embedding;
1394
- try {
1395
- const provider = embedder();
1396
- const values = await provider.embedQuery(request.query);
1397
- if (values.length !== provider.dimensions || values.some((value) => !Number.isFinite(value)) || !values.some((value) => value !== 0)) {
1398
- throw new Error("Knowledge query embedding is unavailable");
1399
- }
1400
- embedding = { model: provider.model, values };
1401
- } catch (error) {
1642
+ const keywordFallback = async (queryDb, error, fallbackReason) => {
1402
1643
  if (request.mode === "vector") throw error;
1403
1644
  return {
1404
- ...await listKnowledgeEntries(db, context, { ...retrievalRequest, mode: "keyword" }),
1405
- searchMode: "keyword"
1645
+ ...await listKnowledgeEntries(queryDb, context, { ...retrievalRequest, mode: "keyword" }),
1646
+ searchMode: "keyword",
1647
+ fallbackReason
1406
1648
  };
1407
- }
1408
- return {
1409
- ...await listKnowledgeEntries(db, context, retrievalRequest, embedding),
1410
- searchMode: request.mode
1411
1649
  };
1650
+ const bytes = Buffer.byteLength(request.query, "utf8");
1651
+ const paidSettings = settings && paidDocumentEmbedding(settings) ? settings : void 0;
1652
+ if (paidSettings && request.cursor)
1653
+ throw new KnowledgeVectorQueryRejectedError(
1654
+ "pagination_unavailable",
1655
+ "Paid semantic Knowledge pagination is unavailable; use keyword mode"
1656
+ );
1657
+ const cost = paidSettings ? documentEmbeddingCostMicros(paidSettings, bytes) : 0;
1658
+ if (paidSettings && (bytes > MAX_PAID_QUERY_BYTES || cost > MAX_PAID_QUERY_MICROS))
1659
+ return keywordFallback(
1660
+ db,
1661
+ new KnowledgeVectorQueryRejectedError(
1662
+ "query_limit",
1663
+ "Paid Knowledge query exceeds the per-request limit"
1664
+ ),
1665
+ "query_limit"
1666
+ );
1667
+ const retrieveThenSettle = async (queryDb) => {
1668
+ let embedding;
1669
+ try {
1670
+ const provider = embedder();
1671
+ const values = await provider.embedQuery(request.query);
1672
+ if (values.length !== provider.dimensions || values.some((value) => !Number.isFinite(value)) || !values.some((value) => value !== 0))
1673
+ throw new Error("Knowledge query embedding is unavailable");
1674
+ embedding = { model: provider.model, values };
1675
+ } catch (error) {
1676
+ return keywordFallback(queryDb, error, "provider_unavailable");
1677
+ }
1678
+ const found = await listKnowledgeEntries(queryDb, context, retrievalRequest, embedding);
1679
+ if (settings) {
1680
+ const usageId = crypto.randomUUID();
1681
+ await recordUsageEvent2(queryDb, {
1682
+ accountId: context.accountId,
1683
+ workspaceId: context.workspaceId,
1684
+ eventType: "document.query_embedding_bytes",
1685
+ quantity: bytes,
1686
+ unit: "byte",
1687
+ sourceResourceType: "knowledge_query",
1688
+ sourceResourceId: usageId,
1689
+ idempotencyKey: `knowledge.query_bytes:${usageId}`
1690
+ });
1691
+ if (paidSettings && cost > 0)
1692
+ await recordUsageEvent2(queryDb, {
1693
+ accountId: context.accountId,
1694
+ workspaceId: context.workspaceId,
1695
+ eventType: "document.query_embedding_cost",
1696
+ quantity: cost,
1697
+ unit: "micro_usd",
1698
+ sourceResourceType: "knowledge_query",
1699
+ sourceResourceId: usageId,
1700
+ idempotencyKey: `knowledge.query_cost:${usageId}`
1701
+ });
1702
+ if (paidSettings && cost > 0)
1703
+ await applyCreditDebitAfterUse(queryDb, {
1704
+ accountId: context.accountId,
1705
+ workspaceId: context.workspaceId,
1706
+ type: "document_embedding_debit",
1707
+ amountMicros: cost,
1708
+ sourceType: "knowledge_query",
1709
+ sourceId: usageId,
1710
+ idempotencyKey: `knowledge.query_embedding:${usageId}`,
1711
+ metadata: { model: embedding.model, bytes }
1712
+ });
1713
+ }
1714
+ return { ...found, searchMode: request.mode };
1715
+ };
1716
+ if (!paidSettings) return retrieveThenSettle(db);
1717
+ return withKnowledgeQueryAccountLock(
1718
+ db,
1719
+ context.accountId,
1720
+ context.workspaceId,
1721
+ async (lockedDb) => {
1722
+ const balance = await getBillingBalance2(lockedDb, context.accountId);
1723
+ if (balance.balanceMicros <= 0)
1724
+ return keywordFallback(lockedDb, new KnowledgeVectorFundingError(), "awaiting_funding");
1725
+ const now = /* @__PURE__ */ new Date();
1726
+ const minuteBytes = await sumUsageQuantity2(lockedDb, {
1727
+ accountId: context.accountId,
1728
+ eventType: "document.query_embedding_bytes",
1729
+ since: new Date(now.getTime() - 6e4)
1730
+ });
1731
+ const monthBytes = await sumUsageQuantity2(lockedDb, {
1732
+ accountId: context.accountId,
1733
+ eventType: "document.query_embedding_bytes",
1734
+ since: new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), 1))
1735
+ });
1736
+ const minuteMicros = await sumUsageQuantity2(lockedDb, {
1737
+ accountId: context.accountId,
1738
+ eventType: "document.query_embedding_cost",
1739
+ since: new Date(now.getTime() - 6e4)
1740
+ });
1741
+ const monthMicros = await sumUsageQuantity2(lockedDb, {
1742
+ accountId: context.accountId,
1743
+ eventType: "document.query_embedding_cost",
1744
+ since: new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), 1))
1745
+ });
1746
+ if (minuteBytes + bytes > MAX_PAID_QUERY_BYTES_PER_MINUTE || monthBytes + bytes > MAX_PAID_QUERY_BYTES_PER_MONTH || minuteMicros + cost > MAX_PAID_QUERY_MICROS_PER_MINUTE || monthMicros + cost > MAX_PAID_QUERY_MICROS_PER_MONTH)
1747
+ return keywordFallback(
1748
+ lockedDb,
1749
+ new KnowledgeVectorQueryRejectedError("quota", "Paid Knowledge query rate limit reached"),
1750
+ "quota"
1751
+ );
1752
+ return retrieveThenSettle(lockedDb);
1753
+ }
1754
+ );
1412
1755
  }
1413
1756
 
1414
1757
  // src/workflow-wake-contract.ts
@@ -1501,6 +1844,7 @@ import {
1501
1844
  configuredGatewayWorkspaceProductModelIds,
1502
1845
  configuredGatewayOrganizationProductModelIds,
1503
1846
  configuredModels,
1847
+ isModelAvailableForNewSelection,
1504
1848
  configuredModelNotes,
1505
1849
  configuredOpenRouterWorkspaceProductModelIds,
1506
1850
  configuredOpenRouterOrganizationProductModelIds,
@@ -1944,7 +2288,7 @@ function resolveWorkspaceModelSelection(input) {
1944
2288
  const requestedNowMs = input.now?.getTime();
1945
2289
  const nowMs = typeof requestedNowMs === "number" && Number.isFinite(requestedNowMs) ? requestedNowMs : Date.now();
1946
2290
  const maxAgeMs = typeof input.credentialReadinessMaxAgeMs === "number" && Number.isFinite(input.credentialReadinessMaxAgeMs) && input.credentialReadinessMaxAgeMs >= 0 ? input.credentialReadinessMaxAgeMs : MODEL_CREDENTIAL_READINESS_OBSERVATION_MAX_AGE_MS;
1947
- return configuredModels(catalogSettings).map((model) => {
2291
+ return configuredModels(catalogSettings).filter((model) => isModelAvailableForNewSelection(catalogSettings, model.id)).map((model) => {
1948
2292
  const provider = providers.get(model.providerId);
1949
2293
  const policyAllowed = evaluateWorkspaceModelPolicy(input.policy, {
1950
2294
  providerId: model.providerId,
@@ -2462,6 +2806,21 @@ function managedSessionGroupBackend(deploymentBackend, sessionBackend) {
2462
2806
  const backend = sessionBackend === "selfhosted" ? deploymentBackend : sessionBackend;
2463
2807
  return backend === "none" || backend === "selfhosted" ? null : backend;
2464
2808
  }
2809
+ var SESSION_GROUP_MACHINE_NAMES = {
2810
+ local: "this computer",
2811
+ docker: "Docker",
2812
+ modal: "Modal",
2813
+ daytona: "Daytona",
2814
+ runloop: "Runloop",
2815
+ e2b: "E2B",
2816
+ blaxel: "Blaxel",
2817
+ cloudflare: "Cloudflare",
2818
+ vercel: "Vercel",
2819
+ opensandbox: "OpenSandbox"
2820
+ };
2821
+ function sessionGroupMachinePresentation(backend) {
2822
+ return { name: SESSION_GROUP_MACHINE_NAMES[backend], kind: backend };
2823
+ }
2465
2824
  function managedSessionGroupOs(sessionBackend, sessionOs) {
2466
2825
  return sessionBackend === "selfhosted" ? "linux" : sessionOs;
2467
2826
  }
@@ -2671,10 +3030,11 @@ async function listFleet(services, ctx) {
2671
3030
  groupLease && (groupLease.recovery.restore.status === "degraded" || groupLease.recovery.restore.status === "unrecoverable" || groupLease.recovery.workspace.status === "degraded" || groupLease.recovery.workspace.status === "unrecoverable")
2672
3031
  );
2673
3032
  const groupOperationAvailability = groupOnline ? "ready" : groupRecoveryUnavailable ? "unavailable" : groupRecovering ? "recovering" : "wakeable";
3033
+ const presentation = sessionGroupMachinePresentation(groupBackend);
2674
3034
  entries.push({
2675
3035
  id: ctx.sessionGroupId,
2676
- kind: groupBackend === "opensandbox" ? "opensandbox" : "modal",
2677
- name: "session sandbox",
3036
+ kind: presentation.kind,
3037
+ name: presentation.name,
2678
3038
  liveness: groupOnline ? "online" : groupRecovering ? "reconnecting" : "offline",
2679
3039
  active: groupActive,
2680
3040
  isSessionGroup: true,
@@ -3255,7 +3615,7 @@ async function provisionSandbox(services, ctx, input) {
3255
3615
  }
3256
3616
 
3257
3617
  // src/application/external-workspace-members.ts
3258
- import { HTTPException as HTTPException4 } from "hono/http-exception";
3618
+ import { HTTPException as HTTPException5 } from "hono/http-exception";
3259
3619
  import {
3260
3620
  AddExternalWorkspaceMemberRequest,
3261
3621
  ExternalIdentityReference,
@@ -3291,12 +3651,12 @@ async function addExternalWorkspaceMemberForRequest(c, deps, workspaceId, input)
3291
3651
  const context = await requireAccessContext(c, deps);
3292
3652
  const authority = accountScopedApiKeyWorkspaceAuthority(context);
3293
3653
  if (!authority)
3294
- throw new HTTPException4(403, {
3654
+ throw new HTTPException5(403, {
3295
3655
  message: "external onboarding requires an organization service key"
3296
3656
  });
3297
3657
  const grant = await requireFreshAccessGrant(c, deps, workspaceId, "members:manage");
3298
3658
  if (grant.accountId !== authority.accountId || payload.permissions.some((permission) => !hasPermission(grant.permissions, permission))) {
3299
- throw new HTTPException4(403, { message: "membership exceeds key authority" });
3659
+ throw new HTTPException5(403, { message: "membership exceeds key authority" });
3300
3660
  }
3301
3661
  if (payload.operationId) {
3302
3662
  try {
@@ -3322,11 +3682,11 @@ async function addExternalWorkspaceMemberForRequest(c, deps, workspaceId, input)
3322
3682
  "members:manage"
3323
3683
  );
3324
3684
  if (live.accountId !== grant.accountId || live.subjectId !== grant.subjectId || payload.permissions.some((permission) => !hasPermission(live.permissions, permission))) {
3325
- throw new HTTPException4(403, { message: "membership authority changed" });
3685
+ throw new HTTPException5(403, { message: "membership authority changed" });
3326
3686
  }
3327
3687
  const workspace = await requireWorkspace2(tx, workspaceId);
3328
3688
  if (workspace.kind !== "shared" || workspace.accountId !== authority.accountId)
3329
- throw new HTTPException4(403, {
3689
+ throw new HTTPException5(403, {
3330
3690
  message: "external onboarding requires a shared organization workspace"
3331
3691
  });
3332
3692
  const identity = await ensureExternalIdentity2(tx, {
@@ -3340,7 +3700,7 @@ async function addExternalWorkspaceMemberForRequest(c, deps, workspaceId, input)
3340
3700
  const permissions = [...new Set(payload.permissions)];
3341
3701
  if (existing) {
3342
3702
  if (existing.permissions.length !== permissions.length || existing.permissions.some((permission) => !permissions.includes(permission))) {
3343
- throw new HTTPException4(409, {
3703
+ throw new HTTPException5(409, {
3344
3704
  message: "existing membership differs; onboarding does not overwrite permissions"
3345
3705
  });
3346
3706
  }
@@ -3359,7 +3719,7 @@ async function addExternalWorkspaceMemberForRequest(c, deps, workspaceId, input)
3359
3719
  function rethrowExternalWorkspaceOperation(error) {
3360
3720
  const status = organizationMembershipHttpStatus(nestedPostgresSqlState2(error));
3361
3721
  if (status)
3362
- throw new HTTPException4(status, {
3722
+ throw new HTTPException5(status, {
3363
3723
  message: status === 409 ? "External membership operation changed or was cancelled" : "External membership operation is not available"
3364
3724
  });
3365
3725
  throw error;
@@ -3368,7 +3728,7 @@ async function externalService(c, deps, organizationId) {
3368
3728
  const context = await requireAccessContext(c, deps);
3369
3729
  const authority = accountScopedApiKeyWorkspaceAuthority(context);
3370
3730
  if (!authority || authority.accountId !== organizationId || !hasPermission(authority.permissions, "members:manage")) {
3371
- throw new HTTPException4(403, {
3731
+ throw new HTTPException5(403, {
3372
3732
  message: "External membership operation requires an organization service key"
3373
3733
  });
3374
3734
  }
@@ -3378,7 +3738,7 @@ async function lookupExternalIdentityForRequest(c, deps, organizationId, input)
3378
3738
  const service = await externalService(c, deps, organizationId);
3379
3739
  const identity = ExternalIdentityReference.safeParse(input);
3380
3740
  if (!identity.success)
3381
- throw new HTTPException4(422, { message: "Invalid external identity reference" });
3741
+ throw new HTTPException5(422, { message: "Invalid external identity reference" });
3382
3742
  try {
3383
3743
  return await lookupExternalIdentity(deps.db, service, identity.data);
3384
3744
  } catch (error) {
@@ -3389,7 +3749,7 @@ async function cancelExternalWorkspaceMemberGrantForRequest(c, deps, organizatio
3389
3749
  const service = await externalService(c, deps, organizationId);
3390
3750
  const request = CancelExternalWorkspaceMemberGrantRequest.safeParse(input);
3391
3751
  if (!request.success)
3392
- throw new HTTPException4(422, { message: "Invalid external grant cancellation" });
3752
+ throw new HTTPException5(422, { message: "Invalid external grant cancellation" });
3393
3753
  try {
3394
3754
  return await cancelExternalWorkspaceMemberGrant(
3395
3755
  deps.db,
@@ -3402,7 +3762,7 @@ async function cancelExternalWorkspaceMemberGrantForRequest(c, deps, organizatio
3402
3762
  }
3403
3763
 
3404
3764
  // src/application/external-identity-lifecycle.ts
3405
- import { HTTPException as HTTPException5 } from "hono/http-exception";
3765
+ import { HTTPException as HTTPException6 } from "hono/http-exception";
3406
3766
  import { UpdateExternalIdentityMembershipRequest } from "@opengeni/contracts/external-identities";
3407
3767
  import { updateOrganizationMember } from "@opengeni/db";
3408
3768
  async function updateExternalIdentityMembershipForRequest(context, deps, organizationId, membershipId, input) {
@@ -3412,13 +3772,13 @@ async function updateExternalIdentityMembershipForRequest(context, deps, organiz
3412
3772
  (grant) => grant.accountId === organizationId && grant.subjectId === access.subjectId
3413
3773
  );
3414
3774
  if (!service || service.accountId !== organizationId || !account?.permissions.includes("account:admin")) {
3415
- throw new HTTPException5(403, {
3775
+ throw new HTTPException6(403, {
3416
3776
  message: "external identity administration requires an organization service key"
3417
3777
  });
3418
3778
  }
3419
3779
  const parsed = UpdateExternalIdentityMembershipRequest.safeParse(input);
3420
3780
  if (!parsed.success)
3421
- throw new HTTPException5(422, { message: "invalid external identity transition" });
3781
+ throw new HTTPException6(422, { message: "invalid external identity transition" });
3422
3782
  return updateOrganizationMember(deps.db, {
3423
3783
  organizationId,
3424
3784
  membershipId,
@@ -3440,7 +3800,7 @@ import {
3440
3800
  nestedPostgresSqlState as nestedPostgresSqlState3,
3441
3801
  withWorkspaceSubjectRls as withWorkspaceSubjectRls3
3442
3802
  } from "@opengeni/db";
3443
- import { HTTPException as HTTPException6 } from "hono/http-exception";
3803
+ import { HTTPException as HTTPException7 } from "hono/http-exception";
3444
3804
  function externalContinuationCommitAuthorizer(authorization) {
3445
3805
  const continuation = authorization ? externalActorContinuationForAuthorization(authorization) : null;
3446
3806
  if (!continuation || !authorization) return void 0;
@@ -3455,7 +3815,7 @@ function externalContinuationCommitAuthorizer(authorization) {
3455
3815
  await requireExternalContinuationAuthority(tx, continuation, scope, permissions);
3456
3816
  } catch (error) {
3457
3817
  const denied2 = nestedPostgresSqlState3(error) === "42501" || error instanceof Error && error.message === "External continuation authority unavailable";
3458
- throw new HTTPException6(denied2 ? 403 : 503, {
3818
+ throw new HTTPException7(denied2 ? 403 : 503, {
3459
3819
  message: denied2 ? "external authority changed" : "external authority is unavailable",
3460
3820
  cause: error
3461
3821
  });
@@ -3520,12 +3880,12 @@ import {
3520
3880
  variableSetVariableNameReservation
3521
3881
  } from "@opengeni/contracts";
3522
3882
  import { getVariableSet, recordAuditEvent } from "@opengeni/db";
3523
- import { HTTPException as HTTPException7 } from "hono/http-exception";
3883
+ import { HTTPException as HTTPException8 } from "hono/http-exception";
3524
3884
  var MAX_ENVIRONMENTS_PER_WORKSPACE = 25;
3525
3885
  var MAX_VARIABLES_PER_ENVIRONMENT = 100;
3526
3886
  function assertAllowedVariableSetVariableName(name) {
3527
3887
  if (variableSetVariableNameReservation(name)) {
3528
- throw new HTTPException7(422, {
3888
+ throw new HTTPException8(422, {
3529
3889
  message: `reserved variable set variable name / reserved environment variable name: ${name}`
3530
3890
  });
3531
3891
  }
@@ -3534,7 +3894,7 @@ var assertAllowedEnvironmentVariableName = assertAllowedVariableSetVariableName;
3534
3894
  function requireVariableSetEncryption(settings) {
3535
3895
  const key = environmentsEncryptionKeyBytes(settings);
3536
3896
  if (!key) {
3537
- throw new HTTPException7(503, {
3897
+ throw new HTTPException8(503, {
3538
3898
  message: "variable sets require OPENGENI_ENVIRONMENTS_ENCRYPTION_KEY"
3539
3899
  });
3540
3900
  }
@@ -3552,7 +3912,7 @@ async function requireVariableSetForApi(db, grant, variableSetId) {
3552
3912
  variableSetId
3553
3913
  );
3554
3914
  if (!variableSet) {
3555
- throw new HTTPException7(404, { message: "variableSet not found" });
3915
+ throw new HTTPException8(404, { message: "variableSet not found" });
3556
3916
  }
3557
3917
  return variableSet;
3558
3918
  }
@@ -3566,7 +3926,7 @@ async function validateVariableSetAttachment(deps, grant, workspaceId, variableS
3566
3926
  variableSetId
3567
3927
  );
3568
3928
  if (!variableSet) {
3569
- throw new HTTPException7(422, { message: "unknown variableSetId" });
3929
+ throw new HTTPException8(422, { message: "unknown variableSetId" });
3570
3930
  }
3571
3931
  return variableSet;
3572
3932
  }
@@ -3666,6 +4026,7 @@ function sessionCreationMetadata(metadata) {
3666
4026
  import {
3667
4027
  canonicalizeConfiguredModelId,
3668
4028
  configuredAllowedModels,
4029
+ withCodexCatalogProvider as withCodexCatalogProvider2,
3669
4030
  ORGANIZATION_GATEWAY_MODEL_ID_PREFIX as ORGANIZATION_GATEWAY_MODEL_ID_PREFIX2,
3670
4031
  ORGANIZATION_OPENROUTER_MODEL_ID_PREFIX as ORGANIZATION_OPENROUTER_MODEL_ID_PREFIX2,
3671
4032
  resolveFirstPartyMcpToolPolicy,
@@ -3691,7 +4052,7 @@ import {
3691
4052
  ServiceTurnInitiatorContext,
3692
4053
  evaluateWorkspaceModelPolicy as evaluateWorkspaceModelPolicy2,
3693
4054
  normalizeAutomaticSessionTitle,
3694
- resolveWorkspaceSessionToolDefaults,
4055
+ resolveWorkspaceSessionToolDefaults as resolveWorkspaceSessionToolDefaults2,
3695
4056
  metadataWithTurnExecutionPolicyV1,
3696
4057
  readTurnExecutionPolicyV1,
3697
4058
  stableJson as stableJson3,
@@ -3726,7 +4087,7 @@ import {
3726
4087
  getSessionTurnPersonalConnectionDelegations as getSessionTurnPersonalConnectionDelegations2,
3727
4088
  getSessionTurnXaiProviderAccountAuthoritySnapshot,
3728
4089
  getWorkspaceModelPolicy,
3729
- requireWorkspace as requireWorkspace3,
4090
+ requireWorkspace as requireWorkspace4,
3730
4091
  initializeSessionStartAtomically,
3731
4092
  listSessionTurns,
3732
4093
  listSessionMcpServersForChildInheritance,
@@ -3757,11 +4118,11 @@ import {
3757
4118
  import { HTTPException as HTTPException15 } from "hono/http-exception";
3758
4119
 
3759
4120
  // src/domain/external-creation-attribution.ts
3760
- import { HTTPException as HTTPException8 } from "hono/http-exception";
4121
+ import { HTTPException as HTTPException9 } from "hono/http-exception";
3761
4122
  var EXTERNAL_CREATION_ATTRIBUTION_KEY = "opengeniExternalCreationAttribution";
3762
4123
  function externalCreationMetadata(metadata, authorization, grant) {
3763
4124
  if (metadata && Object.hasOwn(metadata, EXTERNAL_CREATION_ATTRIBUTION_KEY)) {
3764
- throw new HTTPException8(422, {
4125
+ throw new HTTPException9(422, {
3765
4126
  message: `${EXTERNAL_CREATION_ATTRIBUTION_KEY} is server-owned`
3766
4127
  });
3767
4128
  }
@@ -3828,215 +4189,6 @@ function prepareExternalLinkTaskAdmission(authorization, actor) {
3828
4189
  };
3829
4190
  }
3830
4191
 
3831
- // src/billing/limits.ts
3832
- import {
3833
- configuredStaticUsageLimits,
3834
- resolveModelProviderForTurn
3835
- } from "@opengeni/config";
3836
- import {
3837
- countActiveApiKeysForWorkspace,
3838
- countActiveOrganizationApiKeysForAccount,
3839
- countScheduledTasksForWorkspace,
3840
- countWorkspacesForAccount,
3841
- getBillingBalance,
3842
- isCodexBilledTurn,
3843
- recordUsageEvent,
3844
- sumUsageQuantity
3845
- } from "@opengeni/db";
3846
- import { HTTPException as HTTPException9 } from "hono/http-exception";
3847
- function modelFundingForAdmission(settings, model, codexBilled) {
3848
- const resolvedModel = model ? resolveModelProviderForTurn(settings, model)?.model : null;
3849
- const codexSubscriptionModel = resolvedModel?.credentialSource.kind === "connected_subscription" && resolvedModel.credentialSource.provider === "codex";
3850
- return {
3851
- // A Codex namespace/definition never bypasses credits by itself: the live
3852
- // workspace credential predicate above remains authoritative. SuperGrok's
3853
- // static overlay is likewise secret-free; its worker/provider admission
3854
- // owns live account selection before any upstream request can occur.
3855
- fundedWithoutCredits: codexBilled || resolvedModel != null && !codexSubscriptionModel && resolvedModel.cost !== "credits",
3856
- countsTowardTokenCap: !codexBilled && resolvedModel != null && resolvedModel.billing.upstreamPayer === "deployment"
3857
- };
3858
- }
3859
- async function requireLimit(deps, input) {
3860
- const decision = await checkLimit(deps, input);
3861
- if (decision.allowed) {
3862
- return;
3863
- }
3864
- throw new HTTPException9(decision.code === "insufficient_credits" ? 402 : 429, {
3865
- message: decision.message
3866
- });
3867
- }
3868
- async function checkLimit(deps, input) {
3869
- const codexBilled = input.workspaceId ? await isCodexBilledTurn({
3870
- db: deps.db,
3871
- settings: deps.settings,
3872
- workspaceId: input.workspaceId,
3873
- model: input.model
3874
- }) : false;
3875
- const { fundedWithoutCredits, countsTowardTokenCap } = modelFundingForAdmission(
3876
- deps.settings,
3877
- input.model,
3878
- codexBilled
3879
- );
3880
- const creditDecision = await checkCreditBalance(deps, input, fundedWithoutCredits);
3881
- if (!creditDecision.allowed) {
3882
- return creditDecision;
3883
- }
3884
- if (deps.settings.usageLimitsMode !== "static" && deps.settings.usageLimitsMode !== "managed") {
3885
- return { allowed: true };
3886
- }
3887
- return await checkStaticCaps(deps, input, {
3888
- fundedWithoutCredits,
3889
- countsTowardTokenCap
3890
- });
3891
- }
3892
- async function checkCreditBalance(deps, input, externallyBilled) {
3893
- if (externallyBilled) {
3894
- return { allowed: true };
3895
- }
3896
- if (!usesCreditLimits(deps) || !isCostlyAction(input.action)) {
3897
- return { allowed: true };
3898
- }
3899
- const balance = await getBillingBalance(deps.db, input.accountId);
3900
- if (balance.balanceMicros > 0) {
3901
- return { allowed: true };
3902
- }
3903
- return { allowed: false, code: "insufficient_credits", message: "insufficient OpenGeni credits" };
3904
- }
3905
- async function checkStaticCaps(deps, input, funding) {
3906
- const limits = configuredStaticUsageLimits(deps.settings);
3907
- if (limits.maxMonthlyCostMicrosPerAccount && isCostlyAction(input.action) && !funding.fundedWithoutCredits) {
3908
- const used = await sumUsageQuantity(deps.db, {
3909
- accountId: input.accountId,
3910
- eventType: "model.cost",
3911
- since: startOfUtcMonth()
3912
- });
3913
- if (used >= limits.maxMonthlyCostMicrosPerAccount) {
3914
- return blocked(
3915
- "max_monthly_cost_micros_per_account",
3916
- `monthly model cost limit reached (${limits.maxMonthlyCostMicrosPerAccount} micros)`
3917
- );
3918
- }
3919
- }
3920
- switch (input.action) {
3921
- case "workspace:create": {
3922
- if (!limits.maxWorkspacesPerAccount) {
3923
- return { allowed: true };
3924
- }
3925
- const count = await countWorkspacesForAccount(deps.db, input.accountId);
3926
- return count < limits.maxWorkspacesPerAccount ? { allowed: true } : blocked(
3927
- "max_workspaces_per_account",
3928
- `workspace limit reached (${limits.maxWorkspacesPerAccount})`
3929
- );
3930
- }
3931
- case "api_key:create": {
3932
- if (!limits.maxApiKeysPerWorkspace) {
3933
- return { allowed: true };
3934
- }
3935
- const count = input.workspaceId ? await countActiveApiKeysForWorkspace(deps.db, input.workspaceId) : await countActiveOrganizationApiKeysForAccount(deps.db, input.accountId);
3936
- return count < limits.maxApiKeysPerWorkspace ? { allowed: true } : blocked(
3937
- "max_api_keys_per_workspace",
3938
- `API key limit reached (${limits.maxApiKeysPerWorkspace})`
3939
- );
3940
- }
3941
- case "schedule:create": {
3942
- if (!limits.maxSchedulesPerWorkspace || !input.workspaceId) {
3943
- return { allowed: true };
3944
- }
3945
- const count = await countScheduledTasksForWorkspace(deps.db, input.workspaceId);
3946
- return count < limits.maxSchedulesPerWorkspace ? { allowed: true } : blocked(
3947
- "max_schedules_per_workspace",
3948
- `scheduled task limit reached (${limits.maxSchedulesPerWorkspace})`
3949
- );
3950
- }
3951
- case "file:upload": {
3952
- if (!limits.maxFileUploadBytes || !input.quantity) {
3953
- return { allowed: true };
3954
- }
3955
- return input.quantity <= limits.maxFileUploadBytes ? { allowed: true } : blocked(
3956
- "max_file_upload_bytes",
3957
- `file upload exceeds static limit of ${limits.maxFileUploadBytes} bytes`
3958
- );
3959
- }
3960
- case "agent_run:create": {
3961
- if (!limits.maxMonthlyAgentRunsPerWorkspace || !input.workspaceId) {
3962
- return { allowed: true };
3963
- }
3964
- const used = await sumUsageQuantity(deps.db, {
3965
- workspaceId: input.workspaceId,
3966
- eventType: "agent_run.created",
3967
- since: startOfUtcMonth()
3968
- });
3969
- const requested = input.quantity ?? 0;
3970
- return used + requested <= limits.maxMonthlyAgentRunsPerWorkspace ? { allowed: true } : blocked(
3971
- "max_monthly_agent_runs_per_workspace",
3972
- `monthly agent run limit reached (${limits.maxMonthlyAgentRunsPerWorkspace})`
3973
- );
3974
- }
3975
- case "tokens:consume": {
3976
- if (!funding.countsTowardTokenCap || !limits.maxMonthlyTokensPerWorkspace || !input.workspaceId) {
3977
- return { allowed: true };
3978
- }
3979
- const used = await sumUsageQuantity(deps.db, {
3980
- workspaceId: input.workspaceId,
3981
- eventType: "model.tokens",
3982
- since: startOfUtcMonth()
3983
- });
3984
- const requested = input.quantity ?? 0;
3985
- return used + requested <= limits.maxMonthlyTokensPerWorkspace ? { allowed: true } : blocked(
3986
- "max_monthly_tokens_per_workspace",
3987
- `monthly token limit reached (${limits.maxMonthlyTokensPerWorkspace})`
3988
- );
3989
- }
3990
- case "document:index": {
3991
- if (!limits.maxDocumentIndexedChunksPerWorkspace || !input.workspaceId) {
3992
- return { allowed: true };
3993
- }
3994
- const used = await sumUsageQuantity(deps.db, {
3995
- workspaceId: input.workspaceId,
3996
- eventType: "document.indexed",
3997
- since: startOfUtcMonth()
3998
- });
3999
- const requested = input.quantity ?? 0;
4000
- return used + requested <= limits.maxDocumentIndexedChunksPerWorkspace ? { allowed: true } : blocked(
4001
- "max_document_indexed_chunks_per_workspace",
4002
- `monthly document indexing limit reached (${limits.maxDocumentIndexedChunksPerWorkspace} chunks)`
4003
- );
4004
- }
4005
- }
4006
- }
4007
- async function recordWorkspaceUsage(deps, input) {
4008
- await recordUsageEvent(deps.db, {
4009
- accountId: input.accountId,
4010
- workspaceId: input.workspaceId,
4011
- subjectId: input.subjectId ?? null,
4012
- eventType: input.eventType,
4013
- quantity: input.quantity,
4014
- unit: input.unit,
4015
- sourceResourceType: input.sourceResourceType,
4016
- sourceResourceId: input.sourceResourceId,
4017
- sessionId: input.sessionId ?? null,
4018
- turnId: input.turnId ?? null,
4019
- turnAttemptId: input.turnAttemptId ?? null,
4020
- initiator: input.initiator ?? (input.subjectId ? { kind: "subject", subjectId: input.subjectId } : null),
4021
- ...input.initiatorContext ? { initiatorContext: input.initiatorContext } : {},
4022
- origin: input.origin ?? null,
4023
- idempotencyKey: input.idempotencyKey
4024
- });
4025
- }
4026
- function usesCreditLimits(deps) {
4027
- return deps.settings.billingMode === "stripe" || deps.settings.usageLimitsMode === "managed";
4028
- }
4029
- function isCostlyAction(action) {
4030
- return action === "agent_run:create" || action === "tokens:consume" || action === "document:index";
4031
- }
4032
- function blocked(code, message) {
4033
- return { allowed: false, code, message };
4034
- }
4035
- function startOfUtcMonth() {
4036
- const now = /* @__PURE__ */ new Date();
4037
- return new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), 1));
4038
- }
4039
-
4040
4192
  // src/domain/native-mcp-connection-admission.ts
4041
4193
  import { HTTPException as HTTPException10 } from "hono/http-exception";
4042
4194
  function assertNativeMcpConnectionRef(connectionRef) {
@@ -5030,6 +5182,7 @@ function fikenCatalogItem(fikenConnections) {
5030
5182
  metadata: {
5031
5183
  connectorMode: "first_party_fiken",
5032
5184
  ownership: "workspace",
5185
+ connectionStatus: fikenConnection?.status ?? null,
5033
5186
  // Derived from the contracts catalog so a new fiken_* tool cannot be
5034
5187
  // registered without also appearing on the capability tile.
5035
5188
  firstPartyMcpTools: FIRST_PARTY_MCP_TOOL_NAMES.filter((name) => name.startsWith("fiken_"))
@@ -5231,15 +5384,15 @@ function socialProviderConnectionCounts(item) {
5231
5384
  };
5232
5385
  }
5233
5386
  function applyCapabilityEnablement(item, installation) {
5387
+ if (item.surfaceType === "first_party_fiken") {
5388
+ return { ...item, connectionRef: null };
5389
+ }
5234
5390
  if (item.kind === "skill" || item.kind === "api" || item.kind === "plugin") {
5235
5391
  return { ...item, enabled: false, enabledReason: null, connectionRef: null };
5236
5392
  }
5237
5393
  if (isSocialProviderIntegration(item)) {
5238
5394
  return { ...item, connectionRef: null };
5239
5395
  }
5240
- if (item.surfaceType === "first_party_fiken") {
5241
- return { ...item, connectionRef: null };
5242
- }
5243
5396
  if (item.surfaceType === "codex_apps") {
5244
5397
  return { ...item, connectionRef: null };
5245
5398
  }
@@ -5534,50 +5687,197 @@ function mcpRegistryEntryToCatalogItem(entry) {
5534
5687
  packages: server.packages ?? [],
5535
5688
  requiredHeaders
5536
5689
  }
5537
- });
5690
+ });
5691
+ }
5692
+ function requiredRemoteHeaders(remote) {
5693
+ return (remote.headers ?? []).filter((header) => header.name && header.isRequired !== false).map((header) => header.name.trim()).filter(Boolean);
5694
+ }
5695
+ function validUrl(value) {
5696
+ if (!value) {
5697
+ return null;
5698
+ }
5699
+ try {
5700
+ return new URL(value).toString();
5701
+ } catch {
5702
+ return null;
5703
+ }
5704
+ }
5705
+ function capabilityInstallationRuntimeReady(item, installation) {
5706
+ if (!installation || item.kind !== "mcp") {
5707
+ return !!installation;
5708
+ }
5709
+ if (!item.runtime.available) {
5710
+ return false;
5711
+ }
5712
+ if (!storedCredentialHeadersSatisfy(item, installation)) {
5713
+ return false;
5714
+ }
5715
+ const connectivity = installation.metadata.mcpConnectivity;
5716
+ return !!connectivity && typeof connectivity === "object" && "status" in connectivity && (connectivity.status === "ok" || connectivity.status === "auth_deferred");
5717
+ }
5718
+ function storedCredentialHeadersSatisfy(item, installation) {
5719
+ if (storedConnectionRef(installation.config)) {
5720
+ return true;
5721
+ }
5722
+ const storedNames = new Set(
5723
+ (Array.isArray(installation.config.headerNames) ? installation.config.headerNames : []).filter((name) => typeof name === "string").map((name) => name.toLowerCase())
5724
+ );
5725
+ const required = requiredCapabilityHeaders(item.metadata);
5726
+ if (required.some((name) => !storedNames.has(name.toLowerCase()))) {
5727
+ return false;
5728
+ }
5729
+ return !item.authModel || storedNames.size > 0;
5730
+ }
5731
+ function storedConnectionRef(config) {
5732
+ const ref = config.connectionRef;
5733
+ return !!ref && typeof ref === "object" && !Array.isArray(ref) && typeof ref.providerDomain === "string";
5734
+ }
5735
+
5736
+ // src/domain/session-tool-policy.ts
5737
+ import {
5738
+ SESSION_EFFECTIVE_TOOL_POLICY_ID_LIMIT,
5739
+ SESSION_EFFECTIVE_TOOL_POLICY_ID_MAX_LENGTH,
5740
+ mergeToolRefs,
5741
+ resolveWorkspaceSessionToolDefaults
5742
+ } from "@opengeni/contracts";
5743
+ import { requireWorkspace as requireWorkspace3 } from "@opengeni/db";
5744
+ var MANDATORY_SESSION_MCP_SERVER_IDS = ["opengeni"];
5745
+ var PROJECTABLE_REGISTRY_ID = /^[A-Za-z0-9_-]+$/;
5746
+ function sortedIds(ids) {
5747
+ return [...new Set(ids)].sort();
5748
+ }
5749
+ function defaultSessionMcpServerIds(servers) {
5750
+ const mandatory = new Set(MANDATORY_SESSION_MCP_SERVER_IDS);
5751
+ return sortedIds([...servers].map((server) => server.id).filter((id) => !mandatory.has(id)));
5752
+ }
5753
+ function projectIds(ids) {
5754
+ const projectable = ids.filter(
5755
+ (id) => id.length <= SESSION_EFFECTIVE_TOOL_POLICY_ID_MAX_LENGTH && PROJECTABLE_REGISTRY_ID.test(id)
5756
+ );
5757
+ return {
5758
+ ids: projectable.slice(0, SESSION_EFFECTIVE_TOOL_POLICY_ID_LIMIT),
5759
+ truncated: projectable.length !== ids.length || projectable.length > SESSION_EFFECTIVE_TOOL_POLICY_ID_LIMIT
5760
+ };
5761
+ }
5762
+ function resolveSessionToolPolicy(input) {
5763
+ const policy = input.toolPolicy;
5764
+ const availableIds = new Set(input.availableMcpServerIds);
5765
+ const defaultIds = new Set(input.defaultMcpServerIds ?? []);
5766
+ const mandatoryIds = MANDATORY_SESSION_MCP_SERVER_IDS.filter(
5767
+ (id) => availableIds.has(id)
5768
+ );
5769
+ const mandatoryIdSet = new Set(mandatoryIds);
5770
+ const tracksWorkspaceDefaults = policy.mode === "workspace_default";
5771
+ const excludedIds = new Set(tracksWorkspaceDefaults ? policy.excludedMcpServerIds : []);
5772
+ const selectedRefs = mergeToolRefs([], input.sessionTools).filter(
5773
+ (tool) => !excludedIds.has(tool.id) || mandatoryIdSet.has(tool.id)
5774
+ );
5775
+ let toolRefs = selectedRefs.filter((tool) => availableIds.has(tool.id));
5776
+ if (tracksWorkspaceDefaults) {
5777
+ toolRefs = mergeToolRefs(
5778
+ toolRefs,
5779
+ sortedIds(defaultIds).filter((id) => availableIds.has(id) && !excludedIds.has(id)).map((id) => ({ kind: "mcp", id, optional: true }))
5780
+ );
5781
+ }
5782
+ toolRefs = mergeToolRefs(
5783
+ toolRefs,
5784
+ mandatoryIds.map((id) => ({ kind: "mcp", id }))
5785
+ );
5786
+ const requestedEffectiveRefs = mergeToolRefs(
5787
+ selectedRefs,
5788
+ tracksWorkspaceDefaults ? sortedIds(defaultIds).filter((id) => availableIds.has(id) && !excludedIds.has(id)).map((id) => ({ kind: "mcp", id, optional: true })) : []
5789
+ );
5790
+ const effectiveIds = sortedIds(
5791
+ mergeToolRefs(
5792
+ requestedEffectiveRefs,
5793
+ mandatoryIds.map((id) => ({ kind: "mcp", id }))
5794
+ ).map((tool) => tool.id)
5795
+ );
5796
+ const configuredIds = effectiveIds.filter((id) => availableIds.has(id));
5797
+ const configuredIdSet = new Set(configuredIds);
5798
+ const droppedIds = effectiveIds.filter((id) => !configuredIdSet.has(id));
5799
+ const deferredIds = sortedIds(
5800
+ toolRefs.filter((tool) => configuredIdSet.has(tool.id) && tool.eager !== true).map((tool) => tool.id)
5801
+ );
5802
+ const selectedIds = sortedIds(
5803
+ selectedRefs.filter(
5804
+ (tool) => !mandatoryIdSet.has(tool.id) && !(tracksWorkspaceDefaults && tool.optional === true)
5805
+ ).map((tool) => tool.id)
5806
+ );
5807
+ const projections = {
5808
+ selected: projectIds(selectedIds),
5809
+ effective: projectIds(effectiveIds),
5810
+ mandatory: projectIds(sortedIds(mandatoryIds)),
5811
+ deferred: projectIds(deferredIds),
5812
+ configured: projectIds(configuredIds),
5813
+ dropped: projectIds(droppedIds)
5814
+ };
5815
+ return {
5816
+ toolRefs,
5817
+ effectivePolicy: {
5818
+ mode: policy.mode,
5819
+ inheritedFromSessionId: policy.inheritedFromSessionId,
5820
+ selectedIds: projections.selected.ids,
5821
+ effectiveIds: projections.effective.ids,
5822
+ mandatoryIds: projections.mandatory.ids,
5823
+ lazyRouter: {
5824
+ state: deferredIds.length > 0 ? "required" : "disabled",
5825
+ deferredIds: projections.deferred.ids
5826
+ },
5827
+ configuredIds: projections.configured.ids,
5828
+ droppedIds: projections.dropped.ids,
5829
+ counts: {
5830
+ selected: selectedIds.length,
5831
+ effective: effectiveIds.length,
5832
+ mandatory: mandatoryIds.length,
5833
+ deferred: deferredIds.length,
5834
+ configured: configuredIds.length,
5835
+ dropped: droppedIds.length
5836
+ },
5837
+ idsTruncated: Object.values(projections).some((projection) => projection.truncated)
5838
+ }
5839
+ };
5538
5840
  }
5539
- function requiredRemoteHeaders(remote) {
5540
- return (remote.headers ?? []).filter((header) => header.name && header.isRequired !== false).map((header) => header.name.trim()).filter(Boolean);
5841
+ async function workspaceSessionToolPolicyServerIds(db, workspaceId, settings, subjectId) {
5842
+ const runtimeSettings = await settingsWithEnabledCapabilityMcpServers(db, workspaceId, settings, {
5843
+ ...subjectId ? { subjectId } : {}
5844
+ });
5845
+ return sortedIds(runtimeSettings.mcpServers.map((server) => server.id));
5541
5846
  }
5542
- function validUrl(value) {
5543
- if (!value) {
5544
- return null;
5545
- }
5546
- try {
5547
- return new URL(value).toString();
5548
- } catch {
5549
- return null;
5550
- }
5847
+ async function workspaceSessionToolPolicyDefaultServerIds(db, workspaceId, settings, subjectId) {
5848
+ const runtimeSettings = await settingsWithEnabledCapabilityMcpServers(db, workspaceId, settings, {
5849
+ ...subjectId ? { subjectId } : {}
5850
+ });
5851
+ const workspace = await requireWorkspace3(db, workspaceId);
5852
+ return workspaceSessionToolPolicyDefaultServerIdsFor(
5853
+ runtimeSettings.mcpServers,
5854
+ workspace.settings
5855
+ );
5551
5856
  }
5552
- function capabilityInstallationRuntimeReady(item, installation) {
5553
- if (!installation || item.kind !== "mcp") {
5554
- return !!installation;
5555
- }
5556
- if (!item.runtime.available) {
5557
- return false;
5558
- }
5559
- if (!storedCredentialHeadersSatisfy(item, installation)) {
5560
- return false;
5561
- }
5562
- const connectivity = installation.metadata.mcpConnectivity;
5563
- return !!connectivity && typeof connectivity === "object" && "status" in connectivity && (connectivity.status === "ok" || connectivity.status === "auth_deferred");
5857
+ function workspaceSessionToolPolicyDefaultServerIdsFor(runtimeMcpServers, workspaceSettings) {
5858
+ const availableDefaults = defaultSessionMcpServerIds(runtimeMcpServers);
5859
+ const configured = resolveWorkspaceSessionToolDefaults(workspaceSettings);
5860
+ if (!configured?.mcpServerIds) return availableDefaults;
5861
+ const available = new Set(availableDefaults);
5862
+ return sortedIds([
5863
+ ...configured.mcpServerIds.filter((id) => available.has(id)),
5864
+ ...configured.inheritConnectedMcpServers ? availableDefaults.filter((id) => !["opengeni", "files", "docs"].includes(id)) : []
5865
+ ]);
5564
5866
  }
5565
- function storedCredentialHeadersSatisfy(item, installation) {
5566
- if (storedConnectionRef(installation.config)) {
5567
- return true;
5568
- }
5569
- const storedNames = new Set(
5570
- (Array.isArray(installation.config.headerNames) ? installation.config.headerNames : []).filter((name) => typeof name === "string").map((name) => name.toLowerCase())
5571
- );
5572
- const required = requiredCapabilityHeaders(item.metadata);
5573
- if (required.some((name) => !storedNames.has(name.toLowerCase()))) {
5574
- return false;
5867
+ function sessionWithEffectiveToolPolicy(session, workspaceServerIds, workspaceDefaultServerIds = []) {
5868
+ const availableIds = new Set(workspaceServerIds);
5869
+ for (const server of session.mcpServers) {
5870
+ availableIds.add(server.id);
5575
5871
  }
5576
- return !item.authModel || storedNames.size > 0;
5577
- }
5578
- function storedConnectionRef(config) {
5579
- const ref = config.connectionRef;
5580
- return !!ref && typeof ref === "object" && !Array.isArray(ref) && typeof ref.providerDomain === "string";
5872
+ return {
5873
+ ...session,
5874
+ effectiveToolPolicy: resolveSessionToolPolicy({
5875
+ toolPolicy: session.toolPolicy,
5876
+ sessionTools: session.tools,
5877
+ availableMcpServerIds: availableIds,
5878
+ defaultMcpServerIds: workspaceDefaultServerIds
5879
+ }).effectivePolicy
5880
+ };
5581
5881
  }
5582
5882
 
5583
5883
  // src/domain/timeline-annotations.ts
@@ -5760,7 +6060,7 @@ import {
5760
6060
  gitCredentialProviderForRepository,
5761
6061
  defaultRepositoryMountPath,
5762
6062
  mergeResourceRefs as mergeContractResourceRefs,
5763
- mergeToolRefs,
6063
+ mergeToolRefs as mergeToolRefs2,
5764
6064
  normalizeRepositorySubpath,
5765
6065
  normalizeRepositoryTransportUri,
5766
6066
  normalizeResourceMountPath,
@@ -5800,20 +6100,20 @@ function validateToolRefs(tools, settings) {
5800
6100
  ...tool.eager === true ? { eager: true } : {}
5801
6101
  });
5802
6102
  }
5803
- return mergeToolRefs([], out);
6103
+ return mergeToolRefs2([], out);
5804
6104
  }
5805
6105
  function enabledCapabilityMcpToolRefs(settings, runtimeSettings) {
5806
6106
  const configuredIds = new Set(settings.mcpServers.map((server) => server.id));
5807
6107
  return runtimeSettings.mcpServers.filter((server) => !configuredIds.has(server.id)).map((server) => ({ kind: "mcp", id: server.id, optional: true }));
5808
6108
  }
5809
6109
  function withDefaultEnabledCapabilityMcpTools(tools, settings, runtimeSettings) {
5810
- return mergeToolRefs(tools, enabledCapabilityMcpToolRefs(settings, runtimeSettings));
6110
+ return mergeToolRefs2(tools, enabledCapabilityMcpToolRefs(settings, runtimeSettings));
5811
6111
  }
5812
6112
  function withWorkspaceDefaultMcpTools(tools, settings, runtimeSettings, defaults2) {
5813
6113
  if (!defaults2?.mcpServerIds) {
5814
6114
  return withDefaultEnabledCapabilityMcpTools(tools, settings, runtimeSettings);
5815
6115
  }
5816
- return mergeToolRefs(
6116
+ return mergeToolRefs2(
5817
6117
  tools,
5818
6118
  validateToolRefs(
5819
6119
  [
@@ -7855,6 +8155,12 @@ function canonicalConfiguredModel(settings, model) {
7855
8155
  return model;
7856
8156
  }
7857
8157
  const canonicalModel = canonicalizeConfiguredModelId(settings, model);
8158
+ if (canonicalModel.startsWith(CODEX_MODEL_ID_PREFIX) && settings.resolvedCodexModelsJson !== void 0) {
8159
+ if (settings.codexSubscriptionEnabled && configuredAllowedModels(withCodexCatalogProvider2(settings)).includes(canonicalModel)) {
8160
+ return canonicalModel;
8161
+ }
8162
+ throw new HTTPException15(422, { message: `model is not available: ${model}` });
8163
+ }
7858
8164
  if (configuredAllowedModels(settings).includes(canonicalModel)) {
7859
8165
  return canonicalModel;
7860
8166
  }
@@ -8383,8 +8689,8 @@ async function createSessionForRequestInFileScope(unresolvedDeps, grant, workspa
8383
8689
  message: `parent session not found in workspace: ${parentSessionId}`
8384
8690
  });
8385
8691
  }
8386
- const workspace = await requireWorkspace3(db, workspaceId);
8387
- const workspaceSessionToolDefaults = resolveWorkspaceSessionToolDefaults(workspace.settings);
8692
+ const workspace = await requireWorkspace4(db, workspaceId);
8693
+ const workspaceSessionToolDefaults = resolveWorkspaceSessionToolDefaults2(workspace.settings);
8388
8694
  const parentAuthority = parentSession ? await getSessionAuthorityProjection4(db, workspaceId, parentSession.id) : null;
8389
8695
  if (parentSession && !parentAuthority) {
8390
8696
  throw new HTTPException15(403, {
@@ -9426,23 +9732,32 @@ async function acceptSessionUserMessageInFileScope(deps, grant, workspaceId, ses
9426
9732
  connectionDelegationSource.sessionId,
9427
9733
  connectionDelegationSource.turnId
9428
9734
  ) : null;
9735
+ const capabilityRuntimeSettings = await settingsWithEnabledCapabilityMcpServers(
9736
+ db,
9737
+ workspaceId,
9738
+ settings,
9739
+ inheritedPersonalConnectionDelegations ? {
9740
+ personalConnectionDelegations: inheritedPersonalConnectionDelegations
9741
+ } : { subjectId: grant.subjectId }
9742
+ );
9429
9743
  const runtimeSettings = settingsWithSessionMcpServerMetadata(
9430
- await settingsWithEnabledCapabilityMcpServers(
9431
- db,
9432
- workspaceId,
9433
- settings,
9434
- inheritedPersonalConnectionDelegations ? {
9435
- personalConnectionDelegations: inheritedPersonalConnectionDelegations
9436
- } : { subjectId: grant.subjectId }
9437
- ),
9744
+ capabilityRuntimeSettings,
9438
9745
  existingSession.mcpServers
9439
9746
  );
9747
+ const connectionAccountTools = sessionToolsForConnectionAccounts({
9748
+ session: existingSession,
9749
+ runtimeMcpServers: runtimeSettings.mcpServers,
9750
+ defaultMcpServerIds: workspaceSessionToolPolicyDefaultServerIdsFor(
9751
+ capabilityRuntimeSettings.mcpServers,
9752
+ (await requireWorkspace4(db, workspaceId)).settings
9753
+ )
9754
+ });
9440
9755
  const { personalConnectionDelegations, mcpAccountBindings } = await freezeConnectionAccounts({
9441
9756
  db,
9442
9757
  accountId: grant.accountId,
9443
9758
  workspaceId,
9444
9759
  settings: runtimeSettings,
9445
- tools: existingSession.tools,
9760
+ tools: connectionAccountTools,
9446
9761
  resources: [...existingSession.resources, ...requestedResources],
9447
9762
  source: connectionDelegationSource,
9448
9763
  targetSessionId: sessionId,
@@ -9607,7 +9922,7 @@ async function updateSessionMcpApprovalPolicy(deps, grant, sessionId, serverId,
9607
9922
  };
9608
9923
  }
9609
9924
  function toolPolicyAuditSnapshot(session, tools, firstPartyMcpTools, policy = session.toolPolicy) {
9610
- const allToolRefs = mergeToolRefs([], tools).sort((left, right) => {
9925
+ const allToolRefs = mergeToolRefs2([], tools).sort((left, right) => {
9611
9926
  const leftMandatory = left.kind === "mcp" && left.id === "opengeni";
9612
9927
  const rightMandatory = right.kind === "mcp" && right.id === "opengeni";
9613
9928
  if (leftMandatory !== rightMandatory) return leftMandatory ? -1 : 1;
@@ -9644,8 +9959,8 @@ async function updateSessionToolPolicy(deps, grant, sessionId, request) {
9644
9959
  requirePermission(grant, "sessions:control");
9645
9960
  const agentAttemptCaller = grantHasAgentAttemptAuthority(grant);
9646
9961
  const existingSession = await requireSession2(deps.db, grant.workspaceId, sessionId);
9647
- const workspace = await requireWorkspace3(deps.db, grant.workspaceId);
9648
- const workspaceSessionToolDefaults = resolveWorkspaceSessionToolDefaults(workspace.settings);
9962
+ const workspace = await requireWorkspace4(deps.db, grant.workspaceId);
9963
+ const workspaceSessionToolDefaults = resolveWorkspaceSessionToolDefaults2(workspace.settings);
9649
9964
  const capabilityRuntimeSettings = await settingsWithEnabledCapabilityMcpServers(
9650
9965
  deps.db,
9651
9966
  grant.workspaceId,
@@ -9930,7 +10245,15 @@ function withFirstPartyTools(tools, runtimeSettings) {
9930
10245
  if (!runtimeSettings.mcpServers.some((server) => server.id === "opengeni")) {
9931
10246
  return tools;
9932
10247
  }
9933
- return mergeToolRefs(tools, [{ kind: "mcp", id: "opengeni" }]);
10248
+ return mergeToolRefs2(tools, [{ kind: "mcp", id: "opengeni" }]);
10249
+ }
10250
+ function sessionToolsForConnectionAccounts(input) {
10251
+ return resolveSessionToolPolicy({
10252
+ toolPolicy: input.session.toolPolicy,
10253
+ sessionTools: input.session.tools,
10254
+ availableMcpServerIds: [...input.runtimeMcpServers].map((server) => server.id),
10255
+ defaultMcpServerIds: input.defaultMcpServerIds
10256
+ }).toolRefs;
9934
10257
  }
9935
10258
  function hasOwnProperty(value, key) {
9936
10259
  return Boolean(
@@ -10629,12 +10952,13 @@ import { HTTPException as HTTPException19 } from "hono/http-exception";
10629
10952
  import { pinnedFetch as pinnedFetch2, readResponseJsonBounded as readResponseJsonBounded2, readResponseTextBounded } from "@opengeni/network";
10630
10953
  import {
10631
10954
  PORTABLE_SKILL_MAX_FILES as PORTABLE_SKILL_MAX_FILES2,
10955
+ PORTABLE_SKILL_MAX_FILE_BYTES as PORTABLE_SKILL_MAX_FILE_BYTES2,
10632
10956
  PORTABLE_SKILL_MAX_TOTAL_BYTES as PORTABLE_SKILL_MAX_TOTAL_BYTES2
10633
10957
  } from "@opengeni/runtime/skill-library";
10634
10958
  var githubApiBase = "https://api.github.com";
10635
10959
  var githubRequestTimeoutMs = 15e3;
10636
10960
  var githubMetadataMaxBytes = 4 * 1024 * 1024;
10637
- var githubBlobResponseMaxBytes = 512 * 1024;
10961
+ var githubBlobResponseMaxBytes = PORTABLE_SKILL_MAX_FILE_BYTES2 * 2;
10638
10962
  function createGitHubSkillSourceClient(settings, requestJson = (path, maxBytes, label) => githubJson(settings, path, maxBytes, label)) {
10639
10963
  const readJson = requestJson;
10640
10964
  const cache = /* @__PURE__ */ new Map();
@@ -12187,147 +12511,6 @@ function personalGitHubActionPolicyActor(input) {
12187
12511
  };
12188
12512
  }
12189
12513
 
12190
- // src/domain/session-tool-policy.ts
12191
- import {
12192
- SESSION_EFFECTIVE_TOOL_POLICY_ID_LIMIT,
12193
- SESSION_EFFECTIVE_TOOL_POLICY_ID_MAX_LENGTH,
12194
- mergeToolRefs as mergeToolRefs2,
12195
- resolveWorkspaceSessionToolDefaults as resolveWorkspaceSessionToolDefaults2
12196
- } from "@opengeni/contracts";
12197
- import { requireWorkspace as requireWorkspace4 } from "@opengeni/db";
12198
- var MANDATORY_SESSION_MCP_SERVER_IDS = ["opengeni"];
12199
- var PROJECTABLE_REGISTRY_ID = /^[A-Za-z0-9_-]+$/;
12200
- function sortedIds(ids) {
12201
- return [...new Set(ids)].sort();
12202
- }
12203
- function defaultSessionMcpServerIds(servers) {
12204
- const mandatory = new Set(MANDATORY_SESSION_MCP_SERVER_IDS);
12205
- return sortedIds([...servers].map((server) => server.id).filter((id) => !mandatory.has(id)));
12206
- }
12207
- function projectIds(ids) {
12208
- const projectable = ids.filter(
12209
- (id) => id.length <= SESSION_EFFECTIVE_TOOL_POLICY_ID_MAX_LENGTH && PROJECTABLE_REGISTRY_ID.test(id)
12210
- );
12211
- return {
12212
- ids: projectable.slice(0, SESSION_EFFECTIVE_TOOL_POLICY_ID_LIMIT),
12213
- truncated: projectable.length !== ids.length || projectable.length > SESSION_EFFECTIVE_TOOL_POLICY_ID_LIMIT
12214
- };
12215
- }
12216
- function resolveSessionToolPolicy(input) {
12217
- const policy = input.toolPolicy;
12218
- const availableIds = new Set(input.availableMcpServerIds);
12219
- const defaultIds = new Set(input.defaultMcpServerIds ?? []);
12220
- const mandatoryIds = MANDATORY_SESSION_MCP_SERVER_IDS.filter(
12221
- (id) => availableIds.has(id)
12222
- );
12223
- const mandatoryIdSet = new Set(mandatoryIds);
12224
- const tracksWorkspaceDefaults = policy.mode === "workspace_default";
12225
- const excludedIds = new Set(tracksWorkspaceDefaults ? policy.excludedMcpServerIds : []);
12226
- const selectedRefs = mergeToolRefs2([], input.sessionTools).filter(
12227
- (tool) => !excludedIds.has(tool.id) || mandatoryIdSet.has(tool.id)
12228
- );
12229
- let toolRefs = selectedRefs.filter((tool) => availableIds.has(tool.id));
12230
- if (tracksWorkspaceDefaults) {
12231
- toolRefs = mergeToolRefs2(
12232
- toolRefs,
12233
- sortedIds(defaultIds).filter((id) => availableIds.has(id) && !excludedIds.has(id)).map((id) => ({ kind: "mcp", id, optional: true }))
12234
- );
12235
- }
12236
- toolRefs = mergeToolRefs2(
12237
- toolRefs,
12238
- mandatoryIds.map((id) => ({ kind: "mcp", id }))
12239
- );
12240
- const requestedEffectiveRefs = mergeToolRefs2(
12241
- selectedRefs,
12242
- tracksWorkspaceDefaults ? sortedIds(defaultIds).filter((id) => availableIds.has(id) && !excludedIds.has(id)).map((id) => ({ kind: "mcp", id, optional: true })) : []
12243
- );
12244
- const effectiveIds = sortedIds(
12245
- mergeToolRefs2(
12246
- requestedEffectiveRefs,
12247
- mandatoryIds.map((id) => ({ kind: "mcp", id }))
12248
- ).map((tool) => tool.id)
12249
- );
12250
- const configuredIds = effectiveIds.filter((id) => availableIds.has(id));
12251
- const configuredIdSet = new Set(configuredIds);
12252
- const droppedIds = effectiveIds.filter((id) => !configuredIdSet.has(id));
12253
- const deferredIds = sortedIds(
12254
- toolRefs.filter((tool) => configuredIdSet.has(tool.id) && tool.eager !== true).map((tool) => tool.id)
12255
- );
12256
- const selectedIds = sortedIds(
12257
- selectedRefs.filter(
12258
- (tool) => !mandatoryIdSet.has(tool.id) && !(tracksWorkspaceDefaults && tool.optional === true)
12259
- ).map((tool) => tool.id)
12260
- );
12261
- const projections = {
12262
- selected: projectIds(selectedIds),
12263
- effective: projectIds(effectiveIds),
12264
- mandatory: projectIds(sortedIds(mandatoryIds)),
12265
- deferred: projectIds(deferredIds),
12266
- configured: projectIds(configuredIds),
12267
- dropped: projectIds(droppedIds)
12268
- };
12269
- return {
12270
- toolRefs,
12271
- effectivePolicy: {
12272
- mode: policy.mode,
12273
- inheritedFromSessionId: policy.inheritedFromSessionId,
12274
- selectedIds: projections.selected.ids,
12275
- effectiveIds: projections.effective.ids,
12276
- mandatoryIds: projections.mandatory.ids,
12277
- lazyRouter: {
12278
- state: deferredIds.length > 0 ? "required" : "disabled",
12279
- deferredIds: projections.deferred.ids
12280
- },
12281
- configuredIds: projections.configured.ids,
12282
- droppedIds: projections.dropped.ids,
12283
- counts: {
12284
- selected: selectedIds.length,
12285
- effective: effectiveIds.length,
12286
- mandatory: mandatoryIds.length,
12287
- deferred: deferredIds.length,
12288
- configured: configuredIds.length,
12289
- dropped: droppedIds.length
12290
- },
12291
- idsTruncated: Object.values(projections).some((projection) => projection.truncated)
12292
- }
12293
- };
12294
- }
12295
- async function workspaceSessionToolPolicyServerIds(db, workspaceId, settings, subjectId) {
12296
- const runtimeSettings = await settingsWithEnabledCapabilityMcpServers(db, workspaceId, settings, {
12297
- ...subjectId ? { subjectId } : {}
12298
- });
12299
- return sortedIds(runtimeSettings.mcpServers.map((server) => server.id));
12300
- }
12301
- async function workspaceSessionToolPolicyDefaultServerIds(db, workspaceId, settings, subjectId) {
12302
- const runtimeSettings = await settingsWithEnabledCapabilityMcpServers(db, workspaceId, settings, {
12303
- ...subjectId ? { subjectId } : {}
12304
- });
12305
- const availableDefaults = defaultSessionMcpServerIds(runtimeSettings.mcpServers);
12306
- const workspace = await requireWorkspace4(db, workspaceId);
12307
- const configured = resolveWorkspaceSessionToolDefaults2(workspace.settings);
12308
- if (!configured?.mcpServerIds) return availableDefaults;
12309
- const available = new Set(availableDefaults);
12310
- return sortedIds([
12311
- ...configured.mcpServerIds.filter((id) => available.has(id)),
12312
- ...configured.inheritConnectedMcpServers ? availableDefaults.filter((id) => !["opengeni", "files", "docs"].includes(id)) : []
12313
- ]);
12314
- }
12315
- function sessionWithEffectiveToolPolicy(session, workspaceServerIds, workspaceDefaultServerIds = []) {
12316
- const availableIds = new Set(workspaceServerIds);
12317
- for (const server of session.mcpServers) {
12318
- availableIds.add(server.id);
12319
- }
12320
- return {
12321
- ...session,
12322
- effectiveToolPolicy: resolveSessionToolPolicy({
12323
- toolPolicy: session.toolPolicy,
12324
- sessionTools: session.tools,
12325
- availableMcpServerIds: availableIds,
12326
- defaultMcpServerIds: workspaceDefaultServerIds
12327
- }).effectivePolicy
12328
- };
12329
- }
12330
-
12331
12514
  // src/domain/scheduled-tasks.ts
12332
12515
  import {
12333
12516
  scheduledTaskKnowledgeSource,
@@ -15932,6 +16115,7 @@ import {
15932
16115
  publicNewSessionDraftOptions,
15933
16116
  requireFileForSubject as requireFileForSubject2,
15934
16117
  saveNewSessionDraftInTransaction,
16118
+ reusableNewSessionRepositoryResource,
15935
16119
  withWorkspaceSubjectRls as withWorkspaceSubjectRls6
15936
16120
  } from "@opengeni/db";
15937
16121
  import { HTTPException as HTTPException23 } from "hono/http-exception";
@@ -16153,6 +16337,31 @@ async function saveActorNewSessionDraft(...args) {
16153
16337
  const actor = authorization ? await fileOwnerContextForAccess(deps, authorization, "sessions:create") : { subjectId: grant.subjectId, privateFileOwnerSubjectId: null };
16154
16338
  return withSessionRlsActorContext6(actor, () => saveActorNewSessionDraftInFileScope(...args));
16155
16339
  }
16340
+ async function getActorNewSessionDefaults(deps, grant, workspaceId) {
16341
+ const draft = await getActorNewSessionDraft(deps, grant, workspaceId);
16342
+ const options = draft.options;
16343
+ return {
16344
+ // Revision zero is a synthetic empty form, not a user's model preference.
16345
+ ...draft.revision > 0 ? {
16346
+ model: draft.model,
16347
+ reasoningEffort: draft.reasoningEffort,
16348
+ latencyMode: draft.latencyMode
16349
+ } : {},
16350
+ resources: draft.resources.flatMap(
16351
+ (resource) => resource.kind === "repository" ? [reusableNewSessionRepositoryResource(resource)] : []
16352
+ ),
16353
+ ...draft.toolsProvided ? { tools: draft.tools } : options.excludedMcpServerIds ? { excludedMcpServerIds: options.excludedMcpServerIds } : {},
16354
+ ...options.firstPartyMcpTools ? { firstPartyMcpTools: options.firstPartyMcpTools } : {},
16355
+ ...options.firstPartyMcpPermissions ? { firstPartyMcpPermissions: options.firstPartyMcpPermissions } : {},
16356
+ ...options.variableSetIds ? { variableSetIds: options.variableSetIds } : {},
16357
+ ...options.rigId ? { rigId: options.rigId } : {},
16358
+ ...options.sandboxBackend ? { sandboxBackend: options.sandboxBackend } : {},
16359
+ ...options.targetSandboxId ? {
16360
+ targetSandboxId: options.targetSandboxId,
16361
+ ...options.workingDir ? { workingDir: options.workingDir } : {}
16362
+ } : {}
16363
+ };
16364
+ }
16156
16365
 
16157
16366
  // src/application/composer-submit.ts
16158
16367
  async function submitComposerDraftForRequest(deps, grant, workspaceId, sessionId, input, options = {}) {
@@ -17265,7 +17474,7 @@ var CATALOG_PAGE_SIZE = 25;
17265
17474
  var CATALOG_PAGE_BUDGET = 40;
17266
17475
  var DESCRIPTION_CHARS = 2e3;
17267
17476
  var CATALOG_BYTES = 256 * 1024;
17268
- async function prepareKnowledgeSave(db, context, input, embedder, services = defaults) {
17477
+ async function prepareKnowledgeSave(db, context, input, embedder, services = defaults, settings) {
17269
17478
  const request = KnowledgeSavePreparationRequest.parse(input);
17270
17479
  if (context.actor.kind !== "agent" && !(context.actor.kind === "human" && context.actor.review)) {
17271
17480
  throw Object.assign(
@@ -17290,20 +17499,31 @@ async function prepareKnowledgeSave(db, context, input, embedder, services = def
17290
17499
  complete: true,
17291
17500
  nextCursors: { published: null, needs_review: null }
17292
17501
  };
17293
- const matches = {
17294
- published: await services.search(
17295
- db,
17296
- context,
17297
- { query: request.query, limit: request.limit, view: "published" },
17298
- sharedEmbedder
17299
- ),
17300
- needs_review: await services.search(
17301
- db,
17302
- context,
17303
- { query: request.query, limit: request.limit, view: "needs_review" },
17304
- sharedEmbedder
17305
- )
17306
- };
17502
+ const paid = settings != null && paidDocumentEmbedding(settings);
17503
+ const published = await services.search(
17504
+ db,
17505
+ context,
17506
+ {
17507
+ query: request.query,
17508
+ limit: request.limit,
17509
+ view: "published",
17510
+ ...paid ? { mode: "keyword" } : {}
17511
+ },
17512
+ sharedEmbedder,
17513
+ paid ? void 0 : settings
17514
+ );
17515
+ const needsReview = await services.search(
17516
+ db,
17517
+ context,
17518
+ {
17519
+ query: request.query,
17520
+ limit: request.limit,
17521
+ view: "needs_review",
17522
+ ...published.searchMode === "keyword" ? { mode: "keyword" } : {}
17523
+ },
17524
+ sharedEmbedder
17525
+ );
17526
+ const matches = { published, needs_review: needsReview };
17307
17527
  for (const view of ["published", "needs_review"]) {
17308
17528
  if (request.collectionCursors && request.collectionCursors[view] === null) continue;
17309
17529
  let cursor = request.collectionCursors?.[view] ?? void 0;
@@ -17712,6 +17932,8 @@ export {
17712
17932
  InMemoryEditableArtifactLiveTicketStore,
17713
17933
  InMemoryEditableArtifactStableIdFactory,
17714
17934
  InMemoryEditableArtifactStore,
17935
+ KnowledgeVectorFundingError,
17936
+ KnowledgeVectorQueryRejectedError,
17715
17937
  MAX_CHECKS_PER_RIG,
17716
17938
  MAX_CREDENTIAL_HOOKS_PER_RIG,
17717
17939
  MAX_DEFAULT_VARIABLE_SETS_PER_RIG,
@@ -17860,6 +18082,7 @@ export {
17860
18082
  directRetainedProcessMatchesBackend,
17861
18083
  disableCapability,
17862
18084
  discoverMcpRegistryCapabilities,
18085
+ documentEmbeddingCostMicros,
17863
18086
  editHumanQueuePrompt,
17864
18087
  editableArtifactActorKey,
17865
18088
  editableArtifactAuthorizationRevisionPortFromPostgres,
@@ -17907,6 +18130,7 @@ export {
17907
18130
  freezeAgentChildAutomaticTitleInCreatorContext,
17908
18131
  freezeConnectionAccounts,
17909
18132
  freezePersonalConnectionDelegations,
18133
+ getActorNewSessionDefaults,
17910
18134
  getActorNewSessionDraft,
17911
18135
  getAutomationAdapter,
17912
18136
  getConnectorToolPermissions,
@@ -17977,7 +18201,7 @@ export {
17977
18201
  mergeCausalFrontiers,
17978
18202
  mergeResourceRefs,
17979
18203
  mergeRigDefaultVariableSetEnvironment,
17980
- mergeToolRefs,
18204
+ mergeToolRefs2 as mergeToolRefs,
17981
18205
  modelFundingForAdmission,
17982
18206
  moveHumanQueuePrompt,
17983
18207
  nativeConnectionCapabilityRecommendations,
@@ -18001,6 +18225,7 @@ export {
18001
18225
  openGeniSlackBotMetadata,
18002
18226
  organizationIntegrationCatalog,
18003
18227
  organizationMembershipHttpStatus,
18228
+ paidDocumentEmbedding,
18004
18229
  parseGitHubRepositoryCoordinates,
18005
18230
  parseSkillSource,
18006
18231
  personalAtlassianDelegationsFromVisibleConnections,
@@ -18128,9 +18353,11 @@ export {
18128
18353
  searchKnowledgeEntries,
18129
18354
  selectedPersonalConnectionServers,
18130
18355
  sendAgentSessionMessage,
18356
+ sessionGroupMachinePresentation,
18131
18357
  sessionMcpRotationFingerprint,
18132
18358
  sessionRlsActorForAuthorization,
18133
18359
  sessionSpawnDenialEnvelope,
18360
+ sessionToolsForConnectionAccounts,
18134
18361
  sessionWithEffectiveToolPolicy,
18135
18362
  settingsWithApiIntegrationServers,
18136
18363
  settingsWithCodexAppsMcpServer,
@@ -18196,6 +18423,7 @@ export {
18196
18423
  workspaceCustomModelReference,
18197
18424
  workspaceInsightsPhaseMetricObserver,
18198
18425
  workspaceSessionToolPolicyDefaultServerIds,
18426
+ workspaceSessionToolPolicyDefaultServerIdsFor,
18199
18427
  workspaceSessionToolPolicyServerIds,
18200
18428
  wrapChannelABoxWithRouting
18201
18429
  };