@opengeni/api-router 2.13.0-canary.0 → 2.13.0-canary.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.
Files changed (52) hide show
  1. package/dist/app.js +1 -1
  2. package/dist/{chunk-BJWHVMOL.js → chunk-K2NU4KRK.js} +3165 -3662
  3. package/dist/{chunk-BJWHVMOL.js.map → chunk-K2NU4KRK.js.map} +1 -1
  4. package/dist/index.js +5 -4
  5. package/dist/index.js.map +1 -1
  6. package/dist/integrations/github-lens-connect.d.ts +2 -2
  7. package/dist/integrations/slack-interactions.d.ts +1 -1
  8. package/dist/mcp/documents.d.ts +5 -13
  9. package/dist/mcp/files.d.ts +2 -2
  10. package/dist/mcp/first-party-tool-permissions.d.ts +36 -0
  11. package/dist/mcp/knowledge-entries.d.ts +5 -0
  12. package/dist/mcp/server.d.ts +4 -4
  13. package/dist/routes/host-mcp-resolvers.d.ts +3 -0
  14. package/dist/routes/knowledge.d.ts +3 -0
  15. package/dist/sandbox-file-artifacts.d.ts +6 -2
  16. package/dist/workspace-state-projection.d.ts +3 -5
  17. package/dist/workspace-tool-gateway.d.ts +2 -1
  18. package/package.json +19 -19
  19. package/src/access-grant-rls.ts +13 -1
  20. package/src/app.ts +4 -11
  21. package/src/codemode.ts +4 -8
  22. package/src/index.ts +4 -3
  23. package/src/integrations/atlassian.ts +31 -28
  24. package/src/integrations/google-drive.ts +33 -30
  25. package/src/integrations/marketplace-plugin.ts +1 -1
  26. package/src/integrations/provider-oauth.ts +11 -2
  27. package/src/mcp/documents.ts +57 -428
  28. package/src/mcp/files.ts +76 -58
  29. package/src/mcp/first-party-tool-permissions.ts +9 -0
  30. package/src/mcp/knowledge-entries.ts +276 -0
  31. package/src/mcp/server.ts +7 -361
  32. package/src/routes/company-brain.ts +58 -107
  33. package/src/routes/documents.ts +78 -294
  34. package/src/routes/files.ts +68 -3
  35. package/src/routes/host-mcp-resolvers.ts +41 -0
  36. package/src/routes/knowledge.ts +386 -0
  37. package/src/routes/organization-memberships.ts +33 -0
  38. package/src/routes/scheduled-tasks.ts +9 -1
  39. package/src/routes/sessions.ts +20 -3
  40. package/src/routes/skill-content.ts +8 -2
  41. package/src/routes/video-generation.ts +7 -5
  42. package/src/routes/workspace-learning.ts +12 -82
  43. package/src/routes/workspace-state.ts +34 -25
  44. package/src/routes/workspaces.ts +20 -10
  45. package/src/sandbox-file-artifacts.ts +54 -2
  46. package/src/scheduled-task-deletion.ts +3 -2
  47. package/src/workspace-state-projection.ts +18 -148
  48. package/src/workspace-tool-gateway.ts +14 -25
  49. package/dist/mcp/company-brain-governed-writes.d.ts +0 -26
  50. package/dist/mcp/remember.d.ts +0 -28
  51. package/src/mcp/company-brain-governed-writes.ts +0 -271
  52. package/src/mcp/remember.ts +0 -191
@@ -1,3 +1,8 @@
1
+ import {
2
+ scheduledTaskKnowledgeSource,
3
+ requireScheduledTaskKnowledgeSource,
4
+ knowledgeSourceAgentConfig,
5
+ } from "@opengeni/contracts";
1
6
  import type { Settings } from "@opengeni/config";
2
7
  import { createHash } from "node:crypto";
3
8
  import { ExternalActorContinuation } from "@opengeni/contracts/external-identities";
