@opengeni/core 4.0.1 → 4.0.3-canary.36199476632001

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
@@ -1980,6 +2323,270 @@ function resolveWorkspaceModelSelection(input) {
1980
2323
  });
1981
2324
  }
1982
2325
 
2326
+ // src/default-session-model.ts
2327
+ import {
2328
+ canonicalizeConfiguredModelId
2329
+ } from "@opengeni/config";
2330
+ import {
2331
+ resolveWorkspaceSessionDefaults
2332
+ } from "@opengeni/contracts";
2333
+ import {
2334
+ getScheduledTaskXaiProviderAccountAuthoritySnapshot,
2335
+ getSession as getSession2,
2336
+ getWorkspace,
2337
+ getWorkspaceConnectionModelRestrictions,
2338
+ getWorkspaceModelPolicy,
2339
+ listOrganizationModelProviderCustomModelsForWorkspace as listOrganizationModelProviderCustomModelsForWorkspace2,
2340
+ listWorkspaceGatewayCustomModels as listWorkspaceGatewayCustomModels2,
2341
+ listWorkspaceOpenRouterCustomModels as listWorkspaceOpenRouterCustomModels2,
2342
+ organizationModelProviderConnectionActiveForWorkspace,
2343
+ workspaceCodexSubscriptionActive,
2344
+ workspaceOpenRouterConnectionActive,
2345
+ workspaceVercelAiGatewayConnectionActive,
2346
+ organizationHoldsCredits,
2347
+ workspaceXaiSubscriptionActive,
2348
+ workspaceXaiSubscriptionActiveForAuthority,
2349
+ XaiAuthorityPoolInactiveError
2350
+ } from "@opengeni/db";
2351
+ var REASONING_EFFORT_ORDER = [
2352
+ "none",
2353
+ "minimal",
2354
+ "low",
2355
+ "medium",
2356
+ "high",
2357
+ "xhigh",
2358
+ "max"
2359
+ ];
2360
+ function supportedReasoningEfforts(model) {
2361
+ const efforts = model.capabilities.reasoning.efforts;
2362
+ return REASONING_EFFORT_ORDER.filter((effort) => efforts.includes(effort));
2363
+ }
2364
+ function defaultReasoningEffortForConfiguredModel(model, fallback) {
2365
+ const options = supportedReasoningEfforts(model);
2366
+ if (options.length === 0) return fallback;
2367
+ const configured = model.capabilities.reasoning.defaultEffort;
2368
+ if (configured && options.includes(configured)) return configured;
2369
+ return options[0];
2370
+ }
2371
+ function clampReasoningEffortForConfiguredModel(model, preferred, fallback) {
2372
+ const options = supportedReasoningEfforts(model);
2373
+ if (options.length === 0) return fallback;
2374
+ if (options.includes(preferred)) return preferred;
2375
+ const ceiling = REASONING_EFFORT_ORDER.indexOf(preferred);
2376
+ const below = options.filter((effort) => REASONING_EFFORT_ORDER.indexOf(effort) <= ceiling);
2377
+ return below.at(-1) ?? defaultReasoningEffortForConfiguredModel(model, fallback);
2378
+ }
2379
+ function findSelection(selections, modelId) {
2380
+ return selections.find((selection) => selection.model.id === modelId) ?? selections.find((selection) => selection.model.aliases.includes(modelId));
2381
+ }
2382
+ function creditsCandidate(input) {
2383
+ const fallbackEffort = input.settings.openaiReasoningEffort;
2384
+ const deployment = findSelection(input.selections, input.settings.openaiModel);
2385
+ if (deployment?.availability.selectable && deployment.model.cost === "credits") return null;
2386
+ const configured = findSelection(input.selections, input.settings.creditsDefaultModel);
2387
+ if (configured?.availability.selectable && configured.model.cost === "credits") {
2388
+ return {
2389
+ model: configured.model.id,
2390
+ reasoningEffort: clampReasoningEffortForConfiguredModel(
2391
+ configured.model,
2392
+ input.settings.creditsDefaultReasoningEffort,
2393
+ fallbackEffort
2394
+ ),
2395
+ source: "credits"
2396
+ };
2397
+ }
2398
+ const first = input.selections.find(
2399
+ (selection) => selection.availability.selectable && selection.model.cost === "credits"
2400
+ );
2401
+ return first ? {
2402
+ model: first.model.id,
2403
+ reasoningEffort: defaultReasoningEffortForConfiguredModel(first.model, fallbackEffort),
2404
+ source: "credits"
2405
+ } : null;
2406
+ }
2407
+ function selectDefaultSessionModel(input) {
2408
+ const fallbackEffort = input.settings.openaiReasoningEffort;
2409
+ if (input.workspaceDefaults) {
2410
+ const saved = findSelection(input.selections, input.workspaceDefaults.model);
2411
+ if (saved?.availability.selectable) {
2412
+ return {
2413
+ model: saved.model.id,
2414
+ reasoningEffort: clampReasoningEffortForConfiguredModel(
2415
+ saved.model,
2416
+ input.workspaceDefaults.reasoningEffort,
2417
+ fallbackEffort
2418
+ ),
2419
+ source: "workspace"
2420
+ };
2421
+ }
2422
+ }
2423
+ const deployment = findSelection(input.selections, input.settings.openaiModel);
2424
+ const subscription = deployment?.availability.selectable && deployment.model.cost === "subscription" ? deployment : input.selections.find(
2425
+ (selection) => selection.availability.selectable && selection.model.cost === "subscription"
2426
+ );
2427
+ if (subscription) {
2428
+ return {
2429
+ model: subscription.model.id,
2430
+ reasoningEffort: defaultReasoningEffortForConfiguredModel(subscription.model, fallbackEffort),
2431
+ source: "subscription"
2432
+ };
2433
+ }
2434
+ if (input.creditsAvailable) {
2435
+ const credits = creditsCandidate(input);
2436
+ if (credits) return credits;
2437
+ }
2438
+ return {
2439
+ model: deployment?.model.id ?? canonicalizeConfiguredModelId(input.settings, input.settings.openaiModel),
2440
+ reasoningEffort: fallbackEffort,
2441
+ source: "deployment"
2442
+ };
2443
+ }
2444
+ function creditsDefaultSessionModel(input) {
2445
+ if (input.settings.billingMode !== "stripe") return null;
2446
+ return selectDefaultSessionModel({
2447
+ settings: input.settings,
2448
+ selections: input.selections,
2449
+ workspaceDefaults: resolveWorkspaceSessionDefaults(input.workspaceSettings),
2450
+ creditsAvailable: true
2451
+ });
2452
+ }
2453
+ async function resolveDefaultSessionModelForSelections(db, input) {
2454
+ const decision = {
2455
+ settings: input.settings,
2456
+ selections: input.selections,
2457
+ workspaceDefaults: resolveWorkspaceSessionDefaults(input.workspaceSettings)
2458
+ };
2459
+ const withoutCredits = selectDefaultSessionModel({ ...decision, creditsAvailable: false });
2460
+ if (withoutCredits.source !== "deployment" || input.settings.billingMode !== "stripe" || creditsCandidate(decision) === null) {
2461
+ return withoutCredits;
2462
+ }
2463
+ return await organizationHoldsCredits(db, input.accountId) ? selectDefaultSessionModel({ ...decision, creditsAvailable: true }) : withoutCredits;
2464
+ }
2465
+ async function connectionRestrictionsAndXaiReadiness(db, settings, context) {
2466
+ const { workspaceId, subjectId, xaiAuthoritySnapshot } = context;
2467
+ if (!xaiAuthoritySnapshot) {
2468
+ const [restrictions2, xaiSubscriptionActive] = await Promise.all([
2469
+ getWorkspaceConnectionModelRestrictions(db, workspaceId, subjectId),
2470
+ workspaceXaiSubscriptionActive(db, settings, workspaceId, subjectId)
2471
+ ]);
2472
+ return { restrictions: restrictions2, xaiSubscriptionActive };
2473
+ }
2474
+ const frozen = await Promise.allSettled([
2475
+ getWorkspaceConnectionModelRestrictions(db, workspaceId, subjectId, xaiAuthoritySnapshot),
2476
+ workspaceXaiSubscriptionActiveForAuthority(db, settings, {
2477
+ workspaceId,
2478
+ subjectId,
2479
+ authoritySnapshot: xaiAuthoritySnapshot
2480
+ })
2481
+ ]);
2482
+ const [restrictions, readiness] = frozen;
2483
+ if (restrictions.status === "fulfilled" && readiness.status === "fulfilled") {
2484
+ return { restrictions: restrictions.value, xaiSubscriptionActive: readiness.value };
2485
+ }
2486
+ for (const result of frozen) {
2487
+ if (result.status === "rejected" && !(result.reason instanceof XaiAuthorityPoolInactiveError)) {
2488
+ throw result.reason;
2489
+ }
2490
+ }
2491
+ const current = await getWorkspaceConnectionModelRestrictions(db, workspaceId, subjectId);
2492
+ return {
2493
+ restrictions: { ...current, "supergrok/": [] },
2494
+ xaiSubscriptionActive: false
2495
+ };
2496
+ }
2497
+ async function loadWorkspaceModelSelectionInput(db, settings, context) {
2498
+ const { accountId, workspaceId } = context;
2499
+ const [
2500
+ { restrictions: connectionModelRestrictions, xaiSubscriptionActive },
2501
+ policy,
2502
+ codexSubscriptionActive,
2503
+ workspaceGatewayConnectionActive,
2504
+ workspaceGatewayCustomModels,
2505
+ openRouterConnectionActive,
2506
+ workspaceOpenRouterCustomModels,
2507
+ organizationGatewayConnectionActive,
2508
+ organizationOpenRouterConnectionActive,
2509
+ organizationGatewayCustomModels,
2510
+ organizationOpenRouterCustomModels
2511
+ ] = await Promise.all([
2512
+ connectionRestrictionsAndXaiReadiness(db, settings, context),
2513
+ getWorkspaceModelPolicy(db, workspaceId),
2514
+ workspaceCodexSubscriptionActive(db, settings, workspaceId),
2515
+ workspaceVercelAiGatewayConnectionActive(db, workspaceId),
2516
+ listWorkspaceGatewayCustomModels2(db, { accountId, workspaceId }),
2517
+ workspaceOpenRouterConnectionActive(db, workspaceId),
2518
+ listWorkspaceOpenRouterCustomModels2(db, { accountId, workspaceId }),
2519
+ organizationModelProviderConnectionActiveForWorkspace(db, {
2520
+ accountId,
2521
+ workspaceId,
2522
+ providerKind: "vercel_gateway"
2523
+ }),
2524
+ organizationModelProviderConnectionActiveForWorkspace(db, {
2525
+ accountId,
2526
+ workspaceId,
2527
+ providerKind: "openrouter"
2528
+ }),
2529
+ listOrganizationModelProviderCustomModelsForWorkspace2(db, {
2530
+ accountId,
2531
+ workspaceId,
2532
+ providerKind: "vercel_gateway"
2533
+ }),
2534
+ listOrganizationModelProviderCustomModelsForWorkspace2(db, {
2535
+ accountId,
2536
+ workspaceId,
2537
+ providerKind: "openrouter"
2538
+ })
2539
+ ]);
2540
+ return {
2541
+ connectionModelRestrictions,
2542
+ settings,
2543
+ policy,
2544
+ codexSubscriptionActive,
2545
+ xaiSubscriptionActive,
2546
+ workspaceGatewayConnectionActive,
2547
+ workspaceGatewayCustomModels,
2548
+ workspaceOpenRouterConnectionActive: openRouterConnectionActive,
2549
+ workspaceOpenRouterCustomModels,
2550
+ organizationGatewayConnectionActive,
2551
+ organizationOpenRouterConnectionActive,
2552
+ organizationGatewayCustomModels,
2553
+ organizationOpenRouterCustomModels
2554
+ };
2555
+ }
2556
+ async function resolveDefaultSessionModel(db, settings, context) {
2557
+ const [selectionInput, workspaceSettings] = await Promise.all([
2558
+ loadWorkspaceModelSelectionInput(db, settings, context),
2559
+ context.workspaceSettings !== void 0 ? Promise.resolve(context.workspaceSettings) : getWorkspace(db, context.workspaceId).then((workspace) => workspace?.settings ?? {})
2560
+ ]);
2561
+ return await resolveDefaultSessionModelForSelections(db, {
2562
+ settings,
2563
+ accountId: context.accountId,
2564
+ workspaceSettings,
2565
+ selections: resolveWorkspaceModelSelection(selectionInput)
2566
+ });
2567
+ }
2568
+ async function resolveScheduledTaskDefaultModel(db, settings, task) {
2569
+ return await resolveDefaultSessionModel(db, settings, {
2570
+ accountId: task.accountId,
2571
+ workspaceId: task.workspaceId,
2572
+ subjectId: task.ownerSubjectId ?? task.createdBy.subjectId,
2573
+ xaiAuthoritySnapshot: await getScheduledTaskXaiProviderAccountAuthoritySnapshot(
2574
+ db,
2575
+ task.workspaceId,
2576
+ task.id
2577
+ )
2578
+ });
2579
+ }
2580
+ async function resolveScheduledTaskPreflightModel(db, settings, task) {
2581
+ if (task.agentConfig.model) return task.agentConfig.model;
2582
+ const targetSessionId = task.runMode === "existing_session" ? task.targetSessionId : task.runMode === "reusable_session" ? task.reusableSessionId : null;
2583
+ if (targetSessionId) {
2584
+ const session = await getSession2(db, task.workspaceId, targetSessionId);
2585
+ if (session) return session.model;
2586
+ }
2587
+ return (await resolveScheduledTaskDefaultModel(db, settings, task)).model;
2588
+ }
2589
+
1983
2590
  // src/sandbox/fleet.ts
