@opengeni/api-router 0.21.10 → 0.21.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/app.js CHANGED
@@ -22,7 +22,7 @@ import {
22
22
  validateToolRefs,
23
23
  withDefaultEnabledCapabilityMcpTools,
24
24
  workflowIdForSession
25
- } from "./chunk-J4JS2F7L.js";
25
+ } from "./chunk-R5PDSH2A.js";
26
26
  export {
27
27
  API_MAX_REQUEST_BODY_BYTES,
28
28
  allowedCorsOrigin,
@@ -347,7 +347,6 @@ import {
347
347
  getPreferenceRegistryFullContent,
348
348
  getVariableSet,
349
349
  getVariableSetByName,
350
- areGitHubRepositoriesAllowedForWorkspace,
351
350
  listScheduledTaskRuns,
352
351
  listScheduledTasks,
353
352
  listSessionEventPage,
@@ -386,7 +385,6 @@ import {
386
385
  import { appendAndPublishEvents as appendAndPublishEvents2, publishDurableSessionEvents } from "@opengeni/events";
387
386
  import {
388
387
  createSignedState as createSignedState3,
389
- createGitHubAppInstallationToken,
390
388
  GitHubAppConfigurationError,
391
389
  githubAppMissingSettings
392
390
  } from "@opengeni/github";
@@ -6253,7 +6251,6 @@ var FIRST_PARTY_TOOL_AUTHORIZATION = {
6253
6251
  variable_set_set_variable: { allOf: ["variable-sets:manage"] },
6254
6252
  environment_set_variable: { allOf: ["variable-sets:manage"] },
6255
6253
  github_connect_link: { allOf: ["github:use"] },
6256
- github_token: { sessionRequired: true, allOf: ["github:use"] },
6257
6254
  github_repositories_list: { allOf: ["github:use"] },
6258
6255
  social_connections_list: { allOf: ["connections:read"] },
6259
6256
  social_posts_recent: { allOf: ["connections:read"] },
@@ -6411,9 +6408,6 @@ function buildOpenGeniMcpServer(deps, grant, options = {}) {
6411
6408
  registerVariableSetTools(server, deps, grant, can, json);
6412
6409
  if (can("github:use")) {
6413
6410
  registerGitHubConnectTool(server, deps, grant, options, json);
6414
- if (sessionId !== null) {
6415
- registerGitHubTokenTool(server, deps, grant, sessionId, json);
6416
- }
6417
6411
  }
6418
6412
  if (!toolspaceMode || can("github:use")) {
6419
6413
  server.registerTool(
@@ -8508,50 +8502,6 @@ function registerGitHubConnectTool(server, deps, grant, options, json) {
8508
8502
  }
8509
8503
  );
8510
8504
  }
8511
- function registerGitHubTokenTool(server, deps, grant, sessionId, json) {
8512
- server.registerTool(
8513
- "github_token",
8514
- {
8515
- description: "Mint a fresh short-lived GitHub token for this session's repositories. Write it to $OPENGENI_GIT_TOKEN_FILE (default $HOME/.opengeni/git-token) to refresh git auth before the current token expires.",
8516
- inputSchema: {}
8517
- },
8518
- async () => {
8519
- const session = await requireSession(deps.db, grant.workspaceId, sessionId);
8520
- const selected = (session.resources ?? []).flatMap((resource) => {
8521
- if (resource.kind !== "repository") {
8522
- return [];
8523
- }
8524
- const installationId2 = resource.githubInstallationId;
8525
- const repositoryId = resource.githubRepositoryId;
8526
- return typeof installationId2 === "number" && installationId2 > 0 && typeof repositoryId === "number" && repositoryId > 0 ? [{ installationId: installationId2, repositoryId }] : [];
8527
- });
8528
- if (selected.length === 0) {
8529
- throw new Error("this session has no GitHub App repository resources to mint a token for");
8530
- }
8531
- const installationId = selected[0].installationId;
8532
- if (selected.some((item) => item.installationId !== installationId)) {
8533
- throw new Error("GitHub App repository resources must belong to one installation");
8534
- }
8535
- const repositoryIds = selected.map((item) => item.repositoryId);
8536
- if (!await areGitHubRepositoriesAllowedForWorkspace(
8537
- deps.db,
8538
- grant.workspaceId,
8539
- installationId,
8540
- repositoryIds
8541
- )) {
8542
- throw new Error("this workspace no longer authorizes the session's GitHub repositories");
8543
- }
8544
- const token = await createGitHubAppInstallationToken(deps.settings, {
8545
- installationId,
8546
- repositoryIds
8547
- });
8548
- return json({
8549
- token,
8550
- tokenFile: "$OPENGENI_GIT_TOKEN_FILE (default $HOME/.opengeni/git-token)"
8551
- });
8552
- }
8553
- );
8554
- }
8555
8505
  function requireVariableSetsUseForMcpAttachment(grant, variableSetId) {
8556
8506
  if (variableSetId !== void 0 && !hasPermission4(grant.permissions, "variable-sets:use")) {
8557
8507
  throw new Error("missing permission: variable-sets:use");
@@ -8937,6 +8887,8 @@ import {
8937
8887
  boundedParallelMap,
8938
8888
  cancelMcpResponseBody,
8939
8889
  guardedMcpFetch,
8890
+ mcpJsonRpcErrorPayloadForRequest,
8891
+ mcpRequestReplayInfo,
8940
8892
  mcpSerializedSizeBytes
8941
8893
  } from "@opengeni/runtime/mcp-network";
8942
8894
  import { Buffer as Buffer4 } from "buffer";
@@ -8948,8 +8900,12 @@ var TOOLSPACE_AUTH_NEEDED_ERROR = {
8948
8900
  code: 40101,
8949
8901
  message: "Authentication required - a connection link was posted to the session."
8950
8902
  };
8903
+ var TOOLSPACE_TOOL_OUTCOME_UNCERTAIN_ERROR = {
8904
+ code: 40102,
8905
+ message: "Tool outcome uncertain: the provider returned 401 after receiving the request. OpenGeni did not replay this call. Do not retry automatically; verify provider state before any new attempt."
8906
+ };
8951
8907
  var TOOLSPACE_NO_ACTIVE_TURN_MESSAGE = "no active turn - toolspace calls require an in-flight turn";
8952
- var FIRST_PARTY_PROXY_IDS = /* @__PURE__ */ new Set(["files", "docs"]);
8908
+ var FIRST_PARTY_PROXY_IDS = /* @__PURE__ */ new Set(["files", "docs", "codex_apps"]);
8953
8909
  var TOOLSPACE_TOOL_LIST_TTL_MS = 3e4;
8954
8910
  var TOOLSPACE_TOOL_LIST_CACHE_MAX_ENTRIES = 2e3;
8955
8911
  var TOOLSPACE_TOOL_LIST_CACHE_MAX_BYTES = 64 * 1024 * 1024;
@@ -9462,6 +9418,9 @@ async function callRemoteTool(deps, server, toolName, args) {
9462
9418
  if (isToolspaceAuthNeededError(error)) {
9463
9419
  return mcpError(TOOLSPACE_AUTH_NEEDED_ERROR.message);
9464
9420
  }
9421
+ if (isToolspaceOutcomeUncertainError(error)) {
9422
+ return mcpError(TOOLSPACE_TOOL_OUTCOME_UNCERTAIN_ERROR.message);
9423
+ }
9465
9424
  deps.observability?.warn("toolspace upstream tool call failed", {
9466
9425
  serverId: server.config.id,
9467
9426
  toolName,
@@ -9588,7 +9547,7 @@ function connectionBrokerFetch(baseFetch, input) {
9588
9547
  ownerHasWorkspaceMembership: delegatedOwnerHasMembership
9589
9548
  });
9590
9549
  return async (requestInput, init) => {
9591
- const request = await mcpRequestInfo(requestInput, init);
9550
+ const request = await mcpRequestReplayInfo(requestInput, init);
9592
9551
  const destinationUrl = mcpRequestDestinationUrl(requestInput);
9593
9552
  const resolverSubjectId = connectionRef.subjectScope !== "subject" && hostCredentialPort ? input.grant.subjectId : void 0;
9594
9553
  const resolve = async (forceRefresh) => {
@@ -9613,10 +9572,22 @@ function connectionBrokerFetch(baseFetch, input) {
9613
9572
  );
9614
9573
  if (response.status === 401) {
9615
9574
  await cancelMcpResponseBody(response);
9616
- const refreshed = await resolve(true);
9575
+ let refreshed;
9576
+ try {
9577
+ refreshed = await resolve(true);
9578
+ } catch {
9579
+ refreshed = authNeededFromStatus(input.config, first, "refresh_failed");
9580
+ }
9617
9581
  if (refreshed.status === "auth_needed") {
9582
+ if (!request.replaySafeAfter401) {
9583
+ await publishToolspaceAuthNeeded(input, request, refreshed);
9584
+ return toolspaceMcpOutcomeUncertainResponse(request);
9585
+ }
9618
9586
  return await authNeededFetchResponse(input, request, refreshed);
9619
9587
  }
9588
+ if (!request.replaySafeAfter401) {
9589
+ return toolspaceMcpOutcomeUncertainResponse(request);
9590
+ }
9620
9591
  const retry = await baseFetch(
9621
9592
  fetchInputForAttempt(requestInput),
9622
9593
  withConnectionHeaders(requestInput, init, refreshed.headers)
@@ -9664,6 +9635,13 @@ function authNeededFromStatus(config, first, reason) {
9664
9635
  };
9665
9636
  }
9666
9637
  async function authNeededFetchResponse(input, request, auth) {
9638
+ await publishToolspaceAuthNeeded(input, request, auth);
9639
+ if (request.method === "tools/call") {
9640
+ return toolspaceMcpErrorResponse(request.id, TOOLSPACE_AUTH_NEEDED_ERROR);
9641
+ }
9642
+ return new Response("Authentication required for MCP server connection", { status: 401 });
9643
+ }
9644
+ async function publishToolspaceAuthNeeded(input, request, auth) {
9667
9645
  await appendAndPublishEvents3(
9668
9646
  input.deps.db,
9669
9647
  input.deps.bus,
@@ -9689,42 +9667,30 @@ async function authNeededFetchResponse(input, request, auth) {
9689
9667
  }
9690
9668
  ]
9691
9669
  ).catch(() => void 0);
9692
- if (request.method === "tools/call") {
9693
- return new Response(
9694
- JSON.stringify({
9695
- jsonrpc: "2.0",
9696
- id: request.id ?? null,
9697
- error: {
9698
- code: TOOLSPACE_AUTH_NEEDED_ERROR.code,
9699
- message: TOOLSPACE_AUTH_NEEDED_ERROR.message
9700
- }
9701
- }),
9702
- {
9703
- status: 200,
9704
- headers: { "content-type": "application/json" }
9705
- }
9706
- );
9707
- }
9708
- return new Response("Authentication required for MCP server connection", { status: 401 });
9709
9670
  }
9710
- async function mcpRequestInfo(input, init) {
9711
- const body2 = typeof init?.body === "string" ? init.body : input instanceof Request && (init?.method ?? input.method).toUpperCase() === "POST" ? await input.clone().text().catch(() => "") : "";
9712
- if (!body2) {
9713
- return {};
9714
- }
9715
- try {
9716
- const parsed = JSON.parse(body2);
9717
- const method = typeof parsed.method === "string" ? parsed.method : void 0;
9718
- const id = typeof parsed.id === "string" || typeof parsed.id === "number" || parsed.id === null ? parsed.id : void 0;
9719
- const toolName = method === "tools/call" && typeof parsed.params?.name === "string" ? parsed.params.name : void 0;
9720
- return {
9721
- ...method ? { method } : {},
9722
- ...id !== void 0 ? { id } : {},
9723
- ...toolName ? { toolName } : {}
9724
- };
9725
- } catch {
9726
- return {};
9727
- }
9671
+ function toolspaceMcpErrorResponse(id, error) {
9672
+ return new Response(
9673
+ JSON.stringify({
9674
+ jsonrpc: "2.0",
9675
+ id: id ?? null,
9676
+ error
9677
+ }),
9678
+ {
9679
+ status: 200,
9680
+ headers: { "content-type": "application/json" }
9681
+ }
9682
+ );
9683
+ }
9684
+ function toolspaceMcpOutcomeUncertainResponse(request) {
9685
+ return new Response(
9686
+ JSON.stringify(
9687
+ mcpJsonRpcErrorPayloadForRequest(request, TOOLSPACE_TOOL_OUTCOME_UNCERTAIN_ERROR)
9688
+ ),
9689
+ {
9690
+ status: 200,
9691
+ headers: { "content-type": "application/json" }
9692
+ }
9693
+ );
9728
9694
  }
9729
9695
  function withConnectionHeaders(input, init, authHeaders) {
9730
9696
  const headers = new Headers(
@@ -9745,6 +9711,13 @@ function isToolspaceAuthNeededError(error) {
9745
9711
  const code = error.code;
9746
9712
  return code === TOOLSPACE_AUTH_NEEDED_ERROR.code && (error.message === TOOLSPACE_AUTH_NEEDED_ERROR.message || error.message === `MCP error ${TOOLSPACE_AUTH_NEEDED_ERROR.code}: ${TOOLSPACE_AUTH_NEEDED_ERROR.message}`);
9747
9713
  }
9714
+ function isToolspaceOutcomeUncertainError(error) {
9715
+ if (!(error instanceof Error)) {
9716
+ return false;
9717
+ }
9718
+ const code = error.code;
9719
+ return code === TOOLSPACE_TOOL_OUTCOME_UNCERTAIN_ERROR.code && (error.message === TOOLSPACE_TOOL_OUTCOME_UNCERTAIN_ERROR.message || error.message === `MCP error ${TOOLSPACE_TOOL_OUTCOME_UNCERTAIN_ERROR.code}: ${TOOLSPACE_TOOL_OUTCOME_UNCERTAIN_ERROR.message}`);
9720
+ }
9748
9721
 
9749
9722
  // src/app.ts
9750
9723
  import { boundedMcpRequest, McpPayloadTooLargeError as McpPayloadTooLargeError2 } from "@opengeni/runtime/mcp-network";
@@ -10166,6 +10139,8 @@ import {
10166
10139
  buildCodexTokenResolver,
10167
10140
  claimCodexResetRedemption,
10168
10141
  completeCodexResetRedemption,
10142
+ clearCodexAppsCredential,
10143
+ designateCodexAppsCredential,
10169
10144
  disconnectAllCodexAccounts,
10170
10145
  disconnectCodexAccount,
10171
10146
  encryptEnvironmentValue as encryptEnvironmentValue3,
@@ -10175,6 +10150,7 @@ import {
10175
10150
  fenceCodexResetRedemptionSend,
10176
10151
  getCodexResetRedemptionAttempt,
10177
10152
  getCodexCredentialStatus,
10153
+ getCodexAppsSettings,
10178
10154
  getCodexRotationSettings,
10179
10155
  listPendingCodexCapacityWakeTargets,
10180
10156
  listCodexAccountStatuses,
@@ -10255,7 +10231,7 @@ async function verifyCodexRedemptionConfirmation(secret, token, now = Date.now()
10255
10231
 
10256
10232
  // src/routes/codex.ts
10257
10233
  var CODEX_PROVIDER_LABEL = "Codex subscription \xB7 no credits";
10258
- function codexAccountJson(row) {
10234
+ function codexAccountJson(row, options = {}) {
10259
10235
  return {
10260
10236
  id: row.id,
10261
10237
  chatgptAccountId: row.chatgptAccountId,
@@ -10284,7 +10260,9 @@ function codexAccountJson(row) {
10284
10260
  resetCreditAvailableCount: row.resetCreditAvailableCount,
10285
10261
  resetCreditsCheckedAt: row.resetCreditsCheckedAt,
10286
10262
  // P3 rotation cooldown: when set and in the future, this account is cooling-down.
10287
- exhaustedUntil: row.exhaustedUntil
10263
+ exhaustedUntil: row.exhaustedUntil,
10264
+ appsDesignated: options.appsCredentialId === row.id,
10265
+ canEnableApps: options.appsCredentialId === null && options.canManageApps === true && options.humanSubjectId !== null && options.humanSubjectId !== void 0 && row.connectedBySubjectId === options.humanSubjectId && row.status === "active"
10288
10266
  };
10289
10267
  }
10290
10268
  function codexUsageJson(payload) {
@@ -10378,6 +10356,23 @@ async function requireRedemptionHuman(c, deps, workspaceId) {
10378
10356
  }
10379
10357
  return { human, accountId: grant.accountId };
10380
10358
  }
10359
+ async function requireCodexAppsHuman(c, deps, workspaceId) {
10360
+ if (c.req.header("authorization")) {
10361
+ throw new HTTPException10(403, {
10362
+ message: "authorization bearer is not allowed for Codex Apps designation"
10363
+ });
10364
+ }
10365
+ requireSameOriginBrowserMutation(c, deps);
10366
+ const human = await managedCookieHuman(c, deps);
10367
+ if (!human) {
10368
+ throw new HTTPException10(401, { message: "managed browser session required" });
10369
+ }
10370
+ const grant = await requireAccessGrant2(c, deps, workspaceId, "connections:write");
10371
+ if (grant.subjectId !== human.subjectId) {
10372
+ throw new HTTPException10(403, { message: "managed browser identity mismatch" });
10373
+ }
10374
+ return { human, accountId: grant.accountId };
10375
+ }
10381
10376
  function cachedUsage(row) {
10382
10377
  const fiveHour = buildCodexUsageWindowFromCache(
10383
10378
  row.primaryUsedPercent,
@@ -10733,15 +10728,32 @@ function registerCodexRoutes(app, deps) {
10733
10728
  });
10734
10729
  app.get("/v1/workspaces/:workspaceId/codex/accounts", async (c) => {
10735
10730
  const workspaceId = c.req.param("workspaceId");
10736
- await requireAccessGrant2(c, deps, workspaceId, "workspace:read");
10737
- const [accounts, rotation] = await Promise.all([
10731
+ const grant = await requireAccessGrant2(c, deps, workspaceId, "workspace:read");
10732
+ const [accounts, rotation, apps, human] = await Promise.all([
10738
10733
  listCodexAccountStatuses(db, workspaceId),
10739
- getCodexRotationSettings(db, workspaceId)
10734
+ getCodexRotationSettings(db, workspaceId),
10735
+ getCodexAppsSettings(db, workspaceId),
10736
+ managedCookieHuman(c, deps)
10740
10737
  ]);
10741
10738
  const activeAccountId = rotation?.activeCredentialId ?? null;
10739
+ const humanSubjectId = human?.subjectId === grant.subjectId ? human.subjectId : null;
10740
+ const canManageApps = humanSubjectId !== null && hasPermission6(grant.permissions, "connections:write");
10742
10741
  return c.json({
10743
- accounts: accounts.map(codexAccountJson),
10742
+ accounts: accounts.map(
10743
+ (account) => codexAccountJson(account, {
10744
+ appsCredentialId: apps.credentialId,
10745
+ canManageApps: settings.codexConnectedAppsEnabled && canManageApps,
10746
+ humanSubjectId
10747
+ })
10748
+ ),
10744
10749
  activeAccountId,
10750
+ apps: {
10751
+ available: settings.codexConnectedAppsEnabled,
10752
+ credentialId: apps.credentialId,
10753
+ version: apps.version,
10754
+ designatedAt: apps.designatedAt,
10755
+ canDisable: canManageApps && apps.credentialId !== null
10756
+ },
10745
10757
  settings: {
10746
10758
  rotationEnabled: rotation?.rotationEnabled ?? false,
10747
10759
  // sharded-rotation policy: rotation-enabled always behaves as sticky-sharded; report the
@@ -10751,6 +10763,72 @@ function registerCodexRoutes(app, deps) {
10751
10763
  }
10752
10764
  });
10753
10765
  });
10766
+ app.post("/v1/workspaces/:workspaceId/codex/apps", async (c) => {
10767
+ const workspaceId = c.req.param("workspaceId");
10768
+ if (!settings.codexConnectedAppsEnabled) {
10769
+ throw new HTTPException10(409, { message: "Codex Apps is disabled for this deployment" });
10770
+ }
10771
+ const { human, accountId } = await requireCodexAppsHuman(c, deps, workspaceId);
10772
+ const parsed = z.object({
10773
+ accountId: z.string().uuid(),
10774
+ expectedVersion: z.number().int().nonnegative()
10775
+ }).safeParse(await c.req.json().catch(() => null));
10776
+ if (!parsed.success) {
10777
+ throw new HTTPException10(400, { message: "accountId and expectedVersion are required" });
10778
+ }
10779
+ const result = await designateCodexAppsCredential(db, {
10780
+ accountId,
10781
+ workspaceId,
10782
+ credentialId: parsed.data.accountId,
10783
+ subjectId: human.subjectId,
10784
+ expectedVersion: parsed.data.expectedVersion
10785
+ });
10786
+ if (result.kind === "not_found") {
10787
+ throw new HTTPException10(404, { message: "codex account not found" });
10788
+ }
10789
+ if (result.kind === "not_owner") {
10790
+ throw new HTTPException10(403, {
10791
+ message: "only the managed human who connected this subscription may designate it"
10792
+ });
10793
+ }
10794
+ if (result.kind === "forbidden") {
10795
+ throw new HTTPException10(403, { message: "missing permission: connections:write" });
10796
+ }
10797
+ if (result.kind === "unavailable") {
10798
+ throw new HTTPException10(409, { message: "codex account requires relogin" });
10799
+ }
10800
+ const response = {
10801
+ credentialId: result.credentialId,
10802
+ version: result.version,
10803
+ designatedAt: result.designatedAt,
10804
+ changed: result.kind === "updated"
10805
+ };
10806
+ return result.kind === "updated" ? c.json(response) : c.json(response, 409);
10807
+ });
10808
+ app.delete("/v1/workspaces/:workspaceId/codex/apps", async (c) => {
10809
+ const workspaceId = c.req.param("workspaceId");
10810
+ const { human, accountId } = await requireCodexAppsHuman(c, deps, workspaceId);
10811
+ const parsed = z.object({ expectedVersion: z.number().int().nonnegative() }).safeParse(await c.req.json().catch(() => null));
10812
+ if (!parsed.success) {
10813
+ throw new HTTPException10(400, { message: "expectedVersion is required" });
10814
+ }
10815
+ const result = await clearCodexAppsCredential(db, {
10816
+ accountId,
10817
+ workspaceId,
10818
+ subjectId: human.subjectId,
10819
+ expectedVersion: parsed.data.expectedVersion
10820
+ });
10821
+ if (result.kind === "forbidden") {
10822
+ throw new HTTPException10(403, { message: "missing permission: connections:write" });
10823
+ }
10824
+ const response = {
10825
+ credentialId: result.credentialId,
10826
+ version: result.version,
10827
+ designatedAt: result.designatedAt,
10828
+ changed: result.kind === "updated"
10829
+ };
10830
+ return result.kind === "conflict" ? c.json(response, 409) : c.json(response);
10831
+ });
10754
10832
  app.post("/v1/workspaces/:workspaceId/codex/accounts/:accountId/activate", async (c) => {
10755
10833
  const workspaceId = c.req.param("workspaceId");
10756
10834
  await requireAccessGrant2(c, deps, workspaceId, "workspace:admin");
@@ -10859,13 +10937,13 @@ function registerCodexRoutes(app, deps) {
10859
10937
  });
10860
10938
  app.delete("/v1/workspaces/:workspaceId/codex/accounts/:accountId", async (c) => {
10861
10939
  const workspaceId = c.req.param("workspaceId");
10862
- await requireAccessGrant2(c, deps, workspaceId, "workspace:admin");
10940
+ const grant = await requireAccessGrant2(c, deps, workspaceId, "workspace:admin");
10863
10941
  const accountId = c.req.param("accountId");
10864
10942
  const mutation = await withCodexCapacityMutation(
10865
10943
  db,
10866
10944
  { workspaceId, reason: "codex_credential_disconnected" },
10867
10945
  async (tx) => {
10868
- const result2 = await disconnectCodexAccount(tx, workspaceId, accountId);
10946
+ const result2 = await disconnectCodexAccount(tx, workspaceId, accountId, grant.subjectId);
10869
10947
  return { result: result2, changed: result2.removed };
10870
10948
  }
10871
10949
  );
@@ -10880,12 +10958,12 @@ function registerCodexRoutes(app, deps) {
10880
10958
  });
10881
10959
  app.delete("/v1/workspaces/:workspaceId/codex", async (c) => {
10882
10960
  const workspaceId = c.req.param("workspaceId");
10883
- await requireAccessGrant2(c, deps, workspaceId, "workspace:admin");
10961
+ const grant = await requireAccessGrant2(c, deps, workspaceId, "workspace:admin");
10884
10962
  const mutation = await withCodexCapacityMutation(
10885
10963
  db,
10886
10964
  { workspaceId, reason: "codex_credentials_disconnected" },
10887
10965
  async (tx) => {
10888
- const result2 = await disconnectAllCodexAccounts(tx, workspaceId);
10966
+ const result2 = await disconnectAllCodexAccounts(tx, workspaceId, grant.subjectId);
10889
10967
  return { result: result2, changed: result2.removed > 0 };
10890
10968
  }
10891
10969
  );
@@ -26617,4 +26695,4 @@ export {
26617
26695
  withDefaultEnabledCapabilityMcpTools,
26618
26696
  workflowIdForSession2 as workflowIdForSession
26619
26697
  };
26620
- //# sourceMappingURL=chunk-J4JS2F7L.js.map
26698
+ //# sourceMappingURL=chunk-R5PDSH2A.js.map