@opengeni/api-router 1.4.0 → 1.4.2

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.
@@ -6612,7 +6612,11 @@ import {
6612
6612
  ModelUnavailableError,
6613
6613
  ScheduledTaskTargetAccessChange
6614
6614
  } from "@opengeni/contracts";
6615
- import { isDatabaseConnectionLoss, WorkspaceControlBusyError } from "@opengeni/db";
6615
+ import {
6616
+ isDatabaseConnectionLoss,
6617
+ nestedPostgresSqlState as nestedPostgresSqlState4,
6618
+ WorkspaceControlBusyError
6619
+ } from "@opengeni/db";
6616
6620
  import { HTTPException as HTTPException20 } from "hono/http-exception";
6617
6621
  var ApiHttpError = class extends HTTPException20 {
6618
6622
  code;
@@ -6679,6 +6683,21 @@ function databaseUnavailableHttpError(error, method) {
6679
6683
  details: { code: DATABASE_UNAVAILABLE_ERROR_DETAIL_CODE }
6680
6684
  });
6681
6685
  }
6686
+ var DATABASE_CONTENTION_ERROR_DETAIL_CODE = "DATABASE_CONTENTION";
6687
+ function databaseContentionHttpError(error, method, options = {}) {
6688
+ if (error instanceof ApiHttpError) return null;
6689
+ if (error instanceof HTTPException20 && error.status < 500) return null;
6690
+ const sqlState = nestedPostgresSqlState4(error);
6691
+ if (sqlState !== "40P01" && sqlState !== "40001") return null;
6692
+ const safeMethod = method === "GET" || method === "HEAD" || method === "OPTIONS";
6693
+ return new ApiHttpError(503, {
6694
+ code: "upstream_unavailable",
6695
+ message: "Opengeni hit transient database contention. Retry shortly.",
6696
+ retryable: true,
6697
+ outcomeUnknown: options.outcomeUnknown ?? !safeMethod,
6698
+ details: { code: DATABASE_CONTENTION_ERROR_DETAIL_CODE, sqlState }
6699
+ });
6700
+ }
6682
6701
  function agentConfigHttpError(error) {
6683
6702
  const cause = error instanceof AgentConfigError ? error : error instanceof HTTPException20 && error.cause instanceof AgentConfigError ? error.cause : null;
6684
6703
  if (!cause) return null;
@@ -11828,7 +11847,7 @@ import {
11828
11847
  confirmLegacyInstruction,
11829
11848
  getKnowledgeEntry,
11830
11849
  listKnowledgeEntries,
11831
- nestedPostgresSqlState as nestedPostgresSqlState4,
11850
+ nestedPostgresSqlState as nestedPostgresSqlState5,
11832
11851
  saveKnowledgeEntry,
11833
11852
  saveAgentInstruction,
11834
11853
  getAgentInstruction,
@@ -11874,7 +11893,7 @@ function registerKnowledgeEntryTools(server, deps, grant, sessionId) {
11874
11893
  ]
11875
11894
  };
11876
11895
  }
11877
- const state = nestedPostgresSqlState4(error);
11896
+ const state = nestedPostgresSqlState5(error);
11878
11897
  const message = surface === "instruction" ? state === "40001" ? "This instruction changed. Read its current content and baseline, then retry the same intended edit against that exact state." : state === "23505" ? "This instruction operation ID was already used with different input. Reuse it only for an exact retry." : state === "42501" ? "The instruction change is unavailable in this task's scope or Agent learning policy. Off disables authoring, not the task. Do not ask for approval to continue." : state === "22023" || state === "23514" ? `Invalid instruction change. Read the current instruction, use append for a new rule, or edit with one localized exact oldText match to update or remove text. Agents cannot replace the complete instruction. Each supplied text and the resulting instruction must stay within ${WORKSPACE_INSTRUCTION_POLICY_CONTENT_MAX_CHARS} characters, the same limit as the human editor.` : "Workspace instructions are temporarily unavailable. Retry the same operation ID only if the prior change may have succeeded." : state === "40001" ? "This entry changed. Read its current revision and retry your correction with the current version." : state === "23505" ? "This operation ID was already used with different input. Reuse it only for an exact retry." : state === "42501" ? "The entry, reference, or write is unavailable in this task's scope and Agent learning policy. Off disables saving, not your task. Do not ask for an approval to continue." : state === "22023" || state === "23514" ? "Invalid Knowledge entry or relationship. Check the referenced IDs and revision before retrying." : "Knowledge is temporarily unavailable. Your task can continue; retry the same operation ID if saving may have succeeded.";