1984
2591
  import {
1985
2592
  authorizePersonalMachineForAttempt,
@@ -3272,7 +3879,7 @@ async function provisionSandbox(services, ctx, input) {
3272
3879
  }
3273
3880
 
3274
3881
  // src/application/external-workspace-members.ts
3275
- import { HTTPException as HTTPException4 } from "hono/http-exception";
3882
+ import { HTTPException as HTTPException5 } from "hono/http-exception";
3276
3883
  import {
3277
3884
  AddExternalWorkspaceMemberRequest,
3278
3885
  ExternalIdentityReference,
@@ -3308,12 +3915,12 @@ async function addExternalWorkspaceMemberForRequest(c, deps, workspaceId, input)
3308
3915
  const context = await requireAccessContext(c, deps);
3309
3916
  const authority = accountScopedApiKeyWorkspaceAuthority(context);
3310
3917
  if (!authority)
3311
- throw new HTTPException4(403, {
3918
+ throw new HTTPException5(403, {
3312
3919
  message: "external onboarding requires an organization service key"
3313
3920
  });
3314
3921
  const grant = await requireFreshAccessGrant(c, deps, workspaceId, "members:manage");
3315
3922
  if (grant.accountId !== authority.accountId || payload.permissions.some((permission) => !hasPermission(grant.permissions, permission))) {
3316
- throw new HTTPException4(403, { message: "membership exceeds key authority" });
3923
+ throw new HTTPException5(403, { message: "membership exceeds key authority" });
3317
3924
  }
3318
3925
  if (payload.operationId) {
3319
3926
  try {
@@ -3339,11 +3946,11 @@ async function addExternalWorkspaceMemberForRequest(c, deps, workspaceId, input)
3339
3946
  "members:manage"
3340
3947
  );
3341
3948
  if (live.accountId !== grant.accountId || live.subjectId !== grant.subjectId || payload.permissions.some((permission) => !hasPermission(live.permissions, permission))) {
3342
- throw new HTTPException4(403, { message: "membership authority changed" });
3949
+ throw new HTTPException5(403, { message: "membership authority changed" });
3343
3950
  }
3344
3951
  const workspace = await requireWorkspace2(tx, workspaceId);
3345
3952
  if (workspace.kind !== "shared" || workspace.accountId !== authority.accountId)
3346
- throw new HTTPException4(403, {
3953
+ throw new HTTPException5(403, {
3347
3954
  message: "external onboarding requires a shared organization workspace"
3348
3955
  });
3349
3956
  const identity = await ensureExternalIdentity2(tx, {
@@ -3357,7 +3964,7 @@ async function addExternalWorkspaceMemberForRequest(c, deps, workspaceId, input)
3357
3964
  const permissions = [...new Set(payload.permissions)];
3358
3965
  if (existing) {
3359
3966
  if (existing.permissions.length !== permissions.length || existing.permissions.some((permission) => !permissions.includes(permission))) {
3360
- throw new HTTPException4(409, {
3967
+ throw new HTTPException5(409, {
3361
3968
  message: "existing membership differs; onboarding does not overwrite permissions"
3362
3969
  });
3363
3970
  }
@@ -3376,7 +3983,7 @@ async function addExternalWorkspaceMemberForRequest(c, deps, workspaceId, input)
3376
3983
  function rethrowExternalWorkspaceOperation(error) {
3377
3984
  const status = organizationMembershipHttpStatus(nestedPostgresSqlState2(error));
3378
3985
  if (status)
3379
- throw new HTTPException4(status, {
3986
+ throw new HTTPException5(status, {
3380
3987
  message: status === 409 ? "External membership operation changed or was cancelled" : "External membership operation is not available"
3381
3988
  });
3382
3989
  throw error;
@@ -3385,7 +3992,7 @@ async function externalService(c, deps, organizationId) {
3385
3992
  const context = await requireAccessContext(c, deps);
3386
3993
  const authority = accountScopedApiKeyWorkspaceAuthority(context);
3387
3994
  if (!authority || authority.accountId !== organizationId || !hasPermission(authority.permissions, "members:manage")) {
3388
- throw new HTTPException4(403, {
3995
+ throw new HTTPException5(403, {
3389
3996
  message: "External membership operation requires an organization service key"
3390
3997
  });
3391
3998
  }
@@ -3395,7 +4002,7 @@ async function lookupExternalIdentityForRequest(c, deps, organizationId, input)
3395
4002
  const service = await externalService(c, deps, organizationId);
3396
4003
  const identity = ExternalIdentityReference.safeParse(input);
3397
4004
  if (!identity.success)
3398
- throw new HTTPException4(422, { message: "Invalid external identity reference" });
4005
+ throw new HTTPException5(422, { message: "Invalid external identity reference" });
3399
4006
  try {
3400
4007
  return await lookupExternalIdentity(deps.db, service, identity.data);
3401
4008
  } catch (error) {
@@ -3406,7 +4013,7 @@ async function cancelExternalWorkspaceMemberGrantForRequest(c, deps, organizatio
3406
4013
  const service = await externalService(c, deps, organizationId);
3407
4014
  const request = CancelExternalWorkspaceMemberGrantRequest.safeParse(input);
3408
4015
  if (!request.success)
3409
- throw new HTTPException4(422, { message: "Invalid external grant cancellation" });
4016
+ throw new HTTPException5(422, { message: "Invalid external grant cancellation" });
3410
4017
  try {
3411
4018
  return await cancelExternalWorkspaceMemberGrant(
3412
4019
  deps.db,
@@ -3419,7 +4026,7 @@ async function cancelExternalWorkspaceMemberGrantForRequest(c, deps, organizatio
3419
4026
  }
3420
4027
 
3421
4028
  // src/application/external-identity-lifecycle.ts
3422
- import { HTTPException as HTTPException5 } from "hono/http-exception";
4029
+ import { HTTPException as HTTPException6 } from "hono/http-exception";
3423
4030
  import { UpdateExternalIdentityMembershipRequest } from "@opengeni/contracts/external-identities";
3424
4031
  import { updateOrganizationMember } from "@opengeni/db";
3425
4032
  async function updateExternalIdentityMembershipForRequest(context, deps, organizationId, membershipId, input) {
@@ -3429,13 +4036,13 @@ async function updateExternalIdentityMembershipForRequest(context, deps, organiz
3429
4036
  (grant) => grant.accountId === organizationId && grant.subjectId === access.subjectId
3430
4037
  );
3431
4038
  if (!service || service.accountId !== organizationId || !account?.permissions.includes("account:admin")) {
3432
- throw new HTTPException5(403, {
4039
+ throw new HTTPException6(403, {
3433
4040
  message: "external identity administration requires an organization service key"
3434
4041
  });
3435
4042
  }
3436
4043
  const parsed = UpdateExternalIdentityMembershipRequest.safeParse(input);
3437
4044
  if (!parsed.success)
3438
- throw new HTTPException5(422, { message: "invalid external identity transition" });
4045
+ throw new HTTPException6(422, { message: "invalid external identity transition" });
3439
4046
  return updateOrganizationMember(deps.db, {
3440
4047
  organizationId,
3441
4048
  membershipId,
@@ -3457,7 +4064,7 @@ import {
3457
4064
  nestedPostgresSqlState as nestedPostgresSqlState3,
3458
4065
  withWorkspaceSubjectRls as withWorkspaceSubjectRls3
3459
4066
  } from "@opengeni/db";
3460
- import { HTTPException as HTTPException6 } from "hono/http-exception";
4067
+ import { HTTPException as HTTPException7 } from "hono/http-exception";
3461
4068
  function externalContinuationCommitAuthorizer(authorization) {
3462
4069
  const continuation = authorization ? externalActorContinuationForAuthorization(authorization) : null;
3463
4070
  if (!continuation || !authorization) return void 0;
@@ -3472,7 +4079,7 @@ function externalContinuationCommitAuthorizer(authorization) {
3472
4079
  await requireExternalContinuationAuthority(tx, continuation, scope, permissions);
3473
4080
  } catch (error) {
3474
4081
  const denied2 = nestedPostgresSqlState3(error) === "42501" || error instanceof Error && error.message === "External continuation authority unavailable";
3475
- throw new HTTPException6(denied2 ? 403 : 503, {
4082
+ throw new HTTPException7(denied2 ? 403 : 503, {
3476
4083
  message: denied2 ? "external authority changed" : "external authority is unavailable",
3477
4084
  cause: error
3478
4085
  });
@@ -3537,12 +4144,12 @@ import {
3537
4144
  variableSetVariableNameReservation
3538
4145
  } from "@opengeni/contracts";
3539
4146
  import { getVariableSet, recordAuditEvent } from "@opengeni/db";
3540
- import { HTTPException as HTTPException7 } from "hono/http-exception";
4147
+ import { HTTPException as HTTPException8 } from "hono/http-exception";
3541
4148
  var MAX_ENVIRONMENTS_PER_WORKSPACE = 25;
3542
4149
  var MAX_VARIABLES_PER_ENVIRONMENT = 100;
3543
4150
  function assertAllowedVariableSetVariableName(name) {
3544
4151
  if (variableSetVariableNameReservation(name)) {
3545
- throw new HTTPException7(422, {
4152
+ throw new HTTPException8(422, {
3546
4153
  message: `reserved variable set variable name / reserved environment variable name: ${name}`
3547
4154
  });
3548
4155
  }
@@ -3551,7 +4158,7 @@ var assertAllowedEnvironmentVariableName = assertAllowedVariableSetVariableName;
3551
4158
  function requireVariableSetEncryption(settings) {
3552
4159
  const key = environmentsEncryptionKeyBytes(settings);
3553
4160
  if (!key) {
3554
- throw new HTTPException7(503, {
4161
+ throw new HTTPException8(503, {
3555
4162
  message: "variable sets require OPENGENI_ENVIRONMENTS_ENCRYPTION_KEY"
3556
4163
  });
3557
4164
  }
@@ -3569,7 +4176,7 @@ async function requireVariableSetForApi(db, grant, variableSetId) {
3569
4176
  variableSetId
3570
4177
  );
3571
4178
  if (!variableSet) {
3572
- throw new HTTPException7(404, { message: "variableSet not found" });
4179
+ throw new HTTPException8(404, { message: "variableSet not found" });
3573
4180
  }
3574
4181
  return variableSet;
3575
4182
  }
@@ -3583,7 +4190,7 @@ async function validateVariableSetAttachment(deps, grant, workspaceId, variableS
3583
4190
  variableSetId
3584
4191
  );
3585
4192
  if (!variableSet) {
3586
- throw new HTTPException7(422, { message: "unknown variableSetId" });
4193
+ throw new HTTPException8(422, { message: "unknown variableSetId" });
3587
4194
  }
3588
4195
  return variableSet;
3589
4196
  }
@@ -3681,7 +4288,7 @@ function sessionCreationMetadata(metadata) {
3681
4288
 
3682
4289
  // src/domain/sessions.ts
3683
4290
  import {
3684
- canonicalizeConfiguredModelId,
4291
+ canonicalizeConfiguredModelId as canonicalizeConfiguredModelId2,
3685
4292
  configuredAllowedModels,
3686
4293
  withCodexCatalogProvider as withCodexCatalogProvider2,
3687
4294
  ORGANIZATION_GATEWAY_MODEL_ID_PREFIX as ORGANIZATION_GATEWAY_MODEL_ID_PREFIX2,
@@ -3691,7 +4298,8 @@ import {
3691
4298
  resolveTurnExecutionPolicyV1,
3692
4299
  WORKSPACE_GATEWAY_MODEL_ID_PREFIX as WORKSPACE_GATEWAY_MODEL_ID_PREFIX2,
3693
4300
  WORKSPACE_OPENROUTER_MODEL_ID_PREFIX as WORKSPACE_OPENROUTER_MODEL_ID_PREFIX2,
3694
- XAI_SUBSCRIPTION_MODEL_ID_PREFIX
4301
+ XAI_SUBSCRIPTION_MODEL_ID_PREFIX,
4302
+ codeSearchDeploymentPolicy
3695
4303
  } from "@opengeni/config";
3696
4304
  import {
3697
4305
  AUTOMATIC_SESSION_TITLE_FALLBACK,
@@ -3732,7 +4340,7 @@ import {
3732
4340
  listEnabledMcpCapabilityServers as listEnabledMcpCapabilityServers2,
3733
4341
  requireApprovalWithFloor,
3734
4342
  getSandbox as getSandbox3,
3735
- getSession as getSession2,
4343
+ getSession as getSession3,
3736
4344
  getInitializedSessionCreateReplay,
3737
4345
  getSessionAuthorityProjection as getSessionAuthorityProjection4,
3738
4346
  SessionIdConflictError,
@@ -3743,7 +4351,7 @@ import {
3743
4351
  getSessionTurnForAttempt as getSessionTurnForAttempt3,
3744
4352
  getSessionTurnPersonalConnectionDelegations as getSessionTurnPersonalConnectionDelegations2,
3745
4353
  getSessionTurnXaiProviderAccountAuthoritySnapshot,
3746
- getWorkspaceModelPolicy,
4354
+ getWorkspaceModelPolicy as getWorkspaceModelPolicy2,
3747
4355
  requireWorkspace as requireWorkspace4,
3748
4356
  initializeSessionStartAtomically,
3749
4357
  listSessionTurns,
@@ -3772,287 +4380,78 @@ import {
3772
4380
  publishDurableSessionEvents as publishDurableSessionEvents2,
3773
4381
  publishDurableWorkspaceControlEvent
3774
4382
  } from "@opengeni/events";
3775
- import { HTTPException as HTTPException15 } from "hono/http-exception";
3776
-
3777
- // src/domain/external-creation-attribution.ts
3778
- import { HTTPException as HTTPException8 } from "hono/http-exception";
3779
- var EXTERNAL_CREATION_ATTRIBUTION_KEY = "opengeniExternalCreationAttribution";
3780
- function externalCreationMetadata(metadata, authorization, grant) {
3781
- if (metadata && Object.hasOwn(metadata, EXTERNAL_CREATION_ATTRIBUTION_KEY)) {
3782
- throw new HTTPException8(422, {
3783
- message: `${EXTERNAL_CREATION_ATTRIBUTION_KEY} is server-owned`
3784
- });
3785
- }
3786
- const attribution = externalAttributionForAuthorization(authorization, grant);
3787
- if (!attribution) return metadata;
3788
- return { ...metadata, [EXTERNAL_CREATION_ATTRIBUTION_KEY]: attribution };
3789
- }
3790
-
3791
- // src/application/external-link-work-admission.ts
3792
- import { ExternalLinkWorkSnapshot } from "@opengeni/contracts/external-identities";
3793
- import {
3794
- captureExternalLinkTurnAuthority,
3795
- captureExternalLinkTaskAuthority,
3796
- getExternalLinkTurnSnapshot,
3797
- getSessionTurnForAttempt as getSessionTurnForAttempt2
3798
- } from "@opengeni/db";
3799
- function snapshotFor(authorization) {
3800
- const continuation = authorization ? externalActorContinuationForAuthorization(authorization) : null;
3801
- return continuation?.actor.actingMode === "linked_native" ? ExternalLinkWorkSnapshot.parse({
3802
- ...continuation,
3803
- permissions: [...authorization.grant.permissions]
3804
- }) : null;
3805
- }
3806
- function prepareExternalLinkTurnAdmission(authorization) {
3807
- const snapshot = snapshotFor(authorization);
3808
- if (!snapshot || !authorization) return void 0;
3809
- const workspaceId = authorization.grant.workspaceId;
3810
- const accountId = authorization.grant.accountId;
3811
- const commit = externalContinuationCommitAuthorizer(authorization);
3812
- return async (tx, sessionId, turnId) => {
3813
- await commit(tx);
3814
- await captureExternalLinkTurnAuthority(tx, {
3815
- accountId,
3816
- workspaceId,
3817
- sessionId,
3818
- turnId,
3819
- snapshot
3820
- });
3821
- };
3822
- }
3823
- function prepareExternalLinkTaskAdmission(authorization, actor) {
3824
- const snapshot = snapshotFor(authorization);
3825
- const commit = externalContinuationCommitAuthorizer(authorization);
3826
- if (snapshot)
3827
- return async (tx, task) => {
3828
- await commit?.(tx);
3829
- await captureExternalLinkTaskAuthority(tx, task, snapshot);
3830
- };
3831
- if (!actor) {
3832
- return authorization && hasVerifiedOwningUserAuthorization(authorization) ? async () => {
3833
- } : void 0;
3834
- }
3835
- return async (tx, task) => {
3836
- const turn = await getSessionTurnForAttempt2(
3837
- tx,
3838
- task.workspaceId,
3839
- actor.sessionId,
3840
- actor.attemptId
3841
- );
3842
- if (!turn || turn.id !== actor.turnId || turn.executionGeneration !== actor.executionGeneration)
3843
- throw new Error("Linked task creator attempt is no longer active");
3844
- const inherited = await getExternalLinkTurnSnapshot(tx, task, actor.turnId);
3845
- if (inherited) await captureExternalLinkTaskAuthority(tx, task, inherited);
3846
- };
3847
- }
3848
-
3849
- // src/billing/limits.ts
3850
- import {
3851
- configuredStaticUsageLimits,
3852
- resolveModelProviderForTurn
3853
- } from "@opengeni/config";
3854
- import {
3855
- countActiveApiKeysForWorkspace,
3856
- countActiveOrganizationApiKeysForAccount,
3857
- countScheduledTasksForWorkspace,
3858
- countWorkspacesForAccount,
3859
- getBillingBalance,
3860
- isCodexBilledTurn,
3861
- recordUsageEvent,
3862
- sumUsageQuantity
3863
- } from "@opengeni/db";
3864
- import { HTTPException as HTTPException9 } from "hono/http-exception";
3865
- function modelFundingForAdmission(settings, model, codexBilled) {
3866
- const resolvedModel = model ? resolveModelProviderForTurn(settings, model)?.model : null;
3867
- const codexSubscriptionModel = resolvedModel?.credentialSource.kind === "connected_subscription" && resolvedModel.credentialSource.provider === "codex";
3868
- return {
3869
- // A Codex namespace/definition never bypasses credits by itself: the live
3870
- // workspace credential predicate above remains authoritative. SuperGrok's
3871
- // static overlay is likewise secret-free; its worker/provider admission
3872
- // owns live account selection before any upstream request can occur.
3873
- fundedWithoutCredits: codexBilled || resolvedModel != null && !codexSubscriptionModel && resolvedModel.cost !== "credits",
3874
- countsTowardTokenCap: !codexBilled && resolvedModel != null && resolvedModel.billing.upstreamPayer === "deployment"
3875
- };
3876
- }
3877
- async function requireLimit(deps, input) {
3878
- const decision = await checkLimit(deps, input);
3879
- if (decision.allowed) {
3880
- return;
3881
- }
3882
- throw new HTTPException9(decision.code === "insufficient_credits" ? 402 : 429, {
3883
- message: decision.message
3884
- });
3885
- }
3886
- async function checkLimit(deps, input) {
3887
- const codexBilled = input.workspaceId ? await isCodexBilledTurn({
3888
- db: deps.db,
3889
- settings: deps.settings,
3890
- workspaceId: input.workspaceId,
3891
- model: input.model
3892
- }) : false;
3893
- const { fundedWithoutCredits, countsTowardTokenCap } = modelFundingForAdmission(
3894
- deps.settings,
3895
- input.model,
3896
- codexBilled
3897
- );
3898
- const creditDecision = await checkCreditBalance(deps, input, fundedWithoutCredits);
3899
- if (!creditDecision.allowed) {
3900
- return creditDecision;
3901
- }
3902
- if (deps.settings.usageLimitsMode !== "static" && deps.settings.usageLimitsMode !== "managed") {
3903
- return { allowed: true };
3904
- }
3905
- return await checkStaticCaps(deps, input, {
3906
- fundedWithoutCredits,
3907
- countsTowardTokenCap
3908
- });
3909
- }
3910
- async function checkCreditBalance(deps, input, externallyBilled) {
3911
- if (externallyBilled) {
3912
- return { allowed: true };
3913
- }
3914
- if (!usesCreditLimits(deps) || !isCostlyAction(input.action)) {
3915
- return { allowed: true };
3916
- }
3917
- const balance = await getBillingBalance(deps.db, input.accountId);
3918
- if (balance.balanceMicros > 0) {
3919
- return { allowed: true };
3920
- }
3921
- return { allowed: false, code: "insufficient_credits", message: "insufficient OpenGeni credits" };
3922
- }
3923
- async function checkStaticCaps(deps, input, funding) {
3924
- const limits = configuredStaticUsageLimits(deps.settings);
3925
- if (limits.maxMonthlyCostMicrosPerAccount && isCostlyAction(input.action) && !funding.fundedWithoutCredits) {
3926
- const used = await sumUsageQuantity(deps.db, {
3927
- accountId: input.accountId,
3928
- eventType: "model.cost",
3929
- since: startOfUtcMonth()
4383
+ import { HTTPException as HTTPException15 } from "hono/http-exception";
4384
+
4385
+ // src/domain/external-creation-attribution.ts
4386
+ import { HTTPException as HTTPException9 } from "hono/http-exception";
4387
+ var EXTERNAL_CREATION_ATTRIBUTION_KEY = "opengeniExternalCreationAttribution";
4388
+ function externalCreationMetadata(metadata, authorization, grant) {
4389
+ if (metadata && Object.hasOwn(metadata, EXTERNAL_CREATION_ATTRIBUTION_KEY)) {
4390
+ throw new HTTPException9(422, {
4391
+ message: `${EXTERNAL_CREATION_ATTRIBUTION_KEY} is server-owned`
3930
4392
  });
3931
- if (used >= limits.maxMonthlyCostMicrosPerAccount) {
3932
- return blocked(
3933
- "max_monthly_cost_micros_per_account",
3934
- `monthly model cost limit reached (${limits.maxMonthlyCostMicrosPerAccount} micros)`
3935
- );
3936
- }
3937
- }
3938
- switch (input.action) {
3939
- case "workspace:create": {
3940
- if (!limits.maxWorkspacesPerAccount) {
3941
- return { allowed: true };
3942
- }
3943
- const count = await countWorkspacesForAccount(deps.db, input.accountId);
3944
- return count < limits.maxWorkspacesPerAccount ? { allowed: true } : blocked(
3945
- "max_workspaces_per_account",
3946
- `workspace limit reached (${limits.maxWorkspacesPerAccount})`
3947
- );
3948
- }
3949
- case "api_key:create": {
3950
- if (!limits.maxApiKeysPerWorkspace) {
3951
- return { allowed: true };
3952
- }
3953
- const count = input.workspaceId ? await countActiveApiKeysForWorkspace(deps.db, input.workspaceId) : await countActiveOrganizationApiKeysForAccount(deps.db, input.accountId);
3954
- return count < limits.maxApiKeysPerWorkspace ? { allowed: true } : blocked(
3955
- "max_api_keys_per_workspace",
3956
- `API key limit reached (${limits.maxApiKeysPerWorkspace})`
3957
- );
3958
- }
3959
- case "schedule:create": {
3960
- if (!limits.maxSchedulesPerWorkspace || !input.workspaceId) {
3961
- return { allowed: true };
3962
- }
3963
- const count = await countScheduledTasksForWorkspace(deps.db, input.workspaceId);
3964
- return count < limits.maxSchedulesPerWorkspace ? { allowed: true } : blocked(
3965
- "max_schedules_per_workspace",
3966
- `scheduled task limit reached (${limits.maxSchedulesPerWorkspace})`
3967
- );
3968
- }
3969
- case "file:upload": {
3970
- if (!limits.maxFileUploadBytes || !input.quantity) {
3971
- return { allowed: true };
3972
- }
3973
- return input.quantity <= limits.maxFileUploadBytes ? { allowed: true } : blocked(
3974
- "max_file_upload_bytes",
3975
- `file upload exceeds static limit of ${limits.maxFileUploadBytes} bytes`
3976
- );
3977
- }
3978
- case "agent_run:create": {
3979
- if (!limits.maxMonthlyAgentRunsPerWorkspace || !input.workspaceId) {
3980
- return { allowed: true };
3981
- }
3982
- const used = await sumUsageQuantity(deps.db, {
3983
- workspaceId: input.workspaceId,
3984
- eventType: "agent_run.created",
3985
- since: startOfUtcMonth()
3986
- });
3987
- const requested = input.quantity ?? 0;
3988
- return used + requested <= limits.maxMonthlyAgentRunsPerWorkspace ? { allowed: true } : blocked(
3989
- "max_monthly_agent_runs_per_workspace",
3990
- `monthly agent run limit reached (${limits.maxMonthlyAgentRunsPerWorkspace})`
3991
- );
3992
- }
3993
- case "tokens:consume": {
3994
- if (!funding.countsTowardTokenCap || !limits.maxMonthlyTokensPerWorkspace || !input.workspaceId) {
3995
- return { allowed: true };
3996
- }
3997
- const used = await sumUsageQuantity(deps.db, {
3998
- workspaceId: input.workspaceId,
3999
- eventType: "model.tokens",
4000
- since: startOfUtcMonth()
4001
- });
4002
- const requested = input.quantity ?? 0;
4003
- return used + requested <= limits.maxMonthlyTokensPerWorkspace ? { allowed: true } : blocked(
4004
- "max_monthly_tokens_per_workspace",
4005
- `monthly token limit reached (${limits.maxMonthlyTokensPerWorkspace})`
4006
- );
4007
- }
4008
- case "document:index": {
4009
- if (!limits.maxDocumentIndexedChunksPerWorkspace || !input.workspaceId) {
4010
- return { allowed: true };
4011
- }
4012
- const used = await sumUsageQuantity(deps.db, {
4013
- workspaceId: input.workspaceId,
4014
- eventType: "document.indexed",
4015
- since: startOfUtcMonth()
4016
- });
4017
- const requested = input.quantity ?? 0;
4018
- return used + requested <= limits.maxDocumentIndexedChunksPerWorkspace ? { allowed: true } : blocked(
4019
- "max_document_indexed_chunks_per_workspace",
4020
- `monthly document indexing limit reached (${limits.maxDocumentIndexedChunksPerWorkspace} chunks)`
4021
- );
4022
- }
4023
4393
  }
4394
+ const attribution = externalAttributionForAuthorization(authorization, grant);
4395
+ if (!attribution) return metadata;
4396
+ return { ...metadata, [EXTERNAL_CREATION_ATTRIBUTION_KEY]: attribution };
4024
4397
  }
4025
- async function recordWorkspaceUsage(deps, input) {
4026
- await recordUsageEvent(deps.db, {
4027
- accountId: input.accountId,
4028
- workspaceId: input.workspaceId,
4029
- subjectId: input.subjectId ?? null,
4030
- eventType: input.eventType,
4031
- quantity: input.quantity,
4032
- unit: input.unit,
4033
- sourceResourceType: input.sourceResourceType,
4034
- sourceResourceId: input.sourceResourceId,
4035
- sessionId: input.sessionId ?? null,
4036
- turnId: input.turnId ?? null,
4037
- turnAttemptId: input.turnAttemptId ?? null,
4038
- initiator: input.initiator ?? (input.subjectId ? { kind: "subject", subjectId: input.subjectId } : null),
4039
- ...input.initiatorContext ? { initiatorContext: input.initiatorContext } : {},
4040
- origin: input.origin ?? null,
4041
- idempotencyKey: input.idempotencyKey
4042
- });
4043
- }
4044
- function usesCreditLimits(deps) {
4045
- return deps.settings.billingMode === "stripe" || deps.settings.usageLimitsMode === "managed";
4046
- }
4047
- function isCostlyAction(action) {
4048
- return action === "agent_run:create" || action === "tokens:consume" || action === "document:index";
4398
+
4399
+ // src/application/external-link-work-admission.ts
4400
+ import { ExternalLinkWorkSnapshot } from "@opengeni/contracts/external-identities";
4401
+ import {
4402
+ captureExternalLinkTurnAuthority,
4403
+ captureExternalLinkTaskAuthority,
4404
+ getExternalLinkTurnSnapshot,
4405
+ getSessionTurnForAttempt as getSessionTurnForAttempt2
4406
+ } from "@opengeni/db";
4407
+ function snapshotFor(authorization) {
4408
+ const continuation = authorization ? externalActorContinuationForAuthorization(authorization) : null;
4409
+ return continuation?.actor.actingMode === "linked_native" ? ExternalLinkWorkSnapshot.parse({
4410
+ ...continuation,
4411
+ permissions: [...authorization.grant.permissions]
4412
+ }) : null;
4049
4413
  }
4050
- function blocked(code, message) {
4051
- return { allowed: false, code, message };
4414
+ function prepareExternalLinkTurnAdmission(authorization) {
4415
+ const snapshot = snapshotFor(authorization);
4416
+ if (!snapshot || !authorization) return void 0;
4417
+ const workspaceId = authorization.grant.workspaceId;
4418
+ const accountId = authorization.grant.accountId;
4419
+ const commit = externalContinuationCommitAuthorizer(authorization);
4420
+ return async (tx, sessionId, turnId) => {
4421
+ await commit(tx);
4422
+ await captureExternalLinkTurnAuthority(tx, {
4423
+ accountId,
4424
+ workspaceId,
4425
+ sessionId,
4426
+ turnId,
4427
+ snapshot
4428
+ });
4429
+ };
4052
4430
  }
4053
- function startOfUtcMonth() {
4054
- const now = /* @__PURE__ */ new Date();
4055
- return new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), 1));
4431
+ function prepareExternalLinkTaskAdmission(authorization, actor) {
4432
+ const snapshot = snapshotFor(authorization);
4433
+ const commit = externalContinuationCommitAuthorizer(authorization);
4434
+ if (snapshot)
4435
+ return async (tx, task) => {
4436
+ await commit?.(tx);
4437
+ await captureExternalLinkTaskAuthority(tx, task, snapshot);
4438
+ };
4439
+ if (!actor) {
4440
+ return authorization && hasVerifiedOwningUserAuthorization(authorization) ? async () => {
4441
+ } : void 0;
4442
+ }
4443
+ return async (tx, task) => {
4444
+ const turn = await getSessionTurnForAttempt2(
4445
+ tx,
4446
+ task.workspaceId,
4447
+ actor.sessionId,
4448
+ actor.attemptId
4449
+ );
4450
+ if (!turn || turn.id !== actor.turnId || turn.executionGeneration !== actor.executionGeneration)
4451
+ throw new Error("Linked task creator attempt is no longer active");
4452
+ const inherited = await getExternalLinkTurnSnapshot(tx, task, actor.turnId);
4453
+ if (inherited) await captureExternalLinkTaskAuthority(tx, task, inherited);
4454
+ };
4056
4455
  }
4057
4456
 
4058
4457
  // src/domain/native-mcp-connection-admission.ts
@@ -4071,6 +4470,7 @@ import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/
4071
4470
  import { isDeepStrictEqual } from "util";
4072
4471
  import { withLockedCapabilityInstallation } from "@opengeni/db/capability-reconciliation";
4073
4472
  import { environmentsEncryptionKeyBytes as environmentsEncryptionKeyBytes2 } from "@opengeni/config";
4473
+ import { pinnedFetch } from "@opengeni/network";
4074
4474
  import {
4075
4475
  CapabilityCatalogItem,
4076
4476
  capabilityCatalogItemIsTrustedForExposure,
@@ -4344,7 +4744,12 @@ async function prepareCapabilityEnable(input) {
4344
4744
  assertRequiredMcpCredentialHeaders(item, headers, connectionRef);
4345
4745
  installationMetadata = {
4346
4746
  ...installationMetadata,
4347
- ...connectionRef && !headers ? authDeferredMcpConnectivity() : await validateMcpCapabilityConnection(item, input.probeMcpServer, headers ?? void 0)
4747
+ ...connectionRef && !headers ? authDeferredMcpConnectivity() : await validateMcpCapabilityConnection(
4748
+ item,
4749
+ input.probeMcpServer,
4750
+ headers ?? void 0,
4751
+ input.settings
4752
+ )
4348
4753
  };
4349
4754
  if (connectionRef) {
4350
4755
  installationConfig.connectionRef = connectionRef;
@@ -4591,7 +4996,7 @@ function requireCapabilityHeaderEncryption(settings) {
4591
4996
  }
4592
4997
  return key;
4593
4998
  }
4594
- async function validateMcpCapabilityConnection(item, probe = probeStreamableHttpMcpServer, headers) {
4999
+ async function validateMcpCapabilityConnection(item, probe = probeStreamableHttpMcpServer, headers, settings) {
4595
5000
  if (item.kind !== "mcp") {
4596
5001
  return {};
4597
5002
  }
@@ -4606,7 +5011,8 @@ async function validateMcpCapabilityConnection(item, probe = probeStreamableHttp
4606
5011
  name: item.name,
4607
5012
  url: item.endpointUrl,
4608
5013
  timeoutMs: mcpCapabilityProbeTimeoutMs,
4609
- ...headers ? { headers } : {}
5014
+ ...headers ? { headers } : {},
5015
+ ...settings ? { settings } : {}
4610
5016
  });
4611
5017
  return {
4612
5018
  mcpConnectivity: {
@@ -4622,6 +5028,8 @@ async function validateMcpCapabilityConnection(item, probe = probeStreamableHttp
4622
5028
  }
4623
5029
  }
4624
5030
  async function probeStreamableHttpMcpServer(input) {
5031
+ const settings = input.settings;
5032
+ if (!settings) throw new Error("Network policy is unavailable for MCP validation");
4625
5033
  const controller = new AbortController();
4626
5034
  const timeout = setTimeout(() => controller.abort(), input.timeoutMs);
4627
5035
  const client = new Client(
@@ -4633,7 +5041,11 @@ async function probeStreamableHttpMcpServer(input) {
4633
5041
  requestInit: {
4634
5042
  signal: controller.signal,
4635
5043
  ...input.headers ? { headers: input.headers } : {}
4636
- }
5044
+ },
5045
+ fetch: (url, init) => pinnedFetch(url, init, settings, {
5046
+ label: "MCP capability probe",
5047
+ requireHttpsOutsideLocalTest: true
5048
+ })
4637
5049
  });
4638
5050
  await client.connect(transport, {
4639
5051
  timeout: input.timeoutMs,
@@ -5048,6 +5460,7 @@ function fikenCatalogItem(fikenConnections) {
5048
5460
  metadata: {
5049
5461
  connectorMode: "first_party_fiken",
5050
5462
  ownership: "workspace",
5463
+ connectionStatus: fikenConnection?.status ?? null,
5051
5464
  // Derived from the contracts catalog so a new fiken_* tool cannot be
5052
5465
  // registered without also appearing on the capability tile.
5053
5466
  firstPartyMcpTools: FIRST_PARTY_MCP_TOOL_NAMES.filter((name) => name.startsWith("fiken_"))
@@ -5249,15 +5662,15 @@ function socialProviderConnectionCounts(item) {
5249
5662
  };
5250
5663
  }
5251
5664
  function applyCapabilityEnablement(item, installation) {
5665
+ if (item.surfaceType === "first_party_fiken") {
5666
+ return { ...item, connectionRef: null };
5667
+ }
5252
5668
  if (item.kind === "skill" || item.kind === "api" || item.kind === "plugin") {
5253
5669
  return { ...item, enabled: false, enabledReason: null, connectionRef: null };
5254
5670
  }
5255
5671
  if (isSocialProviderIntegration(item)) {
5256
5672
  return { ...item, connectionRef: null };
5257
5673
  }
5258
- if (item.surfaceType === "first_party_fiken") {
5259
- return { ...item, connectionRef: null };
5260
- }
5261
5674
  if (item.surfaceType === "codex_apps") {
5262
5675
  return { ...item, connectionRef: null };
5263
5676
  }
@@ -7895,6 +8308,7 @@ async function createAndStartSessionWithOutcome(input) {
7895
8308
  ...input.scopeSubjectId !== void 0 ? { scopeSubjectId: input.scopeSubjectId } : {},
7896
8309
  ...input.memoryScope ? { memoryScope: input.memoryScope } : {},
7897
8310
  parentSessionId: input.parentSessionId ?? null,
8311
+ ...input.codeSearchDeploymentPolicy ? { codeSearchDeploymentPolicy: input.codeSearchDeploymentPolicy } : {},
7898
8312
  sandboxGroupId: input.sandboxGroupId ?? null,
7899
8313
  ...input.sandboxOs ? { sandboxOs: input.sandboxOs } : {},
7900
8314
  mcpServers: input.mcpServers ?? [],
@@ -8019,7 +8433,7 @@ function canonicalConfiguredModel(settings, model) {
8019
8433
  if (model === null || model === void 0) {
8020
8434
  return model;
8021
8435
  }
8022
- const canonicalModel = canonicalizeConfiguredModelId(settings, model);
8436
+ const canonicalModel = canonicalizeConfiguredModelId2(settings, model);
8023
8437
  if (canonicalModel.startsWith(CODEX_MODEL_ID_PREFIX) && settings.resolvedCodexModelsJson !== void 0) {
8024
8438
  if (settings.codexSubscriptionEnabled && configuredAllowedModels(withCodexCatalogProvider2(settings)).includes(canonicalModel)) {
8025
8439
  return canonicalModel;
@@ -8066,7 +8480,7 @@ async function assertWorkspaceModelPolicyAllows(db, settings, workspaceId, model
8066
8480
  if (canonicalModel === null || canonicalModel === void 0) {
8067
8481
  return;
8068
8482
  }
8069
- const policy = await getWorkspaceModelPolicy(db, workspaceId);
8483
+ const policy = await getWorkspaceModelPolicy2(db, workspaceId);
8070
8484
  if (!policy) {
8071
8485
  return;
8072
8486
  }
@@ -8548,7 +8962,7 @@ async function createSessionForRequestInFileScope(unresolvedDeps, grant, workspa
8548
8962
  throw error;
8549
8963
  }
8550
8964
  }
8551
- const parentSession = parentSessionId ? await getSession2(db, workspaceId, parentSessionId) : null;
8965
+ const parentSession = parentSessionId ? await getSession3(db, workspaceId, parentSessionId) : null;
8552
8966
  if (parentSessionId && !parentSession) {
8553
8967
  throw new HTTPException15(404, {
8554
8968
  message: `parent session not found in workspace: ${parentSessionId}`
@@ -8615,6 +9029,7 @@ async function createSessionForRequestInFileScope(unresolvedDeps, grant, workspa
8615
9029
  }
8616
9030
  const replayManagedHumanSubjectId = creationInitiator.actor ? parentCallingTurn?.initiatingHumanSubjectId ?? (parentCallingTurn?.initiator.kind === "subject" ? parentCallingTurn.initiator.subjectId : null) : authorization?.canonicalManagedHumanSession || grant.principalKind === "human_session" ? grant.subjectId : null;
8617
9031
  let retainedKeyedShellModel = null;
9032
+ let retainedKeyedShellReasoningEffort = null;
8618
9033
  if (payload.idempotencyKey && (effectiveVisibility !== "user_private" || replayManagedHumanSubjectId !== null)) {
8619
9034
  try {
8620
9035
  const initializedReplay = await getInitializedSessionCreateReplay(db, {
@@ -8639,6 +9054,7 @@ async function createSessionForRequestInFileScope(unresolvedDeps, grant, workspa
8639
9054
  }
8640
9055
  if (initializedReplay.outcome === "pending") {
8641
9056
  retainedKeyedShellModel = initializedReplay.session.model;
9057
+ retainedKeyedShellReasoningEffort = initializedReplay.session.reasoningEffort;
8642
9058
  } else {
8643
9059
  if (initializedReplay.workflowWakeRevision !== null) {
8644
9060
  await unresolvedDeps.workflowClient.wakeSessionWorkflow({
@@ -8696,7 +9112,13 @@ async function createSessionForRequestInFileScope(unresolvedDeps, grant, workspa
8696
9112
  payload.personalResourceAttachment,
8697
9113
  false
8698
9114
  );
8699
- const inheritedModel = parentCallingTurn?.model ?? parentSession?.model ?? settings.openaiModel;
9115
+ const resolvedDefault = parentSession || payload.model !== void 0 ? null : retainedKeyedShellModel !== null && retainedKeyedShellReasoningEffort !== null ? { model: retainedKeyedShellModel, reasoningEffort: retainedKeyedShellReasoningEffort } : await resolveDefaultSessionModel(db, settings, {
9116
+ accountId: grant.accountId,
9117
+ workspaceId,
9118
+ subjectId: grant.subjectId,
9119
+ workspaceSettings: workspace.settings
9120
+ });
9121
+ const inheritedModel = parentCallingTurn?.model ?? parentSession?.model ?? resolvedDefault?.model ?? settings.openaiModel;
8700
9122
  const effectiveModelId = payload.model ?? inheritedModel;
8701
9123
  const effectiveCatalogSettings = await resolveWorkspaceModelBoundarySettings(
8702
9124
  deps,
@@ -8950,7 +9372,7 @@ async function createSessionForRequestInFileScope(unresolvedDeps, grant, workspa
8950
9372
  throw new Error("effective session model unexpectedly resolved to null");
8951
9373
  }
8952
9374
  await assertWorkspaceModelPolicyAllows(db, settings, workspaceId, model);
8953
- const inheritedReasoningEffort = parentCallingTurn?.reasoningEffort ?? parentSession?.reasoningEffort ?? settings.openaiReasoningEffort;
9375
+ const inheritedReasoningEffort = parentCallingTurn?.reasoningEffort ?? parentSession?.reasoningEffort ?? resolvedDefault?.reasoningEffort ?? settings.openaiReasoningEffort;
8954
9376
  const inheritedLatencyMode = parentCallingTurn?.latencyMode ?? parentSession?.latencyMode ?? "standard";
8955
9377
  const reasoningEffort = payload.reasoningEffort ?? inheritedReasoningEffort;
8956
9378
  const latencyMode = payload.latencyMode ?? inheritedLatencyMode;
@@ -9238,6 +9660,7 @@ async function createSessionForRequestInFileScope(unresolvedDeps, grant, workspa
9238
9660
  db,
9239
9661
  bus,
9240
9662
  workflowClient,
9663
+ codeSearchDeploymentPolicy: codeSearchDeploymentPolicy(deps.settings),
9241
9664
  accountId: grant.accountId,
9242
9665
  workspaceId,
9243
9666
  visibility: effectiveVisibility,
@@ -10094,7 +10517,7 @@ async function readSessionLineage(deps, grant, sessionId) {
10094
10517
  surface: "core"
10095
10518
  });
10096
10519
  if (authorization?.relatedSessionAccess === "target") {
10097
- const session = await getSession2(deps.db, grant.workspaceId, sessionId);
10520
+ const session = await getSession3(deps.db, grant.workspaceId, sessionId);
10098
10521
  if (!session) {
10099
10522
  throw new HTTPException15(404, { message: "session not found" });
10100
10523
  }
@@ -10136,6 +10559,39 @@ async function acceptSessionUserMessageWithOutcome(...args) {
10136
10559
  return withSessionRlsActorContext4(actor, () => acceptSessionUserMessageInFileScope(...args));
10137
10560
  }
10138
10561
 
10562
+ // src/domain/session-native-connection-replacement.ts
10563
+ import { connectionMetadataMatchesBinding } from "@opengeni/db/session-mcp-credential-rotation";
10564
+ function nativeSessionConnectionReplacement(input) {
10565
+ const connection = input.connections.find(
10566
+ (candidate) => candidate.id === input.nativeConnectionId
10567
+ );
10568
+ if (!connection || connection.accountId !== input.accountId || connection.status !== "active" || (connection.subjectId === null ? connection.workspaceId !== input.workspaceId : !input.subjectId || connection.subjectId !== input.subjectId || !connection.authorityId)) {
10569
+ throw new Error("native connection unavailable");
10570
+ }
10571
+ const {
10572
+ authoritySource: _authoritySource,
10573
+ hostBinding: _hostBinding,
10574
+ accountSelection: _accountSelection,
10575
+ ...retained
10576
+ } = input.currentRef ?? {};
10577
+ if (input.currentRef && input.currentRef.providerDomain.toLowerCase() !== connection.providerDomain.toLowerCase())
10578
+ throw new Error("native connection provider mismatch");
10579
+ const ref = {
10580
+ ...retained,
10581
+ ...!input.currentRef?.resource && typeof connection.metadata.resource === "string" ? { resource: connection.metadata.resource } : {},
10582
+ connectionId: connection.id,
10583
+ providerDomain: connection.providerDomain,
10584
+ kind: connection.kind,
10585
+ subjectScope: connection.subjectId === null ? "workspace" : "subject"
10586
+ };
10587
+ const destination = input.replacementServerUrl ?? input.serverUrl;
10588
+ if (input.replacementServerUrl && (typeof connection.metadata.mcpUrl !== "string" || !connection.metadata.mcpUrl.trim()))
10589
+ throw new Error("native connection destination unavailable");
10590
+ if (!connectionMetadataMatchesBinding(connection, ref, destination))
10591
+ throw new Error("native connection binding mismatch");
10592
+ return ref;
10593
+ }
10594
+
10139
10595
  // src/application/session-mcp-credential-rotation.ts
10140
10596
  function sessionMcpRotationFingerprint(key, scope, request) {
10141
10597
  return {
@@ -10167,9 +10623,14 @@ async function rotateSessionMcpCredentialsForRequest(deps, authorization, sessio
10167
10623
  id: update.id,
10168
10624
  expectedCredentialVersion: update.expectedCredentialVersion,
10169
10625
  expectedServerUrl: update.expectedServerUrl,
10170
- headers: Object.fromEntries(
10171
- Object.entries(normalizedSessionMcpCredentialHeaders(update.headers)).map(([name, value]) => [name.toLowerCase(), value]).sort(([left], [right]) => left < right ? -1 : left > right ? 1 : 0)
10172
- )
10626
+ ..."nativeConnectionId" in update ? {
10627
+ nativeConnectionId: update.nativeConnectionId,
10628
+ ...update.replacementServerUrl ? { replacementServerUrl: update.replacementServerUrl } : {}
10629
+ } : {
10630
+ headers: Object.fromEntries(
10631
+ Object.entries(normalizedSessionMcpCredentialHeaders(update.headers)).map(([name, value]) => [name.toLowerCase(), value]).sort(([left], [right]) => left < right ? -1 : left > right ? 1 : 0)
10632
+ )
10633
+ }
10173
10634
  })).sort((left, right) => left.id < right.id ? -1 : left.id > right.id ? 1 : 0)
10174
10635
  };
10175
10636
  if (new Set(request.updates.map((update) => update.id)).size !== request.updates.length)
@@ -10185,20 +10646,43 @@ async function rotateSessionMcpCredentialsForRequest(deps, authorization, sessio
10185
10646
  actorType: grant.principalKind === "service" ? "service" : "human"
10186
10647
  };
10187
10648
  const externalAuthorize = externalContinuationCommitAuthorizer(authorization);
10649
+ let authorizedGrant = grant;
10188
10650
  try {
10189
10651
  return await rotateSessionMcpCredentialsAtomically(deps.db, {
10190
10652
  ...scope,
10191
10653
  operationKey: request.operationKey,
10192
10654
  ...sessionMcpRotationFingerprint(encryptionKey, scope, request),
10193
- updates: request.updates.map(({ headers, ...update }) => ({
10194
- ...update,
10195
- headersEncrypted: Object.fromEntries(
10196
- Object.entries(headers).map(([name, value]) => [
10197
- name,
10198
- encryptVariableSetValue3(encryptionKey, value)
10199
- ])
10200
- )
10201
- })),
10655
+ updates: request.updates.map(
10656
+ (update) => "nativeConnectionId" in update ? update : {
10657
+ id: update.id,
10658
+ expectedCredentialVersion: update.expectedCredentialVersion,
10659
+ expectedServerUrl: update.expectedServerUrl,
10660
+ headersEncrypted: Object.fromEntries(
10661
+ Object.entries(update.headers).map(([name, value]) => [
10662
+ name,
10663
+ encryptVariableSetValue3(encryptionKey, value)
10664
+ ])
10665
+ )
10666
+ }
10667
+ ),
10668
+ resolveNativeConnection: async (tx, server, nativeConnectionId, replacementServerUrl) => {
10669
+ const connections = await listOwnConnectionAccountsForGrant(tx, authorizedGrant);
10670
+ const source = personalConnectionDelegationSourceForGrant(authorizedGrant);
10671
+ try {
10672
+ return nativeSessionConnectionReplacement({
10673
+ accountId: grant.accountId,
10674
+ workspaceId: grant.workspaceId,
10675
+ subjectId: source.kind === "subject" ? source.subjectId : null,
10676
+ serverUrl: server.url,
10677
+ ...replacementServerUrl ? { replacementServerUrl } : {},
10678
+ currentRef: server.connectionRef,
10679
+ nativeConnectionId,
10680
+ connections
10681
+ });
10682
+ } catch {
10683
+ throw new SessionMcpCredentialRotationError("connection_unavailable");
10684
+ }
10685
+ },
10202
10686
  authorize: async (tx) => {
10203
10687
  await externalAuthorize?.(tx);
10204
10688
  const fresh = await reauthorize(tx);
@@ -10221,6 +10705,7 @@ async function rotateSessionMcpCredentialsForRequest(deps, authorization, sessio
10221
10705
  operation: "session.mcp.credentials.rotate",
10222
10706
  surface: "http"
10223
10707
  });
10708
+ authorizedGrant = fresh;
10224
10709
  }
10225
10710
  });
10226
10711
  } catch (error) {
@@ -10231,7 +10716,7 @@ async function rotateSessionMcpCredentialsForRequest(deps, authorization, sessio
10231
10716
  if (error instanceof SessionAuthorizationUnavailableError)
10232
10717
  throw new HTTPException16(503, { message: "credential rotation authorization unavailable" });
10233
10718
  if (error instanceof SessionMcpCredentialRotationError) {
10234
- const status = error.code === "receipt_key_unavailable" ? 503 : error.code === "authority_revoked" ? 403 : error.code === "not_found" ? 404 : error.code === "invalid_request" || error.code === "brokered_server" ? 422 : 409;
10719
+ const status = error.code === "receipt_key_unavailable" ? 503 : error.code === "authority_revoked" ? 403 : error.code === "not_found" ? 404 : error.code === "invalid_request" || error.code === "brokered_server" || error.code === "connection_unavailable" ? 422 : 409;
10235
10720
  throw new HTTPException16(status, { message: `credential_rotation_${error.code}` });
10236
10721
  }
10237
10722
  throw new HTTPException16(503, { message: "credential rotation unavailable" });
@@ -10672,7 +11157,7 @@ function sha256Hex2(bytes) {
10672
11157
  }
10673
11158
 
10674
11159
  // src/domain/skill-search.ts
10675
- import { pinnedFetch, readResponseJsonBounded } from "@opengeni/network";
11160
+ import { pinnedFetch as pinnedFetch2, readResponseJsonBounded } from "@opengeni/network";
10676
11161
  var PublicSkillSearchError = class extends Error {
10677
11162
  constructor(code, message, retryAfterSeconds = null) {
10678
11163
  super(message);
@@ -10687,7 +11172,7 @@ var maxResponseBytes = 256 * 1024;
10687
11172
  var maxResults = 20;
10688
11173
  var ownerPattern = /^[a-z0-9](?:[a-z0-9-]{0,38})$/iu;
10689
11174
  var segmentPattern = /^[a-z0-9](?:[a-z0-9._-]{0,98}[a-z0-9])?$/iu;
10690
- function createPublicSkillSearchClient(settings, fetcher = pinnedFetch) {
11175
+ function createPublicSkillSearchClient(settings, fetcher = pinnedFetch2) {
10691
11176
  return {
10692
11177
  async search(input) {
10693
11178
  const query = input.query.trim();
@@ -10814,7 +11299,7 @@ function parseRetryAfter(value) {
10814
11299
 
10815
11300
  // src/domain/github-skill-source.ts
10816
11301
  import { HTTPException as HTTPException19 } from "hono/http-exception";
10817
- import { pinnedFetch as pinnedFetch2, readResponseJsonBounded as readResponseJsonBounded2, readResponseTextBounded } from "@opengeni/network";
11302
+ import { pinnedFetch as pinnedFetch3, readResponseJsonBounded as readResponseJsonBounded2, readResponseTextBounded } from "@opengeni/network";
10818
11303
  import {
10819
11304
  PORTABLE_SKILL_MAX_FILES as PORTABLE_SKILL_MAX_FILES2,
10820
11305
  PORTABLE_SKILL_MAX_FILE_BYTES as PORTABLE_SKILL_MAX_FILE_BYTES2,
@@ -10915,7 +11400,7 @@ function createGitHubSkillSourceClient(settings, requestJson = (path, maxBytes,
10915
11400
  }
10916
11401
  async function downloadSkillSnapshot(settings, owner, repository, slug) {
10917
11402
  const signal = AbortSignal.timeout(githubRequestTimeoutMs);
10918
- const response = await pinnedFetch2(
11403
+ const response = await pinnedFetch3(
10919
11404
  `https://skills.sh/api/download/${[owner, repository, slug].map(encodeURIComponent).join("/")}`,
10920
11405
  { headers: { accept: "application/json" }, credentials: "omit", redirect: "manual", signal },
10921
11406
  settings,
@@ -10950,7 +11435,7 @@ async function githubJson(settings, path, maxBytes, label) {
10950
11435
  const controller = new AbortController();
10951
11436
  const timeout = setTimeout(() => controller.abort(), githubRequestTimeoutMs);
10952
11437
  try {
10953
- const response = await pinnedFetch2(
11438
+ const response = await pinnedFetch3(
10954
11439
  `${githubApiBase}${path}`,
10955
11440
  {
10956
11441
  method: "GET",
@@ -12409,10 +12894,10 @@ import {
12409
12894
  getRig as getRig4,
12410
12895
  getScheduledTask,
12411
12896
  getScheduledTaskIncludingDeletedForUpdate,
12412
- getScheduledTaskXaiProviderAccountAuthoritySnapshot,
12897
+ getScheduledTaskXaiProviderAccountAuthoritySnapshot as getScheduledTaskXaiProviderAccountAuthoritySnapshot2,
12413
12898
  getSandbox as getSandbox4,
12414
12899
  getSessionTurnXaiProviderAccountAuthoritySnapshot as getSessionTurnXaiProviderAccountAuthoritySnapshot2,
12415
- getSession as getSession3,
12900
+ getSession as getSession4,
12416
12901
  getSessionAuthorityProjection as getSessionAuthorityProjection5,
12417
12902
  withSessionRlsActorContext as withSessionRlsActorContext5,
12418
12903
  nestedPostgresSqlState as nestedPostgresSqlState6,
@@ -12669,7 +13154,7 @@ async function createValidatedScheduledTask(input) {
12669
13154
  );
12670
13155
  }
12671
13156
  async function frozenScheduledTaskCreatorPolicy(input) {
12672
- const session = await getSession3(input.db, input.grant.workspaceId, input.sessionId);
13157
+ const session = await getSession4(input.db, input.grant.workspaceId, input.sessionId);
12673
13158
  if (!session) {
12674
13159
  throw new HTTPException21(403, {
12675
13160
  message: "the calling agent session is not available in this workspace"
@@ -12867,7 +13352,7 @@ async function validateScheduledTaskTarget(input) {
12867
13352
  }
12868
13353
  throw error;
12869
13354
  }
12870
- const session = await getSession3(input.db, input.grant.workspaceId, input.targetSessionId);
13355
+ const session = await getSession4(input.db, input.grant.workspaceId, input.targetSessionId);
12871
13356
  if (!session || session.accountId !== input.grant.accountId) {
12872
13357
  throw new HTTPException21(404, { message: "target session not found" });
12873
13358
  }
@@ -13139,7 +13624,7 @@ async function validatedScheduledTaskUpdate(input) {
13139
13624
  });
13140
13625
  if (beforeUpdateCommit) update.beforeUpdateCommit = beforeUpdateCommit;
13141
13626
  }
13142
- const existingXaiAuthority = await getScheduledTaskXaiProviderAccountAuthoritySnapshot(
13627
+ const existingXaiAuthority = await getScheduledTaskXaiProviderAccountAuthoritySnapshot2(
13143
13628
  input.db,
13144
13629
  input.existing.workspaceId,
13145
13630
  input.existing.id
@@ -13429,7 +13914,7 @@ function manualScheduledTaskTriggerUsageKey(workspaceId, taskId, triggerToken) {
13429
13914
  }
13430
13915
  async function validateScheduledTaskAgentConfig(input) {
13431
13916
  const actor = scheduledTaskInitiatorForGrant(input.grant).actor;
13432
- const parent = actor ? await getSession3(input.db, input.workspaceId, actor.sessionId) : null;
13917
+ const parent = actor ? await getSession4(input.db, input.workspaceId, actor.sessionId) : null;
13433
13918
  if (actor && (!parent || parent.accountId !== input.grant.accountId)) {
13434
13919
  throw new HTTPException21(403, {
13435
13920
  message: "Scheduled Skill selection requires the creating agent's session"
@@ -15974,6 +16459,7 @@ import {
15974
16459
  getSandbox as getSandbox5,
15975
16460
  getVariableSet as getVariableSet3,
15976
16461
  NewSessionDraftAccessError,
16462
+ newSessionDraftModelProvided,
15977
16463
  newSessionDraftSelectedProjectChannelId,
15978
16464
  newSessionDraftToolsProvided,
15979
16465
  newSessionSelectionHistory,
@@ -15984,6 +16470,7 @@ import {
15984
16470
  withWorkspaceSubjectRls as withWorkspaceSubjectRls6
15985
16471
  } from "@opengeni/db";
15986
16472
  import { HTTPException as HTTPException23 } from "hono/http-exception";
16473
+ import { canonicalizeConfiguredModelId as canonicalizeConfiguredModelId3 } from "@opengeni/config";
15987
16474
  function hasOwn(value, key) {
15988
16475
  return typeof value === "object" && value !== null && Object.hasOwn(value, key);
15989
16476
  }
@@ -15999,16 +16486,39 @@ function mapNewSessionDraft(row) {
15999
16486
  model: row.model,
16000
16487
  reasoningEffort: row.reasoningEffort,
16001
16488
  latencyMode: row.latencyMode,
16489
+ ...newSessionDraftModelProvided(row) !== void 0 ? { modelProvided: newSessionDraftModelProvided(row) } : {},
16002
16490
  ...selectedProjectChannelId !== void 0 ? { selectedProjectChannelId } : {},
16003
16491
  options: publicNewSessionDraftOptions(row),
16004
16492
  selectionHistory: newSessionSelectionHistory(row),
16005
16493
  updatedAt: row.updatedAt.toISOString()
16006
16494
  });
16007
16495
  }
16008
- async function hydrateNewSessionDraft(deps, grant, workspaceId, row) {
16496
+ function draftModelProvided(settings, draft) {
16497
+ if (draft.modelProvided !== void 0) return draft.modelProvided;
16498
+ return !(canonicalizeConfiguredModelId3(settings, draft.model) === canonicalizeConfiguredModelId3(settings, settings.openaiModel) && draft.reasoningEffort === settings.openaiReasoningEffort && draft.latencyMode === "standard");
16499
+ }
16500
+ async function actorDefaultModel(deps, grant, workspaceId) {
16501
+ return await resolveDefaultSessionModel(deps.db, deps.settings, {
16502
+ accountId: grant.accountId,
16503
+ workspaceId,
16504
+ subjectId: grant.subjectId
16505
+ });
16506
+ }
16507
+ async function hydrateNewSessionDraft(deps, grant, workspaceId, row, readOptions = {}) {
16009
16508
  if (!row) return null;
16010
- const mapped = mapNewSessionDraft(row);
16011
- if (!mapped) return null;
16509
+ const stored = mapNewSessionDraft(row);
16510
+ if (!stored) return null;
16511
+ const modelProvided = draftModelProvided(deps.settings, stored);
16512
+ let mapped = { ...stored, modelProvided };
16513
+ if (!modelProvided && readOptions.projectDefaultModel !== false) {
16514
+ const resolved = await actorDefaultModel(deps, grant, workspaceId);
16515
+ mapped = {
16516
+ ...mapped,
16517
+ model: resolved.model,
16518
+ reasoningEffort: resolved.reasoningEffort,
16519
+ latencyMode: resolved.model === stored.model ? stored.latencyMode : "standard"
16520
+ };
16521
+ }
16012
16522
  const runtimeSettings = await settingsWithEnabledCapabilityMcpServers(
16013
16523
  deps.db,
16014
16524
  workspaceId,
@@ -16098,7 +16608,7 @@ async function hydrateNewSessionDraft(deps, grant, workspaceId, row) {
16098
16608
  options
16099
16609
  };
16100
16610
  }
16101
- async function getActorNewSessionDraftInFileScope(deps, grant, workspaceId) {
16611
+ async function getActorNewSessionDraftInFileScope(deps, grant, workspaceId, readOptions = {}) {
16102
16612
  const row = await withWorkspaceSubjectRls6(
16103
16613
  deps.db,
16104
16614
  workspaceId,
@@ -16108,15 +16618,19 @@ async function getActorNewSessionDraftInFileScope(deps, grant, workspaceId) {
16108
16618
  subjectId: grant.subjectId
16109
16619
  })
16110
16620
  );
16111
- return await hydrateNewSessionDraft(deps, grant, workspaceId, row) ?? {
16621
+ const hydrated = await hydrateNewSessionDraft(deps, grant, workspaceId, row, readOptions);
16622
+ if (hydrated) return hydrated;
16623
+ const resolved = readOptions.projectDefaultModel === false ? { model: deps.settings.openaiModel, reasoningEffort: deps.settings.openaiReasoningEffort } : await actorDefaultModel(deps, grant, workspaceId);
16624
+ return {
16112
16625
  revision: 0,
16113
16626
  text: "",
16114
16627
  resources: [],
16115
16628
  tools: [],
16116
16629
  toolsProvided: false,
16117
- model: deps.settings.openaiModel,
16118
- reasoningEffort: deps.settings.openaiReasoningEffort,
16630
+ model: resolved.model,
16631
+ reasoningEffort: resolved.reasoningEffort,
16119
16632
  latencyMode: "standard",
16633
+ modelProvided: false,
16120
16634
  options: {},
16121
16635
  selectionHistory: { projects: [] },
16122
16636
  updatedAt: null
@@ -16167,6 +16681,7 @@ async function saveActorNewSessionDraftInFileScope(deps, grant, workspaceId, raw
16167
16681
  model: input.model,
16168
16682
  reasoningEffort: input.reasoningEffort,
16169
16683
  latencyMode: input.latencyMode,
16684
+ ...input.modelProvided !== void 0 ? { modelProvided: input.modelProvided } : {},
16170
16685
  ...input.selectedProjectChannelId !== void 0 ? { selectedProjectChannelId: input.selectedProjectChannelId } : {},
16171
16686
  options: input.options,
16172
16687
  // Only managed people are removed through removeWorkspaceMember().
@@ -16182,7 +16697,8 @@ async function saveActorNewSessionDraftInFileScope(deps, grant, workspaceId, raw
16182
16697
  })
16183
16698
  )
16184
16699
  );
16185
- return mapNewSessionDraft(saved);
16700
+ const mapped = mapNewSessionDraft(saved);
16701
+ return { ...mapped, modelProvided: draftModelProvided(deps.settings, mapped) };
16186
16702
  } catch (error) {
16187
16703
  if (error instanceof NewSessionDraftAccessError) {
16188
16704
  throw new HTTPException23(403, { message: error.message });
@@ -16190,11 +16706,11 @@ async function saveActorNewSessionDraftInFileScope(deps, grant, workspaceId, raw
16190
16706
  throw error;
16191
16707
  }
16192
16708
  }
16193
- async function getActorNewSessionDraft(deps, grant, workspaceId, authorization) {
16709
+ async function getActorNewSessionDraft(deps, grant, workspaceId, authorization, readOptions = {}) {
16194
16710
  const actor = authorization ? await fileOwnerContextForAccess(deps, authorization, "sessions:read") : { subjectId: grant.subjectId, privateFileOwnerSubjectId: null };
16195
16711
  return withSessionRlsActorContext6(
16196
16712
  actor,
16197
- () => getActorNewSessionDraftInFileScope(deps, grant, workspaceId)
16713
+ () => getActorNewSessionDraftInFileScope(deps, grant, workspaceId, readOptions)
16198
16714
  );
16199
16715
  }
16200
16716
  async function saveActorNewSessionDraft(...args) {
@@ -16203,11 +16719,15 @@ async function saveActorNewSessionDraft(...args) {
16203
16719
  return withSessionRlsActorContext6(actor, () => saveActorNewSessionDraftInFileScope(...args));
16204
16720
  }
16205
16721
  async function getActorNewSessionDefaults(deps, grant, workspaceId) {
16206
- const draft = await getActorNewSessionDraft(deps, grant, workspaceId);
16722
+ const draft = await getActorNewSessionDraft(deps, grant, workspaceId, void 0, {
16723
+ projectDefaultModel: false
16724
+ });
16207
16725
  const options = draft.options;
16208
16726
  return {
16209
- // Revision zero is a synthetic empty form, not a user's model preference.
16210
- ...draft.revision > 0 ? {
16727
+ // Only a model the person chose is carried over. A draft that follows the
16728
+ // default (including the synthetic revision-zero form) leaves the model
16729
+ // out, so session creation resolves the same default itself.
16730
+ ...draft.revision > 0 && draft.modelProvided === true ? {
16211
16731
  model: draft.model,
16212
16732
  reasoningEffort: draft.reasoningEffort,
16213
16733
  latencyMode: draft.latencyMode
@@ -16270,7 +16790,7 @@ import {
16270
16790
  deleteSessionQueueItemInTransaction,
16271
16791
  editQueuedTurnInTransaction,
16272
16792
  getComposerDraftInTransaction,
16273
- getSession as getSession4,
16793
+ getSession as getSession5,
16274
16794
  getSessionEvent as getSessionEvent3,
16275
16795
  getWorkspaceControlEvent as getWorkspaceControlEvent2,
16276
16796
  getSessionQueueSnapshot,
@@ -16968,7 +17488,7 @@ async function getHumanComposerDraft(deps, context) {
16968
17488
  );
16969
17489
  const mapped = composerDraft(row);
16970
17490
  if (mapped) return mapped;
16971
- const session = await getSession4(deps.db, context.workspaceId, context.sessionId);
17491
+ const session = await getSession5(deps.db, context.workspaceId, context.sessionId);
16972
17492
  if (!session) throw new Error(`Session not found: ${context.sessionId}`);
16973
17493
  return {
16974
17494
  revision: 0,
@@ -17339,7 +17859,7 @@ var CATALOG_PAGE_SIZE = 25;
17339
17859
  var CATALOG_PAGE_BUDGET = 40;
17340
17860
  var DESCRIPTION_CHARS = 2e3;
17341
17861
  var CATALOG_BYTES = 256 * 1024;
17342
- async function prepareKnowledgeSave(db, context, input, embedder, services = defaults) {
17862
+ async function prepareKnowledgeSave(db, context, input, embedder, services = defaults, settings) {
17343
17863
  const request = KnowledgeSavePreparationRequest.parse(input);
17344
17864
  if (context.actor.kind !== "agent" && !(context.actor.kind === "human" && context.actor.review)) {
17345
17865
  throw Object.assign(
@@ -17364,20 +17884,31 @@ async function prepareKnowledgeSave(db, context, input, embedder, services = def
17364
17884
  complete: true,
17365
17885
  nextCursors: { published: null, needs_review: null }
17366
17886
  };
17367
- const matches = {
17368
- published: await services.search(
17369
- db,
17370
- context,
17371
- { query: request.query, limit: request.limit, view: "published" },
17372
- sharedEmbedder
17373
- ),
17374
- needs_review: await services.search(
17375
- db,
17376
- context,
17377
- { query: request.query, limit: request.limit, view: "needs_review" },
17378
- sharedEmbedder
17379
- )
17380
- };
17887
+ const paid = settings != null && paidDocumentEmbedding(settings);
17888
+ const published = await services.search(
17889
+ db,
17890
+ context,
17891
+ {
17892
+ query: request.query,
17893
+ limit: request.limit,
17894
+ view: "published",
17895
+ ...paid ? { mode: "keyword" } : {}
17896
+ },
17897
+ sharedEmbedder,
17898
+ paid ? void 0 : settings
17899
+ );
17900
+ const needsReview = await services.search(
17901
+ db,
17902
+ context,
17903
+ {
17904
+ query: request.query,
17905
+ limit: request.limit,
17906
+ view: "needs_review",
17907
+ ...published.searchMode === "keyword" ? { mode: "keyword" } : {}
17908
+ },
17909
+ sharedEmbedder
17910
+ );
17911
+ const matches = { published, needs_review: needsReview };
17381
17912
  for (const view of ["published", "needs_review"]) {
17382
17913
  if (request.collectionCursors && request.collectionCursors[view] === null) continue;
17383
17914
  let cursor = request.collectionCursors?.[view] ?? void 0;
@@ -17786,6 +18317,8 @@ export {
17786
18317
  InMemoryEditableArtifactLiveTicketStore,
17787
18318
  InMemoryEditableArtifactStableIdFactory,
17788
18319
  InMemoryEditableArtifactStore,
18320
+ KnowledgeVectorFundingError,
18321
+ KnowledgeVectorQueryRejectedError,
17789
18322
  MAX_CHECKS_PER_RIG,
17790
18323
  MAX_CREDENTIAL_HOOKS_PER_RIG,
17791
18324
  MAX_DEFAULT_VARIABLE_SETS_PER_RIG,
@@ -17896,6 +18429,7 @@ export {
17896
18429
  causalFrontierDominates,
17897
18430
  causalFrontiersEqual,
17898
18431
  checkLimit,
18432
+ clampReasoningEffortForConfiguredModel,
17899
18433
  classifyRigVerificationOutcome,
17900
18434
  codexAppsCatalogItem,
17901
18435
  compareCodeUnits,
@@ -17921,10 +18455,12 @@ export {
17921
18455
  createSessionForRequestWithOutcome,
17922
18456
  createValidatedScheduledTask,
17923
18457
  creationInitiatorForGrant,
18458
+ creditsDefaultSessionModel,
17924
18459
  decodeEditableArtifactBrokerHint,
17925
18460
  decodeEditableArtifactLiveClientWireFrame,
17926
18461
  decodeEditableArtifactLiveServerWireFrame,
17927
18462
  defaultPrReviewProviderBaseUrl,
18463
+ defaultReasoningEffortForConfiguredModel,
17928
18464
  defaultSessionMcpServerIds,
17929
18465
  defaultVideoGenerationPolicy,
17930
18466
  deleteHumanQueuePrompt,
@@ -17934,6 +18470,8 @@ export {
17934
18470
  directRetainedProcessMatchesBackend,
17935
18471
  disableCapability,
17936
18472
  discoverMcpRegistryCapabilities,
18473
+ documentEmbeddingCostMicros,
18474
+ draftModelProvided,
17937
18475
  editHumanQueuePrompt,
17938
18476
  editableArtifactActorKey,
17939
18477
  editableArtifactAuthorizationRevisionPortFromPostgres,
@@ -18038,6 +18576,7 @@ export {
18038
18576
  listRigVersionsForApi,
18039
18577
  listSkills,
18040
18578
  loadRigDefaultVariableSetEnvironment,
18579
+ loadWorkspaceModelSelectionInput,
18041
18580
  lockActiveCustomModelForAdmission,
18042
18581
  lookupExternalIdentityForRequest,
18043
18582
  managedSessionGroupBackend,
@@ -18076,6 +18615,7 @@ export {
18076
18615
  openGeniSlackBotMetadata,
18077
18616
  organizationIntegrationCatalog,
18078
18617
  organizationMembershipHttpStatus,
18618
+ paidDocumentEmbedding,
18079
18619
  parseGitHubRepositoryCoordinates,
18080
18620
  parseSkillSource,
18081
18621
  personalAtlassianDelegationsFromVisibleConnections,
@@ -18155,12 +18695,16 @@ export {
18155
18695
  resolveCatalogSettings,
18156
18696
  resolveChildGoalFromAcceptedSnapshot,
18157
18697
  resolveCodexAppsCredentialIdForRun,
18698
+ resolveDefaultSessionModel,
18699
+ resolveDefaultSessionModelForSelections,
18158
18700
  resolveFikenDefaultCompanySlug,
18159
18701
  resolveFirstPartyMcpToolsForCreate,
18160
18702
  resolveGitHubRepositoryBindings,
18161
18703
  resolveMemberSubjectId,
18162
18704
  resolveRigProviderImageForRun,
18163
18705
  resolveRigProviderImageSelection,
18706
+ resolveScheduledTaskDefaultModel,
18707
+ resolveScheduledTaskPreflightModel,
18164
18708
  resolveSessionCreateScope,
18165
18709
  resolveSessionCreateVisibility,
18166
18710
  resolveSessionSandboxRuntime,
@@ -18201,6 +18745,7 @@ export {
18201
18745
  scheduledTaskTriggerToken,
18202
18746
  searchCapabilityCatalogItems,
18203
18747
  searchKnowledgeEntries,
18748
+ selectDefaultSessionModel,
18204
18749
  selectedPersonalConnectionServers,
18205
18750
  sendAgentSessionMessage,
18206
18751
  sessionGroupMachinePresentation,