@opengeni/api-router 3.1.3-canary.38890816741001 → 3.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/dist/app.js +1 -1
  2. package/dist/{chunk-OT56OY4V.js → chunk-6CECHDZP.js} +1569 -399
  3. package/dist/{chunk-OT56OY4V.js.map → chunk-6CECHDZP.js.map} +1 -1
  4. package/dist/index.js +50 -2
  5. package/dist/index.js.map +1 -1
  6. package/dist/integrations/external-vault-providers.d.ts +29 -0
  7. package/dist/interaction-secrets-vault.d.ts +2 -2
  8. package/dist/mcp/action-descriptions.d.ts +1 -1
  9. package/dist/mcp/scheduled-task-view.d.ts +4 -4
  10. package/dist/routes/vault-providers.d.ts +4 -2
  11. package/dist/sandbox/channel-a.d.ts +10 -1
  12. package/dist/shutdown.d.ts +14 -0
  13. package/dist/site-publishing/agent-data-tools.d.ts +5 -5
  14. package/dist/site-publishing/agent-session.d.ts +3 -2
  15. package/dist/site-publishing/runtime.d.ts +7 -6
  16. package/dist/site-publishing/service.d.ts +8 -11
  17. package/dist/site-publishing/session-request-authority.d.ts +3 -0
  18. package/dist/workspace-tool-gateway-secrets.d.ts +1 -1
  19. package/package.json +25 -22
  20. package/src/access-grant-rls.ts +1 -0
  21. package/src/app.ts +14 -2
  22. package/src/http/sse.ts +5 -1
  23. package/src/index.ts +13 -1
  24. package/src/integrations/external-vault-providers.ts +136 -0
  25. package/src/interaction-secrets-vault.ts +6 -2
  26. package/src/mcp/action-catalog.gen.ts +253 -4
  27. package/src/mcp/action-descriptions.ts +32 -2
  28. package/src/mcp/action-schema-imports.gen.ts +3 -1
  29. package/src/routes/browser-sessions.ts +61 -17
  30. package/src/routes/computer-sessions.ts +102 -39
  31. package/src/routes/connections.ts +17 -0
  32. package/src/routes/insights-usage.ts +22 -0
  33. package/src/routes/sessions.ts +22 -4
  34. package/src/routes/site-runtime.ts +62 -20
  35. package/src/routes/vault-providers.ts +788 -29
  36. package/src/routes/vaults.ts +5 -1
  37. package/src/sandbox/channel-a.ts +18 -1
  38. package/src/sandbox/metrics-ingestion.ts +1 -0
  39. package/src/shutdown.ts +54 -0
  40. package/src/site-frame-guard.ts +11 -2
  41. package/src/site-publishing/agent-data-tools.ts +16 -8
  42. package/src/site-publishing/agent-session.ts +24 -6
  43. package/src/site-publishing/runtime.ts +29 -7
  44. package/src/site-publishing/service.ts +65 -77
  45. package/src/site-publishing/session-request-authority.ts +14 -0
  46. package/src/workspace-tool-gateway-secrets.ts +9 -2
  47. package/src/workspace-tool-gateway.ts +6 -2
@@ -1,5 +1,8 @@
1
1
  import { createHash, randomBytes, randomUUID, timingSafeEqual } from "node:crypto";
