@opengeni/api-router 4.0.0 → 4.1.0-canary.35855175602001

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.
@@ -267,6 +267,7 @@ var FIRST_PARTY_TOOL_AUTHORIZATION = {
267
267
  run_on: { sessionRequired: true, allOf: ["sessions:control"] },
268
268
  sandbox_provision: { sessionRequired: true, allOf: ["sessions:control"] },
269
269
  connected_machine_remove: { allOf: ["enrollments:manage"] },
270
+ connected_machine_enroll_token: { allOf: ["enrollments:manage"] },
270
271
  rig_list: { allOf: ["rigs:use"] },
271
272
  rig_get: { allOf: ["rigs:use"] },
272
273
  rig_propose_change: { allOf: ["rigs:use"] },
@@ -649,8 +650,8 @@ import { SiteSessionPathError, OrganizationIntegrationDeniedError as Organizatio
649
650
 
650
651
  // src/routes/model-connection-access.ts
651
652
  import {
652
- configuredModels as configuredModels2,
653
- withCodexCatalogProvider,
653
+ configuredModels as configuredModels3,
654
+ withCodexCatalogProvider as withCodexCatalogProvider2,
654
655
  withXaiSubscriptionCatalogProvider as withXaiSubscriptionCatalogProvider2,
655
656
  withOrganizationGatewayCatalogProvider,
656
657
  withOrganizationOpenRouterCatalogProvider
@@ -673,14 +674,17 @@ import { HTTPException as HTTPException4 } from "hono/http-exception";
673
674
  import { z as z5 } from "zod";
674
675
 
675
676
  // src/routes/codex.ts
676
- import { environmentsEncryptionKeyBytes, productLabelForModelId } from "@opengeni/config";
677
+ import {
678
+ environmentsEncryptionKeyBytes,
679
+ configuredModels,
680
+ getSettings,
681
+ withCodexCatalogProvider
682
+ } from "@opengeni/config";
677
683
  import {
678
684
  accessTokenExpiry,
679
685
  buildCodexUsageWindowFromCache,
680
686
  CODEX_CLIENT_VERSION,
681
- CODEX_FALLBACK_MODEL_SLUGS,
682
687
  CODEX_FIVE_HOUR_WINDOW_SECONDS,
683
- CODEX_MODEL_ID_PREFIX,
684
688
  CODEX_PROVIDER_ID,
685
689
  CODEX_WEEKLY_WINDOW_SECONDS,
686
690
  CodexDeviceError,
@@ -741,7 +745,8 @@ import {
741
745
  getManagedSession,
742
746
  hasPermission as hasPermission2,
743
747
  requireAccessGrant as requireAccessGrant2,
744
- requireCanonicalLocalAccountAdministrator
748
+ requireCanonicalLocalAccountAdministrator,
749
+ resolveCatalogSettings
745
750
  } from "@opengeni/core";
746
751
  import { HTTPException as HTTPException2 } from "hono/http-exception";
747
752
  import * as z3 from "zod/v4";
@@ -863,10 +868,10 @@ function codexWorkerReadiness(input) {
863
868
  function codexUsageJson(payload) {
864
869
  return { status: payload.status, usage: payload };
865
870
  }
866
- function codexModelsForPicker() {
867
- return CODEX_FALLBACK_MODEL_SLUGS.map((slug) => ({
868
- id: `${CODEX_MODEL_ID_PREFIX}${slug}`,
869
- label: productLabelForModelId(slug),
871
+ function codexModelsForPicker(settings = getSettings()) {
872
+ return configuredModels(withCodexCatalogProvider(settings)).filter((model) => model.providerId === CODEX_PROVIDER_ID).map((model) => ({
873
+ id: model.id,
874
+ label: model.label,
870
875
  provider: CODEX_PROVIDER_ID,
871
876
  providerLabel: CODEX_PROVIDER_LABEL,
872
877
  api: "responses"
@@ -1687,7 +1692,7 @@ function registerCodexRoutes(app, deps) {
1687
1692
  now: /* @__PURE__ */ new Date()
1688
1693
  });
1689
1694
  let valid = false;
1690
- const models = codexModelsForPicker();
1695
+ const models = codexModelsForPicker((await resolveCatalogSettings(db, settings)).settings);
1691
1696
  let catalogError = null;
1692
1697
  try {
1693
1698
  const cred = status?.credentialId ? await loadCodexCredentialForRun(db, settings, workspaceId, status.credentialId) : null;
@@ -2471,7 +2476,7 @@ import {
2471
2476
  updateOrganizationXaiRotation
2472
2477
  } from "@opengeni/db";
2473
2478
  import {
2474
- configuredModels,
2479
+ configuredModels as configuredModels2,
2475
2480
  environmentsEncryptionKeyBytes as environmentsEncryptionKeyBytes2,
2476
2481
  withXaiSubscriptionCatalogProvider
2477
2482
  } from "@opengeni/config";
@@ -3184,7 +3189,7 @@ function registerSuperGrokRoutes(app, deps) {
3184
3189
  valid = false;
3185
3190
  }
3186
3191
  const catalogSettings = valid ? (await deps.resolveCatalogSettings()).settings : null;
3187
- const catalog = catalogSettings ? configuredModels(withXaiSubscriptionCatalogProvider(catalogSettings)).filter(
3192
+ const catalog = catalogSettings ? configuredModels2(withXaiSubscriptionCatalogProvider(catalogSettings)).filter(
3188
3193
  (model) => model.credentialSource.kind === "connected_subscription" && model.credentialSource.provider === "xai"
3189
3194
  ).map(projectClientModel) : [];
3190
3195
  return c.json({
@@ -3426,7 +3431,7 @@ function registerModelConnectionAccessRoutes(app, deps) {
3426
3431
  accountId: connection.accountId,
3427
3432
  workspaceId: connection.workspaceId
3428
3433
  })).settings;
3429
- settings = withCodexCatalogProvider(withXaiSubscriptionCatalogProvider2(settings));
3434
+ settings = withCodexCatalogProvider2(withXaiSubscriptionCatalogProvider2(settings));
3430
3435
  let workspaces = [];
3431
3436
  if (connection.workspaceId === null) {
3432
3437
  const actor = {
@@ -3448,7 +3453,7 @@ function registerModelConnectionAccessRoutes(app, deps) {
3448
3453
  ModelConnectionAccessResponse.parse({
3449
3454
  policy,
3450
3455
  workspaces,
3451
- models: configuredModels2(settings).filter((model) => model.id.startsWith(modelPrefix(connection))).map(({ id, label }) => ({ id, label })),
3456
+ models: configuredModels3(settings).filter((model) => model.id.startsWith(modelPrefix(connection))).map(({ id, label }) => ({ id, label })),
3452
3457
  personalWorkspacesSupported: connection.workspaceId === null && (connection.kind === "codex" || connection.kind === "supergrok")
3453
3458
  })
3454
3459
  );
@@ -3482,10 +3487,10 @@ import {
3482
3487
  canonicalizeConfiguredModelId as canonicalizeConfiguredModelId2,
3483
3488
  configuredAllowedModels,
3484
3489
  configuredAllowedReasoningEfforts,
3485
- configuredModels as configuredModels3,
3490
+ configuredModels as configuredModels4,
3486
3491
  resolveFirstPartyMcpToolPolicy as resolveFirstPartyMcpToolPolicy2,
3487
3492
  resolveVoiceInputProviderRegistry as resolveVoiceInputProviderRegistry2,
3488
- withCodexCatalogProvider as withCodexCatalogProvider2,
3493
+ withCodexCatalogProvider as withCodexCatalogProvider3,
3489
3494
  withXaiSubscriptionCatalogProvider as withXaiSubscriptionCatalogProvider3
3490
3495
  } from "@opengeni/config";
3491
3496
  import {
@@ -3600,7 +3605,7 @@ import {
3600
3605
  requireAccessGrantAuthorization as requireAccessGrantAuthorization36,
3601
3606
  requirePermission as requirePermission9,
3602
3607
  releaseManagedAuthRequestActorLease,
3603
- resolveCatalogSettings,
3608
+ resolveCatalogSettings as resolveCatalogSettings2,
3604
3609
  resolveWorkspaceCatalogSettings as resolveWorkspaceCatalogSettings10,
3605
3610
  validateManagedAuthRequestActorLease,
3606
3611
  requireSessionAuthorization as requireSessionAuthorization16,
@@ -5889,7 +5894,296 @@ import {
5889
5894
  deleteChannel,
5890
5895
  setSessionChannel
5891
5896
  } from "@opengeni/db";
5892
- import { createHash as createHash11, randomUUID as randomUUID2 } from "crypto";
5897
+ import { createHash as createHash12, randomUUID as randomUUID3 } from "crypto";
5898
+
5899
+ // src/sandbox/enrollment.ts
5900
+ import { randomBytes } from "crypto";
5901
+ import {
5902
+ resolveEnrollmentSigningSecret,
5903
+ resolveRelayTokenSecret
5904
+ } from "@opengeni/config";
5905
+ import {
5906
+ DeviceEnrollmentState,
5907
+ signEnrollmentBearer,
5908
+ signEnrollToken,
5909
+ signRelayToken,
5910
+ verifyEnrollToken
5911
+ } from "@opengeni/contracts";
5912
+ import {
5913
+ approveDeviceEnrollmentRequest,
5914
+ consumeDeviceEnrollmentRequest,
5915
+ createDeviceEnrollmentRequest,
5916
+ denyDeviceEnrollmentRequest,
5917
+ finalizeEnrollmentByToken,
5918
+ getDeviceEnrollmentRequestByDeviceCode,
5919
+ getEnrollment,
5920
+ getPendingDeviceEnrollmentRequestByUserCode,
5921
+ getPendingDeviceEnrollmentRequestByUserCodeGlobal
5922
+ } from "@opengeni/db";
5923
+ import { relayDialBaseFromSettings } from "@opengeni/core";
5924
+ var DEVICE_CODE_TTL_SECONDS = 600;
5925
+ var DEVICE_POLL_INTERVAL_SECONDS = 5;
5926
+ var ENROLLMENT_BEARER_TTL_SECONDS = 30 * 24 * 3600;
5927
+ var RELAY_TOKEN_TTL_SECONDS = 30 * 24 * 3600;
5928
+ var ENROLL_TOKEN_TTL_SECONDS = 3600;
5929
+ function mintDeviceCode() {
5930
+ return randomBytes(32).toString("base64url");
5931
+ }
5932
+ var USER_CODE_ALPHABET = "ABCDEFGHJKLMNPQRSTUVWXYZ23456789";
5933
+ function mintUserCode() {
5934
+ const bytes = randomBytes(8);
5935
+ let out = "";
5936
+ for (let i = 0; i < 8; i += 1) {
5937
+ out += USER_CODE_ALPHABET[bytes[i] % USER_CODE_ALPHABET.length];
5938
+ }
5939
+ return `${out.slice(0, 4)}-${out.slice(4, 8)}`;
5940
+ }
5941
+ async function startDeviceEnrollment(services, input) {
5942
+ const { db } = services;
5943
+ const expiresAt = new Date(Date.now() + DEVICE_CODE_TTL_SECONDS * 1e3);
5944
+ let request;
5945
+ let lastError;
5946
+ for (let attempt = 0; attempt < 5 && !request; attempt += 1) {
5947
+ const deviceCode = mintDeviceCode();
5948
+ const userCode = mintUserCode();
5949
+ try {
5950
+ request = await createDeviceEnrollmentRequest(db, {
5951
+ accountId: input.accountId,
5952
+ workspaceId: input.workspaceId,
5953
+ deviceCode,
5954
+ userCode,
5955
+ pubkey: input.publicKey,
5956
+ os: input.os,
5957
+ arch: input.arch,
5958
+ machineName: input.machineName ?? null,
5959
+ requestedExposure: "whole-machine",
5960
+ canOfferDisplay: input.canOfferDisplay,
5961
+ requestsScreenControl: input.requestsScreenControl,
5962
+ expiresAt
5963
+ });
5964
+ } catch (error) {
5965
+ lastError = error;
5966
+ }
5967
+ }
5968
+ if (!request) {
5969
+ throw lastError instanceof Error ? lastError : new Error("failed to start device enrollment");
5970
+ }
5971
+ const base = input.verificationOrigin.replace(/\/+$/, "");
5972
+ const verificationUri = `${base}/device`;
5973
+ const verificationUriComplete = `${verificationUri}?user_code=${encodeURIComponent(request.userCode)}`;
5974
+ return {
5975
+ deviceCode: request.deviceCode,
5976
+ userCode: request.userCode,
5977
+ verificationUri,
5978
+ verificationUriComplete,
5979
+ intervalSeconds: DEVICE_POLL_INTERVAL_SECONDS,
5980
+ expiresInSeconds: DEVICE_CODE_TTL_SECONDS
5981
+ };
5982
+ }
5983
+ async function approveDeviceEnrollment(services, input) {
5984
+ const { db } = services;
5985
+ const pending = await getPendingDeviceEnrollmentRequestByUserCode(
5986
+ db,
5987
+ input.workspaceId,
5988
+ input.userCode
5989
+ );
5990
+ if (!pending) {
5991
+ return null;
5992
+ }
5993
+ const sandboxName = (pending.machineName?.trim() || `${pending.os} machine`).slice(0, 256);
5994
+ const result = await approveDeviceEnrollmentRequest(db, {
5995
+ accountId: input.accountId,
5996
+ workspaceId: input.workspaceId,
5997
+ ...input.scope ? { scope: input.scope } : {},
5998
+ allowOrganization: input.allowOrganization === true,
5999
+ requestId: pending.id,
6000
+ allowScreenControl: input.allowScreenControl,
6001
+ approvedBySubjectId: input.approvedBySubjectId,
6002
+ approvedBySubjectLabel: input.approvedBySubjectLabel ?? null,
6003
+ sandboxName
6004
+ });
6005
+ if (!result.approved || !result.enrollment || !result.sandbox) {
6006
+ return null;
6007
+ }
6008
+ return {
6009
+ enrollmentId: result.enrollment.id,
6010
+ sandboxId: result.sandbox.id,
6011
+ allowScreenControl: result.enrollment.allowScreenControl
6012
+ };
6013
+ }
6014
+ async function lookupDeviceEnrollment(services, input) {
6015
+ const { db } = services;
6016
+ return await getPendingDeviceEnrollmentRequestByUserCodeGlobal(db, input.userCode);
6017
+ }
6018
+ function toLookupResponse(record6) {
6019
+ return {
6020
+ workspaceId: record6.workspaceId,
6021
+ userCode: record6.userCode,
6022
+ machine: {
6023
+ machineName: record6.machineName,
6024
+ os: record6.os,
6025
+ arch: record6.arch,
6026
+ canOfferDisplay: record6.canOfferDisplay,
6027
+ requestsScreenControl: record6.requestsScreenControl
6028
+ },
6029
+ expiresAt: record6.expiresAt
6030
+ };
6031
+ }
6032
+ async function denyDeviceEnrollment(services, input) {
6033
+ const { db } = services;
6034
+ const pending = await getPendingDeviceEnrollmentRequestByUserCode(
6035
+ db,
6036
+ input.workspaceId,
6037
+ input.userCode
6038
+ );
6039
+ if (!pending) {
6040
+ return { denied: false };
6041
+ }
6042
+ return await denyDeviceEnrollmentRequest(db, {
6043
+ accountId: input.accountId,
6044
+ workspaceId: input.workspaceId,
6045
+ requestId: pending.id
6046
+ });
6047
+ }
6048
+ async function mintEnrollToken(services, input) {
6049
+ const { settings } = services;
6050
+ const secret = resolveEnrollmentSigningSecret(settings);
6051
+ if (!secret) {
6052
+ return null;
6053
+ }
6054
+ const nowSeconds = Math.floor(Date.now() / 1e3);
6055
+ const exp = nowSeconds + ENROLL_TOKEN_TTL_SECONDS;
6056
+ const token = await signEnrollToken(secret, {
6057
+ typ: "enroll",
6058
+ workspaceId: input.workspaceId,
6059
+ accountId: input.accountId,
6060
+ allowScreenControl: input.allowScreenControl,
6061
+ iat: nowSeconds,
6062
+ exp
6063
+ });
6064
+ return {
6065
+ token,
6066
+ expiresAt: new Date(exp * 1e3).toISOString(),
6067
+ expiresInSeconds: ENROLL_TOKEN_TTL_SECONDS
6068
+ };
6069
+ }
6070
+ async function exchangeEnrollToken(services, input) {
6071
+ const { db, settings } = services;
6072
+ const secret = resolveEnrollmentSigningSecret(settings);
6073
+ if (!secret) {
6074
+ return { ok: false, reason: "disabled" };
6075
+ }
6076
+ const claims = await verifyEnrollToken(secret, input.token);
6077
+ if (!claims) {
6078
+ return { ok: false, reason: "invalid" };
6079
+ }
6080
+ const sandboxName = (input.machineName?.trim() || `${input.os} machine`).slice(0, 256);
6081
+ const { enrollment } = await finalizeEnrollmentByToken(db, {
6082
+ accountId: claims.accountId,
6083
+ workspaceId: claims.workspaceId,
6084
+ pubkey: input.publicKey,
6085
+ hasDisplay: input.canOfferDisplay,
6086
+ // The token's allowScreenControl is the AUTHORITATIVE consent (NOT the agent's
6087
+ // requestsScreenControl) — it was baked in at mint by the authorizing user.
6088
+ allowScreenControl: claims.allowScreenControl,
6089
+ os: input.os,
6090
+ arch: input.arch,
6091
+ sandboxName
6092
+ });
6093
+ const credentials = await buildEnrollmentCredentials(services, {
6094
+ secret,
6095
+ workspaceId: claims.workspaceId,
6096
+ agentId: enrollment.id,
6097
+ credentialGeneration: enrollment.credentialGeneration,
6098
+ consentedScreenControl: enrollment.allowScreenControl
6099
+ });
6100
+ return { ok: true, credentials };
6101
+ }
6102
+ async function pollDeviceEnrollment(services, input) {
6103
+ const { db, settings } = services;
6104
+ const request = await getDeviceEnrollmentRequestByDeviceCode(db, input.deviceCode);
6105
+ if (!request) {
6106
+ return { state: "expired" };
6107
+ }
6108
+ if (request.status === "denied") {
6109
+ return { state: "denied" };
6110
+ }
6111
+ if (request.status === "pending") {
6112
+ if (new Date(request.expiresAt).getTime() <= Date.now()) {
6113
+ return { state: "expired" };
6114
+ }
6115
+ return { state: "pending" };
6116
+ }
6117
+ if (!request.enrollmentId) {
6118
+ return { state: "expired" };
6119
+ }
6120
+ const secret = resolveEnrollmentSigningSecret(settings);
6121
+ if (!secret) {
6122
+ return { state: "disabled" };
6123
+ }
6124
+ const enrollment = await getEnrollment(db, request.workspaceId, request.enrollmentId);
6125
+ if (!enrollment || enrollment.status !== "active") {
6126
+ return { state: "denied" };
6127
+ }
6128
+ const credentials = await buildEnrollmentCredentials(services, {
6129
+ secret,
6130
+ workspaceId: request.workspaceId,
6131
+ agentId: enrollment.id,
6132
+ credentialGeneration: enrollment.credentialGeneration,
6133
+ consentedScreenControl: enrollment.allowScreenControl
6134
+ });
6135
+ if (request.status === "approved") {
6136
+ await consumeDeviceEnrollmentRequest(db, {
6137
+ accountId: request.accountId,
6138
+ workspaceId: request.workspaceId,
6139
+ requestId: request.id
6140
+ });
6141
+ }
6142
+ return { state: DeviceEnrollmentState.enum.authorized, credentials };
6143
+ }
6144
+ async function buildEnrollmentCredentials(services, input) {
6145
+ const { settings } = services;
6146
+ const subjectPrefix = `agent.${input.workspaceId}.${input.agentId}`;
6147
+ const nowSeconds = Math.floor(Date.now() / 1e3);
6148
+ const exp = nowSeconds + ENROLLMENT_BEARER_TTL_SECONDS;
6149
+ const bearer = await signEnrollmentBearer(input.secret, {
6150
+ workspaceId: input.workspaceId,
6151
+ agentId: input.agentId,
6152
+ enrollmentId: input.agentId,
6153
+ credentialGeneration: input.credentialGeneration,
6154
+ subjectPrefix,
6155
+ exp
6156
+ });
6157
+ const natsUrls = settings.selfhostedNatsUrl ? [settings.selfhostedNatsUrl] : [];
6158
+ const relayTokenSecret = resolveRelayTokenSecret(settings);
6159
+ const relayToken = relayTokenSecret ? await signRelayToken(relayTokenSecret, {
6160
+ workspaceId: input.workspaceId,
6161
+ agentId: input.agentId,
6162
+ exp: nowSeconds + RELAY_TOKEN_TTL_SECONDS
6163
+ }) : "";
6164
+ return {
6165
+ agentId: input.agentId,
6166
+ workspaceId: input.workspaceId,
6167
+ bearer,
6168
+ subjectPrefix,
6169
+ natsUrls,
6170
+ // Hand the agent the canonical `/stream` dial base, NOT the raw configured URL.
6171
+ // The agent's relay producer appends only its routing query and assumes the base
6172
+ // already carries the relay's `/stream` route; a path-less base 400s the dial and
6173
+ // makes the terminal/desktop streams unreachable.
6174
+ relayUrl: relayDialBaseFromSettings(settings),
6175
+ relayToken,
6176
+ // M-AUTH closes the placeholder: there is NO per-machine NATS Account creds
6177
+ // file. The agent presents the BEARER as the NATS connect auth-token; the
6178
+ // server's auth-callout responder validates it and mints a workspace-scoped
6179
+ // user JWT. We echo the bearer here so a consumer reading this (vestigial) field
6180
+ // as the connect credential still works — the value IS the bearer.
6181
+ natsAccountCreds: bearer,
6182
+ updatePublicKey: settings.agentUpdatePublicKey ?? "",
6183
+ consentedWholeMachine: true,
6184
+ consentedScreenControl: input.consentedScreenControl
6185
+ };
6186
+ }
5893
6187
 
5894
6188
  // src/mcp/capability-account-readiness.ts
5895
6189
  function capabilityAccountReadiness(availableRoutes, bindings) {
@@ -5905,6 +6199,7 @@ function capabilityAccountReadiness(availableRoutes, bindings) {
5905
6199
 
5906
6200
  // src/site-uploads.ts
5907
6201
  import { WorkspaceArtifactSourceBundle as WorkspaceArtifactSourceBundle2 } from "@opengeni/contracts";
6202
+ import { retryWhileMissing as retryWhileMissing2 } from "@opengeni/storage";
5908
6203
  import {
5909
6204
  createWorkspaceArtifactUpload,
5910
6205
  getWorkspaceArtifactUpload,
@@ -6017,7 +6312,12 @@ async function validateSiteSource(storage, key, sizeBytes) {
6017
6312
  "Editable source JSON must be at most 64 MiB. Exclude dependencies and build output; HTML has a separate storage limit."
6018
6313
  );
6019
6314
  }
6020
- const content = await storage.getObjectBytes(key);
6315
+ const content = await retryWhileMissing2(() => storage.getObjectBytes(key));
6316
+ if (!content) {
6317
+ throw new WorkspaceArtifactOperationError(
6318
+ "Site source is not available yet. Retry publication with the same upload."
6319
+ );
6320
+ }
6021
6321
  try {
6022
6322
  WorkspaceArtifactSourceBundle2.parse(
6023
6323
  JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(content.bytes))
@@ -6110,13 +6410,20 @@ async function freeze(storage, from, to, contentType, optional = false) {
6110
6410
  }
6111
6411
  decoder2.decode();
6112
6412
  }
6113
- await storage.putObjectStreamIfAbsent({
6413
+ const created = await storage.putObjectStreamIfAbsent({
6114
6414
  key: to,
6115
6415
  contentType,
6116
6416
  byteSize: head.ContentLength,
6117
6417
  chunks: chunks()
6118
6418
  });
6119
- return (await storage.headObject(to)).ContentLength;
6419
+ if (created) return head.ContentLength;
6420
+ const stored = await retryWhileMissing2(() => storage.headObject(to));
6421
+ if (!stored || stored.ContentLength === void 0) {
6422
+ throw new WorkspaceArtifactOperationError(
6423
+ "Frozen Site upload is unavailable. Retry publication with the same upload."
6424
+ );
6425
+ }
6426
+ return stored.ContentLength;
6120
6427
  }
6121
6428
  async function prepareWorkspaceArtifactPublication(deps, grant, input) {
6122
6429
  const storage = deps.objectStorage;
@@ -7700,7 +8007,7 @@ import {
7700
8007
  recordSandboxFilePublication,
7701
8008
  withSessionRlsActorContext as withSessionRlsActorContext5
7702
8009
  } from "@opengeni/db";
7703
- import { retryWhileMissing as retryWhileMissing3 } from "@opengeni/storage";
8010
+ import { retryWhileMissing as retryWhileMissing4 } from "@opengeni/storage";
7704
8011
  import { HTTPException as HTTPException12 } from "hono/http-exception";
7705
8012
 
7706
8013
  // src/sandbox/channel-a.ts
@@ -9059,7 +9366,7 @@ import {
9059
9366
  SessionAuthorizationUnavailableError as SessionAuthorizationUnavailableError3
9060
9367
  } from "@opengeni/core";
9061
9368
  import { recordWorkspaceUsage, requireLimit } from "@opengeni/core";
9062
- import { retryWhileMissing as retryWhileMissing2 } from "@opengeni/storage";
9369
+ import { retryWhileMissing as retryWhileMissing3 } from "@opengeni/storage";
9063
9370
  import { WebStandardStreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/webStandardStreamableHttp.js";
9064
9371
 
9065
9372
  // src/mcp/files.ts
@@ -9161,7 +9468,7 @@ function buildFilesMcpServer(deps, authority) {
9161
9468
  }
9162
9469
 
9163
9470
  // src/mcp-oauth.ts
9164
- import { createHash as createHash2, randomBytes as randomBytes2 } from "crypto";
9471
+ import { createHash as createHash2, randomBytes as randomBytes3 } from "crypto";
9165
9472
  import {
9166
9473
  MCP_OAUTH_ACCESS_TOKEN_TTL_SECONDS,
9167
9474
  MCP_OAUTH_AUTHORIZATION_CODE_TTL_SECONDS,
@@ -9219,7 +9526,7 @@ function normalizedAddress(value) {
9219
9526
 
9220
9527
  // src/workspace-tool-gateway.ts
9221
9528
  import { knowledgeContextForGateway } from "@opengeni/core";
9222
- import { createHash, randomBytes } from "crypto";
9529
+ import { createHash, randomBytes as randomBytes2 } from "crypto";
9223
9530
  import { Client } from "@modelcontextprotocol/sdk/client/index.js";
9224
9531
  import { InMemoryTransport } from "@modelcontextprotocol/sdk/inMemory.js";
9225
9532
  import { withSiteSessionOrigin } from "@opengeni/core";
@@ -9869,7 +10176,7 @@ async function approveWorkspaceToolGatewayCall(prepared, grant, db, input, issue
9869
10176
  operation: "approval",
9870
10177
  source: preparedCall.entry.source
9871
10178
  });
9872
- const approvalToken = `ogta_${randomBytes(32).toString("base64url")}`;
10179
+ const approvalToken = `ogta_${randomBytes2(32).toString("base64url")}`;
9873
10180
  const expiresAt = new Date(Date.now() + 5 * 6e4);
9874
10181
  try {
9875
10182
  await prepared.reauthorize?.();
@@ -10501,7 +10808,7 @@ function pkceChallenge(verifier) {
10501
10808
  return createHash2("sha256").update(verifier, "ascii").digest("base64url");
10502
10809
  }
10503
10810
  function opaque(prefix) {
10504
- return `${prefix}${randomBytes2(32).toString("base64url")}`;
10811
+ return `${prefix}${randomBytes3(32).toString("base64url")}`;
10505
10812
  }
10506
10813
  function tokenHash(value) {
10507
10814
  return createHash2("sha256").update(value, "utf8").digest("hex");
@@ -10954,7 +11261,7 @@ function registerFileRoutes(app, deps) {
10954
11261
  const file2 = await rejectAndCleanObject(409, "file upload has expired", "expired");
10955
11262
  return c.json(CompleteFileUploadResponse.parse({ file: file2 }));
10956
11263
  }
10957
- const head = await retryWhileMissing2(async () => {
11264
+ const head = await retryWhileMissing3(async () => {
10958
11265
  if (!await objectStorage.fileExists(upload.file)) return null;
10959
11266
  return await objectStorage.headFile(upload.file);
10960
11267
  });
@@ -11086,7 +11393,7 @@ function registerFileRoutes(app, deps) {
11086
11393
  throw new HTTPException11(409, { message: `generated video is ${retained.file.status}` });
11087
11394
  }
11088
11395
  const file = generatedVideoFileAsset(retained.file);
11089
- const videoPresent = await retryWhileMissing2(
11396
+ const videoPresent = await retryWhileMissing3(
11090
11397
  async () => await objectStorage.fileExists(file) ? true : null
11091
11398
  );
11092
11399
  if (!videoPresent) {
@@ -11196,7 +11503,7 @@ function registerFileRoutes(app, deps) {
11196
11503
  if (file.status !== "ready") {
11197
11504
  throw new HTTPException11(409, { message: `file is ${file.status}` });
11198
11505
  }
11199
- const present = await retryWhileMissing2(
11506
+ const present = await retryWhileMissing3(
11200
11507
  async () => await objectStorage.fileExists(file) ? true : null
11201
11508
  );
11202
11509
  if (!present) {
@@ -11270,7 +11577,7 @@ async function serveRetainedArtifactContent(c, objectStorage, artifactId2, file,
11270
11577
  ...range.contentRange ? { "Content-Range": range.contentRange } : {}
11271
11578
  };
11272
11579
  if (range.kind === "empty") {
11273
- const present = await retryWhileMissing2(
11580
+ const present = await retryWhileMissing3(
11274
11581
  async () => await objectStorage.fileExists(file) ? true : null
11275
11582
  );
11276
11583
  if (!present) {
@@ -11278,7 +11585,7 @@ async function serveRetainedArtifactContent(c, objectStorage, artifactId2, file,
11278
11585
  }
11279
11586
  return c.body(null, 200, headers);
11280
11587
  }
11281
- const bytes = await retryWhileMissing2(
11588
+ const bytes = await retryWhileMissing3(
11282
11589
  async () => objectStorage.getFileRange(file, {
11283
11590
  start: range.start,
11284
11591
  end: range.end
@@ -11674,6 +11981,14 @@ function sandboxFileContentType(filename) {
11674
11981
  ".jpg": "image/jpeg",
11675
11982
  ".json": "application/json",
11676
11983
  ".md": "text/markdown",
11984
+ ".mp4": "video/mp4",
11985
+ ".webm": "video/webm",
11986
+ ".ogv": "video/ogg",
11987
+ ".mp3": "audio/mpeg",
11988
+ ".m4a": "audio/mp4",
11989
+ ".ogg": "audio/ogg",
11990
+ ".wav": "audio/wav",
11991
+ ".flac": "audio/flac",
11677
11992
  ".pdf": "application/pdf",
11678
11993
  ".png": "image/png",
11679
11994
  ".pptx": "application/vnd.openxmlformats-officedocument.presentationml.presentation",
@@ -11685,7 +12000,9 @@ function sandboxFileContentType(filename) {
11685
12000
  }[extension] ?? "application/octet-stream";
11686
12001
  }
11687
12002
  function sandboxArtifactIdentity(input) {
11688
- const digest2 = createHash3("sha256").update("opengeni-sandbox-file-artifact-v1\0").update(input.workspaceId).update("\0").update(input.sessionId).update("\0").update(input.path).update("\0").update(input.sha256).digest("hex");
12003
+ const digest2 = createHash3("sha256").update(
12004
+ /^(audio|video)\//.test(sandboxFileContentType(input.path)) ? "opengeni-sandbox-media-artifact-v1\0" : "opengeni-sandbox-file-artifact-v1\0"
12005
+ ).update(input.workspaceId).update("\0").update(input.sessionId).update("\0").update(input.path).update("\0").update(input.sha256).digest("hex");
11689
12006
  return {
11690
12007
  fileId: uuidFromDigest(digest2, 0),
11691
12008
  uploadId: uuidFromDigest(digest2, 16)
@@ -11704,7 +12021,7 @@ function assertSandboxArtifactFile(file, expected) {
11704
12021
  }
11705
12022
  }
11706
12023
  async function assertVisibleSandboxArtifact(storage, file) {
11707
- const head = await retryWhileMissing3(async () => await storage.headObject(file.objectKey));
12024
+ const head = await retryWhileMissing4(async () => await storage.headObject(file.objectKey));
11708
12025
  assertStoredSandboxArtifact(head, file);
11709
12026
  }
11710
12027
  function assertStoredSandboxArtifact(head, file) {
@@ -11834,9 +12151,11 @@ import {
11834
12151
  getGlobalCatalogOAuthProfile,
11835
12152
  listConnectionsMetadata,
11836
12153
  loadIntegrationOAuthClient,
12154
+ loadIntegrationOAuthPendingState,
11837
12155
  normalizeBearerScheme,
11838
12156
  replaceIntegrationOAuthClientIfCurrent,
11839
12157
  storeIntegrationOAuthClient,
12158
+ storeIntegrationOAuthPendingState,
11840
12159
  updateConnection,
11841
12160
  withDatabaseStatementTimeout
11842
12161
  } from "@opengeni/db";
@@ -11854,7 +12173,7 @@ import {
11854
12173
  validateHttpUrl
11855
12174
  } from "@opengeni/network";
11856
12175
  import { Buffer as Buffer2 } from "buffer";
11857
- import { createHash as createHash4, randomBytes as randomBytes3 } from "crypto";
12176
+ import { createHash as createHash4, randomBytes as randomBytes4, randomUUID } from "crypto";
11858
12177
  import { HTTPException as HTTPException17 } from "hono/http-exception";
11859
12178
 
11860
12179
  // src/connection-ownership.ts
@@ -12406,7 +12725,7 @@ async function startMcpOAuthWithinDeadline(deps, context, deadline) {
12406
12725
  )
12407
12726
  );
12408
12727
  const key = requireEnvironmentEncryption(settings);
12409
- const state = createSignedState3(requireIntegrationsStateSecret(settings), {
12728
+ const fullState = createSignedState3(requireIntegrationsStateSecret(settings), {
12410
12729
  ...context.integrationKey ? { integrationKey: context.integrationKey } : {},
12411
12730
  ...context.connectAttemptId ? { connectAttemptId: context.connectAttemptId } : {},
12412
12731
  accountId: context.accountId,
@@ -12448,6 +12767,30 @@ async function startMcpOAuthWithinDeadline(deps, context, deadline) {
12448
12767
  returnPath,
12449
12768
  ...existing ? { connectionId: existing.id, connectionVersion: existing.version } : {}
12450
12769
  });
12770
+ const expiresAt = new Date(Date.now() + oauthStateTtlMs);
12771
+ let state = fullState;
12772
+ if (settings.integrationsOauthShortStateEnabled) {
12773
+ const stateId = randomUUID();
12774
+ state = createSignedState3(requireIntegrationsStateSecret(settings), {
12775
+ kind: "mcp_oauth_reference",
12776
+ id: stateId,
12777
+ accountId: context.accountId,
12778
+ workspaceId: context.workspaceId
12779
+ });
12780
+ if (state.length > 512) {
12781
+ throw new Error("MCP OAuth reference state exceeded its provider-safe length");
12782
+ }
12783
+ await deadline.run(
12784
+ "state_persist",
12785
+ async () => storeIntegrationOAuthPendingState(db, {
12786
+ id: stateId,
12787
+ accountId: context.accountId,
12788
+ workspaceId: context.workspaceId,
12789
+ stateEncrypted: encryptEnvironmentValue3(key, fullState),
12790
+ expiresAt
12791
+ })
12792
+ );
12793
+ }
12451
12794
  const authorizationUrl = buildAuthorizationUrl({
12452
12795
  endpoint: discovery.as.authorizationEndpoint,
12453
12796
  settings,
@@ -12463,7 +12806,7 @@ async function startMcpOAuthWithinDeadline(deps, context, deadline) {
12463
12806
  return OAuthStartResponse.parse({
12464
12807
  state,
12465
12808
  authorizationUrl,
12466
- expiresAt: new Date(Date.now() + oauthStateTtlMs).toISOString()
12809
+ expiresAt: expiresAt.toISOString()
12467
12810
  });
12468
12811
  }
12469
12812
  function assertOAuthStartProfile(settings, payload, mcpUrl, profile) {
@@ -12519,7 +12862,7 @@ async function completeMcpOAuthCallbackWithinDeadline(deps, input, deadline) {
12519
12862
  };
12520
12863
  }
12521
12864
  try {
12522
- state = readOAuthState(input.state, settings);
12865
+ state = await resolveMcpOAuthState(db, settings, input.state, deadline);
12523
12866
  integrationKey = state.integrationKey ?? "custom:mcp";
12524
12867
  if (state.connectAttemptId) {
12525
12868
  const stored = await getConnectAttempt2(db, state, state.connectAttemptId);
@@ -13297,6 +13640,33 @@ function buildAuthorizationUrl(input) {
13297
13640
  }
13298
13641
  return url.toString();
13299
13642
  }
13643
+ async function resolveMcpOAuthState(db, settings, state, deadline) {
13644
+ const reference = readSignedState4(state, requireIntegrationsStateSecret(settings));
13645
+ if (reference?.kind !== "mcp_oauth_reference") {
13646
+ return readOAuthState(state, settings);
13647
+ }
13648
+ const accountId = requiredString(reference.accountId, "state.accountId");
13649
+ const workspaceId = requiredString(reference.workspaceId, "state.workspaceId");
13650
+ const id = requiredString(reference.id, "state.id");
13651
+ if (!/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/.test(id)) {
13652
+ throw new HTTPException17(400, { message: "invalid OAuth state reference" });
13653
+ }
13654
+ const encrypted = await runCallbackDatabaseStage(
13655
+ deadline,
13656
+ "state_verify",
13657
+ db,
13658
+ (scopedDb) => loadIntegrationOAuthPendingState(scopedDb, { accountId, workspaceId, id })
13659
+ );
13660
+ if (!encrypted) {
13661
+ throw new HTTPException17(400, { message: "invalid or expired OAuth state" });
13662
+ }
13663
+ const fullState = decryptEnvironmentValue2(requireEnvironmentEncryption(settings), encrypted);
13664
+ const resolved = readOAuthState(fullState, settings);
13665
+ if (resolved.accountId !== accountId || resolved.workspaceId !== workspaceId) {
13666
+ throw new HTTPException17(400, { message: "OAuth state reference mismatch" });
13667
+ }
13668
+ return resolved;
13669
+ }
13300
13670
  function readOAuthState(state, settings) {
13301
13671
  const payload = readSignedState4(state, requireIntegrationsStateSecret(settings));
13302
13672
  if (!payload) {
@@ -13633,6 +14003,8 @@ function oauthStartStageLabel(stage) {
13633
14003
  return "authorization-server discovery";
13634
14004
  case "client_registration":
13635
14005
  return "OAuth client registration";
14006
+ case "state_persist":
14007
+ return "OAuth state persistence";
13636
14008
  }
13637
14009
  }
13638
14010
  function logOAuthVerificationWarning(observability, error, _state) {
@@ -13920,7 +14292,7 @@ function pkceChallenge2(verifier) {
13920
14292
  return createHash4("sha256").update(verifier).digest("base64url");
13921
14293
  }
13922
14294
  function randomPkceVerifier() {
13923
- return randomBytes3(32).toString("base64url");
14295
+ return randomBytes4(32).toString("base64url");
13924
14296
  }
13925
14297
  function uniqueStrings(values) {
13926
14298
  return [...new Set(values.map((value) => value.trim()).filter(Boolean))];
@@ -13964,7 +14336,7 @@ import {
13964
14336
  import { createSignedState as createSignedState4, readSignedState as readSignedState5 } from "@opengeni/github";
13965
14337
  import { OAUTH_MAX_RESPONSE_BYTES as OAUTH_MAX_RESPONSE_BYTES3, pinnedFetch as pinnedFetch2, readResponseJsonBounded as readResponseJsonBounded2 } from "@opengeni/network";
13966
14338
  import { Buffer as Buffer3 } from "buffer";
13967
- import { createHash as createHash5, randomBytes as randomBytes4 } from "crypto";
14339
+ import { createHash as createHash5, randomBytes as randomBytes5 } from "crypto";
13968
14340
  import { HTTPException as HTTPException18 } from "hono/http-exception";
13969
14341
  var SOCIAL_USER_AGENT = "opengeni:social-connector:v0.1.0 (self-hosted)";
13970
14342
  var SOCIAL_TIMEOUT_MS = 1e4;
@@ -14033,7 +14405,7 @@ async function startSocialOAuth(deps, context) {
14033
14405
  const redirectUri = socialOAuthRedirectUri(settings, context.requestUrl);
14034
14406
  const returnPath = safeReturnPath2(context.payload.returnPath ?? "/integrations");
14035
14407
  const scopes = uniqueScopes(context.payload.scopes) ?? provider.defaultScopes;
14036
- const verifier = provider.pkce ? randomBytes4(32).toString("base64url") : null;
14408
+ const verifier = provider.pkce ? randomBytes5(32).toString("base64url") : null;
14037
14409
  const key = requireEnvironmentEncryption2(settings);
14038
14410
  const state = createSignedState4(requireIntegrationsStateSecret(settings), {
14039
14411
  kind: "social_oauth",
@@ -15772,6 +16144,21 @@ function boundRigDetailMcp(rig, versionsPage, changesPage, maxBytes = RIG_DETAIL
15772
16144
  return result;
15773
16145
  }
15774
16146
 
16147
+ // src/mcp/child-read-evidence.ts
16148
+ function completeChildReadSequences(page) {
16149
+ if (!page.sourceExact || !["conversation", "results"].includes(page.view)) return [];
16150
+ return page.events.filter((event) => {
16151
+ if (event.sourceOmitted) return false;
16152
+ if (event.fragment === void 0) return true;
16153
+ if (!event.fragment || typeof event.fragment !== "object") return false;
16154
+ const fragment = event.fragment;
16155
+ return fragment.offset === 0 && fragment.complete === true;
16156
+ }).map((event) => event.sequence);
16157
+ }
16158
+
16159
+ // src/mcp/server.ts
16160
+ import { acknowledgeConsumedChildEvents } from "@opengeni/db";
16161
+
15775
16162
  // src/mcp/session-wait.ts
15776
16163
  import {
15777
16164
  SESSION_EVENT_SEMANTIC_CLASS_TYPES,
@@ -16069,6 +16456,7 @@ function summarizeSessionWaitEvent(event, textChars = SUMMARY_TEXT_TIERS[0]) {
16069
16456
  } else if (typeof compact.result === "string" && compact.result !== compact.text) {
16070
16457
  summary.result = clampSummaryString(compact.result, textChars);
16071
16458
  }
16459
+ summary.contentComplete = ["turn.completed", "agent.message.completed"].includes(event.type) && !compact.truncation.truncated && text === compact.text && JSON.stringify(failure) === JSON.stringify(compact.failure) && (compact.output === null || compact.output === compact.text || JSON.stringify(compact.output) === JSON.stringify(summary.result)) && (compact.result === null || compact.result === void 0 || compact.result === compact.text || JSON.stringify(summary.result) === JSON.stringify(compact.result));
16072
16460
  return summary;
16073
16461
  }
16074
16462
  function prettyJsonBytes2(value) {
@@ -16100,6 +16488,7 @@ function boundSessionWaitResult(input, maxBytes = SESSION_EVENT_MCP_MAX_BYTES) {
16100
16488
  ...target,
16101
16489
  events: target.events.map((event) => ({
16102
16490
  ...event,
16491
+ contentComplete: false,
16103
16492
  text: event.text === null ? null : clampSummaryString(event.text, textChars),
16104
16493
  ...typeof event.result === "string" ? { result: clampSummaryString(event.result, textChars) } : {}
16105
16494
  }))
@@ -17543,7 +17932,7 @@ function viewerIdAsUuid(rawViewerId) {
17543
17932
  }
17544
17933
 
17545
17934
  // src/integrations/slack-bot.ts
17546
- import { createHmac as createHmac3, timingSafeEqual as timingSafeEqual2 } from "crypto";
17935
+ import { createHash as createHash7, createHmac as createHmac3, timingSafeEqual as timingSafeEqual2 } from "crypto";
17547
17936
  import { environmentsEncryptionKeyBytes as environmentsEncryptionKeyBytes3 } from "@opengeni/config";
17548
17937
  import {
17549
17938
  OPENGENI_SLACK_BOT_CREDENTIAL_LABEL,
@@ -18228,6 +18617,7 @@ var OpenGeniSlackBotClient = class {
18228
18617
  const targetKind = input.userId ? "user" : "channel";
18229
18618
  const targetId = input.userId ?? input.channelId;
18230
18619
  const blocks = validateSlackMessageBlocks(input.blocks);
18620
+ const wireBlocks = slackMessageWireBlocks(blocks);
18231
18621
  const requestDigest = this.postRequestDigest({
18232
18622
  operationId: input.operationId,
18233
18623
  targetKind,
@@ -18309,7 +18699,7 @@ var OpenGeniSlackBotClient = class {
18309
18699
  const posted = await this.call(headers, "chat.postMessage", {
18310
18700
  channel: channelId,
18311
18701
  text: input.text,
18312
- ...blocks ? { blocks: JSON.stringify(blocks) } : {},
18702
+ ...wireBlocks ? { blocks: JSON.stringify(wireBlocks) } : {},
18313
18703
  client_msg_id: input.operationId,
18314
18704
  unfurl_links: "false",
18315
18705
  unfurl_media: "false",
@@ -18367,6 +18757,7 @@ var OpenGeniSlackBotClient = class {
18367
18757
  let providerCallStarted = false;
18368
18758
  const blocks = validateSlackMessageBlocks(input.blocks);
18369
18759
  try {
18760
+ const wireBlocks = slackMessageWireBlocks(blocks);
18370
18761
  const headers = await this.headersFor(operation);
18371
18762
  await this.requireMemberChannel(headers, input.channelId);
18372
18763
  const requestDigest = this.updateRequestDigest({ ...input, ...blocks ? { blocks } : {} });
@@ -18405,7 +18796,7 @@ var OpenGeniSlackBotClient = class {
18405
18796
  channel: input.channelId,
18406
18797
  ts: input.timestamp,
18407
18798
  text: input.text,
18408
- ...blocks ? { blocks: JSON.stringify(blocks) } : {}
18799
+ ...wireBlocks ? { blocks: JSON.stringify(wireBlocks) } : {}
18409
18800
  });
18410
18801
  const slackChannelId = requiredSlackString(updated.channel, "channel");
18411
18802
  const slackMessageTimestamp = requiredSlackString(updated.ts, "ts");
@@ -19713,6 +20104,20 @@ function nextSlackFilesListPage(payload, requested, returnedFileCount) {
19713
20104
  }
19714
20105
  return nextPage;
19715
20106
  }
20107
+ function slackMessageWireBlocks(blocks) {
20108
+ if (!blocks) return void 0;
20109
+ const wire = blocks.flatMap((block, index) => {
20110
+ if (block.type !== "actions" || new Set(block.elements.map((e) => e.action_id)).size === block.elements.length)
20111
+ return [block];
20112
+ const id = createHash7("sha256").update(`${index}:${block.block_id}`).digest("hex").slice(0, 24);
20113
+ return block.elements.map((element, position2) => ({
20114
+ type: "actions",
20115
+ block_id: `opengeni_wire_${id}_${position2}`,
20116
+ elements: [element]
20117
+ }));
20118
+ });
20119
+ return validateSlackMessageBlocks(wire);
20120
+ }
19716
20121
  function validateSlackMessageBlocks(blocks) {
19717
20122
  if (blocks === void 0) return void 0;
19718
20123
  if (blocks.length < 1 || blocks.length > MAX_SLACK_BLOCKS) {
@@ -19778,7 +20183,7 @@ function slackMutationOutcomeMayBeAmbiguous(error) {
19778
20183
 
19779
20184
  // src/integrations/fiken.ts
19780
20185
  import { withOrganizationIntegrationAcquisition as withOrganizationIntegrationAcquisition3 } from "@opengeni/db/organization-integration-policy";
19781
- import { createHash as createHash7 } from "crypto";
20186
+ import { createHash as createHash8 } from "crypto";
19782
20187
  import { ExternalActorContinuation as ExternalActorContinuation3 } from "@opengeni/contracts/external-identities";
19783
20188
  import { requireConnectOwnerAuthority as requireConnectOwnerAuthority2 } from "@opengeni/core";
19784
20189
  import {
@@ -20599,7 +21004,7 @@ async function completeFikenOAuthCallback(deps, input) {
20599
21004
  operation = {
20600
21005
  attemptId: state.connectAttemptId,
20601
21006
  operationId: `oauth:${state.nonce}`,
20602
- inputDigest: createHash7("sha256").update(input.state).digest("hex")
21007
+ inputDigest: createHash8("sha256").update(input.state).digest("hex")
20603
21008
  };
20604
21009
  const claim = await claimOAuthAcquisition(
20605
21010
  deps.db,
@@ -20906,7 +21311,7 @@ import {
20906
21311
  knowledgeSourceAgentConfig,
20907
21312
  assertOrganizationIntegrationAllowed as assertOrganizationIntegrationAllowed2
20908
21313
  } from "@opengeni/contracts";
20909
- import { createHash as createHash8 } from "crypto";
21314
+ import { createHash as createHash9 } from "crypto";
20910
21315
  import { ExternalActorContinuation as ExternalActorContinuation4 } from "@opengeni/contracts/external-identities";
20911
21316
  import {
20912
21317
  ATLASSIAN_CREDENTIAL_LABEL,
@@ -21032,7 +21437,7 @@ async function completeAtlassianOAuthCallback(deps, input) {
21032
21437
  operation = {
21033
21438
  attemptId: state.connectAttemptId,
21034
21439
  operationId: `oauth:${state.nonce}`,
21035
- inputDigest: createHash8("sha256").update(input.state).digest("hex")
21440
+ inputDigest: createHash9("sha256").update(input.state).digest("hex")
21036
21441
  };
21037
21442
  const claim = await claimOAuthAcquisition(
21038
21443
  deps.db,
@@ -22466,7 +22871,7 @@ function adfText(value) {
22466
22871
  import { AtlassianConnectionMetadata as AtlassianConnectionMetadata2 } from "@opengeni/contracts/atlassian";
22467
22872
 
22468
22873
  // src/mcp/editable-artifacts.ts
22469
- import { createHash as createHash9 } from "crypto";
22874
+ import { createHash as createHash10 } from "crypto";
22470
22875
  import {
22471
22876
  editableArtifactClientTransactionId as editableArtifactClientTransactionId2,
22472
22877
  editableArtifactId as editableArtifactId2
@@ -22889,7 +23294,7 @@ function registerEditableArtifactAgentTools(input) {
22889
23294
  }
22890
23295
  function artifactAttemptContext(grant, sessionId, toolName, extra) {
22891
23296
  const operationId = trustedOperationId(extra);
22892
- const digest2 = createHash9("sha256").update("opengeni:editable-artifact-agent-call:v1\0", "utf8").update(grant.accountId, "utf8").update("\0", "utf8").update(grant.workspaceId, "utf8").update("\0", "utf8").update(sessionId, "utf8").update("\0", "utf8").update(String(grant.metadata?.["turnId"] ?? ""), "utf8").update("\0", "utf8").update(String(grant.metadata?.["attemptId"] ?? ""), "utf8").update("\0", "utf8").update(String(grant.metadata?.["executionGeneration"] ?? ""), "utf8").update("\0", "utf8").update(toolName, "utf8").update("\0", "utf8").update(operationId, "utf8").digest("hex");
23297
+ const digest2 = createHash10("sha256").update("opengeni:editable-artifact-agent-call:v1\0", "utf8").update(grant.accountId, "utf8").update("\0", "utf8").update(grant.workspaceId, "utf8").update("\0", "utf8").update(sessionId, "utf8").update("\0", "utf8").update(String(grant.metadata?.["turnId"] ?? ""), "utf8").update("\0", "utf8").update(String(grant.metadata?.["attemptId"] ?? ""), "utf8").update("\0", "utf8").update(String(grant.metadata?.["executionGeneration"] ?? ""), "utf8").update("\0", "utf8").update(toolName, "utf8").update("\0", "utf8").update(operationId, "utf8").digest("hex");
22893
23298
  const replicaId = digest2.slice(0, 16) === "0".repeat(16) ? `1${digest2.slice(1, 16)}` : digest2.slice(0, 16);
22894
23299
  const actor = editableArtifactActorForGrant(grant, replicaId);
22895
23300
  if (actor.kind !== "agent" || actor.sessionId !== sessionId) {
@@ -23095,7 +23500,7 @@ import {
23095
23500
  knowledgeSourceAgentConfig as knowledgeSourceAgentConfig2,
23096
23501
  assertOrganizationIntegrationAllowed as assertOrganizationIntegrationAllowed3
23097
23502
  } from "@opengeni/contracts";
23098
- import { createHash as createHash10, randomBytes as randomBytes5 } from "crypto";
23503
+ import { createHash as createHash11, randomBytes as randomBytes6 } from "crypto";
23099
23504
  import { ExternalActorContinuation as ExternalActorContinuation5 } from "@opengeni/contracts/external-identities";
23100
23505
  import {
23101
23506
  configuredGoogleDriveSyncLimits,
@@ -23216,7 +23621,7 @@ async function startGoogleDriveOAuth(deps, input) {
23216
23621
  requireGoogleDriveConnection(existing, input.subjectId);
23217
23622
  }
23218
23623
  const key = requireEnvironmentEncryption5(deps.settings);
23219
- const verifier = randomBytes5(48).toString("base64url");
23624
+ const verifier = randomBytes6(48).toString("base64url");
23220
23625
  const redirectUri = requireGoogleDriveOAuthCallbackUrl(deps.settings);
23221
23626
  const state = createSignedState7(requireIntegrationsStateSecret(deps.settings), {
23222
23627
  accountId: input.accountId,
@@ -23262,7 +23667,7 @@ async function startGoogleDriveOAuth(deps, input) {
23262
23667
  authorizationUrl.searchParams.set("code_challenge_method", "S256");
23263
23668
  authorizationUrl.searchParams.set(
23264
23669
  "code_challenge",
23265
- createHash10("sha256").update(verifier).digest("base64url")
23670
+ createHash11("sha256").update(verifier).digest("base64url")
23266
23671
  );
23267
23672
  return GoogleDriveOAuthStartResponse.parse({
23268
23673
  authorizationUrl: authorizationUrl.toString(),
@@ -23286,7 +23691,7 @@ async function completeGoogleDriveOAuthCallback(deps, input) {
23286
23691
  operation = {
23287
23692
  attemptId: state.connectAttemptId,
23288
23693
  operationId: `oauth:${state.nonce}`,
23289
- inputDigest: createHash10("sha256").update(input.state).digest("hex")
23694
+ inputDigest: createHash11("sha256").update(input.state).digest("hex")
23290
23695
  };
23291
23696
  const claim = await claimOAuthAcquisition(
23292
23697
  deps.db,
@@ -25206,7 +25611,7 @@ function uniqueStrings3(values) {
25206
25611
  }
25207
25612
 
25208
25613
  // src/temporal-schedule-cleanup.ts
25209
- import { randomUUID } from "crypto";
25614
+ import { randomUUID as randomUUID2 } from "crypto";
25210
25615
  import {
25211
25616
  claimTemporalScheduleCleanups,
25212
25617
  completeTemporalScheduleConnectorCleanup,
@@ -25278,7 +25683,7 @@ async function processTemporalScheduleCleanupClaims(deps, claims) {
25278
25683
  }
25279
25684
  async function drainTemporalScheduleCleanupOutbox(deps) {
25280
25685
  const claims = await claimTemporalScheduleCleanups(deps.db, {
25281
- claimId: randomUUID(),
25686
+ claimId: randomUUID2(),
25282
25687
  limit: CLEANUP_BATCH_SIZE,
25283
25688
  claimSeconds: CLEANUP_CLAIM_SECONDS
25284
25689
  });
@@ -26627,7 +27032,7 @@ function registerSandboxFileArtifactTool(server, deps, grant, sessionId, json) {
26627
27032
  server.registerTool(
26628
27033
  "sandbox_file_publish",
26629
27034
  {
26630
- description: "Publish one exact file from this session's /workspace into durable workspace storage. Use this before presenting a ZIP, CSV, JSON, Markdown, HTML, PDF, Office file, or other sandbox output as downloadable. Returns a permanent, authenticated artifact receipt; never invent or expose a sandbox: URL as the durable result.",
27035
+ description: "Publish one exact file from this session's /workspace into durable workspace storage. Use this before presenting a video, ZIP, CSV, JSON, Markdown, HTML, PDF, Office file, or other sandbox output as downloadable. Present the returned artifact.artifactId as [Open file](artifact:<artifactId>), or ![Preview](artifact:<artifactId>) for inline image/video/audio/PDF previews. Replace <artifactId> with the exact returned ID and use a descriptive label. Never expose a sandbox: URL as the durable result.",
26631
27036
  inputSchema: {
26632
27037
  path: z43.string().min(1).max(4096)
26633
27038
  }
@@ -27369,7 +27774,7 @@ function registerGoalTools(server, deps, grant, sessionId, json) {
27369
27774
  async ({ reason, timeoutSeconds, idempotencyKey }) => {
27370
27775
  await authorizeFirstPartySession(deps, grant, sessionId, "session.control");
27371
27776
  const context = exactAgentCommandContext(grant, sessionId);
27372
- const operationKey = idempotencyKey ?? `wait-for-input:${context.callerTurnId}:${createHash11("sha256").update(JSON.stringify({ reason, timeoutSeconds })).digest("hex").slice(0, 32)}`;
27777
+ const operationKey = idempotencyKey ?? `wait-for-input:${context.callerTurnId}:${createHash12("sha256").update(JSON.stringify({ reason, timeoutSeconds })).digest("hex").slice(0, 32)}`;
27373
27778
  const { events, operationId, replay, deadlineAt } = await waitForSessionInputWithEvent(
27374
27779
  deps.db,
27375
27780
  grant.workspaceId,
@@ -27610,7 +28015,7 @@ function registerWorkspaceArtifactTools(server, deps, grant, sessionId, json) {
27610
28015
  return {
27611
28016
  accountId: grant.accountId,
27612
28017
  workspaceId: grant.workspaceId,
27613
- operationKey: `attempt:${createHash11("sha256").update(`${claims.sessionId}:${claims.turnId}:${idempotencyKey}`).digest("hex")}`,
28018
+ operationKey: `attempt:${createHash12("sha256").update(`${claims.sessionId}:${claims.turnId}:${idempotencyKey}`).digest("hex")}`,
27614
28019
  actorSubjectId: grant.subjectId,
27615
28020
  sourceSessionId: claims.sessionId,
27616
28021
  sourceTurnId: claims.turnId,
@@ -28300,7 +28705,7 @@ function registerFleetTools(server, deps, grant, sessionId, json) {
28300
28705
  server.registerTool(
28301
28706
  "sandbox_provision",
28302
28707
  {
28303
- description: "Provision a new sandbox for the fleet. kind=selfhosted returns device-flow enrollment instructions to share with a HUMAN (install the agent + enroll their machine with loud whole-machine consent \u2014 the agent cannot self-consent). kind=modal creates a named Modal sandbox record, but it is NOT yet attachable as a swap target: routing a session onto a second Modal box is not supported yet, so sandbox_swap to its id is rejected. Use the session's own box (the default) or attach a Connected Machine instead.",
28708
+ description: "Provision a new sandbox for the fleet. kind=selfhosted returns interactive device-flow instructions for a human to approve. For authorized headless enrollment, use connected_machine_enroll_token when available instead. kind=modal creates a named Modal sandbox record, but it is NOT yet attachable as a swap target: routing a session onto a second Modal box is not supported yet, so sandbox_swap to its id is rejected. Use the session's own box (the default) or attach a Connected Machine instead.",
28304
28709
  inputSchema: {
28305
28710
  kind: z43.enum(["selfhosted", "modal"]),
28306
28711
  name: z43.string().min(1).max(120).optional()
@@ -28315,10 +28720,38 @@ function registerFleetTools(server, deps, grant, sessionId, json) {
28315
28720
  );
28316
28721
  }
28317
28722
  function registerConnectedMachineTools(server, deps, grant, sessionId, json) {
28723
+ server.registerTool(
28724
+ "connected_machine_enroll_token",
28725
+ {
28726
+ description: "Create a short-lived Connected Machine enrollment token for this workspace using existing enrollments:manage authority. Returns the token, expiry and Unix/PowerShell install commands. Run the appropriate command on the intended machine through an already-authorized execution path, then verify it with sandboxes_list. No separate device approval is required. Screen control is optional and defaults off. The token grants whole-machine access on enrollment; do not put it in public code or unrelated logs. Existing machine connections are preserved.",
28727
+ inputSchema: { allowScreenControl: z43.boolean().optional() }
28728
+ },
28729
+ async ({ allowScreenControl }) => {
28730
+ if (sessionId) {
28731
+ await authorizeFirstPartySession(deps, grant, sessionId, "session.first_party_mcp.call");
28732
+ }
28733
+ const minted = await mintEnrollToken(deps, {
28734
+ accountId: grant.accountId,
28735
+ workspaceId: grant.workspaceId,
28736
+ allowScreenControl: allowScreenControl ?? false
28737
+ });
28738
+ if (!minted) throw new Error("enrollment credential plane is not configured");
28739
+ const base = (deps.settings.publicBaseUrl ?? "https://app.opengeni.ai").replace(/\/+$/, "");
28740
+ const unixQuote = (value) => `'${value.replaceAll("'", "'\\''")}'`;
28741
+ const windowsQuote = (value) => `'${value.replaceAll("'", "''")}'`;
28742
+ return json({
28743
+ ...minted,
28744
+ workspaceId: grant.workspaceId,
28745
+ allowScreenControl: allowScreenControl ?? false,
28746
+ installCommandUnix: `curl -fsSL ${unixQuote(`${base}/install.sh`)} | OPENGENI_API_URL=${unixQuote(base)} OPENGENI_ENROLL_TOKEN=${unixQuote(minted.token)} sh`,
28747
+ installCommandWindows: `$env:OPENGENI_API_URL=${windowsQuote(base)}; $env:OPENGENI_ENROLL_TOKEN=${windowsQuote(minted.token)}; irm ${windowsQuote(`${base}/install.ps1`)} | iex`
28748
+ });
28749
+ }
28750
+ );
28318
28751
  server.registerTool(
28319
28752
  "connected_machine_remove",
28320
28753
  {
28321
- description: "Remove one enrolled self-hosted machine while it is offline. Access is revoked, future heartbeat/reconnect credentials are rejected, and session, route, lease, archive, and audit history is retained. Idle dependent sessions are detached atomically; machine-home sessions become compute-less (backend none) until another sandbox is selected. Active turns, live leases, and recovery work remain fail-closed blockers whose typed outcome explains what must settle before retrying. Pass the enrollmentId from the Machines surface, never a Modal sandbox id. Reconnecting later requires a fresh human-approved device-flow enrollment.",
28754
+ description: "Remove one enrolled self-hosted machine while it is offline. Access is revoked, future heartbeat/reconnect credentials are rejected, and session, route, lease, archive, and audit history is retained. Idle dependent sessions are detached atomically; machine-home sessions become compute-less (backend none) until another sandbox is selected. Active turns, live leases, and recovery work remain fail-closed blockers whose typed outcome explains what must settle before retrying. Pass the enrollmentId from the Machines surface, never a Modal sandbox id. Reconnecting later requires fresh enrollment through device approval or an authorized enrollment token.",
28322
28755
  inputSchema: {
28323
28756
  enrollmentId: z43.string().uuid(),
28324
28757
  expectedUpdatedAt: z43.string().datetime({ offset: true }).optional(),
@@ -28343,7 +28776,7 @@ function registerConnectedMachineTools(server, deps, grant, sessionId, json) {
28343
28776
  accountId: grant.accountId,
28344
28777
  workspaceId: enrollment.workspaceId,
28345
28778
  enrollmentId,
28346
- operationKey: idempotencyKey?.trim() || randomUUID2(),
28779
+ operationKey: idempotencyKey?.trim() || randomUUID3(),
28347
28780
  ...expectedUpdatedAt ? { expectedUpdatedAt } : {},
28348
28781
  subjectId: resourceGrant.subjectId
28349
28782
  });
@@ -28671,6 +29104,18 @@ function exactAgentCommandContext(grant, callerSessionId, authorizationSurface)
28671
29104
  };
28672
29105
  }
28673
29106
  function registerWorkspaceOrchestrationTools(server, deps, grant, can, callerSessionId, sessionCreateVisible, json) {
29107
+ const acknowledgeReads = async (children) => {
29108
+ if (!callerSessionId || !exactAgentAttemptClaims(grant) || !children.some((child) => child.sequences.length > 0))
29109
+ return;
29110
+ const actor = await requireLiveAgentAttemptAuthorization4(deps.db, grant, callerSessionId);
29111
+ if (!actor.initiatingHumanSubjectId) return;
29112
+ await acknowledgeConsumedChildEvents(deps.db, {
29113
+ workspaceId: grant.workspaceId,
29114
+ sessionId: callerSessionId,
29115
+ subjectId: actor.initiatingHumanSubjectId,
29116
+ children
29117
+ });
29118
+ };
28674
29119
  if (can("sessions:read")) {
28675
29120
  server.registerTool(
28676
29121
  "sessions_list",
@@ -28965,29 +29410,29 @@ function registerWorkspaceOrchestrationTools(server, deps, grant, can, callerSes
28965
29410
  if (view !== "debug" && !auditRequested) {
28966
29411
  const { readSessionEventView } = await import("./session-event-view-MU3HMNV3.js");
28967
29412
  const { listSessionEventSlices } = await import("@opengeni/db/session-event-slices");
28968
- return json(
28969
- await readSessionEventView(
28970
- {
28971
- sessionId,
28972
- view,
28973
- cursor,
28974
- callId,
28975
- includeArguments,
28976
- includeOutput,
28977
- after,
28978
- before,
28979
- direction: requestedDirection,
28980
- limit
28981
- },
28982
- (options) => listSessionEventSlices(
28983
- deps.db,
28984
- grant.workspaceId,
28985
- sessionId,
28986
- options,
28987
- (legacyOptions) => listSessionEventPage(deps.db, grant.workspaceId, sessionId, legacyOptions)
28988
- )
29413
+ const page2 = await readSessionEventView(
29414
+ {
29415
+ sessionId,
29416
+ view,
29417
+ cursor,
29418
+ callId,
29419
+ includeArguments,
29420
+ includeOutput,
29421
+ after,
29422
+ before,
29423
+ direction: requestedDirection,
29424
+ limit
29425
+ },
29426
+ (options) => listSessionEventSlices(
29427
+ deps.db,
29428
+ grant.workspaceId,
29429
+ sessionId,
29430
+ options,
29431
+ (legacyOptions) => listSessionEventPage(deps.db, grant.workspaceId, sessionId, legacyOptions)
28989
29432
  )
28990
29433
  );
29434
+ await acknowledgeReads([{ sessionId, sequences: completeChildReadSequences(page2) }]);
29435
+ return json(page2);
28991
29436
  }
28992
29437
  if (cursor !== void 0 || callId !== void 0 || includeArguments !== void 0 || includeOutput !== void 0) {
28993
29438
  throw new Error("cursor/callId/includeArguments/includeOutput require a non-debug view");
@@ -29017,31 +29462,37 @@ function registerWorkspaceOrchestrationTools(server, deps, grant, can, callerSes
29017
29462
  });
29018
29463
  if (requestedResultMode === "compact") {
29019
29464
  const event = dbPage.events[0];
29020
- return json(
29021
- event ? boundSessionEventCompactResult(
29022
- compactSessionEventResult2(
29023
- event,
29024
- latestClass,
29025
- dbPage.coveredSequence ?? {
29026
- first: event.sequence,
29027
- last: event.sequence
29028
- }
29029
- )
29030
- ) : null
29031
- );
29465
+ const result = event ? boundSessionEventCompactResult(
29466
+ compactSessionEventResult2(
29467
+ event,
29468
+ latestClass,
29469
+ dbPage.coveredSequence ?? {
29470
+ first: event.sequence,
29471
+ last: event.sequence
29472
+ }
29473
+ )
29474
+ ) : null;
29475
+ if (result && ["turn.completed", "agent.message.completed"].includes(result.type) && !result.truncation.truncated && dbPage.fullPayloadsExact) {
29476
+ await acknowledgeReads([{ sessionId, sequences: [result.sequence] }]);
29477
+ }
29478
+ return json(result);
29032
29479
  }
29033
- return json(
29034
- boundSessionEventMcpPage({
29035
- events: dbPage.events,
29036
- mode,
29037
- payloadMode,
29038
- direction,
29039
- sourceHasMore: dbPage.hasMore,
29040
- sourceTruncatedBy: dbPage.truncatedBy,
29041
- after: after ?? 0,
29042
- before: before ?? null
29043
- })
29044
- );
29480
+ const page = boundSessionEventMcpPage({
29481
+ events: dbPage.events,
29482
+ mode,
29483
+ payloadMode,
29484
+ direction,
29485
+ sourceHasMore: dbPage.hasMore,
29486
+ sourceTruncatedBy: dbPage.truncatedBy,
29487
+ after: after ?? 0,
29488
+ before: before ?? null
29489
+ });
29490
+ if (payloadMode === "full" && dbPage.fullPayloadsExact && !page.truncation?.reasons.includes("model_payload")) {
29491
+ await acknowledgeReads([
29492
+ { sessionId, sequences: page.events.map((event) => event.sequence) }
29493
+ ]);
29494
+ }
29495
+ return json(page);
29045
29496
  }
29046
29497
  );
29047
29498
  server.registerTool(
@@ -29077,45 +29528,52 @@ function registerWorkspaceOrchestrationTools(server, deps, grant, can, callerSes
29077
29528
  const targetEventTypes = waitFor === "completion" ? SESSION_WAIT_COMPLETION_EVENT_TYPES : SESSION_WAIT_EVENT_TYPES;
29078
29529
  const signal = extra?.signal;
29079
29530
  const workspaceId = grant.workspaceId;
29080
- return json(
29081
- await waitForSessionChanges({
29082
- targets,
29083
- ownSessionId,
29084
- maxWaitMs: (maxWaitSeconds ?? SESSION_WAIT_DEFAULT_SECONDS) * 1e3,
29085
- targetEventTypes,
29086
- targetEventMatches: waitFor === "completion" ? sessionWaitCompletionEventMatches : void 0,
29087
- signal,
29088
- source: {
29089
- reauthorizeTargets: async (sessionIds) => {
29090
- for (const targetSessionId of sessionIds) {
29091
- await authorizeFirstPartySession(
29092
- deps,
29093
- grant,
29094
- targetSessionId,
29095
- "session.events.read"
29096
- );
29097
- }
29098
- },
29099
- readTargetEvents: async (target) => {
29100
- const page = await listSessionEventPage(deps.db, workspaceId, target.sessionId, {
29101
- after: target.afterSequence,
29102
- direction: "after",
29103
- limit: SESSION_WAIT_EVENTS_PER_TARGET,
29104
- payloadMode: "full",
29105
- includeTypes: targetEventTypes,
29106
- maxBytes: SESSION_EVENT_MCP_MAX_BYTES * 4
29107
- });
29108
- return { events: page.events, hasMore: page.hasMore };
29109
- },
29110
- readOwnPendingUpdateKinds: ownSessionId === null ? null : async () => (await listOutstandingSessionSystemUpdates(
29111
- deps.db,
29112
- workspaceId,
29113
- ownSessionId
29114
- )).map((update) => update.kind),
29115
- subscribe: (targetSessionId, onEvents) => deps.bus.subscribe(workspaceId, targetSessionId, onEvents)
29116
- }
29117
- })
29118
- );
29531
+ const incompleteWaitEvents = /* @__PURE__ */ new Set();
29532
+ const result = await waitForSessionChanges({
29533
+ targets,
29534
+ ownSessionId,
29535
+ maxWaitMs: (maxWaitSeconds ?? SESSION_WAIT_DEFAULT_SECONDS) * 1e3,
29536
+ targetEventTypes,
29537
+ targetEventMatches: waitFor === "completion" ? sessionWaitCompletionEventMatches : void 0,
29538
+ signal,
29539
+ source: {
29540
+ reauthorizeTargets: async (sessionIds) => {
29541
+ for (const targetSessionId of sessionIds) {
29542
+ await authorizeFirstPartySession(
29543
+ deps,
29544
+ grant,
29545
+ targetSessionId,
29546
+ "session.events.read"
29547
+ );
29548
+ }
29549
+ },
29550
+ readTargetEvents: async (target) => {
29551
+ const page = await listSessionEventPage(deps.db, workspaceId, target.sessionId, {
29552
+ after: target.afterSequence,
29553
+ direction: "after",
29554
+ limit: SESSION_WAIT_EVENTS_PER_TARGET,
29555
+ payloadMode: "full",
29556
+ includeTypes: targetEventTypes,
29557
+ maxBytes: SESSION_EVENT_MCP_MAX_BYTES * 4
29558
+ });
29559
+ if (!page.fullPayloadsExact) {
29560
+ for (const event of page.events) incompleteWaitEvents.add(event.id);
29561
+ }
29562
+ return { events: page.events, hasMore: page.hasMore };
29563
+ },
29564
+ readOwnPendingUpdateKinds: ownSessionId === null ? null : async () => (await listOutstandingSessionSystemUpdates(deps.db, workspaceId, ownSessionId)).map((update) => update.kind),
29565
+ subscribe: (targetSessionId, onEvents) => deps.bus.subscribe(workspaceId, targetSessionId, onEvents)
29566
+ }
29567
+ });
29568
+ if (!result.aborted && !result.truncated) {
29569
+ await acknowledgeReads(
29570
+ result.changed.map((target) => ({
29571
+ sessionId: target.sessionId,
29572
+ sequences: target.events.filter((event) => event.contentComplete && !incompleteWaitEvents.has(event.id)).map((event) => event.sequence)
29573
+ }))
29574
+ );
29575
+ }
29576
+ return json(result);
29119
29577
  }
29120
29578
  );
29121
29579
  if (callerSessionId !== null) {
@@ -60552,7 +61010,7 @@ function registerOrganizationIntegrationPolicyRoutes(app, deps) {
60552
61010
  }
60553
61011
 
60554
61012
  // src/routes/connections.ts
60555
- import { createHash as createHash14, createHmac as createHmac4 } from "crypto";
61013
+ import { createHash as createHash15, createHmac as createHmac4 } from "crypto";
60556
61014
  import {
60557
61015
  createConnectionIdempotently,
60558
61016
  getConnectionCreationResult,
@@ -60721,7 +61179,7 @@ import { HTTPException as HTTPException35 } from "hono/http-exception";
60721
61179
  // src/integrations/provider-oauth.ts
60722
61180
  import { withOrganizationIntegrationAcquisition as withOrganizationIntegrationAcquisition6 } from "@opengeni/db/organization-integration-policy";
60723
61181
  import { Buffer as Buffer4 } from "buffer";
60724
- import { createHash as createHash12, randomBytes as randomBytes6 } from "crypto";
61182
+ import { createHash as createHash13, randomBytes as randomBytes7 } from "crypto";
60725
61183
  import {
60726
61184
  integrationDefinitionProviderDomain as integrationDefinitionProviderDomain2,
60727
61185
  integrationDefinitionById
@@ -60804,7 +61262,7 @@ async function startApiIntegrationProviderOAuth(deps, input) {
60804
61262
  ...definition.authentication.scopes
60805
61263
  ]);
60806
61264
  const client = providerClientForDefinition(deps.settings, definition);
60807
- const verifier = randomBytes6(48).toString("base64url");
61265
+ const verifier = randomBytes7(48).toString("base64url");
60808
61266
  const key = requireEnvironmentEncryption8(deps.settings);
60809
61267
  const baseUrl = integrationBaseUrl(deps.settings.publicBaseUrl, input.requestUrl);
60810
61268
  const redirectUri = `${baseUrl}${providerOAuthCallbackPath(definition)}`;
@@ -60849,7 +61307,7 @@ async function startApiIntegrationProviderOAuth(deps, input) {
60849
61307
  authorizationUrl.searchParams.set("code_challenge_method", "S256");
60850
61308
  authorizationUrl.searchParams.set(
60851
61309
  "code_challenge",
60852
- createHash12("sha256").update(verifier).digest("base64url")
61310
+ createHash13("sha256").update(verifier).digest("base64url")
60853
61311
  );
60854
61312
  authorizationUrl.searchParams.set("prompt", "select_account");
60855
61313
  if (definition.provider.id === "google") {
@@ -60879,7 +61337,7 @@ async function completeApiIntegrationProviderOAuth(deps, input) {
60879
61337
  connectOperation = {
60880
61338
  attemptId: state.connectAttemptId,
60881
61339
  operationId: `oauth:${state.nonce}`,
60882
- inputDigest: createHash12("sha256").update(input.state).digest("hex")
61340
+ inputDigest: createHash13("sha256").update(input.state).digest("hex")
60883
61341
  };
60884
61342
  const claim = await claimOAuthAcquisition(
60885
61343
  deps.db,
@@ -61172,7 +61630,7 @@ function providerClientKeys(definition) {
61172
61630
  ]);
61173
61631
  }
61174
61632
  function providerDefinitionFingerprint(definition) {
61175
- return createHash12("sha256").update(
61633
+ return createHash13("sha256").update(
61176
61634
  JSON.stringify({
61177
61635
  id: definition.id,
61178
61636
  provider: definition.provider,
@@ -61425,7 +61883,7 @@ function numberValue4(value) {
61425
61883
 
61426
61884
  // src/integrations/personal-github.ts
61427
61885
  import { withOrganizationIntegrationAcquisition as withOrganizationIntegrationAcquisition7 } from "@opengeni/db/organization-integration-policy";
61428
- import { createHash as createHash13, randomBytes as randomBytes7, randomUUID as randomUUID3 } from "crypto";
61886
+ import { createHash as createHash14, randomBytes as randomBytes8, randomUUID as randomUUID4 } from "crypto";
61429
61887
  import { ExternalActorContinuation as ExternalActorContinuation8 } from "@opengeni/contracts/external-identities";
61430
61888
  import { personalGitHubOAuthCallbackUrl } from "@opengeni/config";
61431
61889
  import {
@@ -61472,7 +61930,7 @@ var PersonalGitHubCallbackError = class extends Error {
61472
61930
  }
61473
61931
  };
61474
61932
  function personalGitHubClientMarker(clientId) {
61475
- return createHash13("sha256").update(clientId).digest("hex").slice(0, 32);
61933
+ return createHash14("sha256").update(clientId).digest("hex").slice(0, 32);
61476
61934
  }
61477
61935
  function requirePersonalGitHubOAuthSettings(settings) {
61478
61936
  if (!settings.githubPersonalOauthEnabled) {
@@ -61555,7 +62013,7 @@ async function startPersonalGitHubOAuth(deps, input) {
61555
62013
  });
61556
62014
  }
61557
62015
  const key = requireEnvironmentEncryption9(deps.settings);
61558
- const verifier = randomBytes7(48).toString("base64url");
62016
+ const verifier = randomBytes8(48).toString("base64url");
61559
62017
  const returnPath = personalGitHubReturnPath(input.workspaceId, input.returnPath);
61560
62018
  const state = createSignedState11(requireIntegrationsStateSecret(deps.settings), {
61561
62019
  accountId: grant.accountId,
@@ -61584,7 +62042,7 @@ async function startPersonalGitHubOAuth(deps, input) {
61584
62042
  authorizationUrl.searchParams.set("state", state);
61585
62043
  authorizationUrl.searchParams.set(
61586
62044
  "code_challenge",
61587
- createHash13("sha256").update(verifier).digest("base64url")
62045
+ createHash14("sha256").update(verifier).digest("base64url")
61588
62046
  );
61589
62047
  authorizationUrl.searchParams.set("code_challenge_method", "S256");
61590
62048
  return PersonalGitHubOAuthStartResponse.parse({
@@ -61608,7 +62066,7 @@ async function completePersonalGitHubOAuthCallback(deps, input) {
61608
62066
  operation = {
61609
62067
  attemptId: state.connectAttemptId,
61610
62068
  operationId: `oauth:${state.nonce}`,
61611
- inputDigest: createHash13("sha256").update(input.state).digest("hex")
62069
+ inputDigest: createHash14("sha256").update(input.state).digest("hex")
61612
62070
  };
61613
62071
  const claim = await claimOAuthAcquisition(
61614
62072
  deps.db,
@@ -61710,7 +62168,7 @@ async function completePersonalGitHubOAuthCallback(deps, input) {
61710
62168
  githubLogin: identity2.login,
61711
62169
  oauthEnvironment: oauth.oauthEnvironment,
61712
62170
  oauthClientMarker: oauth.oauthClientMarker,
61713
- credentialBindingId: requestedMetadata?.credentialBindingId ?? randomUUID3(),
62171
+ credentialBindingId: requestedMetadata?.credentialBindingId ?? randomUUID4(),
61714
62172
  connectedAt: requestedMetadata?.connectedAt ?? now,
61715
62173
  lastVerifiedAt: now,
61716
62174
  disconnectedAt: null,
@@ -62255,7 +62713,7 @@ function registerConnectionRoutes(app, deps) {
62255
62713
  operation = {
62256
62714
  attemptId: state.connectAttemptId,
62257
62715
  operationId: `oauth:${state.nonce}`,
62258
- inputDigest: createHash14("sha256").update(c.req.query("state")).digest("hex")
62716
+ inputDigest: createHash15("sha256").update(c.req.query("state")).digest("hex")
62259
62717
  };
62260
62718
  const callbackState = state;
62261
62719
  const callbackOperation = operation;
@@ -62414,7 +62872,7 @@ function registerConnectionRoutes(app, deps) {
62414
62872
  accountId: state.accountId,
62415
62873
  workspaceId: state.workspaceId,
62416
62874
  subjectId: state.subjectId,
62417
- callbackDigest: createHash14("sha256").update(state.nonce).digest("hex"),
62875
+ callbackDigest: createHash15("sha256").update(state.nonce).digest("hex"),
62418
62876
  installMode: state.connectionId ? "reinstall" : "connect",
62419
62877
  ...failure
62420
62878
  });
@@ -63445,7 +63903,7 @@ function slackBotCredentialBundle(token) {
63445
63903
  }
63446
63904
 
63447
63905
  // src/routes/connect.ts
63448
- import { createHash as createHash17, createHmac as createHmac5, randomUUID as randomUUID4 } from "crypto";
63906
+ import { createHash as createHash18, createHmac as createHmac5, randomUUID as randomUUID5 } from "crypto";
63449
63907
  import { HTTPException as HTTPException39 } from "hono/http-exception";
63450
63908
  import { getConnectBeginReplay } from "@opengeni/db/connect-attempts";
63451
63909
  import {
@@ -63496,7 +63954,7 @@ import {
63496
63954
  } from "@opengeni/core";
63497
63955
 
63498
63956
  // src/integrations/github-app-connect.ts
63499
- import { createHash as createHash15 } from "crypto";
63957
+ import { createHash as createHash16 } from "crypto";
63500
63958
  import { z as z19 } from "zod";
63501
63959
  import { HTTPException as HTTPException37 } from "hono/http-exception";
63502
63960
  import {
@@ -63705,7 +64163,7 @@ async function completeGitHubAppConnect(deps, input) {
63705
64163
  const operation = {
63706
64164
  attemptId: state.connectAttemptId,
63707
64165
  operationId: `github:${state.nonce}`,
63708
- inputDigest: createHash15("sha256").update(input.state).digest("hex"),
64166
+ inputDigest: createHash16("sha256").update(input.state).digest("hex"),
63709
64167
  authorize
63710
64168
  };
63711
64169
  const claim = await claimOAuthAcquisition(
@@ -63956,7 +64414,7 @@ import {
63956
64414
  import { HTTPException as HTTPException38 } from "hono/http-exception";
63957
64415
 
63958
64416
  // src/integrations/api-integrations.ts
63959
- import { createHash as createHash16 } from "crypto";
64417
+ import { createHash as createHash17 } from "crypto";
63960
64418
  import {
63961
64419
  compileGraphqlRevision,
63962
64420
  compileOpenApiRevision,
@@ -64175,7 +64633,7 @@ function resolvedPreview(input) {
64175
64633
  };
64176
64634
  }
64177
64635
  function integrationInstallationIdentity(protocol, label, locator2) {
64178
- const hash = createHash16("sha256").update(`${protocol}\0${locator2}`).digest("hex").slice(0, 12);
64636
+ const hash = createHash17("sha256").update(`${protocol}\0${locator2}`).digest("hex").slice(0, 12);
64179
64637
  const slug = label.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 48) || "integration";
64180
64638
  return {
64181
64639
  sourceDerivedDefinitionId: `${slug}-${hash}`,
@@ -65000,7 +65458,7 @@ function registerConnectRoutes(app, deps) {
65000
65458
  attemptId: before.id,
65001
65459
  expectedRevision: input.expectedRevision,
65002
65460
  operationId: input.idempotencyKey,
65003
- inputDigest: createHash17("sha256").update(stableJson4(input)).digest("hex"),
65461
+ inputDigest: createHash18("sha256").update(stableJson4(input)).digest("hex"),
65004
65462
  authorize: (tx, _attempt, origin) => requireConnectOwnerAuthority(tx, scope, "capabilities:manage", origin),
65005
65463
  execute: async (attempt) => {
65006
65464
  if (attempt.state !== "credential_input")
@@ -65042,7 +65500,7 @@ function registerConnectRoutes(app, deps) {
65042
65500
  attemptId: before.id,
65043
65501
  expectedRevision: input.expectedRevision,
65044
65502
  operationId: input.idempotencyKey,
65045
- inputDigest: createHash17("sha256").update(stableJson4(input)).digest("hex"),
65503
+ inputDigest: createHash18("sha256").update(stableJson4(input)).digest("hex"),
65046
65504
  authorize: async (tx, _attempt, origin) => {
65047
65505
  await requireConnectOwnerAuthority(tx, scope, installationPermission, origin);
65048
65506
  if (before.providerId === "github-lens") {
@@ -65068,7 +65526,7 @@ function registerConnectRoutes(app, deps) {
65068
65526
  attemptId: before.id,
65069
65527
  expectedRevision: input.expectedRevision,
65070
65528
  operationId: input.idempotencyKey,
65071
- inputDigest: createHash17("sha256").update(stableJson4(input)).digest("hex"),
65529
+ inputDigest: createHash18("sha256").update(stableJson4(input)).digest("hex"),
65072
65530
  authorize: (tx, _attempt, origin) => requireConnectOwnerAuthority(tx, scope, "connections:write", origin),
65073
65531
  execute: async (attempt) => {
65074
65532
  if (attempt.state !== "credential_input")
@@ -65367,7 +65825,7 @@ function registerConnectRoutes(app, deps) {
65367
65825
  attemptId: c.req.param("attemptId"),
65368
65826
  expectedRevision: input.expectedRevision,
65369
65827
  operationId: input.idempotencyKey,
65370
- inputDigest: createHash17("sha256").update(stableJson4(input)).digest("hex"),
65828
+ inputDigest: createHash18("sha256").update(stableJson4(input)).digest("hex"),
65371
65829
  authorize: (tx, _attempt, origin) => requireConnectOwnerAuthority(tx, scope, permission, origin),
65372
65830
  execute: async (attempt) => {
65373
65831
  if (!attempt.source && (!attempt.credentialsCommitted || !attempt.account) || !["connected_but_incomplete", "preview"].includes(attempt.state))
@@ -65475,7 +65933,7 @@ function registerConnectRoutes(app, deps) {
65475
65933
  attemptId: c.req.param("attemptId"),
65476
65934
  expectedRevision: input.expectedRevision,
65477
65935
  operationId: input.idempotencyKey,
65478
- inputDigest: createHash17("sha256").update(stableJson4({ ...input, action: "cancel" })).digest("hex"),
65936
+ inputDigest: createHash18("sha256").update(stableJson4({ ...input, action: "cancel" })).digest("hex"),
65479
65937
  purpose: "cancellation",
65480
65938
  authorize: async (tx, attempt, origin) => {
65481
65939
  const permission = attempt.providerId === "mcp-install" ? "capabilities:manage" : ["x", "reddit"].includes(attempt.providerId) ? attempt.ownership === "workspace" ? "workspace:admin" : "workspace:read" : attempt.providerId === "github-app" ? "github:manage" : attempt.providerId === "github-lens" ? "workspace:admin" : "connections:write";
@@ -65540,7 +65998,7 @@ function registerConnectRoutes(app, deps) {
65540
65998
  await requireConnectOwnerAuthority(actorTx, scope, setupPermission);
65541
65999
  const replay2 = await getConnectBeginReplay(actorTx, scope, {
65542
66000
  idempotencyKey: input.idempotencyKey,
65543
- requestDigest: createHash17("sha256").update(stableJson4(input)).digest("hex"),
66001
+ requestDigest: createHash18("sha256").update(stableJson4(input)).digest("hex"),
65544
66002
  returnUrl: input.returnUrl,
65545
66003
  ...continuation ? { externalContinuation: continuation } : {}
65546
66004
  });
@@ -65574,7 +66032,7 @@ function registerConnectRoutes(app, deps) {
65574
66032
  }
65575
66033
  );
65576
66034
  });
65577
- const id = randomUUID4();
66035
+ const id = randomUUID5();
65578
66036
  if (input.providerId === "mcp-install") {
65579
66037
  if (input.ownership !== "workspace" || input.reconnectAccountId || input.installationTarget)
65580
66038
  throw new HTTPException39(422, {
@@ -65596,7 +66054,7 @@ function registerConnectRoutes(app, deps) {
65596
66054
  return beginConnectAttempt(tx, scope, {
65597
66055
  ...continuation ? { externalContinuation: continuation } : {},
65598
66056
  idempotencyKey: input.idempotencyKey,
65599
- requestDigest: createHash17("sha256").update(stableJson4(input)).digest("hex"),
66057
+ requestDigest: createHash18("sha256").update(stableJson4(input)).digest("hex"),
65600
66058
  returnUrl: input.returnUrl,
65601
66059
  attempt: {
65602
66060
  id,
@@ -65654,7 +66112,7 @@ function registerConnectRoutes(app, deps) {
65654
66112
  return beginConnectAttempt(tx, scope, {
65655
66113
  ...continuation ? { externalContinuation: continuation } : {},
65656
66114
  idempotencyKey: input.idempotencyKey,
65657
- requestDigest: createHash17("sha256").update(stableJson4(input)).digest("hex"),
66115
+ requestDigest: createHash18("sha256").update(stableJson4(input)).digest("hex"),
65658
66116
  returnUrl: input.returnUrl,
65659
66117
  attempt: {
65660
66118
  id,
@@ -65704,7 +66162,7 @@ function registerConnectRoutes(app, deps) {
65704
66162
  return beginConnectAttempt(tx, scope, {
65705
66163
  ...continuation ? { externalContinuation: continuation } : {},
65706
66164
  idempotencyKey: input.idempotencyKey,
65707
- requestDigest: createHash17("sha256").update(stableJson4(input)).digest("hex"),
66165
+ requestDigest: createHash18("sha256").update(stableJson4(input)).digest("hex"),
65708
66166
  returnUrl: input.returnUrl,
65709
66167
  attempt: {
65710
66168
  id,
@@ -65739,7 +66197,7 @@ function registerConnectRoutes(app, deps) {
65739
66197
  return beginConnectAttempt(tx, scope, {
65740
66198
  ...continuation ? { externalContinuation: continuation } : {},
65741
66199
  idempotencyKey: input.idempotencyKey,
65742
- requestDigest: createHash17("sha256").update(stableJson4(input)).digest("hex"),
66200
+ requestDigest: createHash18("sha256").update(stableJson4(input)).digest("hex"),
65743
66201
  returnUrl: input.returnUrl,
65744
66202
  attempt: {
65745
66203
  id,
@@ -65820,7 +66278,7 @@ function registerConnectRoutes(app, deps) {
65820
66278
  return beginConnectAttempt(tx, scope, {
65821
66279
  ...continuation ? { externalContinuation: continuation } : {},
65822
66280
  idempotencyKey: input.idempotencyKey,
65823
- requestDigest: createHash17("sha256").update(stableJson4(input)).digest("hex"),
66281
+ requestDigest: createHash18("sha256").update(stableJson4(input)).digest("hex"),
65824
66282
  returnUrl: input.returnUrl,
65825
66283
  attempt: {
65826
66284
  id,
@@ -65958,7 +66416,7 @@ function registerConnectRoutes(app, deps) {
65958
66416
  return beginConnectAttempt(tx, scope, {
65959
66417
  ...continuation ? { externalContinuation: continuation } : {},
65960
66418
  idempotencyKey: input.idempotencyKey,
65961
- requestDigest: createHash17("sha256").update(stableJson4(input)).digest("hex"),
66419
+ requestDigest: createHash18("sha256").update(stableJson4(input)).digest("hex"),
65962
66420
  returnUrl: input.returnUrl,
65963
66421
  attempt: {
65964
66422
  id,
@@ -67015,7 +67473,7 @@ function requireOrganizationDocumentAuthority(authorityKind, organizationAuthori
67015
67473
  }
67016
67474
 
67017
67475
  // src/routes/knowledge.ts
67018
- import { retryWhileMissing as retryWhileMissing4 } from "@opengeni/storage";
67476
+ import { retryWhileMissing as retryWhileMissing5 } from "@opengeni/storage";
67019
67477
  import { allowedFirstPartyMcpToolsForSession as allowedFirstPartyMcpToolsForSession3 } from "@opengeni/config";
67020
67478
  import {
67021
67479
  AgentLearningContext,
@@ -67155,7 +67613,7 @@ function registerKnowledgeRoutes(app, deps) {
67155
67613
  if (!file) throw new HTTPException42(404, { message: "Original file unavailable" });
67156
67614
  if (!deps.objectStorage)
67157
67615
  throw new HTTPException42(503, { message: "File storage is unavailable" });
67158
- if (!await retryWhileMissing4(
67616
+ if (!await retryWhileMissing5(
67159
67617
  async () => await deps.objectStorage.fileExists(file) ? true : null
67160
67618
  ))
67161
67619
  throw new HTTPException42(410, { message: "Original file bytes are unavailable" });
@@ -67432,7 +67890,7 @@ function registerKnowledgeRoutes(app, deps) {
67432
67890
  }
67433
67891
 
67434
67892
  // src/routes/enrollments.ts
67435
- import { randomUUID as randomUUID5 } from "crypto";
67893
+ import { randomUUID as randomUUID6 } from "crypto";
67436
67894
  import {
67437
67895
  DeviceEnrollmentApproveRequest,
67438
67896
  DeviceEnrollmentApproveResponse,
@@ -67464,297 +67922,6 @@ import {
67464
67922
  requireAccessGrantAuthorization as requireAccessGrantAuthorization10,
67465
67923
  requirePermission
67466
67924
  } from "@opengeni/core";
67467
-
67468
- // src/sandbox/enrollment.ts
67469
- import { randomBytes as randomBytes8 } from "crypto";
67470
- import {
67471
- resolveEnrollmentSigningSecret,
67472
- resolveRelayTokenSecret
67473
- } from "@opengeni/config";
67474
- import {
67475
- DeviceEnrollmentState,
67476
- signEnrollmentBearer,
67477
- signEnrollToken,
67478
- signRelayToken,
67479
- verifyEnrollToken
67480
- } from "@opengeni/contracts";
67481
- import {
67482
- approveDeviceEnrollmentRequest,
67483
- consumeDeviceEnrollmentRequest,
67484
- createDeviceEnrollmentRequest,
67485
- denyDeviceEnrollmentRequest,
67486
- finalizeEnrollmentByToken,
67487
- getDeviceEnrollmentRequestByDeviceCode,
67488
- getEnrollment,
67489
- getPendingDeviceEnrollmentRequestByUserCode,
67490
- getPendingDeviceEnrollmentRequestByUserCodeGlobal
67491
- } from "@opengeni/db";
67492
- import { relayDialBaseFromSettings } from "@opengeni/core";
67493
- var DEVICE_CODE_TTL_SECONDS = 600;
67494
- var DEVICE_POLL_INTERVAL_SECONDS = 5;
67495
- var ENROLLMENT_BEARER_TTL_SECONDS = 30 * 24 * 3600;
67496
- var RELAY_TOKEN_TTL_SECONDS = 30 * 24 * 3600;
67497
- var ENROLL_TOKEN_TTL_SECONDS = 3600;
67498
- function mintDeviceCode() {
67499
- return randomBytes8(32).toString("base64url");
67500
- }
67501
- var USER_CODE_ALPHABET = "ABCDEFGHJKLMNPQRSTUVWXYZ23456789";
67502
- function mintUserCode() {
67503
- const bytes = randomBytes8(8);
67504
- let out = "";
67505
- for (let i = 0; i < 8; i += 1) {
67506
- out += USER_CODE_ALPHABET[bytes[i] % USER_CODE_ALPHABET.length];
67507
- }
67508
- return `${out.slice(0, 4)}-${out.slice(4, 8)}`;
67509
- }
67510
- async function startDeviceEnrollment(services, input) {
67511
- const { db } = services;
67512
- const expiresAt = new Date(Date.now() + DEVICE_CODE_TTL_SECONDS * 1e3);
67513
- let request;
67514
- let lastError;
67515
- for (let attempt = 0; attempt < 5 && !request; attempt += 1) {
67516
- const deviceCode = mintDeviceCode();
67517
- const userCode = mintUserCode();
67518
- try {
67519
- request = await createDeviceEnrollmentRequest(db, {
67520
- accountId: input.accountId,
67521
- workspaceId: input.workspaceId,
67522
- deviceCode,
67523
- userCode,
67524
- pubkey: input.publicKey,
67525
- os: input.os,
67526
- arch: input.arch,
67527
- machineName: input.machineName ?? null,
67528
- requestedExposure: "whole-machine",
67529
- canOfferDisplay: input.canOfferDisplay,
67530
- requestsScreenControl: input.requestsScreenControl,
67531
- expiresAt
67532
- });
67533
- } catch (error) {
67534
- lastError = error;
67535
- }
67536
- }
67537
- if (!request) {
67538
- throw lastError instanceof Error ? lastError : new Error("failed to start device enrollment");
67539
- }
67540
- const base = input.verificationOrigin.replace(/\/+$/, "");
67541
- const verificationUri = `${base}/device`;
67542
- const verificationUriComplete = `${verificationUri}?user_code=${encodeURIComponent(request.userCode)}`;
67543
- return {
67544
- deviceCode: request.deviceCode,
67545
- userCode: request.userCode,
67546
- verificationUri,
67547
- verificationUriComplete,
67548
- intervalSeconds: DEVICE_POLL_INTERVAL_SECONDS,
67549
- expiresInSeconds: DEVICE_CODE_TTL_SECONDS
67550
- };
67551
- }
67552
- async function approveDeviceEnrollment(services, input) {
67553
- const { db } = services;
67554
- const pending = await getPendingDeviceEnrollmentRequestByUserCode(
67555
- db,
67556
- input.workspaceId,
67557
- input.userCode
67558
- );
67559
- if (!pending) {
67560
- return null;
67561
- }
67562
- const sandboxName = (pending.machineName?.trim() || `${pending.os} machine`).slice(0, 256);
67563
- const result = await approveDeviceEnrollmentRequest(db, {
67564
- accountId: input.accountId,
67565
- workspaceId: input.workspaceId,
67566
- ...input.scope ? { scope: input.scope } : {},
67567
- allowOrganization: input.allowOrganization === true,
67568
- requestId: pending.id,
67569
- allowScreenControl: input.allowScreenControl,
67570
- approvedBySubjectId: input.approvedBySubjectId,
67571
- approvedBySubjectLabel: input.approvedBySubjectLabel ?? null,
67572
- sandboxName
67573
- });
67574
- if (!result.approved || !result.enrollment || !result.sandbox) {
67575
- return null;
67576
- }
67577
- return {
67578
- enrollmentId: result.enrollment.id,
67579
- sandboxId: result.sandbox.id,
67580
- allowScreenControl: result.enrollment.allowScreenControl
67581
- };
67582
- }
67583
- async function lookupDeviceEnrollment(services, input) {
67584
- const { db } = services;
67585
- return await getPendingDeviceEnrollmentRequestByUserCodeGlobal(db, input.userCode);
67586
- }
67587
- function toLookupResponse(record6) {
67588
- return {
67589
- workspaceId: record6.workspaceId,
67590
- userCode: record6.userCode,
67591
- machine: {
67592
- machineName: record6.machineName,
67593
- os: record6.os,
67594
- arch: record6.arch,
67595
- canOfferDisplay: record6.canOfferDisplay,
67596
- requestsScreenControl: record6.requestsScreenControl
67597
- },
67598
- expiresAt: record6.expiresAt
67599
- };
67600
- }
67601
- async function denyDeviceEnrollment(services, input) {
67602
- const { db } = services;
67603
- const pending = await getPendingDeviceEnrollmentRequestByUserCode(
67604
- db,
67605
- input.workspaceId,
67606
- input.userCode
67607
- );
67608
- if (!pending) {
67609
- return { denied: false };
67610
- }
67611
- return await denyDeviceEnrollmentRequest(db, {
67612
- accountId: input.accountId,
67613
- workspaceId: input.workspaceId,
67614
- requestId: pending.id
67615
- });
67616
- }
67617
- async function mintEnrollToken(services, input) {
67618
- const { settings } = services;
67619
- const secret = resolveEnrollmentSigningSecret(settings);
67620
- if (!secret) {
67621
- return null;
67622
- }
67623
- const nowSeconds = Math.floor(Date.now() / 1e3);
67624
- const exp = nowSeconds + ENROLL_TOKEN_TTL_SECONDS;
67625
- const token = await signEnrollToken(secret, {
67626
- typ: "enroll",
67627
- workspaceId: input.workspaceId,
67628
- accountId: input.accountId,
67629
- allowScreenControl: input.allowScreenControl,
67630
- iat: nowSeconds,
67631
- exp
67632
- });
67633
- return {
67634
- token,
67635
- expiresAt: new Date(exp * 1e3).toISOString(),
67636
- expiresInSeconds: ENROLL_TOKEN_TTL_SECONDS
67637
- };
67638
- }
67639
- async function exchangeEnrollToken(services, input) {
67640
- const { db, settings } = services;
67641
- const secret = resolveEnrollmentSigningSecret(settings);
67642
- if (!secret) {
67643
- return { ok: false, reason: "disabled" };
67644
- }
67645
- const claims = await verifyEnrollToken(secret, input.token);
67646
- if (!claims) {
67647
- return { ok: false, reason: "invalid" };
67648
- }
67649
- const sandboxName = (input.machineName?.trim() || `${input.os} machine`).slice(0, 256);
67650
- const { enrollment } = await finalizeEnrollmentByToken(db, {
67651
- accountId: claims.accountId,
67652
- workspaceId: claims.workspaceId,
67653
- pubkey: input.publicKey,
67654
- hasDisplay: input.canOfferDisplay,
67655
- // The token's allowScreenControl is the AUTHORITATIVE consent (NOT the agent's
67656
- // requestsScreenControl) — it was baked in at mint by the authorizing user.
67657
- allowScreenControl: claims.allowScreenControl,
67658
- os: input.os,
67659
- arch: input.arch,
67660
- sandboxName
67661
- });
67662
- const credentials = await buildEnrollmentCredentials(services, {
67663
- secret,
67664
- workspaceId: claims.workspaceId,
67665
- agentId: enrollment.id,
67666
- credentialGeneration: enrollment.credentialGeneration,
67667
- consentedScreenControl: enrollment.allowScreenControl
67668
- });
67669
- return { ok: true, credentials };
67670
- }
67671
- async function pollDeviceEnrollment(services, input) {
67672
- const { db, settings } = services;
67673
- const request = await getDeviceEnrollmentRequestByDeviceCode(db, input.deviceCode);
67674
- if (!request) {
67675
- return { state: "expired" };
67676
- }
67677
- if (request.status === "denied") {
67678
- return { state: "denied" };
67679
- }
67680
- if (request.status === "pending") {
67681
- if (new Date(request.expiresAt).getTime() <= Date.now()) {
67682
- return { state: "expired" };
67683
- }
67684
- return { state: "pending" };
67685
- }
67686
- if (!request.enrollmentId) {
67687
- return { state: "expired" };
67688
- }
67689
- const secret = resolveEnrollmentSigningSecret(settings);
67690
- if (!secret) {
67691
- return { state: "disabled" };
67692
- }
67693
- const enrollment = await getEnrollment(db, request.workspaceId, request.enrollmentId);
67694
- if (!enrollment || enrollment.status !== "active") {
67695
- return { state: "denied" };
67696
- }
67697
- const credentials = await buildEnrollmentCredentials(services, {
67698
- secret,
67699
- workspaceId: request.workspaceId,
67700
- agentId: enrollment.id,
67701
- credentialGeneration: enrollment.credentialGeneration,
67702
- consentedScreenControl: enrollment.allowScreenControl
67703
- });
67704
- if (request.status === "approved") {
67705
- await consumeDeviceEnrollmentRequest(db, {
67706
- accountId: request.accountId,
67707
- workspaceId: request.workspaceId,
67708
- requestId: request.id
67709
- });
67710
- }
67711
- return { state: DeviceEnrollmentState.enum.authorized, credentials };
67712
- }
67713
- async function buildEnrollmentCredentials(services, input) {
67714
- const { settings } = services;
67715
- const subjectPrefix = `agent.${input.workspaceId}.${input.agentId}`;
67716
- const nowSeconds = Math.floor(Date.now() / 1e3);
67717
- const exp = nowSeconds + ENROLLMENT_BEARER_TTL_SECONDS;
67718
- const bearer = await signEnrollmentBearer(input.secret, {
67719
- workspaceId: input.workspaceId,
67720
- agentId: input.agentId,
67721
- enrollmentId: input.agentId,
67722
- credentialGeneration: input.credentialGeneration,
67723
- subjectPrefix,
67724
- exp
67725
- });
67726
- const natsUrls = settings.selfhostedNatsUrl ? [settings.selfhostedNatsUrl] : [];
67727
- const relayTokenSecret = resolveRelayTokenSecret(settings);
67728
- const relayToken = relayTokenSecret ? await signRelayToken(relayTokenSecret, {
67729
- workspaceId: input.workspaceId,
67730
- agentId: input.agentId,
67731
- exp: nowSeconds + RELAY_TOKEN_TTL_SECONDS
67732
- }) : "";
67733
- return {
67734
- agentId: input.agentId,
67735
- workspaceId: input.workspaceId,
67736
- bearer,
67737
- subjectPrefix,
67738
- natsUrls,
67739
- // Hand the agent the canonical `/stream` dial base, NOT the raw configured URL.
67740
- // The agent's relay producer appends only its routing query and assumes the base
67741
- // already carries the relay's `/stream` route; a path-less base 400s the dial and
67742
- // makes the terminal/desktop streams unreachable.
67743
- relayUrl: relayDialBaseFromSettings(settings),
67744
- relayToken,
67745
- // M-AUTH closes the placeholder: there is NO per-machine NATS Account creds
67746
- // file. The agent presents the BEARER as the NATS connect auth-token; the
67747
- // server's auth-callout responder validates it and mints a workspace-scoped
67748
- // user JWT. We echo the bearer here so a consumer reading this (vestigial) field
67749
- // as the connect credential still works — the value IS the bearer.
67750
- natsAccountCreds: bearer,
67751
- updatePublicKey: settings.agentUpdatePublicKey ?? "",
67752
- consentedWholeMachine: true,
67753
- consentedScreenControl: input.consentedScreenControl
67754
- };
67755
- }
67756
-
67757
- // src/routes/enrollments.ts
67758
67925
  function registerEnrollmentRoutes(app, deps) {
67759
67926
  const { settings, db } = deps;
67760
67927
  function assertSelfhostedEnabled() {
@@ -68023,7 +68190,7 @@ function registerEnrollmentRoutes(app, deps) {
68023
68190
  message: "invalid machine removal request"
68024
68191
  });
68025
68192
  }
68026
- const idempotencyKey = parsed.data.idempotencyKey?.trim() || c.req.header("idempotency-key")?.trim() || randomUUID5();
68193
+ const idempotencyKey = parsed.data.idempotencyKey?.trim() || c.req.header("idempotency-key")?.trim() || randomUUID6();
68027
68194
  try {
68028
68195
  const enrollmentId = c.req.param("enrollmentId");
68029
68196
  const enrollment = (await listEnrollments2(db, grant, { status: "active" })).find(
@@ -68154,7 +68321,7 @@ import {
68154
68321
  readMachineMetricsLatestForWorkspace
68155
68322
  } from "@opengeni/db";
68156
68323
  import { MachineView, MetricSample } from "@opengeni/contracts";
68157
- import { managedSessionGroupBackend as managedSessionGroupBackend3 } from "@opengeni/core";
68324
+ import { managedSessionGroupBackend as managedSessionGroupBackend3, sessionGroupMachinePresentation } from "@opengeni/core";
68158
68325
  import { selfhostedHeartbeatLiveness } from "@opengeni/runtime/sandbox";
68159
68326
  var ACTIVE_UPDATE_STATUSES = /* @__PURE__ */ new Set([
68160
68327
  "requested",
@@ -68291,23 +68458,24 @@ async function listMachines(services, input) {
68291
68458
  if (session && groupBackend) {
68292
68459
  const groupActive = activeSandboxId === null;
68293
68460
  const groupLease = await readLease3(db, workspaceId, session.sandboxGroupId);
68461
+ const presentation = sessionGroupMachinePresentation(groupBackend);
68462
+ const localHost = groupBackend === "local";
68294
68463
  machines.push(
68295
68464
  MachineView.parse({
68296
68465
  sandboxId: session.sandboxGroupId,
68297
68466
  enrollmentId: null,
68298
- name: "session sandbox",
68299
- kind: groupBackend === "opensandbox" ? "opensandbox" : "modal",
68467
+ name: presentation.name,
68468
+ kind: presentation.kind,
68300
68469
  state: "online",
68301
68470
  active: groupActive,
68302
68471
  isSessionGroup: true,
68303
68472
  workspaceGeneration: groupLease?.workspaceGeneration ?? null,
68304
68473
  archiveGeneration: groupLease?.archiveGeneration ?? null,
68305
68474
  archiveComplete: groupLease?.archiveComplete ?? false,
68306
- // The Modal group box is a cloud Linux box; its precise OS/arch is not
68307
- // surfaced as a metric, so the dashboard shows the canonical linux/x86_64.
68308
- os: "linux",
68309
- arch: "x86_64",
68310
- hasDisplay: false,
68475
+ // A local sandbox is this machine. Other managed providers run a Linux box.
68476
+ os: localHost ? process.platform : "linux",
68477
+ arch: localHost ? process.arch : "x86_64",
68478
+ hasDisplay: localHost,
68311
68479
  desktopUnavailableReason: null,
68312
68480
  allowScreenControl: false,
68313
68481
  sharedSessionCount: 1,
@@ -70222,7 +70390,7 @@ function browserIdentityRouteError(error) {
70222
70390
  }
70223
70391
 
70224
70392
  // src/routes/browser-sessions.ts
70225
- import { randomUUID as randomUUID6 } from "crypto";
70393
+ import { randomUUID as randomUUID7 } from "crypto";
70226
70394
  import {
70227
70395
  environmentsEncryptionKeyBytes as environmentsEncryptionKeyBytes5,
70228
70396
  resolveFirstPartyDelegationSecret as resolveFirstPartyDelegationSecret3,
@@ -70374,7 +70542,7 @@ import {
70374
70542
  provisionBrowserControlClient,
70375
70543
  renewSandboxProviderExpiration as renewSandboxProviderExpiration2
70376
70544
  } from "@opengeni/runtime/sandbox";
70377
- import { retryWhileMissing as retryWhileMissing5 } from "@opengeni/storage";
70545
+ import { retryWhileMissing as retryWhileMissing6 } from "@opengeni/storage";
70378
70546
  import { HTTPException as HTTPException51 } from "hono/http-exception";
70379
70547
 
70380
70548
  // src/browser-controller-authority.ts
@@ -70657,7 +70825,7 @@ async function withInteractionHolderHeartbeat(deps, input, run) {
70657
70825
  }
70658
70826
 
70659
70827
  // src/browser-state-authority.ts
70660
- import { createCipheriv, createDecipheriv, createHash as createHash18, createHmac as createHmac7, randomBytes as randomBytes9 } from "crypto";
70828
+ import { createCipheriv, createDecipheriv, createHash as createHash19, createHmac as createHmac7, randomBytes as randomBytes9 } from "crypto";
70661
70829
  import { BROWSER_PROFILE_ARTIFACT_FORMAT } from "@opengeni/contracts";
70662
70830
  var ROOT_KEY_BYTES = 32;
70663
70831
  var DATA_KEY_BYTES = 32;
@@ -70721,7 +70889,7 @@ function browserStateObjectKey(workspaceIdInput, operationIdInput) {
70721
70889
  return `workspaces/${workspaceId}/browser-state/revisions/${operationId}/chromium-profile.ogbs`;
70722
70890
  }
70723
70891
  function browserStateManifestDigest(manifest) {
70724
- return createHash18("sha256").update(canonicalJson2(manifest), "utf8").digest("hex");
70892
+ return createHash19("sha256").update(canonicalJson2(manifest), "utf8").digest("hex");
70725
70893
  }
70726
70894
  function operationScope(input) {
70727
70895
  const base = baseArtifactScope(input);
@@ -72013,7 +72181,7 @@ function registerBrowserSessionRoutes(app, deps) {
72013
72181
  message: `browser download exceeds single PUT limit of ${objectStorage.maxSinglePutSizeBytes} bytes`
72014
72182
  });
72015
72183
  }
72016
- const fileId = randomUUID6();
72184
+ const fileId = randomUUID7();
72017
72185
  const safeFilename = sanitizeFilename(source.download.filename);
72018
72186
  save = await prepareBrowserDownloadSave(deps.db, {
72019
72187
  ...identity2,
@@ -72916,7 +73084,7 @@ function registerBrowserSessionRoutes(app, deps) {
72916
73084
  if (!targets.some((target) => target.id === request.targetId)) {
72917
73085
  throw new HTTPException51(404, { message: "browser target does not exist" });
72918
73086
  }
72919
- const grantId = randomUUID6();
73087
+ const grantId = randomUUID7();
72920
73088
  const expiresAt = new Date(Date.now() + request.expiresInSeconds * 1e3).toISOString();
72921
73089
  const rootSecret = browserAuthorityRoot(deps);
72922
73090
  const relaySecret = placement.session.openBrowserFrames ? resolveStreamTokenSecret2(deps.settings) : null;
@@ -74664,7 +74832,7 @@ async function ensureDispatchedGeneration(deps, grant, workspaceId, browserSessi
74664
74832
  operationId
74665
74833
  });
74666
74834
  if (record6.operation?.state === "prepared") {
74667
- const controllerGeneration = randomUUID6();
74835
+ const controllerGeneration = randomUUID7();
74668
74836
  try {
74669
74837
  await dispatchBrowserSessionOperation(deps.db, {
74670
74838
  accountId: grant.accountId,
@@ -75273,7 +75441,7 @@ async function finalizeBrowserDownloadFile(deps, grant, workspaceId, uploadId) {
75273
75441
  throw new InteractionResourceStateError("Browser download file upload authority expired");
75274
75442
  }
75275
75443
  const pendingFile = upload.file;
75276
- const head = await retryWhileMissing5(async () => {
75444
+ const head = await retryWhileMissing6(async () => {
75277
75445
  if (!await objectStorage.fileExists(pendingFile)) return null;
75278
75446
  return await objectStorage.headFile(pendingFile);
75279
75447
  });
@@ -75364,7 +75532,7 @@ function isAbort(error) {
75364
75532
  }
75365
75533
 
75366
75534
  // src/routes/computer-sessions.ts
75367
- import { randomUUID as randomUUID7 } from "crypto";
75535
+ import { randomUUID as randomUUID8 } from "crypto";
75368
75536
  import { resolveFirstPartyDelegationSecret as resolveFirstPartyDelegationSecret4, resolveStreamTokenSecret as resolveStreamTokenSecret3 } from "@opengeni/config";
75369
75537
  import {
75370
75538
  BROWSER_CONTROL_WEBSOCKET_BEARER_PREFIX as BROWSER_CONTROL_WEBSOCKET_BEARER_PREFIX2,
@@ -75888,7 +76056,7 @@ function registerComputerSessionRoutes(app, deps) {
75888
76056
  retryable: false
75889
76057
  });
75890
76058
  }
75891
- const grantId = randomUUID7();
76059
+ const grantId = randomUUID8();
75892
76060
  const expiresAt = new Date(Date.now() + request.expiresInSeconds * 1e3).toISOString();
75893
76061
  const token = deriveComputerViewGrantToken({
75894
76062
  rootSecret: controllerAuthorityRoot(deps),
@@ -76599,7 +76767,7 @@ function registerComputerSessionRoutes(app, deps) {
76599
76767
  operationId
76600
76768
  });
76601
76769
  if (record6.operation?.state === "prepared") {
76602
- const controllerGeneration = randomUUID7();
76770
+ const controllerGeneration = randomUUID8();
76603
76771
  try {
76604
76772
  await dispatchComputerSessionOperation(deps.db, {
76605
76773
  accountId: grant.accountId,
@@ -78712,7 +78880,7 @@ import {
78712
78880
  personalGitHubGitBrokerRouteId
78713
78881
  } from "@opengeni/github";
78714
78882
  import { readResponseTextBounded as readResponseTextBounded2 } from "@opengeni/network";
78715
- import { randomUUID as randomUUID8 } from "crypto";
78883
+ import { randomUUID as randomUUID9 } from "crypto";
78716
78884
  import JSONBig2 from "json-bigint";
78717
78885
  var PERSONAL_GITHUB_SERVER_ID = "github:personal";
78718
78886
  var GITHUB_API_VERSION3 = "2022-11-28";
@@ -78930,7 +79098,7 @@ async function authorizeBrokerProviderRequest(deps, authority, destinationUrl, o
78930
79098
  turnId: claims.turnId,
78931
79099
  attemptId: claims.attemptId,
78932
79100
  executionGeneration: claims.executionGeneration,
78933
- physicalRequestId: randomUUID8(),
79101
+ physicalRequestId: randomUUID9(),
78934
79102
  usePhase: "credential_resolution"
78935
79103
  }
78936
79104
  });
@@ -78945,7 +79113,7 @@ async function authorizeBrokerProviderRequest(deps, authority, destinationUrl, o
78945
79113
  turnId: claims.turnId,
78946
79114
  attemptId: claims.attemptId,
78947
79115
  executionGeneration: claims.executionGeneration,
78948
- physicalRequestId: randomUUID8(),
79116
+ physicalRequestId: randomUUID9(),
78949
79117
  usePhase: "provider_request",
78950
79118
  serverId: PERSONAL_GITHUB_SERVER_ID,
78951
79119
  connectionId: claims.connectionId,
@@ -83105,7 +83273,7 @@ import {
83105
83273
  integrationSourceForOrganizationPolicy as integrationSourceForOrganizationPolicy2
83106
83274
  } from "@opengeni/core";
83107
83275
  import { withOrganizationIntegrationPolicyFence as withOrganizationIntegrationPolicyFence8 } from "@opengeni/db/organization-integration-policy";
83108
- import { createHash as createHash19 } from "crypto";
83276
+ import { createHash as createHash20 } from "crypto";
83109
83277
  import {
83110
83278
  createPinnedIntegrationTransport as createPinnedIntegrationTransport3,
83111
83279
  fetchIntegrationSourceDocument as fetchIntegrationSourceDocument2
@@ -83967,7 +84135,7 @@ function pluginFailureCode(error) {
83967
84135
  return "component_install_failed";
83968
84136
  }
83969
84137
  function sha2562(value) {
83970
- return createHash19("sha256").update(value).digest("hex");
84138
+ return createHash20("sha256").update(value).digest("hex");
83971
84139
  }
83972
84140
 
83973
84141
  // src/routes/skills.ts
@@ -84002,14 +84170,14 @@ import {
84002
84170
  SkillSourceRemovalAuthorityError as SkillSourceRemovalAuthorityError2
84003
84171
  } from "@opengeni/db";
84004
84172
  import { loadSkillLibrarySkill, skillLibraryRepositoryUrl } from "@opengeni/runtime/skill-library";
84005
- import { createHash as createHash20 } from "crypto";
84173
+ import { createHash as createHash21 } from "crypto";
84006
84174
  import { HTTPException as HTTPException67 } from "hono/http-exception";
84007
84175
 
84008
84176
  // src/routes/skill-content.ts
84009
84177
  import { z as z24 } from "zod";
84010
84178
  import { HTTPException as HTTPException66 } from "hono/http-exception";
84011
- import { SkillFile } from "@opengeni/contracts";
84012
- import { readSkillRemovalScope } from "@opengeni/db";
84179
+ import { SkillFile, SKILL_MAX_FILES } from "@opengeni/contracts";
84180
+ import { getSessionForSubject, readSkillRemovalScope } from "@opengeni/db";
84013
84181
  import {
84014
84182
  approveSkill,
84015
84183
  rejectSkill,
@@ -84375,8 +84543,8 @@ var saveRequest = z24.object({
84375
84543
  expectedScopeVersion: z24.number().int().nonnegative(),
84376
84544
  scope: scopeSchema.default("workspace"),
84377
84545
  stableKey: z24.string().min(1).max(96),
84378
- files: z24.array(SkillFile).max(128),
84379
- deletions: z24.array(z24.string().min(1).max(512)).max(128).default([]),
84546
+ files: z24.array(SkillFile).max(SKILL_MAX_FILES),
84547
+ deletions: z24.array(z24.string().min(1).max(512)).max(SKILL_MAX_FILES).default([]),
84380
84548
  reason: z24.string().min(1).max(2e3)
84381
84549
  }).strict();
84382
84550
  var revisionRequest = z24.object({
@@ -84405,9 +84573,20 @@ function registerSkillContentRoutes(app, deps) {
84405
84573
  const grant = await requireAccessGrant27(c, deps, workspaceId, "workspace:read");
84406
84574
  const query = z24.object({
84407
84575
  limit: z24.coerce.number().int().min(1).max(250).default(100),
84408
- cursor: z24.string().max(2048).optional()
84576
+ cursor: z24.string().max(2048).optional(),
84577
+ sessionId: z24.uuid().optional()
84409
84578
  }).safeParse(c.req.query());
84410
84579
  if (!query.success) throw new HTTPException66(422, { message: "Invalid Skill list query" });
84580
+ if (query.data.sessionId) {
84581
+ await requireAccessGrant27(c, deps, workspaceId, "sessions:read");
84582
+ const session = await getSessionForSubject(
84583
+ deps.db,
84584
+ workspaceId,
84585
+ query.data.sessionId,
84586
+ grant.subjectId
84587
+ );
84588
+ if (!session) throw new HTTPException66(404, { message: "Session not found" });
84589
+ }
84411
84590
  let after;
84412
84591
  if (query.data.cursor !== void 0) {
84413
84592
  try {
@@ -84419,7 +84598,12 @@ function registerSkillContentRoutes(app, deps) {
84419
84598
  const rows2 = await listSkills(
84420
84599
  deps.db,
84421
84600
  { accountId: grant.accountId, workspaceId, subjectId: grant.subjectId },
84422
- { limit: query.data.limit + 1, metadataOnly: true, ...after ? { after } : {} }
84601
+ {
84602
+ limit: query.data.limit + 1,
84603
+ metadataOnly: true,
84604
+ ...after ? { after } : {},
84605
+ ...query.data.sessionId ? { sessionId: query.data.sessionId } : {}
84606
+ }
84423
84607
  );
84424
84608
  const page = rows2.slice(0, query.data.limit);
84425
84609
  const last = page.at(-1);
@@ -84626,7 +84810,7 @@ function registerSkillRoutes(app, deps, overrides = {}) {
84626
84810
  path: file.path,
84627
84811
  content: file.content,
84628
84812
  byteSize: bytes.byteLength,
84629
- contentSha256: createHash20("sha256").update(bytes).digest("hex")
84813
+ contentSha256: createHash21("sha256").update(bytes).digest("hex")
84630
84814
  };
84631
84815
  });
84632
84816
  try {
@@ -85587,7 +85771,7 @@ import {
85587
85771
  readActiveSandbox as readActiveSandbox3,
85588
85772
  deleteSessionTreeIfQuiescent,
85589
85773
  getSessionEvent,
85590
- getSessionForSubject,
85774
+ getSessionForSubject as getSessionForSubject2,
85591
85775
  getSessionGoal as getSessionGoal2,
85592
85776
  getLatestSessionModelContext,
85593
85777
  getSessionHumanInputRequest,
@@ -87289,7 +87473,7 @@ function registerSessionRoutes(app, deps) {
87289
87473
  if (!z27.string().uuid().safeParse(sessionId).success) {
87290
87474
  throw new HTTPException72(404, { message: "session not found" });
87291
87475
  }
87292
- const session = await getSessionForSubject(
87476
+ const session = await getSessionForSubject2(
87293
87477
  db,
87294
87478
  workspaceId,
87295
87479
  sessionId,
@@ -87320,7 +87504,7 @@ function registerSessionRoutes(app, deps) {
87320
87504
  if (!z27.string().uuid().safeParse(sessionId).success) {
87321
87505
  throw new HTTPException72(404, { message: "session not found" });
87322
87506
  }
87323
- const session = await getSessionForSubject(
87507
+ const session = await getSessionForSubject2(
87324
87508
  db,
87325
87509
  workspaceId,
87326
87510
  sessionId,
@@ -88346,7 +88530,7 @@ function registerSessionRoutes(app, deps) {
88346
88530
  }
88347
88531
  throw error;
88348
88532
  }
88349
- const session = await getSessionForSubject(
88533
+ const session = await getSessionForSubject2(
88350
88534
  db,
88351
88535
  workspaceId,
88352
88536
  sessionId,
@@ -88421,7 +88605,7 @@ function registerSessionRoutes(app, deps) {
88421
88605
  if (result.status === "updated") {
88422
88606
  await publishDurableSessionEvents3(bus, workspaceId, sessionId, [result.event]);
88423
88607
  }
88424
- const session = await getSessionForSubject(
88608
+ const session = await getSessionForSubject2(
88425
88609
  db,
88426
88610
  workspaceId,
88427
88611
  sessionId,
@@ -88440,7 +88624,7 @@ function registerSessionRoutes(app, deps) {
88440
88624
  await assertSessionExists(db, workspaceId, sessionId);
88441
88625
  const payload = UpdateSessionRequest.parse(await c.req.json());
88442
88626
  const titleUpdate = await updateSessionTitle2(deps, grant, sessionId, payload.title, "user");
88443
- const session = await getSessionForSubject(
88627
+ const session = await getSessionForSubject2(
88444
88628
  db,
88445
88629
  workspaceId,
88446
88630
  sessionId,
@@ -91508,7 +91692,7 @@ import { SessionControlConflictError as SessionControlConflictError2, WorkspaceP
91508
91692
  import { updateWorkspaceSettingsWithToolDefaults } from "@opengeni/db/workspace-tool-defaults";
91509
91693
  import { WorkspacePauseTimerRequest } from "@opengeni/contracts";
91510
91694
  import { getWorkspaceConnectionModelRestrictions } from "@opengeni/db";
91511
- import { createHash as createHash21 } from "crypto";
91695
+ import { createHash as createHash22 } from "crypto";
91512
91696
  import {
91513
91697
  AddWorkspaceMemberRequest,
91514
91698
  CreateWorkspaceRequest,
@@ -91775,7 +91959,7 @@ function projectWorkspaceOpenRouterCustomModel(model) {
91775
91959
  });
91776
91960
  }
91777
91961
  function workspaceCustomModelRequestHash(value) {
91778
- return createHash21("sha256").update(stableJson7(value), "utf8").digest("hex");
91962
+ return createHash22("sha256").update(stableJson7(value), "utf8").digest("hex");
91779
91963
  }
91780
91964
  function workspaceMembersResponse(members) {
91781
91965
  return ListWorkspaceMembersResponse.parse({
@@ -92712,7 +92896,7 @@ function requireAccountPermission2(context, accountId, permission) {
92712
92896
  }
92713
92897
 
92714
92898
  // src/routes/workspace-instruction-policies.ts
92715
- import { randomUUID as randomUUID9 } from "crypto";
92899
+ import { randomUUID as randomUUID10 } from "crypto";
92716
92900
  import {
92717
92901
  ActivateWorkspaceInstructionPolicyRequest,
92718
92902
  CreateWorkspaceInstructionPolicyDraftRequest,
@@ -92878,7 +93062,7 @@ function registerWorkspaceInstructionPolicyRoutes(app, deps) {
92878
93062
  return context.json(
92879
93063
  WorkspaceInstructionPolicyRevision.parse(
92880
93064
  await createWorkspaceInstructionPolicyDraft(deps.db, {
92881
- operationId: request.operationId ?? randomUUID9(),
93065
+ operationId: request.operationId ?? randomUUID10(),
92882
93066
  accountId: grant.accountId,
92883
93067
  workspaceId,
92884
93068
  createdBySubjectId: grant.subjectId,
@@ -92906,7 +93090,7 @@ function registerWorkspaceInstructionPolicyRoutes(app, deps) {
92906
93090
  return context.json(
92907
93091
  WorkspaceInstructionPolicyRevision.parse(
92908
93092
  await importLegacyWorkspaceInstructionPolicyDraft(deps.db, {
92909
- operationId: request.operationId ?? randomUUID9(),
93093
+ operationId: request.operationId ?? randomUUID10(),
92910
93094
  accountId: grant.accountId,
92911
93095
  workspaceId,
92912
93096
  createdBySubjectId: grant.subjectId,
@@ -92948,7 +93132,7 @@ function registerWorkspaceInstructionPolicyRoutes(app, deps) {
92948
93132
  return context.json(
92949
93133
  WorkspaceInstructionPolicyOnboardingProposal.parse(
92950
93134
  await createWorkspaceInstructionPolicyOnboardingProposal(deps.db, {
92951
- operationId: request.operationId ?? randomUUID9(),
93135
+ operationId: request.operationId ?? randomUUID10(),
92952
93136
  accountId: grant.accountId,
92953
93137
  workspaceId,
92954
93138
  createdBySubjectId: grant.subjectId,
@@ -92998,7 +93182,7 @@ function registerWorkspaceInstructionPolicyRoutes(app, deps) {
92998
93182
  return context.json(
92999
93183
  WorkspaceInstructionPolicyActivationResponse.parse(
93000
93184
  await rollbackWorkspaceInstructionPolicyRevision(deps.db, {
93001
- operationId: request.operationId ?? randomUUID9(),
93185
+ operationId: request.operationId ?? randomUUID10(),
93002
93186
  accountId: grant.accountId,
93003
93187
  workspaceId,
93004
93188
  targetRevisionId: request.targetRevisionId,
@@ -93037,7 +93221,7 @@ function registerWorkspaceInstructionPolicyRoutes(app, deps) {
93037
93221
  return context.json(
93038
93222
  WorkspaceInstructionPolicyActivationResponse.parse(
93039
93223
  await activateWorkspaceInstructionPolicyRevision(deps.db, {
93040
- operationId: request.operationId ?? randomUUID9(),
93224
+ operationId: request.operationId ?? randomUUID10(),
93041
93225
  accountId: grant.accountId,
93042
93226
  workspaceId,
93043
93227
  revisionId: revisionId2,
@@ -93055,7 +93239,7 @@ function registerWorkspaceInstructionPolicyRoutes(app, deps) {
93055
93239
  }
93056
93240
 
93057
93241
  // src/routes/workspace-learning.ts
93058
- import { randomUUID as randomUUID10 } from "crypto";
93242
+ import { randomUUID as randomUUID11 } from "crypto";
93059
93243
  import {
93060
93244
  UndoGovernedLearningActivationHttpRequest,
93061
93245
  WorkspaceLearningHistoryResponse,
@@ -93178,7 +93362,7 @@ function registerWorkspaceLearningRoutes(app, deps) {
93178
93362
  const undo = await undoGovernedLearningActivation(deps.db, {
93179
93363
  caller: { workspaceId, subjectId: grant.subjectId },
93180
93364
  request: {
93181
- operationId: request.operationId ?? randomUUID10(),
93365
+ operationId: request.operationId ?? randomUUID11(),
93182
93366
  activationReceiptId: activationReceiptId.data
93183
93367
  }
93184
93368
  });
@@ -93193,7 +93377,7 @@ function registerWorkspaceLearningRoutes(app, deps) {
93193
93377
  }
93194
93378
 
93195
93379
  // src/routes/company-profile.ts
93196
- import { randomUUID as randomUUID11 } from "crypto";
93380
+ import { randomUUID as randomUUID12 } from "crypto";
93197
93381
  import {
93198
93382
  ActivateCompanyProfileRevisionRequest,
93199
93383
  CompanyProfileAgentPolicy,
@@ -93370,7 +93554,7 @@ function registerCompanyProfileRoutes(app, deps) {
93370
93554
  return context.json(
93371
93555
  CompanyProfileMutationResponse.parse(
93372
93556
  await updateCompanyProfile(deps.db, {
93373
- operationId: request.operationId ?? randomUUID11(),
93557
+ operationId: request.operationId ?? randomUUID12(),
93374
93558
  accountId: access.grant.accountId,
93375
93559
  workspaceId,
93376
93560
  profile: request.profile,
@@ -93422,7 +93606,7 @@ function registerCompanyProfileRoutes(app, deps) {
93422
93606
  return context.json(
93423
93607
  CompanyProfileMutationResponse.parse(
93424
93608
  await rollbackCompanyProfileRevision(deps.db, {
93425
- operationId: request.operationId ?? randomUUID11(),
93609
+ operationId: request.operationId ?? randomUUID12(),
93426
93610
  accountId: access.grant.accountId,
93427
93611
  workspaceId,
93428
93612
  targetRevisionId: request.targetRevisionId,
@@ -93469,7 +93653,7 @@ function registerCompanyProfileRoutes(app, deps) {
93469
93653
  return context.json(
93470
93654
  CompanyProfileMutationResponse.parse(
93471
93655
  await activateCompanyProfileRevision(deps.db, {
93472
- operationId: request.operationId ?? randomUUID11(),
93656
+ operationId: request.operationId ?? randomUUID12(),
93473
93657
  accountId: access.grant.accountId,
93474
93658
  workspaceId,
93475
93659
  revisionId: revisionId(context),
@@ -93488,7 +93672,7 @@ function registerCompanyProfileRoutes(app, deps) {
93488
93672
  }
93489
93673
 
93490
93674
  // src/routes/company-brain.ts
93491
- import { createHash as createHash23 } from "crypto";
93675
+ import { createHash as createHash24 } from "crypto";
93492
93676
  import {
93493
93677
  COMPANY_BRAIN_INSPECTOR_CURSOR_MAX_CHARS,
93494
93678
  COMPANY_BRAIN_INSPECTOR_DEFAULT_LIMIT,
@@ -93759,14 +93943,14 @@ function serializeCompanyBrainOkf(value) {
93759
93943
  }
93760
93944
 
93761
93945
  // src/workspace-state-projection.ts
93762
- import { createHash as createHash22 } from "crypto";
93946
+ import { createHash as createHash23 } from "crypto";
93763
93947
  import {
93764
93948
  WORKSPACE_STATE_MAX_ACTIVE_POLICY_HEADS,
93765
93949
  WORKSPACE_STATE_KNOWLEDGE_SAMPLE_LIMIT,
93766
93950
  WorkspaceStateResponse
93767
93951
  } from "@opengeni/contracts";
93768
93952
  function hashIdentities(values) {
93769
- return createHash22("sha256").update(values.join("\n"), "utf8").digest("hex");
93953
+ return createHash23("sha256").update(values.join("\n"), "utf8").digest("hex");
93770
93954
  }
93771
93955
  function policyTargetKey(value) {
93772
93956
  return `${value.kind}:${value.scope}:${value.roleKey ?? ""}`;
@@ -93996,7 +94180,7 @@ var inspectorQuery = z32.object({
93996
94180
  message: "attemptId cannot be combined with cursor"
93997
94181
  });
93998
94182
  function receiptCursorScope(workspaceId, subjectId) {
93999
- return createHash23("sha256").update("opengeni:company-brain-context-receipts:v1\0").update(workspaceId).update("\0").update(subjectId).digest("hex");
94183
+ return createHash24("sha256").update("opengeni:company-brain-context-receipts:v1\0").update(workspaceId).update("\0").update(subjectId).digest("hex");
94000
94184
  }
94001
94185
  function encodeReceiptCursor(workspaceId, subjectId, cursor) {
94002
94186
  return Buffer.from(
@@ -94212,7 +94396,7 @@ function registerCompanyBrainRoutes(app, deps) {
94212
94396
  }
94213
94397
 
94214
94398
  // src/routes/slack-task-policy.ts
94215
- import { randomUUID as randomUUID12 } from "crypto";
94399
+ import { randomUUID as randomUUID13 } from "crypto";
94216
94400
  import {
94217
94401
  SlackTaskPolicyListResponse,
94218
94402
  SlackTaskPolicyMutationResponse,
@@ -94295,7 +94479,7 @@ function registerSlackTaskPolicyRoutes(app, deps) {
94295
94479
  return context.json(
94296
94480
  SlackTaskPolicyMutationResponse.parse(
94297
94481
  await updateSlackTaskPolicy(deps.db, {
94298
- operationId: parsed.data.operationId ?? randomUUID12(),
94482
+ operationId: parsed.data.operationId ?? randomUUID13(),
94299
94483
  accountId: access.grant.accountId,
94300
94484
  workspaceId,
94301
94485
  policy: parsed.data.policy,
@@ -94334,7 +94518,7 @@ import {
94334
94518
  import { HTTPException as HTTPException81 } from "hono/http-exception";
94335
94519
 
94336
94520
  // src/workspace-state-export.ts
94337
- import { createHash as createHash24 } from "crypto";
94521
+ import { createHash as createHash25 } from "crypto";
94338
94522
  import {
94339
94523
  WORKSPACE_STATE_EXPORT_SCHEMA_VERSION,
94340
94524
  WorkspaceStateExportResponse
@@ -94365,7 +94549,7 @@ function createWorkspaceStateExport(state) {
94365
94549
  kind: "opengeni.workspace_state.sanitized_export",
94366
94550
  schemaVersion: WORKSPACE_STATE_EXPORT_SCHEMA_VERSION,
94367
94551
  generatedAt: state.generatedAt,
94368
- stateSha256: createHash24("sha256").update(canonicalState, "utf8").digest("hex"),
94552
+ stateSha256: createHash25("sha256").update(canonicalState, "utf8").digest("hex"),
94369
94553
  omissions: WORKSPACE_STATE_EXPORT_OMISSIONS,
94370
94554
  state
94371
94555
  });
@@ -94473,7 +94657,7 @@ function registerWorkspaceStateRoutes(app, deps) {
94473
94657
  }
94474
94658
 
94475
94659
  // src/routes/workspace-artifacts.ts
94476
- import { createHash as createHash25 } from "crypto";
94660
+ import { createHash as createHash26 } from "crypto";
94477
94661
  import {
94478
94662
  CreateWorkspaceArtifactRequest,
94479
94663
  PublishWorkspaceArtifactVersionRequest,
@@ -94565,7 +94749,7 @@ function prepareContent(deps, grant, input) {
94565
94749
  }
94566
94750
  function provenance(subjectId, idempotencyKey) {
94567
94751
  return {
94568
- operationKey: `subject:${createHash25("sha256").update(`${subjectId}:${idempotencyKey}`).digest("hex")}`,
94752
+ operationKey: `subject:${createHash26("sha256").update(`${subjectId}:${idempotencyKey}`).digest("hex")}`,
94569
94753
  actorSubjectId: subjectId,
94570
94754
  sourceSessionId: null,
94571
94755
  sourceTurnId: null,
@@ -94924,7 +95108,7 @@ import {
94924
95108
  import { HTTPException as HTTPException84 } from "hono/http-exception";
94925
95109
 
94926
95110
  // src/artifact-catalog-cursor.ts
94927
- import { createCipheriv as createCipheriv3, createDecipheriv as createDecipheriv3, createHash as createHash26, randomBytes as randomBytes11 } from "crypto";
95111
+ import { createCipheriv as createCipheriv3, createDecipheriv as createDecipheriv3, createHash as createHash27, randomBytes as randomBytes11 } from "crypto";
94928
95112
  import { ArtifactCatalogKind } from "@opengeni/contracts";
94929
95113
  import { HTTPException as HTTPException83 } from "hono/http-exception";
94930
95114
  import { z as z34 } from "zod";
@@ -94939,8 +95123,8 @@ var Cursor = z34.object({
94939
95123
  }).strict()
94940
95124
  }).strict();
94941
95125
  function artifactCatalogCursorCodec(secret, binding) {
94942
- const key = createHash26("sha256").update("opengeni:artifact-catalog:v1\0").update(secret).digest();
94943
- const aad = createHash26("sha256").update(binding).digest();
95126
+ const key = createHash27("sha256").update("opengeni:artifact-catalog:v1\0").update(secret).digest();
95127
+ const aad = createHash27("sha256").update(binding).digest();
94944
95128
  return {
94945
95129
  encode(value) {
94946
95130
  const iv = randomBytes11(12);
@@ -95257,7 +95441,7 @@ import { requireAccessGrant as requireAccessGrant43, TranscriptionServiceError a
95257
95441
  import { getWorkspace as getWorkspace6 } from "@opengeni/db";
95258
95442
 
95259
95443
  // src/routes/transcription-recordings.ts
95260
- import { createHash as createHash27 } from "crypto";
95444
+ import { createHash as createHash28 } from "crypto";
95261
95445
  import {
95262
95446
  CreateTranscriptionRecordingRequest,
95263
95447
  FinalizeTranscriptionRecordingRequest,
@@ -95273,7 +95457,7 @@ import {
95273
95457
  TRANSCRIPTION_PROVIDER_REQUEST_TIMEOUT_MILLISECONDS,
95274
95458
  TranscriptionServiceError
95275
95459
  } from "@opengeni/core";
95276
- import { retryWhileMissing as retryWhileMissing6 } from "@opengeni/storage";
95460
+ import { retryWhileMissing as retryWhileMissing7 } from "@opengeni/storage";
95277
95461
  import {
95278
95462
  claimNextTranscriptionRecordingSegment,
95279
95463
  claimTranscriptionRecordingAssembly,
@@ -95859,7 +96043,7 @@ function registerResumableTranscriptionRoutes(app, deps) {
95859
96043
  attemptedProvider = claim.segment.providerId;
95860
96044
  fallbackAllowed = claim.fallbackAllowed === true;
95861
96045
  const segmentKey = claim.segment.objectKey;
95862
- const stored = deps.objectStorage ? await retryWhileMissing6(async () => deps.objectStorage.getObjectBytes(segmentKey)) : null;
96046
+ const stored = deps.objectStorage ? await retryWhileMissing7(async () => deps.objectStorage.getObjectBytes(segmentKey)) : null;
95863
96047
  if (!stored) {
95864
96048
  throw new RecordingProcessingError("Provider segment is missing", "invalid_audio", false);
95865
96049
  }
@@ -96018,7 +96202,7 @@ async function* verifiedChunkBytes(deps, chunks, signal) {
96018
96202
  }
96019
96203
  let stored;
96020
96204
  try {
96021
- stored = await retryWhileMissing6(
96205
+ stored = await retryWhileMissing7(
96022
96206
  async () => deps.objectStorage.getObjectBytes(chunk.objectKey)
96023
96207
  );
96024
96208
  } catch {
@@ -96102,7 +96286,7 @@ function valueAsUuid(value) {
96102
96286
  if (/^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(value)) {
96103
96287
  return value;
96104
96288
  }
96105
- const hex2 = createHash27("sha256").update(value).digest("hex").slice(0, 32);
96289
+ const hex2 = createHash28("sha256").update(value).digest("hex").slice(0, 32);
96106
96290
  return `${hex2.slice(0, 8)}-${hex2.slice(8, 12)}-4${hex2.slice(13, 16)}-a${hex2.slice(17, 20)}-${hex2.slice(20, 32)}`;
96107
96291
  }
96108
96292
  function nonnegativeInteger(value) {
@@ -96166,7 +96350,7 @@ async function readBoundedBody(request, maxBytes) {
96166
96350
  return body3;
96167
96351
  }
96168
96352
  function sha256Hex3(bytes) {
96169
- return createHash27("sha256").update(bytes).digest("hex");
96353
+ return createHash28("sha256").update(bytes).digest("hex");
96170
96354
  }
96171
96355
 
96172
96356
  // src/routes/transcriptions.ts
@@ -96457,7 +96641,7 @@ function videoGenerationFundingOptions(input) {
96457
96641
  }
96458
96642
 
96459
96643
  // src/routes/canonical-human-identities.ts
96460
- import { randomUUID as randomUUID14 } from "crypto";
96644
+ import { randomUUID as randomUUID15 } from "crypto";
96461
96645
  import {
96462
96646
  CanonicalHumanBindingOperationRequest,
96463
96647
  CanonicalHumanIdentityMutationResponse,
@@ -96506,7 +96690,7 @@ import { HTTPException as HTTPException88 } from "hono/http-exception";
96506
96690
  import { z as z36 } from "zod";
96507
96691
 
96508
96692
  // src/routes/managed-auth-session-sets.ts
96509
- import { randomUUID as randomUUID13 } from "crypto";
96693
+ import { randomUUID as randomUUID14 } from "crypto";
96510
96694
  import {
96511
96695
  BeginManagedAuthLoginTransactionRequest,
96512
96696
  BootstrapManagedAuthSessionSetRequest,
@@ -96717,7 +96901,7 @@ function registerManagedAuthSessionSetRoutes(app, deps) {
96717
96901
  app.post("/v1/auth/session-set/transactions", async (context) => {
96718
96902
  const body3 = await bodyAs(context, BeginManagedAuthLoginTransactionRequest);
96719
96903
  const { authority, actorEpoch } = await requireMutation(context, deps, body3.expectedGeneration);
96720
- const transactionId = randomUUID13();
96904
+ const transactionId = randomUUID14();
96721
96905
  const transactionSecret = managedAuthTransactionSecret(
96722
96906
  requireSigningSecret(deps),
96723
96907
  authority,
@@ -97938,7 +98122,7 @@ function registerCanonicalHumanIdentityRoutes(app, deps) {
97938
98122
  return await mutate(context, deps, {
97939
98123
  operationType: "link",
97940
98124
  ...request,
97941
- operationId: request.operationId ?? randomUUID14()
98125
+ operationId: request.operationId ?? randomUUID15()
97942
98126
  });
97943
98127
  });
97944
98128
  app.delete(`${base}/login-bindings/:bindingId`, async (context) => {
@@ -97956,7 +98140,7 @@ function registerCanonicalHumanIdentityRoutes(app, deps) {
97956
98140
  operationType: "unlink",
97957
98141
  bindingId: bindingId(context),
97958
98142
  ...request,
97959
- operationId: request.operationId ?? randomUUID14()
98143
+ operationId: request.operationId ?? randomUUID15()
97960
98144
  });
97961
98145
  });
97962
98146
  app.post(`${base}/login-bindings/:bindingId/recovery`, async (context) => {
@@ -97974,7 +98158,7 @@ function registerCanonicalHumanIdentityRoutes(app, deps) {
97974
98158
  operationType: "begin_recovery",
97975
98159
  bindingId: bindingId(context),
97976
98160
  ...request,
97977
- operationId: request.operationId ?? randomUUID14()
98161
+ operationId: request.operationId ?? randomUUID15()
97978
98162
  });
97979
98163
  });
97980
98164
  app.post(`${base}/login-bindings/:bindingId/recovery/complete`, async (context) => {
@@ -97989,7 +98173,7 @@ function registerCanonicalHumanIdentityRoutes(app, deps) {
97989
98173
  operationType: "recover",
97990
98174
  bindingId: bindingId(context),
97991
98175
  ...request,
97992
- operationId: request.operationId ?? randomUUID14(),
98176
+ operationId: request.operationId ?? randomUUID15(),
97993
98177
  ...managed ? { verifiedManagedRecovery: true } : {}
97994
98178
  });
97995
98179
  });
@@ -100297,11 +100481,12 @@ async function exactAvailable(providers, providerId, context) {
100297
100481
  }
100298
100482
 
100299
100483
  // src/integrations/slack-interactions.ts
100300
- import { createHash as createHash29, createHmac as createHmac10, timingSafeEqual as timingSafeEqual3 } from "crypto";
100484
+ import { createHash as createHash30, createHmac as createHmac10, timingSafeEqual as timingSafeEqual3 } from "crypto";
100301
100485
  import {
100302
100486
  approvalIdentifier,
100303
100487
  ApproveSlackUserLinkAccessRequest,
100304
100488
  DEFAULT_FIRST_PARTY_MCP_TOOLS,
100489
+ resolveWorkspaceSessionToolDefaults,
100305
100490
  hasOpenGeniSlackReactionScope,
100306
100491
  ListSlackUserLinkAccessRequestsResponse,
100307
100492
  PrepareSlackUserLinkAccessRequest,
@@ -100341,6 +100526,7 @@ import {
100341
100526
  getOrCreateSlackInteraction,
100342
100527
  getLatestSessionModelForSubject,
100343
100528
  getSession as getSession11,
100529
+ getSessionByCreateIdempotencyKey,
100344
100530
  getSessionEvent as getSessionEvent2,
100345
100531
  getSessionHumanInputRequest as getSessionHumanInputRequest2,
100346
100532
  childRequiresActionResolutionExists,
@@ -100400,6 +100586,7 @@ import {
100400
100586
  acceptSessionUserMessage as acceptSessionUserMessage2,
100401
100587
  controlHumanSessionWorkstream as controlHumanSessionWorkstream2,
100402
100588
  createSessionForRequest as createSessionForRequest2,
100589
+ getActorNewSessionDefaults,
100403
100590
  hasPermission as hasPermission26,
100404
100591
  requireAccessContext as requireAccessContext8,
100405
100592
  requireAccessGrant as requireAccessGrant45,
@@ -100775,9 +100962,9 @@ function record4(value) {
100775
100962
  }
100776
100963
 
100777
100964
  // src/slack-reaction-files.ts
100778
- import { createHash as createHash28 } from "crypto";
100965
+ import { createHash as createHash29 } from "crypto";
100779
100966
  import { completeFileUpload as completeFileUpload5, prepareGeneratedWorkspaceFile as prepareGeneratedWorkspaceFile2 } from "@opengeni/db";
100780
- import { retryWhileMissing as retryWhileMissing7 } from "@opengeni/storage";
100967
+ import { retryWhileMissing as retryWhileMissing8 } from "@opengeni/storage";
100781
100968
  var IMPORT_IDENTITY_VERSION = "slack-reaction-image-v1";
100782
100969
  var UPLOAD_INTENT_TTL_MS2 = 60 * 6e4;
100783
100970
  var UUID_PATTERN2 = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/u;
@@ -100792,7 +100979,7 @@ async function importSlackReactionImage(dependencies, source, image, ordinal) {
100792
100979
  if (image.bytes.byteLength < 1 || image.bytes.byteLength > 4 * 1024 * 1024) {
100793
100980
  throw new Error("Slack reaction image size is invalid");
100794
100981
  }
100795
- const sha2563 = createHash28("sha256").update(image.bytes).digest("hex");
100982
+ const sha2563 = createHash29("sha256").update(image.bytes).digest("hex");
100796
100983
  const identity2 = slackReactionImageIdentity(source, image.fileId);
100797
100984
  const fileId = deterministicUuid(`${identity2}:file`);
100798
100985
  const uploadId = deterministicUuid(`${identity2}:upload`);
@@ -100877,7 +101064,7 @@ function safeSlackImageFilename(value, contentType) {
100877
101064
  return `${stem}${extension}`;
100878
101065
  }
100879
101066
  async function assertVisibleSlackImage(storage, objectKey, image, sha2563) {
100880
- const head = await retryWhileMissing7(async () => await storage.headObject(objectKey));
101067
+ const head = await retryWhileMissing8(async () => await storage.headObject(objectKey));
100881
101068
  assertStoredSlackImage(head, image, sha2563);
100882
101069
  }
100883
101070
  function assertStoredSlackImage(head, image, sha2563) {
@@ -100886,7 +101073,7 @@ function assertStoredSlackImage(head, image, sha2563) {
100886
101073
  }
100887
101074
  }
100888
101075
  function deterministicUuid(seed) {
100889
- const bytes = createHash28("sha256").update(seed, "utf8").digest().subarray(0, 16);
101076
+ const bytes = createHash29("sha256").update(seed, "utf8").digest().subarray(0, 16);
100890
101077
  bytes[6] = (bytes[6] ?? 0) & 15 | 80;
100891
101078
  bytes[8] = (bytes[8] ?? 0) & 63 | 128;
100892
101079
  const hex2 = bytes.toString("hex");
@@ -101045,7 +101232,7 @@ function slackReactionInboxEntry(payload, bot, settings) {
101045
101232
  if (!settings.enabled || !event || event.type !== "reaction_added" || item?.type !== "message" || !teamId || !eventId || !userId || userId === bot.botUserId || !reaction || reaction !== settings.emoji || !channelId || !workspaceSlackReactionChannelAllowed(settings, channelId) || !timestamp) {
101046
101233
  return null;
101047
101234
  }
101048
- const stableReactionIdentity = createHash29("sha256").update([teamId, userId, channelId, timestamp, reaction].join("\n")).digest("hex");
101235
+ const stableReactionIdentity = createHash30("sha256").update([teamId, userId, channelId, timestamp, reaction].join("\n")).digest("hex");
101049
101236
  return {
101050
101237
  providerEventId: eventId,
101051
101238
  providerMessageId: `reaction:${stableReactionIdentity}`,
@@ -101235,7 +101422,7 @@ function registerSlackInteractionRoutes(app, deps) {
101235
101422
  const prepared = await prepareSlackUserLinkAccessRequest(deps.db, {
101236
101423
  accountId: installation.accountId,
101237
101424
  workspaceId,
101238
- tokenDigest: createHash29("sha256").update(payload.linkToken).digest("hex"),
101425
+ tokenDigest: createHash30("sha256").update(payload.linkToken).digest("hex"),
101239
101426
  connectionId: link.connectionId,
101240
101427
  slackTeamId: link.slackTeamId,
101241
101428
  slackUserId: link.slackUserId,
@@ -101442,7 +101629,7 @@ function registerSlackInteractionRoutes(app, deps) {
101442
101629
  const prepared = await prepareSlackUserLinkAccessRequest(deps.db, {
101443
101630
  accountId: grant.accountId,
101444
101631
  workspaceId,
101445
- tokenDigest: createHash29("sha256").update(linkToken).digest("hex"),
101632
+ tokenDigest: createHash30("sha256").update(linkToken).digest("hex"),
101446
101633
  connectionId: link.connectionId,
101447
101634
  slackTeamId: link.slackTeamId,
101448
101635
  slackUserId: link.slackUserId,
@@ -102405,6 +102592,14 @@ async function processSlackInboxEntry(deps, entry2) {
102405
102592
  );
102406
102593
  let session;
102407
102594
  try {
102595
+ const defaults = await slackNewSessionDefaults(
102596
+ deps,
102597
+ grant,
102598
+ interaction,
102599
+ `slack:${entry2.connectionId}:${entry2.providerEventId}`
102600
+ );
102601
+ const workspace = await getWorkspace7(deps.db, interaction.workspaceId);
102602
+ const defaultTools = defaults.firstPartyMcpTools ?? resolveWorkspaceSessionToolDefaults(workspace?.settings)?.firstPartyMcpTools;
102408
102603
  const prepared = slackInvocationPreparedMessage(
102409
102604
  preparedEntry,
102410
102605
  preparedAttachments,
@@ -102415,13 +102610,14 @@ async function processSlackInboxEntry(deps, entry2) {
102415
102610
  grant,
102416
102611
  interaction.workspaceId,
102417
102612
  {
102613
+ ...defaults,
102418
102614
  requestedSessionId: interaction.sessionReservationId,
102419
102615
  initialMessage: prepared.entry.text,
102420
102616
  ...prepared.modelContext ? { modelContext: prepared.modelContext } : {},
102421
102617
  instructions: SLACK_SESSION_INSTRUCTIONS,
102422
- firstPartyMcpTools: slackTaskFirstPartyMcpTools(deps.settings),
102423
- resources: preparedAttachments.resources,
102424
- ...preferredModel ? { model: preferredModel } : {},
102618
+ firstPartyMcpTools: defaultTools !== void 0 ? allowedFirstPartyMcpToolsForSession4(deps.settings, defaultTools) : slackTaskFirstPartyMcpTools(deps.settings),
102619
+ resources: [...defaults.resources, ...preparedAttachments.resources],
102620
+ ...!defaults.model && preferredModel ? { model: preferredModel } : {},
102425
102621
  idempotencyKey: `slack:${entry2.connectionId}:${entry2.providerEventId}`,
102426
102622
  clientEventId: `slack:${entry2.providerEventId}`
102427
102623
  }
@@ -102842,19 +103038,25 @@ async function processSlackReactionInboxEntry(deps, entry2) {
102842
103038
  const preparedEntry = slackReactionPreparedEntry(entry2, context, preparedTask);
102843
103039
  let session;
102844
103040
  try {
103041
+ const defaults = await slackNewSessionDefaults(
103042
+ deps,
103043
+ grant,
103044
+ interaction,
103045
+ `slack-interaction:${interaction.id}`
103046
+ );
102845
103047
  session = await createSessionForRequest2(
102846
103048
  await withCatalogSettings(deps, grant),
102847
103049
  grant,
102848
103050
  interaction.workspaceId,
102849
103051
  {
103052
+ ...defaults,
102850
103053
  requestedSessionId: interaction.sessionReservationId,
102851
103054
  initialMessage: preparedEntry.text,
102852
103055
  instructions: SLACK_SESSION_INSTRUCTIONS,
102853
- // The exact reacted message and bounded containing thread are already in
102854
- // the prompt; do not expose general Slack history tools for this trigger.
102855
- firstPartyMcpTools: resolveFirstPartyMcpToolPolicy(deps.settings).default,
102856
- resources: preparedTask.resources,
102857
- ...preferredModel ? { model: preferredModel } : {},
103056
+ // Reaction context stays bounded; ordinary tools follow the same saved
103057
+ // selection/workspace defaults as the website, without adding Slack tools.
103058
+ resources: [...defaults.resources, ...preparedTask.resources],
103059
+ ...!defaults.model && preferredModel ? { model: preferredModel } : {},
102858
103060
  // Every reaction entry converging on this route must use the same create
102859
103061
  // key. This closes the same-owner multi-event race while the owner check
102860
103062
  // above prevents a different subject from winning creation authority.
@@ -102904,6 +103106,35 @@ function slackReactionPreparedEntry(entry2, context, prepared) {
102904
103106
  text: slackReactionTaskText(context, prepared)
102905
103107
  };
102906
103108
  }
103109
+ async function slackNewSessionDefaults(deps, grant, interaction, createKey) {
103110
+ const pending = await getSessionByCreateIdempotencyKey(
103111
+ deps.db,
103112
+ interaction.workspaceId,
103113
+ createKey
103114
+ );
103115
+ if (!pending) return getActorNewSessionDefaults(deps, grant, interaction.workspaceId);
103116
+ if (pending.id !== interaction.sessionReservationId || interaction.owningSubjectId !== grant.subjectId || pending.createdBy.kind !== "subject" || pending.createdBy.subjectId !== grant.subjectId) {
103117
+ throw new SlackInteractionPermanentError("slack_session_create_identity_mismatch");
103118
+ }
103119
+ return {
103120
+ model: pending.model,
103121
+ reasoningEffort: pending.reasoningEffort,
103122
+ latencyMode: pending.latencyMode,
103123
+ resources: pending.resources.filter((resource) => resource.kind === "repository"),
103124
+ ...pending.toolPolicy.mode === "explicit" ? { tools: pending.tools } : {
103125
+ excludedMcpServerIds: pending.toolPolicy.excludedMcpServerIds
103126
+ },
103127
+ firstPartyMcpTools: pending.firstPartyMcpTools,
103128
+ ...pending.firstPartyMcpPermissions ? { firstPartyMcpPermissions: pending.firstPartyMcpPermissions } : {},
103129
+ variableSetIds: pending.variableSetIds,
103130
+ ...pending.rigId ? { rigId: pending.rigId } : {},
103131
+ sandboxBackend: pending.sandboxBackend,
103132
+ ...pending.sandboxBackend === "selfhosted" && pending.activeSandboxId ? {
103133
+ targetSandboxId: pending.activeSandboxId,
103134
+ ...pending.workingDir ? { workingDir: pending.workingDir } : {}
103135
+ } : {}
103136
+ };
103137
+ }
102907
103138
  async function remountSlackReactionTaskForSession(deps, workspaceId, sessionId, prepared) {
102908
103139
  if (prepared.attachments.length === 0) return prepared;
102909
103140
  const session = await getSession11(deps.db, workspaceId, sessionId);
@@ -104335,7 +104566,7 @@ function normalizedBlockActionInteraction(payload) {
104335
104566
  if (!teamId || !userId || !channelId || !messageTs || !actionTs || !actionId || !SLACK_BLOCK_ACTION_IDS.has(actionId) || !handleId || !/^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(handleId) || !Array.isArray(payload.actions) || payload.actions.length !== 1) {
104336
104567
  throw new HTTPException95(400, { message: "invalid Slack block action" });
104337
104568
  }
104338
- const identity2 = createHash29("sha256").update([teamId, userId, channelId, messageTs, actionTs, actionId, handleId].join("\n")).digest("hex");
104569
+ const identity2 = createHash30("sha256").update([teamId, userId, channelId, messageTs, actionTs, actionId, handleId].join("\n")).digest("hex");
104339
104570
  return {
104340
104571
  providerEventId: `block:${identity2}`,
104341
104572
  providerMessageId: `block:${identity2}`,
@@ -104600,7 +104831,7 @@ function usesPrivateBotDm(interaction, entry2) {
104600
104831
  return isDirectMessageShortcut(entry2) || interaction.visibility === "private" && entry2.triggerKind !== "dm";
104601
104832
  }
104602
104833
  function deterministicUuid2(value) {
104603
- const bytes = createHash29("sha256").update(value).digest().subarray(0, 16);
104834
+ const bytes = createHash30("sha256").update(value).digest().subarray(0, 16);
104604
104835
  bytes[6] = bytes[6] & 15 | 80;
104605
104836
  bytes[8] = bytes[8] & 63 | 128;
104606
104837
  const hex2 = bytes.toString("hex");
@@ -104825,7 +105056,7 @@ function createAppComposition(deps) {
104825
105056
  }) : deps.transcriptionSegmenter;
104826
105057
  const routeDeps = {
104827
105058
  ...deps,
104828
- resolveCatalogSettings: () => resolveCatalogSettings(deps.db, deps.settings),
105059
+ resolveCatalogSettings: () => resolveCatalogSettings2(deps.db, deps.settings),
104829
105060
  observability,
104830
105061
  githubStateSecret: deps.githubStateSecret ?? deps.settings.githubAppManifestStateSecret ?? crypto.randomUUID(),
104831
105062
  managedAuth,
@@ -105255,9 +105486,9 @@ function createAppComposition(deps) {
105255
105486
  registerMcpOAuthRoutes(app, routeDeps);
105256
105487
  app.get("/v1/config/client", async (c) => {
105257
105488
  c.header("cache-control", "no-store");
105258
- const resolvedCatalog = await resolveCatalogSettings(deps.db, deps.settings);
105489
+ const resolvedCatalog = await resolveCatalogSettings2(deps.db, deps.settings);
105259
105490
  const baseCatalogSettings = resolvedCatalog.settings;
105260
- const codexCatalogSettings = baseCatalogSettings.codexSubscriptionEnabled ? withCodexCatalogProvider2(baseCatalogSettings) : baseCatalogSettings;
105491
+ const codexCatalogSettings = baseCatalogSettings.codexSubscriptionEnabled ? withCodexCatalogProvider3(baseCatalogSettings) : baseCatalogSettings;
105261
105492
  const catalogSettings = baseCatalogSettings.supergrokSubscriptionEnabled ? withXaiSubscriptionCatalogProvider3(codexCatalogSettings) : codexCatalogSettings;
105262
105493
  return c.json(
105263
105494
  ClientConfig.parse({
@@ -105270,7 +105501,7 @@ function createAppComposition(deps) {
105270
105501
  // union of the built-in allow-list and every registry provider's models, in
105271
105502
  // selection order (default model first); project each to the client-safe
105272
105503
  // provider-blind ClientModel shape (execution topology remains server-side).
105273
- models: configuredModels3(catalogSettings).map(projectClientModel),
105504
+ models: configuredModels4(catalogSettings).map(projectClientModel),
105274
105505
  defaultReasoningEffort: deps.settings.openaiReasoningEffort,
105275
105506
  allowedReasoningEfforts: configuredAllowedReasoningEfforts(deps.settings),
105276
105507
  defaultSandboxBackend: deps.settings.sandboxBackend,
@@ -105952,7 +106183,7 @@ function readinessChecks(deps) {
105952
106183
  } else {
105953
106184
  await deps.db.execute(dbSql`select 1`);
105954
106185
  }
105955
- await resolveCatalogSettings(deps.db, deps.settings);
106186
+ await resolveCatalogSettings2(deps.db, deps.settings);
105956
106187
  },
105957
106188
  nats: async () => {
105958
106189
  requireSessionEventDurableFanoutCapability2(deps.bus);
@@ -106882,4 +107113,4 @@ export {
106882
107113
  withDefaultEnabledCapabilityMcpTools,
106883
107114
  workflowIdForSession4 as workflowIdForSession
106884
107115
  };
106885
- //# sourceMappingURL=chunk-E7TZFJ65.js.map
107116
+ //# sourceMappingURL=chunk-24C5LPNE.js.map