@opengeni/api-router 2.13.0-canary.1 → 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 (50) hide show
  1. package/dist/app.js +1 -1
  2. package/dist/{chunk-V4IDX7VJ.js → chunk-K2NU4KRK.js} +3138 -3635
  3. package/dist/{chunk-V4IDX7VJ.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 +1 -1
  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/package.json +19 -19
  18. package/src/access-grant-rls.ts +13 -1
  19. package/src/app.ts +4 -11
  20. package/src/index.ts +4 -3
  21. package/src/integrations/atlassian.ts +31 -28
  22. package/src/integrations/google-drive.ts +33 -30
  23. package/src/integrations/marketplace-plugin.ts +1 -1
  24. package/src/integrations/provider-oauth.ts +11 -2
  25. package/src/mcp/documents.ts +57 -428
  26. package/src/mcp/files.ts +76 -58
  27. package/src/mcp/first-party-tool-permissions.ts +9 -0
  28. package/src/mcp/knowledge-entries.ts +276 -0
  29. package/src/mcp/server.ts +7 -361
  30. package/src/routes/company-brain.ts +58 -107
  31. package/src/routes/documents.ts +78 -294
  32. package/src/routes/files.ts +68 -3
  33. package/src/routes/host-mcp-resolvers.ts +41 -0
  34. package/src/routes/knowledge.ts +386 -0
  35. package/src/routes/organization-memberships.ts +33 -0
  36. package/src/routes/scheduled-tasks.ts +9 -1
  37. package/src/routes/sessions.ts +20 -3
  38. package/src/routes/skill-content.ts +8 -2
  39. package/src/routes/video-generation.ts +7 -5
  40. package/src/routes/workspace-learning.ts +12 -82
  41. package/src/routes/workspace-state.ts +34 -25
  42. package/src/routes/workspaces.ts +20 -10
  43. package/src/sandbox-file-artifacts.ts +54 -2
  44. package/src/scheduled-task-deletion.ts +3 -2
  45. package/src/workspace-state-projection.ts +18 -148
  46. package/src/workspace-tool-gateway.ts +3 -15
  47. package/dist/mcp/company-brain-governed-writes.d.ts +0 -26
  48. package/dist/mcp/remember.d.ts +0 -28
  49. package/src/mcp/company-brain-governed-writes.ts +0 -271
  50. 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 { 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(