@@ -840,10 +845,10 @@ export async function preflightAtlassianScheduleAuthorization(
840
845
  input: { task: ScheduledTask; subjectId: string },
841
846
  ): Promise<void> {
842
847
  const { task } = input;
843
- if (task.action.kind !== "knowledge_source_sync") return;
848
+ if (!scheduledTaskKnowledgeSource(task)) return;
844
849
  if (
845
- task.action.initiatingSubjectId !== input.subjectId ||
846
- task.action.connection.ownerSubjectId !== input.subjectId
850
+ requireScheduledTaskKnowledgeSource(task).initiatingSubjectId !== input.subjectId ||
851
+ requireScheduledTaskKnowledgeSource(task).connection.ownerSubjectId !== input.subjectId
847
852
  ) {
848
853
  throw new HTTPException(403, {
849
854
  message: "knowledge source schedule requires the exact initiating subject",
@@ -862,10 +867,10 @@ export async function revokeAtlassianScheduleAuthorization(
862
867
  input: { task: ScheduledTask; subjectId: string },
863
868
  ): Promise<void> {
864
869
  const { task } = input;
865
- if (task.action.kind !== "knowledge_source_sync") return;
870
+ if (!scheduledTaskKnowledgeSource(task)) return;
866
871
  if (
867
- task.action.initiatingSubjectId !== input.subjectId ||
868
- task.action.connection.ownerSubjectId !== input.subjectId
872
+ requireScheduledTaskKnowledgeSource(task).initiatingSubjectId !== input.subjectId ||
873
+ requireScheduledTaskKnowledgeSource(task).connection.ownerSubjectId !== input.subjectId
869
874
  ) {
870
875
  throw new HTTPException(403, {
871
876
  message: "knowledge source schedule requires the exact initiating subject",
@@ -879,11 +884,11 @@ export async function revokeAtlassianScheduleAuthorization(
879
884
  taskId: task.id,
880
885
  accountId: task.accountId,
881
886
  workspaceId: task.workspaceId,
882
- connectionId: task.action.connection.connectionId,
883
- connectionVersion: task.action.connection.connectionVersion,
884
- sourceId: task.action.sourceId,
885
- sourceLifecycleGeneration: task.action.sourceLifecycleGeneration,
886
- sourceConfigGeneration: task.action.sourceConfigGeneration,
887
+ connectionId: requireScheduledTaskKnowledgeSource(task).connection.connectionId,
888
+ connectionVersion: requireScheduledTaskKnowledgeSource(task).connection.connectionVersion,
889
+ sourceId: requireScheduledTaskKnowledgeSource(task).sourceId,
890
+ sourceLifecycleGeneration: requireScheduledTaskKnowledgeSource(task).sourceLifecycleGeneration,
891
+ sourceConfigGeneration: requireScheduledTaskKnowledgeSource(task).sourceConfigGeneration,
887
892
  externalSourceId,
888
893
  subjectId: input.subjectId,
889
894
  });
@@ -1014,11 +1019,11 @@ async function materializeSchedules(
1014
1019
  let source = null as Awaited<ReturnType<typeof upsertKnowledgeSource>> | null;
1015
1020
  let existingTask: (typeof tasks)[number] | null = null;
1016
1021
  for (const task of tasks) {
1017
- if (task.action.kind !== "knowledge_source_sync") continue;
1022
+ if (!scheduledTaskKnowledgeSource(task)) continue;
1018
1023
  const resolved = await getKnowledgeSourceForSyncAuthority(deps.db, {
1019
1024
  accountId: input.accountId,
1020
1025
  workspaceId: input.workspaceId,
1021
- sourceId: task.action.sourceId,
1026
+ sourceId: requireScheduledTaskKnowledgeSource(task).sourceId,
1022
1027
  initiatingSubjectId: input.subjectId,
1023
1028
  });
1024
1029
  if (resolved?.source.externalSourceId !== identity.externalSourceId) continue;
@@ -1125,7 +1130,10 @@ async function materializeSchedules(
1125
1130
  name: `Sync ${selectedSource.kind === "jira_project" ? "Jira" : "Confluence"}: ${selectedSource.name}`,
1126
1131
  schedule: atlassianSchedule(selectedSource.syncCadence),
1127
1132
  overlapPolicy: "buffer_one",
1128
- action,
1133
+ action: { kind: "agent_turn" },
1134
+ agentConfig: knowledgeSourceAgentConfig(action, existingTask.agentConfig),
1135
+ refreshPersonalResourceAuthority: true,
1136
+ authorityUpdatedBy: { kind: "subject", subjectId: input.subjectId },
1129
1137
  metadata: {
1130
1138
  ...existingTask.metadata,
1131
1139
  connectorKind: "atlassian",
@@ -1153,16 +1161,11 @@ async function materializeSchedules(
1153
1161
  status: "active",
1154
1162
  schedule: atlassianSchedule(selectedSource.syncCadence),
1155
1163
  overlapPolicy: "buffer_one",
1156
- action,
1164
+ action: { kind: "agent_turn" },
1157
1165
  runMode: "new_session_per_run",
1158
1166
  targetSessionId: null,
1159
1167
  connectionAuthorities: [],
1160
- agentConfig: {
1161
- prompt: "Knowledge source synchronization",
1162
- resources: [],
1163
- tools: [],
1164
- metadata: {},
1165
- },
1168
+ agentConfig: knowledgeSourceAgentConfig(action),
1166
1169
  variableSetId: null,
1167
1170
  environmentId: null,
1168
1171
  rigId: null,
@@ -1187,11 +1190,11 @@ async function materializeSchedules(
1187
1190
  }
1188
1191
 
1189
1192
  for (const task of tasks) {
1190
- if (task.action.kind !== "knowledge_source_sync") continue;
1193
+ if (!scheduledTaskKnowledgeSource(task)) continue;
1191
1194
  const resolved = await getKnowledgeSourceForSyncAuthority(deps.db, {
1192
1195
  accountId: input.accountId,
1193
1196
  workspaceId: input.workspaceId,
1194
- sourceId: task.action.sourceId,
1197
+ sourceId: requireScheduledTaskKnowledgeSource(task).sourceId,
1195
1198
  initiatingSubjectId: input.subjectId,
1196
1199
  });
1197
1200
  if (!resolved || enabledIds.has(resolved.source.externalSourceId)) continue;
@@ -1510,20 +1513,20 @@ async function deauthorizeConnectionSources(
1510
1513
  connection.id,
1511
1514
  );
1512
1515
  for (const task of tasks) {
1513
- if (task.action.kind !== "knowledge_source_sync") continue;
1516
+ if (!scheduledTaskKnowledgeSource(task)) continue;
1514
1517
  const resolved = await getKnowledgeSourceForSyncAuthority(deps.db, {
1515
1518
  accountId: task.accountId,
1516
1519
  workspaceId: task.workspaceId,
1517
- sourceId: task.action.sourceId,
1520
+ sourceId: requireScheduledTaskKnowledgeSource(task).sourceId,
1518
1521
  initiatingSubjectId: subjectId,
1519
1522
  });
1520
1523
  if (!resolved || resolved.source.lifecycleState !== "active") continue;
1521
1524
  await deauthorizeKnowledgeSourceRetrieval(deps.db, {
1522
1525
  accountId: task.accountId,
1523
1526
  workspaceId: task.workspaceId,
1524
- sourceId: task.action.sourceId,
1525
- audience: task.action.destination,
1526
- operationId: `atlassian-deauthorize:${connection.id}:${connection.version + 1}:${task.action.sourceId}:${reasonCode}`,
1527
+ sourceId: requireScheduledTaskKnowledgeSource(task).sourceId,
1528
+ audience: requireScheduledTaskKnowledgeSource(task).destination,
1529
+ operationId: `atlassian-deauthorize:${connection.id}:${connection.version + 1}:${requireScheduledTaskKnowledgeSource(task).sourceId}:${reasonCode}`,
1527
1530
  reasonCode,
1528
1531
  actor: { kind: "human", subjectId, initiatingHumanSubjectId: subjectId },
1529
1532
  });
@@ -1,3 +1,8 @@
1
+ import {
2
+ scheduledTaskKnowledgeSource,
3
+ requireScheduledTaskKnowledgeSource,
4
+ knowledgeSourceAgentConfig,
5
+ } from "@opengeni/contracts";
1
6
  import { createHash, randomBytes } from "node:crypto";
2
7
  import { ExternalActorContinuation } from "@opengeni/contracts/external-identities";
3
8
  import { requireConnectOwnerAuthority } from "./connect-authority";
@@ -188,7 +193,7 @@ export async function wakeGoogleDriveSourcesFromWorkspaceEvent(
188
193
  );
189
194
  let triggered = 0;
190
195
  for (const task of tasks) {
191
- if (task.action.kind !== "knowledge_source_sync" || task.status !== "active") continue;
196
+ if (!scheduledTaskKnowledgeSource(task) || task.status !== "active") continue;
192
197
  const externalSourceId =
193
198
  typeof task.metadata.externalSourceId === "string" ? task.metadata.externalSourceId : null;
194
199
  const selectedSource = externalSourceId ? selectedById.get(externalSourceId) : null;
@@ -808,20 +813,20 @@ async function deauthorizeGoogleDriveConnectionSources(
808
813
  connection.workspaceId,
809
814
  connection.id,
810
815
  async (task) => {
811
- if (task.action.initiatingSubjectId !== subjectId) return;
816
+ if (requireScheduledTaskKnowledgeSource(task).initiatingSubjectId !== subjectId) return;
812
817
  const resolved = await getKnowledgeSourceForSyncAuthority(deps.db, {
813
818
  accountId: task.accountId,
814
819
  workspaceId: task.workspaceId,
815
- sourceId: task.action.sourceId,
820
+ sourceId: requireScheduledTaskKnowledgeSource(task).sourceId,
816
821
  initiatingSubjectId: subjectId,
817
822
  });
818
823
  if (!resolved || resolved.source.lifecycleState !== "active") return;
819
824
  await deauthorizeKnowledgeSourceRetrieval(deps.db, {
820
825
  accountId: task.accountId,
821
826
  workspaceId: task.workspaceId,
822
- sourceId: task.action.sourceId,
823
- audience: task.action.destination,
824
- operationId: `google-drive-deauthorize:${connection.id}:${authorityVersion}:${task.action.sourceId}:${reasonCode}`,
827
+ sourceId: requireScheduledTaskKnowledgeSource(task).sourceId,
828
+ audience: requireScheduledTaskKnowledgeSource(task).destination,
829
+ operationId: `google-drive-deauthorize:${connection.id}:${authorityVersion}:${requireScheduledTaskKnowledgeSource(task).sourceId}:${reasonCode}`,
825
830
  reasonCode,
826
831
  actor: {
827
832
  kind: "human",
@@ -837,7 +842,7 @@ async function forEachGoogleDriveConnectionTask(
837
842
  deps: ApiRouteDeps,
838
843
  workspaceId: string,
839
844
  connectionId: string,
840
- fn: (task: ScheduledTask & { action: { kind: "knowledge_source_sync" } }) => Promise<void>,
845
+ fn: (task: ScheduledTask) => Promise<void>,
841
846
  ): Promise<void> {
842
847
  const tasks = await listKnowledgeSourceSyncTasksForConnection(deps.db, workspaceId, connectionId);
843
848
  for (const task of tasks) {
@@ -1393,11 +1398,11 @@ async function materializeGoogleDriveKnowledgeSchedules(
1393
1398
  let source = null as Awaited<ReturnType<typeof upsertKnowledgeSource>> | null;
1394
1399
  let existingTask = null as (typeof connectionTasks)[number] | null;
1395
1400
  for (const task of connectionTasks) {
1396
- if (task.action.kind !== "knowledge_source_sync") continue;
1401
+ if (!scheduledTaskKnowledgeSource(task)) continue;
1397
1402
  const resolved = await getKnowledgeSourceForSyncAuthority(deps.db, {
1398
1403
  accountId: input.accountId,
1399
1404
  workspaceId: input.workspaceId,
1400
- sourceId: task.action.sourceId,
1405
+ sourceId: requireScheduledTaskKnowledgeSource(task).sourceId,
1401
1406
  initiatingSubjectId: input.subjectId,
1402
1407
  });
1403
1408
  if (resolved?.source.externalSourceId !== identity.externalSourceId) continue;
@@ -1499,7 +1504,10 @@ async function materializeGoogleDriveKnowledgeSchedules(
1499
1504
  task = await updateScheduledTask(deps.db, input.workspaceId, existingTask.id, {
1500
1505
  name: `Sync Google Drive: ${selectedSource.name}`,
1501
1506
  overlapPolicy: "buffer_one",
1502
- action,
1507
+ action: { kind: "agent_turn" },
1508
+ agentConfig: knowledgeSourceAgentConfig(action, existingTask.agentConfig),
1509
+ refreshPersonalResourceAuthority: true,
1510
+ authorityUpdatedBy: { kind: "subject", subjectId: input.subjectId },
1503
1511
  metadata: {
1504
1512
  ...existingTask.metadata,
1505
1513
  connectorKind: "google_drive",
@@ -1531,16 +1539,11 @@ async function materializeGoogleDriveKnowledgeSchedules(
1531
1539
  status: "active",
1532
1540
  schedule,
1533
1541
  overlapPolicy: "buffer_one",
1534
- action,
1542
+ action: { kind: "agent_turn" },
1535
1543
  runMode: "new_session_per_run",
1536
1544
  targetSessionId: null,
1537
1545
  connectionAuthorities: [],
1538
- agentConfig: {
1539
- prompt: "Knowledge source synchronization",
1540
- resources: [],
1541
- tools: [],
1542
- metadata: {},
1543
- },
1546
+ agentConfig: knowledgeSourceAgentConfig(action),
1544
1547
  variableSetId: null,
1545
1548
  environmentId: null,
1546
1549
  rigId: null,
@@ -1565,11 +1568,11 @@ async function materializeGoogleDriveKnowledgeSchedules(
1565
1568
  }
1566
1569
 
1567
1570
  for (const task of connectionTasks) {
1568
- if (task.action.kind !== "knowledge_source_sync") continue;
1571
+ if (!scheduledTaskKnowledgeSource(task)) continue;
1569
1572
  const resolved = await getKnowledgeSourceForSyncAuthority(deps.db, {
1570
1573
  accountId: input.accountId,
1571
1574
  workspaceId: input.workspaceId,
1572
- sourceId: task.action.sourceId,
1575
+ sourceId: requireScheduledTaskKnowledgeSource(task).sourceId,
1573
1576
  initiatingSubjectId: input.subjectId,
1574
1577
  });
1575
1578
  if (!resolved || enabledIds.has(resolved.source.externalSourceId)) continue;
@@ -1613,10 +1616,10 @@ export async function preflightKnowledgeSourceScheduleAuthorization(
1613
1616
  input: { task: ScheduledTask; subjectId: string },
1614
1617
  ): Promise<void> {
1615
1618
  const { task } = input;
1616
- if (task.action.kind !== "knowledge_source_sync") return;
1619
+ if (!scheduledTaskKnowledgeSource(task)) return;
1617
1620
  if (
1618
- task.action.initiatingSubjectId !== input.subjectId ||
1619
- task.action.connection.ownerSubjectId !== input.subjectId
1621
+ requireScheduledTaskKnowledgeSource(task).initiatingSubjectId !== input.subjectId ||
1622
+ requireScheduledTaskKnowledgeSource(task).connection.ownerSubjectId !== input.subjectId
1620
1623
  ) {
1621
1624
  throw new HTTPException(403, {
1622
1625
  message: "knowledge source schedule requires the exact initiating subject",
@@ -1642,10 +1645,10 @@ export async function revokeKnowledgeSourceScheduleAuthorization(
1642
1645
  input: { task: ScheduledTask; subjectId: string },
1643
1646
  ): Promise<void> {
1644
1647
  const { task } = input;
1645
- if (task.action.kind !== "knowledge_source_sync") return;
1648
+ if (!scheduledTaskKnowledgeSource(task)) return;
1646
1649
  if (
1647
- task.action.initiatingSubjectId !== input.subjectId ||
1648
- task.action.connection.ownerSubjectId !== input.subjectId
1650
+ requireScheduledTaskKnowledgeSource(task).initiatingSubjectId !== input.subjectId ||
1651
+ requireScheduledTaskKnowledgeSource(task).connection.ownerSubjectId !== input.subjectId
1649
1652
  ) {
1650
1653
  throw new HTTPException(403, {
1651
1654
  message: "knowledge source schedule requires the exact initiating subject",
@@ -1665,11 +1668,11 @@ export async function revokeKnowledgeSourceScheduleAuthorization(
1665
1668
  taskId: task.id,
1666
1669
  accountId: task.accountId,
1667
1670
  workspaceId: task.workspaceId,
1668
- connectionId: task.action.connection.connectionId,
1669
- connectionVersion: task.action.connection.connectionVersion,
1670
- sourceId: task.action.sourceId,
1671
- sourceLifecycleGeneration: task.action.sourceLifecycleGeneration,
1672
- sourceConfigGeneration: task.action.sourceConfigGeneration,
1671
+ connectionId: requireScheduledTaskKnowledgeSource(task).connection.connectionId,
1672
+ connectionVersion: requireScheduledTaskKnowledgeSource(task).connection.connectionVersion,
1673
+ sourceId: requireScheduledTaskKnowledgeSource(task).sourceId,
1674
+ sourceLifecycleGeneration: requireScheduledTaskKnowledgeSource(task).sourceLifecycleGeneration,
1675
+ sourceConfigGeneration: requireScheduledTaskKnowledgeSource(task).sourceConfigGeneration,
1673
1676
  externalSourceId,
1674
1677
  subjectId: input.subjectId,
1675
1678
  });
@@ -5,7 +5,7 @@ import { HTTPException } from "hono/http-exception";
5
5
  /** Adapt only indexed portable components. Never silently drop required components. */
6
6
  export function marketplacePlugin(url: string) {
7
7
  const source = snapshot.sources.find((candidate) =>
8
- candidate.entries.some((item) => item.sourceUrl === url),
8
+ candidate.entries.some((entry) => entry.sourceUrl === url),
9
9
  );
10
10
  const item = source?.entries.find((candidate) => candidate.sourceUrl === url);
11
11
  if (!item || !source) return null;
@@ -375,7 +375,7 @@ export async function completeApiIntegrationProviderOAuth(
375
375
  if (!providerScopesInclude(definition, token.scopes, state.authorizeScopes)) {
376
376
  throw new ProviderOAuthCallbackError("scope_not_granted");
377
377
  }
378
- const grantedScopes = token.scopes.length > 0 ? token.scopes : state.authorizeScopes;
378
+ let grantedScopes = token.scopes.length > 0 ? token.scopes : state.authorizeScopes;
379
379
  const identity = await verifyProviderIdentity(deps, definition, token);
380
380
  if (
381
381
  state.expectedProviderPrincipalId &&
@@ -415,6 +415,11 @@ export async function completeApiIntegrationProviderOAuth(
415
415
  if (!refreshToken) {
416
416
  throw new ProviderOAuthCallbackError("refresh_token_missing");
417
417
  }
418
+ // Microsoft omits offline_access from access-token scopes. The new or
419
+ // previously verified refresh token proves this capability instead.
420
+ if (definition.provider.id === "microsoft") {
421
+ grantedScopes = uniqueStrings([...grantedScopes, "offline_access"]);
422
+ }
418
423
  const credentialEncrypted = encryptEnvironmentValue(
419
424
  key,
420
425
  JSON.stringify({
@@ -926,7 +931,11 @@ function providerScopesInclude(
926
931
  return value;
927
932
  };
928
933
  const granted = new Set(effective.map(normalize));
929
- return definition.authentication.scopes.every((scope) => granted.has(normalize(scope)));
934
+ return definition.authentication.scopes.every(
935
+ (scope) =>
936
+ (definition.provider.id === "microsoft" && normalize(scope) === "offline_access") ||
937
+ granted.has(normalize(scope)),
938
+ );
930
939
  }
931
940
 
932
941
  function providerOAuthReturnUrl(