11879
11898
  return {
11880
11899
  isError: true,
@@ -12419,7 +12438,7 @@ import { HTTPException as HTTPException22 } from "hono/http-exception";
12419
12438
  import {
12420
12439
  getScheduledScopedRigVersionMetadata,
12421
12440
  loadWorkspaceEnvironmentForRun,
12422
- nestedPostgresSqlState as nestedPostgresSqlState5
12441
+ nestedPostgresSqlState as nestedPostgresSqlState6
12423
12442
  } from "@opengeni/db";
12424
12443
  async function loadSessionAttachVariableSetValues(db, settings, input) {
12425
12444
  const { accountId, workspaceId, session, subjectId } = input;
@@ -12469,7 +12488,7 @@ async function loadSessionAttachVariableSetValues(db, settings, input) {
12469
12488
  variableSetId,
12470
12489
  source
12471
12490
  });
12472
- if (nestedPostgresSqlState5(error) === "42501") {
12491
+ if (nestedPostgresSqlState6(error) === "42501") {
12473
12492
  throw new ApiHttpError(403, {
12474
12493
  code: "forbidden",
12475
12494
  message: source === "sandbox_environment_default" ? "A default Variable Set of this session's Sandbox Environment is not available to this session." : "A Variable Set selected for this session is not available to this session.",
@@ -12483,7 +12502,7 @@ async function loadSessionAttachVariableSetValues(db, settings, input) {
12483
12502
  return values;
12484
12503
  }
12485
12504
  function logAttachFailure(message, error, context) {
12486
- const sqlState = nestedPostgresSqlState5(error);
12505
+ const sqlState = nestedPostgresSqlState6(error);
12487
12506
  console.warn(`[session-attach] ${message}`, {
12488
12507
  ...context,
12489
12508
  ...sqlState ? { sqlState } : {},
@@ -16907,7 +16926,10 @@ import {
16907
16926
  } from "@opengeni/db/organization-integration-policy";
16908
16927
  import { Client as Client2 } from "@modelcontextprotocol/sdk/client/index.js";
16909
16928
  import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
16910
- import { parseIntegrationsOauthClientsJson } from "@opengeni/config";
16929
+ import {
16930
+ findIntegrationsOauthClient,
16931
+ parseIntegrationsOauthClientsJson
16932
+ } from "@opengeni/config";
16911
16933
  import {
16912
16934
  OAuthStartResponse,
16913
16935
  selectCanonicalPersonalSlackConnection
@@ -18513,7 +18535,6 @@ function operatorClientForAs(settings, as) {
18513
18535
  };
18514
18536
  }
18515
18537
  function operatorClientEntryFor(settings, candidates) {
18516
- const normalizedCandidates = new Set(candidates.map(normalizedIssuerKey));
18517
18538
  const candidateOrigins = candidates.flatMap((candidate) => {
18518
18539
  try {
18519
18540
  return [new URL(candidate).origin];
@@ -18530,22 +18551,10 @@ function operatorClientEntryFor(settings, candidates) {
18530
18551
  return resolved;
18531
18552
  }
18532
18553
  }
18533
- const configured2 = parseIntegrationsOauthClientsJson(settings.integrationsOauthClientsJson);
18534
- const exactKeys = uniqueStrings(
18535
- candidates.flatMap((candidate) => [candidate, normalizedIssuerKey(candidate)])
18554
+ return findIntegrationsOauthClient(
18555
+ parseIntegrationsOauthClientsJson(settings.integrationsOauthClientsJson),
18556
+ candidates
18536
18557
  );
18537
- for (const key of exactKeys) {
18538
- const entry2 = configured2[key];
18539
- if (entry2) {
18540
- return entry2;
18541
- }
18542
- }
18543
- for (const [key, entry2] of Object.entries(configured2)) {
18544
- if (normalizedCandidates.has(normalizedIssuerKey(key))) {
18545
- return entry2;
18546
- }
18547
- }
18548
- return null;
18549
18558
  }
18550
18559
  function gmailOAuthClientConfigured(settings) {
18551
18560
  const entry2 = operatorClientEntryFor(settings, ["https://accounts.google.com"]);
@@ -74277,7 +74286,7 @@ import {
74277
74286
  getOrganizationIntegrationPolicy,
74278
74287
  updateOrganizationIntegrationPolicy
74279
74288
  } from "@opengeni/db/organization-integration-policy";
74280
- import { nestedPostgresSqlState as nestedPostgresSqlState6 } from "@opengeni/db";
74289
+ import { nestedPostgresSqlState as nestedPostgresSqlState7 } from "@opengeni/db";
74281
74290
  import { HTTPException as HTTPException46 } from "hono/http-exception";
74282
74291
  import { z as z32 } from "zod";
74283
74292
  async function authorizeOrganizationIntegrationAdministration(context, deps, accountId, mutation) {
@@ -74306,7 +74315,7 @@ async function policyResponse(readOrWrite) {
74306
74315
  return await readOrWrite();
74307
74316
  } catch (error) {
74308
74317
  if (error instanceof HTTPException46) throw error;
74309
- const state = nestedPostgresSqlState6(error);
74318
+ const state = nestedPostgresSqlState7(error);
74310
74319
  if (state === "42501") {
74311
74320
  throw new HTTPException46(403, { message: "Organization administration required" });
74312
74321
  }
@@ -81229,7 +81238,7 @@ import {
81229
81238
  listAgentLearningOverrides,
81230
81239
  listKnowledgeEntryHistory,
81231
81240
  listKnowledgeReviewBatches,
81232
- nestedPostgresSqlState as nestedPostgresSqlState7,
81241
+ nestedPostgresSqlState as nestedPostgresSqlState8,
81233
81242
  restoreKnowledgeEntry,
81234
81243
  reviewKnowledgeEntry,
81235
81244
  saveAgentLearningSettings,
@@ -81283,7 +81292,7 @@ function knowledgeHttpError(error) {
81283
81292
  throw new HTTPException57(422, {
81284
81293
  message: error.issues[0]?.message ?? "Invalid Knowledge request"
81285
81294
  });
81286
- const state = nestedPostgresSqlState7(error);
81295
+ const state = nestedPostgresSqlState8(error);
81287
81296
  if (state === "40001" || state === "23505")
81288
81297
  throw new HTTPException57(409, { message: "This item changed. Refresh it and try again." });
81289
81298
  if (state === "42501")
@@ -95559,7 +95568,7 @@ import {
95559
95568
  getPrReviewAppRegistrationSecret,
95560
95569
  listPrReviewAppRegistrations as listPrReviewAppRegistrations3,
95561
95570
  listPrReviewRepositoryBindings as listPrReviewRepositoryBindings2,
95562
- nestedPostgresSqlState as nestedPostgresSqlState9,
95571
+ nestedPostgresSqlState as nestedPostgresSqlState10,
95563
95572
  recordAuditEvent as recordAuditEvent12,
95564
95573
  updatePrReviewAppRegistration,
95565
95574
  updatePrReviewRepositoryBinding
@@ -95775,7 +95784,7 @@ import {
95775
95784
  getAutomationSourceSecret as getAutomationSourceSecret2,
95776
95785
  listPrReviewAppRegistrations as listPrReviewAppRegistrations2,
95777
95786
  listPrReviewRepositoryBindings,
95778
- nestedPostgresSqlState as nestedPostgresSqlState8,
95787
+ nestedPostgresSqlState as nestedPostgresSqlState9,
95779
95788
  PrReviewDispatchAuthorityError,
95780
95789
  recordAuditEvent as recordAuditEvent11,
95781
95790
  resolveManagedGitHubPrReviewRoute,
@@ -96816,7 +96825,7 @@ function registerPrReviewGitHubRoutes(app, deps) {
96816
96825
  if (error instanceof PrReviewDispatchAuthorityError) {
96817
96826
  throw new HTTPException76(409, { message: error.message });
96818
96827
  }
96819
- if (nestedPostgresSqlState8(error) === "23505") {
96828
+ if (nestedPostgresSqlState9(error) === "23505") {
96820
96829
  throw new HTTPException76(409, {
96821
96830
  message: "One of these repositories is already connected to Opengeni Lens in another workspace"
96822
96831
  });
@@ -97561,7 +97570,7 @@ async function mapPrReviewUniqueConflict(operation, message) {
97561
97570
  try {
97562
97571
  return await operation;
97563
97572
  } catch (error) {
97564
- if (nestedPostgresSqlState9(error) === "23505") {
97573
+ if (nestedPostgresSqlState10(error) === "23505") {
97565
97574
  throw new HTTPException77(409, { message });
97566
97575
  }
97567
97576
  throw error;
@@ -100676,7 +100685,7 @@ import { searchSessionMessagesForSubject, SessionMessageSearchCursorError } from
100676
100685
  import { listSessionEventSlices } from "@opengeni/db/session-event-slices";
100677
100686
  import * as sessionPreviewSchema from "@opengeni/db/schema";
100678
100687
  import { SessionMessageSearchRequest } from "@opengeni/contracts";
100679
- import { scheduledSessionIds } from "@opengeni/db";
100688
+ import { requireWorkspace as requireWorkspace3, scheduledSessionIds } from "@opengeni/db";
100680
100689
  import { isVerifiedDelegatedHumanAuthorization as isVerifiedDelegatedHumanAuthorization4, withSiteSessionOrigin as withSiteSessionOrigin3 } from "@opengeni/core";
100681
100690
  import { freezeSessionRealtimeConnectionAccounts } from "@opengeni/core";
100682
100691
  import {
@@ -100922,6 +100931,7 @@ async function createGatewayRealtimeConnectionSecret(input) {
100922
100931
  getSessionRealtimeContinuityEntries3(input.db, input.workspaceId, input.sessionId),
100923
100932
  mintGatewayClientSecret({
100924
100933
  apiKey,
100934
+ source: resolved.source,
100925
100935
  upstreamModelId: resolved.upstreamModelId,
100926
100936
  fetchImpl: input.fetchImpl ?? fetch
100927
100937
  })
@@ -100950,13 +100960,14 @@ async function mintGatewayClientSecret(input) {
100950
100960
  } catch {
100951
100961
  throw new GatewayRealtimeBrokerError(
100952
100962
  "provider_error",
100953
- "AI Gateway realtime token request failed"
100963
+ "The voice provider could not be reached. Try again."
100954
100964
  );
100955
100965
  }
100956
100966
  if (!response.ok) {
100967
+ const rejected = response.status === 401 || response.status === 403;
100957
100968
  throw new GatewayRealtimeBrokerError(
100958
- response.status === 401 || response.status === 403 ? "credential_unavailable" : "provider_error",
100959
- response.status === 401 || response.status === 403 ? "AI Gateway credentials were rejected" : "AI Gateway realtime token request failed",
100969
+ rejected ? "credential_unavailable" : "provider_error",
100970
+ rejected ? input.source === "managed" ? "Opengeni voice is temporarily unavailable. Try another voice model." : "Your AI Gateway key was rejected. Update it in workspace settings." : "The voice provider could not start a call. Try again.",
100960
100971
  response.status
100961
100972
  );
100962
100973
  }
@@ -102321,18 +102332,26 @@ function registerSessionRoutes(app, deps) {
102321
102332
  if (!session) {
102322
102333
  throw new HTTPException88(404, { message: "session not found" });
102323
102334
  }
102324
- const activity = await backgroundCommandActivityForSessions(db, {
102325
- accountId: grant.accountId,
102326
- workspaceId,
102327
- sessionIds: [sessionId]
102328
- });
102329
- const scheduleTargets = hasPermission23(grant.permissions, "scheduled_tasks:run") && hasPermission23(grant.permissions, "sessions:control") ? await scheduledSessionIds(db, workspaceId, [sessionId]) : /* @__PURE__ */ new Set();
102335
+ const [activity, scheduleTargets, policy] = await Promise.all([
102336
+ backgroundCommandActivityForSessions(db, {
102337
+ accountId: grant.accountId,
102338
+ workspaceId,
102339
+ sessionIds: [sessionId]
102340
+ }),
102341
+ hasPermission23(grant.permissions, "scheduled_tasks:run") && hasPermission23(grant.permissions, "sessions:control") ? scheduledSessionIds(db, workspaceId, [sessionId]) : Promise.resolve(/* @__PURE__ */ new Set()),
102342
+ loadEffectivePolicyContext(deps, workspaceId, grant.subjectId, [session])
102343
+ ]);
102330
102344
  return c.json(
102331
- await withEffectivePolicy(deps, workspaceId, grant.subjectId, {
102332
- ...session,
102333
- hasSchedules: scheduleTargets.has(sessionId),
102334
- ...activity.get(sessionId) ? { backgroundCommandActivity: activity.get(sessionId) } : {}
102335
- })
102345
+ sessionWithEffectiveToolPolicy2(
102346
+ {
102347
+ ...session,
102348
+ hasSchedules: scheduleTargets.has(sessionId),
102349
+ ...activity.get(sessionId) ? { backgroundCommandActivity: activity.get(sessionId) } : {}
102350
+ },
102351
+ policy.workspaceServerIds,
102352
+ policy.workspaceDefaultServerIds,
102353
+ policy.effectiveToolsContext
102354
+ )
102336
102355
  );
102337
102356
  });
102338
102357
  app.get("/v1/workspaces/:workspaceId/sessions/:sessionId/model-context", async (c) => {
@@ -103146,23 +103165,31 @@ function registerSessionRoutes(app, deps) {
103146
103165
  });
103147
103166
  }
103148
103167
  try {
103149
- const result = await withWorkspaceSessionActivityRls(db, workspaceId, async (scopedDb) => {
103150
- await beforeCommit?.(scopedDb);
103151
- return syncSessionRealtimeLedgerInTransaction(
103152
- scopedDb,
103153
- {
103154
- workspaceId,
103155
- sessionId,
103156
- realtimeId,
103157
- ownerSubjectId: grant.subjectId,
103158
- ...parsed.data,
103159
- controlLockTimeoutMs: workspaceControlRequestLockTimeoutMs()
103160
- },
103161
- captureLinked ? {
103162
- afterDelegationAdmission: async ({ turnId }) => captureLinked(scopedDb, sessionId, turnId)
103163
- } : {}
103164
- );
103165
- });
103168
+ const result = await withWorkspaceSessionActivityRls(
103169
+ db,
103170
+ workspaceId,
103171
+ async (scopedDb) => {
103172
+ await beforeCommit?.(scopedDb);
103173
+ return syncSessionRealtimeLedgerInTransaction(
103174
+ scopedDb,
103175
+ {
103176
+ workspaceId,
103177
+ sessionId,
103178
+ realtimeId,
103179
+ ownerSubjectId: grant.subjectId,
103180
+ ...parsed.data,
103181
+ controlLockTimeoutMs: workspaceControlRequestLockTimeoutMs()
103182
+ },
103183
+ captureLinked ? {
103184
+ afterDelegationAdmission: async ({ turnId }) => captureLinked(scopedDb, sessionId, turnId)
103185
+ } : {}
103186
+ );
103187
+ },
103188
+ void 0,
103189
+ // External reauthorization takes the organization-membership lock,
103190
+ // which precedes the tenancy fence and the canonical session prefix.
103191
+ Boolean(beforeCommit)
103192
+ );
103166
103193
  await publishRealtimeMutation(grant.accountId, workspaceId, sessionId, result);
103167
103194
  c.header("cache-control", "private, no-store");
103168
103195
  return c.json({ accepted: result.accepted, outbound: result.outbound });
@@ -105806,11 +105833,16 @@ function codexRealtimeHttpFailure(error) {
105806
105833
  return { status: 409, code: "conflict", retryable: false };
105807
105834
  }
105808
105835
  }
105836
+ var SESSION_REALTIME_USER_MESSAGES = {
105837
+ REALTIME_ACTIVE: "Voice is already on for this session in another tab or window. End it there, or try again in a minute.",
105838
+ CONTROL_NOT_ACTIVE: "Resume this session to start voice.",
105839
+ SESSION_CANCELLED: "This session was cancelled, so voice can't start."
105840
+ };
105809
105841
  function sessionRealtimeHttpError(error) {
105810
105842
  if (error instanceof HTTPException88) return error;
105811
105843
  if (error instanceof SessionRealtimeConflictError) {
105812
105844
  return new HTTPException88(error.code === "REALTIME_NOT_FOUND" ? 404 : 409, {
105813
- message: error.message,
105845
+ message: SESSION_REALTIME_USER_MESSAGES[error.code] ?? error.message,
105814
105846
  cause: error
105815
105847
  });
105816
105848
  }
@@ -106588,9 +106620,17 @@ function commandConflictResponse(c, error) {
106588
106620
  throw error;
106589
106621
  }
106590
106622
  async function loadEffectivePolicyContext(deps, workspaceId, subjectId, sessions) {
106623
+ const workspaceRead = requireWorkspace3(deps.db, workspaceId);
106624
+ void workspaceRead.catch(() => void 0);
106591
106625
  const [policy, effectiveToolsContext] = await Promise.all([
106592
- workspaceSessionToolPolicyContext(deps.db, workspaceId, deps.settings, subjectId),
106593
- workspaceSessionEffectiveToolsContext2(deps, workspaceId, subjectId, sessions)
106626
+ workspaceSessionToolPolicyContext(
106627
+ deps.db,
106628
+ workspaceId,
106629
+ deps.settings,
106630
+ subjectId,
106631
+ workspaceRead
106632
+ ),
106633
+ workspaceSessionEffectiveToolsContext2(deps, workspaceId, subjectId, sessions, workspaceRead)
106594
106634
  ]);
106595
106635
  return { ...policy, effectiveToolsContext };
106596
106636
  }
@@ -107134,9 +107174,9 @@ import {
107134
107174
  replayWorkspaceGatewayCustomModelCreate,
107135
107175
  replayWorkspaceOpenRouterCustomModelCreate,
107136
107176
  listWorkspacesForSubject as listWorkspacesForSubject2,
107137
- nestedPostgresSqlState as nestedPostgresSqlState11,
107177
+ nestedPostgresSqlState as nestedPostgresSqlState12,
107138
107178
  removeWorkspaceMember,
107139
- requireWorkspace as requireWorkspace3,
107179
+ requireWorkspace as requireWorkspace4,
107140
107180
  updateWorkspaceSettings,
107141
107181
  getRig,
107142
107182
  setWorkspaceDefaultRig,
@@ -107185,7 +107225,7 @@ import {
107185
107225
  } from "@opengeni/core";
107186
107226
 
107187
107227
  // src/workspace-deletion.ts
107188
- import { deleteWorkspaceIfQuiescent, nestedPostgresSqlState as nestedPostgresSqlState10 } from "@opengeni/db";
107228
+ import { deleteWorkspaceIfQuiescent, nestedPostgresSqlState as nestedPostgresSqlState11 } from "@opengeni/db";
107189
107229
  import { HTTPException as HTTPException91 } from "hono/http-exception";
107190
107230
 
107191
107231
  // src/workspace-delete-observability.ts
@@ -107275,7 +107315,7 @@ async function deleteWorkspaceForRequest(deps, input) {
107275
107315
  ...observer ? { observer } : {}
107276
107316
  });
107277
107317
  } catch (error) {
107278
- const state = nestedPostgresSqlState10(error);
107318
+ const state = nestedPostgresSqlState11(error);
107279
107319
  if (state === "42501") {
107280
107320
  throw new HTTPException91(403, { message: "organization administration is not authorized" });
107281
107321
  }
@@ -107429,7 +107469,7 @@ function registerWorkspaceRoutes(app, deps) {
107429
107469
  ];
107430
107470
  if (readableWorkspaceIds.length > 0) {
107431
107471
  const workspaces = await Promise.all(
107432
- readableWorkspaceIds.map((workspaceId) => requireWorkspace3(deps.db, workspaceId))
107472
+ readableWorkspaceIds.map((workspaceId) => requireWorkspace4(deps.db, workspaceId))
107433
107473
  );
107434
107474
  return c.json(workspaces.map((workspace) => Workspace.parse(workspace)));
107435
107475
  }
@@ -107546,7 +107586,7 @@ function registerWorkspaceRoutes(app, deps) {
107546
107586
  app.get("/v1/workspaces/:workspaceId", async (c) => {
107547
107587
  const workspaceId = c.req.param("workspaceId");
107548
107588
  await requireAccessGrant39(c, deps, workspaceId, "workspace:read");
107549
- return c.json(Workspace.parse(await requireWorkspace3(deps.db, workspaceId)));
107589
+ return c.json(Workspace.parse(await requireWorkspace4(deps.db, workspaceId)));
107550
107590
  });
107551
107591
  app.patch("/v1/workspaces/:workspaceId", async (c) => {
107552
107592
  const workspaceId = c.req.param("workspaceId");
@@ -107608,14 +107648,14 @@ function registerWorkspaceRoutes(app, deps) {
107608
107648
  deps.db,
107609
107649
  workspaceId,
107610
107650
  parsed.data,
107611
- { requireWorkspace: requireWorkspace3, updateWorkspaceSettings },
107651
+ { requireWorkspace: requireWorkspace4, updateWorkspaceSettings },
107612
107652
  {
107613
107653
  controlLockTimeoutMs: workspaceControlRequestLockTimeoutMs2()
107614
107654
  }
107615
107655
  );
107616
107656
  return c.json(Workspace.parse(workspace));
107617
107657
  } catch (error) {
107618
- if (nestedPostgresSqlState11(error) === "0A000") {
107658
+ if (nestedPostgresSqlState12(error) === "0A000") {
107619
107659
  throw new HTTPException92(409, {
107620
107660
  message: "Memory settings moved to Settings > Agent learning. Refresh the app to change them."
107621
107661
  });
@@ -107811,7 +107851,7 @@ function registerWorkspaceRoutes(app, deps) {
107811
107851
  if (error instanceof WorkspaceGatewayCustomModelLimitError || error instanceof WorkspaceGatewayCustomModelHistoryLimitError) {
107812
107852
  throw new HTTPException92(422, { message: error.message });
107813
107853
  }
107814
- if (nestedPostgresSqlState11(error) === "23505") {
107854
+ if (nestedPostgresSqlState12(error) === "23505") {
107815
107855
  throw new HTTPException92(422, {
107816
107856
  message: "Gateway custom model already exists"
107817
107857
  });
@@ -107940,7 +107980,7 @@ function registerWorkspaceRoutes(app, deps) {
107940
107980
  if (error instanceof WorkspaceOpenRouterCustomModelLimitError || error instanceof WorkspaceOpenRouterCustomModelHistoryLimitError) {
107941
107981
  throw new HTTPException92(422, { message: error.message });
107942
107982
  }
107943
- if (nestedPostgresSqlState11(error) === "23505") {
107983
+ if (nestedPostgresSqlState12(error) === "23505") {
107944
107984
  throw new HTTPException92(422, {
107945
107985
  message: "OpenRouter custom model already exists"
107946
107986
  });
@@ -108020,17 +108060,18 @@ function registerWorkspaceRoutes(app, deps) {
108020
108060
  }).filter(
108021
108061
  (model, _index, offered) => offered.some((candidate) => candidate.id === AZURE_LIVE_MODEL_ID) ? model.id === AZURE_LIVE_MODEL_ID : true
108022
108062
  );
108023
- const hasCredits = managedCandidates.length > 0 && await createRealtimeVoiceBilling2({
108063
+ const creditStanding = managedCandidates.length > 0 ? await createRealtimeVoiceBilling2({
108024
108064
  db: deps.db,
108025
108065
  settings: deps.settings
108026
- }).hasSpendableCredits(grant.accountId);
108066
+ }).creditStanding(grant.accountId) : "none";
108067
+ const hasCredits = creditStanding === "spendable";
108027
108068
  const models = [
108028
108069
  ...managedCandidates.map((model, index) => ({
108029
108070
  ...model,
108030
108071
  provider: "OpenGeni",
108031
108072
  ...hasCredits ? { available: true, unavailableReason: null, unavailableCode: null } : {
108032
108073
  available: false,
108033
- unavailableReason: "Add Opengeni credits to use live voice",
108074
+ unavailableReason: creditStanding === "promotional_only" ? "Promotional credits don't cover live voice. Add credits to use it." : "Add Opengeni credits to use live voice",
108034
108075
  unavailableCode: "insufficient_credits"
108035
108076
  },
108036
108077
  recommended: index === 0
@@ -108378,7 +108419,7 @@ function rethrowWorkspaceMemberCandidateError(error) {
108378
108419
  message: "the workspace must keep at least one administrator"
108379
108420
  });
108380
108421
  }
108381
- const sqlState = nestedPostgresSqlState11(error);
108422
+ const sqlState = nestedPostgresSqlState12(error);
108382
108423
  if (sqlState === "P0002") {
108383
108424
  throw new HTTPException92(404, { message: "workspace not found" });
108384
108425
  }
@@ -108443,7 +108484,7 @@ import {
108443
108484
  getWorkspace as getWorkspace6,
108444
108485
  getWorkspaceUsage,
108445
108486
  grantWorkspaceCredits,
108446
- nestedPostgresSqlState as nestedPostgresSqlState12,
108487
+ nestedPostgresSqlState as nestedPostgresSqlState13,
108447
108488
  setMemberAllowance,
108448
108489
  setWorkspaceAllowance,
108449
108490
  withAccountRls as withAccountRls3,
@@ -108578,7 +108619,7 @@ async function lifecycle2(operation) {
108578
108619
  } catch (error) {
108579
108620
  if (error instanceof UsageAllowanceVersionConflictError)
108580
108621
  throw new HTTPException93(409, { message: error.message });
108581
- const state = nestedPostgresSqlState12(error);
108622
+ const state = nestedPostgresSqlState13(error);
108582
108623
  if (state === "40001" || state === "23505")
108583
108624
  throw new HTTPException93(409, { message: "Allowance version or operation conflicts" });
108584
108625
  if (state === "42501")
@@ -110329,7 +110370,7 @@ import {
110329
110370
  } from "@opengeni/core";
110330
110371
  import {
110331
110372
  availableSlackBotConnectionMetadata as availableSlackBotConnectionMetadata2,
110332
- nestedPostgresSqlState as nestedPostgresSqlState13,
110373
+ nestedPostgresSqlState as nestedPostgresSqlState14,
110333
110374
  readOrganizationSlackBotAccess,
110334
110375
  setOrganizationSlackBotAccess,
110335
110376
  sharedOrganizationSlackBots as sharedOrganizationSlackBots2
@@ -110359,7 +110400,7 @@ function registerSlackBotAccessRoutes(app, deps) {
110359
110400
  )
110360
110401
  );
110361
110402
  } catch (error) {
110362
- if (nestedPostgresSqlState13(error) === "42501")
110403
+ if (nestedPostgresSqlState14(error) === "42501")
110363
110404
  throw new HTTPException99(404, { message: "Local bot installation unavailable" });
110364
110405
  throw error;
110365
110406
  }
@@ -110413,7 +110454,7 @@ function registerSlackBotAccessRoutes(app, deps) {
110413
110454
  return context.json(OpenGeniSlackBotOrganizationAccess.parse(result));
110414
110455
  } catch (error) {
110415
110456
  if (error instanceof HTTPException99) throw error;
110416
- if (nestedPostgresSqlState13(error) === "42501")
110457
+ if (nestedPostgresSqlState14(error) === "42501")
110417
110458
  throw new HTTPException99(403, {
110418
110459
  message: "Organization administrator and a verified local bot installation required"
110419
110460
  });
@@ -110610,7 +110651,7 @@ import {
110610
110651
  getWorkspaceArtifact as getWorkspaceArtifact3,
110611
110652
  getWorkspaceArtifactContentRef as getWorkspaceArtifactContentRef3,
110612
110653
  listWorkspaceArtifacts as listWorkspaceArtifacts2,
110613
- nestedPostgresSqlState as nestedPostgresSqlState14,
110654
+ nestedPostgresSqlState as nestedPostgresSqlState15,
110614
110655
  publishWorkspaceArtifactVersion as publishWorkspaceArtifactVersion2,
110615
110656
  rollbackWorkspaceArtifact as rollbackWorkspaceArtifact2,
110616
110657
  setWorkspaceArtifactStatus as setWorkspaceArtifactStatus2,
@@ -110657,7 +110698,7 @@ function workspaceArtifactErrorResponse(context, error) {
110657
110698
  422
110658
110699
  );
110659
110700
  }
110660
- if (nestedPostgresSqlState14(error) === "23505") {
110701
+ if (nestedPostgresSqlState15(error) === "23505") {
110661
110702
  return context.json(
110662
110703
  {
110663
110704
  code: "WORKSPACE_ARTIFACT_CONFLICT",
@@ -111041,7 +111082,7 @@ import {
111041
111082
  getGeneratedImageArtifact as getGeneratedImageArtifact2,
111042
111083
  getSessionAuthorityProjection as getSessionAuthorityProjection3,
111043
111084
  listArtifactCatalogCandidates,
111044
- nestedPostgresSqlState as nestedPostgresSqlState15,
111085
+ nestedPostgresSqlState as nestedPostgresSqlState16,
111045
111086
  updateArtifactPin,
111046
111087
  withSessionRlsActorContext as withSessionRlsActorContext9
111047
111088
  } from "@opengeni/db";
@@ -111176,7 +111217,7 @@ function registerArtifactCatalogRoutes(app, deps) {
111176
111217
  }
111177
111218
  );
111178
111219
  } catch (error) {
111179
- if (nestedPostgresSqlState15(error) === "42501")
111220
+ if (nestedPostgresSqlState16(error) === "42501")
111180
111221
  throw new HTTPException103(404, { message: "Artifact not found" });
111181
111222
  throw error;
111182
111223
  }
@@ -114896,11 +114937,11 @@ import {
114896
114937
  getOrganizationPrivateSessionSettings,
114897
114938
  getSelfOrganizationInvitation,
114898
114939
  getOrganizationRetentionPolicy,
114899
- requireWorkspace as requireWorkspace4,
114940
+ requireWorkspace as requireWorkspace5,
114900
114941
  listOrganizationAdministrationMembers,
114901
114942
  listOrganizationInvitations,
114902
114943
  listSelfOrganizationInvitations,
114903
- nestedPostgresSqlState as nestedPostgresSqlState16,
114944
+ nestedPostgresSqlState as nestedPostgresSqlState17,
114904
114945
  prepareOrganizationUserSetupDelivery,
114905
114946
  revokeOrganizationInvitation,
114906
114947
  settleOrganizationUserSetupDelivery,
@@ -114949,7 +114990,7 @@ async function requireOrganizationKeyWorkspaceDeletion(context, deps, organizati
114949
114990
  message: "deleting an organization workspace requires an organization owner session or an organization API key with workspace:admin"
114950
114991
  });
114951
114992
  }
114952
- const workspace = await requireWorkspace4(deps.db, workspaceId).catch(() => null);
114993
+ const workspace = await requireWorkspace5(deps.db, workspaceId).catch(() => null);
114953
114994
  if (!workspace || workspace.accountId !== organizationId2) {
114954
114995
  throw new HTTPException112(404, { message: "workspace not found" });
114955
114996
  }
@@ -115017,7 +115058,7 @@ function parseId(schema, value, label) {
115017
115058
  return parsed.data;
115018
115059
  }
115019
115060
  function rethrowMembershipError(error, resourceLimitMessage) {
115020
- const sqlState = nestedPostgresSqlState16(error);
115061
+ const sqlState = nestedPostgresSqlState17(error);
115021
115062
  if (sqlState === "54000" && resourceLimitMessage) {
115022
115063
  throw new HTTPException112(409, {
115023
115064
  message: resourceLimitMessage
@@ -115123,7 +115164,7 @@ function registerOrganizationMembershipRoutes(app, deps) {
115123
115164
  })
115124
115165
  );
115125
115166
  } catch (error) {
115126
- if (nestedPostgresSqlState16(error) === "42501") {
115167
+ if (nestedPostgresSqlState17(error) === "42501") {
115127
115168
  throw new HTTPException112(403, {
115128
115169
  message: "organization membership is not active"
115129
115170
  });
@@ -116266,7 +116307,7 @@ import {
116266
116307
  completeSelfServiceOrganizationSetup,
116267
116308
  completeOrganizationUserSetup,
116268
116309
  getSelfServiceOrganizationOnboardingState,
116269
- nestedPostgresSqlState as nestedPostgresSqlState17,
116310
+ nestedPostgresSqlState as nestedPostgresSqlState18,
116270
116311
  preflightOrganizationUserSetup,
116271
116312
  previewOrganizationUserSetup,
116272
116313
  recordOrganizationSignupUseCase
@@ -116324,14 +116365,14 @@ function registerManagedOnboardingRoutes(app, deps, options = {}) {
116324
116365
  useCase: parsed.data.useCase
116325
116366
  }).catch((error) => {
116326
116367
  console.warn("[api] could not record the signup use case", {
116327
- sqlState: nestedPostgresSqlState17(error) ?? null
116368
+ sqlState: nestedPostgresSqlState18(error) ?? null
116328
116369
  });
116329
116370
  });
116330
116371
  }
116331
116372
  return context.json(completed);
116332
116373
  } catch (error) {
116333
116374
  recordOrganizationSetupOutcome(deps.observability, "failed");
116334
- const sqlState = nestedPostgresSqlState17(error);
116375
+ const sqlState = nestedPostgresSqlState18(error);
116335
116376
  if (sqlState === "22023") {
116336
116377
  throw new HTTPException115(422, {
116337
116378
  message: "invalid organization setup request"
@@ -116411,7 +116452,7 @@ function registerManagedOnboardingRoutes(app, deps, options = {}) {
116411
116452
  )
116412
116453
  );
116413
116454
  } catch (error) {
116414
- const sqlState = nestedPostgresSqlState17(error);
116455
+ const sqlState = nestedPostgresSqlState18(error);
116415
116456
  if (sqlState === "22023") {
116416
116457
  throw new HTTPException115(422, {
116417
116458
  message: "invalid account setup request"
@@ -116532,7 +116573,7 @@ import {
116532
116573
  SessionAuthorizationUnavailableError as SessionAuthorizationUnavailableError15,
116533
116574
  SessionTenancyManagedHumanRequiredError as SessionTenancyManagedHumanRequiredError3
116534
116575
  } from "@opengeni/core";
116535
- import { nestedPostgresSqlState as nestedPostgresSqlState18, SessionTenancyNotActivatedError as SessionTenancyNotActivatedError3 } from "@opengeni/db";
116576
+ import { nestedPostgresSqlState as nestedPostgresSqlState19, SessionTenancyNotActivatedError as SessionTenancyNotActivatedError3 } from "@opengeni/db";
116536
116577
  import { HTTPException as HTTPException116 } from "hono/http-exception";
116537
116578
  import { z as z62 } from "zod";
116538
116579
  async function body2(context, schema) {
@@ -116547,10 +116588,10 @@ function lifecycleError(error) {
116547
116588
  if (error instanceof SessionAuthorizationUnavailableError15) {
116548
116589
  throw new HTTPException116(503, { message: "session authorization unavailable" });
116549
116590
  }
116550
- if (nestedPostgresSqlState18(error) === "42501") {
116591
+ if (nestedPostgresSqlState19(error) === "42501") {
116551
116592
  throw new HTTPException116(403, { message: "user-resource authority denied" });
116552
116593
  }
116553
- if (nestedPostgresSqlState18(error) === "22023") {
116594
+ if (nestedPostgresSqlState19(error) === "22023") {
116554
116595
  throw new HTTPException116(422, { message: "invalid user-resource request" });
116555
116596
  }
116556
116597
  throw error;
@@ -123141,6 +123182,10 @@ function createAppComposition(deps) {
123141
123182
  "X-OpenGeni-Access-Key",
123142
123183
  "X-OpenGeni-Api-Contract",
123143
123184
  "X-OpenGeni-Actor-Epoch",
123185
+ // Resumable voice-input chunk integrity/timing (cross-origin embeds).
123186
+ "X-OpenGeni-Chunk-Duration-Milliseconds",
123187
+ "X-OpenGeni-Chunk-Sha256",
123188
+ "X-OpenGeni-Chunk-Start-Milliseconds",
123144
123189
  "X-OpenGeni-Correlation-Id",
123145
123190
  "X-OpenGeni-Session-Csrf",
123146
123191
  // Session scope for a session proxy; the API itself ignores it.
@@ -124240,13 +124285,13 @@ function createAppComposition(deps) {
124240
124285
  latencyMode: rawError.latencyMode,
124241
124286
  allowedLatencyModes: [...rawError.allowedLatencyModes]
124242
124287
  }
124243
- }) : null) ?? requestBodyValidationHttpError(rawError) ?? invalidPathIdentifierHttpError(rawError, new URL(c.req.url).pathname) ?? databaseUnavailableHttpError(rawError, c.req.method) ?? rawError;
124288
+ }) : null) ?? requestBodyValidationHttpError(rawError) ?? invalidPathIdentifierHttpError(rawError, new URL(c.req.url).pathname) ?? databaseUnavailableHttpError(rawError, c.req.method) ?? databaseContentionHttpError(rawError, c.req.method) ?? rawError;
124244
124289
  const compactionLock = codexCompactionV2ProviderLockedError(error);
124245
124290
  const apiError = error instanceof ApiHttpError ? error : null;
124246
124291
  const status = compactionLock ? 422 : httpStatusForError(error);
124247
124292
  const code = compactionLock ? compactionLock.code : apiError?.code ?? errorCodeForStatus(status);
124248
124293
  if (status >= 500) logHttpFailure(c, status, code, rawError);
124249
- if (apiError?.details?.code === DATABASE_UNAVAILABLE_ERROR_DETAIL_CODE) {
124294
+ if (apiError?.details?.code === DATABASE_UNAVAILABLE_ERROR_DETAIL_CODE || apiError?.details?.code === DATABASE_CONTENTION_ERROR_DETAIL_CODE) {
124250
124295
  c.header("retry-after", "1");
124251
124296
  }
124252
124297
  const envelope = ErrorEnvelope.parse({
@@ -124467,6 +124512,8 @@ function assertConfiguredCodemodeSessionProxyPath(session, path, method) {
124467
124512
  }
124468
124513
  }
124469
124514
  function codemodeHttpError(error) {
124515
+ const contention = databaseContentionHttpError(error, "POST", { outcomeUnknown: false });
124516
+ if (contention) return contention;
124470
124517
  if (error instanceof SiteSessionPathError) {
124471
124518
  return new HTTPException118(404, { message: error.message, cause: error });
124472
124519
  }
@@ -125706,4 +125753,4 @@ export {
125706
125753
  withDefaultEnabledCapabilityMcpTools,
125707
125754
  workflowIdForSession4 as workflowIdForSession
125708
125755
  };
125709
- //# sourceMappingURL=chunk-KKEXIBQG.js.map
125756
+ //# sourceMappingURL=chunk-F3LQ6VWR.js.map