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