2
2
  import {
3
+ ReasoningEffort,
4
+ LatencyMode,
5
+ permissionsRequiredByFirstPartyTools,
3
6
  DeleteSessionQueueItemRequest,
4
7
  EditSessionQueueItemRequest,
5
8
  matchSiteOperation,
@@ -30,6 +33,7 @@ import {
30
33
  type ToolRef,
31
34
  } from "@opengeni/contracts";
32
35
  import {
36
+ cancelPublishedSiteSession,
33
37
  withHostSessionUsageLimit,
34
38
  withSiteSessionOrigin,
35
39
  admissibleWorkspaceModel,
@@ -42,6 +46,7 @@ import {
42
46
  consumeSiteAuthCode,
43
47
  finishSiteRuntimeAdmission,
44
48
  withSiteRuntimeAdmission,
49
+ withSiteViewerRlsContext,
45
50
  createSiteAbuseReport,
46
51
  getSiteWorkspaceMemberPermissions,
47
52
  readSitePlatformUsage,
@@ -65,7 +70,6 @@ import {
65
70
  type SiteRuntimeConversationRecord,
66
71
  } from "@opengeni/db";
67
72
  import {
68
- SITE_AGENT_DATA_TOOL_PERMISSIONS,
69
73
  siteAgentDataToolsForStart,
70
74
  siteAgentInstructions,
71
75
  sitePublishedDataViewer,
@@ -145,7 +149,7 @@ import {
145
149
  configuredSitesDomain,
146
150
  healSiteEdgeIfStale,
147
151
  notifySiteAbuse,
148
- setSitePublishingDispatch,
152
+ setSitePublishingCancellation,
149
153
  siteHostMapRecord,
150
154
  sitePublishingError,
151
155
  } from "../site-publishing/service";
@@ -212,6 +216,9 @@ const CreateConversationRequest = z
212
216
  .object({
213
217
  initialMessage: z.string().trim().min(1).max(MESSAGE_MAX_CHARS),
214
218
  idempotencyKey: z.string().min(1).max(200).optional(),
219
+ model: z.string().min(1).optional(),
220
+ reasoningEffort: ReasoningEffort.optional(),
221
+ latencyMode: LatencyMode.optional(),
215
222
  })
216
223
  .passthrough();
217
224
  const SendMessageRequest = z
@@ -497,8 +504,8 @@ type RuntimeRequest = {
497
504
  export function registerSiteRuntimeRoutes(app: Hono, deps: ApiRouteDeps): void {
498
505
  const dispatch = async (request: Request): Promise<Response> =>
499
506
  await app.fetch(markLocalInternalDispatch(request));
500
- // Publication changes cancel a Site's conversations through this dispatch.
501
- setSitePublishingDispatch(deps.settings, dispatch);
507
+ // Lifecycle cancellation is a native internal command, never viewer dispatch.
508
+ setSitePublishingCancellation(deps.settings, (input) => cancelPublishedSiteSession(deps, input));
502
509
 
503
510
  const handler = async (context: Context): Promise<Response> => {
504
511
  const domain = configuredSitesDomain(deps.settings);
@@ -1232,7 +1239,7 @@ export function registerSiteRuntimeRoutes(app: Hono, deps: ApiRouteDeps): void {
1232
1239
  throw unsupported();
1233
1240
  };
1234
1241
 
1235
- /** The viewer's own agent conversations on this Site, run as `site:<siteId>`. */
1242
+ /** The viewer's own conversations, with native member or viewer-bound outsider authority. */
1236
1243
  const sessions = async (
1237
1244
  request: RuntimeRequest,
1238
1245
  id: string,
@@ -1246,6 +1253,20 @@ export function registerSiteRuntimeRoutes(app: Hono, deps: ApiRouteDeps): void {
1246
1253
  // carries the Site and version headers the API's Site frame guard
1247
1254
  // validates; sessions and turns it starts record this Site and version.
1248
1255
  const siteOrigin = { siteId: host.site.id, title: host.site.title, versionId: host.versionId };
1256
+ const reauthorizeViewer = async () => {
1257
+ const liveHost = await requireServedSiteRuntimeHost(deps, host.domain, request.fields.host);
1258
+ const liveViewer = await resolveSiteRuntimeViewer(deps, liveHost, request.fields);
1259
+ if (
1260
+ liveHost.site.id !== host.site.id ||
1261
+ liveViewer.principal !== viewer.principal ||
1262
+ liveViewer.kind !== viewer.kind ||
1263
+ liveViewer.sessionId !== viewer.sessionId
1264
+ )
1265
+ throw siteNotAvailableForViewer(
1266
+ "agent",
1267
+ "This conversation is no longer available to this viewer",
1268
+ );
1269
+ };
1249
1270
  let pendingAdmission: { sessionId: string; admissionId: string } | undefined;
1250
1271
  const send = async (
1251
1272
  method: string,
@@ -1253,16 +1274,20 @@ export function registerSiteRuntimeRoutes(app: Hono, deps: ApiRouteDeps): void {
1253
1274
  body?: unknown,
1254
1275
  extraPermissions?: readonly Permission[],
1255
1276
  ) => {
1277
+ await reauthorizeViewer();
1256
1278
  const execute = () =>
1257
- withSiteSessionOrigin(siteOrigin, async () =>
1258
- dispatch(
1259
- await siteRuntimeSessionRequest(deps, host, viewer, {
1260
- origin: url.origin,
1261
- method,
1262
- path,
1263
- ...(body === undefined ? {} : { body }),
1264
- ...(extraPermissions ? { extraPermissions } : {}),
1265
- }),
1279
+ withSiteViewerRlsContext({ siteId: host.site.id, principal: viewer.principal }, () =>
1280
+ withSiteSessionOrigin(siteOrigin, async () =>
1281
+ dispatch(
1282
+ await siteRuntimeSessionRequest(deps, host, viewer, {
1283
+ origin: url.origin,
1284
+ method,
1285
+ path,
1286
+ reauthorize: reauthorizeViewer,
1287
+ ...(body === undefined ? {} : { body }),
1288
+ ...(extraPermissions ? { extraPermissions } : {}),
1289
+ }),
1290
+ ),
1266
1291
  ),
1267
1292
  );
1268
1293
  const pending = pendingAdmission;
@@ -1344,6 +1369,11 @@ export function registerSiteRuntimeRoutes(app: Hono, deps: ApiRouteDeps): void {
1344
1369
  if (viewer.kind === "guest" || viewer.kind === "user")
1345
1370
  await requireSitePlatformOpen(deps, "guest_agent");
1346
1371
  const models = await siteViewerModels(host, viewer, limits);
1372
+ if (input.model && !models.allowed.includes(input.model))
1373
+ throw siteNotAvailableForViewer(
1374
+ "agent_model",
1375
+ "This model is not available to you on this Site",
1376
+ );
1347
1377
  if (models.unavailable)
1348
1378
  throw siteNotAvailableForViewer(
1349
1379
  "agent_model",
@@ -1402,6 +1432,11 @@ export function registerSiteRuntimeRoutes(app: Hono, deps: ApiRouteDeps): void {
1402
1432
  }
1403
1433
  }
1404
1434
  // Settle the viewer's recent spend so the day budget sees it.
1435
+ if (!repair && viewer.kind !== "member" && deps.settings.privacyOnlyMeAllowed === false)
1436
+ throw siteNotAvailableForViewer(
1437
+ "private_conversations",
1438
+ "Private Site conversations are disabled by this deployment",
1439
+ );
1405
1440
  for (const conversation of await listOwnedSiteRuntimeConversations(deps.db, host.scope, {
1406
1441
  siteId: host.site.id,
1407
1442
  viewerPrincipal: viewer.principal,
@@ -1455,7 +1490,9 @@ export function registerSiteRuntimeRoutes(app: Hono, deps: ApiRouteDeps): void {
1455
1490
  host.scope,
1456
1491
  host.site.id,
1457
1492
  viewer.kind,
1493
+ viewer.kind === "member" ? (memberPermissions ?? []) : undefined,
1458
1494
  );
1495
+ const dataToolPermissions = permissionsRequiredByFirstPartyTools(dataTools);
1459
1496
  // One transaction counts the start and reserves a per-turn estimate
1460
1497
  // against the visitor's and the Site's windows; only the funded allowance
1461
1498
  // becomes the session's usage limit, set in the create transaction. The
@@ -1491,15 +1528,14 @@ export function registerSiteRuntimeRoutes(app: Hono, deps: ApiRouteDeps): void {
1491
1528
  const body = {
1492
1529
  initialMessage: input.initialMessage,
1493
1530
  requestedSessionId,
1531
+ ...(viewer.kind === "member" ? { visibility: "private" } : {}),
1494
1532
  startMode: "standard",
1495
1533
  agentAccess: "session",
1496
1534
  memoryScope: "off",
1497
1535
  rigId: null,
1498
1536
  // Only this Site's data tools; never management or workspace tools.
1499
1537
  firstPartyMcpTools: dataTools,
1500
- ...(dataTools.length > 0
1501
- ? { firstPartyMcpPermissions: [...SITE_AGENT_DATA_TOOL_PERMISSIONS] }
1502
- : {}),
1538
+ ...(dataTools.length > 0 ? { firstPartyMcpPermissions: dataToolPermissions } : {}),
1503
1539
  agent: {
1504
1540
  capabilities: {
1505
1541
  from: "none",
@@ -1511,7 +1547,13 @@ export function registerSiteRuntimeRoutes(app: Hono, deps: ApiRouteDeps): void {
1511
1547
  // No sandbox: a Site's agent answers from the page and the Site's
1512
1548
  // data, with no shell or workspace files.
1513
1549
  sandboxBackend: "none",
1514
- ...(repair ? { model: repair.model } : models.default ? { model: models.default } : {}),
1550
+ ...(repair
1551
+ ? { model: repair.model }
1552
+ : input.model || models.default
1553
+ ? { model: input.model ?? models.default }
1554
+ : {}),
1555
+ ...(input.reasoningEffort === undefined ? {} : { reasoningEffort: input.reasoningEffort }),
1556
+ ...(input.latencyMode === undefined ? {} : { latencyMode: input.latencyMode }),
1515
1557
  instructions: siteAgentInstructions(host, viewer, dataTools, agent.instructions),
1516
1558
  // Always explicit: an empty list means no workspace tools at all.
1517
1559
  tools: mcpTools,
@@ -1525,8 +1567,7 @@ export function registerSiteRuntimeRoutes(app: Hono, deps: ApiRouteDeps): void {
1525
1567
  },
1526
1568
  ...(input.idempotencyKey ? { idempotencyKey: `site-runtime:${requestedSessionId}` } : {}),
1527
1569
  };
1528
- const start = () =>
1529
- send("POST", base, body, dataTools.length > 0 ? SITE_AGENT_DATA_TOOL_PERMISSIONS : []);
1570
+ const start = () => send("POST", base, body, dataToolPermissions);
1530
1571
  // Workspace members get no Site budget at all: their conversation is an
1531
1572
  // ordinary session under the workspace's normal limits, so no session
1532
1573
  // usage limit is stamped on it, whatever the Site's limits say.
@@ -1694,6 +1735,7 @@ export function registerSiteRuntimeRoutes(app: Hono, deps: ApiRouteDeps): void {
1694
1735
  viewer,
1695
1736
  conversation.sessionId,
1696
1737
  conversation.toolIds,
1738
+ viewer.kind === "member" ? (memberPermissions ?? []) : undefined,
1697
1739
  );
1698
1740
  const usage = await settleSiteRuntimeSpend(deps, host, conversation);
1699
1741
  // Clear the stamped session cap before dropping the durable conversation